aboutsummaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-04-16 16:01:22 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-04-16 16:01:22 +0000
commit71d5a2540a98c81f5bcaeb48805e0e2881f530ef (patch)
tree5343938942df402b49ec7300a1c25a2d4ccd5821 /include
parent31bbf64f3a4974a2d6c8b3b27ad2f519caf74057 (diff)
downloadsrc-71d5a2540a98c81f5bcaeb48805e0e2881f530ef.tar.gz
src-71d5a2540a98c81f5bcaeb48805e0e2881f530ef.zip
Vendor import of llvm trunk r300422:vendor/llvm/llvm-trunk-r300422
Notes
Notes: svn path=/vendor/llvm/dist/; revision=317017 svn path=/vendor/llvm/llvm-trunk-r300422/; revision=317018; tag=vendor/llvm/llvm-trunk-r300422
Diffstat (limited to 'include')
-rw-r--r--include/llvm-c/Transforms/Scalar.h3
-rw-r--r--include/llvm-c/lto.h144
-rw-r--r--include/llvm/ADT/APFloat.h370
-rw-r--r--include/llvm/ADT/APInt.h668
-rw-r--r--include/llvm/ADT/APSInt.h3
-rw-r--r--include/llvm/ADT/ArrayRef.h12
-rw-r--r--include/llvm/ADT/BitVector.h43
-rw-r--r--include/llvm/ADT/BreadthFirstIterator.h164
-rw-r--r--include/llvm/ADT/DenseMap.h13
-rw-r--r--include/llvm/ADT/DenseMapInfo.h18
-rw-r--r--include/llvm/ADT/DenseSet.h27
-rw-r--r--include/llvm/ADT/DepthFirstIterator.h2
-rw-r--r--include/llvm/ADT/GraphTraits.h29
-rw-r--r--include/llvm/ADT/None.h5
-rw-r--r--include/llvm/ADT/PointerUnion.h8
-rw-r--r--include/llvm/ADT/PostOrderIterator.h4
-rw-r--r--include/llvm/ADT/STLExtras.h236
-rw-r--r--include/llvm/ADT/ScopedHashTable.h4
-rw-r--r--include/llvm/ADT/SetVector.h8
-rw-r--r--include/llvm/ADT/SmallBitVector.h29
-rw-r--r--include/llvm/ADT/SmallPtrSet.h57
-rw-r--r--include/llvm/ADT/SparseBitVector.h19
-rw-r--r--include/llvm/ADT/StringExtras.h7
-rw-r--r--include/llvm/ADT/StringMap.h110
-rw-r--r--include/llvm/ADT/StringRef.h10
-rw-r--r--include/llvm/ADT/Triple.h23
-rw-r--r--include/llvm/ADT/iterator.h34
-rw-r--r--include/llvm/Analysis/AliasAnalysis.h14
-rw-r--r--include/llvm/Analysis/AliasSetTracker.h7
-rw-r--r--include/llvm/Analysis/AssumptionCache.h21
-rw-r--r--include/llvm/Analysis/BasicAliasAnalysis.h18
-rw-r--r--include/llvm/Analysis/BlockFrequencyInfo.h10
-rw-r--r--include/llvm/Analysis/BlockFrequencyInfoImpl.h7
-rw-r--r--include/llvm/Analysis/BranchProbabilityInfo.h2
-rw-r--r--include/llvm/Analysis/CFGPrinter.h3
-rw-r--r--include/llvm/Analysis/CGSCCPassManager.h1
-rw-r--r--include/llvm/Analysis/CallGraph.h2
-rw-r--r--include/llvm/Analysis/ConstantFolding.h6
-rw-r--r--include/llvm/Analysis/DominanceFrontier.h4
-rw-r--r--include/llvm/Analysis/IndirectCallSiteVisitor.h12
-rw-r--r--include/llvm/Analysis/InlineCost.h6
-rw-r--r--include/llvm/Analysis/InstructionSimplify.h12
-rw-r--r--include/llvm/Analysis/LazyBlockFrequencyInfo.h104
-rw-r--r--include/llvm/Analysis/LazyBranchProbabilityInfo.h12
-rw-r--r--include/llvm/Analysis/LazyCallGraph.h493
-rw-r--r--include/llvm/Analysis/LazyValueInfo.h15
-rw-r--r--include/llvm/Analysis/Loads.h31
-rw-r--r--include/llvm/Analysis/LoopAccessAnalysis.h37
-rw-r--r--include/llvm/Analysis/LoopInfo.h30
-rw-r--r--include/llvm/Analysis/LoopInfoImpl.h150
-rw-r--r--include/llvm/Analysis/MemoryBuiltins.h43
-rw-r--r--include/llvm/Analysis/MemorySSA.h (renamed from include/llvm/Transforms/Utils/MemorySSA.h)505
-rw-r--r--include/llvm/Analysis/MemorySSAUpdater.h153
-rw-r--r--include/llvm/Analysis/ObjectUtils.h42
-rw-r--r--include/llvm/Analysis/OptimizationDiagnosticInfo.h150
-rw-r--r--include/llvm/Analysis/PostDominators.h4
-rw-r--r--include/llvm/Analysis/ProfileSummaryInfo.h16
-rw-r--r--include/llvm/Analysis/PtrUseVisitor.h5
-rw-r--r--include/llvm/Analysis/RegionInfo.h4
-rw-r--r--include/llvm/Analysis/ScalarEvolution.h71
-rw-r--r--include/llvm/Analysis/ScalarEvolutionExpressions.h66
-rw-r--r--include/llvm/Analysis/ScalarEvolutionNormalization.h45
-rw-r--r--include/llvm/Analysis/TargetLibraryInfo.def2
-rw-r--r--include/llvm/Analysis/TargetLibraryInfo.h78
-rw-r--r--include/llvm/Analysis/TargetTransformInfo.h161
-rw-r--r--include/llvm/Analysis/TargetTransformInfoImpl.h33
-rw-r--r--include/llvm/Analysis/TypeMetadataUtils.h5
-rw-r--r--include/llvm/Analysis/ValueTracking.h32
-rw-r--r--include/llvm/Analysis/VectorUtils.h59
-rw-r--r--include/llvm/Bitcode/BitcodeWriter.h19
-rw-r--r--include/llvm/Bitcode/LLVMBitCodes.h25
-rw-r--r--include/llvm/CMakeLists.txt1
-rw-r--r--include/llvm/CodeGen/Analysis.h7
-rw-r--r--include/llvm/CodeGen/AsmPrinter.h91
-rw-r--r--include/llvm/CodeGen/BasicTTIImpl.h175
-rw-r--r--include/llvm/CodeGen/CallingConvLower.h10
-rw-r--r--include/llvm/CodeGen/CommandFlags.h33
-rw-r--r--include/llvm/CodeGen/ExecutionDepsFix.h220
-rw-r--r--include/llvm/CodeGen/FastISel.h87
-rw-r--r--include/llvm/CodeGen/FaultMaps.h43
-rw-r--r--include/llvm/CodeGen/GCStrategy.h46
-rw-r--r--include/llvm/CodeGen/GlobalISel/CallLowering.h51
-rw-r--r--include/llvm/CodeGen/GlobalISel/IRTranslator.h96
-rw-r--r--include/llvm/CodeGen/GlobalISel/InstructionSelector.h13
-rw-r--r--include/llvm/CodeGen/GlobalISel/Legalizer.h3
-rw-r--r--include/llvm/CodeGen/GlobalISel/LegalizerHelper.h12
-rw-r--r--include/llvm/CodeGen/GlobalISel/LegalizerInfo.h8
-rw-r--r--include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h150
-rw-r--r--include/llvm/CodeGen/GlobalISel/RegBankSelect.h4
-rw-r--r--include/llvm/CodeGen/GlobalISel/RegisterBank.h2
-rw-r--r--include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h20
-rw-r--r--include/llvm/CodeGen/GlobalISel/Utils.h21
-rw-r--r--include/llvm/CodeGen/ISDOpcodes.h25
-rw-r--r--include/llvm/CodeGen/LazyMachineBlockFrequencyInfo.h76
-rw-r--r--include/llvm/CodeGen/LexicalScopes.h38
-rw-r--r--include/llvm/CodeGen/LiveInterval.h28
-rw-r--r--include/llvm/CodeGen/LiveIntervalAnalysis.h140
-rw-r--r--include/llvm/CodeGen/LiveIntervalUnion.h117
-rw-r--r--include/llvm/CodeGen/LiveRegMatrix.h21
-rw-r--r--include/llvm/CodeGen/LiveRegUnits.h128
-rw-r--r--include/llvm/CodeGen/LowLevelType.h190
-rw-r--r--include/llvm/CodeGen/MIRYamlMapping.h4
-rw-r--r--include/llvm/CodeGen/MachineBasicBlock.h23
-rw-r--r--include/llvm/CodeGen/MachineBlockFrequencyInfo.h8
-rw-r--r--include/llvm/CodeGen/MachineDominators.h22
-rw-r--r--include/llvm/CodeGen/MachineFrameInfo.h10
-rw-r--r--include/llvm/CodeGen/MachineFunction.h5
-rw-r--r--include/llvm/CodeGen/MachineFunctionInitializer.h2
-rw-r--r--include/llvm/CodeGen/MachineInstr.h29
-rw-r--r--include/llvm/CodeGen/MachineInstrBuilder.h35
-rw-r--r--include/llvm/CodeGen/MachineLoopInfo.h7
-rw-r--r--include/llvm/CodeGen/MachineModuleInfoImpls.h29
-rw-r--r--include/llvm/CodeGen/MachineOperand.h30
-rw-r--r--include/llvm/CodeGen/MachineOptimizationRemarkEmitter.h203
-rw-r--r--include/llvm/CodeGen/MachineRegisterInfo.h92
-rw-r--r--include/llvm/CodeGen/MachineScheduler.h100
-rw-r--r--include/llvm/CodeGen/MachineTraceMetrics.h66
-rw-r--r--include/llvm/CodeGen/MachineValueType.h81
-rw-r--r--include/llvm/CodeGen/PBQP/Solution.h21
-rw-r--r--include/llvm/CodeGen/Passes.h28
-rw-r--r--include/llvm/CodeGen/RegAllocPBQP.h82
-rw-r--r--include/llvm/CodeGen/RegisterClassInfo.h43
-rw-r--r--include/llvm/CodeGen/RegisterPressure.h72
-rw-r--r--include/llvm/CodeGen/RegisterScavenging.h42
-rw-r--r--include/llvm/CodeGen/ScheduleDAG.h509
-rw-r--r--include/llvm/CodeGen/ScheduleDAGInstrs.h139
-rw-r--r--include/llvm/CodeGen/ScheduleDAGMutation.h25
-rw-r--r--include/llvm/CodeGen/ScheduleDFS.h26
-rw-r--r--include/llvm/CodeGen/ScheduleHazardRecognizer.h8
-rw-r--r--include/llvm/CodeGen/ScoreboardHazardRecognizer.h22
-rw-r--r--include/llvm/CodeGen/SelectionDAG.h44
-rw-r--r--include/llvm/CodeGen/SelectionDAGISel.h23
-rw-r--r--include/llvm/CodeGen/SelectionDAGNodes.h162
-rw-r--r--include/llvm/CodeGen/SlotIndexes.h22
-rw-r--r--include/llvm/CodeGen/StackMaps.h51
-rw-r--r--include/llvm/CodeGen/StackProtector.h18
-rw-r--r--include/llvm/CodeGen/TargetLoweringObjectFileImpl.h60
-rw-r--r--include/llvm/CodeGen/TargetPassConfig.h13
-rw-r--r--include/llvm/CodeGen/TargetSchedule.h28
-rw-r--r--include/llvm/CodeGen/ValueTypes.h131
-rw-r--r--include/llvm/Config/abi-breaking.h.cmake5
-rw-r--r--include/llvm/Config/config.h.cmake8
-rw-r--r--include/llvm/Config/llvm-config.h.cmake3
-rw-r--r--include/llvm/DebugInfo/CodeView/CVRecord.h12
-rw-r--r--include/llvm/DebugInfo/CodeView/CVTypeDumper.h7
-rw-r--r--include/llvm/DebugInfo/CodeView/CVTypeVisitor.h10
-rw-r--r--include/llvm/DebugInfo/CodeView/CodeView.h6
-rw-r--r--include/llvm/DebugInfo/CodeView/CodeViewError.h1
-rw-r--r--include/llvm/DebugInfo/CodeView/CodeViewRecordIO.h12
-rw-r--r--include/llvm/DebugInfo/CodeView/Formatters.h40
-rw-r--r--include/llvm/DebugInfo/CodeView/ModuleSubstream.h18
-rw-r--r--include/llvm/DebugInfo/CodeView/ModuleSubstreamVisitor.h54
-rw-r--r--include/llvm/DebugInfo/CodeView/RecordSerialization.h44
-rw-r--r--include/llvm/DebugInfo/CodeView/SymbolDeserializer.h11
-rw-r--r--include/llvm/DebugInfo/CodeView/SymbolRecord.h8
-rw-r--r--include/llvm/DebugInfo/CodeView/SymbolRecordMapping.h10
-rw-r--r--include/llvm/DebugInfo/CodeView/SymbolSerializer.h47
-rw-r--r--include/llvm/DebugInfo/CodeView/SymbolVisitorDelegate.h6
-rw-r--r--include/llvm/DebugInfo/CodeView/TypeDatabase.h4
-rw-r--r--include/llvm/DebugInfo/CodeView/TypeDeserializer.h17
-rw-r--r--include/llvm/DebugInfo/CodeView/TypeDumpVisitor.h14
-rw-r--r--include/llvm/DebugInfo/CodeView/TypeRecord.h157
-rw-r--r--include/llvm/DebugInfo/CodeView/TypeRecordMapping.h11
-rw-r--r--include/llvm/DebugInfo/CodeView/TypeRecords.def6
-rw-r--r--include/llvm/DebugInfo/CodeView/TypeSerializer.h8
-rw-r--r--include/llvm/DebugInfo/CodeView/TypeServerHandler.h36
-rw-r--r--include/llvm/DebugInfo/CodeView/TypeStreamMerger.h7
-rw-r--r--include/llvm/DebugInfo/CodeView/TypeTableBuilder.h6
-rw-r--r--include/llvm/DebugInfo/DIContext.h30
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h49
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h17
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFAttribute.h56
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFCompileUnit.h18
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFContext.h25
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h12
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h13
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFDebugAranges.h14
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h14
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h35
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFDebugLine.h33
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h14
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFDebugMacro.h3
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFDebugPubTable.h18
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h16
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFDie.h163
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFFormValue.h178
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFGdbIndex.h20
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFRelocMap.h15
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFSection.h12
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h23
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFUnit.h59
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFUnitIndex.h25
-rw-r--r--include/llvm/DebugInfo/MSF/ByteStream.h169
-rw-r--r--include/llvm/DebugInfo/MSF/MappedBlockStream.h65
-rw-r--r--include/llvm/DebugInfo/MSF/StreamInterface.h53
-rw-r--r--include/llvm/DebugInfo/MSF/StreamReader.h121
-rw-r--r--include/llvm/DebugInfo/MSF/StreamRef.h135
-rw-r--r--include/llvm/DebugInfo/MSF/StreamWriter.h92
-rw-r--r--include/llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h10
-rw-r--r--include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h1
-rw-r--r--include/llvm/DebugInfo/PDB/IPDBRawSymbol.h5
-rw-r--r--include/llvm/DebugInfo/PDB/IPDBSession.h11
-rw-r--r--include/llvm/DebugInfo/PDB/Native/DbiStream.h (renamed from include/llvm/DebugInfo/PDB/Raw/DbiStream.h)50
-rw-r--r--include/llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h (renamed from include/llvm/DebugInfo/PDB/Raw/DbiStreamBuilder.h)30
-rw-r--r--include/llvm/DebugInfo/PDB/Native/EnumTables.h (renamed from include/llvm/DebugInfo/PDB/Raw/EnumTables.h)0
-rw-r--r--include/llvm/DebugInfo/PDB/Native/Formatters.h52
-rw-r--r--include/llvm/DebugInfo/PDB/Native/GlobalsStream.h (renamed from include/llvm/DebugInfo/PDB/Raw/GlobalsStream.h)12
-rw-r--r--include/llvm/DebugInfo/PDB/Native/Hash.h (renamed from include/llvm/DebugInfo/PDB/Raw/Hash.h)0
-rw-r--r--include/llvm/DebugInfo/PDB/Native/HashTable.h106
-rw-r--r--include/llvm/DebugInfo/PDB/Native/ISectionContribVisitor.h (renamed from include/llvm/DebugInfo/PDB/Raw/ISectionContribVisitor.h)0
-rw-r--r--include/llvm/DebugInfo/PDB/Native/InfoStream.h (renamed from include/llvm/DebugInfo/PDB/Raw/InfoStream.h)20
-rw-r--r--include/llvm/DebugInfo/PDB/Native/InfoStreamBuilder.h (renamed from include/llvm/DebugInfo/PDB/Raw/InfoStreamBuilder.h)22
-rw-r--r--include/llvm/DebugInfo/PDB/Native/ModInfo.h (renamed from include/llvm/DebugInfo/PDB/Raw/ModInfo.h)14
-rw-r--r--include/llvm/DebugInfo/PDB/Native/ModInfoBuilder.h74
-rw-r--r--include/llvm/DebugInfo/PDB/Native/ModStream.h (renamed from include/llvm/DebugInfo/PDB/Raw/ModStream.h)10
-rw-r--r--include/llvm/DebugInfo/PDB/Native/NamedStreamMap.h55
-rw-r--r--include/llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h35
-rw-r--r--include/llvm/DebugInfo/PDB/Native/NativeEnumModules.h41
-rw-r--r--include/llvm/DebugInfo/PDB/Native/NativeExeSymbol.h39
-rw-r--r--include/llvm/DebugInfo/PDB/Native/NativeRawSymbol.h208
-rw-r--r--include/llvm/DebugInfo/PDB/Native/NativeSession.h (renamed from include/llvm/DebugInfo/PDB/Raw/RawSession.h)10
-rw-r--r--include/llvm/DebugInfo/PDB/Native/PDBFile.h (renamed from include/llvm/DebugInfo/PDB/Raw/PDBFile.h)30
-rw-r--r--include/llvm/DebugInfo/PDB/Native/PDBFileBuilder.h (renamed from include/llvm/DebugInfo/PDB/Raw/PDBFileBuilder.h)13
-rw-r--r--include/llvm/DebugInfo/PDB/Native/PDBTypeServerHandler.h48
-rw-r--r--include/llvm/DebugInfo/PDB/Native/PublicsStream.h (renamed from include/llvm/DebugInfo/PDB/Raw/PublicsStream.h)25
-rw-r--r--include/llvm/DebugInfo/PDB/Native/RawConstants.h (renamed from include/llvm/DebugInfo/PDB/Raw/RawConstants.h)16
-rw-r--r--include/llvm/DebugInfo/PDB/Native/RawError.h (renamed from include/llvm/DebugInfo/PDB/Raw/RawError.h)1
-rw-r--r--include/llvm/DebugInfo/PDB/Native/RawTypes.h (renamed from include/llvm/DebugInfo/PDB/Raw/RawTypes.h)13
-rw-r--r--include/llvm/DebugInfo/PDB/Native/StringTable.h (renamed from include/llvm/DebugInfo/PDB/Raw/NameHashTable.h)38
-rw-r--r--include/llvm/DebugInfo/PDB/Native/StringTableBuilder.h44
-rw-r--r--include/llvm/DebugInfo/PDB/Native/SymbolStream.h (renamed from include/llvm/DebugInfo/PDB/Raw/SymbolStream.h)0
-rw-r--r--include/llvm/DebugInfo/PDB/Native/TpiHashing.h (renamed from include/llvm/DebugInfo/PDB/Raw/TpiHashing.h)8
-rw-r--r--include/llvm/DebugInfo/PDB/Native/TpiStream.h (renamed from include/llvm/DebugInfo/PDB/Raw/TpiStream.h)23
-rw-r--r--include/llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h (renamed from include/llvm/DebugInfo/PDB/Raw/TpiStreamBuilder.h)44
-rw-r--r--include/llvm/DebugInfo/PDB/PDBExtras.h2
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymDumper.h16
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbol.h37
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolBlock.h2
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolCompiland.h2
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolCompilandDetails.h2
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolCompilandEnv.h2
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolData.h8
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolExe.h2
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolFunc.h12
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h2
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h2
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolLabel.h2
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h2
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolThunk.h6
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolTypeArray.h9
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h11
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h2
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h12
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolTypeFriend.h4
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h6
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h11
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolTypePointer.h7
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h8
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h16
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h7
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolTypeVTableShape.h2
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbolUsingNamespace.h2
-rw-r--r--include/llvm/DebugInfo/PDB/PDBTypes.h6
-rw-r--r--include/llvm/DebugInfo/PDB/Raw/NameMap.h44
-rw-r--r--include/llvm/DebugInfo/PDB/Raw/NameMapBuilder.h45
-rw-r--r--include/llvm/DebugInfo/PDB/UDTLayout.h180
-rw-r--r--include/llvm/DebugInfo/Symbolize/DIPrinter.h7
-rw-r--r--include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h12
-rw-r--r--include/llvm/ExecutionEngine/Orc/OrcError.h6
-rw-r--r--include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h1
-rw-r--r--include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h23
-rw-r--r--include/llvm/ExecutionEngine/Orc/RPCSerialization.h243
-rw-r--r--include/llvm/ExecutionEngine/Orc/RPCUtils.h787
-rw-r--r--include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h (renamed from include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h)18
-rw-r--r--include/llvm/ExecutionEngine/Orc/RawByteChannel.h34
-rw-r--r--include/llvm/IR/Argument.h99
-rw-r--r--include/llvm/IR/Attributes.h294
-rw-r--r--include/llvm/IR/BasicBlock.h87
-rw-r--r--include/llvm/IR/CallSite.h177
-rw-r--r--include/llvm/IR/Comdat.h6
-rw-r--r--include/llvm/IR/Constant.h7
-rw-r--r--include/llvm/IR/ConstantRange.h11
-rw-r--r--include/llvm/IR/Constants.h2
-rw-r--r--include/llvm/IR/DIBuilder.h28
-rw-r--r--include/llvm/IR/DataLayout.h42
-rw-r--r--include/llvm/IR/DebugInfoFlags.def3
-rw-r--r--include/llvm/IR/DebugInfoMetadata.h209
-rw-r--r--include/llvm/IR/DiagnosticInfo.h591
-rw-r--r--include/llvm/IR/Dominators.h45
-rw-r--r--include/llvm/IR/Function.h101
-rw-r--r--include/llvm/IR/GlobalIndirectSymbol.h18
-rw-r--r--include/llvm/IR/GlobalObject.h13
-rw-r--r--include/llvm/IR/GlobalValue.h14
-rw-r--r--include/llvm/IR/IRBuilder.h104
-rw-r--r--include/llvm/IR/InlineAsm.h24
-rw-r--r--include/llvm/IR/InstVisitor.h3
-rw-r--r--include/llvm/IR/InstrTypes.h4
-rw-r--r--include/llvm/IR/Instruction.h51
-rw-r--r--include/llvm/IR/Instructions.h348
-rw-r--r--include/llvm/IR/IntrinsicInst.h65
-rw-r--r--include/llvm/IR/Intrinsics.h4
-rw-r--r--include/llvm/IR/Intrinsics.td82
-rw-r--r--include/llvm/IR/IntrinsicsAMDGPU.td109
-rw-r--r--include/llvm/IR/IntrinsicsARM.td2
-rw-r--r--include/llvm/IR/IntrinsicsHexagon.td870
-rw-r--r--include/llvm/IR/IntrinsicsNVVM.td84
-rw-r--r--include/llvm/IR/IntrinsicsPowerPC.td32
-rw-r--r--include/llvm/IR/IntrinsicsWebAssembly.td2
-rw-r--r--include/llvm/IR/IntrinsicsX86.td156
-rw-r--r--include/llvm/IR/LLVMContext.h1
-rw-r--r--include/llvm/IR/MDBuilder.h9
-rw-r--r--include/llvm/IR/Mangler.h4
-rw-r--r--include/llvm/IR/Metadata.h15
-rw-r--r--include/llvm/IR/Module.h66
-rw-r--r--include/llvm/IR/ModuleSummaryIndex.h222
-rw-r--r--include/llvm/IR/ModuleSummaryIndexYAML.h135
-rw-r--r--include/llvm/IR/Operator.h24
-rw-r--r--include/llvm/IR/OptBisect.h18
-rw-r--r--include/llvm/IR/PassManager.h70
-rw-r--r--include/llvm/IR/PassManagerInternal.h2
-rw-r--r--include/llvm/IR/PatternMatch.h56
-rw-r--r--include/llvm/IR/PredIteratorCache.h14
-rw-r--r--include/llvm/IR/Statepoint.h2
-rw-r--r--include/llvm/IR/SymbolTableListTraits.h28
-rw-r--r--include/llvm/IR/TrackingMDRef.h17
-rw-r--r--include/llvm/IR/Type.h8
-rw-r--r--include/llvm/IR/TypeFinder.h14
-rw-r--r--include/llvm/IR/Use.h4
-rw-r--r--include/llvm/IR/UseListOrder.h7
-rw-r--r--include/llvm/IR/User.h14
-rw-r--r--include/llvm/IR/Value.h57
-rw-r--r--include/llvm/IR/ValueHandle.h136
-rw-r--r--include/llvm/IR/ValueSymbolTable.h45
-rw-r--r--include/llvm/InitializePasses.h125
-rw-r--r--include/llvm/LTO/Caching.h15
-rw-r--r--include/llvm/LTO/Config.h8
-rw-r--r--include/llvm/LTO/LTO.h197
-rw-r--r--include/llvm/LTO/LTOBackend.h7
-rw-r--r--include/llvm/LTO/legacy/LTOCodeGenerator.h7
-rw-r--r--include/llvm/LTO/legacy/ThinLTOCodeGenerator.h19
-rw-r--r--include/llvm/LinkAllPasses.h3
-rw-r--r--include/llvm/Linker/IRMover.h6
-rw-r--r--include/llvm/Linker/Linker.h19
-rw-r--r--include/llvm/MC/ConstantPools.h10
-rw-r--r--include/llvm/MC/MCAsmBackend.h26
-rw-r--r--include/llvm/MC/MCAsmInfo.h140
-rw-r--r--include/llvm/MC/MCAsmInfoCOFF.h42
-rw-r--r--include/llvm/MC/MCAsmInfoDarwin.h16
-rw-r--r--include/llvm/MC/MCAsmInfoELF.h10
-rw-r--r--include/llvm/MC/MCAsmInfoWasm.h24
-rw-r--r--include/llvm/MC/MCAssembler.h59
-rw-r--r--include/llvm/MC/MCCodeEmitter.h15
-rw-r--r--include/llvm/MC/MCContext.h186
-rw-r--r--include/llvm/MC/MCDisassembler/MCDisassembler.h17
-rw-r--r--include/llvm/MC/MCDisassembler/MCRelocationInfo.h18
-rw-r--r--include/llvm/MC/MCDisassembler/MCSymbolizer.h16
-rw-r--r--include/llvm/MC/MCDwarf.h48
-rw-r--r--include/llvm/MC/MCELFObjectWriter.h25
-rw-r--r--include/llvm/MC/MCELFStreamer.h26
-rw-r--r--include/llvm/MC/MCExpr.h85
-rw-r--r--include/llvm/MC/MCFragment.h32
-rw-r--r--include/llvm/MC/MCInst.h30
-rw-r--r--include/llvm/MC/MCInstPrinter.h16
-rw-r--r--include/llvm/MC/MCInstrAnalysis.h11
-rw-r--r--include/llvm/MC/MCInstrItineraries.h28
-rw-r--r--include/llvm/MC/MCLabel.h12
-rw-r--r--include/llvm/MC/MCLinkerOptimizationHint.h11
-rw-r--r--include/llvm/MC/MCMachObjectWriter.h15
-rw-r--r--include/llvm/MC/MCObjectFileInfo.h5
-rw-r--r--include/llvm/MC/MCObjectStreamer.h7
-rw-r--r--include/llvm/MC/MCObjectWriter.h24
-rw-r--r--include/llvm/MC/MCParser/AsmCond.h10
-rw-r--r--include/llvm/MC/MCParser/AsmLexer.h19
-rw-r--r--include/llvm/MC/MCParser/MCAsmLexer.h30
-rw-r--r--include/llvm/MC/MCParser/MCAsmParser.h41
-rw-r--r--include/llvm/MC/MCParser/MCAsmParserExtension.h26
-rw-r--r--include/llvm/MC/MCParser/MCAsmParserUtils.h5
-rw-r--r--include/llvm/MC/MCParser/MCParsedAsmOperand.h14
-rw-r--r--include/llvm/MC/MCParser/MCTargetAsmParser.h34
-rw-r--r--include/llvm/MC/MCRegisterInfo.h58
-rw-r--r--include/llvm/MC/MCSection.h33
-rw-r--r--include/llvm/MC/MCSectionCOFF.h8
-rw-r--r--include/llvm/MC/MCSectionELF.h23
-rw-r--r--include/llvm/MC/MCSectionMachO.h3
-rw-r--r--include/llvm/MC/MCSectionWasm.h86
-rw-r--r--include/llvm/MC/MCStreamer.h41
-rw-r--r--include/llvm/MC/MCSubtargetInfo.h34
-rw-r--r--include/llvm/MC/MCSymbol.h29
-rw-r--r--include/llvm/MC/MCSymbolCOFF.h13
-rw-r--r--include/llvm/MC/MCSymbolWasm.h57
-rw-r--r--include/llvm/MC/MCTargetOptions.h40
-rw-r--r--include/llvm/MC/MCWasmObjectWriter.h85
-rw-r--r--include/llvm/MC/MCWasmStreamer.h83
-rw-r--r--include/llvm/MC/MCWinCOFFObjectWriter.h11
-rw-r--r--include/llvm/MC/MCWinCOFFStreamer.h11
-rw-r--r--include/llvm/MC/MachineLocation.h30
-rw-r--r--include/llvm/MC/StringTableBuilder.h11
-rw-r--r--include/llvm/MC/SubtargetFeature.h96
-rw-r--r--include/llvm/Object/Archive.h1
-rw-r--r--include/llvm/Object/Binary.h11
-rw-r--r--include/llvm/Object/ELF.h2
-rw-r--r--include/llvm/Object/ELFObjectFile.h31
-rw-r--r--include/llvm/Object/IRSymtab.h302
-rw-r--r--include/llvm/Object/MachO.h197
-rw-r--r--include/llvm/Object/ModuleSummaryIndexObjectFile.h7
-rw-r--r--include/llvm/Object/ModuleSymbolTable.h3
-rw-r--r--include/llvm/Object/ObjectFile.h8
-rw-r--r--include/llvm/Object/RelocVisitor.h7
-rw-r--r--include/llvm/Object/SymbolicFile.h4
-rw-r--r--include/llvm/Object/Wasm.h112
-rw-r--r--include/llvm/ObjectYAML/DWARFEmitter.h48
-rw-r--r--include/llvm/ObjectYAML/DWARFYAML.h52
-rw-r--r--include/llvm/ObjectYAML/MachOYAML.h8
-rw-r--r--include/llvm/ObjectYAML/ObjectYAML.h6
-rw-r--r--include/llvm/ObjectYAML/WasmYAML.h339
-rw-r--r--include/llvm/Option/ArgList.h214
-rw-r--r--include/llvm/PassSupport.h10
-rw-r--r--include/llvm/Passes/PassBuilder.h13
-rw-r--r--include/llvm/ProfileData/Coverage/CoverageMapping.h79
-rw-r--r--include/llvm/ProfileData/Coverage/CoverageMappingReader.h46
-rw-r--r--include/llvm/ProfileData/Coverage/CoverageMappingWriter.h15
-rw-r--r--include/llvm/ProfileData/InstrProf.h171
-rw-r--r--include/llvm/ProfileData/InstrProfData.inc84
-rw-r--r--include/llvm/ProfileData/InstrProfReader.h88
-rw-r--r--include/llvm/ProfileData/InstrProfWriter.h20
-rw-r--r--include/llvm/ProfileData/ProfileCommon.h54
-rw-r--r--include/llvm/ProfileData/SampleProf.h124
-rw-r--r--include/llvm/ProfileData/SampleProfReader.h29
-rw-r--r--include/llvm/ProfileData/SampleProfWriter.h20
-rw-r--r--include/llvm/Support/AArch64TargetParser.def13
-rw-r--r--include/llvm/Support/ARMAttributeParser.h140
-rw-r--r--include/llvm/Support/ARMBuildAttributes.h14
-rw-r--r--include/llvm/Support/ARMTargetParser.def6
-rw-r--r--include/llvm/Support/Allocator.h50
-rw-r--r--include/llvm/Support/Atomic.h5
-rw-r--r--include/llvm/Support/BinaryByteStream.h192
-rw-r--r--include/llvm/Support/BinaryItemStream.h (renamed from include/llvm/DebugInfo/MSF/SequencedItemStream.h)54
-rw-r--r--include/llvm/Support/BinaryStream.h78
-rw-r--r--include/llvm/Support/BinaryStreamArray.h (renamed from include/llvm/DebugInfo/MSF/StreamArray.h)86
-rw-r--r--include/llvm/Support/BinaryStreamError.h48
-rw-r--r--include/llvm/Support/BinaryStreamReader.h234
-rw-r--r--include/llvm/Support/BinaryStreamRef.h174
-rw-r--r--include/llvm/Support/BinaryStreamWriter.h166
-rw-r--r--include/llvm/Support/CMakeLists.txt54
-rw-r--r--include/llvm/Support/CachePruning.h79
-rw-r--r--include/llvm/Support/Casting.h70
-rw-r--r--include/llvm/Support/Chrono.h95
-rw-r--r--include/llvm/Support/CommandLine.h8
-rw-r--r--include/llvm/Support/Compiler.h7
-rw-r--r--include/llvm/Support/Compression.h24
-rw-r--r--include/llvm/Support/Debug.h28
-rw-r--r--include/llvm/Support/DebugCounter.h165
-rw-r--r--include/llvm/Support/Dwarf.def87
-rw-r--r--include/llvm/Support/Dwarf.h13
-rw-r--r--include/llvm/Support/DynamicLibrary.h9
-rw-r--r--include/llvm/Support/ELF.h36
-rw-r--r--include/llvm/Support/Endian.h89
-rw-r--r--include/llvm/Support/Error.h102
-rw-r--r--include/llvm/Support/FileSystem.h274
-rw-r--r--include/llvm/Support/FormatAdapters.h3
-rw-r--r--include/llvm/Support/FormatProviders.h22
-rw-r--r--include/llvm/Support/FormatVariadic.h2
-rw-r--r--include/llvm/Support/GCOV.h67
-rw-r--r--include/llvm/Support/GenericDomTree.h76
-rw-r--r--include/llvm/Support/GenericDomTreeConstruction.h142
-rw-r--r--include/llvm/Support/Host.h12
-rw-r--r--include/llvm/Support/LEB128.h72
-rw-r--r--include/llvm/Support/LowLevelTypeImpl.h202
-rw-r--r--include/llvm/Support/MD5.h59
-rw-r--r--include/llvm/Support/MachO.def4
-rw-r--r--include/llvm/Support/MachO.h102
-rw-r--r--include/llvm/Support/MathExtras.h4
-rw-r--r--include/llvm/Support/MemoryBuffer.h20
-rw-r--r--include/llvm/Support/Path.h80
-rw-r--r--include/llvm/Support/PointerLikeTypeTraits.h14
-rw-r--r--include/llvm/Support/RWMutex.h25
-rw-r--r--include/llvm/Support/SMLoc.h4
-rw-r--r--include/llvm/Support/SourceMgr.h57
-rw-r--r--include/llvm/Support/TargetParser.h2
-rw-r--r--include/llvm/Support/TargetRegistry.h71
-rw-r--r--include/llvm/Support/ThreadPool.h15
-rw-r--r--include/llvm/Support/Threading.h104
-rw-r--r--include/llvm/Support/Timer.h4
-rw-r--r--include/llvm/Support/TrailingObjects.h7
-rw-r--r--include/llvm/Support/UniqueLock.h18
-rw-r--r--include/llvm/Support/Wasm.h145
-rw-r--r--include/llvm/Support/WasmRelocs/WebAssembly.def13
-rw-r--r--include/llvm/Support/YAMLTraits.h15
-rw-r--r--include/llvm/Support/thread.h14
-rw-r--r--include/llvm/Support/type_traits.h9
-rw-r--r--include/llvm/TableGen/Record.h4
-rw-r--r--include/llvm/TableGen/StringMatcher.h2
-rw-r--r--include/llvm/TableGen/StringToOffsetTable.h8
-rw-r--r--include/llvm/Target/GenericOpcodes.td121
-rw-r--r--include/llvm/Target/GlobalISel/RegisterBank.td16
-rw-r--r--include/llvm/Target/GlobalISel/SelectionDAGCompat.td (renamed from include/llvm/Target/TargetGlobalISel.td)24
-rw-r--r--include/llvm/Target/GlobalISel/Target.td56
-rw-r--r--include/llvm/Target/Target.td33
-rw-r--r--include/llvm/Target/TargetCallingConv.h202
-rw-r--r--include/llvm/Target/TargetInstrInfo.h140
-rw-r--r--include/llvm/Target/TargetLowering.h154
-rw-r--r--include/llvm/Target/TargetLoweringObjectFile.h50
-rw-r--r--include/llvm/Target/TargetMachine.h12
-rw-r--r--include/llvm/Target/TargetOpcodes.def55
-rw-r--r--include/llvm/Target/TargetOptions.h89
-rw-r--r--include/llvm/Target/TargetRegisterInfo.h12
-rw-r--r--include/llvm/Target/TargetSchedule.td5
-rw-r--r--include/llvm/Target/TargetSelectionDAG.td22
-rw-r--r--include/llvm/Target/TargetSubtargetInfo.h8
-rw-r--r--include/llvm/Transforms/IPO.h45
-rw-r--r--include/llvm/Transforms/IPO/ArgumentPromotion.h31
-rw-r--r--include/llvm/Transforms/IPO/FunctionAttrs.h15
-rw-r--r--include/llvm/Transforms/IPO/FunctionImport.h6
-rw-r--r--include/llvm/Transforms/IPO/GlobalDCE.h21
-rw-r--r--include/llvm/Transforms/IPO/LowerTypeTests.h10
-rw-r--r--include/llvm/Transforms/IPO/PassManagerBuilder.h20
-rw-r--r--include/llvm/Transforms/InstrProfiling.h40
-rw-r--r--include/llvm/Transforms/Instrumentation.h84
-rw-r--r--include/llvm/Transforms/PGOInstrumentation.h15
-rw-r--r--include/llvm/Transforms/Scalar.h30
-rw-r--r--include/llvm/Transforms/Scalar/GVNExpression.h313
-rw-r--r--include/llvm/Transforms/Scalar/JumpThreading.h10
-rw-r--r--include/llvm/Transforms/Scalar/LoopDataPrefetch.h8
-rw-r--r--include/llvm/Transforms/Scalar/LoopDeletion.h17
-rw-r--r--include/llvm/Transforms/Scalar/LoopLoadElimination.h30
-rw-r--r--include/llvm/Transforms/Scalar/LoopPassManager.h36
-rw-r--r--include/llvm/Transforms/Scalar/LoopPredication.h32
-rw-r--r--include/llvm/Transforms/Scalar/LoopSink.h40
-rw-r--r--include/llvm/Transforms/Scalar/LoopUnrollPass.h30
-rw-r--r--include/llvm/Transforms/Scalar/MemCpyOptimizer.h11
-rw-r--r--include/llvm/Transforms/Scalar/SROA.h18
-rw-r--r--include/llvm/Transforms/Scalar/SimplifyCFG.h9
-rw-r--r--include/llvm/Transforms/Utils/BasicBlockUtils.h9
-rw-r--r--include/llvm/Transforms/Utils/BuildLibCalls.h4
-rw-r--r--include/llvm/Transforms/Utils/Cloning.h54
-rw-r--r--include/llvm/Transforms/Utils/FunctionComparator.h2
-rw-r--r--include/llvm/Transforms/Utils/FunctionImportUtils.h11
-rw-r--r--include/llvm/Transforms/Utils/GlobalStatus.h31
-rw-r--r--include/llvm/Transforms/Utils/Local.h23
-rw-r--r--include/llvm/Transforms/Utils/LoopUtils.h57
-rw-r--r--include/llvm/Transforms/Utils/LowerMemIntrinsics.h44
-rw-r--r--include/llvm/Transforms/Utils/ModuleUtils.h3
-rw-r--r--include/llvm/Transforms/Utils/NameAnonGlobals.h8
-rw-r--r--include/llvm/Transforms/Utils/PredicateInfo.h295
-rw-r--r--include/llvm/Transforms/Utils/PromoteMemToReg.h3
-rw-r--r--include/llvm/Transforms/Utils/SSAUpdater.h38
-rw-r--r--include/llvm/Transforms/Utils/SimplifyIndVar.h11
-rw-r--r--include/llvm/Transforms/Utils/SimplifyLibCalls.h5
-rw-r--r--include/llvm/Transforms/Utils/SymbolRewriter.h23
-rw-r--r--include/llvm/Transforms/Utils/UnifyFunctionExitNodes.h12
-rw-r--r--include/llvm/Transforms/Utils/UnrollLoop.h5
-rw-r--r--include/llvm/Transforms/Utils/VNCoercion.h108
-rw-r--r--include/llvm/Transforms/Utils/ValueMapper.h20
-rw-r--r--include/llvm/Transforms/Vectorize/SLPVectorizer.h6
-rw-r--r--include/llvm/XRay/Graph.h494
-rw-r--r--include/llvm/XRay/InstrumentationMap.h129
-rw-r--r--include/llvm/XRay/XRayRecord.h9
-rw-r--r--include/llvm/XRay/YAMLXRayRecord.h2
-rw-r--r--include/llvm/module.modulemap11
559 files changed, 20790 insertions, 8857 deletions
diff --git a/include/llvm-c/Transforms/Scalar.h b/include/llvm-c/Transforms/Scalar.h
index 8991e0904849..b9612b9cec04 100644
--- a/include/llvm-c/Transforms/Scalar.h
+++ b/include/llvm-c/Transforms/Scalar.h
@@ -44,6 +44,9 @@ void LLVMAddAlignmentFromAssumptionsPass(LLVMPassManagerRef PM);
/** See llvm::createCFGSimplificationPass function. */
void LLVMAddCFGSimplificationPass(LLVMPassManagerRef PM);
+/** See llvm::createLateCFGSimplificationPass function. */
+void LLVMAddLateCFGSimplificationPass(LLVMPassManagerRef PM);
+
/** See llvm::createDeadStoreEliminationPass function. */
void LLVMAddDeadStoreEliminationPass(LLVMPassManagerRef PM);
diff --git a/include/llvm-c/lto.h b/include/llvm-c/lto.h
index c3af74cdedab..8d45b7832041 100644
--- a/include/llvm-c/lto.h
+++ b/include/llvm-c/lto.h
@@ -551,7 +551,7 @@ lto_codegen_set_should_embed_uselists(lto_code_gen_t cg,
lto_bool_t ShouldEmbedUselists);
/**
- * @}
+ * @} // endgoup LLVMCLTO
* @defgroup LLVMCTLTO ThinLTO
* @ingroup LLVMC
*
@@ -669,75 +669,6 @@ extern lto_bool_t thinlto_codegen_set_pic_model(thinlto_code_gen_t cg,
lto_codegen_model);
/**
- * @}
- * @defgroup LLVMCTLTO_CACHING ThinLTO Cache Control
- * @ingroup LLVMCTLTO
- *
- * These entry points control the ThinLTO cache. The cache is intended to
- * support incremental build, and thus needs to be persistent accross build.
- * The client enabled the cache by supplying a path to an existing directory.
- * The code generator will use this to store objects files that may be reused
- * during a subsequent build.
- * To avoid filling the disk space, a few knobs are provided:
- * - The pruning interval limit the frequency at which the garbage collector
- * will try to scan the cache directory to prune it from expired entries.
- * Setting to -1 disable the pruning (default).
- * - The pruning expiration time indicates to the garbage collector how old an
- * entry needs to be to be removed.
- * - Finally, the garbage collector can be instructed to prune the cache till
- * the occupied space goes below a threshold.
- * @{
- */
-
-/**
- * Sets the path to a directory to use as a cache storage for incremental build.
- * Setting this activates caching.
- *
- * \since LTO_API_VERSION=18
- */
-extern void thinlto_codegen_set_cache_dir(thinlto_code_gen_t cg,
- const char *cache_dir);
-
-/**
- * Sets the cache pruning interval (in seconds). A negative value disable the
- * pruning. An unspecified default value will be applied, and a value of 0 will
- * be ignored.
- *
- * \since LTO_API_VERSION=18
- */
-extern void thinlto_codegen_set_cache_pruning_interval(thinlto_code_gen_t cg,
- int interval);
-
-/**
- * Sets the maximum cache size that can be persistent across build, in terms of
- * percentage of the available space on the the disk. Set to 100 to indicate
- * no limit, 50 to indicate that the cache size will not be left over half the
- * available space. A value over 100 will be reduced to 100, a value of 0 will
- * be ignored. An unspecified default value will be applied.
- *
- * The formula looks like:
- * AvailableSpace = FreeSpace + ExistingCacheSize
- * NewCacheSize = AvailableSpace * P/100
- *
- * \since LTO_API_VERSION=18
- */
-extern void thinlto_codegen_set_final_cache_size_relative_to_available_space(
- thinlto_code_gen_t cg, unsigned percentage);
-
-/**
- * Sets the expiration (in seconds) for an entry in the cache. An unspecified
- * default value will be applied. A value of 0 will be ignored.
- *
- * \since LTO_API_VERSION=18
- */
-extern void thinlto_codegen_set_cache_entry_expiration(thinlto_code_gen_t cg,
- unsigned expiration);
-
-/**
- * @}
- */
-
-/**
* Sets the path to a directory to use as a storage for temporary bitcode files.
* The intention is to make the bitcode files available for debugging at various
* stage of the pipeline.
@@ -820,12 +751,77 @@ extern void thinlto_codegen_add_cross_referenced_symbol(thinlto_code_gen_t cg,
const char *name,
int length);
-#ifdef __cplusplus
-}
-#endif
+/**
+ * @} // endgoup LLVMCTLTO
+ * @defgroup LLVMCTLTO_CACHING ThinLTO Cache Control
+ * @ingroup LLVMCTLTO
+ *
+ * These entry points control the ThinLTO cache. The cache is intended to
+ * support incremental build, and thus needs to be persistent accross build.
+ * The client enabled the cache by supplying a path to an existing directory.
+ * The code generator will use this to store objects files that may be reused
+ * during a subsequent build.
+ * To avoid filling the disk space, a few knobs are provided:
+ * - The pruning interval limit the frequency at which the garbage collector
+ * will try to scan the cache directory to prune it from expired entries.
+ * Setting to -1 disable the pruning (default).
+ * - The pruning expiration time indicates to the garbage collector how old an
+ * entry needs to be to be removed.
+ * - Finally, the garbage collector can be instructed to prune the cache till
+ * the occupied space goes below a threshold.
+ * @{
+ */
+
+/**
+ * Sets the path to a directory to use as a cache storage for incremental build.
+ * Setting this activates caching.
+ *
+ * \since LTO_API_VERSION=18
+ */
+extern void thinlto_codegen_set_cache_dir(thinlto_code_gen_t cg,
+ const char *cache_dir);
+
+/**
+ * Sets the cache pruning interval (in seconds). A negative value disable the
+ * pruning. An unspecified default value will be applied, and a value of 0 will
+ * be ignored.
+ *
+ * \since LTO_API_VERSION=18
+ */
+extern void thinlto_codegen_set_cache_pruning_interval(thinlto_code_gen_t cg,
+ int interval);
+
+/**
+ * Sets the maximum cache size that can be persistent across build, in terms of
+ * percentage of the available space on the the disk. Set to 100 to indicate
+ * no limit, 50 to indicate that the cache size will not be left over half the
+ * available space. A value over 100 will be reduced to 100, a value of 0 will
+ * be ignored. An unspecified default value will be applied.
+ *
+ * The formula looks like:
+ * AvailableSpace = FreeSpace + ExistingCacheSize
+ * NewCacheSize = AvailableSpace * P/100
+ *
+ * \since LTO_API_VERSION=18
+ */
+extern void thinlto_codegen_set_final_cache_size_relative_to_available_space(
+ thinlto_code_gen_t cg, unsigned percentage);
/**
- * @}
+ * Sets the expiration (in seconds) for an entry in the cache. An unspecified
+ * default value will be applied. A value of 0 will be ignored.
+ *
+ * \since LTO_API_VERSION=18
*/
+extern void thinlto_codegen_set_cache_entry_expiration(thinlto_code_gen_t cg,
+ unsigned expiration);
+
+/**
+ * @} // endgroup LLVMCTLTO_CACHING
+ */
+
+#ifdef __cplusplus
+}
+#endif
#endif /* LLVM_C_LTO_H */
diff --git a/include/llvm/ADT/APFloat.h b/include/llvm/ADT/APFloat.h
index 00304230a991..e7e5036e6930 100644
--- a/include/llvm/ADT/APFloat.h
+++ b/include/llvm/ADT/APFloat.h
@@ -18,9 +18,19 @@
#define LLVM_ADT_APFLOAT_H
#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/Support/ErrorHandling.h"
#include <memory>
+#define APFLOAT_DISPATCH_ON_SEMANTICS(METHOD_CALL) \
+ do { \
+ if (usesLayout<IEEEFloat>(getSemantics())) \
+ return U.IEEE.METHOD_CALL; \
+ if (usesLayout<DoubleAPFloat>(getSemantics())) \
+ return U.Double.METHOD_CALL; \
+ llvm_unreachable("Unexpected semantics"); \
+ } while (false)
+
namespace llvm {
struct fltSemantics;
@@ -42,7 +52,7 @@ enum lostFraction { // Example of truncated bits:
lfMoreThanHalf // 1xxxxx x's not all zero
};
-/// \brief A self-contained host- and target-independent arbitrary-precision
+/// A self-contained host- and target-independent arbitrary-precision
/// floating-point software implementation.
///
/// APFloat uses bignum integer arithmetic as provided by static functions in
@@ -130,22 +140,25 @@ enum lostFraction { // Example of truncated bits:
// implementation classes. This struct should not define any non-static data
// members.
struct APFloatBase {
+ // TODO remove this and use APInt typedef directly.
+ typedef APInt::WordType integerPart;
+
/// A signed type to represent a floating point numbers unbiased exponent.
typedef signed short ExponentType;
/// \name Floating Point Semantics.
/// @{
- static const fltSemantics &IEEEhalf();
- static const fltSemantics &IEEEsingle();
- static const fltSemantics &IEEEdouble();
- static const fltSemantics &IEEEquad();
- static const fltSemantics &PPCDoubleDouble();
- static const fltSemantics &x87DoubleExtended();
+ static const fltSemantics &IEEEhalf() LLVM_READNONE;
+ static const fltSemantics &IEEEsingle() LLVM_READNONE;
+ static const fltSemantics &IEEEdouble() LLVM_READNONE;
+ static const fltSemantics &IEEEquad() LLVM_READNONE;
+ static const fltSemantics &PPCDoubleDouble() LLVM_READNONE;
+ static const fltSemantics &x87DoubleExtended() LLVM_READNONE;
/// A Pseudo fltsemantic used to construct APFloats that cannot conflict with
/// anything real.
- static const fltSemantics &Bogus();
+ static const fltSemantics &Bogus() LLVM_READNONE;
/// @}
@@ -191,7 +204,7 @@ struct APFloatBase {
uninitialized
};
- /// \brief Enumeration of \c ilogb error results.
+ /// Enumeration of \c ilogb error results.
enum IlogbErrorKinds {
IEK_Zero = INT_MIN + 1,
IEK_NaN = INT_MIN,
@@ -227,7 +240,7 @@ public:
/// @}
- /// \brief Returns whether this instance allocated memory.
+ /// Returns whether this instance allocated memory.
bool needsCleanup() const { return partCount() > 1; }
/// \name Convenience "constructors"
@@ -235,10 +248,6 @@ public:
/// @}
- /// Used to insert APFloat objects, or objects that contain APFloat objects,
- /// into FoldingSets.
- void Profile(FoldingSetNodeID &NID) const;
-
/// \name Arithmetic
/// @{
@@ -255,53 +264,12 @@ public:
/// IEEE-754R 5.3.1: nextUp/nextDown.
opStatus next(bool nextDown);
- /// \brief Operator+ overload which provides the default
- /// \c nmNearestTiesToEven rounding mode and *no* error checking.
- IEEEFloat operator+(const IEEEFloat &RHS) const {
- IEEEFloat Result = *this;
- Result.add(RHS, rmNearestTiesToEven);
- return Result;
- }
-
- /// \brief Operator- overload which provides the default
- /// \c nmNearestTiesToEven rounding mode and *no* error checking.
- IEEEFloat operator-(const IEEEFloat &RHS) const {
- IEEEFloat Result = *this;
- Result.subtract(RHS, rmNearestTiesToEven);
- return Result;
- }
-
- /// \brief Operator* overload which provides the default
- /// \c nmNearestTiesToEven rounding mode and *no* error checking.
- IEEEFloat operator*(const IEEEFloat &RHS) const {
- IEEEFloat Result = *this;
- Result.multiply(RHS, rmNearestTiesToEven);
- return Result;
- }
-
- /// \brief Operator/ overload which provides the default
- /// \c nmNearestTiesToEven rounding mode and *no* error checking.
- IEEEFloat operator/(const IEEEFloat &RHS) const {
- IEEEFloat Result = *this;
- Result.divide(RHS, rmNearestTiesToEven);
- return Result;
- }
-
/// @}
/// \name Sign operations.
/// @{
void changeSign();
- void clearSign();
- void copySign(const IEEEFloat &);
-
- /// \brief A static helper to produce a copy of an APFloat value with its sign
- /// copied from some other APFloat.
- static IEEEFloat copySign(IEEEFloat Value, const IEEEFloat &Sign) {
- Value.copySign(Sign);
- return Value;
- }
/// @}
@@ -309,9 +277,8 @@ public:
/// @{
opStatus convert(const fltSemantics &, roundingMode, bool *);
- opStatus convertToInteger(integerPart *, unsigned int, bool, roundingMode,
- bool *) const;
- opStatus convertToInteger(APSInt &, roundingMode, bool *) const;
+ opStatus convertToInteger(MutableArrayRef<integerPart>, unsigned int, bool,
+ roundingMode, bool *) const;
opStatus convertFromAPInt(const APInt &, bool, roundingMode);
opStatus convertFromSignExtendedInteger(const integerPart *, unsigned int,
bool, roundingMode);
@@ -398,7 +365,7 @@ public:
/// Returns true if and only if the number has the largest possible finite
/// magnitude in the current semantics.
bool isLargest() const;
-
+
/// Returns true if and only if the number is an exact integer.
bool isInteger() const;
@@ -407,7 +374,7 @@ public:
IEEEFloat &operator=(const IEEEFloat &);
IEEEFloat &operator=(IEEEFloat &&);
- /// \brief Overload to compute a hash code for an APFloat value.
+ /// Overload to compute a hash code for an APFloat value.
///
/// Note that the use of hash codes for floating point values is in general
/// frought with peril. Equality is hard to define for these values. For
@@ -443,9 +410,9 @@ public:
/// If this value has an exact multiplicative inverse, store it in inv and
/// return true.
- bool getExactInverse(IEEEFloat *inv) const;
+ bool getExactInverse(APFloat *inv) const;
- /// \brief Returns the exponent of the internal representation of the APFloat.
+ /// Returns the exponent of the internal representation of the APFloat.
///
/// Because the radix of APFloat is 2, this is equivalent to floor(log2(x)).
/// For special APFloat values, this returns special error codes:
@@ -456,7 +423,7 @@ public:
///
friend int ilogb(const IEEEFloat &Arg);
- /// \brief Returns: X * 2^Exp for integral exponents.
+ /// Returns: X * 2^Exp for integral exponents.
friend IEEEFloat scalbn(IEEEFloat X, int Exp, roundingMode);
friend IEEEFloat frexp(const IEEEFloat &X, int &Exp, roundingMode);
@@ -532,8 +499,9 @@ private:
opStatus addOrSubtract(const IEEEFloat &, roundingMode, bool subtract);
opStatus handleOverflow(roundingMode);
bool roundAwayFromZero(roundingMode, lostFraction, unsigned int) const;
- opStatus convertToSignExtendedInteger(integerPart *, unsigned int, bool,
- roundingMode, bool *) const;
+ opStatus convertToSignExtendedInteger(MutableArrayRef<integerPart>,
+ unsigned int, bool, roundingMode,
+ bool *) const;
opStatus convertFromUnsignedParts(const integerPart *, unsigned int,
roundingMode);
opStatus convertFromHexadecimalString(StringRef, roundingMode);
@@ -636,6 +604,13 @@ public:
opStatus add(const DoubleAPFloat &RHS, roundingMode RM);
opStatus subtract(const DoubleAPFloat &RHS, roundingMode RM);
+ opStatus multiply(const DoubleAPFloat &RHS, roundingMode RM);
+ opStatus divide(const DoubleAPFloat &RHS, roundingMode RM);
+ opStatus remainder(const DoubleAPFloat &RHS);
+ opStatus mod(const DoubleAPFloat &RHS);
+ opStatus fusedMultiplyAdd(const DoubleAPFloat &Multiplicand,
+ const DoubleAPFloat &Addend, roundingMode RM);
+ opStatus roundToIntegral(roundingMode RM);
void changeSign();
cmpResult compareAbsoluteValue(const DoubleAPFloat &RHS) const;
@@ -643,9 +618,49 @@ public:
bool isNegative() const;
void makeInf(bool Neg);
+ void makeZero(bool Neg);
+ void makeLargest(bool Neg);
+ void makeSmallest(bool Neg);
+ void makeSmallestNormalized(bool Neg);
void makeNaN(bool SNaN, bool Neg, const APInt *fill);
+
+ cmpResult compare(const DoubleAPFloat &RHS) const;
+ bool bitwiseIsEqual(const DoubleAPFloat &RHS) const;
+ APInt bitcastToAPInt() const;
+ opStatus convertFromString(StringRef, roundingMode);
+ opStatus next(bool nextDown);
+
+ opStatus convertToInteger(MutableArrayRef<integerPart> Input,
+ unsigned int Width, bool IsSigned, roundingMode RM,
+ bool *IsExact) const;
+ opStatus convertFromAPInt(const APInt &Input, bool IsSigned, roundingMode RM);
+ opStatus convertFromSignExtendedInteger(const integerPart *Input,
+ unsigned int InputSize, bool IsSigned,
+ roundingMode RM);
+ opStatus convertFromZeroExtendedInteger(const integerPart *Input,
+ unsigned int InputSize, bool IsSigned,
+ roundingMode RM);
+ unsigned int convertToHexString(char *DST, unsigned int HexDigits,
+ bool UpperCase, roundingMode RM) const;
+
+ bool isDenormal() const;
+ bool isSmallest() const;
+ bool isLargest() const;
+ bool isInteger() const;
+
+ void toString(SmallVectorImpl<char> &Str, unsigned FormatPrecision,
+ unsigned FormatMaxPadding) const;
+
+ bool getExactInverse(APFloat *inv) const;
+
+ friend int ilogb(const DoubleAPFloat &Arg);
+ friend DoubleAPFloat scalbn(DoubleAPFloat X, int Exp, roundingMode);
+ friend DoubleAPFloat frexp(const DoubleAPFloat &X, int &Exp, roundingMode);
+ friend hash_code hash_value(const DoubleAPFloat &Arg);
};
+hash_code hash_value(const DoubleAPFloat &Arg);
+
} // End detail namespace
// This is a interface class that is currently forwarding functionalities from
@@ -770,26 +785,24 @@ class APFloat : public APFloatBase {
llvm_unreachable("Unexpected semantics");
}
- void makeZero(bool Neg) { getIEEE().makeZero(Neg); }
+ void makeZero(bool Neg) { APFLOAT_DISPATCH_ON_SEMANTICS(makeZero(Neg)); }
- void makeInf(bool Neg) {
- if (usesLayout<IEEEFloat>(*U.semantics))
- return U.IEEE.makeInf(Neg);
- if (usesLayout<DoubleAPFloat>(*U.semantics))
- return U.Double.makeInf(Neg);
- llvm_unreachable("Unexpected semantics");
- }
+ void makeInf(bool Neg) { APFLOAT_DISPATCH_ON_SEMANTICS(makeInf(Neg)); }
void makeNaN(bool SNaN, bool Neg, const APInt *fill) {
- getIEEE().makeNaN(SNaN, Neg, fill);
+ APFLOAT_DISPATCH_ON_SEMANTICS(makeNaN(SNaN, Neg, fill));
}
- void makeLargest(bool Neg) { getIEEE().makeLargest(Neg); }
+ void makeLargest(bool Neg) {
+ APFLOAT_DISPATCH_ON_SEMANTICS(makeLargest(Neg));
+ }
- void makeSmallest(bool Neg) { getIEEE().makeSmallest(Neg); }
+ void makeSmallest(bool Neg) {
+ APFLOAT_DISPATCH_ON_SEMANTICS(makeSmallest(Neg));
+ }
void makeSmallestNormalized(bool Neg) {
- getIEEE().makeSmallestNormalized(Neg);
+ APFLOAT_DISPATCH_ON_SEMANTICS(makeSmallestNormalized(Neg));
}
// FIXME: This is due to clang 3.3 (or older version) always checks for the
@@ -804,7 +817,8 @@ class APFloat : public APFloatBase {
: U(std::move(F), S) {}
cmpResult compareAbsoluteValue(const APFloat &RHS) const {
- assert(&getSemantics() == &RHS.getSemantics());
+ assert(&getSemantics() == &RHS.getSemantics() &&
+ "Should only compare APFloats with the same semantics");
if (usesLayout<IEEEFloat>(getSemantics()))
return U.IEEE.compareAbsoluteValue(RHS.U.IEEE);
if (usesLayout<DoubleAPFloat>(getSemantics()))
@@ -827,13 +841,7 @@ public:
~APFloat() = default;
- bool needsCleanup() const {
- if (usesLayout<IEEEFloat>(getSemantics()))
- return U.IEEE.needsCleanup();
- if (usesLayout<DoubleAPFloat>(getSemantics()))
- return U.Double.needsCleanup();
- llvm_unreachable("Unexpected semantics");
- }
+ bool needsCleanup() const { APFLOAT_DISPATCH_ON_SEMANTICS(needsCleanup()); }
/// Factory for Positive and Negative Zero.
///
@@ -920,9 +928,13 @@ public:
/// \param isIEEE - If 128 bit number, select between PPC and IEEE
static APFloat getAllOnesValue(unsigned BitWidth, bool isIEEE = false);
- void Profile(FoldingSetNodeID &NID) const { getIEEE().Profile(NID); }
+ /// Used to insert APFloat objects, or objects that contain APFloat objects,
+ /// into FoldingSets.
+ void Profile(FoldingSetNodeID &NID) const;
opStatus add(const APFloat &RHS, roundingMode RM) {
+ assert(&getSemantics() == &RHS.getSemantics() &&
+ "Should only call on two APFloats with the same semantics");
if (usesLayout<IEEEFloat>(getSemantics()))
return U.IEEE.add(RHS.U.IEEE, RM);
if (usesLayout<DoubleAPFloat>(getSemantics()))
@@ -930,6 +942,8 @@ public:
llvm_unreachable("Unexpected semantics");
}
opStatus subtract(const APFloat &RHS, roundingMode RM) {
+ assert(&getSemantics() == &RHS.getSemantics() &&
+ "Should only call on two APFloats with the same semantics");
if (usesLayout<IEEEFloat>(getSemantics()))
return U.IEEE.subtract(RHS.U.IEEE, RM);
if (usesLayout<DoubleAPFloat>(getSemantics()))
@@ -937,95 +951,172 @@ public:
llvm_unreachable("Unexpected semantics");
}
opStatus multiply(const APFloat &RHS, roundingMode RM) {
- return getIEEE().multiply(RHS.getIEEE(), RM);
+ assert(&getSemantics() == &RHS.getSemantics() &&
+ "Should only call on two APFloats with the same semantics");
+ if (usesLayout<IEEEFloat>(getSemantics()))
+ return U.IEEE.multiply(RHS.U.IEEE, RM);
+ if (usesLayout<DoubleAPFloat>(getSemantics()))
+ return U.Double.multiply(RHS.U.Double, RM);
+ llvm_unreachable("Unexpected semantics");
}
opStatus divide(const APFloat &RHS, roundingMode RM) {
- return getIEEE().divide(RHS.getIEEE(), RM);
+ assert(&getSemantics() == &RHS.getSemantics() &&
+ "Should only call on two APFloats with the same semantics");
+ if (usesLayout<IEEEFloat>(getSemantics()))
+ return U.IEEE.divide(RHS.U.IEEE, RM);
+ if (usesLayout<DoubleAPFloat>(getSemantics()))
+ return U.Double.divide(RHS.U.Double, RM);
+ llvm_unreachable("Unexpected semantics");
}
opStatus remainder(const APFloat &RHS) {
- return getIEEE().remainder(RHS.getIEEE());
+ assert(&getSemantics() == &RHS.getSemantics() &&
+ "Should only call on two APFloats with the same semantics");
+ if (usesLayout<IEEEFloat>(getSemantics()))
+ return U.IEEE.remainder(RHS.U.IEEE);
+ if (usesLayout<DoubleAPFloat>(getSemantics()))
+ return U.Double.remainder(RHS.U.Double);
+ llvm_unreachable("Unexpected semantics");
+ }
+ opStatus mod(const APFloat &RHS) {
+ assert(&getSemantics() == &RHS.getSemantics() &&
+ "Should only call on two APFloats with the same semantics");
+ if (usesLayout<IEEEFloat>(getSemantics()))
+ return U.IEEE.mod(RHS.U.IEEE);
+ if (usesLayout<DoubleAPFloat>(getSemantics()))
+ return U.Double.mod(RHS.U.Double);
+ llvm_unreachable("Unexpected semantics");
}
- opStatus mod(const APFloat &RHS) { return getIEEE().mod(RHS.getIEEE()); }
opStatus fusedMultiplyAdd(const APFloat &Multiplicand, const APFloat &Addend,
roundingMode RM) {
- return getIEEE().fusedMultiplyAdd(Multiplicand.getIEEE(), Addend.getIEEE(),
- RM);
+ assert(&getSemantics() == &Multiplicand.getSemantics() &&
+ "Should only call on APFloats with the same semantics");
+ assert(&getSemantics() == &Addend.getSemantics() &&
+ "Should only call on APFloats with the same semantics");
+ if (usesLayout<IEEEFloat>(getSemantics()))
+ return U.IEEE.fusedMultiplyAdd(Multiplicand.U.IEEE, Addend.U.IEEE, RM);
+ if (usesLayout<DoubleAPFloat>(getSemantics()))
+ return U.Double.fusedMultiplyAdd(Multiplicand.U.Double, Addend.U.Double,
+ RM);
+ llvm_unreachable("Unexpected semantics");
}
opStatus roundToIntegral(roundingMode RM) {
- return getIEEE().roundToIntegral(RM);
+ APFLOAT_DISPATCH_ON_SEMANTICS(roundToIntegral(RM));
+ }
+
+ // TODO: bool parameters are not readable and a source of bugs.
+ // Do something.
+ opStatus next(bool nextDown) {
+ APFLOAT_DISPATCH_ON_SEMANTICS(next(nextDown));
}
- opStatus next(bool nextDown) { return getIEEE().next(nextDown); }
+ /// Add two APFloats, rounding ties to the nearest even.
+ /// No error checking.
APFloat operator+(const APFloat &RHS) const {
- return APFloat(getIEEE() + RHS.getIEEE(), getSemantics());
+ APFloat Result(*this);
+ (void)Result.add(RHS, rmNearestTiesToEven);
+ return Result;
}
+ /// Subtract two APFloats, rounding ties to the nearest even.
+ /// No error checking.
APFloat operator-(const APFloat &RHS) const {
- return APFloat(getIEEE() - RHS.getIEEE(), getSemantics());
+ APFloat Result(*this);
+ (void)Result.subtract(RHS, rmNearestTiesToEven);
+ return Result;
}
+ /// Multiply two APFloats, rounding ties to the nearest even.
+ /// No error checking.
APFloat operator*(const APFloat &RHS) const {
- return APFloat(getIEEE() * RHS.getIEEE(), getSemantics());
+ APFloat Result(*this);
+ (void)Result.multiply(RHS, rmNearestTiesToEven);
+ return Result;
}
+ /// Divide the first APFloat by the second, rounding ties to the nearest even.
+ /// No error checking.
APFloat operator/(const APFloat &RHS) const {
- return APFloat(getIEEE() / RHS.getIEEE(), getSemantics());
+ APFloat Result(*this);
+ (void)Result.divide(RHS, rmNearestTiesToEven);
+ return Result;
}
- void changeSign() { getIEEE().changeSign(); }
- void clearSign() { getIEEE().clearSign(); }
- void copySign(const APFloat &RHS) { getIEEE().copySign(RHS.getIEEE()); }
+ void changeSign() { APFLOAT_DISPATCH_ON_SEMANTICS(changeSign()); }
+ void clearSign() {
+ if (isNegative())
+ changeSign();
+ }
+ void copySign(const APFloat &RHS) {
+ if (isNegative() != RHS.isNegative())
+ changeSign();
+ }
+ /// A static helper to produce a copy of an APFloat value with its sign
+ /// copied from some other APFloat.
static APFloat copySign(APFloat Value, const APFloat &Sign) {
- return APFloat(IEEEFloat::copySign(Value.getIEEE(), Sign.getIEEE()),
- Value.getSemantics());
+ Value.copySign(Sign);
+ return Value;
}
opStatus convert(const fltSemantics &ToSemantics, roundingMode RM,
bool *losesInfo);
- opStatus convertToInteger(integerPart *Input, unsigned int Width,
- bool IsSigned, roundingMode RM,
+ opStatus convertToInteger(MutableArrayRef<integerPart> Input,
+ unsigned int Width, bool IsSigned, roundingMode RM,
bool *IsExact) const {
- return getIEEE().convertToInteger(Input, Width, IsSigned, RM, IsExact);
+ APFLOAT_DISPATCH_ON_SEMANTICS(
+ convertToInteger(Input, Width, IsSigned, RM, IsExact));
}
opStatus convertToInteger(APSInt &Result, roundingMode RM,
- bool *IsExact) const {
- return getIEEE().convertToInteger(Result, RM, IsExact);
- }
+ bool *IsExact) const;
opStatus convertFromAPInt(const APInt &Input, bool IsSigned,
roundingMode RM) {
- return getIEEE().convertFromAPInt(Input, IsSigned, RM);
+ APFLOAT_DISPATCH_ON_SEMANTICS(convertFromAPInt(Input, IsSigned, RM));
}
opStatus convertFromSignExtendedInteger(const integerPart *Input,
unsigned int InputSize, bool IsSigned,
roundingMode RM) {
- return getIEEE().convertFromSignExtendedInteger(Input, InputSize, IsSigned,
- RM);
+ APFLOAT_DISPATCH_ON_SEMANTICS(
+ convertFromSignExtendedInteger(Input, InputSize, IsSigned, RM));
}
opStatus convertFromZeroExtendedInteger(const integerPart *Input,
unsigned int InputSize, bool IsSigned,
roundingMode RM) {
- return getIEEE().convertFromZeroExtendedInteger(Input, InputSize, IsSigned,
- RM);
+ APFLOAT_DISPATCH_ON_SEMANTICS(
+ convertFromZeroExtendedInteger(Input, InputSize, IsSigned, RM));
}
opStatus convertFromString(StringRef, roundingMode);
- APInt bitcastToAPInt() const { return getIEEE().bitcastToAPInt(); }
+ APInt bitcastToAPInt() const {
+ APFLOAT_DISPATCH_ON_SEMANTICS(bitcastToAPInt());
+ }
double convertToDouble() const { return getIEEE().convertToDouble(); }
float convertToFloat() const { return getIEEE().convertToFloat(); }
bool operator==(const APFloat &) const = delete;
cmpResult compare(const APFloat &RHS) const {
- return getIEEE().compare(RHS.getIEEE());
+ assert(&getSemantics() == &RHS.getSemantics() &&
+ "Should only compare APFloats with the same semantics");
+ if (usesLayout<IEEEFloat>(getSemantics()))
+ return U.IEEE.compare(RHS.U.IEEE);
+ if (usesLayout<DoubleAPFloat>(getSemantics()))
+ return U.Double.compare(RHS.U.Double);
+ llvm_unreachable("Unexpected semantics");
}
bool bitwiseIsEqual(const APFloat &RHS) const {
- return getIEEE().bitwiseIsEqual(RHS.getIEEE());
+ if (&getSemantics() != &RHS.getSemantics())
+ return false;
+ if (usesLayout<IEEEFloat>(getSemantics()))
+ return U.IEEE.bitwiseIsEqual(RHS.U.IEEE);
+ if (usesLayout<DoubleAPFloat>(getSemantics()))
+ return U.Double.bitwiseIsEqual(RHS.U.Double);
+ llvm_unreachable("Unexpected semantics");
}
unsigned int convertToHexString(char *DST, unsigned int HexDigits,
bool UpperCase, roundingMode RM) const {
- return getIEEE().convertToHexString(DST, HexDigits, UpperCase, RM);
+ APFLOAT_DISPATCH_ON_SEMANTICS(
+ convertToHexString(DST, HexDigits, UpperCase, RM));
}
bool isZero() const { return getCategory() == fcZero; }
@@ -1033,7 +1124,7 @@ public:
bool isNaN() const { return getCategory() == fcNaN; }
bool isNegative() const { return getIEEE().isNegative(); }
- bool isDenormal() const { return getIEEE().isDenormal(); }
+ bool isDenormal() const { APFLOAT_DISPATCH_ON_SEMANTICS(isDenormal()); }
bool isSignaling() const { return getIEEE().isSignaling(); }
bool isNormal() const { return !isDenormal() && isFiniteNonZero(); }
@@ -1045,30 +1136,24 @@ public:
bool isFiniteNonZero() const { return isFinite() && !isZero(); }
bool isPosZero() const { return isZero() && !isNegative(); }
bool isNegZero() const { return isZero() && isNegative(); }
- bool isSmallest() const { return getIEEE().isSmallest(); }
- bool isLargest() const { return getIEEE().isLargest(); }
- bool isInteger() const { return getIEEE().isInteger(); }
+ bool isSmallest() const { APFLOAT_DISPATCH_ON_SEMANTICS(isSmallest()); }
+ bool isLargest() const { APFLOAT_DISPATCH_ON_SEMANTICS(isLargest()); }
+ bool isInteger() const { APFLOAT_DISPATCH_ON_SEMANTICS(isInteger()); }
APFloat &operator=(const APFloat &RHS) = default;
APFloat &operator=(APFloat &&RHS) = default;
void toString(SmallVectorImpl<char> &Str, unsigned FormatPrecision = 0,
unsigned FormatMaxPadding = 3) const {
- return getIEEE().toString(Str, FormatPrecision, FormatMaxPadding);
+ APFLOAT_DISPATCH_ON_SEMANTICS(
+ toString(Str, FormatPrecision, FormatMaxPadding));
}
void print(raw_ostream &) const;
void dump() const;
bool getExactInverse(APFloat *inv) const {
- return getIEEE().getExactInverse(inv ? &inv->getIEEE() : nullptr);
- }
-
- // This is for internal test only.
- // TODO: Remove it after the PPCDoubleDouble transition.
- const APFloat &getSecondFloat() const {
- assert(&getSemantics() == &PPCDoubleDouble());
- return U.Double.getSecond();
+ APFLOAT_DISPATCH_ON_SEMANTICS(getExactInverse(inv));
}
friend hash_code hash_value(const APFloat &Arg);
@@ -1085,22 +1170,36 @@ public:
/// xlC compiler.
hash_code hash_value(const APFloat &Arg);
inline APFloat scalbn(APFloat X, int Exp, APFloat::roundingMode RM) {
- return APFloat(scalbn(X.getIEEE(), Exp, RM), X.getSemantics());
+ if (APFloat::usesLayout<detail::IEEEFloat>(X.getSemantics()))
+ return APFloat(scalbn(X.U.IEEE, Exp, RM), X.getSemantics());
+ if (APFloat::usesLayout<detail::DoubleAPFloat>(X.getSemantics()))
+ return APFloat(scalbn(X.U.Double, Exp, RM), X.getSemantics());
+ llvm_unreachable("Unexpected semantics");
}
-/// \brief Equivalent of C standard library function.
+/// Equivalent of C standard library function.
///
/// While the C standard says Exp is an unspecified value for infinity and nan,
/// this returns INT_MAX for infinities, and INT_MIN for NaNs.
inline APFloat frexp(const APFloat &X, int &Exp, APFloat::roundingMode RM) {
- return APFloat(frexp(X.getIEEE(), Exp, RM), X.getSemantics());
+ if (APFloat::usesLayout<detail::IEEEFloat>(X.getSemantics()))
+ return APFloat(frexp(X.U.IEEE, Exp, RM), X.getSemantics());
+ if (APFloat::usesLayout<detail::DoubleAPFloat>(X.getSemantics()))
+ return APFloat(frexp(X.U.Double, Exp, RM), X.getSemantics());
+ llvm_unreachable("Unexpected semantics");
}
-/// \brief Returns the absolute value of the argument.
+/// Returns the absolute value of the argument.
inline APFloat abs(APFloat X) {
X.clearSign();
return X;
}
+/// \brief Returns the negated value of the argument.
+inline APFloat neg(APFloat X) {
+ X.changeSign();
+ return X;
+}
+
/// Implements IEEE minNum semantics. Returns the smaller of the 2 arguments if
/// both are not NaN. If either argument is a NaN, returns the other argument.
LLVM_READONLY
@@ -1125,4 +1224,5 @@ inline APFloat maxnum(const APFloat &A, const APFloat &B) {
} // namespace llvm
+#undef APFLOAT_DISPATCH_ON_SEMANTICS
#endif // LLVM_ADT_APFLOAT_H
diff --git a/include/llvm/ADT/APInt.h b/include/llvm/ADT/APInt.h
index 2c0713da256c..ab23130b137d 100644
--- a/include/llvm/ADT/APInt.h
+++ b/include/llvm/ADT/APInt.h
@@ -32,14 +32,6 @@ class raw_ostream;
template <typename T> class SmallVectorImpl;
template <typename T> class ArrayRef;
-// An unsigned host type used as a single part of a multi-part
-// bignum.
-typedef uint64_t integerPart;
-
-const unsigned int host_char_bit = 8;
-const unsigned int integerPartWidth =
- host_char_bit * static_cast<unsigned int>(sizeof(integerPart));
-
class APInt;
inline APInt operator-(APInt);
@@ -75,8 +67,18 @@ inline APInt operator-(APInt);
/// uses in its IR. This simplifies its use for LLVM.
///
class LLVM_NODISCARD APInt {
- unsigned BitWidth; ///< The number of bits in this APInt.
+public:
+ typedef uint64_t WordType;
+ /// This enum is used to hold the constants we needed for APInt.
+ enum : unsigned {
+ /// Byte size of a word.
+ APINT_WORD_SIZE = sizeof(WordType),
+ /// Bits in a word.
+ APINT_BITS_PER_WORD = APINT_WORD_SIZE * CHAR_BIT
+ };
+
+private:
/// This union is used to store the integer value. When the
/// integer bit-width <= 64, it uses VAL, otherwise it uses pVal.
union {
@@ -84,14 +86,7 @@ class LLVM_NODISCARD APInt {
uint64_t *pVal; ///< Used to store the >64 bits integer value.
};
- /// This enum is used to hold the constants we needed for APInt.
- enum {
- /// Bits in a word
- APINT_BITS_PER_WORD =
- static_cast<unsigned int>(sizeof(uint64_t)) * CHAR_BIT,
- /// Byte size of a word
- APINT_WORD_SIZE = static_cast<unsigned int>(sizeof(uint64_t))
- };
+ unsigned BitWidth; ///< The number of bits in this APInt.
friend struct DenseMapAPIntKeyInfo;
@@ -99,7 +94,7 @@ class LLVM_NODISCARD APInt {
///
/// This constructor is used only internally for speed of construction of
/// temporaries. It is unsafe for general use so it is not public.
- APInt(uint64_t *val, unsigned bits) : BitWidth(bits), pVal(val) {}
+ APInt(uint64_t *val, unsigned bits) : pVal(val), BitWidth(bits) {}
/// \brief Determine if this APInt just has one word to store value.
///
@@ -147,7 +142,7 @@ class LLVM_NODISCARD APInt {
return *this;
// Mask out the high bits.
- uint64_t mask = ~uint64_t(0ULL) >> (APINT_BITS_PER_WORD - wordBits);
+ uint64_t mask = UINT64_MAX >> (APINT_BITS_PER_WORD - wordBits);
if (isSingleWord())
VAL &= mask;
else
@@ -196,32 +191,38 @@ class LLVM_NODISCARD APInt {
/// out-of-line slow case for shl
APInt shlSlowCase(unsigned shiftAmt) const;
- /// out-of-line slow case for operator&
- APInt AndSlowCase(const APInt &RHS) const;
-
- /// out-of-line slow case for operator|
- APInt OrSlowCase(const APInt &RHS) const;
-
- /// out-of-line slow case for operator^
- APInt XorSlowCase(const APInt &RHS) const;
-
/// out-of-line slow case for operator=
APInt &AssignSlowCase(const APInt &RHS);
/// out-of-line slow case for operator==
- bool EqualSlowCase(const APInt &RHS) const;
+ bool EqualSlowCase(const APInt &RHS) const LLVM_READONLY;
/// out-of-line slow case for operator==
- bool EqualSlowCase(uint64_t Val) const;
+ bool EqualSlowCase(uint64_t Val) const LLVM_READONLY;
/// out-of-line slow case for countLeadingZeros
- unsigned countLeadingZerosSlowCase() const;
+ unsigned countLeadingZerosSlowCase() const LLVM_READONLY;
/// out-of-line slow case for countTrailingOnes
- unsigned countTrailingOnesSlowCase() const;
+ unsigned countTrailingOnesSlowCase() const LLVM_READONLY;
/// out-of-line slow case for countPopulation
- unsigned countPopulationSlowCase() const;
+ unsigned countPopulationSlowCase() const LLVM_READONLY;
+
+ /// out-of-line slow case for setBits.
+ void setBitsSlowCase(unsigned loBit, unsigned hiBit);
+
+ /// out-of-line slow case for flipAllBits.
+ void flipAllBitsSlowCase();
+
+ /// out-of-line slow case for operator&=.
+ APInt& AndAssignSlowCase(const APInt& RHS);
+
+ /// out-of-line slow case for operator|=.
+ APInt& OrAssignSlowCase(const APInt& RHS);
+
+ /// out-of-line slow case for operator^=.
+ APInt& XorAssignSlowCase(const APInt& RHS);
public:
/// \name Constructors
@@ -238,13 +239,14 @@ public:
/// \param val the initial value of the APInt
/// \param isSigned how to treat signedness of val
APInt(unsigned numBits, uint64_t val, bool isSigned = false)
- : BitWidth(numBits), VAL(0) {
+ : BitWidth(numBits) {
assert(BitWidth && "bitwidth too small");
- if (isSingleWord())
+ if (isSingleWord()) {
VAL = val;
- else
+ clearUnusedBits();
+ } else {
initSlowCase(val, isSigned);
- clearUnusedBits();
+ }
}
/// \brief Construct an APInt of numBits width, initialized as bigVal[].
@@ -280,7 +282,7 @@ public:
/// Simply makes *this a copy of that.
/// @brief Copy Constructor.
- APInt(const APInt &that) : BitWidth(that.BitWidth), VAL(0) {
+ APInt(const APInt &that) : BitWidth(that.BitWidth) {
if (isSingleWord())
VAL = that.VAL;
else
@@ -288,7 +290,7 @@ public:
}
/// \brief Move Constructor.
- APInt(APInt &&that) : BitWidth(that.BitWidth), VAL(that.VAL) {
+ APInt(APInt &&that) : VAL(that.VAL), BitWidth(that.BitWidth) {
that.BitWidth = 0;
}
@@ -303,7 +305,7 @@ public:
///
/// This is useful for object deserialization (pair this with the static
/// method Read).
- explicit APInt() : BitWidth(1), VAL(0) {}
+ explicit APInt() : VAL(0), BitWidth(1) {}
/// \brief Returns whether this instance allocated memory.
bool needsCleanup() const { return !isSingleWord(); }
@@ -341,7 +343,7 @@ public:
/// This checks to see if the value has all bits of the APInt are set or not.
bool isAllOnesValue() const {
if (isSingleWord())
- return VAL == ~integerPart(0) >> (APINT_BITS_PER_WORD - BitWidth);
+ return VAL == UINT64_MAX >> (APINT_BITS_PER_WORD - BitWidth);
return countPopulationSlowCase() == BitWidth;
}
@@ -406,7 +408,7 @@ public:
/// If this value is smaller than the specified limit, return it, otherwise
/// return the limit value. This causes the value to saturate to the limit.
- uint64_t getLimitedValue(uint64_t Limit = ~0ULL) const {
+ uint64_t getLimitedValue(uint64_t Limit = UINT64_MAX) const {
return (getActiveBits() > 64 || getZExtValue() > Limit) ? Limit
: getZExtValue();
}
@@ -418,6 +420,36 @@ public:
/// width without remainder.
bool isSplat(unsigned SplatSizeInBits) const;
+ /// \returns true if this APInt value is a sequence of \param numBits ones
+ /// starting at the least significant bit with the remainder zero.
+ bool isMask(unsigned numBits) const {
+ assert(numBits != 0 && "numBits must be non-zero");
+ assert(numBits <= BitWidth && "numBits out of range");
+ if (isSingleWord())
+ return VAL == (UINT64_MAX >> (APINT_BITS_PER_WORD - numBits));
+ unsigned Ones = countTrailingOnes();
+ return (numBits == Ones) && ((Ones + countLeadingZeros()) == BitWidth);
+ }
+
+ /// \returns true if this APInt is a non-empty sequence of ones starting at
+ /// the least significant bit with the remainder zero.
+ /// Ex. isMask(0x0000FFFFU) == true.
+ bool isMask() const {
+ if (isSingleWord())
+ return isMask_64(VAL);
+ unsigned Ones = countTrailingOnes();
+ return (Ones > 0) && ((Ones + countLeadingZeros()) == BitWidth);
+ }
+
+ /// \brief Return true if this APInt value contains a sequence of ones with
+ /// the remainder zero.
+ bool isShiftedMask() const {
+ if (isSingleWord())
+ return isShiftedMask_64(VAL);
+ unsigned Ones = countPopulation();
+ return (Ones + countTrailingZeros() + countLeadingZeros()) == BitWidth;
+ }
+
/// @}
/// \name Value Generators
/// @{
@@ -501,12 +533,26 @@ public:
///
/// \returns An APInt value with the requested bits set.
static APInt getBitsSet(unsigned numBits, unsigned loBit, unsigned hiBit) {
- assert(hiBit <= numBits && "hiBit out of range");
- assert(loBit < numBits && "loBit out of range");
- if (hiBit < loBit)
- return getLowBitsSet(numBits, hiBit) |
- getHighBitsSet(numBits, numBits - loBit);
- return getLowBitsSet(numBits, hiBit - loBit).shl(loBit);
+ APInt Res(numBits, 0);
+ Res.setBits(loBit, hiBit);
+ return Res;
+ }
+
+ /// \brief Get a value with upper bits starting at loBit set.
+ ///
+ /// Constructs an APInt value that has a contiguous range of bits set. The
+ /// bits from loBit (inclusive) to numBits (exclusive) will be set. All other
+ /// bits will be zero. For example, with parameters(32, 12) you would get
+ /// 0xFFFFF000.
+ ///
+ /// \param numBits the intended bit width of the result
+ /// \param loBit the index of the lowest bit to set.
+ ///
+ /// \returns An APInt value with the requested bits set.
+ static APInt getBitsSetFrom(unsigned numBits, unsigned loBit) {
+ APInt Res(numBits, 0);
+ Res.setBitsFrom(loBit);
+ return Res;
}
/// \brief Get a value with high bits set
@@ -516,15 +562,9 @@ public:
/// \param numBits the bitwidth of the result
/// \param hiBitsSet the number of high-order bits set in the result.
static APInt getHighBitsSet(unsigned numBits, unsigned hiBitsSet) {
- assert(hiBitsSet <= numBits && "Too many bits to set!");
- // Handle a degenerate case, to avoid shifting by word size
- if (hiBitsSet == 0)
- return APInt(numBits, 0);
- unsigned shiftAmt = numBits - hiBitsSet;
- // For small values, return quickly
- if (numBits <= APINT_BITS_PER_WORD)
- return APInt(numBits, ~0ULL << shiftAmt);
- return getAllOnesValue(numBits).shl(shiftAmt);
+ APInt Res(numBits, 0);
+ Res.setHighBits(hiBitsSet);
+ return Res;
}
/// \brief Get a value with low bits set
@@ -534,16 +574,9 @@ public:
/// \param numBits the bitwidth of the result
/// \param loBitsSet the number of low-order bits set in the result.
static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet) {
- assert(loBitsSet <= numBits && "Too many bits to set!");
- // Handle a degenerate case, to avoid shifting by word size
- if (loBitsSet == 0)
- return APInt(numBits, 0);
- if (loBitsSet == APINT_BITS_PER_WORD)
- return APInt(numBits, UINT64_MAX);
- // For small values, return quickly.
- if (loBitsSet <= APINT_BITS_PER_WORD)
- return APInt(numBits, UINT64_MAX >> (APINT_BITS_PER_WORD - loBitsSet));
- return getAllOnesValue(numBits).lshr(numBits - loBitsSet);
+ APInt Res(numBits, 0);
+ Res.setLowBits(loBitsSet);
+ return Res;
}
/// \brief Return a value containing V broadcasted over NewLen bits.
@@ -587,7 +620,9 @@ public:
/// \brief Postfix increment operator.
///
- /// \returns a new APInt value representing *this incremented by one
+ /// Increments *this by 1.
+ ///
+ /// \returns a new APInt value representing the original value of *this.
const APInt operator++(int) {
APInt API(*this);
++(*this);
@@ -601,7 +636,9 @@ public:
/// \brief Postfix decrement operator.
///
- /// \returns a new APInt representing *this decremented by one.
+ /// Decrements *this by 1.
+ ///
+ /// \returns a new APInt value representing the original value of *this.
const APInt operator--(int) {
APInt API(*this);
--(*this);
@@ -613,30 +650,13 @@ public:
/// \returns *this decremented by one.
APInt &operator--();
- /// \brief Unary bitwise complement operator.
- ///
- /// Performs a bitwise complement operation on this APInt.
- ///
- /// \returns an APInt that is the bitwise complement of *this
- APInt operator~() const {
- APInt Result(*this);
- Result.flipAllBits();
- return Result;
- }
-
/// \brief Logical negation operator.
///
/// Performs logical negation operation on this APInt.
///
/// \returns true if *this is zero, false otherwise.
bool operator!() const {
- if (isSingleWord())
- return !VAL;
-
- for (unsigned i = 0; i != getNumWords(); ++i)
- if (pVal[i])
- return false;
- return true;
+ return *this == 0;
}
/// @}
@@ -688,7 +708,16 @@ public:
/// than 64, the value is zero filled in the unspecified high order bits.
///
/// \returns *this after assignment of RHS value.
- APInt &operator=(uint64_t RHS);
+ APInt &operator=(uint64_t RHS) {
+ if (isSingleWord()) {
+ VAL = RHS;
+ clearUnusedBits();
+ } else {
+ pVal[0] = RHS;
+ memset(pVal+1, 0, (getNumWords() - 1) * APINT_WORD_SIZE);
+ }
+ return *this;
+ }
/// \brief Bitwise AND assignment operator.
///
@@ -696,7 +725,29 @@ public:
/// assigned to *this.
///
/// \returns *this after ANDing with RHS.
- APInt &operator&=(const APInt &RHS);
+ APInt &operator&=(const APInt &RHS) {
+ assert(BitWidth == RHS.BitWidth && "Bit widths must be the same");
+ if (isSingleWord()) {
+ VAL &= RHS.VAL;
+ return *this;
+ }
+ return AndAssignSlowCase(RHS);
+ }
+
+ /// \brief Bitwise AND assignment operator.
+ ///
+ /// Performs a bitwise AND operation on this APInt and RHS. RHS is
+ /// logically zero-extended or truncated to match the bit-width of
+ /// the LHS.
+ APInt &operator&=(uint64_t RHS) {
+ if (isSingleWord()) {
+ VAL &= RHS;
+ return *this;
+ }
+ pVal[0] &= RHS;
+ memset(pVal+1, 0, (getNumWords() - 1) * APINT_WORD_SIZE);
+ return *this;
+ }
/// \brief Bitwise OR assignment operator.
///
@@ -704,7 +755,14 @@ public:
/// assigned *this;
///
/// \returns *this after ORing with RHS.
- APInt &operator|=(const APInt &RHS);
+ APInt &operator|=(const APInt &RHS) {
+ assert(BitWidth == RHS.BitWidth && "Bit widths must be the same");
+ if (isSingleWord()) {
+ VAL |= RHS.VAL;
+ return *this;
+ }
+ return OrAssignSlowCase(RHS);
+ }
/// \brief Bitwise OR assignment operator.
///
@@ -727,7 +785,29 @@ public:
/// assigned to *this.
///
/// \returns *this after XORing with RHS.
- APInt &operator^=(const APInt &RHS);
+ APInt &operator^=(const APInt &RHS) {
+ assert(BitWidth == RHS.BitWidth && "Bit widths must be the same");
+ if (isSingleWord()) {
+ VAL ^= RHS.VAL;
+ return *this;
+ }
+ return XorAssignSlowCase(RHS);
+ }
+
+ /// \brief Bitwise XOR assignment operator.
+ ///
+ /// Performs a bitwise XOR operation on this APInt and RHS. RHS is
+ /// logically zero-extended or truncated to match the bit-width of
+ /// the LHS.
+ APInt &operator^=(uint64_t RHS) {
+ if (isSingleWord()) {
+ VAL ^= RHS;
+ clearUnusedBits();
+ } else {
+ pVal[0] ^= RHS;
+ }
+ return *this;
+ }
/// \brief Multiplication assignment operator.
///
@@ -766,59 +846,6 @@ public:
/// \name Binary Operators
/// @{
- /// \brief Bitwise AND operator.
- ///
- /// Performs a bitwise AND operation on *this and RHS.
- ///
- /// \returns An APInt value representing the bitwise AND of *this and RHS.
- APInt operator&(const APInt &RHS) const {
- assert(BitWidth == RHS.BitWidth && "Bit widths must be the same");
- if (isSingleWord())
- return APInt(getBitWidth(), VAL & RHS.VAL);
- return AndSlowCase(RHS);
- }
- APInt And(const APInt &RHS) const { return this->operator&(RHS); }
-
- /// \brief Bitwise OR operator.
- ///
- /// Performs a bitwise OR operation on *this and RHS.
- ///
- /// \returns An APInt value representing the bitwise OR of *this and RHS.
- APInt operator|(const APInt &RHS) const {
- assert(BitWidth == RHS.BitWidth && "Bit widths must be the same");
- if (isSingleWord())
- return APInt(getBitWidth(), VAL | RHS.VAL);
- return OrSlowCase(RHS);
- }
-
- /// \brief Bitwise OR function.
- ///
- /// Performs a bitwise or on *this and RHS. This is implemented by simply
- /// calling operator|.
- ///
- /// \returns An APInt value representing the bitwise OR of *this and RHS.
- APInt Or(const APInt &RHS) const { return this->operator|(RHS); }
-
- /// \brief Bitwise XOR operator.
- ///
- /// Performs a bitwise XOR operation on *this and RHS.
- ///
- /// \returns An APInt value representing the bitwise XOR of *this and RHS.
- APInt operator^(const APInt &RHS) const {
- assert(BitWidth == RHS.BitWidth && "Bit widths must be the same");
- if (isSingleWord())
- return APInt(BitWidth, VAL ^ RHS.VAL);
- return XorSlowCase(RHS);
- }
-
- /// \brief Bitwise XOR function.
- ///
- /// Performs a bitwise XOR operation on *this and RHS. This is implemented
- /// through the usage of operator^.
- ///
- /// \returns An APInt value representing the bitwise XOR of *this and RHS.
- APInt Xor(const APInt &RHS) const { return this->operator^(RHS); }
-
/// \brief Multiplication operator.
///
/// Multiplies this APInt by RHS and returns the result.
@@ -842,7 +869,14 @@ public:
/// \brief Logical right-shift function.
///
/// Logical right-shift this APInt by shiftAmt.
- APInt lshr(unsigned shiftAmt) const;
+ APInt lshr(unsigned shiftAmt) const {
+ APInt R(*this);
+ R.lshrInPlace(shiftAmt);
+ return R;
+ }
+
+ /// Logical right-shift this APInt by shiftAmt in place.
+ void lshrInPlace(unsigned shiftAmt);
/// \brief Left-shift function.
///
@@ -1012,7 +1046,7 @@ public:
/// the validity of the less-than relationship.
///
/// \returns true if *this < RHS when both are considered unsigned.
- bool ult(const APInt &RHS) const;
+ bool ult(const APInt &RHS) const LLVM_READONLY;
/// \brief Unsigned less than comparison
///
@@ -1030,7 +1064,7 @@ public:
/// validity of the less-than relationship.
///
/// \returns true if *this < RHS when both are considered signed.
- bool slt(const APInt &RHS) const;
+ bool slt(const APInt &RHS) const LLVM_READONLY;
/// \brief Signed less than comparison
///
@@ -1144,7 +1178,11 @@ public:
/// This operation tests if there are any pairs of corresponding bits
/// between this APInt and RHS that are both set.
- bool intersects(const APInt &RHS) const { return (*this & RHS) != 0; }
+ bool intersects(const APInt &RHS) const {
+ APInt temp(*this);
+ temp &= RHS;
+ return temp != 0;
+ }
/// @}
/// \name Resizing Operators
@@ -1203,11 +1241,9 @@ public:
void setAllBits() {
if (isSingleWord())
VAL = UINT64_MAX;
- else {
+ else
// Set all the bits in all the words.
- for (unsigned i = 0; i < getNumWords(); ++i)
- pVal[i] = UINT64_MAX;
- }
+ memset(pVal, -1, getNumWords() * APINT_WORD_SIZE);
// Clear the unused ones
clearUnusedBits();
}
@@ -1217,6 +1253,49 @@ public:
/// Set the given bit to 1 whose position is given as "bitPosition".
void setBit(unsigned bitPosition);
+ /// Set the sign bit to 1.
+ void setSignBit() {
+ setBit(BitWidth - 1);
+ }
+
+ /// Set the bits from loBit (inclusive) to hiBit (exclusive) to 1.
+ void setBits(unsigned loBit, unsigned hiBit) {
+ assert(hiBit <= BitWidth && "hiBit out of range");
+ assert(loBit <= BitWidth && "loBit out of range");
+ if (loBit == hiBit)
+ return;
+ if (loBit > hiBit) {
+ setLowBits(hiBit);
+ setHighBits(BitWidth - loBit);
+ return;
+ }
+ if (loBit < APINT_BITS_PER_WORD && hiBit <= APINT_BITS_PER_WORD) {
+ uint64_t mask = UINT64_MAX >> (APINT_BITS_PER_WORD - (hiBit - loBit));
+ mask <<= loBit;
+ if (isSingleWord())
+ VAL |= mask;
+ else
+ pVal[0] |= mask;
+ } else {
+ setBitsSlowCase(loBit, hiBit);
+ }
+ }
+
+ /// Set the top bits starting from loBit.
+ void setBitsFrom(unsigned loBit) {
+ return setBits(loBit, BitWidth);
+ }
+
+ /// Set the bottom loBits bits.
+ void setLowBits(unsigned loBits) {
+ return setBits(0, loBits);
+ }
+
+ /// Set the top hiBits bits.
+ void setHighBits(unsigned hiBits) {
+ return setBits(BitWidth - hiBits, BitWidth);
+ }
+
/// \brief Set every bit to 0.
void clearAllBits() {
if (isSingleWord())
@@ -1232,13 +1311,12 @@ public:
/// \brief Toggle every bit to its opposite value.
void flipAllBits() {
- if (isSingleWord())
+ if (isSingleWord()) {
VAL ^= UINT64_MAX;
- else {
- for (unsigned i = 0; i < getNumWords(); ++i)
- pVal[i] ^= UINT64_MAX;
+ clearUnusedBits();
+ } else {
+ flipAllBitsSlowCase();
}
- clearUnusedBits();
}
/// \brief Toggles a given bit to its opposite value.
@@ -1247,6 +1325,12 @@ public:
/// as "bitPosition".
void flipBit(unsigned bitPosition);
+ /// Insert the bits from a smaller APInt starting at bitPosition.
+ void insertBits(const APInt &SubBits, unsigned bitPosition);
+
+ /// Return an APInt with the extracted bits [bitPosition,bitPosition+numBits).
+ APInt extractBits(unsigned numBits, unsigned bitPosition) const;
+
/// @}
/// \name Value Characterization Functions
/// @{
@@ -1356,7 +1440,7 @@ public:
///
/// \returns 0 if the high order bit is not set, otherwise returns the number
/// of 1 bits from the most significant to the least
- unsigned countLeadingOnes() const;
+ unsigned countLeadingOnes() const LLVM_READONLY;
/// Computes the number of leading bits of this APInt that are equal to its
/// sign bit.
@@ -1372,7 +1456,7 @@ public:
///
/// \returns BitWidth if the value is zero, otherwise returns the number of
/// zeros from the least significant bit to the first one bit.
- unsigned countTrailingZeros() const;
+ unsigned countTrailingZeros() const LLVM_READONLY;
/// \brief Count the number of trailing one bits.
///
@@ -1589,46 +1673,50 @@ public:
/// Sets the least significant part of a bignum to the input value, and zeroes
/// out higher parts.
- static void tcSet(integerPart *, integerPart, unsigned int);
+ static void tcSet(WordType *, WordType, unsigned);
/// Assign one bignum to another.
- static void tcAssign(integerPart *, const integerPart *, unsigned int);
+ static void tcAssign(WordType *, const WordType *, unsigned);
/// Returns true if a bignum is zero, false otherwise.
- static bool tcIsZero(const integerPart *, unsigned int);
+ static bool tcIsZero(const WordType *, unsigned);
/// Extract the given bit of a bignum; returns 0 or 1. Zero-based.
- static int tcExtractBit(const integerPart *, unsigned int bit);
+ static int tcExtractBit(const WordType *, unsigned bit);
/// Copy the bit vector of width srcBITS from SRC, starting at bit srcLSB, to
/// DST, of dstCOUNT parts, such that the bit srcLSB becomes the least
/// significant bit of DST. All high bits above srcBITS in DST are
/// zero-filled.
- static void tcExtract(integerPart *, unsigned int dstCount,
- const integerPart *, unsigned int srcBits,
- unsigned int srcLSB);
+ static void tcExtract(WordType *, unsigned dstCount,
+ const WordType *, unsigned srcBits,
+ unsigned srcLSB);
/// Set the given bit of a bignum. Zero-based.
- static void tcSetBit(integerPart *, unsigned int bit);
+ static void tcSetBit(WordType *, unsigned bit);
/// Clear the given bit of a bignum. Zero-based.
- static void tcClearBit(integerPart *, unsigned int bit);
+ static void tcClearBit(WordType *, unsigned bit);
/// Returns the bit number of the least or most significant set bit of a
/// number. If the input number has no bits set -1U is returned.
- static unsigned int tcLSB(const integerPart *, unsigned int);
- static unsigned int tcMSB(const integerPart *parts, unsigned int n);
+ static unsigned tcLSB(const WordType *, unsigned n);
+ static unsigned tcMSB(const WordType *parts, unsigned n);
/// Negate a bignum in-place.
- static void tcNegate(integerPart *, unsigned int);
+ static void tcNegate(WordType *, unsigned);
/// DST += RHS + CARRY where CARRY is zero or one. Returns the carry flag.
- static integerPart tcAdd(integerPart *, const integerPart *,
- integerPart carry, unsigned);
+ static WordType tcAdd(WordType *, const WordType *,
+ WordType carry, unsigned);
+ /// DST += RHS. Returns the carry flag.
+ static WordType tcAddPart(WordType *, WordType, unsigned);
/// DST -= RHS + CARRY where CARRY is zero or one. Returns the carry flag.
- static integerPart tcSubtract(integerPart *, const integerPart *,
- integerPart carry, unsigned);
+ static WordType tcSubtract(WordType *, const WordType *,
+ WordType carry, unsigned);
+ /// DST -= RHS. Returns the carry flag.
+ static WordType tcSubtractPart(WordType *, WordType, unsigned);
/// DST += SRC * MULTIPLIER + PART if add is true
/// DST = SRC * MULTIPLIER + PART if add is false
@@ -1640,23 +1728,23 @@ public:
/// Otherwise DST is filled with the least significant DSTPARTS parts of the
/// result, and if all of the omitted higher parts were zero return zero,
/// otherwise overflow occurred and return one.
- static int tcMultiplyPart(integerPart *dst, const integerPart *src,
- integerPart multiplier, integerPart carry,
- unsigned int srcParts, unsigned int dstParts,
+ static int tcMultiplyPart(WordType *dst, const WordType *src,
+ WordType multiplier, WordType carry,
+ unsigned srcParts, unsigned dstParts,
bool add);
/// DST = LHS * RHS, where DST has the same width as the operands and is
/// filled with the least significant parts of the result. Returns one if
/// overflow occurred, otherwise zero. DST must be disjoint from both
/// operands.
- static int tcMultiply(integerPart *, const integerPart *, const integerPart *,
+ static int tcMultiply(WordType *, const WordType *, const WordType *,
unsigned);
/// DST = LHS * RHS, where DST has width the sum of the widths of the
/// operands. No overflow occurs. DST must be disjoint from both
/// operands. Returns the number of parts required to hold the result.
- static unsigned int tcFullMultiply(integerPart *, const integerPart *,
- const integerPart *, unsigned, unsigned);
+ static unsigned tcFullMultiply(WordType *, const WordType *,
+ const WordType *, unsigned, unsigned);
/// If RHS is zero LHS and REMAINDER are left unchanged, return one.
/// Otherwise set LHS to LHS / RHS with the fractional part discarded, set
@@ -1667,38 +1755,39 @@ public:
/// SCRATCH is a bignum of the same size as the operands and result for use by
/// the routine; its contents need not be initialized and are destroyed. LHS,
/// REMAINDER and SCRATCH must be distinct.
- static int tcDivide(integerPart *lhs, const integerPart *rhs,
- integerPart *remainder, integerPart *scratch,
- unsigned int parts);
+ static int tcDivide(WordType *lhs, const WordType *rhs,
+ WordType *remainder, WordType *scratch,
+ unsigned parts);
/// Shift a bignum left COUNT bits. Shifted in bits are zero. There are no
/// restrictions on COUNT.
- static void tcShiftLeft(integerPart *, unsigned int parts,
- unsigned int count);
+ static void tcShiftLeft(WordType *, unsigned parts, unsigned count);
/// Shift a bignum right COUNT bits. Shifted in bits are zero. There are no
/// restrictions on COUNT.
- static void tcShiftRight(integerPart *, unsigned int parts,
- unsigned int count);
+ static void tcShiftRight(WordType *, unsigned parts, unsigned count);
/// The obvious AND, OR and XOR and complement operations.
- static void tcAnd(integerPart *, const integerPart *, unsigned int);
- static void tcOr(integerPart *, const integerPart *, unsigned int);
- static void tcXor(integerPart *, const integerPart *, unsigned int);
- static void tcComplement(integerPart *, unsigned int);
+ static void tcAnd(WordType *, const WordType *, unsigned);
+ static void tcOr(WordType *, const WordType *, unsigned);
+ static void tcXor(WordType *, const WordType *, unsigned);
+ static void tcComplement(WordType *, unsigned);
/// Comparison (unsigned) of two bignums.
- static int tcCompare(const integerPart *, const integerPart *, unsigned int);
+ static int tcCompare(const WordType *, const WordType *, unsigned);
/// Increment a bignum in-place. Return the carry flag.
- static integerPart tcIncrement(integerPart *, unsigned int);
+ static WordType tcIncrement(WordType *dst, unsigned parts) {
+ return tcAddPart(dst, 1, parts);
+ }
/// Decrement a bignum in-place. Return the borrow flag.
- static integerPart tcDecrement(integerPart *, unsigned int);
+ static WordType tcDecrement(WordType *dst, unsigned parts) {
+ return tcSubtractPart(dst, 1, parts);
+ }
/// Set the least significant BITS and clear the rest.
- static void tcSetLeastSignificantBits(integerPart *, unsigned int,
- unsigned int bits);
+ static void tcSetLeastSignificantBits(WordType *, unsigned, unsigned bits);
/// \brief debug method
void dump() const;
@@ -1723,6 +1812,74 @@ inline bool operator==(uint64_t V1, const APInt &V2) { return V2 == V1; }
inline bool operator!=(uint64_t V1, const APInt &V2) { return V2 != V1; }
+/// \brief Unary bitwise complement operator.
+///
+/// \returns an APInt that is the bitwise complement of \p v.
+inline APInt operator~(APInt v) {
+ v.flipAllBits();
+ return v;
+}
+
+inline APInt operator&(APInt a, const APInt &b) {
+ a &= b;
+ return a;
+}
+
+inline APInt operator&(const APInt &a, APInt &&b) {
+ b &= a;
+ return std::move(b);
+}
+
+inline APInt operator&(APInt a, uint64_t RHS) {
+ a &= RHS;
+ return a;
+}
+
+inline APInt operator&(uint64_t LHS, APInt b) {
+ b &= LHS;
+ return b;
+}
+
+inline APInt operator|(APInt a, const APInt &b) {
+ a |= b;
+ return a;
+}
+
+inline APInt operator|(const APInt &a, APInt &&b) {
+ b |= a;
+ return std::move(b);
+}
+
+inline APInt operator|(APInt a, uint64_t RHS) {
+ a |= RHS;
+ return a;
+}
+
+inline APInt operator|(uint64_t LHS, APInt b) {
+ b |= LHS;
+ return b;
+}
+
+inline APInt operator^(APInt a, const APInt &b) {
+ a ^= b;
+ return a;
+}
+
+inline APInt operator^(const APInt &a, APInt &&b) {
+ b ^= a;
+ return std::move(b);
+}
+
+inline APInt operator^(APInt a, uint64_t RHS) {
+ a ^= RHS;
+ return a;
+}
+
+inline APInt operator^(uint64_t LHS, APInt b) {
+ b ^= LHS;
+ return b;
+}
+
inline raw_ostream &operator<<(raw_ostream &OS, const APInt &I) {
I.print(OS, true);
return OS;
@@ -1799,47 +1956,13 @@ inline const APInt &umax(const APInt &A, const APInt &B) {
return A.ugt(B) ? A : B;
}
-/// \brief Check if the specified APInt has a N-bits unsigned integer value.
-inline bool isIntN(unsigned N, const APInt &APIVal) { return APIVal.isIntN(N); }
-
-/// \brief Check if the specified APInt has a N-bits signed integer value.
-inline bool isSignedIntN(unsigned N, const APInt &APIVal) {
- return APIVal.isSignedIntN(N);
-}
-
-/// \returns true if the argument APInt value is a sequence of ones starting at
-/// the least significant bit with the remainder zero.
-inline bool isMask(unsigned numBits, const APInt &APIVal) {
- return numBits <= APIVal.getBitWidth() &&
- APIVal == APInt::getLowBitsSet(APIVal.getBitWidth(), numBits);
-}
-
-/// \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(0x0000FFFFU) == true.
-inline bool isMask(const APInt &Value) {
- return (Value != 0) && ((Value + 1) & Value) == 0;
-}
-
-/// \brief Return true if the argument APInt value contains a sequence of ones
-/// with the remainder zero.
-inline bool isShiftedMask(unsigned numBits, const APInt &APIVal) {
- return isMask(numBits, (APIVal - APInt(numBits, 1)) | APIVal);
-}
-
-/// \brief Returns a byte-swapped representation of the specified APInt Value.
-inline APInt byteSwap(const APInt &APIVal) { return APIVal.byteSwap(); }
-
-/// \brief Returns the floor log base 2 of the specified APInt value.
-inline unsigned logBase2(const APInt &APIVal) { return APIVal.logBase2(); }
-
-/// \brief Compute GCD of two APInt values.
+/// \brief Compute GCD of two unsigned APInt values.
///
/// This function returns the greatest common divisor of the two APInt values
/// using Euclid's algorithm.
///
-/// \returns the greatest common divisor of Val1 and Val2
-APInt GreatestCommonDivisor(const APInt &Val1, const APInt &Val2);
+/// \returns the greatest common divisor of A and B.
+APInt GreatestCommonDivisor(APInt A, APInt B);
/// \brief Converts the given APInt to a double value.
///
@@ -1879,83 +2002,6 @@ inline APInt RoundFloatToAPInt(float Float, unsigned width) {
return RoundDoubleToAPInt(double(Float), width);
}
-/// \brief Arithmetic right-shift function.
-///
-/// Arithmetic right-shift the APInt by shiftAmt.
-inline APInt ashr(const APInt &LHS, unsigned shiftAmt) {
- return LHS.ashr(shiftAmt);
-}
-
-/// \brief Logical right-shift function.
-///
-/// Logical right-shift the APInt by shiftAmt.
-inline APInt lshr(const APInt &LHS, unsigned shiftAmt) {
- return LHS.lshr(shiftAmt);
-}
-
-/// \brief Left-shift function.
-///
-/// Left-shift the APInt by shiftAmt.
-inline APInt shl(const APInt &LHS, unsigned shiftAmt) {
- return LHS.shl(shiftAmt);
-}
-
-/// \brief Signed division function for APInt.
-///
-/// Signed divide APInt LHS by APInt RHS.
-inline APInt sdiv(const APInt &LHS, const APInt &RHS) { return LHS.sdiv(RHS); }
-
-/// \brief Unsigned division function for APInt.
-///
-/// Unsigned divide APInt LHS by APInt RHS.
-inline APInt udiv(const APInt &LHS, const APInt &RHS) { return LHS.udiv(RHS); }
-
-/// \brief Function for signed remainder operation.
-///
-/// Signed remainder operation on APInt.
-inline APInt srem(const APInt &LHS, const APInt &RHS) { return LHS.srem(RHS); }
-
-/// \brief Function for unsigned remainder operation.
-///
-/// Unsigned remainder operation on APInt.
-inline APInt urem(const APInt &LHS, const APInt &RHS) { return LHS.urem(RHS); }
-
-/// \brief Function for multiplication operation.
-///
-/// Performs multiplication on APInt values.
-inline APInt mul(const APInt &LHS, const APInt &RHS) { return LHS * RHS; }
-
-/// \brief Function for addition operation.
-///
-/// Performs addition on APInt values.
-inline APInt add(const APInt &LHS, const APInt &RHS) { return LHS + RHS; }
-
-/// \brief Function for subtraction operation.
-///
-/// Performs subtraction on APInt values.
-inline APInt sub(const APInt &LHS, const APInt &RHS) { return LHS - RHS; }
-
-/// \brief Bitwise AND function for APInt.
-///
-/// Performs bitwise AND operation on APInt LHS and
-/// APInt RHS.
-inline APInt And(const APInt &LHS, const APInt &RHS) { return LHS & RHS; }
-
-/// \brief Bitwise OR function for APInt.
-///
-/// Performs bitwise OR operation on APInt LHS and APInt RHS.
-inline APInt Or(const APInt &LHS, const APInt &RHS) { return LHS | RHS; }
-
-/// \brief Bitwise XOR function for APInt.
-///
-/// Performs bitwise XOR operation on APInt.
-inline APInt Xor(const APInt &LHS, const APInt &RHS) { return LHS ^ RHS; }
-
-/// \brief Bitwise complement function.
-///
-/// Performs a bitwise complement operation on APInt.
-inline APInt Not(const APInt &APIVal) { return ~APIVal; }
-
} // End of APIntOps namespace
// See friend declaration above. This additional declaration is required in
diff --git a/include/llvm/ADT/APSInt.h b/include/llvm/ADT/APSInt.h
index 813b3686d6b1..5b6dfa4a4b64 100644
--- a/include/llvm/ADT/APSInt.h
+++ b/include/llvm/ADT/APSInt.h
@@ -235,19 +235,16 @@ public:
assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
return APSInt(static_cast<const APInt&>(*this) & RHS, IsUnsigned);
}
- APSInt And(const APSInt &RHS) const { return this->operator&(RHS); }
APSInt operator|(const APSInt& RHS) const {
assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
return APSInt(static_cast<const APInt&>(*this) | RHS, IsUnsigned);
}
- APSInt Or(const APSInt &RHS) const { return this->operator|(RHS); }
APSInt operator^(const APSInt &RHS) const {
assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
return APSInt(static_cast<const APInt&>(*this) ^ RHS, IsUnsigned);
}
- APSInt Xor(const APSInt &RHS) const { return this->operator^(RHS); }
APSInt operator*(const APSInt& RHS) const {
assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
diff --git a/include/llvm/ADT/ArrayRef.h b/include/llvm/ADT/ArrayRef.h
index b3fe31f4a806..6b35d0aec8b2 100644
--- a/include/llvm/ADT/ArrayRef.h
+++ b/include/llvm/ADT/ArrayRef.h
@@ -487,6 +487,18 @@ namespace llvm {
return ArrayRef<T>(Arr);
}
+ /// Construct a MutableArrayRef from a single element.
+ template<typename T>
+ MutableArrayRef<T> makeMutableArrayRef(T &OneElt) {
+ return OneElt;
+ }
+
+ /// Construct a MutableArrayRef from a pointer and length.
+ template<typename T>
+ MutableArrayRef<T> makeMutableArrayRef(T *data, size_t length) {
+ return MutableArrayRef<T>(data, length);
+ }
+
/// @}
/// @name ArrayRef Comparison Operators
/// @{
diff --git a/include/llvm/ADT/BitVector.h b/include/llvm/ADT/BitVector.h
index cf3756d0d9c1..8240d01ae977 100644
--- a/include/llvm/ADT/BitVector.h
+++ b/include/llvm/ADT/BitVector.h
@@ -161,6 +161,17 @@ public:
return -1;
}
+ /// find_first_unset - Returns the index of the first unset bit, -1 if all
+ /// of the bits are set.
+ int find_first_unset() const {
+ for (unsigned i = 0; i < NumBitWords(size()); ++i)
+ if (Bits[i] != ~0UL) {
+ unsigned Result = i * BITWORD_SIZE + countTrailingOnes(Bits[i]);
+ return Result < size() ? Result : -1;
+ }
+ return -1;
+ }
+
/// find_next - Returns the index of the next set bit following the
/// "Prev" bit. Returns -1 if the next set bit is not found.
int find_next(unsigned Prev) const {
@@ -184,6 +195,30 @@ public:
return -1;
}
+ /// find_next_unset - Returns the index of the next usnet bit following the
+ /// "Prev" bit. Returns -1 if all remaining bits are set.
+ int find_next_unset(unsigned Prev) const {
+ ++Prev;
+ if (Prev >= Size)
+ return -1;
+
+ unsigned WordPos = Prev / BITWORD_SIZE;
+ unsigned BitPos = Prev % BITWORD_SIZE;
+ BitWord Copy = Bits[WordPos];
+ // Mask in previous bits.
+ BitWord Mask = (1 << BitPos) - 1;
+ Copy |= Mask;
+
+ if (Copy != ~0UL)
+ return next_unset_in_word(WordPos, Copy);
+
+ // Check subsequent words.
+ for (unsigned i = WordPos + 1; i < NumBitWords(size()); ++i)
+ if (Bits[i] != ~0UL)
+ return next_unset_in_word(i, Bits[i]);
+ return -1;
+ }
+
/// clear - Clear all bits.
void clear() {
Size = 0;
@@ -503,6 +538,11 @@ public:
}
private:
+ int next_unset_in_word(int WordIndex, BitWord Word) const {
+ unsigned Result = WordIndex * BITWORD_SIZE + countTrailingOnes(Word);
+ return Result < size() ? Result : -1;
+ }
+
unsigned NumBitWords(unsigned S) const {
return (S + BITWORD_SIZE-1) / BITWORD_SIZE;
}
@@ -539,7 +579,8 @@ private:
}
void init_words(BitWord *B, unsigned NumWords, bool t) {
- memset(B, 0 - (int)t, NumWords*sizeof(BitWord));
+ if (NumWords > 0)
+ memset(B, 0 - (int)t, NumWords*sizeof(BitWord));
}
template<bool AddBits, bool InvertMask>
diff --git a/include/llvm/ADT/BreadthFirstIterator.h b/include/llvm/ADT/BreadthFirstIterator.h
new file mode 100644
index 000000000000..eaeecb6e057f
--- /dev/null
+++ b/include/llvm/ADT/BreadthFirstIterator.h
@@ -0,0 +1,164 @@
+//===- llvm/ADT/BreadthFirstIterator.h - Breadth First iterator -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file builds on the ADT/GraphTraits.h file to build a generic breadth
+// first graph iterator. This file exposes the following functions/types:
+//
+// bf_begin/bf_end/bf_iterator
+// * Normal breadth-first iteration - visit a graph level-by-level.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_BREADTHFIRSTITERATOR_H
+#define LLVM_ADT_BREADTHFIRSTITERATOR_H
+
+#include "llvm/ADT/GraphTraits.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/iterator_range.h"
+#include <iterator>
+#include <queue>
+#include <set>
+#include <utility>
+
+namespace llvm {
+
+// bf_iterator_storage - A private class which is used to figure out where to
+// store the visited set. We only provide a non-external variant for now.
+template <class SetType> class bf_iterator_storage {
+public:
+ SetType Visited;
+};
+
+// The visited state for the iteration is a simple set.
+template <typename NodeRef, unsigned SmallSize = 8>
+using bf_iterator_default_set = SmallPtrSet<NodeRef, SmallSize>;
+
+// Generic Breadth first search iterator.
+template <class GraphT,
+ class SetType =
+ bf_iterator_default_set<typename GraphTraits<GraphT>::NodeRef>,
+ class GT = GraphTraits<GraphT>>
+class bf_iterator
+ : public std::iterator<std::forward_iterator_tag, typename GT::NodeRef>,
+ public bf_iterator_storage<SetType> {
+ typedef std::iterator<std::forward_iterator_tag, typename GT::NodeRef> super;
+
+ typedef typename GT::NodeRef NodeRef;
+ typedef typename GT::ChildIteratorType ChildItTy;
+
+ // First element is the node reference, second is the next child to visit.
+ typedef std::pair<NodeRef, Optional<ChildItTy>> QueueElement;
+
+ // Visit queue - used to maintain BFS ordering.
+ // Optional<> because we need markers for levels.
+ std::queue<Optional<QueueElement>> VisitQueue;
+
+ // Current level.
+ unsigned Level;
+
+private:
+ inline bf_iterator(NodeRef Node) {
+ this->Visited.insert(Node);
+ Level = 0;
+
+ // Also, insert a dummy node as marker.
+ VisitQueue.push(QueueElement(Node, None));
+ VisitQueue.push(None);
+ }
+
+ inline bf_iterator() = default;
+
+ inline void toNext() {
+ Optional<QueueElement> Head = VisitQueue.front();
+ QueueElement H = Head.getValue();
+ NodeRef Node = H.first;
+ Optional<ChildItTy> &ChildIt = H.second;
+
+ if (!ChildIt)
+ ChildIt.emplace(GT::child_begin(Node));
+ while (*ChildIt != GT::child_end(Node)) {
+ NodeRef Next = *(*ChildIt)++;
+
+ // Already visited?
+ if (this->Visited.insert(Next).second)
+ VisitQueue.push(QueueElement(Next, None));
+ }
+ VisitQueue.pop();
+
+ // Go to the next element skipping markers if needed.
+ if (!VisitQueue.empty()) {
+ Head = VisitQueue.front();
+ if (Head != None)
+ return;
+ Level += 1;
+ VisitQueue.pop();
+
+ // Don't push another marker if this is the last
+ // element.
+ if (!VisitQueue.empty())
+ VisitQueue.push(None);
+ }
+ }
+
+public:
+ typedef typename super::pointer pointer;
+
+ // Provide static begin and end methods as our public "constructors"
+ static bf_iterator begin(const GraphT &G) {
+ return bf_iterator(GT::getEntryNode(G));
+ }
+
+ static bf_iterator end(const GraphT &G) { return bf_iterator(); }
+
+ bool operator==(const bf_iterator &RHS) const {
+ return VisitQueue == RHS.VisitQueue;
+ }
+
+ bool operator!=(const bf_iterator &RHS) const { return !(*this == RHS); }
+
+ const NodeRef &operator*() const { return VisitQueue.front()->first; }
+
+ // This is a nonstandard operator-> that dereferenfces the pointer an extra
+ // time so that you can actually call methods on the node, because the
+ // contained type is a pointer.
+ NodeRef operator->() const { return **this; }
+
+ bf_iterator &operator++() { // Pre-increment
+ toNext();
+ return *this;
+ }
+
+ bf_iterator operator++(int) { // Post-increment
+ bf_iterator ItCopy = *this;
+ ++*this;
+ return ItCopy;
+ }
+
+ unsigned getLevel() const { return Level; }
+};
+
+// Provide global constructors that automatically figure out correct types.
+template <class T> bf_iterator<T> bf_begin(const T &G) {
+ return bf_iterator<T>::begin(G);
+}
+
+template <class T> bf_iterator<T> bf_end(const T &G) {
+ return bf_iterator<T>::end(G);
+}
+
+// Provide an accessor method to use them in range-based patterns.
+template <class T> iterator_range<bf_iterator<T>> breadth_first(const T &G) {
+ return make_range(bf_begin(G), bf_end(G));
+}
+
+} // end namespace llvm
+
+#endif // LLVM_ADT_BREADTHFIRSTITERATOR_H
diff --git a/include/llvm/ADT/DenseMap.h b/include/llvm/ADT/DenseMap.h
index 0b4b09d4b733..fd8d3bf368a8 100644
--- a/include/llvm/ADT/DenseMap.h
+++ b/include/llvm/ADT/DenseMap.h
@@ -53,6 +53,9 @@ class DenseMapIterator;
template <typename DerivedT, typename KeyT, typename ValueT, typename KeyInfoT,
typename BucketT>
class DenseMapBase : public DebugEpochBase {
+ template <typename T>
+ using const_arg_type_t = typename const_pointer_or_const_ref<T>::type;
+
public:
typedef unsigned size_type;
typedef KeyT key_type;
@@ -119,18 +122,18 @@ public:
}
/// Return 1 if the specified key is in the map, 0 otherwise.
- size_type count(const KeyT &Val) const {
+ size_type count(const_arg_type_t<KeyT> Val) const {
const BucketT *TheBucket;
return LookupBucketFor(Val, TheBucket) ? 1 : 0;
}
- iterator find(const KeyT &Val) {
+ iterator find(const_arg_type_t<KeyT> Val) {
BucketT *TheBucket;
if (LookupBucketFor(Val, TheBucket))
return iterator(TheBucket, getBucketsEnd(), *this, true);
return end();
}
- const_iterator find(const KeyT &Val) const {
+ const_iterator find(const_arg_type_t<KeyT> Val) const {
const BucketT *TheBucket;
if (LookupBucketFor(Val, TheBucket))
return const_iterator(TheBucket, getBucketsEnd(), *this, true);
@@ -159,7 +162,7 @@ public:
/// lookup - Return the entry for the specified key, or a default
/// constructed value if no such entry exists.
- ValueT lookup(const KeyT &Val) const {
+ ValueT lookup(const_arg_type_t<KeyT> Val) const {
const BucketT *TheBucket;
if (LookupBucketFor(Val, TheBucket))
return TheBucket->getSecond();
@@ -389,6 +392,8 @@ protected:
return KeyInfoT::getHashValue(Val);
}
static const KeyT getEmptyKey() {
+ static_assert(std::is_base_of<DenseMapBase, DerivedT>::value,
+ "Must pass the derived type to this template!");
return KeyInfoT::getEmptyKey();
}
static const KeyT getTombstoneKey() {
diff --git a/include/llvm/ADT/DenseMapInfo.h b/include/llvm/ADT/DenseMapInfo.h
index a844ebcccf5b..bb973ac65063 100644
--- a/include/llvm/ADT/DenseMapInfo.h
+++ b/include/llvm/ADT/DenseMapInfo.h
@@ -60,6 +60,16 @@ template<> struct DenseMapInfo<char> {
}
};
+// Provide DenseMapInfo for unsigned shorts.
+template <> struct DenseMapInfo<unsigned short> {
+ static inline unsigned short getEmptyKey() { return 0xFFFF; }
+ static inline unsigned short getTombstoneKey() { return 0xFFFF - 1; }
+ static unsigned getHashValue(const unsigned short &Val) { return Val * 37U; }
+ static bool isEqual(const unsigned short &LHS, const unsigned short &RHS) {
+ return LHS == RHS;
+ }
+};
+
// Provide DenseMapInfo for unsigned ints.
template<> struct DenseMapInfo<unsigned> {
static inline unsigned getEmptyKey() { return ~0U; }
@@ -95,6 +105,14 @@ template<> struct DenseMapInfo<unsigned long long> {
}
};
+// Provide DenseMapInfo for shorts.
+template <> struct DenseMapInfo<short> {
+ static inline short getEmptyKey() { return 0x7FFF; }
+ static inline short getTombstoneKey() { return -0x7FFF - 1; }
+ static unsigned getHashValue(const short &Val) { return Val * 37U; }
+ static bool isEqual(const short &LHS, const short &RHS) { return LHS == RHS; }
+};
+
// Provide DenseMapInfo for ints.
template<> struct DenseMapInfo<int> {
static inline int getEmptyKey() { return 0x7fffffff; }
diff --git a/include/llvm/ADT/DenseSet.h b/include/llvm/ADT/DenseSet.h
index b25d3b7cba6f..fcf304c3ecc4 100644
--- a/include/llvm/ADT/DenseSet.h
+++ b/include/llvm/ADT/DenseSet.h
@@ -48,6 +48,8 @@ class DenseSetImpl {
static_assert(sizeof(typename MapTy::value_type) == sizeof(ValueT),
"DenseMap buckets unexpectedly large!");
MapTy TheMap;
+ template <typename T>
+ using const_arg_type_t = typename const_pointer_or_const_ref<T>::type;
public:
typedef ValueT key_type;
@@ -78,7 +80,7 @@ public:
}
/// Return 1 if the specified key is in the set, 0 otherwise.
- size_type count(const ValueT &V) const {
+ size_type count(const_arg_type_t<ValueT> V) const {
return TheMap.count(V);
}
@@ -90,9 +92,12 @@ public:
// Iterators.
+ class ConstIterator;
+
class Iterator {
typename MapTy::iterator I;
friend class DenseSetImpl;
+ friend class ConstIterator;
public:
typedef typename MapTy::iterator::difference_type difference_type;
@@ -101,20 +106,24 @@ public:
typedef value_type &reference;
typedef std::forward_iterator_tag iterator_category;
+ Iterator() = default;
Iterator(const typename MapTy::iterator &i) : I(i) {}
ValueT &operator*() { return I->getFirst(); }
+ const ValueT &operator*() const { return I->getFirst(); }
ValueT *operator->() { return &I->getFirst(); }
+ const ValueT *operator->() const { return &I->getFirst(); }
Iterator& operator++() { ++I; return *this; }
Iterator operator++(int) { auto T = *this; ++I; return T; }
- bool operator==(const Iterator& X) const { return I == X.I; }
- bool operator!=(const Iterator& X) const { return I != X.I; }
+ bool operator==(const ConstIterator& X) const { return I == X.I; }
+ bool operator!=(const ConstIterator& X) const { return I != X.I; }
};
class ConstIterator {
typename MapTy::const_iterator I;
friend class DenseSet;
+ friend class Iterator;
public:
typedef typename MapTy::const_iterator::difference_type difference_type;
@@ -123,10 +132,14 @@ public:
typedef value_type &reference;
typedef std::forward_iterator_tag iterator_category;
+ ConstIterator(const Iterator &B) : I(B.I) {}
+
+ ConstIterator() = default;
+
ConstIterator(const typename MapTy::const_iterator &i) : I(i) {}
- const ValueT &operator*() { return I->getFirst(); }
- const ValueT *operator->() { return &I->getFirst(); }
+ const ValueT &operator*() const { return I->getFirst(); }
+ const ValueT *operator->() const { return &I->getFirst(); }
ConstIterator& operator++() { ++I; return *this; }
ConstIterator operator++(int) { auto T = *this; ++I; return T; }
@@ -143,8 +156,8 @@ public:
const_iterator begin() const { return ConstIterator(TheMap.begin()); }
const_iterator end() const { return ConstIterator(TheMap.end()); }
- iterator find(const ValueT &V) { return Iterator(TheMap.find(V)); }
- const_iterator find(const ValueT &V) const {
+ iterator find(const_arg_type_t<ValueT> V) { return Iterator(TheMap.find(V)); }
+ const_iterator find(const_arg_type_t<ValueT> V) const {
return ConstIterator(TheMap.find(V));
}
diff --git a/include/llvm/ADT/DepthFirstIterator.h b/include/llvm/ADT/DepthFirstIterator.h
index c54573204588..b020d48cb3f0 100644
--- a/include/llvm/ADT/DepthFirstIterator.h
+++ b/include/llvm/ADT/DepthFirstIterator.h
@@ -135,7 +135,7 @@ private:
}
}
this->Visited.completed(Node);
-
+
// Oops, ran out of successors... go up a level on the stack.
VisitStack.pop_back();
} while (!VisitStack.empty());
diff --git a/include/llvm/ADT/GraphTraits.h b/include/llvm/ADT/GraphTraits.h
index 29bbcb010eee..2c88c4271b48 100644
--- a/include/llvm/ADT/GraphTraits.h
+++ b/include/llvm/ADT/GraphTraits.h
@@ -18,6 +18,8 @@
#ifndef LLVM_ADT_GRAPHTRAITS_H
#define LLVM_ADT_GRAPHTRAITS_H
+#include "llvm/ADT/iterator_range.h"
+
namespace llvm {
// GraphTraits - This class should be specialized by different graph types...
@@ -86,6 +88,33 @@ struct Inverse {
// inverse falls back to the original graph.
template <class T> struct GraphTraits<Inverse<Inverse<T>>> : GraphTraits<T> {};
+// Provide iterator ranges for the graph traits nodes and children
+template <class GraphType>
+iterator_range<typename GraphTraits<GraphType>::nodes_iterator>
+nodes(const GraphType &G) {
+ return make_range(GraphTraits<GraphType>::nodes_begin(G),
+ GraphTraits<GraphType>::nodes_end(G));
+}
+template <class GraphType>
+iterator_range<typename GraphTraits<Inverse<GraphType>>::nodes_iterator>
+inverse_nodes(const GraphType &G) {
+ return make_range(GraphTraits<Inverse<GraphType>>::nodes_begin(G),
+ GraphTraits<Inverse<GraphType>>::nodes_end(G));
+}
+
+template <class GraphType>
+iterator_range<typename GraphTraits<GraphType>::ChildIteratorType>
+children(const typename GraphTraits<GraphType>::NodeRef &G) {
+ return make_range(GraphTraits<GraphType>::child_begin(G),
+ GraphTraits<GraphType>::child_end(G));
+}
+
+template <class GraphType>
+iterator_range<typename GraphTraits<Inverse<GraphType>>::ChildIteratorType>
+inverse_children(const typename GraphTraits<GraphType>::NodeRef &G) {
+ return make_range(GraphTraits<Inverse<GraphType>>::child_begin(G),
+ GraphTraits<Inverse<GraphType>>::child_end(G));
+}
} // End llvm namespace
#endif
diff --git a/include/llvm/ADT/None.h b/include/llvm/ADT/None.h
index d69ec17c15f9..c7a99c61994e 100644
--- a/include/llvm/ADT/None.h
+++ b/include/llvm/ADT/None.h
@@ -19,8 +19,9 @@
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 class NoneType { None };
-const NoneType None = None;
+// (constant value 1 in an attempt to workaround MSVC build issue... )
+enum class NoneType { None = 1 };
+const NoneType None = NoneType::None;
}
#endif
diff --git a/include/llvm/ADT/PointerUnion.h b/include/llvm/ADT/PointerUnion.h
index a8ac18645f3a..9eb15524c0f3 100644
--- a/include/llvm/ADT/PointerUnion.h
+++ b/include/llvm/ADT/PointerUnion.h
@@ -31,7 +31,7 @@ template <typename T> struct PointerUnionTypeSelectorReturn {
/// Get a type based on whether two types are the same or not.
///
/// For:
-///
+///
/// \code
/// typedef typename PointerUnionTypeSelector<T1, T2, EQ, NE>::Return Ret;
/// \endcode
@@ -190,17 +190,17 @@ public:
};
template <typename PT1, typename PT2>
-static bool operator==(PointerUnion<PT1, PT2> lhs, PointerUnion<PT1, PT2> rhs) {
+bool operator==(PointerUnion<PT1, PT2> lhs, PointerUnion<PT1, PT2> rhs) {
return lhs.getOpaqueValue() == rhs.getOpaqueValue();
}
template <typename PT1, typename PT2>
-static bool operator!=(PointerUnion<PT1, PT2> lhs, PointerUnion<PT1, PT2> rhs) {
+bool operator!=(PointerUnion<PT1, PT2> lhs, PointerUnion<PT1, PT2> rhs) {
return lhs.getOpaqueValue() != rhs.getOpaqueValue();
}
template <typename PT1, typename PT2>
-static bool operator<(PointerUnion<PT1, PT2> lhs, PointerUnion<PT1, PT2> rhs) {
+bool operator<(PointerUnion<PT1, PT2> lhs, PointerUnion<PT1, PT2> rhs) {
return lhs.getOpaqueValue() < rhs.getOpaqueValue();
}
diff --git a/include/llvm/ADT/PostOrderIterator.h b/include/llvm/ADT/PostOrderIterator.h
index e519b5c07964..8fc08eb252eb 100644
--- a/include/llvm/ADT/PostOrderIterator.h
+++ b/include/llvm/ADT/PostOrderIterator.h
@@ -268,6 +268,10 @@ inverse_post_order_ext(const T &G, SetType &S) {
// with a postorder iterator to build the data structures). The moral of this
// story is: Don't create more ReversePostOrderTraversal classes than necessary.
//
+// Because it does the traversal in its constructor, it won't invalidate when
+// BasicBlocks are removed, *but* it may contain erased blocks. Some places
+// rely on this behavior (i.e. GVN).
+//
// This class should be used like this:
// {
// ReversePostOrderTraversal<Function*> RPOT(FuncPtr); // Expensive to create
diff --git a/include/llvm/ADT/STLExtras.h b/include/llvm/ADT/STLExtras.h
index ec121e0d55cd..15945adbe589 100644
--- a/include/llvm/ADT/STLExtras.h
+++ b/include/llvm/ADT/STLExtras.h
@@ -23,11 +23,13 @@
#include <cstdlib> // for qsort
#include <functional>
#include <iterator>
+#include <limits>
#include <memory>
#include <tuple>
#include <utility> // for std::pair
#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/iterator.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/Compiler.h"
@@ -44,6 +46,10 @@ namespace detail {
template <typename RangeT>
using IterOfRange = decltype(std::begin(std::declval<RangeT &>()));
+template <typename RangeT>
+using ValueOfRange = typename std::remove_reference<decltype(
+ *std::begin(std::declval<RangeT &>()))>::type;
+
} // End detail namespace
//===----------------------------------------------------------------------===//
@@ -123,7 +129,7 @@ inline void deleter(T *Ptr) {
//===----------------------------------------------------------------------===//
// mapped_iterator - This is a simple iterator adapter that causes a function to
-// be dereferenced whenever operator* is invoked on the iterator.
+// be applied whenever operator* is invoked on the iterator.
//
template <class RootIt, class UnaryFunc>
class mapped_iterator {
@@ -134,9 +140,8 @@ public:
iterator_category;
typedef typename std::iterator_traits<RootIt>::difference_type
difference_type;
- typedef typename std::result_of<
- UnaryFunc(decltype(*std::declval<RootIt>()))>
- ::type value_type;
+ typedef decltype(std::declval<UnaryFunc>()(*std::declval<RootIt>()))
+ value_type;
typedef void pointer;
//typedef typename UnaryFunc::result_type *pointer;
@@ -356,65 +361,126 @@ template <size_t... I> struct index_sequence;
template <class... Ts> struct index_sequence_for;
namespace detail {
-template <typename... Iters> class zip_first {
-public:
- typedef std::input_iterator_tag iterator_category;
- typedef std::tuple<decltype(*std::declval<Iters>())...> value_type;
+using std::declval;
+
+// We have to alias this since inlining the actual type at the usage site
+// in the parameter list of iterator_facade_base<> below ICEs MSVC 2017.
+template<typename... Iters> struct ZipTupleType {
+ typedef std::tuple<decltype(*declval<Iters>())...> type;
+};
+
+template <typename ZipType, typename... Iters>
+using zip_traits = iterator_facade_base<
+ ZipType, typename std::common_type<std::bidirectional_iterator_tag,
+ typename std::iterator_traits<
+ Iters>::iterator_category...>::type,
+ // ^ TODO: Implement random access methods.
+ typename ZipTupleType<Iters...>::type,
+ typename std::iterator_traits<typename std::tuple_element<
+ 0, std::tuple<Iters...>>::type>::difference_type,
+ // ^ FIXME: This follows boost::make_zip_iterator's assumption that all
+ // inner iterators have the same difference_type. It would fail if, for
+ // instance, the second field's difference_type were non-numeric while the
+ // first is.
+ typename ZipTupleType<Iters...>::type *,
+ typename ZipTupleType<Iters...>::type>;
+
+template <typename ZipType, typename... Iters>
+struct zip_common : public zip_traits<ZipType, Iters...> {
+ using Base = zip_traits<ZipType, Iters...>;
+ using value_type = typename Base::value_type;
+
std::tuple<Iters...> iterators;
-private:
- template <size_t... Ns> value_type deres(index_sequence<Ns...>) {
+protected:
+ template <size_t... Ns> value_type deref(index_sequence<Ns...>) const {
return value_type(*std::get<Ns>(iterators)...);
}
- template <size_t... Ns> decltype(iterators) tup_inc(index_sequence<Ns...>) {
+ template <size_t... Ns>
+ decltype(iterators) tup_inc(index_sequence<Ns...>) const {
return std::tuple<Iters...>(std::next(std::get<Ns>(iterators))...);
}
+ template <size_t... Ns>
+ decltype(iterators) tup_dec(index_sequence<Ns...>) const {
+ return std::tuple<Iters...>(std::prev(std::get<Ns>(iterators))...);
+ }
+
public:
- value_type operator*() { return deres(index_sequence_for<Iters...>{}); }
+ zip_common(Iters &&... ts) : iterators(std::forward<Iters>(ts)...) {}
+
+ value_type operator*() { return deref(index_sequence_for<Iters...>{}); }
- void operator++() { iterators = tup_inc(index_sequence_for<Iters...>{}); }
+ const value_type operator*() const {
+ return deref(index_sequence_for<Iters...>{});
+ }
- bool operator!=(const zip_first<Iters...> &other) const {
- return std::get<0>(iterators) != std::get<0>(other.iterators);
+ ZipType &operator++() {
+ iterators = tup_inc(index_sequence_for<Iters...>{});
+ return *reinterpret_cast<ZipType *>(this);
}
- zip_first(Iters &&... ts) : iterators(std::forward<Iters>(ts)...) {}
+
+ ZipType &operator--() {
+ static_assert(Base::IsBidirectional,
+ "All inner iterators must be at least bidirectional.");
+ iterators = tup_dec(index_sequence_for<Iters...>{});
+ return *reinterpret_cast<ZipType *>(this);
+ }
+};
+
+template <typename... Iters>
+struct zip_first : public zip_common<zip_first<Iters...>, Iters...> {
+ using Base = zip_common<zip_first<Iters...>, Iters...>;
+
+ bool operator==(const zip_first<Iters...> &other) const {
+ return std::get<0>(this->iterators) == std::get<0>(other.iterators);
+ }
+
+ zip_first(Iters &&... ts) : Base(std::forward<Iters>(ts)...) {}
};
-template <typename... Iters> class zip_shortest : public zip_first<Iters...> {
+template <typename... Iters>
+class zip_shortest : public zip_common<zip_shortest<Iters...>, Iters...> {
template <size_t... Ns>
- bool test(const zip_first<Iters...> &other, index_sequence<Ns...>) const {
+ bool test(const zip_shortest<Iters...> &other, index_sequence<Ns...>) const {
return all_of(std::initializer_list<bool>{std::get<Ns>(this->iterators) !=
std::get<Ns>(other.iterators)...},
identity<bool>{});
}
public:
- bool operator!=(const zip_first<Iters...> &other) const {
- return test(other, index_sequence_for<Iters...>{});
+ using Base = zip_common<zip_shortest<Iters...>, Iters...>;
+
+ bool operator==(const zip_shortest<Iters...> &other) const {
+ return !test(other, index_sequence_for<Iters...>{});
}
- zip_shortest(Iters &&... ts)
- : zip_first<Iters...>(std::forward<Iters>(ts)...) {}
+
+ zip_shortest(Iters &&... ts) : Base(std::forward<Iters>(ts)...) {}
};
template <template <typename...> class ItType, typename... Args> class zippy {
public:
- typedef ItType<decltype(std::begin(std::declval<Args>()))...> iterator;
+ using iterator = ItType<decltype(std::begin(std::declval<Args>()))...>;
+ using iterator_category = typename iterator::iterator_category;
+ using value_type = typename iterator::value_type;
+ using difference_type = typename iterator::difference_type;
+ using pointer = typename iterator::pointer;
+ using reference = typename iterator::reference;
private:
std::tuple<Args...> ts;
- template <size_t... Ns> iterator begin_impl(index_sequence<Ns...>) {
+ template <size_t... Ns> iterator begin_impl(index_sequence<Ns...>) const {
return iterator(std::begin(std::get<Ns>(ts))...);
}
- template <size_t... Ns> iterator end_impl(index_sequence<Ns...>) {
+ template <size_t... Ns> iterator end_impl(index_sequence<Ns...>) const {
return iterator(std::end(std::get<Ns>(ts))...);
}
public:
- iterator begin() { return begin_impl(index_sequence_for<Args...>{}); }
- iterator end() { return end_impl(index_sequence_for<Args...>{}); }
+ iterator begin() const { return begin_impl(index_sequence_for<Args...>{}); }
+ iterator end() const { return end_impl(index_sequence_for<Args...>{}); }
zippy(Args &&... ts_) : ts(std::forward<Args>(ts_)...) {}
};
} // End detail namespace
@@ -777,6 +843,13 @@ auto remove_if(R &&Range, UnaryPredicate P) -> decltype(std::begin(Range)) {
return std::remove_if(std::begin(Range), std::end(Range), P);
}
+/// Provide wrappers to std::copy_if which take ranges instead of having to
+/// pass begin/end explicitly.
+template <typename R, typename OutputIt, typename UnaryPredicate>
+OutputIt copy_if(R &&Range, OutputIt Out, UnaryPredicate P) {
+ return std::copy_if(std::begin(Range), std::end(Range), Out, P);
+}
+
/// Wrapper function around std::find to detect if an element exists
/// in a container.
template <typename R, typename E>
@@ -815,6 +888,15 @@ auto partition(R &&Range, UnaryPredicate P) -> decltype(std::begin(Range)) {
return std::partition(std::begin(Range), std::end(Range), P);
}
+/// \brief Given a range of type R, iterate the entire range and return a
+/// SmallVector with elements of the vector. This is useful, for example,
+/// when you want to iterate a range and then sort the results.
+template <unsigned Size, typename R>
+SmallVector<typename std::remove_const<detail::ValueOfRange<R>>::type, Size>
+to_vector(R &&Range) {
+ return {std::begin(Range), std::end(Range)};
+}
+
/// Provide a container algorithm similar to C++ Library Fundamentals v2's
/// `erase_if` which is equivalent to:
///
@@ -909,47 +991,85 @@ template <typename T> struct deref {
};
namespace detail {
-template <typename R> class enumerator_impl {
-public:
- template <typename X> struct result_pair {
- result_pair(std::size_t Index, X Value) : Index(Index), Value(Value) {}
+template <typename R> class enumerator_iter;
- const std::size_t Index;
- X Value;
- };
+template <typename R> struct result_pair {
+ friend class enumerator_iter<R>;
+
+ result_pair() : Index(-1) {}
+ result_pair(std::size_t Index, IterOfRange<R> Iter)
+ : Index(Index), Iter(Iter) {}
- class iterator {
- typedef
- typename std::iterator_traits<IterOfRange<R>>::reference iter_reference;
- typedef result_pair<iter_reference> result_type;
+ result_pair<R> &operator=(const result_pair<R> &Other) {
+ Index = Other.Index;
+ Iter = Other.Iter;
+ return *this;
+ }
- public:
- iterator(IterOfRange<R> &&Iter, std::size_t Index)
- : Iter(Iter), Index(Index) {}
+ std::size_t index() const { return Index; }
+ const ValueOfRange<R> &value() const { return *Iter; }
+ ValueOfRange<R> &value() { return *Iter; }
- result_type operator*() const { return result_type(Index, *Iter); }
+private:
+ std::size_t Index;
+ IterOfRange<R> Iter;
+};
- iterator &operator++() {
- ++Iter;
- ++Index;
- return *this;
- }
+template <typename R>
+class enumerator_iter
+ : public iterator_facade_base<
+ enumerator_iter<R>, std::forward_iterator_tag, result_pair<R>,
+ typename std::iterator_traits<IterOfRange<R>>::difference_type,
+ typename std::iterator_traits<IterOfRange<R>>::pointer,
+ typename std::iterator_traits<IterOfRange<R>>::reference> {
+ using result_type = result_pair<R>;
- bool operator!=(const iterator &RHS) const { return Iter != RHS.Iter; }
+public:
+ explicit enumerator_iter(IterOfRange<R> EndIter)
+ : Result(std::numeric_limits<size_t>::max(), EndIter) { }
- private:
- IterOfRange<R> Iter;
- std::size_t Index;
- };
+ enumerator_iter(std::size_t Index, IterOfRange<R> Iter)
+ : Result(Index, Iter) {}
+
+ result_type &operator*() { return Result; }
+ const result_type &operator*() const { return Result; }
+ enumerator_iter<R> &operator++() {
+ assert(Result.Index != std::numeric_limits<size_t>::max());
+ ++Result.Iter;
+ ++Result.Index;
+ return *this;
+ }
+
+ bool operator==(const enumerator_iter<R> &RHS) const {
+ // Don't compare indices here, only iterators. It's possible for an end
+ // iterator to have different indices depending on whether it was created
+ // by calling std::end() versus incrementing a valid iterator.
+ return Result.Iter == RHS.Result.Iter;
+ }
+
+ enumerator_iter<R> &operator=(const enumerator_iter<R> &Other) {
+ Result = Other.Result;
+ return *this;
+ }
+
+private:
+ result_type Result;
+};
+
+template <typename R> class enumerator {
public:
- explicit enumerator_impl(R &&Range) : Range(std::forward<R>(Range)) {}
+ explicit enumerator(R &&Range) : TheRange(std::forward<R>(Range)) {}
- iterator begin() { return iterator(std::begin(Range), 0); }
- iterator end() { return iterator(std::end(Range), std::size_t(-1)); }
+ enumerator_iter<R> begin() {
+ return enumerator_iter<R>(0, std::begin(TheRange));
+ }
+ enumerator_iter<R> end() {
+ return enumerator_iter<R>(std::end(TheRange));
+ }
private:
- R Range;
+ R TheRange;
};
}
@@ -968,8 +1088,8 @@ private:
/// Item 2 - C
/// Item 3 - D
///
-template <typename R> detail::enumerator_impl<R> enumerate(R &&Range) {
- return detail::enumerator_impl<R>(std::forward<R>(Range));
+template <typename R> detail::enumerator<R> enumerate(R &&TheRange) {
+ return detail::enumerator<R>(std::forward<R>(TheRange));
}
namespace detail {
diff --git a/include/llvm/ADT/ScopedHashTable.h b/include/llvm/ADT/ScopedHashTable.h
index ad805b0991c1..d52128e294a3 100644
--- a/include/llvm/ADT/ScopedHashTable.h
+++ b/include/llvm/ADT/ScopedHashTable.h
@@ -182,8 +182,8 @@ public:
return TopLevelMap.count(Key);
}
- V lookup(const K &Key) {
- typename DenseMap<K, ValTy*, KInfo>::iterator I = TopLevelMap.find(Key);
+ V lookup(const K &Key) const {
+ auto I = TopLevelMap.find(Key);
if (I != TopLevelMap.end())
return I->second->getValue();
diff --git a/include/llvm/ADT/SetVector.h b/include/llvm/ADT/SetVector.h
index 4dc18bc52178..13378aa3a04e 100644
--- a/include/llvm/ADT/SetVector.h
+++ b/include/llvm/ADT/SetVector.h
@@ -119,6 +119,12 @@ public:
return vector_.rend();
}
+ /// \brief Return the first element of the SetVector.
+ const T &front() const {
+ assert(!empty() && "Cannot call front() on empty SetVector!");
+ return vector_.front();
+ }
+
/// \brief Return the last element of the SetVector.
const T &back() const {
assert(!empty() && "Cannot call back() on empty SetVector!");
@@ -232,7 +238,7 @@ public:
bool operator!=(const SetVector &that) const {
return vector_ != that.vector_;
}
-
+
/// \brief Compute This := This u S, return whether 'This' changed.
/// TODO: We should be able to use set_union from SetOperations.h, but
/// SetVector interface is inconsistent with DenseSet.
diff --git a/include/llvm/ADT/SmallBitVector.h b/include/llvm/ADT/SmallBitVector.h
index bb99e0cf221f..edb37da38da1 100644
--- a/include/llvm/ADT/SmallBitVector.h
+++ b/include/llvm/ADT/SmallBitVector.h
@@ -216,6 +216,18 @@ public:
return getPointer()->find_first();
}
+ /// Returns the index of the first unset bit, -1 if all of the bits are set.
+ int find_first_unset() const {
+ if (isSmall()) {
+ if (count() == getSmallSize())
+ return -1;
+
+ uintptr_t Bits = getSmallBits();
+ return countTrailingOnes(Bits);
+ }
+ return getPointer()->find_first_unset();
+ }
+
/// Returns the index of the next set bit following the "Prev" bit.
/// Returns -1 if the next set bit is not found.
int find_next(unsigned Prev) const {
@@ -230,6 +242,23 @@ public:
return getPointer()->find_next(Prev);
}
+ /// Returns the index of the next unset bit following the "Prev" bit.
+ /// Returns -1 if the next unset bit is not found.
+ int find_next_unset(unsigned Prev) const {
+ if (isSmall()) {
+ ++Prev;
+ uintptr_t Bits = getSmallBits();
+ // Mask in previous bits.
+ uintptr_t Mask = (1 << Prev) - 1;
+ Bits |= Mask;
+
+ if (Bits == ~uintptr_t(0) || Prev + 1 >= getSmallSize())
+ return -1;
+ return countTrailingOnes(Bits);
+ }
+ return getPointer()->find_next_unset(Prev);
+ }
+
/// Clear all bits.
void clear() {
if (!isSmall())
diff --git a/include/llvm/ADT/SmallPtrSet.h b/include/llvm/ADT/SmallPtrSet.h
index 49feb9da897a..196ab6338047 100644
--- a/include/llvm/ADT/SmallPtrSet.h
+++ b/include/llvm/ADT/SmallPtrSet.h
@@ -18,6 +18,7 @@
#include "llvm/Config/abi-breaking.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/PointerLikeTypeTraits.h"
+#include "llvm/Support/type_traits.h"
#include <cassert>
#include <cstddef>
#include <cstring>
@@ -166,8 +167,8 @@ protected:
const void *const *P = find_imp(Ptr);
if (P == EndPointer())
return false;
-
- const void ** Loc = const_cast<const void **>(P);
+
+ const void **Loc = const_cast<const void **>(P);
assert(*Loc == Ptr && "broken find!");
*Loc = getTombstoneMarker();
NumTombstones++;
@@ -193,7 +194,7 @@ protected:
return Bucket;
return EndPointer();
}
-
+
private:
bool isSmall() const { return CurArray == SmallArray; }
@@ -259,11 +260,10 @@ protected:
}
#if LLVM_ENABLE_ABI_BREAKING_CHECKS
void RetreatIfNotValid() {
- --Bucket;
- assert(Bucket <= End);
+ assert(Bucket >= End);
while (Bucket != End &&
- (*Bucket == SmallPtrSetImplBase::getEmptyMarker() ||
- *Bucket == SmallPtrSetImplBase::getTombstoneMarker())) {
+ (Bucket[-1] == SmallPtrSetImplBase::getEmptyMarker() ||
+ Bucket[-1] == SmallPtrSetImplBase::getTombstoneMarker())) {
--Bucket;
}
}
@@ -288,6 +288,12 @@ public:
// Most methods provided by baseclass.
const PtrTy operator*() const {
+#if LLVM_ENABLE_ABI_BREAKING_CHECKS
+ if (ReverseIterate<bool>::value) {
+ assert(Bucket > End);
+ return PtrTraits::getFromVoidPointer(const_cast<void *>(Bucket[-1]));
+ }
+#endif
assert(Bucket < End);
return PtrTraits::getFromVoidPointer(const_cast<void*>(*Bucket));
}
@@ -295,6 +301,7 @@ public:
inline SmallPtrSetIterator& operator++() { // Preincrement
#if LLVM_ENABLE_ABI_BREAKING_CHECKS
if (ReverseIterate<bool>::value) {
+ --Bucket;
RetreatIfNotValid();
return *this;
}
@@ -343,7 +350,9 @@ struct RoundUpToPowerOfTwo {
/// to avoid encoding a particular small size in the interface boundary.
template <typename PtrType>
class SmallPtrSetImpl : public SmallPtrSetImplBase {
+ using ConstPtrType = typename add_const_past_pointer<PtrType>::type;
typedef PointerLikeTypeTraits<PtrType> PtrTraits;
+ typedef PointerLikeTypeTraits<ConstPtrType> ConstPtrTraits;
protected:
// Constructors that forward to the base.
@@ -367,7 +376,7 @@ public:
/// the element equal to Ptr.
std::pair<iterator, bool> insert(PtrType Ptr) {
auto p = insert_imp(PtrTraits::getAsVoidPointer(Ptr));
- return std::make_pair(iterator(p.first, EndPointer()), p.second);
+ return std::make_pair(makeIterator(p.first), p.second);
}
/// erase - If the set contains the specified pointer, remove it and return
@@ -375,14 +384,10 @@ public:
bool erase(PtrType Ptr) {
return erase_imp(PtrTraits::getAsVoidPointer(Ptr));
}
-
/// count - Return 1 if the specified pointer is in the set, 0 otherwise.
- size_type count(PtrType Ptr) const {
- return find(Ptr) != endPtr() ? 1 : 0;
- }
- iterator find(PtrType Ptr) const {
- auto *P = find_imp(PtrTraits::getAsVoidPointer(Ptr));
- return iterator(P, EndPointer());
+ size_type count(ConstPtrType Ptr) const { return find(Ptr) != end() ? 1 : 0; }
+ iterator find(ConstPtrType Ptr) const {
+ return makeIterator(find_imp(ConstPtrTraits::getAsVoidPointer(Ptr)));
}
template <typename IterT>
@@ -395,25 +400,23 @@ public:
insert(IL.begin(), IL.end());
}
- inline iterator begin() const {
+ iterator begin() const {
#if LLVM_ENABLE_ABI_BREAKING_CHECKS
if (ReverseIterate<bool>::value)
- return endPtr();
+ return makeIterator(EndPointer() - 1);
#endif
- return iterator(CurArray, EndPointer());
+ return makeIterator(CurArray);
}
- inline iterator end() const {
+ iterator end() const { return makeIterator(EndPointer()); }
+
+private:
+ /// Create an iterator that dereferences to same place as the given pointer.
+ iterator makeIterator(const void *const *P) const {
#if LLVM_ENABLE_ABI_BREAKING_CHECKS
if (ReverseIterate<bool>::value)
- return iterator(CurArray, CurArray);
+ return iterator(P == EndPointer() ? CurArray : P + 1, CurArray);
#endif
- return endPtr();
- }
-
-private:
- inline iterator endPtr() const {
- const void *const *End = EndPointer();
- return iterator(End, End);
+ return iterator(P, EndPointer());
}
};
diff --git a/include/llvm/ADT/SparseBitVector.h b/include/llvm/ADT/SparseBitVector.h
index e2822c46e266..a82cef6028f9 100644
--- a/include/llvm/ADT/SparseBitVector.h
+++ b/include/llvm/ADT/SparseBitVector.h
@@ -132,6 +132,17 @@ public:
llvm_unreachable("Illegal empty element");
}
+ /// find_last - Returns the index of the last set bit.
+ int find_last() const {
+ for (unsigned I = 0; I < BITWORDS_PER_ELEMENT; ++I) {
+ unsigned Idx = BITWORDS_PER_ELEMENT - I - 1;
+ if (Bits[Idx] != 0)
+ return Idx * BITWORD_SIZE + BITWORD_SIZE -
+ countLeadingZeros(Bits[Idx]) - 1;
+ }
+ llvm_unreachable("Illegal empty element");
+ }
+
/// find_next - Returns the index of the next set bit starting from the
/// "Curr" bit. Returns -1 if the next set bit is not found.
int find_next(unsigned Curr) const {
@@ -768,6 +779,14 @@ public:
return (First.index() * ElementSize) + First.find_first();
}
+ // Return the last set bit in the bitmap. Return -1 if no bits are set.
+ int find_last() const {
+ if (Elements.empty())
+ return -1;
+ const SparseBitVectorElement<ElementSize> &Last = *(Elements.rbegin());
+ return (Last.index() * ElementSize) + Last.find_last();
+ }
+
// Return true if the SparseBitVector is empty
bool empty() const {
return Elements.empty();
diff --git a/include/llvm/ADT/StringExtras.h b/include/llvm/ADT/StringExtras.h
index 488748a5f605..8214782bfe80 100644
--- a/include/llvm/ADT/StringExtras.h
+++ b/include/llvm/ADT/StringExtras.h
@@ -234,6 +234,13 @@ inline std::string join(IteratorT Begin, IteratorT End, StringRef Separator) {
return detail::join_impl(Begin, End, Separator, tag());
}
+/// Joins the strings in the range [R.begin(), R.end()), adding Separator
+/// between the elements.
+template <typename Range>
+inline std::string join(Range &&R, StringRef Separator) {
+ return join(R.begin(), R.end(), Separator);
+}
+
/// Joins the strings in the parameter pack \p Items, adding \p Separator
/// between the elements. All arguments must be implicitly convertible to
/// std::string, or there should be an overload of std::string::operator+=()
diff --git a/include/llvm/ADT/StringMap.h b/include/llvm/ADT/StringMap.h
index 24e3ecf71b13..c36fda7d6906 100644
--- a/include/llvm/ADT/StringMap.h
+++ b/include/llvm/ADT/StringMap.h
@@ -15,13 +15,13 @@
#define LLVM_ADT_STRINGMAP_H
#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/iterator.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/PointerLikeTypeTraits.h"
#include <cassert>
#include <cstdint>
#include <cstdlib>
#include <cstring>
-#include <utility>
#include <initializer_list>
#include <new>
#include <utility>
@@ -32,6 +32,7 @@ namespace llvm {
class StringMapConstIterator;
template<typename ValueT>
class StringMapIterator;
+ template <typename ValueT> class StringMapKeyIterator;
template<typename ValueTy>
class StringMapEntry;
@@ -312,6 +313,11 @@ public:
return const_iterator(TheTable+NumBuckets, true);
}
+ llvm::iterator_range<StringMapKeyIterator<ValueTy>> keys() const {
+ return make_range(StringMapKeyIterator<ValueTy>(begin()),
+ StringMapKeyIterator<ValueTy>(end()));
+ }
+
iterator find(StringRef Key) {
int Bucket = FindKey(Key);
if (Bucket == -1) return end();
@@ -444,42 +450,39 @@ public:
}
};
-template <typename ValueTy> class StringMapConstIterator {
+template <typename DerivedTy, typename ValueTy>
+class StringMapIterBase
+ : public iterator_facade_base<DerivedTy, std::forward_iterator_tag,
+ ValueTy> {
protected:
StringMapEntryBase **Ptr = nullptr;
public:
- typedef StringMapEntry<ValueTy> value_type;
-
- StringMapConstIterator() = default;
+ StringMapIterBase() = default;
- explicit StringMapConstIterator(StringMapEntryBase **Bucket,
- bool NoAdvance = false)
- : Ptr(Bucket) {
+ explicit StringMapIterBase(StringMapEntryBase **Bucket,
+ bool NoAdvance = false)
+ : Ptr(Bucket) {
if (!NoAdvance) AdvancePastEmptyBuckets();
}
- const value_type &operator*() const {
- return *static_cast<StringMapEntry<ValueTy>*>(*Ptr);
- }
- const value_type *operator->() const {
- return static_cast<StringMapEntry<ValueTy>*>(*Ptr);
+ DerivedTy &operator=(const DerivedTy &Other) {
+ Ptr = Other.Ptr;
+ return static_cast<DerivedTy &>(*this);
}
- bool operator==(const StringMapConstIterator &RHS) const {
- return Ptr == RHS.Ptr;
- }
- bool operator!=(const StringMapConstIterator &RHS) const {
- return Ptr != RHS.Ptr;
- }
+ bool operator==(const DerivedTy &RHS) const { return Ptr == RHS.Ptr; }
- inline StringMapConstIterator& operator++() { // Preincrement
+ DerivedTy &operator++() { // Preincrement
++Ptr;
AdvancePastEmptyBuckets();
- return *this;
+ return static_cast<DerivedTy &>(*this);
}
- StringMapConstIterator operator++(int) { // Postincrement
- StringMapConstIterator tmp = *this; ++*this; return tmp;
+
+ DerivedTy operator++(int) { // Post-increment
+ DerivedTy Tmp(Ptr);
+ ++*this;
+ return Tmp;
}
private:
@@ -489,22 +492,67 @@ private:
}
};
-template<typename ValueTy>
-class StringMapIterator : public StringMapConstIterator<ValueTy> {
+template <typename ValueTy>
+class StringMapConstIterator
+ : public StringMapIterBase<StringMapConstIterator<ValueTy>,
+ const StringMapEntry<ValueTy>> {
+ using base = StringMapIterBase<StringMapConstIterator<ValueTy>,
+ const StringMapEntry<ValueTy>>;
+
public:
- StringMapIterator() = default;
+ StringMapConstIterator() = default;
+ explicit StringMapConstIterator(StringMapEntryBase **Bucket,
+ bool NoAdvance = false)
+ : base(Bucket, NoAdvance) {}
+
+ const StringMapEntry<ValueTy> &operator*() const {
+ return *static_cast<const StringMapEntry<ValueTy> *>(*this->Ptr);
+ }
+};
+
+template <typename ValueTy>
+class StringMapIterator : public StringMapIterBase<StringMapIterator<ValueTy>,
+ StringMapEntry<ValueTy>> {
+ using base =
+ StringMapIterBase<StringMapIterator<ValueTy>, StringMapEntry<ValueTy>>;
+public:
+ StringMapIterator() = default;
explicit StringMapIterator(StringMapEntryBase **Bucket,
bool NoAdvance = false)
- : StringMapConstIterator<ValueTy>(Bucket, NoAdvance) {
- }
+ : base(Bucket, NoAdvance) {}
StringMapEntry<ValueTy> &operator*() const {
- return *static_cast<StringMapEntry<ValueTy>*>(*this->Ptr);
+ return *static_cast<StringMapEntry<ValueTy> *>(*this->Ptr);
+ }
+
+ operator StringMapConstIterator<ValueTy>() const {
+ return StringMapConstIterator<ValueTy>(this->Ptr, true);
}
- StringMapEntry<ValueTy> *operator->() const {
- return static_cast<StringMapEntry<ValueTy>*>(*this->Ptr);
+};
+
+template <typename ValueTy>
+class StringMapKeyIterator
+ : public iterator_adaptor_base<StringMapKeyIterator<ValueTy>,
+ StringMapConstIterator<ValueTy>,
+ std::forward_iterator_tag, StringRef> {
+ using base = iterator_adaptor_base<StringMapKeyIterator<ValueTy>,
+ StringMapConstIterator<ValueTy>,
+ std::forward_iterator_tag, StringRef>;
+
+public:
+ StringMapKeyIterator() = default;
+
+ explicit StringMapKeyIterator(StringMapConstIterator<ValueTy> Iter)
+ : base(std::move(Iter)) {}
+
+ StringRef &operator*() {
+ Key = this->wrapped()->getKey();
+ return Key;
}
+
+private:
+ StringRef Key;
};
} // end namespace llvm
diff --git a/include/llvm/ADT/StringRef.h b/include/llvm/ADT/StringRef.h
index d80a848c44a1..ce48f6d3bad3 100644
--- a/include/llvm/ADT/StringRef.h
+++ b/include/llvm/ADT/StringRef.h
@@ -557,6 +557,14 @@ namespace llvm {
/// string is well-formed in the given radix.
bool getAsInteger(unsigned Radix, APInt &Result) const;
+ /// Parse the current string as an IEEE double-precision floating
+ /// point value. The string must be a well-formed double.
+ ///
+ /// If \p AllowInexact is false, the function will fail if the string
+ /// cannot be represented exactly. Otherwise, the function only fails
+ /// in case of an overflow or underflow.
+ bool getAsDouble(double &Result, bool AllowInexact = true) const;
+
/// @}
/// @name String Operations
/// @{
@@ -600,7 +608,7 @@ namespace llvm {
return drop_back(size() - N);
}
- /// Return a StringRef equal to 'this' but with only the first \p N
+ /// Return a StringRef equal to 'this' but with only the last \p N
/// elements remaining. If \p N is greater than the length of the
/// string, the entire string is returned.
LLVM_NODISCARD
diff --git a/include/llvm/ADT/Triple.h b/include/llvm/ADT/Triple.h
index d4130e1e85ae..e271075b7e2a 100644
--- a/include/llvm/ADT/Triple.h
+++ b/include/llvm/ADT/Triple.h
@@ -110,6 +110,7 @@ public:
ARMSubArch_v7m,
ARMSubArch_v7s,
ARMSubArch_v7k,
+ ARMSubArch_v7ve,
ARMSubArch_v6,
ARMSubArch_v6m,
ARMSubArch_v6k,
@@ -206,6 +207,7 @@ public:
COFF,
ELF,
MachO,
+ Wasm,
};
private:
@@ -558,7 +560,8 @@ public:
/// Tests whether the OS uses glibc.
bool isOSGlibc() const {
- return getOS() == Triple::Linux || getOS() == Triple::KFreeBSD;
+ return (getOS() == Triple::Linux || getOS() == Triple::KFreeBSD) &&
+ !isAndroid();
}
/// Tests whether the OS uses the ELF binary format.
@@ -576,6 +579,11 @@ public:
return getObjectFormat() == Triple::MachO;
}
+ /// Tests whether the OS uses the Wasm binary format.
+ bool isOSBinFormatWasm() const {
+ return getObjectFormat() == Triple::Wasm;
+ }
+
/// Tests whether the target is the PS4 CPU
bool isPS4CPU() const {
return getArch() == Triple::x86_64 &&
@@ -592,6 +600,19 @@ public:
/// Tests whether the target is Android
bool isAndroid() const { return getEnvironment() == Triple::Android; }
+ bool isAndroidVersionLT(unsigned Major) const {
+ assert(isAndroid() && "Not an Android triple!");
+
+ unsigned Env[3];
+ getEnvironmentVersion(Env[0], Env[1], Env[2]);
+
+ // 64-bit targets did not exist before API level 21 (Lollipop).
+ if (isArch64Bit() && Env[0] < 21)
+ Env[0] = 21;
+
+ return Env[0] < Major;
+ }
+
/// Tests whether the environment is musl-libc
bool isMusl() const {
return getEnvironment() == Triple::Musl ||
diff --git a/include/llvm/ADT/iterator.h b/include/llvm/ADT/iterator.h
index 6470e09db86c..28dcdf9613ef 100644
--- a/include/llvm/ADT/iterator.h
+++ b/include/llvm/ADT/iterator.h
@@ -10,6 +10,7 @@
#ifndef LLVM_ADT_ITERATOR_H
#define LLVM_ADT_ITERATOR_H
+#include "llvm/ADT/iterator_range.h"
#include <cstddef>
#include <iterator>
#include <type_traits>
@@ -91,6 +92,8 @@ protected:
public:
DerivedT operator+(DifferenceTypeT n) const {
+ static_assert(std::is_base_of<iterator_facade_base, DerivedT>::value,
+ "Must pass the derived type to this template!");
static_assert(
IsRandomAccess,
"The '+' operator is only defined for random access iterators.");
@@ -114,6 +117,8 @@ public:
}
DerivedT &operator++() {
+ static_assert(std::is_base_of<iterator_facade_base, DerivedT>::value,
+ "Must pass the derived type to this template!");
return static_cast<DerivedT *>(this)->operator+=(1);
}
DerivedT operator++(int) {
@@ -160,9 +165,15 @@ public:
return !static_cast<const DerivedT *>(this)->operator<(RHS);
}
+ PointerT operator->() { return &static_cast<DerivedT *>(this)->operator*(); }
PointerT operator->() const {
return &static_cast<const DerivedT *>(this)->operator*();
}
+ ReferenceProxy operator[](DifferenceTypeT n) {
+ static_assert(IsRandomAccess,
+ "Subscripting is only defined for random access iterators.");
+ return ReferenceProxy(static_cast<DerivedT *>(this)->operator+(n));
+ }
ReferenceProxy operator[](DifferenceTypeT n) const {
static_assert(IsRandomAccess,
"Subscripting is only defined for random access iterators.");
@@ -202,7 +213,10 @@ protected:
iterator_adaptor_base() = default;
- explicit iterator_adaptor_base(WrappedIteratorT u) : I(std::move(u)) {}
+ explicit iterator_adaptor_base(WrappedIteratorT u) : I(std::move(u)) {
+ static_assert(std::is_base_of<iterator_adaptor_base, DerivedT>::value,
+ "Must pass the derived type to this template!");
+ }
const WrappedIteratorT &wrapped() const { return I; }
@@ -283,6 +297,15 @@ struct pointee_iterator
T &operator*() const { return **this->I; }
};
+template <typename RangeT, typename WrappedIteratorT =
+ decltype(std::begin(std::declval<RangeT>()))>
+iterator_range<pointee_iterator<WrappedIteratorT>>
+make_pointee_range(RangeT &&Range) {
+ using PointeeIteratorT = pointee_iterator<WrappedIteratorT>;
+ return make_range(PointeeIteratorT(std::begin(std::forward<RangeT>(Range))),
+ PointeeIteratorT(std::end(std::forward<RangeT>(Range))));
+}
+
template <typename WrappedIteratorT,
typename T = decltype(&*std::declval<WrappedIteratorT>())>
class pointer_iterator
@@ -300,6 +323,15 @@ public:
const T &operator*() const { return Ptr = &*this->I; }
};
+template <typename RangeT, typename WrappedIteratorT =
+ decltype(std::begin(std::declval<RangeT>()))>
+iterator_range<pointer_iterator<WrappedIteratorT>>
+make_pointer_range(RangeT &&Range) {
+ using PointerIteratorT = pointer_iterator<WrappedIteratorT>;
+ return make_range(PointerIteratorT(std::begin(std::forward<RangeT>(Range))),
+ PointerIteratorT(std::end(std::forward<RangeT>(Range))));
+}
+
} // end namespace llvm
#endif // LLVM_ADT_ITERATOR_H
diff --git a/include/llvm/Analysis/AliasAnalysis.h b/include/llvm/Analysis/AliasAnalysis.h
index d8e50438e722..1b8b9751faa1 100644
--- a/include/llvm/Analysis/AliasAnalysis.h
+++ b/include/llvm/Analysis/AliasAnalysis.h
@@ -443,11 +443,7 @@ public:
/// getModRefInfo (for fences) - Return information about whether
/// a particular store modifies or reads the specified memory location.
- ModRefInfo getModRefInfo(const FenceInst *S, const MemoryLocation &Loc) {
- // Conservatively correct. (We could possibly be a bit smarter if
- // Loc is a alloca that doesn't escape.)
- return MRI_ModRef;
- }
+ ModRefInfo getModRefInfo(const FenceInst *S, const MemoryLocation &Loc);
/// getModRefInfo (for fences) - A convenience wrapper.
ModRefInfo getModRefInfo(const FenceInst *S, const Value *P, uint64_t Size) {
@@ -528,6 +524,14 @@ public:
/// Check whether or not an instruction may read or write the specified
/// memory location.
///
+ /// Note explicitly that getModRefInfo considers the effects of reading and
+ /// writing the memory location, and not the effect of ordering relative to
+ /// other instructions. Thus, a volatile load is considered to be Ref,
+ /// because it does not actually write memory, it just can't be reordered
+ /// relative to other volatiles (or removed). Atomic ordered loads/stores are
+ /// considered ModRef ATM because conservatively, the visible effect appears
+ /// as if memory was written, not just an ordering constraint.
+ ///
/// An instruction that doesn't read or write memory may be trivially LICM'd
/// for example.
///
diff --git a/include/llvm/Analysis/AliasSetTracker.h b/include/llvm/Analysis/AliasSetTracker.h
index 5d11b22c6eed..eac97501c759 100644
--- a/include/llvm/Analysis/AliasSetTracker.h
+++ b/include/llvm/Analysis/AliasSetTracker.h
@@ -121,7 +121,10 @@ class AliasSet : public ilist_node<AliasSet> {
AliasSet *Forward;
/// All instructions without a specific address in this alias set.
- std::vector<AssertingVH<Instruction> > UnknownInsts;
+ /// In rare cases this vector can have a null'ed out WeakVH
+ /// instances (can happen if some other loop pass deletes an
+ /// instruction in this list).
+ std::vector<WeakVH> UnknownInsts;
/// Number of nodes pointing to this AliasSet plus the number of AliasSets
/// forwarding to it.
@@ -171,7 +174,7 @@ class AliasSet : public ilist_node<AliasSet> {
Instruction *getUnknownInst(unsigned i) const {
assert(i < UnknownInsts.size());
- return UnknownInsts[i];
+ return cast_or_null<Instruction>(UnknownInsts[i]);
}
public:
diff --git a/include/llvm/Analysis/AssumptionCache.h b/include/llvm/Analysis/AssumptionCache.h
index 79287ed76f2e..f833f417c7dd 100644
--- a/include/llvm/Analysis/AssumptionCache.h
+++ b/include/llvm/Analysis/AssumptionCache.h
@@ -31,11 +31,10 @@ namespace llvm {
/// \brief A cache of @llvm.assume calls within a function.
///
/// This cache provides fast lookup of assumptions within a function by caching
-/// them and amortizing the cost of scanning for them across all queries. The
-/// cache is also conservatively self-updating so that it will never return
-/// incorrect results about a function even as the function is being mutated.
-/// However, flushing the cache and rebuilding it (or explicitly updating it)
-/// may allow it to discover new assumptions.
+/// them and amortizing the cost of scanning for them across all queries. Passes
+/// that create new assumptions are required to call registerAssumption() to
+/// register any new @llvm.assume calls that they create. Deletions of
+/// @llvm.assume calls do not require special handling.
class AssumptionCache {
/// \brief The function for which this cache is handling assumptions.
///
@@ -87,6 +86,13 @@ public:
/// its instructions.
AssumptionCache(Function &F) : F(F), Scanned(false) {}
+ /// This cache is designed to be self-updating and so it should never be
+ /// invalidated.
+ bool invalidate(Function &, const PreservedAnalyses &,
+ FunctionAnalysisManager::Invalidator &) {
+ return false;
+ }
+
/// \brief Add an @llvm.assume intrinsic to this function's cache.
///
/// The call passed in must be an instruction within this function and must
@@ -196,7 +202,10 @@ public:
AssumptionCacheTracker();
~AssumptionCacheTracker() override;
- void releaseMemory() override { AssumptionCaches.shrink_and_clear(); }
+ void releaseMemory() override {
+ verifyAnalysis();
+ AssumptionCaches.shrink_and_clear();
+ }
void verifyAnalysis() const override;
bool doFinalization(Module &) override {
diff --git a/include/llvm/Analysis/BasicAliasAnalysis.h b/include/llvm/Analysis/BasicAliasAnalysis.h
index addfffa01061..14e4bded264a 100644
--- a/include/llvm/Analysis/BasicAliasAnalysis.h
+++ b/include/llvm/Analysis/BasicAliasAnalysis.h
@@ -233,6 +233,24 @@ FunctionPass *createBasicAAWrapperPass();
/// populated to the best of our ability for a particular function when inside
/// of a \c ModulePass or a \c CallGraphSCCPass.
BasicAAResult createLegacyPMBasicAAResult(Pass &P, Function &F);
+
+/// This class is a functor to be used in legacy module or SCC passes for
+/// computing AA results for a function. We store the results in fields so that
+/// they live long enough to be queried, but we re-use them each time.
+class LegacyAARGetter {
+ Pass &P;
+ Optional<BasicAAResult> BAR;
+ Optional<AAResults> AAR;
+
+public:
+ LegacyAARGetter(Pass &P) : P(P) {}
+ AAResults &operator()(Function &F) {
+ BAR.emplace(createLegacyPMBasicAAResult(P, F));
+ AAR.emplace(createLegacyPMAAResults(P, F, *BAR));
+ return *AAR;
+ }
+};
+
}
#endif
diff --git a/include/llvm/Analysis/BlockFrequencyInfo.h b/include/llvm/Analysis/BlockFrequencyInfo.h
index 562041d11fa1..cbae01c9102f 100644
--- a/include/llvm/Analysis/BlockFrequencyInfo.h
+++ b/include/llvm/Analysis/BlockFrequencyInfo.h
@@ -45,6 +45,10 @@ public:
~BlockFrequencyInfo();
+ /// Handle invalidation explicitly.
+ bool invalidate(Function &F, const PreservedAnalyses &PA,
+ FunctionAnalysisManager::Invalidator &);
+
const Function *getFunction() const;
const BranchProbabilityInfo *getBPI() const;
void view() const;
@@ -69,6 +73,12 @@ public:
// Set the frequency of the given basic block.
void setBlockFreq(const BasicBlock *BB, uint64_t Freq);
+ /// Set the frequency of \p ReferenceBB to \p Freq and scale the frequencies
+ /// of the blocks in \p BlocksToScale such that their frequencies relative
+ /// to \p ReferenceBB remain unchanged.
+ void setBlockFreqAndScale(const BasicBlock *ReferenceBB, uint64_t Freq,
+ SmallPtrSetImpl<BasicBlock *> &BlocksToScale);
+
/// calculate - compute block frequency info for the given function.
void calculate(const Function &F, const BranchProbabilityInfo &BPI,
const LoopInfo &LI);
diff --git a/include/llvm/Analysis/BlockFrequencyInfoImpl.h b/include/llvm/Analysis/BlockFrequencyInfoImpl.h
index 3f4428d18740..e3d81fea49ea 100644
--- a/include/llvm/Analysis/BlockFrequencyInfoImpl.h
+++ b/include/llvm/Analysis/BlockFrequencyInfoImpl.h
@@ -1291,11 +1291,14 @@ struct BFIDOTGraphTraitsBase : public DefaultDOTGraphTraits {
}
std::string getNodeLabel(NodeRef Node, const BlockFrequencyInfoT *Graph,
- GVDAGType GType) {
+ GVDAGType GType, int layout_order = -1) {
std::string Result;
raw_string_ostream OS(Result);
- OS << Node->getName().str() << " : ";
+ if (layout_order != -1)
+ OS << Node->getName() << "[" << layout_order << "] : ";
+ else
+ OS << Node->getName() << " : ";
switch (GType) {
case GVDT_Fraction:
Graph->printBlockFreq(OS, Node);
diff --git a/include/llvm/Analysis/BranchProbabilityInfo.h b/include/llvm/Analysis/BranchProbabilityInfo.h
index 14b7a7f529f7..6a876679543d 100644
--- a/include/llvm/Analysis/BranchProbabilityInfo.h
+++ b/include/llvm/Analysis/BranchProbabilityInfo.h
@@ -164,6 +164,8 @@ private:
/// \brief Track the set of blocks that always lead to a cold call.
SmallPtrSet<const BasicBlock *, 16> PostDominatedByColdCall;
+ void updatePostDominatedByUnreachable(const BasicBlock *BB);
+ void updatePostDominatedByColdCall(const BasicBlock *BB);
bool calcUnreachableHeuristics(const BasicBlock *BB);
bool calcMetadataWeights(const BasicBlock *BB);
bool calcColdCallHeuristics(const BasicBlock *BB);
diff --git a/include/llvm/Analysis/CFGPrinter.h b/include/llvm/Analysis/CFGPrinter.h
index efaa9d6df8ea..5786769cc500 100644
--- a/include/llvm/Analysis/CFGPrinter.h
+++ b/include/llvm/Analysis/CFGPrinter.h
@@ -140,8 +140,7 @@ struct DOTGraphTraits<const Function*> : public DefaultDOTGraphTraits {
std::string Str;
raw_string_ostream OS(Str);
- SwitchInst::ConstCaseIt Case =
- SwitchInst::ConstCaseIt::fromSuccessorIndex(SI, SuccNo);
+ auto Case = *SwitchInst::ConstCaseIt::fromSuccessorIndex(SI, SuccNo);
OS << Case.getCaseValue()->getValue();
return OS.str();
}
diff --git a/include/llvm/Analysis/CGSCCPassManager.h b/include/llvm/Analysis/CGSCCPassManager.h
index 6fbe532112b2..398bbfb0c413 100644
--- a/include/llvm/Analysis/CGSCCPassManager.h
+++ b/include/llvm/Analysis/CGSCCPassManager.h
@@ -334,6 +334,7 @@ public:
InvalidSCCSet, nullptr, nullptr};
PreservedAnalyses PA = PreservedAnalyses::all();
+ CG.buildRefSCCs();
for (auto RCI = CG.postorder_ref_scc_begin(),
RCE = CG.postorder_ref_scc_end();
RCI != RCE;) {
diff --git a/include/llvm/Analysis/CallGraph.h b/include/llvm/Analysis/CallGraph.h
index 4ecbaa75ac75..ea85436ee580 100644
--- a/include/llvm/Analysis/CallGraph.h
+++ b/include/llvm/Analysis/CallGraph.h
@@ -272,7 +272,7 @@ public:
private:
friend class CallGraph;
- AssertingVH<Function> F;
+ Function *F;
std::vector<CallRecord> CalledFunctions;
diff --git a/include/llvm/Analysis/ConstantFolding.h b/include/llvm/Analysis/ConstantFolding.h
index 517842c8b0dc..ff6ca1959153 100644
--- a/include/llvm/Analysis/ConstantFolding.h
+++ b/include/llvm/Analysis/ConstantFolding.h
@@ -100,6 +100,12 @@ Constant *ConstantFoldExtractValueInstruction(Constant *Agg,
/// successful; if not, null is returned.
Constant *ConstantFoldExtractElementInstruction(Constant *Val, Constant *Idx);
+/// \brief Attempt to constant fold a shufflevector instruction with the
+/// specified operands and indices. The constant result is returned if
+/// successful; if not, null is returned.
+Constant *ConstantFoldShuffleVectorInstruction(Constant *V1, Constant *V2,
+ Constant *Mask);
+
/// ConstantFoldLoadFromConstPtr - Return the value that a load from C would
/// produce if it is constant and determinable. If this is not determinable,
/// return null.
diff --git a/include/llvm/Analysis/DominanceFrontier.h b/include/llvm/Analysis/DominanceFrontier.h
index b9667f801ed3..8cae63c3c869 100644
--- a/include/llvm/Analysis/DominanceFrontier.h
+++ b/include/llvm/Analysis/DominanceFrontier.h
@@ -141,6 +141,10 @@ public:
typedef DominanceFrontierBase<BasicBlock>::DomSetType DomSetType;
typedef DominanceFrontierBase<BasicBlock>::iterator iterator;
typedef DominanceFrontierBase<BasicBlock>::const_iterator const_iterator;
+
+ /// Handle invalidation explicitly.
+ bool invalidate(Function &F, const PreservedAnalyses &PA,
+ FunctionAnalysisManager::Invalidator &);
};
class DominanceFrontierWrapperPass : public FunctionPass {
diff --git a/include/llvm/Analysis/IndirectCallSiteVisitor.h b/include/llvm/Analysis/IndirectCallSiteVisitor.h
index 71a8cb886321..3c40cc0235cc 100644
--- a/include/llvm/Analysis/IndirectCallSiteVisitor.h
+++ b/include/llvm/Analysis/IndirectCallSiteVisitor.h
@@ -21,16 +21,8 @@ struct PGOIndirectCallSiteVisitor
PGOIndirectCallSiteVisitor() {}
void visitCallSite(CallSite CS) {
- if (CS.getCalledFunction() || !CS.getCalledValue())
- return;
- Instruction *I = CS.getInstruction();
- if (CallInst *CI = dyn_cast<CallInst>(I)) {
- if (CI->isInlineAsm())
- return;
- }
- if (isa<Constant>(CS.getCalledValue()))
- return;
- IndirectCallInsts.push_back(I);
+ if (CS.isIndirectCall())
+ IndirectCallInsts.push_back(CS.getInstruction());
}
};
diff --git a/include/llvm/Analysis/InlineCost.h b/include/llvm/Analysis/InlineCost.h
index 5e7b00261f63..17e5cb6db02d 100644
--- a/include/llvm/Analysis/InlineCost.h
+++ b/include/llvm/Analysis/InlineCost.h
@@ -21,6 +21,7 @@
namespace llvm {
class AssumptionCacheTracker;
+class BlockFrequencyInfo;
class CallSite;
class DataLayout;
class Function;
@@ -137,6 +138,9 @@ struct InlineParams {
/// Threshold to use when the callsite is considered hot.
Optional<int> HotCallSiteThreshold;
+
+ /// Threshold to use when the callsite is considered cold.
+ Optional<int> ColdCallSiteThreshold;
};
/// Generate the parameters to tune the inline cost analysis based only on the
@@ -171,6 +175,7 @@ InlineCost
getInlineCost(CallSite CS, const InlineParams &Params,
TargetTransformInfo &CalleeTTI,
std::function<AssumptionCache &(Function &)> &GetAssumptionCache,
+ Optional<function_ref<BlockFrequencyInfo &(Function &)>> GetBFI,
ProfileSummaryInfo *PSI);
/// \brief Get an InlineCost with the callee explicitly specified.
@@ -182,6 +187,7 @@ InlineCost
getInlineCost(CallSite CS, Function *Callee, const InlineParams &Params,
TargetTransformInfo &CalleeTTI,
std::function<AssumptionCache &(Function &)> &GetAssumptionCache,
+ Optional<function_ref<BlockFrequencyInfo &(Function &)>> GetBFI,
ProfileSummaryInfo *PSI);
/// \brief Minimal filter to detect invalid constructs for inlining.
diff --git a/include/llvm/Analysis/InstructionSimplify.h b/include/llvm/Analysis/InstructionSimplify.h
index 47d6118313cb..b829e995db05 100644
--- a/include/llvm/Analysis/InstructionSimplify.h
+++ b/include/llvm/Analysis/InstructionSimplify.h
@@ -42,6 +42,7 @@ namespace llvm {
class Instruction;
class DataLayout;
class FastMathFlags;
+ class OptimizationRemarkEmitter;
class TargetLibraryInfo;
class Type;
class Value;
@@ -246,6 +247,14 @@ namespace llvm {
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr);
+ /// Given operands for a ShuffleVectorInst, fold the result or return null.
+ Value *SimplifyShuffleVectorInst(Value *Op0, Value *Op1, Constant *Mask,
+ Type *RetTy, const DataLayout &DL,
+ const TargetLibraryInfo *TLI = nullptr,
+ const DominatorTree *DT = nullptr,
+ AssumptionCache *AC = nullptr,
+ const Instruction *CxtI = nullptr);
+
//=== Helper functions for higher up the class hierarchy.
@@ -296,7 +305,8 @@ namespace llvm {
Value *SimplifyInstruction(Instruction *I, const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
- AssumptionCache *AC = nullptr);
+ AssumptionCache *AC = nullptr,
+ OptimizationRemarkEmitter *ORE = nullptr);
/// Replace all uses of 'I' with 'SimpleV' and simplify the uses recursively.
///
diff --git a/include/llvm/Analysis/LazyBlockFrequencyInfo.h b/include/llvm/Analysis/LazyBlockFrequencyInfo.h
index 5a02b9dce463..71ce0842f6a9 100644
--- a/include/llvm/Analysis/LazyBlockFrequencyInfo.h
+++ b/include/llvm/Analysis/LazyBlockFrequencyInfo.h
@@ -9,7 +9,7 @@
//
// This is an alternative analysis pass to BlockFrequencyInfoWrapperPass. The
// difference is that with this pass the block frequencies are not computed when
-// the analysis pass is executed but rather when the BFI results is explicitly
+// the analysis pass is executed but rather when the BFI result is explicitly
// requested by the analysis client.
//
//===----------------------------------------------------------------------===//
@@ -27,10 +27,58 @@ class BranchProbabilityInfo;
class Function;
class LoopInfo;
+/// Wraps a BFI to allow lazy computation of the block frequencies.
+///
+/// A pass that only conditionally uses BFI can uncondtionally require the
+/// analysis without paying for the overhead if BFI doesn't end up being used.
+template <typename FunctionT, typename BranchProbabilityInfoPassT,
+ typename LoopInfoT, typename BlockFrequencyInfoT>
+class LazyBlockFrequencyInfo {
+public:
+ LazyBlockFrequencyInfo()
+ : Calculated(false), F(nullptr), BPIPass(nullptr), LI(nullptr) {}
+
+ /// Set up the per-function input.
+ void setAnalysis(const FunctionT *F, BranchProbabilityInfoPassT *BPIPass,
+ const LoopInfoT *LI) {
+ this->F = F;
+ this->BPIPass = BPIPass;
+ this->LI = LI;
+ }
+
+ /// Retrieve the BFI with the block frequencies computed.
+ BlockFrequencyInfoT &getCalculated() {
+ if (!Calculated) {
+ assert(F && BPIPass && LI && "call setAnalysis");
+ BFI.calculate(
+ *F, BPIPassTrait<BranchProbabilityInfoPassT>::getBPI(BPIPass), *LI);
+ Calculated = true;
+ }
+ return BFI;
+ }
+
+ const BlockFrequencyInfoT &getCalculated() const {
+ return const_cast<LazyBlockFrequencyInfo *>(this)->getCalculated();
+ }
+
+ void releaseMemory() {
+ BFI.releaseMemory();
+ Calculated = false;
+ setAnalysis(nullptr, nullptr, nullptr);
+ }
+
+private:
+ BlockFrequencyInfoT BFI;
+ bool Calculated;
+ const FunctionT *F;
+ BranchProbabilityInfoPassT *BPIPass;
+ const LoopInfoT *LI;
+};
+
/// \brief This is an alternative analysis pass to
/// BlockFrequencyInfoWrapperPass. The difference is that with this pass the
/// block frequencies are not computed when the analysis pass is executed but
-/// rather when the BFI results is explicitly requested by the analysis client.
+/// rather when the BFI result is explicitly requested by the analysis client.
///
/// There are some additional requirements for any client pass that wants to use
/// the analysis:
@@ -49,54 +97,12 @@ class LoopInfo;
///
/// Note that it is expected that we wouldn't need this functionality for the
/// new PM since with the new PM, analyses are executed on demand.
-class LazyBlockFrequencyInfoPass : public FunctionPass {
-
- /// Wraps a BFI to allow lazy computation of the block frequencies.
- ///
- /// A pass that only conditionally uses BFI can uncondtionally require the
- /// analysis without paying for the overhead if BFI doesn't end up being used.
- class LazyBlockFrequencyInfo {
- public:
- LazyBlockFrequencyInfo()
- : Calculated(false), F(nullptr), BPIPass(nullptr), LI(nullptr) {}
-
- /// Set up the per-function input.
- void setAnalysis(const Function *F, LazyBranchProbabilityInfoPass *BPIPass,
- const LoopInfo *LI) {
- this->F = F;
- this->BPIPass = BPIPass;
- this->LI = LI;
- }
- /// Retrieve the BFI with the block frequencies computed.
- BlockFrequencyInfo &getCalculated() {
- if (!Calculated) {
- assert(F && BPIPass && LI && "call setAnalysis");
- BFI.calculate(*F, BPIPass->getBPI(), *LI);
- Calculated = true;
- }
- return BFI;
- }
-
- const BlockFrequencyInfo &getCalculated() const {
- return const_cast<LazyBlockFrequencyInfo *>(this)->getCalculated();
- }
-
- void releaseMemory() {
- BFI.releaseMemory();
- Calculated = false;
- setAnalysis(nullptr, nullptr, nullptr);
- }
-
- private:
- BlockFrequencyInfo BFI;
- bool Calculated;
- const Function *F;
- LazyBranchProbabilityInfoPass *BPIPass;
- const LoopInfo *LI;
- };
-
- LazyBlockFrequencyInfo LBFI;
+class LazyBlockFrequencyInfoPass : public FunctionPass {
+private:
+ LazyBlockFrequencyInfo<Function, LazyBranchProbabilityInfoPass, LoopInfo,
+ BlockFrequencyInfo>
+ LBFI;
public:
static char ID;
diff --git a/include/llvm/Analysis/LazyBranchProbabilityInfo.h b/include/llvm/Analysis/LazyBranchProbabilityInfo.h
index c76fa1e819ae..067d7ebfd1f5 100644
--- a/include/llvm/Analysis/LazyBranchProbabilityInfo.h
+++ b/include/llvm/Analysis/LazyBranchProbabilityInfo.h
@@ -105,5 +105,17 @@ public:
/// \brief Helper for client passes to initialize dependent passes for LBPI.
void initializeLazyBPIPassPass(PassRegistry &Registry);
+
+/// \brief Simple trait class that provides a mapping between BPI passes and the
+/// corresponding BPInfo.
+template <typename PassT> struct BPIPassTrait {
+ static PassT &getBPI(PassT *P) { return *P; }
+};
+
+template <> struct BPIPassTrait<LazyBranchProbabilityInfoPass> {
+ static BranchProbabilityInfo &getBPI(LazyBranchProbabilityInfoPass *P) {
+ return P->getBPI();
+ }
+};
}
#endif
diff --git a/include/llvm/Analysis/LazyCallGraph.h b/include/llvm/Analysis/LazyCallGraph.h
index bca0aebe2eef..ad7f5c80549f 100644
--- a/include/llvm/Analysis/LazyCallGraph.h
+++ b/include/llvm/Analysis/LazyCallGraph.h
@@ -106,6 +106,7 @@ class raw_ostream;
class LazyCallGraph {
public:
class Node;
+ class EdgeSequence;
class SCC;
class RefSCC;
class edge_iterator;
@@ -121,16 +122,6 @@ public:
/// inherently reference edges, and so the reference graph forms a superset
/// of the formal call graph.
///
- /// Furthermore, edges also may point to raw \c Function objects when those
- /// functions have not been scanned and incorporated into the graph (yet).
- /// This is one of the primary ways in which the graph can be lazy. When
- /// functions are scanned and fully incorporated into the graph, all of the
- /// edges referencing them are updated to point to the graph \c Node objects
- /// instead of to the raw \c Function objects. This class even provides
- /// methods to trigger this scan on-demand by attempting to get the target
- /// node of the graph and providing a reference back to the graph in order to
- /// lazily build it if necessary.
- ///
/// All of these forms of edges are fundamentally represented as outgoing
/// edges. The edges are stored in the source node and point at the target
/// node. This allows the edge structure itself to be a very compact data
@@ -141,7 +132,6 @@ public:
enum Kind : bool { Ref = false, Call = true };
Edge();
- explicit Edge(Function &F, Kind K);
explicit Edge(Node &N, Kind K);
/// Test whether the edge is null.
@@ -158,197 +148,251 @@ public:
/// This requires that the edge is not null.
bool isCall() const;
- /// Get the function referenced by this edge.
- ///
- /// This requires that the edge is not null, but will succeed whether we
- /// have built a graph node for the function yet or not.
- Function &getFunction() const;
-
- /// Get the call graph node referenced by this edge if one exists.
+ /// Get the call graph node referenced by this edge.
///
- /// This requires that the edge is not null. If we have built a graph node
- /// for the function this edge points to, this will return that node,
- /// otherwise it will return null.
- Node *getNode() const;
+ /// This requires that the edge is not null.
+ Node &getNode() const;
- /// Get the call graph node for this edge, building it if necessary.
+ /// Get the function referenced by this edge.
///
- /// This requires that the edge is not null. If we have not yet built
- /// a graph node for the function this edge points to, this will first ask
- /// the graph to build that node, inserting it into all the relevant
- /// structures.
- Node &getNode(LazyCallGraph &G);
+ /// This requires that the edge is not null.
+ Function &getFunction() const;
private:
- friend class LazyCallGraph::Node;
+ friend class LazyCallGraph::EdgeSequence;
friend class LazyCallGraph::RefSCC;
- PointerIntPair<PointerUnion<Function *, Node *>, 1, Kind> Value;
+ PointerIntPair<Node *, 1, Kind> Value;
void setKind(Kind K) { Value.setInt(K); }
};
- typedef SmallVector<Edge, 4> EdgeVectorT;
- typedef SmallVectorImpl<Edge> EdgeVectorImplT;
-
- /// A node in the call graph.
+ /// The edge sequence object.
///
- /// This represents a single node. It's primary roles are to cache the list of
- /// callees, de-duplicate and provide fast testing of whether a function is
- /// a callee, and facilitate iteration of child nodes in the graph.
- class Node {
+ /// This typically exists entirely within the node but is exposed as
+ /// a separate type because a node doesn't initially have edges. An explicit
+ /// population step is required to produce this sequence at first and it is
+ /// then cached in the node. It is also used to represent edges entering the
+ /// graph from outside the module to model the graph's roots.
+ ///
+ /// The sequence itself both iterable and indexable. The indexes remain
+ /// stable even as the sequence mutates (including removal).
+ class EdgeSequence {
friend class LazyCallGraph;
- friend class LazyCallGraph::SCC;
+ friend class LazyCallGraph::Node;
friend class LazyCallGraph::RefSCC;
- LazyCallGraph *G;
- Function &F;
+ typedef SmallVector<Edge, 4> VectorT;
+ typedef SmallVectorImpl<Edge> VectorImplT;
- // We provide for the DFS numbering and Tarjan walk lowlink numbers to be
- // stored directly within the node. These are both '-1' when nodes are part
- // of an SCC (or RefSCC), or '0' when not yet reached in a DFS walk.
- int DFSNumber;
- int LowLink;
+ public:
+ /// An iterator used for the edges to both entry nodes and child nodes.
+ class iterator
+ : public iterator_adaptor_base<iterator, VectorImplT::iterator,
+ std::forward_iterator_tag> {
+ friend class LazyCallGraph;
+ friend class LazyCallGraph::Node;
+
+ VectorImplT::iterator E;
+
+ // Build the iterator for a specific position in the edge list.
+ iterator(VectorImplT::iterator BaseI, VectorImplT::iterator E)
+ : iterator_adaptor_base(BaseI), E(E) {
+ while (I != E && !*I)
+ ++I;
+ }
- mutable EdgeVectorT Edges;
- DenseMap<Function *, int> EdgeIndexMap;
+ public:
+ iterator() {}
- /// Basic constructor implements the scanning of F into Edges and
- /// EdgeIndexMap.
- Node(LazyCallGraph &G, Function &F);
+ using iterator_adaptor_base::operator++;
+ iterator &operator++() {
+ do {
+ ++I;
+ } while (I != E && !*I);
+ return *this;
+ }
+ };
- /// Internal helper to insert an edge to a function.
- void insertEdgeInternal(Function &ChildF, Edge::Kind EK);
+ /// An iterator over specifically call edges.
+ ///
+ /// This has the same iteration properties as the \c iterator, but
+ /// restricts itself to edges which represent actual calls.
+ class call_iterator
+ : public iterator_adaptor_base<call_iterator, VectorImplT::iterator,
+ std::forward_iterator_tag> {
+ friend class LazyCallGraph;
+ friend class LazyCallGraph::Node;
+
+ VectorImplT::iterator E;
+
+ /// Advance the iterator to the next valid, call edge.
+ void advanceToNextEdge() {
+ while (I != E && (!*I || !I->isCall()))
+ ++I;
+ }
- /// Internal helper to insert an edge to a node.
- void insertEdgeInternal(Node &ChildN, Edge::Kind EK);
+ // Build the iterator for a specific position in the edge list.
+ call_iterator(VectorImplT::iterator BaseI, VectorImplT::iterator E)
+ : iterator_adaptor_base(BaseI), E(E) {
+ advanceToNextEdge();
+ }
- /// Internal helper to change an edge kind.
- void setEdgeKind(Function &ChildF, Edge::Kind EK);
+ public:
+ call_iterator() {}
- /// Internal helper to remove the edge to the given function.
- void removeEdgeInternal(Function &ChildF);
+ using iterator_adaptor_base::operator++;
+ call_iterator &operator++() {
+ ++I;
+ advanceToNextEdge();
+ return *this;
+ }
+ };
- void clear() {
- Edges.clear();
- EdgeIndexMap.clear();
- }
+ iterator begin() { return iterator(Edges.begin(), Edges.end()); }
+ iterator end() { return iterator(Edges.end(), Edges.end()); }
- /// Print the name of this node's function.
- friend raw_ostream &operator<<(raw_ostream &OS, const Node &N) {
- return OS << N.F.getName();
+ Edge &operator[](int i) { return Edges[i]; }
+ Edge &operator[](Node &N) {
+ assert(EdgeIndexMap.find(&N) != EdgeIndexMap.end() && "No such edge!");
+ return Edges[EdgeIndexMap.find(&N)->second];
}
-
- /// Dump the name of this node's function to stderr.
- void dump() const;
-
- public:
- LazyCallGraph &getGraph() const { return *G; }
-
- Function &getFunction() const { return F; }
-
- edge_iterator begin() const {
- return edge_iterator(Edges.begin(), Edges.end());
+ Edge *lookup(Node &N) {
+ auto EI = EdgeIndexMap.find(&N);
+ return EI != EdgeIndexMap.end() ? &Edges[EI->second] : nullptr;
}
- edge_iterator end() const { return edge_iterator(Edges.end(), Edges.end()); }
- const Edge &operator[](int i) const { return Edges[i]; }
- const Edge &operator[](Function &F) const {
- assert(EdgeIndexMap.find(&F) != EdgeIndexMap.end() && "No such edge!");
- return Edges[EdgeIndexMap.find(&F)->second];
+ call_iterator call_begin() {
+ return call_iterator(Edges.begin(), Edges.end());
}
- const Edge &operator[](Node &N) const { return (*this)[N.getFunction()]; }
+ call_iterator call_end() { return call_iterator(Edges.end(), Edges.end()); }
- const Edge *lookup(Function &F) const {
- auto EI = EdgeIndexMap.find(&F);
- return EI != EdgeIndexMap.end() ? &Edges[EI->second] : nullptr;
+ iterator_range<call_iterator> calls() {
+ return make_range(call_begin(), call_end());
}
- call_edge_iterator call_begin() const {
- return call_edge_iterator(Edges.begin(), Edges.end());
- }
- call_edge_iterator call_end() const {
- return call_edge_iterator(Edges.end(), Edges.end());
- }
+ bool empty() {
+ for (auto &E : Edges)
+ if (E)
+ return false;
- iterator_range<call_edge_iterator> calls() const {
- return make_range(call_begin(), call_end());
+ return true;
}
- /// Equality is defined as address equality.
- bool operator==(const Node &N) const { return this == &N; }
- bool operator!=(const Node &N) const { return !operator==(N); }
- };
+ private:
+ VectorT Edges;
+ DenseMap<Node *, int> EdgeIndexMap;
- /// A lazy iterator used for both the entry nodes and child nodes.
- ///
- /// When this iterator is dereferenced, if not yet available, a function will
- /// be scanned for "calls" or uses of functions and its child information
- /// will be constructed. All of these results are accumulated and cached in
- /// the graph.
- class edge_iterator
- : public iterator_adaptor_base<edge_iterator, EdgeVectorImplT::iterator,
- std::forward_iterator_tag> {
- friend class LazyCallGraph;
- friend class LazyCallGraph::Node;
+ EdgeSequence() = default;
- EdgeVectorImplT::iterator E;
+ /// Internal helper to insert an edge to a node.
+ void insertEdgeInternal(Node &ChildN, Edge::Kind EK);
- // Build the iterator for a specific position in the edge list.
- edge_iterator(EdgeVectorImplT::iterator BaseI,
- EdgeVectorImplT::iterator E)
- : iterator_adaptor_base(BaseI), E(E) {
- while (I != E && !*I)
- ++I;
- }
+ /// Internal helper to change an edge kind.
+ void setEdgeKind(Node &ChildN, Edge::Kind EK);
- public:
- edge_iterator() {}
+ /// Internal helper to remove the edge to the given function.
+ bool removeEdgeInternal(Node &ChildN);
- using iterator_adaptor_base::operator++;
- edge_iterator &operator++() {
- do {
- ++I;
- } while (I != E && !*I);
- return *this;
- }
+ /// Internal helper to replace an edge key with a new one.
+ ///
+ /// This should be used when the function for a particular node in the
+ /// graph gets replaced and we are updating all of the edges to that node
+ /// to use the new function as the key.
+ void replaceEdgeKey(Function &OldTarget, Function &NewTarget);
};
- /// A lazy iterator over specifically call edges.
+ /// A node in the call graph.
+ ///
+ /// This represents a single node. It's primary roles are to cache the list of
+ /// callees, de-duplicate and provide fast testing of whether a function is
+ /// a callee, and facilitate iteration of child nodes in the graph.
///
- /// This has the same iteration properties as the \c edge_iterator, but
- /// restricts itself to edges which represent actual calls.
- class call_edge_iterator
- : public iterator_adaptor_base<call_edge_iterator,
- EdgeVectorImplT::iterator,
- std::forward_iterator_tag> {
+ /// The node works much like an optional in order to lazily populate the
+ /// edges of each node. Until populated, there are no edges. Once populated,
+ /// you can access the edges by dereferencing the node or using the `->`
+ /// operator as if the node was an `Optional<EdgeSequence>`.
+ class Node {
friend class LazyCallGraph;
- friend class LazyCallGraph::Node;
+ friend class LazyCallGraph::RefSCC;
- EdgeVectorImplT::iterator E;
+ public:
+ LazyCallGraph &getGraph() const { return *G; }
- /// Advance the iterator to the next valid, call edge.
- void advanceToNextEdge() {
- while (I != E && (!*I || !I->isCall()))
- ++I;
+ Function &getFunction() const { return *F; }
+
+ StringRef getName() const { return F->getName(); }
+
+ /// Equality is defined as address equality.
+ bool operator==(const Node &N) const { return this == &N; }
+ bool operator!=(const Node &N) const { return !operator==(N); }
+
+ /// Tests whether the node has been populated with edges.
+ operator bool() const { return Edges.hasValue(); }
+
+ // We allow accessing the edges by dereferencing or using the arrow
+ // operator, essentially wrapping the internal optional.
+ EdgeSequence &operator*() const {
+ // Rip const off because the node itself isn't changing here.
+ return const_cast<EdgeSequence &>(*Edges);
}
+ EdgeSequence *operator->() const { return &**this; }
- // Build the iterator for a specific position in the edge list.
- call_edge_iterator(EdgeVectorImplT::iterator BaseI,
- EdgeVectorImplT::iterator E)
- : iterator_adaptor_base(BaseI), E(E) {
- advanceToNextEdge();
+ /// Populate the edges of this node if necessary.
+ ///
+ /// The first time this is called it will populate the edges for this node
+ /// in the graph. It does this by scanning the underlying function, so once
+ /// this is done, any changes to that function must be explicitly reflected
+ /// in updates to the graph.
+ ///
+ /// \returns the populated \c EdgeSequence to simplify walking it.
+ ///
+ /// This will not update or re-scan anything if called repeatedly. Instead,
+ /// the edge sequence is cached and returned immediately on subsequent
+ /// calls.
+ EdgeSequence &populate() {
+ if (Edges)
+ return *Edges;
+
+ return populateSlow();
}
- public:
- call_edge_iterator() {}
+ private:
+ LazyCallGraph *G;
+ Function *F;
- using iterator_adaptor_base::operator++;
- call_edge_iterator &operator++() {
- ++I;
- advanceToNextEdge();
- return *this;
+ // We provide for the DFS numbering and Tarjan walk lowlink numbers to be
+ // stored directly within the node. These are both '-1' when nodes are part
+ // of an SCC (or RefSCC), or '0' when not yet reached in a DFS walk.
+ int DFSNumber;
+ int LowLink;
+
+ Optional<EdgeSequence> Edges;
+
+ /// Basic constructor implements the scanning of F into Edges and
+ /// EdgeIndexMap.
+ Node(LazyCallGraph &G, Function &F)
+ : G(&G), F(&F), DFSNumber(0), LowLink(0) {}
+
+ /// Implementation of the scan when populating.
+ EdgeSequence &populateSlow();
+
+ /// Internal helper to directly replace the function with a new one.
+ ///
+ /// This is used to facilitate tranfsormations which need to replace the
+ /// formal Function object but directly move the body and users from one to
+ /// the other.
+ void replaceFunction(Function &NewF);
+
+ void clear() { Edges.reset(); }
+
+ /// Print the name of this node's function.
+ friend raw_ostream &operator<<(raw_ostream &OS, const Node &N) {
+ return OS << N.F->getName();
}
+
+ /// Dump the name of this node's function to stderr.
+ void dump() const;
};
/// An SCC of the call graph.
@@ -789,19 +833,26 @@ public:
/// already existing edges.
void insertTrivialRefEdge(Node &SourceN, Node &TargetN);
+ /// Directly replace a node's function with a new function.
+ ///
+ /// This should be used when moving the body and users of a function to
+ /// a new formal function object but not otherwise changing the call graph
+ /// structure in any way.
+ ///
+ /// It requires that the old function in the provided node have zero uses
+ /// and the new function must have calls and references to it establishing
+ /// an equivalent graph.
+ void replaceNodeFunction(Node &N, Function &NewF);
+
///@}
};
/// A post-order depth-first RefSCC iterator over the call graph.
///
- /// This iterator triggers the Tarjan DFS-based formation of the RefSCC (and
- /// SCC) DAG for the call graph, walking it lazily in depth-first post-order.
- /// That is, it always visits RefSCCs for the target of a reference edge
- /// prior to visiting the RefSCC for a source of the edge (when they are in
- /// different RefSCCs).
- ///
- /// When forming each RefSCC, the call edges within it are used to form SCCs
- /// within it, so iterating this also controls the lazy formation of SCCs.
+ /// This iterator walks the cached post-order sequence of RefSCCs. However,
+ /// it trades stability for flexibility. It is restricted to a forward
+ /// iterator but will survive mutations which insert new RefSCCs and continue
+ /// to point to the same RefSCC even if it moves in the post-order sequence.
class postorder_ref_scc_iterator
: public iterator_facade_base<postorder_ref_scc_iterator,
std::forward_iterator_tag, RefSCC> {
@@ -825,12 +876,9 @@ public:
/// populating it if necessary.
static RefSCC *getRC(LazyCallGraph &G, int Index) {
if (Index == (int)G.PostOrderRefSCCs.size())
- if (!G.buildNextRefSCCInPostOrder())
- // We're at the end.
- return nullptr;
+ // We're at the end.
+ return nullptr;
- assert(Index < (int)G.PostOrderRefSCCs.size() &&
- "Built the next post-order RefSCC without growing list!");
return G.PostOrderRefSCCs[Index];
}
@@ -859,17 +907,21 @@ public:
LazyCallGraph(LazyCallGraph &&G);
LazyCallGraph &operator=(LazyCallGraph &&RHS);
- edge_iterator begin() {
- return edge_iterator(EntryEdges.begin(), EntryEdges.end());
- }
- edge_iterator end() {
- return edge_iterator(EntryEdges.end(), EntryEdges.end());
- }
+ EdgeSequence::iterator begin() { return EntryEdges.begin(); }
+ EdgeSequence::iterator end() { return EntryEdges.end(); }
+
+ void buildRefSCCs();
postorder_ref_scc_iterator postorder_ref_scc_begin() {
+ if (!EntryEdges.empty())
+ assert(!PostOrderRefSCCs.empty() &&
+ "Must form RefSCCs before iterating them!");
return postorder_ref_scc_iterator(*this);
}
postorder_ref_scc_iterator postorder_ref_scc_end() {
+ if (!EntryEdges.empty())
+ assert(!PostOrderRefSCCs.empty() &&
+ "Must form RefSCCs before iterating them!");
return postorder_ref_scc_iterator(*this,
postorder_ref_scc_iterator::IsAtEndT());
}
@@ -920,19 +972,19 @@ public:
/// below.
/// Update the call graph after inserting a new edge.
- void insertEdge(Node &Caller, Function &Callee, Edge::Kind EK);
+ void insertEdge(Node &SourceN, Node &TargetN, Edge::Kind EK);
/// Update the call graph after inserting a new edge.
- void insertEdge(Function &Caller, Function &Callee, Edge::Kind EK) {
- return insertEdge(get(Caller), Callee, EK);
+ void insertEdge(Function &Source, Function &Target, Edge::Kind EK) {
+ return insertEdge(get(Source), get(Target), EK);
}
/// Update the call graph after deleting an edge.
- void removeEdge(Node &Caller, Function &Callee);
+ void removeEdge(Node &SourceN, Node &TargetN);
/// Update the call graph after deleting an edge.
- void removeEdge(Function &Caller, Function &Callee) {
- return removeEdge(get(Caller), Callee);
+ void removeEdge(Function &Source, Function &Target) {
+ return removeEdge(get(Source), get(Target));
}
///@}
@@ -1013,14 +1065,11 @@ private:
/// Maps function->node for fast lookup.
DenseMap<const Function *, Node *> NodeMap;
- /// The entry nodes to the graph.
+ /// The entry edges into the graph.
///
- /// These nodes are reachable through "external" means. Put another way, they
+ /// These edges are from "external" sources. Put another way, they
/// escape at the module scope.
- EdgeVectorT EntryEdges;
-
- /// Map of the entry nodes in the graph to their indices in \c EntryEdges.
- DenseMap<Function *, int> EntryIndexMap;
+ EdgeSequence EntryEdges;
/// Allocator that holds all the call graph SCCs.
SpecificBumpPtrAllocator<SCC> SCCBPA;
@@ -1045,18 +1094,6 @@ private:
/// These are all of the RefSCCs which have no children.
SmallVector<RefSCC *, 4> LeafRefSCCs;
- /// Stack of nodes in the DFS walk.
- SmallVector<std::pair<Node *, edge_iterator>, 4> DFSStack;
-
- /// Set of entry nodes not-yet-processed into RefSCCs.
- SmallVector<Function *, 4> RefSCCEntryNodes;
-
- /// Stack of nodes the DFS has walked but not yet put into a RefSCC.
- SmallVector<Node *, 4> PendingRefSCCStack;
-
- /// Counter for the next DFS number to assign.
- int NextDFSNumber;
-
/// Helper to insert a new function, with an already looked-up entry in
/// the NodeMap.
Node &insertInto(Function &F, Node *&MappedN);
@@ -1078,6 +1115,23 @@ private:
return new (RefSCCBPA.Allocate()) RefSCC(std::forward<Ts>(Args)...);
}
+ /// Common logic for building SCCs from a sequence of roots.
+ ///
+ /// This is a very generic implementation of the depth-first walk and SCC
+ /// formation algorithm. It uses a generic sequence of roots and generic
+ /// callbacks for each step. This is designed to be used to implement both
+ /// the RefSCC formation and SCC formation with shared logic.
+ ///
+ /// Currently this is a relatively naive implementation of Tarjan's DFS
+ /// algorithm to form the SCCs.
+ ///
+ /// FIXME: We should consider newer variants such as Nuutila.
+ template <typename RootsT, typename GetBeginT, typename GetEndT,
+ typename GetNodeT, typename FormSCCCallbackT>
+ static void buildGenericSCCs(RootsT &&Roots, GetBeginT &&GetBegin,
+ GetEndT &&GetEnd, GetNodeT &&GetNode,
+ FormSCCCallbackT &&FormSCC);
+
/// Build the SCCs for a RefSCC out of a list of nodes.
void buildSCCs(RefSCC &RC, node_stack_range Nodes);
@@ -1098,22 +1152,12 @@ private:
"Index does not point back at RC!");
return IndexIt->second;
}
-
- /// Builds the next node in the post-order RefSCC walk of the call graph and
- /// appends it to the \c PostOrderRefSCCs vector.
- ///
- /// Returns true if a new RefSCC was successfully constructed, and false if
- /// there are no more RefSCCs to build in the graph.
- bool buildNextRefSCCInPostOrder();
};
inline LazyCallGraph::Edge::Edge() : Value() {}
-inline LazyCallGraph::Edge::Edge(Function &F, Kind K) : Value(&F, K) {}
inline LazyCallGraph::Edge::Edge(Node &N, Kind K) : Value(&N, K) {}
-inline LazyCallGraph::Edge::operator bool() const {
- return !Value.getPointer().isNull();
-}
+inline LazyCallGraph::Edge::operator bool() const { return Value.getPointer(); }
inline LazyCallGraph::Edge::Kind LazyCallGraph::Edge::getKind() const {
assert(*this && "Queried a null edge!");
@@ -1125,51 +1169,32 @@ inline bool LazyCallGraph::Edge::isCall() const {
return getKind() == Call;
}
-inline Function &LazyCallGraph::Edge::getFunction() const {
+inline LazyCallGraph::Node &LazyCallGraph::Edge::getNode() const {
assert(*this && "Queried a null edge!");
- auto P = Value.getPointer();
- if (auto *F = P.dyn_cast<Function *>())
- return *F;
-
- return P.get<Node *>()->getFunction();
+ return *Value.getPointer();
}
-inline LazyCallGraph::Node *LazyCallGraph::Edge::getNode() const {
- assert(*this && "Queried a null edge!");
- auto P = Value.getPointer();
- if (auto *N = P.dyn_cast<Node *>())
- return N;
-
- return nullptr;
-}
-
-inline LazyCallGraph::Node &LazyCallGraph::Edge::getNode(LazyCallGraph &G) {
+inline Function &LazyCallGraph::Edge::getFunction() const {
assert(*this && "Queried a null edge!");
- auto P = Value.getPointer();
- if (auto *N = P.dyn_cast<Node *>())
- return *N;
-
- Node &N = G.get(*P.get<Function *>());
- Value.setPointer(&N);
- return N;
+ return getNode().getFunction();
}
// Provide GraphTraits specializations for call graphs.
template <> struct GraphTraits<LazyCallGraph::Node *> {
typedef LazyCallGraph::Node *NodeRef;
- typedef LazyCallGraph::edge_iterator ChildIteratorType;
+ typedef LazyCallGraph::EdgeSequence::iterator ChildIteratorType;
static NodeRef getEntryNode(NodeRef N) { return N; }
- static ChildIteratorType child_begin(NodeRef N) { return N->begin(); }
- static ChildIteratorType child_end(NodeRef N) { return N->end(); }
+ static ChildIteratorType child_begin(NodeRef N) { return (*N)->begin(); }
+ static ChildIteratorType child_end(NodeRef N) { return (*N)->end(); }
};
template <> struct GraphTraits<LazyCallGraph *> {
typedef LazyCallGraph::Node *NodeRef;
- typedef LazyCallGraph::edge_iterator ChildIteratorType;
+ typedef LazyCallGraph::EdgeSequence::iterator ChildIteratorType;
static NodeRef getEntryNode(NodeRef N) { return N; }
- static ChildIteratorType child_begin(NodeRef N) { return N->begin(); }
- static ChildIteratorType child_end(NodeRef N) { return N->end(); }
+ static ChildIteratorType child_begin(NodeRef N) { return (*N)->begin(); }
+ static ChildIteratorType child_end(NodeRef N) { return (*N)->end(); }
};
/// An analysis pass which computes the call graph for a module.
diff --git a/include/llvm/Analysis/LazyValueInfo.h b/include/llvm/Analysis/LazyValueInfo.h
index 610791023a7d..49e088e533dc 100644
--- a/include/llvm/Analysis/LazyValueInfo.h
+++ b/include/llvm/Analysis/LazyValueInfo.h
@@ -32,6 +32,7 @@ namespace llvm {
class LazyValueInfo {
friend class LazyValueInfoWrapperPass;
AssumptionCache *AC = nullptr;
+ const DataLayout *DL = nullptr;
class TargetLibraryInfo *TLI = nullptr;
DominatorTree *DT = nullptr;
void *PImpl = nullptr;
@@ -40,16 +41,17 @@ class LazyValueInfo {
public:
~LazyValueInfo();
LazyValueInfo() {}
- LazyValueInfo(AssumptionCache *AC_, TargetLibraryInfo *TLI_,
+ LazyValueInfo(AssumptionCache *AC_, const DataLayout *DL_, TargetLibraryInfo *TLI_,
DominatorTree *DT_)
- : AC(AC_), TLI(TLI_), DT(DT_) {}
+ : AC(AC_), DL(DL_), TLI(TLI_), DT(DT_) {}
LazyValueInfo(LazyValueInfo &&Arg)
- : AC(Arg.AC), TLI(Arg.TLI), DT(Arg.DT), PImpl(Arg.PImpl) {
+ : AC(Arg.AC), DL(Arg.DL), TLI(Arg.TLI), DT(Arg.DT), PImpl(Arg.PImpl) {
Arg.PImpl = nullptr;
}
LazyValueInfo &operator=(LazyValueInfo &&Arg) {
releaseMemory();
AC = Arg.AC;
+ DL = Arg.DL;
TLI = Arg.TLI;
DT = Arg.DT;
PImpl = Arg.PImpl;
@@ -98,8 +100,15 @@ public:
/// Inform the analysis cache that we have erased a block.
void eraseBlock(BasicBlock *BB);
+ /// Print the \LazyValueInfoCache.
+ void printCache(Function &F, raw_ostream &OS);
+
// For old PM pass. Delete once LazyValueInfoWrapperPass is gone.
void releaseMemory();
+
+ /// Handle invalidation events in the new pass manager.
+ bool invalidate(Function &F, const PreservedAnalyses &PA,
+ FunctionAnalysisManager::Invalidator &Inv);
};
/// \brief Analysis to compute lazy value information.
diff --git a/include/llvm/Analysis/Loads.h b/include/llvm/Analysis/Loads.h
index e167f36219d2..a59c1f88e229 100644
--- a/include/llvm/Analysis/Loads.h
+++ b/include/llvm/Analysis/Loads.h
@@ -85,8 +85,37 @@ Value *FindAvailableLoadedValue(LoadInst *Load,
BasicBlock::iterator &ScanFrom,
unsigned MaxInstsToScan = DefMaxInstsToScan,
AliasAnalysis *AA = nullptr,
- bool *IsLoadCSE = nullptr);
+ bool *IsLoadCSE = nullptr,
+ unsigned *NumScanedInst = nullptr);
+/// Scan backwards to see if we have the value of the given pointer available
+/// locally within a small number of instructions.
+///
+/// You can use this function to scan across multiple blocks: after you call
+/// this function, if ScanFrom points at the beginning of the block, it's safe
+/// to continue scanning the predecessors.
+///
+/// \param Ptr The pointer we want the load and store to originate from.
+/// \param AccessTy The access type of the pointer.
+/// \param AtLeastAtomic Are we looking for at-least an atomic load/store ? In
+/// case it is false, we can return an atomic or non-atomic load or store. In
+/// case it is true, we need to return an atomic load or store.
+/// \param ScanBB The basic block to scan.
+/// \param [in,out] ScanFrom The location to start scanning from. When this
+/// function returns, it points at the last instruction scanned.
+/// \param MaxInstsToScan The maximum number of instructions to scan. If this
+/// is zero, the whole block will be scanned.
+/// \param AA Optional pointer to alias analysis, to make the scan more
+/// precise.
+/// \param [out] IsLoad Whether the returned value is a load from the same
+/// location in memory, as opposed to the value operand of a store.
+///
+/// \returns The found value, or nullptr if no value is found.
+Value *FindAvailablePtrLoadStore(Value *Ptr, Type *AccessTy, bool AtLeastAtomic,
+ BasicBlock *ScanBB,
+ BasicBlock::iterator &ScanFrom,
+ unsigned MaxInstsToScan, AliasAnalysis *AA,
+ bool *IsLoad, unsigned *NumScanedInst);
}
#endif
diff --git a/include/llvm/Analysis/LoopAccessAnalysis.h b/include/llvm/Analysis/LoopAccessAnalysis.h
index 901b193c7e2d..2568903c57f3 100644
--- a/include/llvm/Analysis/LoopAccessAnalysis.h
+++ b/include/llvm/Analysis/LoopAccessAnalysis.h
@@ -38,39 +38,6 @@ class SCEVUnionPredicate;
class LoopAccessInfo;
class OptimizationRemarkEmitter;
-/// 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 Loop *TheLoop,
- const char *PassName,
- OptimizationRemarkEmitter &ORE);
-};
-
/// \brief Collection of parameters shared beetween the Loop Vectorizer and the
/// Loop Access Analysis.
struct VectorizerParams {
@@ -126,7 +93,7 @@ struct VectorizerParams {
class MemoryDepChecker {
public:
typedef PointerIntPair<Value *, 1, bool> MemAccessInfo;
- typedef SmallPtrSet<MemAccessInfo, 8> MemAccessInfoSet;
+ typedef SmallVector<MemAccessInfo, 8> MemAccessInfoList;
/// \brief Set of potential dependent memory accesses.
typedef EquivalenceClasses<MemAccessInfo> DepCandidates;
@@ -221,7 +188,7 @@ public:
/// \brief Check whether the dependencies between the accesses are safe.
///
/// Only checks sets with elements in \p CheckDeps.
- bool areDepsSafe(DepCandidates &AccessSets, MemAccessInfoSet &CheckDeps,
+ bool areDepsSafe(DepCandidates &AccessSets, MemAccessInfoList &CheckDeps,
const ValueToValueMap &Strides);
/// \brief No memory dependence was encountered that would inhibit
diff --git a/include/llvm/Analysis/LoopInfo.h b/include/llvm/Analysis/LoopInfo.h
index 20e6af2727fe..996794b660a9 100644
--- a/include/llvm/Analysis/LoopInfo.h
+++ b/include/llvm/Analysis/LoopInfo.h
@@ -26,7 +26,7 @@
// * etc...
//
// Note that this analysis specifically identifies *Loops* not cycles or SCCs
-// in the CFG. There can be strongly connected compontents in the CFG which
+// in the CFG. There can be strongly connected components in the CFG which
// this analysis will not recognize and that will not be represented by a Loop
// instance. In particular, a Loop might be inside such a non-loop SCC, or a
// non-loop SCC might contain a sub-SCC which is a Loop.
@@ -364,7 +364,7 @@ extern template class LoopBase<BasicBlock, Loop>;
/// Represents a single loop in the control flow graph. Note that not all SCCs
-/// in the CFG are neccessarily loops.
+/// in the CFG are necessarily loops.
class Loop : public LoopBase<BasicBlock, Loop> {
public:
/// \brief A range representing the start and end location of a loop.
@@ -469,7 +469,7 @@ public:
/// the loop that branches to the loop header.
///
/// The LoopID metadata node should have one or more operands and the first
- /// operand should should be the node itself.
+ /// operand should be the node itself.
void setLoopID(MDNode *LoopID) const;
/// Return true if no exit block for the loop has a predecessor that is
@@ -478,7 +478,8 @@ public:
/// Return all unique successor blocks of this loop.
/// These are the blocks _outside of the current loop_ which are branched to.
- /// This assumes that loop exits are in canonical form.
+ /// This assumes that loop exits are in canonical form, i.e. all exits are
+ /// dedicated exits.
void getUniqueExitBlocks(SmallVectorImpl<BasicBlock *> &ExitBlocks) const;
/// If getUniqueExitBlocks would return exactly one block, return that block.
@@ -570,6 +571,23 @@ public:
reverse_iterator rend() const { return TopLevelLoops.rend(); }
bool empty() const { return TopLevelLoops.empty(); }
+ /// Return all of the loops in the function in preorder across the loop
+ /// nests, with siblings in forward program order.
+ ///
+ /// Note that because loops form a forest of trees, preorder is equivalent to
+ /// reverse postorder.
+ SmallVector<LoopT *, 4> getLoopsInPreorder();
+
+ /// Return all of the loops in the function in preorder across the loop
+ /// nests, with siblings in *reverse* program order.
+ ///
+ /// Note that because loops form a forest of trees, preorder is equivalent to
+ /// reverse postorder.
+ ///
+ /// Also note that this is *not* a reverse preorder. Only the siblings are in
+ /// reverse program order.
+ SmallVector<LoopT *, 4> getLoopsInReverseSiblingPreorder();
+
/// 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.
LoopT *getLoopFor(const BlockT *BB) const { return BBMap.lookup(BB); }
@@ -682,6 +700,10 @@ public:
return *this;
}
+ /// Handle invalidation explicitly.
+ bool invalidate(Function &F, const PreservedAnalyses &PA,
+ FunctionAnalysisManager::Invalidator &);
+
// Most of the public interface is provided via LoopInfoBase.
/// Update LoopInfo after removing the last backedge from a loop. This updates
diff --git a/include/llvm/Analysis/LoopInfoImpl.h b/include/llvm/Analysis/LoopInfoImpl.h
index 833a2202a568..761f8721b54f 100644
--- a/include/llvm/Analysis/LoopInfoImpl.h
+++ b/include/llvm/Analysis/LoopInfoImpl.h
@@ -507,6 +507,55 @@ analyze(const DominatorTreeBase<BlockT> &DomTree) {
DFS.traverse(DomRoot->getBlock());
}
+template <class BlockT, class LoopT>
+SmallVector<LoopT *, 4> LoopInfoBase<BlockT, LoopT>::getLoopsInPreorder() {
+ SmallVector<LoopT *, 4> PreOrderLoops, PreOrderWorklist;
+ // The outer-most loop actually goes into the result in the same relative
+ // order as we walk it. But LoopInfo stores the top level loops in reverse
+ // program order so for here we reverse it to get forward program order.
+ // FIXME: If we change the order of LoopInfo we will want to remove the
+ // reverse here.
+ for (LoopT *RootL : reverse(*this)) {
+ assert(PreOrderWorklist.empty() &&
+ "Must start with an empty preorder walk worklist.");
+ PreOrderWorklist.push_back(RootL);
+ do {
+ LoopT *L = PreOrderWorklist.pop_back_val();
+ // Sub-loops are stored in forward program order, but will process the
+ // worklist backwards so append them in reverse order.
+ PreOrderWorklist.append(L->rbegin(), L->rend());
+ PreOrderLoops.push_back(L);
+ } while (!PreOrderWorklist.empty());
+ }
+
+ return PreOrderLoops;
+}
+
+template <class BlockT, class LoopT>
+SmallVector<LoopT *, 4>
+LoopInfoBase<BlockT, LoopT>::getLoopsInReverseSiblingPreorder() {
+ SmallVector<LoopT *, 4> PreOrderLoops, PreOrderWorklist;
+ // The outer-most loop actually goes into the result in the same relative
+ // order as we walk it. LoopInfo stores the top level loops in reverse
+ // program order so we walk in order here.
+ // FIXME: If we change the order of LoopInfo we will want to add a reverse
+ // here.
+ for (LoopT *RootL : *this) {
+ assert(PreOrderWorklist.empty() &&
+ "Must start with an empty preorder walk worklist.");
+ PreOrderWorklist.push_back(RootL);
+ do {
+ LoopT *L = PreOrderWorklist.pop_back_val();
+ // Sub-loops are stored in forward program order, but will process the
+ // worklist backwards so we can just append them in order.
+ PreOrderWorklist.append(L->begin(), L->end());
+ PreOrderLoops.push_back(L);
+ } while (!PreOrderWorklist.empty());
+ }
+
+ return PreOrderLoops;
+}
+
// Debugging
template<class BlockT, class LoopT>
void LoopInfoBase<BlockT, LoopT>::print(raw_ostream &OS) const {
@@ -528,15 +577,48 @@ bool compareVectors(std::vector<T> &BB1, std::vector<T> &BB2) {
}
template <class BlockT, class LoopT>
-static void
-addInnerLoopsToHeadersMap(DenseMap<BlockT *, const LoopT *> &LoopHeaders,
- const LoopInfoBase<BlockT, LoopT> &LI,
- const LoopT &L) {
+void addInnerLoopsToHeadersMap(DenseMap<BlockT *, const LoopT *> &LoopHeaders,
+ const LoopInfoBase<BlockT, LoopT> &LI,
+ const LoopT &L) {
LoopHeaders[L.getHeader()] = &L;
for (LoopT *SL : L)
addInnerLoopsToHeadersMap(LoopHeaders, LI, *SL);
}
+#ifndef NDEBUG
+template <class BlockT, class LoopT>
+static void compareLoops(const LoopT *L, const LoopT *OtherL,
+ DenseMap<BlockT *, const LoopT *> &OtherLoopHeaders) {
+ BlockT *H = L->getHeader();
+ BlockT *OtherH = OtherL->getHeader();
+ assert(H == OtherH &&
+ "Mismatched headers even though found in the same map entry!");
+
+ assert(L->getLoopDepth() == OtherL->getLoopDepth() &&
+ "Mismatched loop depth!");
+ const LoopT *ParentL = L, *OtherParentL = OtherL;
+ do {
+ assert(ParentL->getHeader() == OtherParentL->getHeader() &&
+ "Mismatched parent loop headers!");
+ ParentL = ParentL->getParentLoop();
+ OtherParentL = OtherParentL->getParentLoop();
+ } while (ParentL);
+
+ for (const LoopT *SubL : *L) {
+ BlockT *SubH = SubL->getHeader();
+ const LoopT *OtherSubL = OtherLoopHeaders.lookup(SubH);
+ assert(OtherSubL && "Inner loop is missing in computed loop info!");
+ OtherLoopHeaders.erase(SubH);
+ compareLoops(SubL, OtherSubL, OtherLoopHeaders);
+ }
+
+ std::vector<BlockT *> BBs = L->getBlocks();
+ std::vector<BlockT *> OtherBBs = OtherL->getBlocks();
+ assert(compareVectors(BBs, OtherBBs) &&
+ "Mismatched basic blocks in the loops!");
+}
+#endif
+
template <class BlockT, class LoopT>
void LoopInfoBase<BlockT, LoopT>::verify(
const DominatorTreeBase<BlockT> &DomTree) const {
@@ -559,42 +641,32 @@ void LoopInfoBase<BlockT, LoopT>::verify(
LoopInfoBase<BlockT, LoopT> OtherLI;
OtherLI.analyze(DomTree);
- DenseMap<BlockT *, const LoopT *> LoopHeaders1;
- DenseMap<BlockT *, const LoopT *> LoopHeaders2;
-
- for (LoopT *L : *this)
- addInnerLoopsToHeadersMap(LoopHeaders1, *this, *L);
+ // Build a map we can use to move from our LI to the computed one. This
+ // allows us to ignore the particular order in any layer of the loop forest
+ // while still comparing the structure.
+ DenseMap<BlockT *, const LoopT *> OtherLoopHeaders;
for (LoopT *L : OtherLI)
- addInnerLoopsToHeadersMap(LoopHeaders2, OtherLI, *L);
- assert(LoopHeaders1.size() == LoopHeaders2.size() &&
- "LoopInfo is incorrect.");
-
- auto compareLoops = [&](const LoopT *L1, const LoopT *L2) {
- BlockT *H1 = L1->getHeader();
- BlockT *H2 = L2->getHeader();
- if (H1 != H2)
- return false;
- std::vector<BlockT *> BB1 = L1->getBlocks();
- std::vector<BlockT *> BB2 = L2->getBlocks();
- if (!compareVectors(BB1, BB2))
- return false;
-
- std::vector<BlockT *> SubLoopHeaders1;
- std::vector<BlockT *> SubLoopHeaders2;
- for (LoopT *L : *L1)
- SubLoopHeaders1.push_back(L->getHeader());
- for (LoopT *L : *L2)
- SubLoopHeaders2.push_back(L->getHeader());
-
- if (!compareVectors(SubLoopHeaders1, SubLoopHeaders2))
- return false;
- return true;
- };
-
- for (auto &I : LoopHeaders1) {
- BlockT *H = I.first;
- bool LoopsMatch = compareLoops(LoopHeaders1[H], LoopHeaders2[H]);
- assert(LoopsMatch && "LoopInfo is incorrect.");
+ addInnerLoopsToHeadersMap(OtherLoopHeaders, OtherLI, *L);
+
+ // Walk the top level loops and ensure there is a corresponding top-level
+ // loop in the computed version and then recursively compare those loop
+ // nests.
+ for (LoopT *L : *this) {
+ BlockT *Header = L->getHeader();
+ const LoopT *OtherL = OtherLoopHeaders.lookup(Header);
+ assert(OtherL && "Top level loop is missing in computed loop info!");
+ // Now that we've matched this loop, erase its header from the map.
+ OtherLoopHeaders.erase(Header);
+ // And recursively compare these loops.
+ compareLoops(L, OtherL, OtherLoopHeaders);
+ }
+
+ // Any remaining entries in the map are loops which were found when computing
+ // a fresh LoopInfo but not present in the current one.
+ if (!OtherLoopHeaders.empty()) {
+ for (const auto &HeaderAndLoop : OtherLoopHeaders)
+ dbgs() << "Found new loop: " << *HeaderAndLoop.second << "\n";
+ llvm_unreachable("Found new loops when recomputing LoopInfo!");
}
#endif
}
diff --git a/include/llvm/Analysis/MemoryBuiltins.h b/include/llvm/Analysis/MemoryBuiltins.h
index b58f07e69475..c5514316f75f 100644
--- a/include/llvm/Analysis/MemoryBuiltins.h
+++ b/include/llvm/Analysis/MemoryBuiltins.h
@@ -32,12 +32,6 @@ class TargetLibraryInfo;
class Type;
class Value;
-enum class ObjSizeMode {
- Exact = 0,
- Min = 1,
- Max = 2
-};
-
/// \brief Tests if a value is a call or invoke to a library function that
/// allocates or reallocates memory (either malloc, calloc, realloc, or strdup
/// like).
@@ -129,17 +123,36 @@ static inline CallInst *isFreeCall(Value *I, const TargetLibraryInfo *TLI) {
// Utility functions to compute size of objects.
//
+/// Various options to control the behavior of getObjectSize.
+struct ObjectSizeOpts {
+ /// Controls how we handle conditional statements with unknown conditions.
+ enum class Mode : uint8_t {
+ /// Fail to evaluate an unknown condition.
+ Exact,
+ /// Evaluate all branches of an unknown condition. If all evaluations
+ /// succeed, pick the minimum size.
+ Min,
+ /// Same as Min, except we pick the maximum size of all of the branches.
+ Max
+ };
+
+ /// How we want to evaluate this object's size.
+ Mode EvalMode = Mode::Exact;
+ /// Whether to round the result up to the alignment of allocas, byval
+ /// arguments, and global variables.
+ bool RoundToAlign = false;
+ /// If this is true, null pointers in address space 0 will be treated as
+ /// though they can't be evaluated. Otherwise, null is always considered to
+ /// point to a 0 byte region of memory.
+ bool NullIsUnknownSize = false;
+};
+
/// \brief Compute the size of the object pointed by Ptr. Returns true and the
/// object size in Size if successful, and false otherwise. In this context, by
/// object we mean the region of memory starting at Ptr to the end of the
/// underlying object pointed to by Ptr.
-/// If RoundToAlign is true, then Size is rounded up to the aligment of allocas,
-/// byval arguments, and global variables.
-/// If Mode is Min or Max the size will be evaluated even if it depends on
-/// a condition and corresponding value will be returned (min or max).
bool getObjectSize(const Value *Ptr, uint64_t &Size, const DataLayout &DL,
- const TargetLibraryInfo *TLI, bool RoundToAlign = false,
- ObjSizeMode Mode = ObjSizeMode::Exact);
+ const TargetLibraryInfo *TLI, ObjectSizeOpts Opts = {});
/// Try to turn a call to @llvm.objectsize into an integer value of the given
/// Type. Returns null on failure.
@@ -160,8 +173,7 @@ class ObjectSizeOffsetVisitor
const DataLayout &DL;
const TargetLibraryInfo *TLI;
- bool RoundToAlign;
- ObjSizeMode Mode;
+ ObjectSizeOpts Options;
unsigned IntTyBits;
APInt Zero;
SmallPtrSet<Instruction *, 8> SeenInsts;
@@ -174,8 +186,7 @@ class ObjectSizeOffsetVisitor
public:
ObjectSizeOffsetVisitor(const DataLayout &DL, const TargetLibraryInfo *TLI,
- LLVMContext &Context, bool RoundToAlign = false,
- ObjSizeMode Mode = ObjSizeMode::Exact);
+ LLVMContext &Context, ObjectSizeOpts Options = {});
SizeOffsetType compute(Value *V);
diff --git a/include/llvm/Transforms/Utils/MemorySSA.h b/include/llvm/Analysis/MemorySSA.h
index 408c6a157cd0..db31ae9f4f10 100644
--- a/include/llvm/Transforms/Utils/MemorySSA.h
+++ b/include/llvm/Analysis/MemorySSA.h
@@ -6,71 +6,71 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// \file
-// \brief This file exposes an interface to building/using memory SSA to
-// walk memory instructions using a use/def graph.
-//
-// Memory SSA class builds an SSA form that links together memory access
-// instructions such as loads, stores, atomics, and calls. Additionally, it does
-// a trivial form of "heap versioning" Every time the memory state changes in
-// the program, we generate a new heap version. It generates MemoryDef/Uses/Phis
-// that are overlayed on top of the existing instructions.
-//
-// As a trivial example,
-// define i32 @main() #0 {
-// entry:
-// %call = call noalias i8* @_Znwm(i64 4) #2
-// %0 = bitcast i8* %call to i32*
-// %call1 = call noalias i8* @_Znwm(i64 4) #2
-// %1 = bitcast i8* %call1 to i32*
-// store i32 5, i32* %0, align 4
-// store i32 7, i32* %1, align 4
-// %2 = load i32* %0, align 4
-// %3 = load i32* %1, align 4
-// %add = add nsw i32 %2, %3
-// ret i32 %add
-// }
-//
-// Will become
-// define i32 @main() #0 {
-// entry:
-// ; 1 = MemoryDef(0)
-// %call = call noalias i8* @_Znwm(i64 4) #3
-// %2 = bitcast i8* %call to i32*
-// ; 2 = MemoryDef(1)
-// %call1 = call noalias i8* @_Znwm(i64 4) #3
-// %4 = bitcast i8* %call1 to i32*
-// ; 3 = MemoryDef(2)
-// store i32 5, i32* %2, align 4
-// ; 4 = MemoryDef(3)
-// store i32 7, i32* %4, align 4
-// ; MemoryUse(3)
-// %7 = load i32* %2, align 4
-// ; MemoryUse(4)
-// %8 = load i32* %4, align 4
-// %add = add nsw i32 %7, %8
-// ret i32 %add
-// }
-//
-// Given this form, all the stores that could ever effect the load at %8 can be
-// gotten by using the MemoryUse associated with it, and walking from use to def
-// until you hit the top of the function.
-//
-// Each def also has a list of users associated with it, so you can walk from
-// both def to users, and users to defs. Note that we disambiguate MemoryUses,
-// but not the RHS of MemoryDefs. You can see this above at %7, which would
-// otherwise be a MemoryUse(4). Being disambiguated means that for a given
-// store, all the MemoryUses on its use lists are may-aliases of that store (but
-// the MemoryDefs on its use list may not be).
-//
-// MemoryDefs are not disambiguated because it would require multiple reaching
-// definitions, which would require multiple phis, and multiple memoryaccesses
-// per instruction.
+///
+/// \file
+/// \brief This file exposes an interface to building/using memory SSA to
+/// walk memory instructions using a use/def graph.
+///
+/// Memory SSA class builds an SSA form that links together memory access
+/// instructions such as loads, stores, atomics, and calls. Additionally, it
+/// does a trivial form of "heap versioning" Every time the memory state changes
+/// in the program, we generate a new heap version. It generates
+/// MemoryDef/Uses/Phis that are overlayed on top of the existing instructions.
+///
+/// As a trivial example,
+/// define i32 @main() #0 {
+/// entry:
+/// %call = call noalias i8* @_Znwm(i64 4) #2
+/// %0 = bitcast i8* %call to i32*
+/// %call1 = call noalias i8* @_Znwm(i64 4) #2
+/// %1 = bitcast i8* %call1 to i32*
+/// store i32 5, i32* %0, align 4
+/// store i32 7, i32* %1, align 4
+/// %2 = load i32* %0, align 4
+/// %3 = load i32* %1, align 4
+/// %add = add nsw i32 %2, %3
+/// ret i32 %add
+/// }
+///
+/// Will become
+/// define i32 @main() #0 {
+/// entry:
+/// ; 1 = MemoryDef(0)
+/// %call = call noalias i8* @_Znwm(i64 4) #3
+/// %2 = bitcast i8* %call to i32*
+/// ; 2 = MemoryDef(1)
+/// %call1 = call noalias i8* @_Znwm(i64 4) #3
+/// %4 = bitcast i8* %call1 to i32*
+/// ; 3 = MemoryDef(2)
+/// store i32 5, i32* %2, align 4
+/// ; 4 = MemoryDef(3)
+/// store i32 7, i32* %4, align 4
+/// ; MemoryUse(3)
+/// %7 = load i32* %2, align 4
+/// ; MemoryUse(4)
+/// %8 = load i32* %4, align 4
+/// %add = add nsw i32 %7, %8
+/// ret i32 %add
+/// }
+///
+/// Given this form, all the stores that could ever effect the load at %8 can be
+/// gotten by using the MemoryUse associated with it, and walking from use to
+/// def until you hit the top of the function.
+///
+/// Each def also has a list of users associated with it, so you can walk from
+/// both def to users, and users to defs. Note that we disambiguate MemoryUses,
+/// but not the RHS of MemoryDefs. You can see this above at %7, which would
+/// otherwise be a MemoryUse(4). Being disambiguated means that for a given
+/// store, all the MemoryUses on its use lists are may-aliases of that store
+/// (but the MemoryDefs on its use list may not be).
+///
+/// MemoryDefs are not disambiguated because it would require multiple reaching
+/// definitions, which would require multiple phis, and multiple memoryaccesses
+/// per instruction.
//===----------------------------------------------------------------------===//
-#ifndef LLVM_TRANSFORMS_UTILS_MEMORYSSA_H
-#define LLVM_TRANSFORMS_UTILS_MEMORYSSA_H
+#ifndef LLVM_ANALYSIS_MEMORYSSA_H
+#define LLVM_ANALYSIS_MEMORYSSA_H
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/GraphTraits.h"
@@ -79,6 +79,7 @@
#include "llvm/ADT/ilist.h"
#include "llvm/ADT/ilist_node.h"
#include "llvm/ADT/iterator.h"
+#include "llvm/ADT/iterator_range.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/MemoryLocation.h"
#include "llvm/Analysis/PHITransAddr.h"
@@ -91,9 +92,7 @@
#include "llvm/IR/User.h"
#include "llvm/IR/Value.h"
#include "llvm/Pass.h"
-#include "llvm/PassAnalysisSupport.h"
#include "llvm/Support/Casting.h"
-#include "llvm/Support/Compiler.h"
#include "llvm/Support/ErrorHandling.h"
#include <algorithm>
#include <cassert>
@@ -104,12 +103,16 @@
namespace llvm {
-class DominatorTree;
class Function;
class Instruction;
class MemoryAccess;
class LLVMContext;
class raw_ostream;
+namespace MSSAHelpers {
+struct AllAccessTag {};
+struct DefsOnlyTag {};
+}
+
enum {
// Used to signify what the default invalid ID is for MemoryAccess's
// getID()
@@ -123,21 +126,30 @@ using const_memoryaccess_def_iterator =
// \brief The base for all memory accesses. All memory accesses in a block are
// linked together using an intrusive list.
-class MemoryAccess : public User, public ilist_node<MemoryAccess> {
- void *operator new(size_t, unsigned) = delete;
- void *operator new(size_t) = delete;
-
+class MemoryAccess
+ : public User,
+ public ilist_node<MemoryAccess, ilist_tag<MSSAHelpers::AllAccessTag>>,
+ public ilist_node<MemoryAccess, ilist_tag<MSSAHelpers::DefsOnlyTag>> {
public:
+ using AllAccessType =
+ ilist_node<MemoryAccess, ilist_tag<MSSAHelpers::AllAccessTag>>;
+ using DefsOnlyType =
+ ilist_node<MemoryAccess, ilist_tag<MSSAHelpers::DefsOnlyTag>>;
+
// Methods for support type inquiry through isa, cast, and
// dyn_cast
- static inline bool classof(const MemoryAccess *) { return true; }
static inline bool classof(const Value *V) {
unsigned ID = V->getValueID();
return ID == MemoryUseVal || ID == MemoryPhiVal || ID == MemoryDefVal;
}
+ MemoryAccess(const MemoryAccess &) = delete;
+ MemoryAccess &operator=(const MemoryAccess &) = delete;
~MemoryAccess() override;
+ void *operator new(size_t, unsigned) = delete;
+ void *operator new(size_t) = delete;
+
BasicBlock *getBlock() const { return Block; }
virtual void print(raw_ostream &OS) const = 0;
@@ -155,6 +167,33 @@ public:
memoryaccess_def_iterator defs_end();
const_memoryaccess_def_iterator defs_end() const;
+ /// \brief Get the iterators for the all access list and the defs only list
+ /// We default to the all access list.
+ AllAccessType::self_iterator getIterator() {
+ return this->AllAccessType::getIterator();
+ }
+ AllAccessType::const_self_iterator getIterator() const {
+ return this->AllAccessType::getIterator();
+ }
+ AllAccessType::reverse_self_iterator getReverseIterator() {
+ return this->AllAccessType::getReverseIterator();
+ }
+ AllAccessType::const_reverse_self_iterator getReverseIterator() const {
+ return this->AllAccessType::getReverseIterator();
+ }
+ DefsOnlyType::self_iterator getDefsIterator() {
+ return this->DefsOnlyType::getIterator();
+ }
+ DefsOnlyType::const_self_iterator getDefsIterator() const {
+ return this->DefsOnlyType::getIterator();
+ }
+ DefsOnlyType::reverse_self_iterator getReverseDefsIterator() {
+ return this->DefsOnlyType::getReverseIterator();
+ }
+ DefsOnlyType::const_reverse_self_iterator getReverseDefsIterator() const {
+ return this->DefsOnlyType::getReverseIterator();
+ }
+
protected:
friend class MemorySSA;
friend class MemoryUseOrDef;
@@ -162,6 +201,10 @@ protected:
friend class MemoryDef;
friend class MemoryPhi;
+ /// \brief Used by MemorySSA to change the block of a MemoryAccess when it is
+ /// moved.
+ void setBlock(BasicBlock *BB) { Block = BB; }
+
/// \brief Used for debugging and tracking things about MemoryAccesses.
/// Guaranteed unique among MemoryAccesses, no guarantees otherwise.
virtual unsigned getID() const = 0;
@@ -171,8 +214,6 @@ protected:
: User(Type::getVoidTy(C), Vty, nullptr, NumOperands), Block(BB) {}
private:
- MemoryAccess(const MemoryAccess &);
- void operator=(const MemoryAccess &);
BasicBlock *Block;
};
@@ -189,10 +230,10 @@ inline raw_ostream &operator<<(raw_ostream &OS, const MemoryAccess &MA) {
/// This class should never be instantiated directly; make a MemoryUse or
/// MemoryDef instead.
class MemoryUseOrDef : public MemoryAccess {
+public:
void *operator new(size_t, unsigned) = delete;
void *operator new(size_t) = delete;
-public:
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(MemoryAccess);
/// \brief Get the instruction that this MemoryUse represents.
@@ -201,21 +242,36 @@ public:
/// \brief Get the access that produces the memory state used by this Use.
MemoryAccess *getDefiningAccess() const { return getOperand(0); }
- static inline bool classof(const MemoryUseOrDef *) { return true; }
static inline bool classof(const Value *MA) {
return MA->getValueID() == MemoryUseVal || MA->getValueID() == MemoryDefVal;
}
+ // Sadly, these have to be public because they are needed in some of the
+ // iterators.
+ virtual bool isOptimized() const = 0;
+ virtual MemoryAccess *getOptimized() const = 0;
+ virtual void setOptimized(MemoryAccess *) = 0;
+
+ /// \brief Reset the ID of what this MemoryUse was optimized to, causing it to
+ /// be rewalked by the walker if necessary.
+ /// This really should only be called by tests.
+ virtual void resetOptimized() = 0;
+
protected:
friend class MemorySSA;
-
+ friend class MemorySSAUpdater;
MemoryUseOrDef(LLVMContext &C, MemoryAccess *DMA, unsigned Vty,
Instruction *MI, BasicBlock *BB)
: MemoryAccess(C, Vty, BB, 1), MemoryInst(MI) {
setDefiningAccess(DMA);
}
-
- void setDefiningAccess(MemoryAccess *DMA) { setOperand(0, DMA); }
+ void setDefiningAccess(MemoryAccess *DMA, bool Optimized = false) {
+ if (!Optimized) {
+ setOperand(0, DMA);
+ return;
+ }
+ setOptimized(DMA);
+ }
private:
Instruction *MemoryInst;
@@ -232,35 +288,37 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(MemoryUseOrDef, MemoryAccess)
/// MemoryUse's is exactly the set of Instructions for which
/// AliasAnalysis::getModRefInfo returns "Ref".
class MemoryUse final : public MemoryUseOrDef {
- void *operator new(size_t, unsigned) = delete;
-
public:
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(MemoryAccess);
- // allocate space for exactly one operand
- void *operator new(size_t s) { return User::operator new(s, 1); }
-
MemoryUse(LLVMContext &C, MemoryAccess *DMA, Instruction *MI, BasicBlock *BB)
: MemoryUseOrDef(C, DMA, MemoryUseVal, MI, BB), OptimizedID(0) {}
- static inline bool classof(const MemoryUse *) { return true; }
+ // allocate space for exactly one operand
+ void *operator new(size_t s) { return User::operator new(s, 1); }
+ void *operator new(size_t, unsigned) = delete;
+
static inline bool classof(const Value *MA) {
return MA->getValueID() == MemoryUseVal;
}
void print(raw_ostream &OS) const override;
- void setDefiningAccess(MemoryAccess *DMA, bool Optimized = false) {
- if (Optimized)
- OptimizedID = DMA->getID();
- MemoryUseOrDef::setDefiningAccess(DMA);
+
+ virtual void setOptimized(MemoryAccess *DMA) override {
+ OptimizedID = DMA->getID();
+ setOperand(0, DMA);
}
- bool isOptimized() const {
+
+ virtual bool isOptimized() const override {
return getDefiningAccess() && OptimizedID == getDefiningAccess()->getID();
}
- /// \brief Reset the ID of what this MemoryUse was optimized to, causing it to
- /// be rewalked by the walker if necessary.
- /// This really should only be called by tests.
- void resetOptimized() { OptimizedID = INVALID_MEMORYACCESS_ID; }
+
+ virtual MemoryAccess *getOptimized() const override {
+ return getDefiningAccess();
+ }
+ virtual void resetOptimized() override {
+ OptimizedID = INVALID_MEMORYACCESS_ID;
+ }
protected:
friend class MemorySSA;
@@ -287,23 +345,35 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(MemoryUse, MemoryAccess)
/// associated with them. This use points to the nearest reaching
/// MemoryDef/MemoryPhi.
class MemoryDef final : public MemoryUseOrDef {
- void *operator new(size_t, unsigned) = delete;
-
public:
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(MemoryAccess);
- // allocate space for exactly one operand
- void *operator new(size_t s) { return User::operator new(s, 1); }
-
MemoryDef(LLVMContext &C, MemoryAccess *DMA, Instruction *MI, BasicBlock *BB,
unsigned Ver)
- : MemoryUseOrDef(C, DMA, MemoryDefVal, MI, BB), ID(Ver) {}
+ : MemoryUseOrDef(C, DMA, MemoryDefVal, MI, BB), ID(Ver),
+ Optimized(nullptr), OptimizedID(INVALID_MEMORYACCESS_ID) {}
+
+ // allocate space for exactly one operand
+ void *operator new(size_t s) { return User::operator new(s, 1); }
+ void *operator new(size_t, unsigned) = delete;
- static inline bool classof(const MemoryDef *) { return true; }
static inline bool classof(const Value *MA) {
return MA->getValueID() == MemoryDefVal;
}
+ virtual void setOptimized(MemoryAccess *MA) override {
+ Optimized = MA;
+ OptimizedID = getDefiningAccess()->getID();
+ }
+ virtual MemoryAccess *getOptimized() const override { return Optimized; }
+ virtual bool isOptimized() const override {
+ return getOptimized() && getDefiningAccess() &&
+ OptimizedID == getDefiningAccess()->getID();
+ }
+ virtual void resetOptimized() override {
+ OptimizedID = INVALID_MEMORYACCESS_ID;
+ }
+
void print(raw_ostream &OS) const override;
protected:
@@ -313,6 +383,8 @@ protected:
private:
const unsigned ID;
+ MemoryAccess *Optimized;
+ unsigned int OptimizedID;
};
template <>
@@ -352,7 +424,6 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(MemoryDef, MemoryAccess)
/// Because MemoryUse's do not generate new definitions, they do not have this
/// issue.
class MemoryPhi final : public MemoryAccess {
- void *operator new(size_t, unsigned) = delete;
// allocate space for exactly zero operands
void *operator new(size_t s) { return User::operator new(s); }
@@ -365,6 +436,8 @@ public:
allocHungoffUses(ReservedSpace);
}
+ void *operator new(size_t, unsigned) = delete;
+
// Block iterator interface. This provides access to the list of incoming
// basic blocks, which parallels the list of incoming values.
typedef BasicBlock **block_iterator;
@@ -457,7 +530,6 @@ public:
return getIncomingValue(Idx);
}
- static inline bool classof(const MemoryPhi *) { return true; }
static inline bool classof(const Value *V) {
return V->getValueID() == MemoryPhiVal;
}
@@ -466,6 +538,7 @@ public:
protected:
friend class MemorySSA;
+
/// \brief this is more complicated than the generic
/// User::allocHungoffUses, because we have to allocate Uses for the incoming
/// values and pointers to the incoming blocks, all in one allocation.
@@ -529,7 +602,14 @@ public:
return LiveOnEntryDef.get();
}
- using AccessList = iplist<MemoryAccess>;
+ // Sadly, iplists, by default, owns and deletes pointers added to the
+ // list. It's not currently possible to have two iplists for the same type,
+ // where one owns the pointers, and one does not. This is because the traits
+ // are per-type, not per-tag. If this ever changes, we should make the
+ // DefList an iplist.
+ using AccessList = iplist<MemoryAccess, ilist_tag<MSSAHelpers::AllAccessTag>>;
+ using DefsList =
+ simple_ilist<MemoryAccess, ilist_tag<MSSAHelpers::DefsOnlyTag>>;
/// \brief Return the list of MemoryAccess's for a given basic block.
///
@@ -538,62 +618,13 @@ public:
return getWritableBlockAccesses(BB);
}
- /// \brief Create an empty MemoryPhi in MemorySSA for a given basic block.
- /// Only one MemoryPhi for a block exists at a time, so this function will
- /// assert if you try to create one where it already exists.
- MemoryPhi *createMemoryPhi(BasicBlock *BB);
-
- enum InsertionPlace { Beginning, End };
-
- /// \brief Create a MemoryAccess in MemorySSA at a specified point in a block,
- /// with a specified clobbering definition.
- ///
- /// Returns the new MemoryAccess.
- /// This should be called when a memory instruction is created that is being
- /// used to replace an existing memory instruction. It will *not* create PHI
- /// nodes, or verify the clobbering definition. The insertion place is used
- /// solely to determine where in the memoryssa access lists the instruction
- /// will be placed. The caller is expected to keep ordering the same as
- /// instructions.
- /// It will return the new MemoryAccess.
- /// Note: If a MemoryAccess already exists for I, this function will make it
- /// inaccessible and it *must* have removeMemoryAccess called on it.
- MemoryAccess *createMemoryAccessInBB(Instruction *I, MemoryAccess *Definition,
- const BasicBlock *BB,
- InsertionPlace Point);
- /// \brief Create a MemoryAccess in MemorySSA before or after an existing
- /// MemoryAccess.
+ /// \brief Return the list of MemoryDef's and MemoryPhi's for a given basic
+ /// block.
///
- /// Returns the new MemoryAccess.
- /// This should be called when a memory instruction is created that is being
- /// used to replace an existing memory instruction. It will *not* create PHI
- /// nodes, or verify the clobbering definition. The clobbering definition
- /// must be non-null.
- /// Note: If a MemoryAccess already exists for I, this function will make it
- /// inaccessible and it *must* have removeMemoryAccess called on it.
- MemoryUseOrDef *createMemoryAccessBefore(Instruction *I,
- MemoryAccess *Definition,
- MemoryUseOrDef *InsertPt);
- MemoryUseOrDef *createMemoryAccessAfter(Instruction *I,
- MemoryAccess *Definition,
- MemoryAccess *InsertPt);
-
- // \brief Splice \p What to just before \p Where.
- //
- // In order to be efficient, the following conditions must be met:
- // - \p Where dominates \p What,
- // - All memory accesses in [\p Where, \p What) are no-alias with \p What.
- //
- // TODO: relax the MemoryDef requirement on Where.
- void spliceMemoryAccessAbove(MemoryDef *Where, MemoryUseOrDef *What);
-
- /// \brief Remove a MemoryAccess from MemorySSA, including updating all
- /// definitions and uses.
- /// This should be called when a memory instruction that has a MemoryAccess
- /// associated with it is erased from the program. For example, if a store or
- /// load is simply erased (not replaced), removeMemoryAccess should be called
- /// on the MemoryAccess for that store/load.
- void removeMemoryAccess(MemoryAccess *);
+ /// This list is not modifiable by the user.
+ const DefsList *getBlockDefs(const BasicBlock *BB) const {
+ return getWritableBlockDefs(BB);
+ }
/// \brief Given two memory accesses in the same basic block, determine
/// whether MemoryAccess \p A dominates MemoryAccess \p B.
@@ -611,20 +642,51 @@ public:
/// all uses, uses appear in the right places). This is used by unit tests.
void verifyMemorySSA() const;
+ /// Used in various insertion functions to specify whether we are talking
+ /// about the beginning or end of a block.
+ enum InsertionPlace { Beginning, End };
+
protected:
// Used by Memory SSA annotater, dumpers, and wrapper pass
friend class MemorySSAAnnotatedWriter;
friend class MemorySSAPrinterLegacyPass;
+ friend class MemorySSAUpdater;
+
void verifyDefUses(Function &F) const;
void verifyDomination(Function &F) const;
void verifyOrdering(Function &F) const;
- // This is used by the use optimizer class
+ // This is used by the use optimizer and updater.
AccessList *getWritableBlockAccesses(const BasicBlock *BB) const {
auto It = PerBlockAccesses.find(BB);
return It == PerBlockAccesses.end() ? nullptr : It->second.get();
}
+ // This is used by the use optimizer and updater.
+ DefsList *getWritableBlockDefs(const BasicBlock *BB) const {
+ auto It = PerBlockDefs.find(BB);
+ return It == PerBlockDefs.end() ? nullptr : It->second.get();
+ }
+
+ // These is used by the updater to perform various internal MemorySSA
+ // machinsations. They do not always leave the IR in a correct state, and
+ // relies on the updater to fixup what it breaks, so it is not public.
+
+ void moveTo(MemoryUseOrDef *What, BasicBlock *BB, AccessList::iterator Where);
+ void moveTo(MemoryUseOrDef *What, BasicBlock *BB, InsertionPlace Point);
+ // Rename the dominator tree branch rooted at BB.
+ void renamePass(BasicBlock *BB, MemoryAccess *IncomingVal,
+ SmallPtrSetImpl<BasicBlock *> &Visited) {
+ renamePass(DT->getNode(BB), IncomingVal, Visited, true, true);
+ }
+ void removeFromLookups(MemoryAccess *);
+ void removeFromLists(MemoryAccess *, bool ShouldDelete = true);
+ void insertIntoListsForBlock(MemoryAccess *, const BasicBlock *,
+ InsertionPlace);
+ void insertIntoListsBefore(MemoryAccess *, const BasicBlock *,
+ AccessList::iterator);
+ MemoryUseOrDef *createDefinedAccess(Instruction *, MemoryAccess *);
+
private:
class CachingWalker;
class OptimizeUses;
@@ -635,32 +697,39 @@ private:
void verifyUseInDefs(MemoryAccess *, MemoryAccess *) const;
using AccessMap = DenseMap<const BasicBlock *, std::unique_ptr<AccessList>>;
+ using DefsMap = DenseMap<const BasicBlock *, std::unique_ptr<DefsList>>;
void
determineInsertionPoint(const SmallPtrSetImpl<BasicBlock *> &DefiningBlocks);
- void computeDomLevels(DenseMap<DomTreeNode *, unsigned> &DomLevels);
void markUnreachableAsLiveOnEntry(BasicBlock *BB);
bool dominatesUse(const MemoryAccess *, const MemoryAccess *) const;
+ MemoryPhi *createMemoryPhi(BasicBlock *BB);
MemoryUseOrDef *createNewAccess(Instruction *);
- MemoryUseOrDef *createDefinedAccess(Instruction *, MemoryAccess *);
MemoryAccess *findDominatingDef(BasicBlock *, enum InsertionPlace);
- void removeFromLookups(MemoryAccess *);
-
void placePHINodes(const SmallPtrSetImpl<BasicBlock *> &,
const DenseMap<const BasicBlock *, unsigned int> &);
- MemoryAccess *renameBlock(BasicBlock *, MemoryAccess *);
+ MemoryAccess *renameBlock(BasicBlock *, MemoryAccess *, bool);
+ void renameSuccessorPhis(BasicBlock *, MemoryAccess *, bool);
void renamePass(DomTreeNode *, MemoryAccess *IncomingVal,
- SmallPtrSet<BasicBlock *, 16> &Visited);
+ SmallPtrSetImpl<BasicBlock *> &Visited,
+ bool SkipVisited = false, bool RenameAllUses = false);
AccessList *getOrCreateAccessList(const BasicBlock *);
+ DefsList *getOrCreateDefsList(const BasicBlock *);
void renumberBlock(const BasicBlock *) const;
-
AliasAnalysis *AA;
DominatorTree *DT;
Function &F;
// Memory SSA mappings
DenseMap<const Value *, MemoryAccess *> ValueToMemoryAccess;
+ // These two mappings contain the main block to access/def mappings for
+ // MemorySSA. The list contained in PerBlockAccesses really owns all the
+ // MemoryAccesses.
+ // Both maps maintain the invariant that if a block is found in them, the
+ // corresponding list is not empty, and if a block is not found in them, the
+ // corresponding list is empty.
AccessMap PerBlockAccesses;
+ DefsMap PerBlockDefs;
std::unique_ptr<MemoryAccess> LiveOnEntryDef;
// Domination mappings
@@ -674,21 +743,33 @@ private:
unsigned NextID;
};
+// Internal MemorySSA utils, for use by MemorySSA classes and walkers
+class MemorySSAUtil {
+protected:
+ friend class MemorySSAWalker;
+ friend class GVNHoist;
+ // This function should not be used by new passes.
+ static bool defClobbersUseOrDef(MemoryDef *MD, const MemoryUseOrDef *MU,
+ AliasAnalysis &AA);
+};
+
// This pass does eager building and then printing of MemorySSA. It is used by
// the tests to be able to build, dump, and verify Memory SSA.
class MemorySSAPrinterLegacyPass : public FunctionPass {
public:
MemorySSAPrinterLegacyPass();
- static char ID;
bool runOnFunction(Function &) override;
void getAnalysisUsage(AnalysisUsage &AU) const override;
+
+ static char ID;
};
/// An analysis that produces \c MemorySSA for a function.
///
class MemorySSAAnalysis : public AnalysisInfoMixin<MemorySSAAnalysis> {
friend AnalysisInfoMixin<MemorySSAAnalysis>;
+
static AnalysisKey Key;
public:
@@ -711,6 +792,7 @@ class MemorySSAPrinterPass : public PassInfoMixin<MemorySSAPrinterPass> {
public:
explicit MemorySSAPrinterPass(raw_ostream &OS) : OS(OS) {}
+
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
};
@@ -725,6 +807,7 @@ public:
MemorySSAWrapperPass();
static char ID;
+
bool runOnFunction(Function &) override;
void releaseMemory() override;
MemorySSA &getMSSA() { return *MSSA; }
@@ -753,7 +836,7 @@ private:
class MemorySSAWalker {
public:
MemorySSAWalker(MemorySSA *);
- virtual ~MemorySSAWalker() {}
+ virtual ~MemorySSAWalker() = default;
using MemoryAccessSet = SmallVector<MemoryAccess *, 8>;
@@ -825,6 +908,7 @@ public:
// Keep the overrides below from hiding the Instruction overload of
// getClobberingMemoryAccess.
using MemorySSAWalker::getClobberingMemoryAccess;
+
MemoryAccess *getClobberingMemoryAccess(MemoryAccess *) override;
MemoryAccess *getClobberingMemoryAccess(MemoryAccess *,
const MemoryLocation &) override;
@@ -843,8 +927,9 @@ class memoryaccess_def_iterator_base
using BaseT = typename memoryaccess_def_iterator_base::iterator_facade_base;
public:
- memoryaccess_def_iterator_base(T *Start) : Access(Start), ArgNo(0) {}
- memoryaccess_def_iterator_base() : Access(nullptr), ArgNo(0) {}
+ memoryaccess_def_iterator_base(T *Start) : Access(Start) {}
+ memoryaccess_def_iterator_base() = default;
+
bool operator==(const memoryaccess_def_iterator_base &Other) const {
return Access == Other.Access && (!Access || ArgNo == Other.ArgNo);
}
@@ -883,8 +968,8 @@ public:
}
private:
- T *Access;
- unsigned ArgNo;
+ T *Access = nullptr;
+ unsigned ArgNo = 0;
};
inline memoryaccess_def_iterator MemoryAccess::defs_begin() {
@@ -947,10 +1032,7 @@ public:
fillInCurrentPair();
}
- upward_defs_iterator()
- : DefIterator(), Location(), OriginalAccess(), WalkingPhi(false) {
- CurrentPair.first = nullptr;
- }
+ upward_defs_iterator() { CurrentPair.first = nullptr; }
bool operator==(const upward_defs_iterator &Other) const {
return DefIterator == Other.DefIterator;
@@ -995,8 +1077,8 @@ private:
MemoryAccessPair CurrentPair;
memoryaccess_def_iterator DefIterator;
MemoryLocation Location;
- MemoryAccess *OriginalAccess;
- bool WalkingPhi;
+ MemoryAccess *OriginalAccess = nullptr;
+ bool WalkingPhi = false;
};
inline upward_defs_iterator upward_defs_begin(const MemoryAccessPair &Pair) {
@@ -1005,10 +1087,69 @@ inline upward_defs_iterator upward_defs_begin(const MemoryAccessPair &Pair) {
inline upward_defs_iterator upward_defs_end() { return upward_defs_iterator(); }
-// Return true when MD may alias MU, return false otherwise.
-bool defClobbersUseOrDef(MemoryDef *MD, const MemoryUseOrDef *MU,
- AliasAnalysis &AA);
+inline iterator_range<upward_defs_iterator>
+upward_defs(const MemoryAccessPair &Pair) {
+ return make_range(upward_defs_begin(Pair), upward_defs_end());
+}
+
+/// Walks the defining accesses of MemoryDefs. Stops after we hit something that
+/// has no defining use (e.g. a MemoryPhi or liveOnEntry). Note that, when
+/// comparing against a null def_chain_iterator, this will compare equal only
+/// after walking said Phi/liveOnEntry.
+///
+/// The UseOptimizedChain flag specifies whether to walk the clobbering
+/// access chain, or all the accesses.
+///
+/// Normally, MemoryDef are all just def/use linked together, so a def_chain on
+/// a MemoryDef will walk all MemoryDefs above it in the program until it hits
+/// a phi node. The optimized chain walks the clobbering access of a store.
+/// So if you are just trying to find, given a store, what the next
+/// thing that would clobber the same memory is, you want the optimized chain.
+template <class T, bool UseOptimizedChain = false>
+struct def_chain_iterator
+ : public iterator_facade_base<def_chain_iterator<T, UseOptimizedChain>,
+ std::forward_iterator_tag, MemoryAccess *> {
+ def_chain_iterator() : MA(nullptr) {}
+ def_chain_iterator(T MA) : MA(MA) {}
+
+ T operator*() const { return MA; }
+
+ def_chain_iterator &operator++() {
+ // N.B. liveOnEntry has a null defining access.
+ if (auto *MUD = dyn_cast<MemoryUseOrDef>(MA)) {
+ if (UseOptimizedChain && MUD->isOptimized())
+ MA = MUD->getOptimized();
+ else
+ MA = MUD->getDefiningAccess();
+ } else {
+ MA = nullptr;
+ }
+
+ return *this;
+ }
+
+ bool operator==(const def_chain_iterator &O) const { return MA == O.MA; }
+
+private:
+ T MA;
+};
+
+template <class T>
+inline iterator_range<def_chain_iterator<T>>
+def_chain(T MA, MemoryAccess *UpTo = nullptr) {
+#ifdef EXPENSIVE_CHECKS
+ assert((!UpTo || find(def_chain(MA), UpTo) != def_chain_iterator<T>()) &&
+ "UpTo isn't in the def chain!");
+#endif
+ return make_range(def_chain_iterator<T>(MA), def_chain_iterator<T>(UpTo));
+}
+
+template <class T>
+inline iterator_range<def_chain_iterator<T, true>> optimized_def_chain(T MA) {
+ return make_range(def_chain_iterator<T, true>(MA),
+ def_chain_iterator<T, true>(nullptr));
+}
} // end namespace llvm
-#endif // LLVM_TRANSFORMS_UTILS_MEMORYSSA_H
+#endif // LLVM_ANALYSIS_MEMORYSSA_H
diff --git a/include/llvm/Analysis/MemorySSAUpdater.h b/include/llvm/Analysis/MemorySSAUpdater.h
new file mode 100644
index 000000000000..d30eeeaa95b6
--- /dev/null
+++ b/include/llvm/Analysis/MemorySSAUpdater.h
@@ -0,0 +1,153 @@
+//===- MemorySSAUpdater.h - Memory SSA Updater-------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// \file
+// \brief An automatic updater for MemorySSA that handles arbitrary insertion,
+// deletion, and moves. It performs phi insertion where necessary, and
+// automatically updates the MemorySSA IR to be correct.
+// While updating loads or removing instructions is often easy enough to not
+// need this, updating stores should generally not be attemped outside this
+// API.
+//
+// Basic API usage:
+// Create the memory access you want for the instruction (this is mainly so
+// we know where it is, without having to duplicate the entire set of create
+// functions MemorySSA supports).
+// Call insertDef or insertUse depending on whether it's a MemoryUse or a
+// MemoryDef.
+// That's it.
+//
+// For moving, first, move the instruction itself using the normal SSA
+// instruction moving API, then just call moveBefore, moveAfter,or moveTo with
+// the right arguments.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ANALYSIS_MEMORYSSAUPDATER_H
+#define LLVM_ANALYSIS_MEMORYSSAUPDATER_H
+
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/IR/BasicBlock.h"
+#include "llvm/IR/Dominators.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/OperandTraits.h"
+#include "llvm/IR/Type.h"
+#include "llvm/IR/Use.h"
+#include "llvm/IR/User.h"
+#include "llvm/IR/Value.h"
+#include "llvm/Pass.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Analysis/MemorySSA.h"
+
+namespace llvm {
+
+class Function;
+class Instruction;
+class MemoryAccess;
+class LLVMContext;
+class raw_ostream;
+
+class MemorySSAUpdater {
+private:
+ MemorySSA *MSSA;
+ SmallVector<MemoryPhi *, 8> InsertedPHIs;
+ SmallPtrSet<BasicBlock *, 8> VisitedBlocks;
+
+public:
+ MemorySSAUpdater(MemorySSA *MSSA) : MSSA(MSSA) {}
+ /// Insert a definition into the MemorySSA IR. RenameUses will rename any use
+ /// below the new def block (and any inserted phis). RenameUses should be set
+ /// to true if the definition may cause new aliases for loads below it. This
+ /// is not the case for hoisting or sinking or other forms of code *movement*.
+ /// It *is* the case for straight code insertion.
+ /// For example:
+ /// store a
+ /// if (foo) { }
+ /// load a
+ ///
+ /// Moving the store into the if block, and calling insertDef, does not
+ /// require RenameUses.
+ /// However, changing it to:
+ /// store a
+ /// if (foo) { store b }
+ /// load a
+ /// Where a mayalias b, *does* require RenameUses be set to true.
+ void insertDef(MemoryDef *Def, bool RenameUses = false);
+ void insertUse(MemoryUse *Use);
+ void moveBefore(MemoryUseOrDef *What, MemoryUseOrDef *Where);
+ void moveAfter(MemoryUseOrDef *What, MemoryUseOrDef *Where);
+ void moveToPlace(MemoryUseOrDef *What, BasicBlock *BB,
+ MemorySSA::InsertionPlace Where);
+
+ // The below are utility functions. Other than creation of accesses to pass
+ // to insertDef, and removeAccess to remove accesses, you should generally
+ // not attempt to update memoryssa yourself. It is very non-trivial to get
+ // the edge cases right, and the above calls already operate in near-optimal
+ // time bounds.
+
+ /// \brief Create a MemoryAccess in MemorySSA at a specified point in a block,
+ /// with a specified clobbering definition.
+ ///
+ /// Returns the new MemoryAccess.
+ /// This should be called when a memory instruction is created that is being
+ /// used to replace an existing memory instruction. It will *not* create PHI
+ /// nodes, or verify the clobbering definition. The insertion place is used
+ /// solely to determine where in the memoryssa access lists the instruction
+ /// will be placed. The caller is expected to keep ordering the same as
+ /// instructions.
+ /// It will return the new MemoryAccess.
+ /// Note: If a MemoryAccess already exists for I, this function will make it
+ /// inaccessible and it *must* have removeMemoryAccess called on it.
+ MemoryAccess *createMemoryAccessInBB(Instruction *I, MemoryAccess *Definition,
+ const BasicBlock *BB,
+ MemorySSA::InsertionPlace Point);
+
+ /// \brief Create a MemoryAccess in MemorySSA before or after an existing
+ /// MemoryAccess.
+ ///
+ /// Returns the new MemoryAccess.
+ /// This should be called when a memory instruction is created that is being
+ /// used to replace an existing memory instruction. It will *not* create PHI
+ /// nodes, or verify the clobbering definition.
+ ///
+ /// Note: If a MemoryAccess already exists for I, this function will make it
+ /// inaccessible and it *must* have removeMemoryAccess called on it.
+ MemoryUseOrDef *createMemoryAccessBefore(Instruction *I,
+ MemoryAccess *Definition,
+ MemoryUseOrDef *InsertPt);
+ MemoryUseOrDef *createMemoryAccessAfter(Instruction *I,
+ MemoryAccess *Definition,
+ MemoryAccess *InsertPt);
+
+ /// \brief Remove a MemoryAccess from MemorySSA, including updating all
+ /// definitions and uses.
+ /// This should be called when a memory instruction that has a MemoryAccess
+ /// associated with it is erased from the program. For example, if a store or
+ /// load is simply erased (not replaced), removeMemoryAccess should be called
+ /// on the MemoryAccess for that store/load.
+ void removeMemoryAccess(MemoryAccess *);
+
+private:
+ // Move What before Where in the MemorySSA IR.
+ template <class WhereType>
+ void moveTo(MemoryUseOrDef *What, BasicBlock *BB, WhereType Where);
+ MemoryAccess *getPreviousDef(MemoryAccess *);
+ MemoryAccess *getPreviousDefInBlock(MemoryAccess *);
+ MemoryAccess *getPreviousDefFromEnd(BasicBlock *);
+ MemoryAccess *getPreviousDefRecursive(BasicBlock *);
+ MemoryAccess *recursePhi(MemoryAccess *Phi);
+ template <class RangeType>
+ MemoryAccess *tryRemoveTrivialPhi(MemoryPhi *Phi, RangeType &Operands);
+ void fixupDefs(const SmallVectorImpl<MemoryAccess *> &);
+};
+} // end namespace llvm
+
+#endif // LLVM_ANALYSIS_MEMORYSSAUPDATER_H
diff --git a/include/llvm/Analysis/ObjectUtils.h b/include/llvm/Analysis/ObjectUtils.h
new file mode 100644
index 000000000000..2ad3b1717009
--- /dev/null
+++ b/include/llvm/Analysis/ObjectUtils.h
@@ -0,0 +1,42 @@
+//===- Analysis/ObjectUtils.h - analysis utils for object files -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ANALYSIS_OBJECT_UTILS_H
+#define LLVM_ANALYSIS_OBJECT_UTILS_H
+
+#include "llvm/IR/GlobalVariable.h"
+
+namespace llvm {
+
+/// True if GV can be left out of the object symbol table. This is the case
+/// for linkonce_odr values whose address is not significant. While legal, it is
+/// not normally profitable to omit them from the .o symbol table. Using this
+/// analysis makes sense when the information can be passed down to the linker
+/// or we are in LTO.
+inline bool canBeOmittedFromSymbolTable(const GlobalValue *GV) {
+ if (!GV->hasLinkOnceODRLinkage())
+ return false;
+
+ // We assume that anyone who sets global unnamed_addr on a non-constant knows
+ // what they're doing.
+ if (GV->hasGlobalUnnamedAddr())
+ return true;
+
+ // If it is a non constant variable, it needs to be uniqued across shared
+ // objects.
+ if (auto *Var = dyn_cast<GlobalVariable>(GV))
+ if (!Var->isConstant())
+ return false;
+
+ return GV->hasAtLeastLocalUnnamedAddr();
+}
+
+}
+
+#endif
diff --git a/include/llvm/Analysis/OptimizationDiagnosticInfo.h b/include/llvm/Analysis/OptimizationDiagnosticInfo.h
index 39269269c244..edd9140a3493 100644
--- a/include/llvm/Analysis/OptimizationDiagnosticInfo.h
+++ b/include/llvm/Analysis/OptimizationDiagnosticInfo.h
@@ -38,7 +38,7 @@ class Value;
/// enabled in the LLVM context.
class OptimizationRemarkEmitter {
public:
- OptimizationRemarkEmitter(Function *F, BlockFrequencyInfo *BFI)
+ OptimizationRemarkEmitter(const Function *F, BlockFrequencyInfo *BFI)
: F(F), BFI(BFI) {}
/// \brief This variant can be used to generate ORE on demand (without the
@@ -52,7 +52,7 @@ public:
/// operation since BFI and all its required analyses are computed. This is
/// for example useful for CGSCC passes that can't use function analyses
/// passes in the old PM.
- OptimizationRemarkEmitter(Function *F);
+ OptimizationRemarkEmitter(const Function *F);
OptimizationRemarkEmitter(OptimizationRemarkEmitter &&Arg)
: F(Arg.F), BFI(Arg.BFI) {}
@@ -63,136 +63,16 @@ public:
return *this;
}
- /// The new interface to emit remarks.
- void emit(DiagnosticInfoOptimizationBase &OptDiag);
-
- /// Emit an optimization-applied message.
- ///
- /// \p PassName is the name of the pass emitting the message. If -Rpass= is
- /// given and \p PassName matches the regular expression in -Rpass, then the
- /// remark will be emitted. \p Fn is the function triggering the remark, \p
- /// DLoc is the debug location where the diagnostic is generated. \p V is the
- /// IR Value that identifies the code region. \p Msg is the message string to
- /// use.
- void emitOptimizationRemark(const char *PassName, const DebugLoc &DLoc,
- const Value *V, const Twine &Msg);
-
- /// \brief Same as above but derives the IR Value for the code region and the
- /// debug location from the Loop parameter \p L.
- void emitOptimizationRemark(const char *PassName, Loop *L, const Twine &Msg);
-
- /// \brief Same as above but derives the debug location and the code region
- /// from the debug location and the basic block of \p Inst, respectively.
- void emitOptimizationRemark(const char *PassName, Instruction *Inst,
- const Twine &Msg) {
- emitOptimizationRemark(PassName, Inst->getDebugLoc(), Inst->getParent(),
- Msg);
- }
-
- /// Emit an optimization-missed message.
- ///
- /// \p PassName is the name of the pass emitting the message. If
- /// -Rpass-missed= is given and the name matches the regular expression in
- /// -Rpass, then the remark will be emitted. \p DLoc is the debug location
- /// where the diagnostic is generated. \p V is the IR Value that identifies
- /// the code region. \p Msg is the message string to use. If \p IsVerbose is
- /// true, the message is considered verbose and will only be emitted when
- /// verbose output is turned on.
- void emitOptimizationRemarkMissed(const char *PassName, const DebugLoc &DLoc,
- const Value *V, const Twine &Msg,
- bool IsVerbose = false);
-
- /// \brief Same as above but derives the IR Value for the code region and the
- /// debug location from the Loop parameter \p L.
- void emitOptimizationRemarkMissed(const char *PassName, Loop *L,
- const Twine &Msg, bool IsVerbose = false);
-
- /// \brief Same as above but derives the debug location and the code region
- /// from the debug location and the basic block of \p Inst, respectively.
- void emitOptimizationRemarkMissed(const char *PassName, Instruction *Inst,
- const Twine &Msg, bool IsVerbose = false) {
- emitOptimizationRemarkMissed(PassName, Inst->getDebugLoc(),
- Inst->getParent(), Msg, IsVerbose);
- }
-
- /// Emit an optimization analysis remark message.
- ///
- /// \p PassName is the name of the pass emitting the message. If
- /// -Rpass-analysis= is given and \p PassName matches the regular expression
- /// in -Rpass, then the remark will be emitted. \p DLoc is the debug location
- /// where the diagnostic is generated. \p V is the IR Value that identifies
- /// the code region. \p Msg is the message string to use. If \p IsVerbose is
- /// true, the message is considered verbose and will only be emitted when
- /// verbose output is turned on.
- void emitOptimizationRemarkAnalysis(const char *PassName,
- const DebugLoc &DLoc, const Value *V,
- const Twine &Msg, bool IsVerbose = false);
-
- /// \brief Same as above but derives the IR Value for the code region and the
- /// debug location from the Loop parameter \p L.
- void emitOptimizationRemarkAnalysis(const char *PassName, Loop *L,
- const Twine &Msg, bool IsVerbose = false);
+ /// Handle invalidation events in the new pass manager.
+ bool invalidate(Function &F, const PreservedAnalyses &PA,
+ FunctionAnalysisManager::Invalidator &Inv);
- /// \brief Same as above but derives the debug location and the code region
- /// from the debug location and the basic block of \p Inst, respectively.
- void emitOptimizationRemarkAnalysis(const char *PassName, Instruction *Inst,
- const Twine &Msg,
- bool IsVerbose = false) {
- emitOptimizationRemarkAnalysis(PassName, Inst->getDebugLoc(),
- Inst->getParent(), Msg, IsVerbose);
- }
-
- /// \brief This variant allows specifying what should be emitted for missed
- /// and analysis remarks in one call.
- ///
- /// \p PassName is the name of the pass emitting the message. If
- /// -Rpass-missed= is given and \p PassName matches the regular expression, \p
- /// MsgForMissedRemark is emitted.
- ///
- /// If -Rpass-analysis= is given and \p PassName matches the regular
- /// expression, \p MsgForAnalysisRemark is emitted.
- ///
- /// The debug location and the code region is derived from \p Inst. If \p
- /// IsVerbose is true, the message is considered verbose and will only be
- /// emitted when verbose output is turned on.
- void emitOptimizationRemarkMissedAndAnalysis(
- const char *PassName, Instruction *Inst, const Twine &MsgForMissedRemark,
- const Twine &MsgForAnalysisRemark, bool IsVerbose = false) {
- emitOptimizationRemarkAnalysis(PassName, Inst, MsgForAnalysisRemark,
- IsVerbose);
- emitOptimizationRemarkMissed(PassName, Inst, MsgForMissedRemark, IsVerbose);
- }
-
- /// \brief Emit an optimization analysis remark related to floating-point
- /// non-commutativity.
+ /// \brief Output the remark via the diagnostic handler and to the
+ /// optimization record file.
///
- /// \p PassName is the name of the pass emitting the message. If
- /// -Rpass-analysis= is given and \p PassName matches the regular expression
- /// in -Rpass, then the remark will be emitted. \p Fn is the function
- /// triggering the remark, \p DLoc is the debug location where the diagnostic
- /// is generated.\p V is the IR Value that identifies the code region. \p Msg
- /// is the message string to use.
- void emitOptimizationRemarkAnalysisFPCommute(const char *PassName,
- const DebugLoc &DLoc,
- const Value *V,
- const Twine &Msg);
-
- /// \brief Emit an optimization analysis remark related to pointer aliasing.
- ///
- /// \p PassName is the name of the pass emitting the message. If
- /// -Rpass-analysis= is given and \p PassName matches the regular expression
- /// in -Rpass, then the remark will be emitted. \p Fn is the function
- /// triggering the remark, \p DLoc is the debug location where the diagnostic
- /// is generated.\p V is the IR Value that identifies the code region. \p Msg
- /// is the message string to use.
- void emitOptimizationRemarkAnalysisAliasing(const char *PassName,
- const DebugLoc &DLoc,
- const Value *V, const Twine &Msg);
-
- /// \brief Same as above but derives the IR Value for the code region and the
- /// debug location from the Loop parameter \p L.
- void emitOptimizationRemarkAnalysisAliasing(const char *PassName, Loop *L,
- const Twine &Msg);
+ /// This is the new interface that should be now used rather than the legacy
+ /// emit* APIs.
+ void emit(DiagnosticInfoOptimizationBase &OptDiag);
/// \brief Whether we allow for extra compile-time budget to perform more
/// analysis to produce fewer false positives.
@@ -208,7 +88,7 @@ public:
}
private:
- Function *F;
+ const Function *F;
BlockFrequencyInfo *BFI;
@@ -220,7 +100,7 @@ private:
Optional<uint64_t> computeHotness(const Value *V);
/// Similar but use value from \p OptDiag and update hotness there.
- void computeHotness(DiagnosticInfoOptimizationBase &OptDiag);
+ void computeHotness(DiagnosticInfoIROptimization &OptDiag);
/// \brief Only allow verbose messages if we know we're filtering by hotness
/// (BFI is only set in this case).
@@ -274,5 +154,11 @@ public:
/// \brief Run the analysis pass over a function and produce BFI.
Result run(Function &F, FunctionAnalysisManager &AM);
};
+
+namespace yaml {
+template <> struct MappingTraits<DiagnosticInfoOptimizationBase *> {
+ static void mapping(IO &io, DiagnosticInfoOptimizationBase *&OptDiag);
+};
+}
}
#endif // LLVM_IR_OPTIMIZATIONDIAGNOSTICINFO_H
diff --git a/include/llvm/Analysis/PostDominators.h b/include/llvm/Analysis/PostDominators.h
index 34361dac8c16..94ee3b03bb86 100644
--- a/include/llvm/Analysis/PostDominators.h
+++ b/include/llvm/Analysis/PostDominators.h
@@ -26,6 +26,10 @@ struct PostDominatorTree : public DominatorTreeBase<BasicBlock> {
typedef DominatorTreeBase<BasicBlock> Base;
PostDominatorTree() : DominatorTreeBase<BasicBlock>(true) {}
+
+ /// Handle invalidation explicitly.
+ bool invalidate(Function &F, const PreservedAnalyses &PA,
+ FunctionAnalysisManager::Invalidator &);
};
/// \brief Analysis pass which computes a \c PostDominatorTree.
diff --git a/include/llvm/Analysis/ProfileSummaryInfo.h b/include/llvm/Analysis/ProfileSummaryInfo.h
index d7fe76e278e3..1aec35c3e677 100644
--- a/include/llvm/Analysis/ProfileSummaryInfo.h
+++ b/include/llvm/Analysis/ProfileSummaryInfo.h
@@ -29,6 +29,7 @@
namespace llvm {
class BasicBlock;
class BlockFrequencyInfo;
+class CallSite;
class ProfileSummary;
/// \brief Analysis providing profile information.
///
@@ -44,7 +45,7 @@ class ProfileSummaryInfo {
private:
Module &M;
std::unique_ptr<ProfileSummary> Summary;
- void computeSummary();
+ bool computeSummary();
void computeThresholds();
// Count thresholds to answer isHotCount and isColdCount queries.
Optional<uint64_t> HotCountThreshold, ColdCountThreshold;
@@ -53,16 +54,29 @@ public:
ProfileSummaryInfo(Module &M) : M(M) {}
ProfileSummaryInfo(ProfileSummaryInfo &&Arg)
: M(Arg.M), Summary(std::move(Arg.Summary)) {}
+ /// Returns the profile count for \p CallInst.
+ static Optional<uint64_t> getProfileCount(const Instruction *CallInst,
+ BlockFrequencyInfo *BFI);
/// \brief Returns true if \p F has hot function entry.
bool isFunctionEntryHot(const Function *F);
+ /// Returns true if \p F has hot function entry or hot call edge.
+ bool isFunctionHotInCallGraph(const Function *F);
/// \brief Returns true if \p F has cold function entry.
bool isFunctionEntryCold(const Function *F);
+ /// Returns true if \p F has cold function entry or cold call edge.
+ bool isFunctionColdInCallGraph(const Function *F);
/// \brief Returns true if \p F is a hot function.
bool isHotCount(uint64_t C);
/// \brief Returns true if count \p C is considered cold.
bool isColdCount(uint64_t C);
/// \brief Returns true if BasicBlock \p B is considered hot.
bool isHotBB(const BasicBlock *B, BlockFrequencyInfo *BFI);
+ /// \brief Returns true if BasicBlock \p B is considered cold.
+ bool isColdBB(const BasicBlock *B, BlockFrequencyInfo *BFI);
+ /// \brief Returns true if CallSite \p CS is considered hot.
+ bool isHotCallSite(const CallSite &CS, BlockFrequencyInfo *BFI);
+ /// \brief Returns true if Callsite \p CS is considered cold.
+ bool isColdCallSite(const CallSite &CS, BlockFrequencyInfo *BFI);
};
/// An analysis pass based on legacy pass manager to deliver ProfileSummaryInfo.
diff --git a/include/llvm/Analysis/PtrUseVisitor.h b/include/llvm/Analysis/PtrUseVisitor.h
index 6e61fc3be384..2fe7c6725266 100644
--- a/include/llvm/Analysis/PtrUseVisitor.h
+++ b/include/llvm/Analysis/PtrUseVisitor.h
@@ -196,7 +196,10 @@ class PtrUseVisitor : protected InstVisitor<DerivedT>,
typedef InstVisitor<DerivedT> Base;
public:
- PtrUseVisitor(const DataLayout &DL) : PtrUseVisitorBase(DL) {}
+ PtrUseVisitor(const DataLayout &DL) : PtrUseVisitorBase(DL) {
+ static_assert(std::is_base_of<PtrUseVisitor, DerivedT>::value,
+ "Must pass the derived type to this template!");
+ }
/// \brief Recursively visit the uses of the given pointer.
/// \returns An info struct about the pointer. See \c PtrInfo for details.
diff --git a/include/llvm/Analysis/RegionInfo.h b/include/llvm/Analysis/RegionInfo.h
index f2f27a137a88..caeb21db613e 100644
--- a/include/llvm/Analysis/RegionInfo.h
+++ b/include/llvm/Analysis/RegionInfo.h
@@ -886,6 +886,10 @@ public:
return *this;
}
+ /// Handle invalidation explicitly.
+ bool invalidate(Function &F, const PreservedAnalyses &PA,
+ FunctionAnalysisManager::Invalidator &);
+
// updateStatistics - Update statistic about created regions.
void updateStatistics(Region *R) final;
diff --git a/include/llvm/Analysis/ScalarEvolution.h b/include/llvm/Analysis/ScalarEvolution.h
index 1a93f9aa5fd2..9a50de540f2b 100644
--- a/include/llvm/Analysis/ScalarEvolution.h
+++ b/include/llvm/Analysis/ScalarEvolution.h
@@ -543,6 +543,12 @@ private:
/// predicate by splitting it into a set of independent predicates.
bool ProvingSplitPredicate;
+ /// Memoized values for the GetMinTrailingZeros
+ DenseMap<const SCEV *, uint32_t> MinTrailingZerosCache;
+
+ /// Private helper method for the GetMinTrailingZeros method
+ uint32_t GetMinTrailingZerosImpl(const SCEV *S);
+
/// 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 summarized in
@@ -600,14 +606,14 @@ private:
/// Information about the number of times a particular loop exit may be
/// reached before exiting the loop.
struct ExitNotTakenInfo {
- AssertingVH<BasicBlock> ExitingBlock;
+ PoisoningVH<BasicBlock> ExitingBlock;
const SCEV *ExactNotTaken;
std::unique_ptr<SCEVUnionPredicate> Predicate;
bool hasAlwaysTruePredicate() const {
return !Predicate || Predicate->isAlwaysTrue();
}
- explicit ExitNotTakenInfo(AssertingVH<BasicBlock> ExitingBlock,
+ explicit ExitNotTakenInfo(PoisoningVH<BasicBlock> ExitingBlock,
const SCEV *ExactNotTaken,
std::unique_ptr<SCEVUnionPredicate> Predicate)
: ExitingBlock(ExitingBlock), ExactNotTaken(ExactNotTaken),
@@ -972,6 +978,20 @@ private:
/// Test whether the condition described by Pred, LHS, and RHS is true
/// whenever the condition described by Pred, FoundLHS, and FoundRHS is
+ /// true. Here LHS is an operation that includes FoundLHS as one of its
+ /// arguments.
+ bool isImpliedViaOperations(ICmpInst::Predicate Pred,
+ const SCEV *LHS, const SCEV *RHS,
+ const SCEV *FoundLHS, const SCEV *FoundRHS,
+ unsigned Depth = 0);
+
+ /// Test whether the condition described by Pred, LHS, and RHS is true.
+ /// Use only simple non-recursive types of checks, such as range analysis etc.
+ bool isKnownViaSimpleReasoning(ICmpInst::Predicate Pred,
+ const SCEV *LHS, const SCEV *RHS);
+
+ /// Test whether the condition described by Pred, LHS, and RHS is true
+ /// whenever the condition described by Pred, FoundLHS, and FoundRHS is
/// true.
bool isImpliedCondOperandsHelper(ICmpInst::Predicate Pred, const SCEV *LHS,
const SCEV *RHS, const SCEV *FoundLHS,
@@ -1065,18 +1085,6 @@ private:
bool isMonotonicPredicateImpl(const SCEVAddRecExpr *LHS,
ICmpInst::Predicate Pred, bool &Increasing);
- /// Return true if, for all loop invariant X, the predicate "LHS `Pred` X"
- /// is monotonically increasing or decreasing. In the former case set
- /// `Increasing` to true and in the latter case set `Increasing` to false.
- ///
- /// A predicate is said to be monotonically increasing if may go from being
- /// false to being true as the loop iterates, but never the other way
- /// around. A predicate is said to be monotonically decreasing if may go
- /// from being true to being false as the loop iterates, but never the other
- /// way around.
- bool isMonotonicPredicate(const SCEVAddRecExpr *LHS, ICmpInst::Predicate Pred,
- bool &Increasing);
-
/// Return SCEV no-wrap flags that can be proven based on reasoning about
/// how poison produced from no-wrap flags on this value (e.g. a nuw add)
/// would trigger undefined behavior on overflow.
@@ -1129,6 +1137,9 @@ public:
/// return true. For pointer types, this is the pointer-sized integer type.
Type *getEffectiveSCEVType(Type *Ty) const;
+ // Returns a wider type among {Ty1, Ty2}.
+ Type *getWiderType(Type *Ty1, Type *Ty2) const;
+
/// Return true if the SCEV is a scAddRecExpr or it contains
/// scAddRecExpr. The result will be cached in HasRecMap.
///
@@ -1152,7 +1163,8 @@ public:
const SCEV *getSignExtendExpr(const SCEV *Op, Type *Ty);
const SCEV *getAnyExtendExpr(const SCEV *Op, Type *Ty);
const SCEV *getAddExpr(SmallVectorImpl<const SCEV *> &Ops,
- SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap);
+ SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap,
+ unsigned Depth = 0);
const SCEV *getAddExpr(const SCEV *LHS, const SCEV *RHS,
SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap) {
SmallVector<const SCEV *, 2> Ops = {LHS, RHS};
@@ -1301,7 +1313,7 @@ public:
///
/// Implemented in terms of the \c getSmallConstantTripCount overload with
/// the single exiting block passed to it. See that routine for details.
- unsigned getSmallConstantTripCount(Loop *L);
+ unsigned getSmallConstantTripCount(const Loop *L);
/// Returns the maximum trip count of this loop as a normal unsigned
/// value. Returns 0 if the trip count is unknown or not constant. This
@@ -1310,12 +1322,12 @@ public:
/// before taking the branch. For loops with multiple exits, it may not be
/// the number times that the loop header executes if the loop exits
/// prematurely via another branch.
- unsigned getSmallConstantTripCount(Loop *L, BasicBlock *ExitingBlock);
+ unsigned getSmallConstantTripCount(const Loop *L, BasicBlock *ExitingBlock);
/// Returns the upper bound of the loop trip count as a normal unsigned
/// value.
/// Returns 0 if the trip count is unknown or not constant.
- unsigned getSmallConstantMaxTripCount(Loop *L);
+ unsigned getSmallConstantMaxTripCount(const Loop *L);
/// Returns the largest constant divisor of the trip count of the
/// loop if it is a single-exit loop and we can compute a small maximum for
@@ -1323,7 +1335,7 @@ public:
///
/// Implemented in terms of the \c getSmallConstantTripMultiple overload with
/// the single exiting block passed to it. See that routine for details.
- unsigned getSmallConstantTripMultiple(Loop *L);
+ unsigned getSmallConstantTripMultiple(const Loop *L);
/// Returns the largest constant divisor of the trip count of this loop as a
/// normal unsigned value, if possible. This means that the actual trip
@@ -1331,12 +1343,13 @@ public:
/// count could very well be zero as well!). As explained in the comments
/// for getSmallConstantTripCount, this assumes that control exits the loop
/// via ExitingBlock.
- unsigned getSmallConstantTripMultiple(Loop *L, BasicBlock *ExitingBlock);
+ unsigned getSmallConstantTripMultiple(const Loop *L,
+ BasicBlock *ExitingBlock);
/// Get the expression for the number of loop iterations for which this loop
/// is guaranteed not to exit via ExitingBlock. Otherwise return
/// SCEVCouldNotCompute.
- const SCEV *getExitCount(Loop *L, BasicBlock *ExitingBlock);
+ const SCEV *getExitCount(const Loop *L, BasicBlock *ExitingBlock);
/// If the specified loop has a predictable backedge-taken count, return it,
/// otherwise return a SCEVCouldNotCompute object. The backedge-taken count
@@ -1432,6 +1445,18 @@ public:
bool isKnownPredicate(ICmpInst::Predicate Pred, const SCEV *LHS,
const SCEV *RHS);
+ /// Return true if, for all loop invariant X, the predicate "LHS `Pred` X"
+ /// is monotonically increasing or decreasing. In the former case set
+ /// `Increasing` to true and in the latter case set `Increasing` to false.
+ ///
+ /// A predicate is said to be monotonically increasing if may go from being
+ /// false to being true as the loop iterates, but never the other way
+ /// around. A predicate is said to be monotonically decreasing if may go
+ /// from being true to being false as the loop iterates, but never the other
+ /// way around.
+ bool isMonotonicPredicate(const SCEVAddRecExpr *LHS, ICmpInst::Predicate Pred,
+ bool &Increasing);
+
/// Return true if the result of the predicate LHS `Pred` RHS is loop
/// invariant with respect to L. Set InvariantPred, InvariantLHS and
/// InvariantLHS so that InvariantLHS `InvariantPred` InvariantRHS is the
@@ -1613,6 +1638,10 @@ private:
bool doesIVOverflowOnGT(const SCEV *RHS, const SCEV *Stride, bool IsSigned,
bool NoWrap);
+ /// Get add expr already created or create a new one
+ const SCEV *getOrCreateAddExpr(SmallVectorImpl<const SCEV *> &Ops,
+ SCEV::NoWrapFlags Flags);
+
private:
FoldingSet<SCEV> UniqueSCEVs;
FoldingSet<SCEVPredicate> UniquePreds;
diff --git a/include/llvm/Analysis/ScalarEvolutionExpressions.h b/include/llvm/Analysis/ScalarEvolutionExpressions.h
index fdcd8be00dde..2c693bceb24d 100644
--- a/include/llvm/Analysis/ScalarEvolutionExpressions.h
+++ b/include/llvm/Analysis/ScalarEvolutionExpressions.h
@@ -595,58 +595,82 @@ namespace llvm {
const SCEV *visitTruncateExpr(const SCEVTruncateExpr *Expr) {
const SCEV *Operand = ((SC*)this)->visit(Expr->getOperand());
- return SE.getTruncateExpr(Operand, Expr->getType());
+ return Operand == Expr->getOperand()
+ ? Expr
+ : SE.getTruncateExpr(Operand, Expr->getType());
}
const SCEV *visitZeroExtendExpr(const SCEVZeroExtendExpr *Expr) {
const SCEV *Operand = ((SC*)this)->visit(Expr->getOperand());
- return SE.getZeroExtendExpr(Operand, Expr->getType());
+ return Operand == Expr->getOperand()
+ ? Expr
+ : SE.getZeroExtendExpr(Operand, Expr->getType());
}
const SCEV *visitSignExtendExpr(const SCEVSignExtendExpr *Expr) {
const SCEV *Operand = ((SC*)this)->visit(Expr->getOperand());
- return SE.getSignExtendExpr(Operand, Expr->getType());
+ return Operand == Expr->getOperand()
+ ? Expr
+ : SE.getSignExtendExpr(Operand, Expr->getType());
}
const SCEV *visitAddExpr(const SCEVAddExpr *Expr) {
SmallVector<const SCEV *, 2> Operands;
- for (int i = 0, e = Expr->getNumOperands(); i < e; ++i)
- Operands.push_back(((SC*)this)->visit(Expr->getOperand(i)));
- return SE.getAddExpr(Operands);
+ bool Changed = false;
+ for (auto *Op : Expr->operands()) {
+ Operands.push_back(((SC*)this)->visit(Op));
+ Changed |= Op != Operands.back();
+ }
+ return !Changed ? Expr : SE.getAddExpr(Operands);
}
const SCEV *visitMulExpr(const SCEVMulExpr *Expr) {
SmallVector<const SCEV *, 2> Operands;
- for (int i = 0, e = Expr->getNumOperands(); i < e; ++i)
- Operands.push_back(((SC*)this)->visit(Expr->getOperand(i)));
- return SE.getMulExpr(Operands);
+ bool Changed = false;
+ for (auto *Op : Expr->operands()) {
+ Operands.push_back(((SC*)this)->visit(Op));
+ Changed |= Op != Operands.back();
+ }
+ return !Changed ? Expr : SE.getMulExpr(Operands);
}
const SCEV *visitUDivExpr(const SCEVUDivExpr *Expr) {
- return SE.getUDivExpr(((SC*)this)->visit(Expr->getLHS()),
- ((SC*)this)->visit(Expr->getRHS()));
+ auto *LHS = ((SC *)this)->visit(Expr->getLHS());
+ auto *RHS = ((SC *)this)->visit(Expr->getRHS());
+ bool Changed = LHS != Expr->getLHS() || RHS != Expr->getRHS();
+ return !Changed ? Expr : SE.getUDivExpr(LHS, RHS);
}
const SCEV *visitAddRecExpr(const SCEVAddRecExpr *Expr) {
SmallVector<const SCEV *, 2> Operands;
- for (int i = 0, e = Expr->getNumOperands(); i < e; ++i)
- Operands.push_back(((SC*)this)->visit(Expr->getOperand(i)));
- return SE.getAddRecExpr(Operands, Expr->getLoop(),
- Expr->getNoWrapFlags());
+ bool Changed = false;
+ for (auto *Op : Expr->operands()) {
+ Operands.push_back(((SC*)this)->visit(Op));
+ Changed |= Op != Operands.back();
+ }
+ return !Changed ? Expr
+ : SE.getAddRecExpr(Operands, Expr->getLoop(),
+ Expr->getNoWrapFlags());
}
const SCEV *visitSMaxExpr(const SCEVSMaxExpr *Expr) {
SmallVector<const SCEV *, 2> Operands;
- for (int i = 0, e = Expr->getNumOperands(); i < e; ++i)
- Operands.push_back(((SC*)this)->visit(Expr->getOperand(i)));
- return SE.getSMaxExpr(Operands);
+ bool Changed = false;
+ for (auto *Op : Expr->operands()) {
+ Operands.push_back(((SC *)this)->visit(Op));
+ Changed |= Op != Operands.back();
+ }
+ return !Changed ? Expr : SE.getSMaxExpr(Operands);
}
const SCEV *visitUMaxExpr(const SCEVUMaxExpr *Expr) {
SmallVector<const SCEV *, 2> Operands;
- for (int i = 0, e = Expr->getNumOperands(); i < e; ++i)
- Operands.push_back(((SC*)this)->visit(Expr->getOperand(i)));
- return SE.getUMaxExpr(Operands);
+ bool Changed = false;
+ for (auto *Op : Expr->operands()) {
+ Operands.push_back(((SC*)this)->visit(Op));
+ Changed |= Op != Operands.back();
+ }
+ return !Changed ? Expr : SE.getUMaxExpr(Operands);
}
const SCEV *visitUnknown(const SCEVUnknown *Expr) {
diff --git a/include/llvm/Analysis/ScalarEvolutionNormalization.h b/include/llvm/Analysis/ScalarEvolutionNormalization.h
index 7c6423a21cfa..b73ad95278a0 100644
--- a/include/llvm/Analysis/ScalarEvolutionNormalization.h
+++ b/include/llvm/Analysis/ScalarEvolutionNormalization.h
@@ -37,42 +37,33 @@
#define LLVM_ANALYSIS_SCALAREVOLUTIONNORMALIZATION_H
#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Analysis/ScalarEvolutionExpressions.h"
namespace llvm {
-class Instruction;
-class DominatorTree;
class Loop;
class ScalarEvolution;
class SCEV;
-class Value;
-/// TransformKind - Different types of transformations that
-/// TransformForPostIncUse can do.
-enum TransformKind {
- /// Normalize - Normalize according to the given loops.
- Normalize,
- /// NormalizeAutodetect - Detect post-inc opportunities on new expressions,
- /// update the given loop set, and normalize.
- NormalizeAutodetect,
- /// Denormalize - Perform the inverse transform on the expression with the
- /// given loop set.
- Denormalize
-};
-
-/// PostIncLoopSet - A set of loops.
typedef SmallPtrSet<const Loop *, 2> PostIncLoopSet;
-/// TransformForPostIncUse - Transform the given expression according to the
-/// given transformation kind.
-const SCEV *TransformForPostIncUse(TransformKind Kind,
- const SCEV *S,
- Instruction *User,
- Value *OperandValToReplace,
- PostIncLoopSet &Loops,
- ScalarEvolution &SE,
- DominatorTree &DT);
+typedef function_ref<bool(const SCEVAddRecExpr *)> NormalizePredTy;
+
+/// Normalize \p S to be post-increment for all loops present in \p
+/// Loops.
+const SCEV *normalizeForPostIncUse(const SCEV *S, const PostIncLoopSet &Loops,
+ ScalarEvolution &SE);
+
+/// Normalize \p S for all add recurrence sub-expressions for which \p
+/// Pred returns true.
+const SCEV *normalizeForPostIncUseIf(const SCEV *S, NormalizePredTy Pred,
+ ScalarEvolution &SE);
-}
+/// Denormalize \p S to be post-increment for all loops present in \p
+/// Loops.
+const SCEV *denormalizeForPostIncUse(const SCEV *S, const PostIncLoopSet &Loops,
+ ScalarEvolution &SE);
+} // namespace llvm
#endif
diff --git a/include/llvm/Analysis/TargetLibraryInfo.def b/include/llvm/Analysis/TargetLibraryInfo.def
index 5d5e5b127e63..637fc7ed30dd 100644
--- a/include/llvm/Analysis/TargetLibraryInfo.def
+++ b/include/llvm/Analysis/TargetLibraryInfo.def
@@ -20,7 +20,7 @@
// 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_ENUM_INTERNAL(enum_variant) LibFunc_##enum_variant,
#define TLI_DEFINE_STRING_INTERNAL(string_repr)
#else
#define TLI_DEFINE_ENUM_INTERNAL(enum_variant)
diff --git a/include/llvm/Analysis/TargetLibraryInfo.h b/include/llvm/Analysis/TargetLibraryInfo.h
index 8675882431d5..944250cfd6ac 100644
--- a/include/llvm/Analysis/TargetLibraryInfo.h
+++ b/include/llvm/Analysis/TargetLibraryInfo.h
@@ -30,14 +30,12 @@ struct VecDesc {
unsigned VectorizationFactor;
};
- namespace LibFunc {
- enum Func {
+ enum LibFunc {
#define TLI_DEFINE_ENUM
#include "llvm/Analysis/TargetLibraryInfo.def"
- NumLibFuncs
- };
- }
+ NumLibFuncs
+ };
/// Implementation of the target library information.
///
@@ -48,9 +46,9 @@ struct VecDesc {
class TargetLibraryInfoImpl {
friend class TargetLibraryInfo;
- unsigned char AvailableArray[(LibFunc::NumLibFuncs+3)/4];
+ unsigned char AvailableArray[(NumLibFuncs+3)/4];
llvm::DenseMap<unsigned, std::string> CustomNames;
- static StringRef const StandardNames[LibFunc::NumLibFuncs];
+ static StringRef const StandardNames[NumLibFuncs];
bool ShouldExtI32Param, ShouldExtI32Return, ShouldSignExtI32Param;
enum AvailabilityState {
@@ -58,11 +56,11 @@ class TargetLibraryInfoImpl {
CustomName = 1,
Unavailable = 0 // (memset to all zeros)
};
- void setState(LibFunc::Func F, AvailabilityState State) {
+ void setState(LibFunc F, AvailabilityState State) {
AvailableArray[F/4] &= ~(3 << 2*(F&3));
AvailableArray[F/4] |= State << 2*(F&3);
}
- AvailabilityState getState(LibFunc::Func F) const {
+ AvailabilityState getState(LibFunc F) const {
return static_cast<AvailabilityState>((AvailableArray[F/4] >> 2*(F&3)) & 3);
}
@@ -74,7 +72,7 @@ class TargetLibraryInfoImpl {
/// Return true if the function type FTy is valid for the library function
/// F, regardless of whether the function is available.
- bool isValidProtoForLibFunc(const FunctionType &FTy, LibFunc::Func F,
+ bool isValidProtoForLibFunc(const FunctionType &FTy, LibFunc F,
const DataLayout *DL) const;
public:
@@ -104,28 +102,28 @@ public:
///
/// 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;
+ bool getLibFunc(StringRef funcName, LibFunc &F) const;
/// Searches for a particular function name, also checking that its type is
/// valid for the library function matching that name.
///
/// If it is one of the known library functions, return true and set F to the
/// corresponding value.
- bool getLibFunc(const Function &FDecl, LibFunc::Func &F) const;
+ bool getLibFunc(const Function &FDecl, LibFunc &F) const;
/// Forces a function to be marked as unavailable.
- void setUnavailable(LibFunc::Func F) {
+ void setUnavailable(LibFunc F) {
setState(F, Unavailable);
}
/// Forces a function to be marked as available.
- void setAvailable(LibFunc::Func F) {
+ void setAvailable(LibFunc F) {
setState(F, StandardName);
}
/// Forces a function to be marked as available and provide an alternate name
/// that must be used.
- void setAvailableWithName(LibFunc::Func F, StringRef Name) {
+ void setAvailableWithName(LibFunc F, StringRef Name) {
if (StandardNames[F] != Name) {
setState(F, CustomName);
CustomNames[F] = Name;
@@ -225,16 +223,16 @@ public:
///
/// 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 {
+ bool getLibFunc(StringRef funcName, LibFunc &F) const {
return Impl->getLibFunc(funcName, F);
}
- bool getLibFunc(const Function &FDecl, LibFunc::Func &F) const {
+ bool getLibFunc(const Function &FDecl, LibFunc &F) const {
return Impl->getLibFunc(FDecl, F);
}
/// Tests whether a library function is available.
- bool has(LibFunc::Func F) const {
+ bool has(LibFunc F) const {
return Impl->getState(F) != TargetLibraryInfoImpl::Unavailable;
}
bool isFunctionVectorizable(StringRef F, unsigned VF) const {
@@ -249,37 +247,37 @@ public:
/// Tests if the function is both available and a candidate for optimized code
/// generation.
- bool hasOptimizedCodeGen(LibFunc::Func F) const {
+ bool hasOptimizedCodeGen(LibFunc 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: case LibFunc::mempcpy:
+ 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: case LibFunc_mempcpy:
return true;
}
return false;
}
- StringRef getName(LibFunc::Func F) const {
+ StringRef getName(LibFunc F) const {
auto State = Impl->getState(F);
if (State == TargetLibraryInfoImpl::Unavailable)
return StringRef();
diff --git a/include/llvm/Analysis/TargetTransformInfo.h b/include/llvm/Analysis/TargetTransformInfo.h
index 209f05c279d0..67196687d556 100644
--- a/include/llvm/Analysis/TargetTransformInfo.h
+++ b/include/llvm/Analysis/TargetTransformInfo.h
@@ -44,23 +44,26 @@ class Value;
/// \brief Information about a load/store intrinsic defined by the target.
struct MemIntrinsicInfo {
- MemIntrinsicInfo()
- : ReadMem(false), WriteMem(false), IsSimple(false), MatchingId(0),
- NumMemRefs(0), PtrVal(nullptr) {}
- bool ReadMem;
- bool WriteMem;
- /// True only if this memory operation is non-volatile, non-atomic, and
- /// unordered. (See LoadInst/StoreInst for details on each)
- bool IsSimple;
- // Same Id is set by the target for corresponding load/store intrinsics.
- unsigned short MatchingId;
- int NumMemRefs;
-
/// This is the pointer that the intrinsic is loading from or storing to.
/// If this is non-null, then analysis/optimization passes can assume that
/// this intrinsic is functionally equivalent to a load/store from this
/// pointer.
- Value *PtrVal;
+ Value *PtrVal = nullptr;
+
+ // Ordering for atomic operations.
+ AtomicOrdering Ordering = AtomicOrdering::NotAtomic;
+
+ // Same Id is set by the target for corresponding load/store intrinsics.
+ unsigned short MatchingId = 0;
+
+ bool ReadMem = false;
+ bool WriteMem = false;
+ bool IsVolatile = false;
+
+ bool isUnordered() const {
+ return (Ordering == AtomicOrdering::NotAtomic ||
+ Ordering == AtomicOrdering::Unordered) && !IsVolatile;
+ }
};
/// \brief This pass provides access to the codegen interfaces that are needed
@@ -226,6 +229,24 @@ public:
/// starting with the sources of divergence.
bool isSourceOfDivergence(const Value *V) const;
+ /// Returns the address space ID for a target's 'flat' address space. Note
+ /// this is not necessarily the same as addrspace(0), which LLVM sometimes
+ /// refers to as the generic address space. The flat address space is a
+ /// generic address space that can be used access multiple segments of memory
+ /// with different address spaces. Access of a memory location through a
+ /// pointer with this address space is expected to be legal but slower
+ /// compared to the same memory location accessed through a pointer with a
+ /// different address space.
+ //
+ /// This is for for targets with different pointer representations which can
+ /// be converted with the addrspacecast instruction. If a pointer is converted
+ /// to this address space, optimizations should attempt to replace the access
+ /// with the source address space.
+ ///
+ /// \returns ~0u if the target does not have such a flat address space to
+ /// optimize away.
+ unsigned getFlatAddressSpace() const;
+
/// \brief Test whether calls to a function lower to actual program function
/// calls.
///
@@ -411,6 +432,16 @@ public:
/// containing this constant value for the target.
bool shouldBuildLookupTablesForConstant(Constant *C) const;
+ unsigned getScalarizationOverhead(Type *Ty, bool Insert, bool Extract) const;
+
+ unsigned getOperandsScalarizationOverhead(ArrayRef<const Value *> Args,
+ unsigned VF) const;
+
+ /// If target has efficient vector element load/store instructions, it can
+ /// return true here so that insertion/extraction costs are not added to
+ /// the scalarization cost of a load/store.
+ bool supportsEfficientVectorElementLoadStore() const;
+
/// \brief Don't restrict interleaved unrolling to small loops.
bool enableAggressiveInterleaving(bool LoopHasReductions) const;
@@ -500,6 +531,12 @@ public:
/// \return The width of the largest scalar or vector register type.
unsigned getRegisterBitWidth(bool Vector) const;
+ /// \return True if it should be considered for address type promotion.
+ /// \p AllowPromotionWithoutCommonHeader Set true if promoting \p I is
+ /// profitable without finding other extensions fed by the same input.
+ bool shouldConsiderAddressTypePromotion(
+ const Instruction &I, bool &AllowPromotionWithoutCommonHeader) const;
+
/// \return The size of a cache line in bytes.
unsigned getCacheLineSize() const;
@@ -540,8 +577,10 @@ public:
Type *SubTp = nullptr) const;
/// \return The expected cost of cast instructions, such as bitcast, trunc,
- /// zext, etc.
- int getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src) const;
+ /// zext, etc. If there is an existing instruction that holds Opcode, it
+ /// may be passed in the 'I' parameter.
+ int getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src,
+ const Instruction *I = nullptr) const;
/// \return The expected cost of a sign- or zero-extended vector extract. Use
/// -1 to indicate that there is no information about the index value.
@@ -552,9 +591,11 @@ public:
/// Phi, Ret, Br.
int getCFInstrCost(unsigned Opcode) const;
- /// \returns The expected cost of compare and select instructions.
+ /// \returns The expected cost of compare and select instructions. If there
+ /// is an existing instruction that holds Opcode, it may be passed in the
+ /// 'I' parameter.
int getCmpSelInstrCost(unsigned Opcode, Type *ValTy,
- Type *CondTy = nullptr) const;
+ Type *CondTy = nullptr, const Instruction *I = nullptr) const;
/// \return The expected cost of vector Insert and Extract.
/// Use -1 to indicate that there is no information on the index value.
@@ -562,7 +603,7 @@ public:
/// \return The cost of Load and Store instructions.
int getMemoryOpCost(unsigned Opcode, Type *Src, unsigned Alignment,
- unsigned AddressSpace) const;
+ unsigned AddressSpace, const Instruction *I = nullptr) const;
/// \return The cost of masked Load and Store instructions.
int getMaskedMemoryOpCost(unsigned Opcode, Type *Src, unsigned Alignment,
@@ -605,13 +646,19 @@ public:
/// ((v0+v2), (v1+v3), undef, undef)
int getReductionCost(unsigned Opcode, Type *Ty, bool IsPairwiseForm) const;
- /// \returns The cost of Intrinsic instructions. Types analysis only.
+ /// \returns The cost of Intrinsic instructions. Analyses the real arguments.
+ /// Three cases are handled: 1. scalar instruction 2. vector instruction
+ /// 3. scalar instruction which is to be vectorized with VF.
int getIntrinsicInstrCost(Intrinsic::ID ID, Type *RetTy,
- ArrayRef<Type *> Tys, FastMathFlags FMF) const;
+ ArrayRef<Value *> Args, FastMathFlags FMF,
+ unsigned VF = 1) const;
- /// \returns The cost of Intrinsic instructions. Analyses the real arguments.
+ /// \returns The cost of Intrinsic instructions. Types analysis only.
+ /// If ScalarizationCostPassed is UINT_MAX, the cost of scalarizing the
+ /// arguments and the return value will be computed based on types.
int getIntrinsicInstrCost(Intrinsic::ID ID, Type *RetTy,
- ArrayRef<Value *> Args, FastMathFlags FMF) const;
+ ArrayRef<Type *> Tys, FastMathFlags FMF,
+ unsigned ScalarizationCostPassed = UINT_MAX) const;
/// \returns The cost of Call instructions.
int getCallInstrCost(Function *F, Type *RetTy, ArrayRef<Type *> Tys) const;
@@ -720,6 +767,7 @@ public:
virtual int getUserCost(const User *U) = 0;
virtual bool hasBranchDivergence() = 0;
virtual bool isSourceOfDivergence(const Value *V) = 0;
+ virtual unsigned getFlatAddressSpace() = 0;
virtual bool isLoweredToCall(const Function *F) = 0;
virtual void getUnrollingPreferences(Loop *L, UnrollingPreferences &UP) = 0;
virtual bool isLegalAddImmediate(int64_t Imm) = 0;
@@ -743,6 +791,11 @@ public:
virtual unsigned getJumpBufSize() = 0;
virtual bool shouldBuildLookupTables() = 0;
virtual bool shouldBuildLookupTablesForConstant(Constant *C) = 0;
+ virtual unsigned
+ getScalarizationOverhead(Type *Ty, bool Insert, bool Extract) = 0;
+ virtual unsigned getOperandsScalarizationOverhead(ArrayRef<const Value *> Args,
+ unsigned VF) = 0;
+ virtual bool supportsEfficientVectorElementLoadStore() = 0;
virtual bool enableAggressiveInterleaving(bool LoopHasReductions) = 0;
virtual bool enableInterleavedAccessVectorization() = 0;
virtual bool isFPVectorizationPotentiallyUnsafe() = 0;
@@ -763,6 +816,8 @@ public:
Type *Ty) = 0;
virtual unsigned getNumberOfRegisters(bool Vector) = 0;
virtual unsigned getRegisterBitWidth(bool Vector) = 0;
+ virtual bool shouldConsiderAddressTypePromotion(
+ const Instruction &I, bool &AllowPromotionWithoutCommonHeader) = 0;
virtual unsigned getCacheLineSize() = 0;
virtual unsigned getPrefetchDistance() = 0;
virtual unsigned getMinPrefetchStride() = 0;
@@ -776,16 +831,17 @@ public:
ArrayRef<const Value *> Args) = 0;
virtual int getShuffleCost(ShuffleKind Kind, Type *Tp, int Index,
Type *SubTp) = 0;
- virtual int getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src) = 0;
+ virtual int getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src,
+ const Instruction *I) = 0;
virtual int getExtractWithExtendCost(unsigned Opcode, Type *Dst,
VectorType *VecTy, unsigned Index) = 0;
virtual int getCFInstrCost(unsigned Opcode) = 0;
virtual int getCmpSelInstrCost(unsigned Opcode, Type *ValTy,
- Type *CondTy) = 0;
+ Type *CondTy, const Instruction *I) = 0;
virtual int getVectorInstrCost(unsigned Opcode, Type *Val,
unsigned Index) = 0;
virtual int getMemoryOpCost(unsigned Opcode, Type *Src, unsigned Alignment,
- unsigned AddressSpace) = 0;
+ unsigned AddressSpace, const Instruction *I) = 0;
virtual int getMaskedMemoryOpCost(unsigned Opcode, Type *Src,
unsigned Alignment,
unsigned AddressSpace) = 0;
@@ -800,11 +856,10 @@ public:
virtual int getReductionCost(unsigned Opcode, Type *Ty,
bool IsPairwiseForm) = 0;
virtual int getIntrinsicInstrCost(Intrinsic::ID ID, Type *RetTy,
- ArrayRef<Type *> Tys,
- FastMathFlags FMF) = 0;
+ ArrayRef<Type *> Tys, FastMathFlags FMF,
+ unsigned ScalarizationCostPassed) = 0;
virtual int getIntrinsicInstrCost(Intrinsic::ID ID, Type *RetTy,
- ArrayRef<Value *> Args,
- FastMathFlags FMF) = 0;
+ ArrayRef<Value *> Args, FastMathFlags FMF, unsigned VF) = 0;
virtual int getCallInstrCost(Function *F, Type *RetTy,
ArrayRef<Type *> Tys) = 0;
virtual unsigned getNumberOfParts(Type *Tp) = 0;
@@ -879,6 +934,11 @@ public:
bool isSourceOfDivergence(const Value *V) override {
return Impl.isSourceOfDivergence(V);
}
+
+ unsigned getFlatAddressSpace() override {
+ return Impl.getFlatAddressSpace();
+ }
+
bool isLoweredToCall(const Function *F) override {
return Impl.isLoweredToCall(F);
}
@@ -933,6 +993,19 @@ public:
bool shouldBuildLookupTablesForConstant(Constant *C) override {
return Impl.shouldBuildLookupTablesForConstant(C);
}
+ unsigned getScalarizationOverhead(Type *Ty, bool Insert,
+ bool Extract) override {
+ return Impl.getScalarizationOverhead(Ty, Insert, Extract);
+ }
+ unsigned getOperandsScalarizationOverhead(ArrayRef<const Value *> Args,
+ unsigned VF) override {
+ return Impl.getOperandsScalarizationOverhead(Args, VF);
+ }
+
+ bool supportsEfficientVectorElementLoadStore() override {
+ return Impl.supportsEfficientVectorElementLoadStore();
+ }
+
bool enableAggressiveInterleaving(bool LoopHasReductions) override {
return Impl.enableAggressiveInterleaving(LoopHasReductions);
}
@@ -976,7 +1049,11 @@ public:
unsigned getRegisterBitWidth(bool Vector) override {
return Impl.getRegisterBitWidth(Vector);
}
-
+ bool shouldConsiderAddressTypePromotion(
+ const Instruction &I, bool &AllowPromotionWithoutCommonHeader) override {
+ return Impl.shouldConsiderAddressTypePromotion(
+ I, AllowPromotionWithoutCommonHeader);
+ }
unsigned getCacheLineSize() override {
return Impl.getCacheLineSize();
}
@@ -1003,8 +1080,9 @@ public:
Type *SubTp) override {
return Impl.getShuffleCost(Kind, Tp, Index, SubTp);
}
- int getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src) override {
- return Impl.getCastInstrCost(Opcode, Dst, Src);
+ int getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src,
+ const Instruction *I) override {
+ return Impl.getCastInstrCost(Opcode, Dst, Src, I);
}
int getExtractWithExtendCost(unsigned Opcode, Type *Dst, VectorType *VecTy,
unsigned Index) override {
@@ -1013,15 +1091,16 @@ public:
int getCFInstrCost(unsigned Opcode) override {
return Impl.getCFInstrCost(Opcode);
}
- int getCmpSelInstrCost(unsigned Opcode, Type *ValTy, Type *CondTy) override {
- return Impl.getCmpSelInstrCost(Opcode, ValTy, CondTy);
+ int getCmpSelInstrCost(unsigned Opcode, Type *ValTy, Type *CondTy,
+ const Instruction *I) override {
+ return Impl.getCmpSelInstrCost(Opcode, ValTy, CondTy, I);
}
int getVectorInstrCost(unsigned Opcode, Type *Val, unsigned Index) override {
return Impl.getVectorInstrCost(Opcode, Val, Index);
}
int getMemoryOpCost(unsigned Opcode, Type *Src, unsigned Alignment,
- unsigned AddressSpace) override {
- return Impl.getMemoryOpCost(Opcode, Src, Alignment, AddressSpace);
+ unsigned AddressSpace, const Instruction *I) override {
+ return Impl.getMemoryOpCost(Opcode, Src, Alignment, AddressSpace, I);
}
int getMaskedMemoryOpCost(unsigned Opcode, Type *Src, unsigned Alignment,
unsigned AddressSpace) override {
@@ -1044,13 +1123,13 @@ public:
return Impl.getReductionCost(Opcode, Ty, IsPairwiseForm);
}
int getIntrinsicInstrCost(Intrinsic::ID ID, Type *RetTy, ArrayRef<Type *> Tys,
- FastMathFlags FMF) override {
- return Impl.getIntrinsicInstrCost(ID, RetTy, Tys, FMF);
+ FastMathFlags FMF, unsigned ScalarizationCostPassed) override {
+ return Impl.getIntrinsicInstrCost(ID, RetTy, Tys, FMF,
+ ScalarizationCostPassed);
}
int getIntrinsicInstrCost(Intrinsic::ID ID, Type *RetTy,
- ArrayRef<Value *> Args,
- FastMathFlags FMF) override {
- return Impl.getIntrinsicInstrCost(ID, RetTy, Args, FMF);
+ ArrayRef<Value *> Args, FastMathFlags FMF, unsigned VF) override {
+ return Impl.getIntrinsicInstrCost(ID, RetTy, Args, FMF, VF);
}
int getCallInstrCost(Function *F, Type *RetTy,
ArrayRef<Type *> Tys) override {
diff --git a/include/llvm/Analysis/TargetTransformInfoImpl.h b/include/llvm/Analysis/TargetTransformInfoImpl.h
index cafc40723c9d..9ab6b7445ab8 100644
--- a/include/llvm/Analysis/TargetTransformInfoImpl.h
+++ b/include/llvm/Analysis/TargetTransformInfoImpl.h
@@ -171,6 +171,10 @@ public:
bool isSourceOfDivergence(const Value *V) { return false; }
+ unsigned getFlatAddressSpace () {
+ return -1;
+ }
+
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
@@ -251,6 +255,15 @@ public:
bool shouldBuildLookupTables() { return true; }
bool shouldBuildLookupTablesForConstant(Constant *C) { return true; }
+ unsigned getScalarizationOverhead(Type *Ty, bool Insert, bool Extract) {
+ return 0;
+ }
+
+ unsigned getOperandsScalarizationOverhead(ArrayRef<const Value *> Args,
+ unsigned VF) { return 0; }
+
+ bool supportsEfficientVectorElementLoadStore() { return false; }
+
bool enableAggressiveInterleaving(bool LoopHasReductions) { return false; }
bool enableInterleavedAccessVectorization() { return false; }
@@ -292,6 +305,13 @@ public:
unsigned getRegisterBitWidth(bool Vector) { return 32; }
+ bool
+ shouldConsiderAddressTypePromotion(const Instruction &I,
+ bool &AllowPromotionWithoutCommonHeader) {
+ AllowPromotionWithoutCommonHeader = false;
+ return false;
+ }
+
unsigned getCacheLineSize() { return 0; }
unsigned getPrefetchDistance() { return 0; }
@@ -316,7 +336,8 @@ public:
return 1;
}
- unsigned getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src) { return 1; }
+ unsigned getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src,
+ const Instruction *I) { return 1; }
unsigned getExtractWithExtendCost(unsigned Opcode, Type *Dst,
VectorType *VecTy, unsigned Index) {
@@ -325,7 +346,8 @@ public:
unsigned getCFInstrCost(unsigned Opcode) { return 1; }
- unsigned getCmpSelInstrCost(unsigned Opcode, Type *ValTy, Type *CondTy) {
+ unsigned getCmpSelInstrCost(unsigned Opcode, Type *ValTy, Type *CondTy,
+ const Instruction *I) {
return 1;
}
@@ -334,7 +356,7 @@ public:
}
unsigned getMemoryOpCost(unsigned Opcode, Type *Src, unsigned Alignment,
- unsigned AddressSpace) {
+ unsigned AddressSpace, const Instruction *I) {
return 1;
}
@@ -358,11 +380,12 @@ public:
}
unsigned getIntrinsicInstrCost(Intrinsic::ID ID, Type *RetTy,
- ArrayRef<Type *> Tys, FastMathFlags FMF) {
+ ArrayRef<Type *> Tys, FastMathFlags FMF,
+ unsigned ScalarizationCostPassed) {
return 1;
}
unsigned getIntrinsicInstrCost(Intrinsic::ID ID, Type *RetTy,
- ArrayRef<Value *> Args, FastMathFlags FMF) {
+ ArrayRef<Value *> Args, FastMathFlags FMF, unsigned VF) {
return 1;
}
diff --git a/include/llvm/Analysis/TypeMetadataUtils.h b/include/llvm/Analysis/TypeMetadataUtils.h
index c3f688f5d7f1..17906ba4e392 100644
--- a/include/llvm/Analysis/TypeMetadataUtils.h
+++ b/include/llvm/Analysis/TypeMetadataUtils.h
@@ -32,14 +32,15 @@ struct DevirtCallSite {
/// call sites based on the call and return them in DevirtCalls.
void findDevirtualizableCallsForTypeTest(
SmallVectorImpl<DevirtCallSite> &DevirtCalls,
- SmallVectorImpl<CallInst *> &Assumes, CallInst *CI);
+ SmallVectorImpl<CallInst *> &Assumes, const CallInst *CI);
/// Given a call to the intrinsic @llvm.type.checked.load, find all
/// devirtualizable call sites based on the call and return them in DevirtCalls.
void findDevirtualizableCallsForTypeCheckedLoad(
SmallVectorImpl<DevirtCallSite> &DevirtCalls,
SmallVectorImpl<Instruction *> &LoadedPtrs,
- SmallVectorImpl<Instruction *> &Preds, bool &HasNonCallUses, CallInst *CI);
+ SmallVectorImpl<Instruction *> &Preds, bool &HasNonCallUses,
+ const CallInst *CI);
}
#endif
diff --git a/include/llvm/Analysis/ValueTracking.h b/include/llvm/Analysis/ValueTracking.h
index aaf6f888e06f..e3c2f3bed227 100644
--- a/include/llvm/Analysis/ValueTracking.h
+++ b/include/llvm/Analysis/ValueTracking.h
@@ -31,6 +31,7 @@ template <typename T> class ArrayRef;
class Instruction;
class Loop;
class LoopInfo;
+ class OptimizationRemarkEmitter;
class MDNode;
class StringRef;
class TargetLibraryInfo;
@@ -52,7 +53,8 @@ template <typename T> class ArrayRef;
const DataLayout &DL, unsigned Depth = 0,
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr,
- const DominatorTree *DT = nullptr);
+ const DominatorTree *DT = nullptr,
+ OptimizationRemarkEmitter *ORE = nullptr);
/// Compute known bits from the range metadata.
/// \p KnownZero the set of bits that are known to be zero
/// \p KnownOne the set of bits that are known to be one
@@ -86,8 +88,10 @@ template <typename T> class ArrayRef;
/// Return true if the given value is known to be non-zero when defined. For
/// vectors, return true if every element is known to be non-zero when
- /// defined. Supports values with integer or pointer type and vectors of
- /// integers.
+ /// defined. For pointers, if the context instruction and dominator tree are
+ /// specified, perform context-sensitive analysis and return true if the
+ /// pointer couldn't possibly be null at the specified instruction.
+ /// Supports values with integer or pointer type and vectors of integers.
bool isKnownNonZero(const Value *V, const DataLayout &DL, unsigned Depth = 0,
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr,
@@ -167,13 +171,25 @@ template <typename T> class ArrayRef;
bool CannotBeNegativeZero(const Value *V, const TargetLibraryInfo *TLI,
unsigned Depth = 0);
- /// Return true if we can prove that the specified FP value is either a NaN or
- /// never less than 0.0.
- /// If \p IncludeNeg0 is false, -0.0 is considered less than 0.0.
+ /// Return true if we can prove that the specified FP value is either NaN or
+ /// never less than -0.0.
+ ///
+ /// NaN --> true
+ /// +0 --> true
+ /// -0 --> true
+ /// x > +0 --> true
+ /// x < -0 --> false
+ ///
bool CannotBeOrderedLessThanZero(const Value *V, const TargetLibraryInfo *TLI);
- /// \returns true if we can prove that the specified FP value has a 0 sign
- /// bit.
+ /// Return true if we can prove that the specified FP value's sign bit is 0.
+ ///
+ /// NaN --> true/false (depending on the NaN's sign bit)
+ /// +0 --> true
+ /// -0 --> false
+ /// x > +0 --> true
+ /// x < -0 --> false
+ ///
bool SignBitMustBeZero(const Value *V, const TargetLibraryInfo *TLI);
/// If the specified value can be set by repeating the same byte in memory,
diff --git a/include/llvm/Analysis/VectorUtils.h b/include/llvm/Analysis/VectorUtils.h
index eaa068b89c77..6315e8408f05 100644
--- a/include/llvm/Analysis/VectorUtils.h
+++ b/include/llvm/Analysis/VectorUtils.h
@@ -1,4 +1,4 @@
-//===- llvm/Transforms/Utils/VectorUtils.h - Vector utilities -*- C++ -*-=====//
+//===- llvm/Analysis/VectorUtils.h - Vector utilities -----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -11,11 +11,12 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_TRANSFORMS_UTILS_VECTORUTILS_H
-#define LLVM_TRANSFORMS_UTILS_VECTORUTILS_H
+#ifndef LLVM_ANALYSIS_VECTORUTILS_H
+#define LLVM_ANALYSIS_VECTORUTILS_H
#include "llvm/ADT/MapVector.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
+#include "llvm/IR/IRBuilder.h"
namespace llvm {
@@ -123,6 +124,58 @@ computeMinimumValueSizes(ArrayRef<BasicBlock*> Blocks,
/// This function always sets a (possibly null) value for each K in Kinds.
Instruction *propagateMetadata(Instruction *I, ArrayRef<Value *> VL);
+/// \brief Create an interleave shuffle mask.
+///
+/// This function creates a shuffle mask for interleaving \p NumVecs vectors of
+/// vectorization factor \p VF into a single wide vector. The mask is of the
+/// form:
+///
+/// <0, VF, VF * 2, ..., VF * (NumVecs - 1), 1, VF + 1, VF * 2 + 1, ...>
+///
+/// For example, the mask for VF = 4 and NumVecs = 2 is:
+///
+/// <0, 4, 1, 5, 2, 6, 3, 7>.
+Constant *createInterleaveMask(IRBuilder<> &Builder, unsigned VF,
+ unsigned NumVecs);
+
+/// \brief Create a stride shuffle mask.
+///
+/// This function creates a shuffle mask whose elements begin at \p Start and
+/// are incremented by \p Stride. The mask can be used to deinterleave an
+/// interleaved vector into separate vectors of vectorization factor \p VF. The
+/// mask is of the form:
+///
+/// <Start, Start + Stride, ..., Start + Stride * (VF - 1)>
+///
+/// For example, the mask for Start = 0, Stride = 2, and VF = 4 is:
+///
+/// <0, 2, 4, 6>
+Constant *createStrideMask(IRBuilder<> &Builder, unsigned Start,
+ unsigned Stride, unsigned VF);
+
+/// \brief Create a sequential shuffle mask.
+///
+/// This function creates shuffle mask whose elements are sequential and begin
+/// at \p Start. The mask contains \p NumInts integers and is padded with \p
+/// NumUndefs undef values. The mask is of the form:
+///
+/// <Start, Start + 1, ... Start + NumInts - 1, undef_1, ... undef_NumUndefs>
+///
+/// For example, the mask for Start = 0, NumInsts = 4, and NumUndefs = 4 is:
+///
+/// <0, 1, 2, 3, undef, undef, undef, undef>
+Constant *createSequentialMask(IRBuilder<> &Builder, unsigned Start,
+ unsigned NumInts, unsigned NumUndefs);
+
+/// \brief Concatenate a list of vectors.
+///
+/// This function generates code that concatenate the vectors in \p Vecs into a
+/// single large vector. The number of vectors should be greater than one, and
+/// their element types should be the same. The number of elements in the
+/// vectors should also be the same; however, if the last vector has fewer
+/// elements, it will be padded with undefs.
+Value *concatenateVectors(IRBuilder<> &Builder, ArrayRef<Value *> Vecs);
+
} // llvm namespace
#endif
diff --git a/include/llvm/Bitcode/BitcodeWriter.h b/include/llvm/Bitcode/BitcodeWriter.h
index 4f72f98bbf9c..271cb2d81bbb 100644
--- a/include/llvm/Bitcode/BitcodeWriter.h
+++ b/include/llvm/Bitcode/BitcodeWriter.h
@@ -43,9 +43,16 @@ namespace llvm {
///
/// \p GenerateHash enables hashing the Module and including the hash in the
/// bitcode (currently for use in ThinLTO incremental build).
+ ///
+ /// If \p ModHash is non-null, when GenerateHash is true, the resulting
+ /// hash is written into ModHash. When GenerateHash is false, that value
+ /// is used as the hash instead of computing from the generated bitcode.
+ /// Can be used to produce the same module hash for a minimized bitcode
+ /// used just for the thin link as in the regular full bitcode that will
+ /// be used in the backend.
void writeModule(const Module *M, bool ShouldPreserveUseListOrder = false,
const ModuleSummaryIndex *Index = nullptr,
- bool GenerateHash = false);
+ bool GenerateHash = false, ModuleHash *ModHash = nullptr);
};
/// \brief Write the specified module to the specified raw output stream.
@@ -62,10 +69,18 @@ namespace llvm {
///
/// \p GenerateHash enables hashing the Module and including the hash in the
/// bitcode (currently for use in ThinLTO incremental build).
+ ///
+ /// If \p ModHash is non-null, when GenerateHash is true, the resulting
+ /// hash is written into ModHash. When GenerateHash is false, that value
+ /// is used as the hash instead of computing from the generated bitcode.
+ /// Can be used to produce the same module hash for a minimized bitcode
+ /// used just for the thin link as in the regular full bitcode that will
+ /// be used in the backend.
void WriteBitcodeToFile(const Module *M, raw_ostream &Out,
bool ShouldPreserveUseListOrder = false,
const ModuleSummaryIndex *Index = nullptr,
- bool GenerateHash = false);
+ bool GenerateHash = false,
+ ModuleHash *ModHash = nullptr);
/// Write the specified module summary index to the given raw output stream,
/// where it will be written in a new bitcode block. This is used when
diff --git a/include/llvm/Bitcode/LLVMBitCodes.h b/include/llvm/Bitcode/LLVMBitCodes.h
index c996c38261c0..e2d2fbb0f449 100644
--- a/include/llvm/Bitcode/LLVMBitCodes.h
+++ b/include/llvm/Bitcode/LLVMBitCodes.h
@@ -92,9 +92,6 @@ enum ModuleCodes {
// ALIAS: [alias type, aliasee val#, linkage, visibility]
MODULE_CODE_ALIAS_OLD = 9,
- // MODULE_CODE_PURGEVALS: [numvals]
- MODULE_CODE_PURGEVALS = 10,
-
MODULE_CODE_GCNAME = 11, // GCNAME: [strchr x N]
MODULE_CODE_COMDAT = 12, // COMDAT: [selection_kind, name]
@@ -213,8 +210,28 @@ enum GlobalValueSummarySymtabCodes {
FS_COMBINED_ORIGINAL_NAME = 9,
// VERSION of the summary, bumped when adding flags for instance.
FS_VERSION = 10,
- // The list of llvm.type.test type identifiers used by the following function.
+ // The list of llvm.type.test type identifiers used by the following function
+ // that are used other than by an llvm.assume.
+ // [n x typeid]
FS_TYPE_TESTS = 11,
+ // The list of virtual calls made by this function using
+ // llvm.assume(llvm.type.test) intrinsics that do not have all constant
+ // integer arguments.
+ // [n x (typeid, offset)]
+ FS_TYPE_TEST_ASSUME_VCALLS = 12,
+ // The list of virtual calls made by this function using
+ // llvm.type.checked.load intrinsics that do not have all constant integer
+ // arguments.
+ // [n x (typeid, offset)]
+ FS_TYPE_CHECKED_LOAD_VCALLS = 13,
+ // Identifies a virtual call made by this function using an
+ // llvm.assume(llvm.type.test) intrinsic with all constant integer arguments.
+ // [typeid, offset, n x arg]
+ FS_TYPE_TEST_ASSUME_CONST_VCALL = 14,
+ // Identifies a virtual call made by this function using an
+ // llvm.type.checked.load intrinsic with all constant integer arguments.
+ // [typeid, offset, n x arg]
+ FS_TYPE_CHECKED_LOAD_CONST_VCALL = 15,
};
enum MetadataCodes {
diff --git a/include/llvm/CMakeLists.txt b/include/llvm/CMakeLists.txt
index ff805396eb0c..1d5ca3ba92b0 100644
--- a/include/llvm/CMakeLists.txt
+++ b/include/llvm/CMakeLists.txt
@@ -1,4 +1,5 @@
add_subdirectory(IR)
+add_subdirectory(Support)
# If we're doing an out-of-tree build, copy a module map for generated
# header files into the build area.
diff --git a/include/llvm/CodeGen/Analysis.h b/include/llvm/CodeGen/Analysis.h
index f20185c4499a..ba88f1f78fb8 100644
--- a/include/llvm/CodeGen/Analysis.h
+++ b/include/llvm/CodeGen/Analysis.h
@@ -123,13 +123,6 @@ bool returnTypeIsEligibleForTailCall(const Function *F, const Instruction *I,
const ReturnInst *Ret,
const TargetLoweringBase &TLI);
-// True if GV can be left out of the object symbol table. This is the case
-// for linkonce_odr values whose address is not significant. While legal, it is
-// not normally profitable to omit them from the .o symbol table. Using this
-// analysis makes sense when the information can be passed down to the linker
-// or we are in LTO.
-bool canBeOmittedFromSymbolTable(const GlobalValue *GV);
-
DenseMap<const MachineBasicBlock *, int>
getFuncletMembership(const MachineFunction &MF);
diff --git a/include/llvm/CodeGen/AsmPrinter.h b/include/llvm/CodeGen/AsmPrinter.h
index 4daca0347b77..fb8c8408fc77 100644
--- a/include/llvm/CodeGen/AsmPrinter.h
+++ b/include/llvm/CodeGen/AsmPrinter.h
@@ -1,4 +1,4 @@
-//===-- llvm/CodeGen/AsmPrinter.h - AsmPrinter Framework --------*- C++ -*-===//
+//===- llvm/CodeGen/AsmPrinter.h - AsmPrinter Framework ---------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -17,35 +17,43 @@
#define LLVM_CODEGEN_ASMPRINTER_H
#include "llvm/ADT/MapVector.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
-#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/DwarfStringPoolEntry.h"
+#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/IR/InlineAsm.h"
-#include "llvm/Support/DataTypes.h"
+#include "llvm/IR/LLVMContext.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/SourceMgr.h"
+#include <cstdint>
+#include <memory>
+#include <utility>
+#include <vector>
namespace llvm {
+
class AsmPrinterHandler;
class BlockAddress;
-class ByteStreamer;
-class GCStrategy;
class Constant;
class ConstantArray;
+class DataLayout;
class DIE;
class DIEAbbrev;
+class DwarfDebug;
class GCMetadataPrinter;
class GlobalIndirectSymbol;
class GlobalValue;
class GlobalVariable;
+class GCStrategy;
class MachineBasicBlock;
+class MachineConstantPoolValue;
class MachineFunction;
class MachineInstr;
-class MachineLocation;
-class MachineLoopInfo;
-class MachineLoop;
-class MachineConstantPoolValue;
class MachineJumpTableInfo;
+class MachineLoopInfo;
class MachineModuleInfo;
+class MachineOptimizationRemarkEmitter;
class MCAsmInfo;
class MCCFIInstruction;
class MCContext;
@@ -57,10 +65,7 @@ class MCSubtargetInfo;
class MCSymbol;
class MCTargetOptions;
class MDNode;
-class DwarfDebug;
-class Mangler;
class TargetLoweringObjectFile;
-class DataLayout;
class TargetMachine;
/// This class is intended to be used as a driving class for all asm writers.
@@ -84,33 +89,39 @@ public:
std::unique_ptr<MCStreamer> OutStreamer;
/// The current machine function.
- const MachineFunction *MF;
+ const MachineFunction *MF = nullptr;
/// This is a pointer to the current MachineModuleInfo.
- MachineModuleInfo *MMI;
+ MachineModuleInfo *MMI = nullptr;
+
+ /// Optimization remark emitter.
+ MachineOptimizationRemarkEmitter *ORE;
/// The symbol for the current function. This is recalculated at the beginning
/// of each call to runOnMachineFunction().
///
- MCSymbol *CurrentFnSym;
+ MCSymbol *CurrentFnSym = nullptr;
/// The symbol used to represent the start of the current function for the
/// purpose of calculating its size (e.g. using the .size directive). By
/// default, this is equal to CurrentFnSym.
- MCSymbol *CurrentFnSymForSize;
+ MCSymbol *CurrentFnSymForSize = nullptr;
/// 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;
+ /// Enable print [latency:throughput] in output
+ bool EnablePrintSchedInfo = false;
+
private:
- MCSymbol *CurrentFnBegin;
- MCSymbol *CurrentFnEnd;
- MCSymbol *CurExceptionSym;
+ MCSymbol *CurrentFnBegin = nullptr;
+ MCSymbol *CurrentFnEnd = nullptr;
+ MCSymbol *CurExceptionSym = nullptr;
// The garbage collection metadata printer table.
- void *GCMetadataPrinters; // Really a DenseMap.
+ void *GCMetadataPrinters = nullptr; // Really a DenseMap.
/// Emit comments in assembly output if this is true.
///
@@ -118,7 +129,7 @@ private:
static char ID;
/// If VerboseAsm is set, a pointer to the loop info for this function.
- MachineLoopInfo *LI;
+ MachineLoopInfo *LI = nullptr;
struct HandlerInfo {
AsmPrinterHandler *Handler;
@@ -126,6 +137,7 @@ private:
const char *TimerDescription;
const char *TimerGroupName;
const char *TimerGroupDescription;
+
HandlerInfo(AsmPrinterHandler *Handler, const char *TimerName,
const char *TimerDescription, const char *TimerGroupName,
const char *TimerGroupDescription)
@@ -137,11 +149,24 @@ private:
/// maintains ownership of the emitters.
SmallVector<HandlerInfo, 1> Handlers;
+public:
+ struct SrcMgrDiagInfo {
+ SourceMgr SrcMgr;
+ std::vector<const MDNode *> LocInfos;
+ LLVMContext::InlineAsmDiagHandlerTy DiagHandler;
+ void *DiagContext;
+ };
+
+private:
+ /// Structure for generating diagnostics for inline assembly. Only initialised
+ /// when necessary.
+ mutable std::unique_ptr<SrcMgrDiagInfo> DiagInfo;
+
/// If the target supports dwarf debug info, this pointer is non-null.
- DwarfDebug *DD;
+ DwarfDebug *DD = nullptr;
/// If the current module uses dwarf CFI annotations strictly for debugging.
- bool isCFIMoveForDebugging;
+ bool isCFIMoveForDebugging = false;
protected:
explicit AsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer);
@@ -200,6 +225,7 @@ public:
FUNCTION_ENTER = 0,
FUNCTION_EXIT = 1,
TAIL_CALL = 2,
+ LOG_ARGS_ENTER = 3,
};
// The table will contain these structs that point to the sled, the function
@@ -381,7 +407,7 @@ public:
//===------------------------------------------------------------------===//
// Symbol Lowering Routines.
//===------------------------------------------------------------------===//
-public:
+
MCSymbol *createTempSymbol(const Twine &Name) const;
/// Return the MCSymbol for a private symbol with global value name as its
@@ -407,7 +433,7 @@ public:
//===------------------------------------------------------------------===//
// Emission Helper Routines.
//===------------------------------------------------------------------===//
-public:
+
/// This is just convenient handler for printing offsets.
void printOffset(int64_t Offset, raw_ostream &OS) const;
@@ -484,7 +510,7 @@ public:
///
/// \p Value - The value to emit.
/// \p Size - The size of the integer (in bytes) to emit.
- virtual void EmitDebugValue(const MCExpr *Value, unsigned Size) const;
+ virtual void EmitDebugThreadLocal(const MCExpr *Value, unsigned Size) const;
//===------------------------------------------------------------------===//
// Dwarf Lowering Routines
@@ -511,7 +537,7 @@ public:
//===------------------------------------------------------------------===//
// Inline Asm Support
//===------------------------------------------------------------------===//
-public:
+
// These are hooks that targets can override to implement inline asm
// support. These should probably be moved out of AsmPrinter someday.
@@ -555,9 +581,9 @@ public:
private:
/// Private state for PrintSpecial()
// Assign a unique ID to this machine instruction.
- mutable const MachineInstr *LastMI;
- mutable unsigned LastFn;
- mutable unsigned Counter;
+ mutable const MachineInstr *LastMI = nullptr;
+ mutable unsigned LastFn = 0;
+ mutable unsigned Counter = ~0U;
/// This method emits the header for the current function.
virtual void EmitFunctionHeader();
@@ -596,6 +622,7 @@ private:
void emitGlobalIndirectSymbol(Module &M,
const GlobalIndirectSymbol& GIS);
};
-}
-#endif
+} // end namespace llvm
+
+#endif // LLVM_CODEGEN_ASMPRINTER_H
diff --git a/include/llvm/CodeGen/BasicTTIImpl.h b/include/llvm/CodeGen/BasicTTIImpl.h
index 7efdbcccdef5..e30e947f787f 100644
--- a/include/llvm/CodeGen/BasicTTIImpl.h
+++ b/include/llvm/CodeGen/BasicTTIImpl.h
@@ -42,24 +42,6 @@ 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 a cost of shuffle as a sequence of extract and insert
/// operations.
unsigned getPermuteShuffleOverhead(Type *Ty) {
@@ -111,6 +93,11 @@ public:
bool isSourceOfDivergence(const Value *V) { return false; }
+ unsigned getFlatAddressSpace() {
+ // Return an invalid address space.
+ return -1;
+ }
+
bool isLegalAddImmediate(int64_t imm) {
return getTLI()->isLegalAddImmediate(imm);
}
@@ -301,6 +288,67 @@ public:
unsigned getRegisterBitWidth(bool Vector) { return 32; }
+ /// 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 overhead of scalarizing an instructions unique
+ /// non-constant operands. The types of the arguments are ordinarily
+ /// scalar, in which case the costs are multiplied with VF.
+ unsigned getOperandsScalarizationOverhead(ArrayRef<const Value *> Args,
+ unsigned VF) {
+ unsigned Cost = 0;
+ SmallPtrSet<const Value*, 4> UniqueOperands;
+ for (const Value *A : Args) {
+ if (!isa<Constant>(A) && UniqueOperands.insert(A).second) {
+ Type *VecTy = nullptr;
+ if (A->getType()->isVectorTy()) {
+ VecTy = A->getType();
+ // If A is a vector operand, VF should be 1 or correspond to A.
+ assert ((VF == 1 || VF == VecTy->getVectorNumElements()) &&
+ "Vector argument does not match VF");
+ }
+ else
+ VecTy = VectorType::get(A->getType(), VF);
+
+ Cost += getScalarizationOverhead(VecTy, false, true);
+ }
+ }
+
+ return Cost;
+ }
+
+ unsigned getScalarizationOverhead(Type *VecTy, ArrayRef<const Value *> Args) {
+ assert (VecTy->isVectorTy());
+
+ unsigned Cost = 0;
+
+ Cost += getScalarizationOverhead(VecTy, true, false);
+ if (!Args.empty())
+ Cost += getOperandsScalarizationOverhead(Args,
+ VecTy->getVectorNumElements());
+ else
+ // When no information on arguments is provided, we add the cost
+ // associated with one argument as a heuristic.
+ Cost += getScalarizationOverhead(VecTy, false, true);
+
+ return Cost;
+ }
+
unsigned getMaxInterleaveFactor(unsigned VF) { return 1; }
unsigned getArithmeticInstrCost(
@@ -341,10 +389,9 @@ public:
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;
+ // Return the cost of multiple scalar invocation plus the cost of
+ // inserting and extracting the values.
+ return getScalarizationOverhead(Ty, Args) + Num * Cost;
}
// We don't know anything about this scalar instruction.
@@ -360,7 +407,8 @@ public:
return 1;
}
- unsigned getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src) {
+ unsigned getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src,
+ const Instruction *I = nullptr) {
const TargetLoweringBase *TLI = getTLI();
int ISD = TLI->InstructionOpcodeToISD(Opcode);
assert(ISD && "Invalid opcode");
@@ -389,6 +437,18 @@ public:
Dst->getPointerAddressSpace()))
return 0;
+ // If this is a zext/sext of a load, return 0 if the corresponding
+ // extending load exists on target.
+ if ((Opcode == Instruction::ZExt || Opcode == Instruction::SExt) &&
+ I && isa<LoadInst>(I->getOperand(0))) {
+ EVT ExtVT = EVT::getEVT(Dst);
+ EVT LoadVT = EVT::getEVT(Src);
+ unsigned LType =
+ ((Opcode == Instruction::ZExt) ? ISD::ZEXTLOAD : ISD::SEXTLOAD);
+ if (TLI->isLoadExtLegal(LType, ExtVT, LoadVT))
+ 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))
@@ -446,14 +506,14 @@ public:
Src->getVectorNumElements() / 2);
T *TTI = static_cast<T *>(this);
return TTI->getVectorSplitCost() +
- (2 * TTI->getCastInstrCost(Opcode, SplitDst, SplitSrc));
+ (2 * TTI->getCastInstrCost(Opcode, SplitDst, SplitSrc, I));
}
// In other cases where the source or destination are illegal, assume
// the operation will get scalarized.
unsigned Num = Dst->getVectorNumElements();
unsigned Cost = static_cast<T *>(this)->getCastInstrCost(
- Opcode, Dst->getScalarType(), Src->getScalarType());
+ Opcode, Dst->getScalarType(), Src->getScalarType(), I);
// Return the cost of multiple scalar invocation plus the cost of
// inserting and extracting the values.
@@ -487,7 +547,8 @@ public:
return 0;
}
- unsigned getCmpSelInstrCost(unsigned Opcode, Type *ValTy, Type *CondTy) {
+ unsigned getCmpSelInstrCost(unsigned Opcode, Type *ValTy, Type *CondTy,
+ const Instruction *I) {
const TargetLoweringBase *TLI = getTLI();
int ISD = TLI->InstructionOpcodeToISD(Opcode);
assert(ISD && "Invalid opcode");
@@ -515,7 +576,7 @@ public:
if (CondTy)
CondTy = CondTy->getScalarType();
unsigned Cost = static_cast<T *>(this)->getCmpSelInstrCost(
- Opcode, ValTy->getScalarType(), CondTy);
+ Opcode, ValTy->getScalarType(), CondTy, I);
// Return the cost of multiple scalar invocation plus the cost of
// inserting and extracting the values.
@@ -534,7 +595,7 @@ public:
}
unsigned getMemoryOpCost(unsigned Opcode, Type *Src, unsigned Alignment,
- unsigned AddressSpace) {
+ unsigned AddressSpace, const Instruction *I = nullptr) {
assert(!Src->isVoidTy() && "Invalid type");
std::pair<unsigned, MVT> LT = getTLI()->getTypeLegalizationCost(DL, Src);
@@ -680,18 +741,42 @@ public:
return Cost;
}
- /// Get intrinsic cost based on arguments
+ /// Get intrinsic cost based on arguments.
unsigned getIntrinsicInstrCost(Intrinsic::ID IID, Type *RetTy,
- ArrayRef<Value *> Args, FastMathFlags FMF) {
+ ArrayRef<Value *> Args, FastMathFlags FMF,
+ unsigned VF = 1) {
+ unsigned RetVF = (RetTy->isVectorTy() ? RetTy->getVectorNumElements() : 1);
+ assert ((RetVF == 1 || VF == 1) && "VF > 1 and RetVF is a vector type");
+
switch (IID) {
default: {
+ // Assume that we need to scalarize this intrinsic.
SmallVector<Type *, 4> Types;
- for (Value *Op : Args)
- Types.push_back(Op->getType());
- return static_cast<T *>(this)->getIntrinsicInstrCost(IID, RetTy, Types,
- FMF);
+ for (Value *Op : Args) {
+ Type *OpTy = Op->getType();
+ assert (VF == 1 || !OpTy->isVectorTy());
+ Types.push_back(VF == 1 ? OpTy : VectorType::get(OpTy, VF));
+ }
+
+ if (VF > 1 && !RetTy->isVoidTy())
+ RetTy = VectorType::get(RetTy, VF);
+
+ // Compute the scalarization overhead based on Args for a vector
+ // intrinsic. A vectorizer will pass a scalar RetTy and VF > 1, while
+ // CostModel will pass a vector RetTy and VF is 1.
+ unsigned ScalarizationCost = UINT_MAX;
+ if (RetVF > 1 || VF > 1) {
+ ScalarizationCost = 0;
+ if (!RetTy->isVoidTy())
+ ScalarizationCost += getScalarizationOverhead(RetTy, true, false);
+ ScalarizationCost += getOperandsScalarizationOverhead(Args, VF);
+ }
+
+ return static_cast<T *>(this)->
+ getIntrinsicInstrCost(IID, RetTy, Types, FMF, ScalarizationCost);
}
case Intrinsic::masked_scatter: {
+ assert (VF == 1 && "Can't vectorize types here.");
Value *Mask = Args[3];
bool VarMask = !isa<Constant>(Mask);
unsigned Alignment = cast<ConstantInt>(Args[2])->getZExtValue();
@@ -702,6 +787,7 @@ public:
Alignment);
}
case Intrinsic::masked_gather: {
+ assert (VF == 1 && "Can't vectorize types here.");
Value *Mask = Args[2];
bool VarMask = !isa<Constant>(Mask);
unsigned Alignment = cast<ConstantInt>(Args[1])->getZExtValue();
@@ -713,19 +799,23 @@ public:
}
}
- /// Get intrinsic cost based on argument types
+ /// Get intrinsic cost based on argument types.
+ /// If ScalarizationCostPassed is UINT_MAX, the cost of scalarizing the
+ /// arguments and the return value will be computed based on types.
unsigned getIntrinsicInstrCost(Intrinsic::ID IID, Type *RetTy,
- ArrayRef<Type *> Tys, FastMathFlags FMF) {
+ ArrayRef<Type *> Tys, FastMathFlags FMF,
+ unsigned ScalarizationCostPassed = UINT_MAX) {
SmallVector<unsigned, 2> ISDs;
unsigned SingleCallCost = 10; // Library call cost. Make it expensive.
switch (IID) {
default: {
// Assume that we need to scalarize this intrinsic.
- unsigned ScalarizationCost = 0;
+ unsigned ScalarizationCost = ScalarizationCostPassed;
unsigned ScalarCalls = 1;
Type *ScalarRetTy = RetTy;
if (RetTy->isVectorTy()) {
- ScalarizationCost = getScalarizationOverhead(RetTy, true, false);
+ if (ScalarizationCostPassed == UINT_MAX)
+ ScalarizationCost = getScalarizationOverhead(RetTy, true, false);
ScalarCalls = std::max(ScalarCalls, RetTy->getVectorNumElements());
ScalarRetTy = RetTy->getScalarType();
}
@@ -733,7 +823,8 @@ public:
for (unsigned i = 0, ie = Tys.size(); i != ie; ++i) {
Type *Ty = Tys[i];
if (Ty->isVectorTy()) {
- ScalarizationCost += getScalarizationOverhead(Ty, false, true);
+ if (ScalarizationCostPassed == UINT_MAX)
+ ScalarizationCost += getScalarizationOverhead(Ty, false, true);
ScalarCalls = std::max(ScalarCalls, Ty->getVectorNumElements());
Ty = Ty->getScalarType();
}
@@ -881,7 +972,8 @@ public:
// 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 ScalarizationCost = ((ScalarizationCostPassed != UINT_MAX) ?
+ ScalarizationCostPassed : getScalarizationOverhead(RetTy, true, false));
unsigned ScalarCalls = RetTy->getVectorNumElements();
SmallVector<Type *, 4> ScalarTys;
for (unsigned i = 0, ie = Tys.size(); i != ie; ++i) {
@@ -894,7 +986,8 @@ public:
IID, RetTy->getScalarType(), ScalarTys, FMF);
for (unsigned i = 0, ie = Tys.size(); i != ie; ++i) {
if (Tys[i]->isVectorTy()) {
- ScalarizationCost += getScalarizationOverhead(Tys[i], false, true);
+ if (ScalarizationCostPassed == UINT_MAX)
+ ScalarizationCost += getScalarizationOverhead(Tys[i], false, true);
ScalarCalls = std::max(ScalarCalls, Tys[i]->getVectorNumElements());
}
}
diff --git a/include/llvm/CodeGen/CallingConvLower.h b/include/llvm/CodeGen/CallingConvLower.h
index bfbd22823eb8..50e464ebb9b8 100644
--- a/include/llvm/CodeGen/CallingConvLower.h
+++ b/include/llvm/CodeGen/CallingConvLower.h
@@ -183,11 +183,6 @@ typedef bool CCCustomFn(unsigned &ValNo, MVT &ValVT,
MVT &LocVT, CCValAssign::LocInfo &LocInfo,
ISD::ArgFlagsTy &ArgFlags, CCState &State);
-/// ParmContext - This enum tracks whether calling convention lowering is in
-/// the context of prologue or call generation. Not all backends make use of
-/// this information.
-typedef enum { Unknown, Prologue, Call } ParmContext;
-
/// CCState - This class holds information needed while lowering arguments and
/// return values. It captures which registers are already assigned and which
/// stack slots are used. It provides accessors to allocate these values.
@@ -256,9 +251,6 @@ private:
// during argument analysis.
unsigned InRegsParamsProcessed;
-protected:
- ParmContext CallOrPrologue;
-
public:
CCState(CallingConv::ID CC, bool isVarArg, MachineFunction &MF,
SmallVectorImpl<CCValAssign> &locs, LLVMContext &C);
@@ -510,8 +502,6 @@ public:
InRegsParamsProcessed = 0;
}
- ParmContext getCallOrPrologue() const { return CallOrPrologue; }
-
// Get list of pending assignments
SmallVectorImpl<llvm::CCValAssign> &getPendingLocs() {
return PendingLocs;
diff --git a/include/llvm/CodeGen/CommandFlags.h b/include/llvm/CodeGen/CommandFlags.h
index aab522d00de7..317a5d3f54c8 100644
--- a/include/llvm/CodeGen/CommandFlags.h
+++ b/include/llvm/CodeGen/CommandFlags.h
@@ -119,11 +119,6 @@ FileType("filetype", cl::init(TargetMachine::CGFT_AssemblyFile),
"Emit nothing, for performance testing")));
cl::opt<bool>
-EnableFPMAD("enable-fp-mad",
- cl::desc("Enable less precise MAD instructions to be generated"),
- cl::init(false));
-
-cl::opt<bool>
DisableFPElim("disable-fp-elim",
cl::desc("Disable frame pointer elimination optimization"),
cl::init(false));
@@ -144,6 +139,12 @@ EnableNoNaNsFPMath("enable-no-nans-fp-math",
cl::init(false));
cl::opt<bool>
+EnableNoSignedZerosFPMath("enable-no-signed-zeros-fp-math",
+ cl::desc("Enable FP math optimizations that assume "
+ "the sign of 0 is insignificant"),
+ cl::init(false));
+
+cl::opt<bool>
EnableNoTrappingFPMath("enable-no-trapping-fp-math",
cl::desc("Enable setting the FP exceptions build "
"attribute not to use exceptions"),
@@ -277,11 +278,11 @@ DebuggerTuningOpt("debugger-tune",
// a TargetOptions object with CodeGen flags and returns it.
static inline TargetOptions InitTargetOptionsFromCodeGenFlags() {
TargetOptions Options;
- Options.LessPreciseFPMADOption = EnableFPMAD;
Options.AllowFPOpFusion = FuseFPOps;
Options.UnsafeFPMath = EnableUnsafeFPMath;
Options.NoInfsFPMath = EnableNoInfsFPMath;
Options.NoNaNsFPMath = EnableNoNaNsFPMath;
+ Options.NoSignedZerosFPMath = EnableNoSignedZerosFPMath;
Options.NoTrappingFPMath = EnableNoTrappingFPMath;
Options.FPDenormalMode = DenormalMode;
Options.HonorSignDependentRoundingFPMathOption =
@@ -345,28 +346,28 @@ static inline void setFunctionAttributes(StringRef CPU, StringRef Features,
Module &M) {
for (auto &F : M) {
auto &Ctx = F.getContext();
- AttributeSet Attrs = F.getAttributes(), NewAttrs;
+ AttributeList Attrs = F.getAttributes(), NewAttrs;
if (!CPU.empty())
- NewAttrs = NewAttrs.addAttribute(Ctx, AttributeSet::FunctionIndex,
+ NewAttrs = NewAttrs.addAttribute(Ctx, AttributeList::FunctionIndex,
"target-cpu", CPU);
if (!Features.empty())
- NewAttrs = NewAttrs.addAttribute(Ctx, AttributeSet::FunctionIndex,
+ NewAttrs = NewAttrs.addAttribute(Ctx, AttributeList::FunctionIndex,
"target-features", Features);
if (DisableFPElim.getNumOccurrences() > 0)
- NewAttrs = NewAttrs.addAttribute(Ctx, AttributeSet::FunctionIndex,
+ NewAttrs = NewAttrs.addAttribute(Ctx, AttributeList::FunctionIndex,
"no-frame-pointer-elim",
DisableFPElim ? "true" : "false");
if (DisableTailCalls.getNumOccurrences() > 0)
- NewAttrs = NewAttrs.addAttribute(Ctx, AttributeSet::FunctionIndex,
+ NewAttrs = NewAttrs.addAttribute(Ctx, AttributeList::FunctionIndex,
"disable-tail-calls",
toStringRef(DisableTailCalls));
if (StackRealign)
- NewAttrs = NewAttrs.addAttribute(Ctx, AttributeSet::FunctionIndex,
+ NewAttrs = NewAttrs.addAttribute(Ctx, AttributeList::FunctionIndex,
"stackrealign");
if (TrapFuncName.getNumOccurrences() > 0)
@@ -376,12 +377,12 @@ static inline void setFunctionAttributes(StringRef CPU, StringRef Features,
if (const auto *F = Call->getCalledFunction())
if (F->getIntrinsicID() == Intrinsic::debugtrap ||
F->getIntrinsicID() == Intrinsic::trap)
- Call->addAttribute(llvm::AttributeSet::FunctionIndex,
- Attribute::get(Ctx, "trap-func-name",
- TrapFuncName));
+ Call->addAttribute(
+ llvm::AttributeList::FunctionIndex,
+ Attribute::get(Ctx, "trap-func-name", TrapFuncName));
// Let NewAttrs override Attrs.
- NewAttrs = Attrs.addAttributes(Ctx, AttributeSet::FunctionIndex, NewAttrs);
+ NewAttrs = Attrs.addAttributes(Ctx, AttributeList::FunctionIndex, NewAttrs);
F.setAttributes(NewAttrs);
}
}
diff --git a/include/llvm/CodeGen/ExecutionDepsFix.h b/include/llvm/CodeGen/ExecutionDepsFix.h
new file mode 100644
index 000000000000..1d5b9684e105
--- /dev/null
+++ b/include/llvm/CodeGen/ExecutionDepsFix.h
@@ -0,0 +1,220 @@
+//===- llvm/CodeGen/ExecutionDepsFix.h - Execution Dependency Fix -*- C++ -*-=//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+/// \file Execution Dependency Fix pass.
+///
+/// Some X86 SSE instructions like mov, and, or, xor are available in different
+/// variants for different operand types. These variant instructions are
+/// equivalent, but on Nehalem and newer cpus there is extra latency
+/// transferring data between integer and floating point domains. ARM cores
+/// have similar issues when they are configured with both VFP and NEON
+/// pipelines.
+///
+/// This pass changes the variant instructions to minimize domain crossings.
+//
+//===----------------------------------------------------------------------===//
+
+
+#ifndef LLVM_CODEGEN_EXECUTIONDEPSFIX_H
+#define LLVM_CODEGEN_EXECUTIONDEPSFIX_H
+
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/CodeGen/LivePhysRegs.h"
+#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/CodeGen/RegisterClassInfo.h"
+#include "llvm/Support/Allocator.h"
+#include <vector>
+
+namespace llvm {
+
+/// A DomainValue is a bit like LiveIntervals' ValNo, but it also keeps track
+/// of execution domains.
+///
+/// An open DomainValue represents a set of instructions that can still switch
+/// execution domain. Multiple registers may refer to the same open
+/// DomainValue - they will eventually be collapsed to the same execution
+/// domain.
+///
+/// A collapsed DomainValue represents a single register that has been forced
+/// into one of more execution domains. There is a separate collapsed
+/// DomainValue for each register, but it may contain multiple execution
+/// domains. A register value is initially created in a single execution
+/// domain, but if we were forced to pay the penalty of a domain crossing, we
+/// keep track of the fact that the register is now available in multiple
+/// domains.
+struct DomainValue {
+ // Basic reference counting.
+ unsigned Refs;
+
+ // Bitmask of available domains. For an open DomainValue, it is the still
+ // possible domains for collapsing. For a collapsed DomainValue it is the
+ // domains where the register is available for free.
+ unsigned AvailableDomains;
+
+ // Pointer to the next DomainValue in a chain. When two DomainValues are
+ // merged, Victim.Next is set to point to Victor, so old DomainValue
+ // references can be updated by following the chain.
+ DomainValue *Next;
+
+ // Twiddleable instructions using or defining these registers.
+ SmallVector<MachineInstr*, 8> Instrs;
+
+ // A collapsed DomainValue has no instructions to twiddle - it simply keeps
+ // track of the domains where the registers are already available.
+ bool isCollapsed() const { return Instrs.empty(); }
+
+ // Is domain available?
+ bool hasDomain(unsigned domain) const {
+ assert(domain <
+ static_cast<unsigned>(std::numeric_limits<unsigned>::digits) &&
+ "undefined behavior");
+ return AvailableDomains & (1u << domain);
+ }
+
+ // Mark domain as available.
+ void addDomain(unsigned domain) {
+ AvailableDomains |= 1u << domain;
+ }
+
+ // Restrict to a single domain available.
+ void setSingleDomain(unsigned domain) {
+ AvailableDomains = 1u << domain;
+ }
+
+ // Return bitmask of domains that are available and in mask.
+ unsigned getCommonDomains(unsigned mask) const {
+ return AvailableDomains & mask;
+ }
+
+ // First domain available.
+ unsigned getFirstDomain() const {
+ return countTrailingZeros(AvailableDomains);
+ }
+
+ DomainValue() : Refs(0) { clear(); }
+
+ // Clear this DomainValue and point to next which has all its data.
+ void clear() {
+ AvailableDomains = 0;
+ Next = nullptr;
+ Instrs.clear();
+ }
+};
+
+/// Information about a live register.
+struct LiveReg {
+ /// Value currently in this register, or NULL when no value is being tracked.
+ /// This counts as a DomainValue reference.
+ DomainValue *Value;
+
+ /// Instruction that defined this register, relative to the beginning of the
+ /// current basic block. When a LiveReg is used to represent a live-out
+ /// register, this value is relative to the end of the basic block, so it
+ /// will be a negative number.
+ int Def;
+};
+
+class ExecutionDepsFix : public MachineFunctionPass {
+ SpecificBumpPtrAllocator<DomainValue> Allocator;
+ SmallVector<DomainValue*,16> Avail;
+
+ const TargetRegisterClass *const RC;
+ MachineFunction *MF;
+ const TargetInstrInfo *TII;
+ const TargetRegisterInfo *TRI;
+ RegisterClassInfo RegClassInfo;
+ std::vector<SmallVector<int, 1>> AliasMap;
+ const unsigned NumRegs;
+ LiveReg *LiveRegs;
+ struct MBBInfo {
+ // Keeps clearance and domain information for all registers. Note that this
+ // is different from the usual definition notion of liveness. The CPU
+ // doesn't care whether or not we consider a register killed.
+ LiveReg *OutRegs;
+
+ // Whether we have gotten to this block in primary processing yet.
+ bool PrimaryCompleted;
+
+ // The number of predecessors for which primary processing has completed
+ unsigned IncomingProcessed;
+
+ // The value of `IncomingProcessed` at the start of primary processing
+ unsigned PrimaryIncoming;
+
+ // The number of predecessors for which all processing steps are done.
+ unsigned IncomingCompleted;
+
+ MBBInfo()
+ : OutRegs(nullptr), PrimaryCompleted(false), IncomingProcessed(0),
+ PrimaryIncoming(0), IncomingCompleted(0) {}
+ };
+ typedef DenseMap<MachineBasicBlock *, MBBInfo> MBBInfoMap;
+ MBBInfoMap MBBInfos;
+
+ /// List of undefined register reads in this block in forward order.
+ std::vector<std::pair<MachineInstr*, unsigned> > UndefReads;
+
+ /// Storage for register unit liveness.
+ LivePhysRegs LiveRegSet;
+
+ /// Current instruction number.
+ /// The first instruction in each basic block is 0.
+ int CurInstr;
+public:
+ ExecutionDepsFix(char &PassID, const TargetRegisterClass &RC)
+ : MachineFunctionPass(PassID), RC(&RC), NumRegs(RC.getNumRegs()) {}
+
+ void getAnalysisUsage(AnalysisUsage &AU) const override {
+ AU.setPreservesAll();
+ MachineFunctionPass::getAnalysisUsage(AU);
+ }
+
+ bool runOnMachineFunction(MachineFunction &MF) override;
+
+ MachineFunctionProperties getRequiredProperties() const override {
+ return MachineFunctionProperties().set(
+ MachineFunctionProperties::Property::NoVRegs);
+ }
+
+private:
+ iterator_range<SmallVectorImpl<int>::const_iterator>
+ regIndices(unsigned Reg) const;
+ // DomainValue allocation.
+ DomainValue *alloc(int domain = -1);
+ DomainValue *retain(DomainValue *DV) {
+ if (DV) ++DV->Refs;
+ return DV;
+ }
+ void release(DomainValue*);
+ DomainValue *resolve(DomainValue*&);
+
+ // LiveRegs manipulations.
+ void setLiveReg(int rx, DomainValue *DV);
+ void kill(int rx);
+ void force(int rx, unsigned domain);
+ void collapse(DomainValue *dv, unsigned domain);
+ bool merge(DomainValue *A, DomainValue *B);
+
+ void enterBasicBlock(MachineBasicBlock*);
+ void leaveBasicBlock(MachineBasicBlock*);
+ bool isBlockDone(MachineBasicBlock *);
+ void processBasicBlock(MachineBasicBlock *MBB, bool PrimaryPass);
+ bool visitInstr(MachineInstr *);
+ void processDefs(MachineInstr *, bool breakDependency, bool Kill);
+ void visitSoftInstr(MachineInstr*, unsigned mask);
+ void visitHardInstr(MachineInstr*, unsigned domain);
+ bool pickBestRegisterForUndef(MachineInstr *MI, unsigned OpIdx,
+ unsigned Pref);
+ bool shouldBreakDependence(MachineInstr*, unsigned OpIdx, unsigned Pref);
+ void processUndefReads(MachineBasicBlock*);
+};
+
+} // end namepsace llvm
+
+#endif
diff --git a/include/llvm/CodeGen/FastISel.h b/include/llvm/CodeGen/FastISel.h
index cdaea250c33b..2abe3bb11556 100644
--- a/include/llvm/CodeGen/FastISel.h
+++ b/include/llvm/CodeGen/FastISel.h
@@ -1,4 +1,4 @@
-//===-- FastISel.h - Definition of the FastISel class ---*- C++ -*---------===//
+//===- FastISel.h - Definition of the FastISel class ------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -16,10 +16,21 @@
#define LLVM_CODEGEN_FASTISEL_H
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
+#include "llvm/CodeGen/MachineValueType.h"
+#include "llvm/IR/Attributes.h"
#include "llvm/IR/CallingConv.h"
+#include "llvm/IR/CallSite.h"
+#include "llvm/IR/DebugLoc.h"
+#include "llvm/IR/DerivedTypes.h"
+#include "llvm/IR/InstrTypes.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/Target/TargetLowering.h"
+#include <algorithm>
+#include <cstdint>
+#include <utility>
+#include <vector>
namespace llvm {
@@ -30,57 +41,31 @@ class MachineConstantPool;
/// quickly.
class FastISel {
public:
- struct ArgListEntry {
- Value *Val;
- Type *Ty;
- bool IsSExt : 1;
- bool IsZExt : 1;
- bool IsInReg : 1;
- bool IsSRet : 1;
- bool IsNest : 1;
- bool IsByVal : 1;
- bool IsInAlloca : 1;
- bool IsReturned : 1;
- bool IsSwiftSelf : 1;
- bool IsSwiftError : 1;
- uint16_t Alignment;
-
- ArgListEntry()
- : Val(nullptr), Ty(nullptr), IsSExt(false), IsZExt(false),
- IsInReg(false), IsSRet(false), IsNest(false), IsByVal(false),
- IsInAlloca(false), IsReturned(false), IsSwiftSelf(false),
- IsSwiftError(false), Alignment(0) {}
-
- /// \brief Set CallLoweringInfo attribute flags based on a call instruction
- /// and called function attributes.
- void setAttributes(ImmutableCallSite *CS, unsigned AttrIdx);
- };
- typedef std::vector<ArgListEntry> ArgListTy;
-
+ typedef TargetLoweringBase::ArgListEntry ArgListEntry;
+ typedef TargetLoweringBase::ArgListTy ArgListTy;
struct CallLoweringInfo {
- Type *RetTy;
+ Type *RetTy = nullptr;
bool RetSExt : 1;
bool RetZExt : 1;
bool IsVarArg : 1;
bool IsInReg : 1;
bool DoesNotReturn : 1;
bool IsReturnValueUsed : 1;
+ bool IsPatchPoint : 1;
// \brief IsTailCall Should be modified by implementations of FastLowerCall
// that perform tail call conversions.
- bool IsTailCall;
+ bool IsTailCall = false;
- unsigned NumFixedArgs;
- CallingConv::ID CallConv;
- const Value *Callee;
- MCSymbol *Symbol;
+ unsigned NumFixedArgs = -1;
+ CallingConv::ID CallConv = CallingConv::C;
+ const Value *Callee = nullptr;
+ MCSymbol *Symbol = nullptr;
ArgListTy Args;
- ImmutableCallSite *CS;
- MachineInstr *Call;
- unsigned ResultReg;
- unsigned NumResultRegs;
-
- bool IsPatchPoint;
+ ImmutableCallSite *CS = nullptr;
+ MachineInstr *Call = nullptr;
+ unsigned ResultReg = 0;
+ unsigned NumResultRegs = 0;
SmallVector<Value *, 16> OutVals;
SmallVector<ISD::ArgFlagsTy, 16> OutFlags;
@@ -89,11 +74,8 @@ public:
SmallVector<unsigned, 4> InRegs;
CallLoweringInfo()
- : RetTy(nullptr), RetSExt(false), RetZExt(false), IsVarArg(false),
- IsInReg(false), DoesNotReturn(false), IsReturnValueUsed(true),
- IsTailCall(false), NumFixedArgs(-1), CallConv(CallingConv::C),
- Callee(nullptr), Symbol(nullptr), CS(nullptr), Call(nullptr),
- ResultReg(0), NumResultRegs(0), IsPatchPoint(false) {}
+ : RetSExt(false), RetZExt(false), IsVarArg(false), IsInReg(false),
+ DoesNotReturn(false), IsReturnValueUsed(true), IsPatchPoint(false) {}
CallLoweringInfo &setCallee(Type *ResultTy, FunctionType *FuncTy,
const Value *Target, ArgListTy &&ArgsList,
@@ -101,12 +83,12 @@ public:
RetTy = ResultTy;
Callee = Target;
- IsInReg = Call.paramHasAttr(0, Attribute::InReg);
+ IsInReg = Call.hasRetAttr(Attribute::InReg);
DoesNotReturn = Call.doesNotReturn();
IsVarArg = FuncTy->isVarArg();
IsReturnValueUsed = !Call.getInstruction()->use_empty();
- RetSExt = Call.paramHasAttr(0, Attribute::SExt);
- RetZExt = Call.paramHasAttr(0, Attribute::ZExt);
+ RetSExt = Call.hasRetAttr(Attribute::SExt);
+ RetZExt = Call.hasRetAttr(Attribute::ZExt);
CallConv = Call.getCallingConv();
Args = std::move(ArgsList);
@@ -125,12 +107,12 @@ public:
Callee = Call.getCalledValue();
Symbol = Target;
- IsInReg = Call.paramHasAttr(0, Attribute::InReg);
+ IsInReg = Call.hasRetAttr(Attribute::InReg);
DoesNotReturn = Call.doesNotReturn();
IsVarArg = FuncTy->isVarArg();
IsReturnValueUsed = !Call.getInstruction()->use_empty();
- RetSExt = Call.paramHasAttr(0, Attribute::SExt);
- RetZExt = Call.paramHasAttr(0, Attribute::ZExt);
+ RetSExt = Call.hasRetAttr(Attribute::SExt);
+ RetZExt = Call.hasRetAttr(Attribute::ZExt);
CallConv = Call.getCallingConv();
Args = std::move(ArgsList);
@@ -510,7 +492,6 @@ protected:
}
}
-
bool lowerCall(const CallInst *I);
/// \brief Select and emit code for a binary operator instruction, which has
/// an opcode which directly corresponds to the given ISD opcode.
@@ -567,4 +548,4 @@ private:
} // end namespace llvm
-#endif
+#endif // LLVM_CODEGEN_FASTISEL_H
diff --git a/include/llvm/CodeGen/FaultMaps.h b/include/llvm/CodeGen/FaultMaps.h
index 9b5a3e1ba050..0f0005b83c54 100644
--- a/include/llvm/CodeGen/FaultMaps.h
+++ b/include/llvm/CodeGen/FaultMaps.h
@@ -1,4 +1,4 @@
-//===------------------- FaultMaps.h - The "FaultMaps" section --*- C++ -*-===//
+//===- FaultMaps.h - The "FaultMaps" section --------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -12,26 +12,31 @@
#include "llvm/MC/MCSymbol.h"
#include "llvm/Support/Endian.h"
-#include "llvm/Support/Format.h"
-
-#include <vector>
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
#include <map>
+#include <vector>
namespace llvm {
class AsmPrinter;
class MCExpr;
-class MCSymbol;
-class MCStreamer;
+class raw_ostream;
class FaultMaps {
public:
- enum FaultKind { FaultingLoad = 1, FaultKindMax };
-
- static const char *faultTypeToString(FaultKind);
+ enum FaultKind {
+ FaultingLoad = 1,
+ FaultingLoadStore,
+ FaultingStore,
+ FaultKindMax
+ };
explicit FaultMaps(AsmPrinter &AP);
+ static const char *faultTypeToString(FaultKind);
+
void recordFaultingOp(FaultKind FaultTy, const MCSymbol *HandlerLabel);
void serializeToFaultMapSection();
@@ -39,13 +44,11 @@ private:
static const char *WFMP;
struct FaultInfo {
- FaultKind Kind;
- const MCExpr *FaultingOffsetExpr;
- const MCExpr *HandlerOffsetExpr;
+ FaultKind Kind = FaultKindMax;
+ const MCExpr *FaultingOffsetExpr = nullptr;
+ const MCExpr *HandlerOffsetExpr = nullptr;
- FaultInfo()
- : Kind(FaultKindMax), FaultingOffsetExpr(nullptr),
- HandlerOffsetExpr(nullptr) {}
+ FaultInfo() = default;
explicit FaultInfo(FaultMaps::FaultKind Kind, const MCExpr *FaultingOffset,
const MCExpr *HandlerOffset)
@@ -153,11 +156,11 @@ public:
static const size_t FunctionInfoHeaderSize = FunctionFaultInfosOffset;
- const uint8_t *P;
- const uint8_t *E;
+ const uint8_t *P = nullptr;
+ const uint8_t *E = nullptr;
public:
- FunctionInfoAccessor() : P(nullptr), E(nullptr) {}
+ FunctionInfoAccessor() = default;
explicit FunctionInfoAccessor(const uint8_t *P, const uint8_t *E)
: P(P), E(E) {}
@@ -214,6 +217,6 @@ raw_ostream &operator<<(raw_ostream &OS,
raw_ostream &operator<<(raw_ostream &OS, const FaultMapParser &);
-} // namespace llvm
+} // end namespace llvm
-#endif
+#endif // LLVM_CODEGEN_FAULTMAPS_H
diff --git a/include/llvm/CodeGen/GCStrategy.h b/include/llvm/CodeGen/GCStrategy.h
index 3088a86a3260..5b1fafea25b5 100644
--- a/include/llvm/CodeGen/GCStrategy.h
+++ b/include/llvm/CodeGen/GCStrategy.h
@@ -1,4 +1,4 @@
-//===-- llvm/CodeGen/GCStrategy.h - Garbage collection ----------*- C++ -*-===//
+//===- llvm/CodeGen/GCStrategy.h - Garbage collection -----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -47,19 +47,20 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_IR_GCSTRATEGY_H
-#define LLVM_IR_GCSTRATEGY_H
+#ifndef LLVM_CODEGEN_GCSTRATEGY_H
+#define LLVM_CODEGEN_GCSTRATEGY_H
+#include "llvm/ADT/None.h"
#include "llvm/ADT/Optional.h"
-#include "llvm/IR/Function.h"
-#include "llvm/IR/Module.h"
-#include "llvm/IR/Value.h"
-#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Registry.h"
#include <string>
namespace llvm {
+
+class Type;
+
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.
@@ -68,7 +69,8 @@ enum PointKind {
PreCall, ///< Instr is a call instruction.
PostCall ///< Instr is the return address of a call.
};
-}
+
+} // end namespace GC
/// GCStrategy describes a garbage collector algorithm's code generation
/// requirements, and provides overridable hooks for those needs which cannot
@@ -77,24 +79,25 @@ enum PointKind {
/// be immutable.
class GCStrategy {
private:
- std::string Name;
friend class GCModuleInfo;
+ std::string Name;
+
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.
+ bool UseStatepoints = false; /// 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.
+ unsigned NeededSafePoints = 0; ///< Bitmask of required safe points.
+ bool CustomReadBarriers = false; ///< Default is to insert loads.
+ bool CustomWriteBarriers = false; ///< Default is to insert stores.
+ bool CustomRoots = false; ///< Default is to pass through to backend.
+ bool InitRoots= true; ///< If set, roots are nulled during lowering.
+ bool UsesMetadata = false; ///< If set, backend must emit metadata tables.
public:
GCStrategy();
- virtual ~GCStrategy() {}
+ virtual ~GCStrategy() = default;
/// Return the name of the GC strategy. This is the value of the collector
/// name string specified on functions which use this strategy.
@@ -172,6 +175,7 @@ public:
/// register your GCMetadataPrinter subclass with the
/// GCMetadataPrinterRegistery as well.
typedef Registry<GCStrategy> GCRegistry;
-}
-#endif
+} // end namespace llvm
+
+#endif // LLVM_CODEGEN_GCSTRATEGY_H
diff --git a/include/llvm/CodeGen/GlobalISel/CallLowering.h b/include/llvm/CodeGen/GlobalISel/CallLowering.h
index 0b157bf937a3..3e9a9d514cb8 100644
--- a/include/llvm/CodeGen/GlobalISel/CallLowering.h
+++ b/include/llvm/CodeGen/GlobalISel/CallLowering.h
@@ -35,9 +35,11 @@ public:
unsigned Reg;
Type *Ty;
ISD::ArgFlagsTy Flags;
+ bool IsFixed;
- ArgInfo(unsigned Reg, Type *Ty, ISD::ArgFlagsTy Flags = ISD::ArgFlagsTy{})
- : Reg(Reg), Ty(Ty), Flags(Flags) {}
+ ArgInfo(unsigned Reg, Type *Ty, ISD::ArgFlagsTy Flags = ISD::ArgFlagsTy{},
+ bool IsFixed = true)
+ : Reg(Reg), Ty(Ty), Flags(Flags), IsFixed(IsFixed) {}
};
/// Argument handling is mostly uniform between the four places that
@@ -68,15 +70,34 @@ public:
uint64_t Size, MachinePointerInfo &MPO,
CCValAssign &VA) = 0;
+ /// Handle custom values, which may be passed into one or more of \p VAs.
+ /// \return The number of \p VAs that have been assigned after the first
+ /// one, and which should therefore be skipped from further
+ /// processing.
+ virtual unsigned assignCustomValue(const ArgInfo &Arg,
+ ArrayRef<CCValAssign> VAs) {
+ // This is not a pure virtual method because not all targets need to worry
+ // about custom values.
+ llvm_unreachable("Custom values not supported");
+ }
+
unsigned extendRegister(unsigned ValReg, CCValAssign &VA);
- ValueHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI)
- : MIRBuilder(MIRBuilder), MRI(MRI) {}
+ virtual bool assignArg(unsigned ValNo, MVT ValVT, MVT LocVT,
+ CCValAssign::LocInfo LocInfo, const ArgInfo &Info,
+ CCState &State) {
+ return AssignFn(ValNo, ValVT, LocVT, LocInfo, Info.Flags, State);
+ }
+
+ ValueHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI,
+ CCAssignFn *AssignFn)
+ : MIRBuilder(MIRBuilder), MRI(MRI), AssignFn(AssignFn) {}
virtual ~ValueHandler() {}
MachineIRBuilder &MIRBuilder;
MachineRegisterInfo &MRI;
+ CCAssignFn *AssignFn;
};
protected:
@@ -96,12 +117,12 @@ protected:
void setArgFlags(ArgInfo &Arg, unsigned OpNum, const DataLayout &DL,
const FuncInfoTy &FuncInfo) const;
- /// Invoke the \p AssignFn on each of the given \p Args and then use
+ /// Invoke Handler::assignArg on each of the given \p Args and then use
/// \p Callback to move them to the assigned locations.
///
/// \return True if everything has succeeded, false otherwise.
- bool handleAssignments(MachineIRBuilder &MIRBuilder, CCAssignFn *AssignFn,
- ArrayRef<ArgInfo> Args, ValueHandler &Callback) const;
+ bool handleAssignments(MachineIRBuilder &MIRBuilder, ArrayRef<ArgInfo> Args,
+ ValueHandler &Callback) const;
public:
CallLowering(const TargetLowering *TLI) : TLI(TLI) {}
@@ -135,6 +156,8 @@ public:
/// This hook must be implemented to lower the given call instruction,
/// including argument and return value marshalling.
///
+ /// \p CallConv is the calling convention to be used for the call.
+ ///
/// \p Callee is the destination of the call. It should be either a register,
/// globaladdress, or externalsymbol.
///
@@ -150,14 +173,16 @@ public:
/// needs to be passed.
///
/// \return true if the lowering succeeded, false otherwise.
- virtual bool lowerCall(MachineIRBuilder &MIRBuilder,
+ virtual bool lowerCall(MachineIRBuilder &MIRBuilder, CallingConv::ID CallConv,
const MachineOperand &Callee, const ArgInfo &OrigRet,
ArrayRef<ArgInfo> OrigArgs) const {
return false;
}
- /// This hook must be implemented to lower the given call instruction,
- /// including argument and return value marshalling.
+ /// Lower the given call instruction, including argument and return value
+ /// marshalling.
+ ///
+ /// \p CI is the call/invoke instruction.
///
/// \p ResReg is a register where the call's return value should be stored (or
/// 0 if there is no return value).
@@ -171,9 +196,9 @@ public:
/// range of an immediate jump.
///
/// \return true if the lowering succeeded, false otherwise.
- virtual bool lowerCall(MachineIRBuilder &MIRBuilder, const CallInst &CI,
- unsigned ResReg, ArrayRef<unsigned> ArgRegs,
- std::function<unsigned()> GetCalleeReg) const;
+ bool lowerCall(MachineIRBuilder &MIRBuilder, ImmutableCallSite CS,
+ unsigned ResReg, ArrayRef<unsigned> ArgRegs,
+ std::function<unsigned()> GetCalleeReg) const;
};
} // End namespace llvm.
diff --git a/include/llvm/CodeGen/GlobalISel/IRTranslator.h b/include/llvm/CodeGen/GlobalISel/IRTranslator.h
index 26ba5c67beb5..31ffdc0e2e78 100644
--- a/include/llvm/CodeGen/GlobalISel/IRTranslator.h
+++ b/include/llvm/CodeGen/GlobalISel/IRTranslator.h
@@ -34,6 +34,7 @@ class Instruction;
class MachineBasicBlock;
class MachineFunction;
class MachineInstr;
+class OptimizationRemarkEmitter;
class MachineRegisterInfo;
class TargetPassConfig;
@@ -55,21 +56,20 @@ private:
/// Mapping of the values of the current LLVM IR function
/// to the related virtual registers.
ValueToVReg ValToVReg;
- // Constants are special because when we encounter one,
- // we do not know at first where to insert the definition since
- // this depends on all its uses.
- // Thus, we will insert the sequences to materialize them when
- // we know all their users.
- // In the meantime, just keep it in a set.
- // Note: Constants that end up as immediate in the related instructions,
- // do not appear in that map.
- SmallSetVector<const Constant *, 8> Constants;
// N.b. it's not completely obvious that this will be sufficient for every
// LLVM IR construct (with "invoke" being the obvious candidate to mess up our
// lives.
DenseMap<const BasicBlock *, MachineBasicBlock *> BBToMBB;
+ // One BasicBlock can be translated to multiple MachineBasicBlocks. For such
+ // BasicBlocks translated to multiple MachineBasicBlocks, MachinePreds retains
+ // a mapping between the edges arriving at the BasicBlock to the corresponding
+ // created MachineBasicBlocks. Some BasicBlocks that get translated to a
+ // single MachineBasicBlock may also end up in this Map.
+ typedef std::pair<const BasicBlock *, const BasicBlock *> CFGEdge;
+ DenseMap<CFGEdge, SmallVector<MachineBasicBlock *, 1>> MachinePreds;
+
// List of stubbed PHI instructions, for values and basic blocks to be filled
// in once all MachineBasicBlocks have been created.
SmallVector<std::pair<const PHINode *, MachineInstr *>, 4> PendingPHIs;
@@ -122,7 +122,9 @@ private:
/// Translate an LLVM store instruction into generic IR.
bool translateStore(const User &U, MachineIRBuilder &MIRBuilder);
- bool translateMemcpy(const CallInst &CI, MachineIRBuilder &MIRBuilder);
+ /// Translate an LLVM string intrinsic (memcpy, memset, ...).
+ bool translateMemfunc(const CallInst &CI, MachineIRBuilder &MIRBuilder,
+ unsigned Intrinsic);
void getStackGuard(unsigned DstReg, MachineIRBuilder &MIRBuilder);
@@ -132,6 +134,8 @@ private:
bool translateKnownIntrinsic(const CallInst &CI, Intrinsic::ID ID,
MachineIRBuilder &MIRBuilder);
+ bool translateInlineAsm(const CallInst &CI, MachineIRBuilder &MIRBuilder);
+
/// Translate call instruction.
/// \pre \p U is a call instruction.
bool translateCall(const User &U, MachineIRBuilder &MIRBuilder);
@@ -145,11 +149,6 @@ private:
bool translateCast(unsigned Opcode, const User &U,
MachineIRBuilder &MIRBuilder);
- /// Translate static alloca instruction (i.e. one of constant size and in the
- /// first basic block).
- bool translateStaticAlloca(const AllocaInst &Inst,
- MachineIRBuilder &MIRBuilder);
-
/// Translate a phi instruction.
bool translatePHI(const User &U, MachineIRBuilder &MIRBuilder);
@@ -182,6 +181,8 @@ private:
bool translateSwitch(const User &U, MachineIRBuilder &MIRBuilder);
+ bool translateIndirectBr(const User &U, MachineIRBuilder &MIRBuilder);
+
bool translateExtractValue(const User &U, MachineIRBuilder &MIRBuilder);
bool translateInsertValue(const User &U, MachineIRBuilder &MIRBuilder);
@@ -190,12 +191,16 @@ private:
bool translateGetElementPtr(const User &U, MachineIRBuilder &MIRBuilder);
+ bool translateAlloca(const User &U, MachineIRBuilder &MIRBuilder);
+
/// Translate return (ret) instruction.
/// The target needs to implement CallLowering::lowerReturn for
/// this to succeed.
/// \pre \p U is a return instruction.
bool translateRet(const User &U, MachineIRBuilder &MIRBuilder);
+ bool translateFSub(const User &U, MachineIRBuilder &MIRBuilder);
+
bool translateAdd(const User &U, MachineIRBuilder &MIRBuilder) {
return translateBinaryOp(TargetOpcode::G_ADD, U, MIRBuilder);
}
@@ -227,9 +232,6 @@ private:
bool translateSRem(const User &U, MachineIRBuilder &MIRBuilder) {
return translateBinaryOp(TargetOpcode::G_SREM, U, MIRBuilder);
}
- bool translateAlloca(const User &U, MachineIRBuilder &MIRBuilder) {
- return translateStaticAlloca(cast<AllocaInst>(U), MIRBuilder);
- }
bool translateIntToPtr(const User &U, MachineIRBuilder &MIRBuilder) {
return translateCast(TargetOpcode::G_INTTOPTR, U, MIRBuilder);
}
@@ -281,9 +283,6 @@ private:
bool translateFAdd(const User &U, MachineIRBuilder &MIRBuilder) {
return translateBinaryOp(TargetOpcode::G_FADD, U, MIRBuilder);
}
- bool translateFSub(const User &U, MachineIRBuilder &MIRBuilder) {
- return translateBinaryOp(TargetOpcode::G_FSUB, U, MIRBuilder);
- }
bool translateFMul(const User &U, MachineIRBuilder &MIRBuilder) {
return translateBinaryOp(TargetOpcode::G_FMUL, U, MIRBuilder);
}
@@ -294,11 +293,16 @@ private:
return translateBinaryOp(TargetOpcode::G_FREM, U, MIRBuilder);
}
+ bool translateVAArg(const User &U, MachineIRBuilder &MIRBuilder);
+
+ bool translateInsertElement(const User &U, MachineIRBuilder &MIRBuilder);
+
+ bool translateExtractElement(const User &U, MachineIRBuilder &MIRBuilder);
+
+ bool translateShuffleVector(const User &U, MachineIRBuilder &MIRBuilder);
+
// Stubs to keep the compiler happy while we implement the rest of the
// translation.
- bool translateIndirectBr(const User &U, MachineIRBuilder &MIRBuilder) {
- return false;
- }
bool translateResume(const User &U, MachineIRBuilder &MIRBuilder) {
return false;
}
@@ -335,18 +339,6 @@ private:
bool translateUserOp2(const User &U, MachineIRBuilder &MIRBuilder) {
return false;
}
- bool translateVAArg(const User &U, MachineIRBuilder &MIRBuilder) {
- return false;
- }
- bool translateExtractElement(const User &U, MachineIRBuilder &MIRBuilder) {
- return false;
- }
- bool translateInsertElement(const User &U, MachineIRBuilder &MIRBuilder) {
- return false;
- }
- bool translateShuffleVector(const User &U, MachineIRBuilder &MIRBuilder) {
- return false;
- }
/// @}
@@ -371,6 +363,9 @@ private:
/// Current target configuration. Controls how the pass handles errors.
const TargetPassConfig *TPC;
+ /// Current optimization remark emitter. Used to report failures.
+ std::unique_ptr<OptimizationRemarkEmitter> ORE;
+
// * Insert all the code needed to materialize the constants
// at the proper place. E.g., Entry block or dominator block
// of each constant depending on how fancy we want to be.
@@ -390,10 +385,27 @@ private:
/// the type being accessed (according to the Module's DataLayout).
unsigned getMemOpAlignment(const Instruction &I);
- /// Get the MachineBasicBlock that represents \p BB.
- /// If such basic block does not exist, it is created.
- MachineBasicBlock &getOrCreateBB(const BasicBlock &BB);
+ /// Get the MachineBasicBlock that represents \p BB. Specifically, the block
+ /// returned will be the head of the translated block (suitable for branch
+ /// destinations).
+ MachineBasicBlock &getMBB(const BasicBlock &BB);
+
+ /// Record \p NewPred as a Machine predecessor to `Edge.second`, corresponding
+ /// to `Edge.first` at the IR level. This is used when IRTranslation creates
+ /// multiple MachineBasicBlocks for a given IR block and the CFG is no longer
+ /// represented simply by the IR-level CFG.
+ void addMachineCFGPred(CFGEdge Edge, MachineBasicBlock *NewPred);
+ /// Returns the Machine IR predecessors for the given IR CFG edge. Usually
+ /// this is just the single MachineBasicBlock corresponding to the predecessor
+ /// in the IR. More complex lowering can result in multiple MachineBasicBlocks
+ /// preceding the original though (e.g. switch instructions).
+ SmallVector<MachineBasicBlock *, 1> getMachinePredBBs(CFGEdge Edge) {
+ auto RemappedEdge = MachinePreds.find(Edge);
+ if (RemappedEdge != MachinePreds.end())
+ return RemappedEdge->second;
+ return SmallVector<MachineBasicBlock *, 4>(1, &getMBB(*Edge.first));
+ }
public:
// Ctor, nothing fancy.
@@ -407,13 +419,13 @@ public:
// CallLowering = MF.subtarget.getCallLowering()
// F = MF.getParent()
// MIRBuilder.reset(MF)
- // MIRBuilder.getOrCreateBB(F.getEntryBB())
+ // getMBB(F.getEntryBB())
// CallLowering->translateArguments(MIRBuilder, F, ValToVReg)
// for each bb in F
- // MIRBuilder.getOrCreateBB(bb)
+ // getMBB(bb)
// for each inst in bb
// if (!translate(MIRBuilder, inst, ValToVReg, ConstantToSequence))
- // report_fatal_error(“Don’t know how to translate input");
+ // report_fatal_error("Don't know how to translate input");
// finalize()
bool runOnMachineFunction(MachineFunction &MF) override;
};
diff --git a/include/llvm/CodeGen/GlobalISel/InstructionSelector.h b/include/llvm/CodeGen/GlobalISel/InstructionSelector.h
index 63b4f7b9507f..d8096aeb215a 100644
--- a/include/llvm/CodeGen/GlobalISel/InstructionSelector.h
+++ b/include/llvm/CodeGen/GlobalISel/InstructionSelector.h
@@ -16,8 +16,13 @@
#ifndef LLVM_CODEGEN_GLOBALISEL_INSTRUCTIONSELECTOR_H
#define LLVM_CODEGEN_GLOBALISEL_INSTRUCTIONSELECTOR_H
+#include "llvm/ADT/Optional.h"
+#include <cstdint>
+
namespace llvm {
class MachineInstr;
+class MachineOperand;
+class MachineRegisterInfo;
class RegisterBankInfo;
class TargetInstrInfo;
class TargetRegisterInfo;
@@ -56,6 +61,14 @@ protected:
const TargetInstrInfo &TII,
const TargetRegisterInfo &TRI,
const RegisterBankInfo &RBI) const;
+
+ Optional<int64_t> getConstantVRegVal(unsigned VReg,
+ const MachineRegisterInfo &MRI) const;
+
+ bool isOperandImmEqual(const MachineOperand &MO, int64_t Value,
+ const MachineRegisterInfo &MRI) const;
+
+ bool isObviouslySafeToFold(MachineInstr &MI) const;
};
} // End namespace llvm.
diff --git a/include/llvm/CodeGen/GlobalISel/Legalizer.h b/include/llvm/CodeGen/GlobalISel/Legalizer.h
index 8284ab6dac65..bed7230cc013 100644
--- a/include/llvm/CodeGen/GlobalISel/Legalizer.h
+++ b/include/llvm/CodeGen/GlobalISel/Legalizer.h
@@ -58,6 +58,9 @@ public:
bool combineExtracts(MachineInstr &MI, MachineRegisterInfo &MRI,
const TargetInstrInfo &TII);
+ bool combineMerges(MachineInstr &MI, MachineRegisterInfo &MRI,
+ const TargetInstrInfo &TII);
+
bool runOnMachineFunction(MachineFunction &MF) override;
};
} // End namespace llvm.
diff --git a/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h b/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h
index 56c444ca46be..8fecafdc08d0 100644
--- a/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h
+++ b/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h
@@ -55,11 +55,7 @@ public:
///
/// Considered as an opaque blob, the legal code will use and define the same
/// registers as \p MI.
- LegalizeResult legalizeInstrStep(MachineInstr &MI,
- const LegalizerInfo &LegalizerInfo);
-
- LegalizeResult legalizeInstr(MachineInstr &MI,
- const LegalizerInfo &LegalizerInfo);
+ LegalizeResult legalizeInstrStep(MachineInstr &MI);
/// Legalize an instruction by emiting a runtime library call instead.
LegalizeResult libcall(MachineInstr &MI);
@@ -87,6 +83,10 @@ public:
LegalizeResult moreElementsVector(MachineInstr &MI, unsigned TypeIdx,
LLT WideTy);
+ /// Expose MIRBuilder so clients can set their own RecordInsertInstruction
+ /// functions
+ MachineIRBuilder MIRBuilder;
+
private:
/// Helper function to split a wide generic register into bitwise blocks with
@@ -95,8 +95,8 @@ private:
void extractParts(unsigned Reg, LLT Ty, int NumParts,
SmallVectorImpl<unsigned> &Ops);
- MachineIRBuilder MIRBuilder;
MachineRegisterInfo &MRI;
+ const LegalizerInfo &LI;
};
} // End namespace llvm.
diff --git a/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h b/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h
index edf52daf3f8f..30d67eb49923 100644
--- a/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h
+++ b/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h
@@ -25,6 +25,7 @@
namespace llvm {
class LLVMContext;
class MachineInstr;
+class MachineIRBuilder;
class MachineRegisterInfo;
class Type;
class VectorType;
@@ -96,6 +97,7 @@ public:
};
LegalizerInfo();
+ virtual ~LegalizerInfo() = default;
/// Compute any ancillary tables needed to quickly decide how an operation
/// should be handled. This must be called after all "set*Action"methods but
@@ -144,7 +146,7 @@ public:
/// Iterate the given function (typically something like doubling the width)
/// on Ty until we find a legal type for this operation.
LLT findLegalType(const InstrAspect &Aspect,
- std::function<LLT(LLT)> NextType) const {
+ function_ref<LLT(LLT)> NextType) const {
LegalizeAction Action;
const TypeMap &Map = Actions[Aspect.Opcode - FirstOp][Aspect.Idx];
LLT Ty = Aspect.Type;
@@ -186,6 +188,10 @@ public:
bool isLegal(const MachineInstr &MI, const MachineRegisterInfo &MRI) const;
+ virtual bool legalizeCustom(MachineInstr &MI,
+ MachineRegisterInfo &MRI,
+ MachineIRBuilder &MIRBuilder) const;
+
private:
static const int FirstOp = TargetOpcode::PRE_ISEL_GENERIC_OPCODE_START;
static const int LastOp = TargetOpcode::PRE_ISEL_GENERIC_OPCODE_END;
diff --git a/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h b/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
index ecd3e5e1e138..472f50576d96 100644
--- a/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
+++ b/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
@@ -108,6 +108,9 @@ public:
/// Set the debug location to \p DL for all the next build instructions.
void setDebugLoc(const DebugLoc &DL) { this->DL = DL; }
+ /// Get the current instruction's debug location.
+ DebugLoc getDebugLoc() { return DL; }
+
/// Build and insert <empty> = \p Opcode <empty>.
/// The insertion point is the one set by the last call of either
/// setBasicBlock or setMI.
@@ -127,6 +130,29 @@ public:
/// Insert an existing instruction at the insertion point.
MachineInstrBuilder insertInstr(MachineInstrBuilder MIB);
+ /// Build and insert a DBG_VALUE instruction expressing the fact that the
+ /// associated \p Variable lives in \p Reg (suitably modified by \p Expr).
+ MachineInstrBuilder buildDirectDbgValue(unsigned Reg, const MDNode *Variable,
+ const MDNode *Expr);
+
+ /// Build and insert a DBG_VALUE instruction expressing the fact that the
+ /// associated \p Variable lives in memory at \p Reg + \p Offset (suitably
+ /// modified by \p Expr).
+ MachineInstrBuilder buildIndirectDbgValue(unsigned Reg, unsigned Offset,
+ const MDNode *Variable,
+ const MDNode *Expr);
+ /// Build and insert a DBG_VALUE instruction expressing the fact that the
+ /// associated \p Variable lives in the stack slot specified by \p FI
+ /// (suitably modified by \p Expr).
+ MachineInstrBuilder buildFIDbgValue(int FI, const MDNode *Variable,
+ const MDNode *Expr);
+
+ /// Build and insert a DBG_VALUE instructions specifying that \p Variable is
+ /// given by \p C (suitably modified by \p Expr).
+ MachineInstrBuilder buildConstDbgValue(const Constant &C, unsigned Offset,
+ const MDNode *Variable,
+ const MDNode *Expr);
+
/// Build and insert \p Res<def> = G_FRAME_INDEX \p Idx
///
/// G_FRAME_INDEX materializes the address of an alloca value or other
@@ -203,6 +229,22 @@ public:
MachineInstrBuilder buildGEP(unsigned Res, unsigned Op0,
unsigned Op1);
+ /// Build and insert \p Res<def> = G_PTR_MASK \p Op0, \p NumBits
+ ///
+ /// G_PTR_MASK clears the low bits of a pointer operand without destroying its
+ /// pointer properties. This has the effect of rounding the address *down* to
+ /// a specified alignment in bits.
+ ///
+ /// \pre setBasicBlock or setMI must have been called.
+ /// \pre \p Res and \p Op0 must be generic virtual registers with pointer
+ /// type.
+ /// \pre \p NumBits must be an integer representing the number of low bits to
+ /// be cleared in \p Op0.
+ ///
+ /// \return a MachineInstrBuilder for the newly created instruction.
+ MachineInstrBuilder buildPtrMask(unsigned Res, unsigned Op0,
+ uint32_t NumBits);
+
/// Build and insert \p Res<def>, \p CarryOut<def> = G_UADDE \p Op0,
/// \p Op1, \p CarryIn
///
@@ -220,6 +262,19 @@ public:
MachineInstrBuilder buildUAdde(unsigned Res, unsigned CarryOut, unsigned Op0,
unsigned Op1, unsigned CarryIn);
+ /// Build and insert \p Res<def> = G_AND \p Op0, \p Op1
+ ///
+ /// G_AND sets \p Res to the bitwise and of integer parameters \p Op0 and \p
+ /// Op1.
+ ///
+ /// \pre setBasicBlock or setMI must have been called.
+ /// \pre \p Res, \p Op0 and \p Op1 must be generic virtual registers
+ /// with the same (scalar or vector) type).
+ ///
+ /// \return a MachineInstrBuilder for the newly created instruction.
+ MachineInstrBuilder buildAnd(unsigned Res, unsigned Op0,
+ unsigned Op1);
+
/// Build and insert \p Res<def> = G_ANYEXT \p Op0
///
/// G_ANYEXT produces a register of the specified width, with bits 0 to
@@ -273,6 +328,19 @@ public:
/// \return The newly created instruction.
MachineInstrBuilder buildSExtOrTrunc(unsigned Res, unsigned Op);
+ /// Build and insert \p Res<def> = G_ZEXT \p Op, \p Res = G_TRUNC \p Op, or
+ /// \p Res = COPY \p Op depending on the differing sizes of \p Res and \p Op.
+ /// ///
+ /// \pre setBasicBlock or setMI must have been called.
+ /// \pre \p Res must be a generic virtual register with scalar or vector type.
+ /// \pre \p Op must be a generic virtual register with scalar or vector type.
+ ///
+ /// \return The newly created instruction.
+ MachineInstrBuilder buildZExtOrTrunc(unsigned Res, unsigned Op);
+
+ /// Build and insert an appropriate cast between two registers of equal size.
+ MachineInstrBuilder buildCast(unsigned Dst, unsigned Src);
+
/// Build and insert G_BR \p Dest
///
/// G_BR is an unconditional branch to \p Dest.
@@ -296,6 +364,16 @@ public:
/// \return The newly created instruction.
MachineInstrBuilder buildBrCond(unsigned Tst, MachineBasicBlock &BB);
+ /// Build and insert G_BRINDIRECT \p Tgt
+ ///
+ /// G_BRINDIRECT is an indirect branch to \p Tgt.
+ ///
+ /// \pre setBasicBlock or setMI must have been called.
+ /// \pre \p Tgt must be a generic virtual register with pointer type.
+ ///
+ /// \return a MachineInstrBuilder for the newly created instruction.
+ MachineInstrBuilder buildBrIndirect(unsigned Tgt);
+
/// Build and insert \p Res = G_CONSTANT \p Val
///
/// G_CONSTANT is an integer constant with the specified size and value. \p
@@ -362,19 +440,16 @@ public:
MachineInstrBuilder buildStore(unsigned Val, unsigned Addr,
MachineMemOperand &MMO);
- /// Build and insert `Res0<def>, ... = G_EXTRACT Src, Idx0, ...`.
- ///
- /// If \p Res[i] has size N bits, G_EXTRACT sets \p Res[i] to bits `[Idxs[i],
- /// Idxs[i] + N)` of \p Src.
+ /// Build and insert `Res0<def>, ... = G_EXTRACT Src, Idx0`.
///
/// \pre setBasicBlock or setMI must have been called.
- /// \pre Indices must be in ascending order of bit position.
- /// \pre Each member of \p Results and \p Src must be a generic
- /// virtual register.
+ /// \pre \p Res and \p Src must be generic virtual registers.
///
/// \return a MachineInstrBuilder for the newly created instruction.
- MachineInstrBuilder buildExtract(ArrayRef<unsigned> Results,
- ArrayRef<uint64_t> Indices, unsigned Src);
+ MachineInstrBuilder buildExtract(unsigned Res, unsigned Src, uint64_t Index);
+
+ /// Build and insert \p Res = IMPLICIT_DEF.
+ MachineInstrBuilder buildUndef(unsigned Dst);
/// Build and insert \p Res<def> = G_SEQUENCE \p Op0, \p Idx0...
///
@@ -393,6 +468,31 @@ public:
ArrayRef<unsigned> Ops,
ArrayRef<uint64_t> Indices);
+ /// Build and insert \p Res<def> = G_MERGE_VALUES \p Op0, ...
+ ///
+ /// G_MERGE_VALUES combines the input elements contiguously into a larger
+ /// register.
+ ///
+ /// \pre setBasicBlock or setMI must have been called.
+ /// \pre The entire register \p Res (and no more) must be covered by the input
+ /// registers.
+ /// \pre The type of all \p Ops registers must be identical.
+ ///
+ /// \return a MachineInstrBuilder for the newly created instruction.
+ MachineInstrBuilder buildMerge(unsigned Res, ArrayRef<unsigned> Ops);
+
+ /// Build and insert \p Res0<def>, ... = G_UNMERGE_VALUES \p Op
+ ///
+ /// G_UNMERGE_VALUES splits contiguous bits of the input into multiple
+ ///
+ /// \pre setBasicBlock or setMI must have been called.
+ /// \pre The entire register \p Res (and no more) must be covered by the input
+ /// registers.
+ /// \pre The type of all \p Res registers must be identical.
+ ///
+ /// \return a MachineInstrBuilder for the newly created instruction.
+ MachineInstrBuilder buildUnmerge(ArrayRef<unsigned> Res, unsigned Op);
+
void addUsesWithIndices(MachineInstrBuilder MIB) {}
template <typename... ArgTys>
@@ -411,14 +511,8 @@ public:
return MIB;
}
- template <typename... ArgTys>
MachineInstrBuilder buildInsert(unsigned Res, unsigned Src,
- unsigned Op, unsigned Index, ArgTys... Args) {
- MachineInstrBuilder MIB =
- buildInstr(TargetOpcode::G_INSERT).addDef(Res).addUse(Src);
- addUsesWithIndices(MIB, Op, Index, Args...);
- return MIB;
- }
+ unsigned Op, unsigned Index);
/// Build and insert either a G_INTRINSIC (if \p HasSideEffects is false) or
/// G_INTRINSIC_W_SIDE_EFFECTS instruction. Its first operand will be the
@@ -500,6 +594,30 @@ public:
/// \return a MachineInstrBuilder for the newly created instruction.
MachineInstrBuilder buildSelect(unsigned Res, unsigned Tst,
unsigned Op0, unsigned Op1);
+
+ /// Build and insert \p Res<def> = G_INSERT_VECTOR_ELT \p Val,
+ /// \p Elt, \p Idx
+ ///
+ /// \pre setBasicBlock or setMI must have been called.
+ /// \pre \p Res and \p Val must be a generic virtual register
+ // with the same vector type.
+ /// \pre \p Elt and \p Idx must be a generic virtual register
+ /// with scalar type.
+ ///
+ /// \return The newly created instruction.
+ MachineInstrBuilder buildInsertVectorElement(unsigned Res, unsigned Val,
+ unsigned Elt, unsigned Idx);
+
+ /// Build and insert \p Res<def> = G_EXTRACT_VECTOR_ELT \p Val, \p Idx
+ ///
+ /// \pre setBasicBlock or setMI must have been called.
+ /// \pre \p Res must be a generic virtual register with scalar type.
+ /// \pre \p Val must be a generic virtual register with vector type.
+ /// \pre \p Idx must be a generic virtual register with scalar type.
+ ///
+ /// \return The newly created instruction.
+ MachineInstrBuilder buildExtractVectorElement(unsigned Res, unsigned Val,
+ unsigned Idx);
};
} // End namespace llvm.
diff --git a/include/llvm/CodeGen/GlobalISel/RegBankSelect.h b/include/llvm/CodeGen/GlobalISel/RegBankSelect.h
index b331533cd7fb..daa8dcf2061b 100644
--- a/include/llvm/CodeGen/GlobalISel/RegBankSelect.h
+++ b/include/llvm/CodeGen/GlobalISel/RegBankSelect.h
@@ -67,6 +67,7 @@
#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
#include "llvm/CodeGen/GlobalISel/RegisterBankInfo.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h"
namespace llvm {
// Forward declarations.
@@ -484,6 +485,9 @@ private:
/// This is required for non-fast mode.
MachineBranchProbabilityInfo *MBPI;
+ /// Current optimization remark emitter. Used to report failures.
+ std::unique_ptr<MachineOptimizationRemarkEmitter> MORE;
+
/// Helper class used for every code morphing.
MachineIRBuilder MIRBuilder;
diff --git a/include/llvm/CodeGen/GlobalISel/RegisterBank.h b/include/llvm/CodeGen/GlobalISel/RegisterBank.h
index b05bf9948243..5d758423f4e7 100644
--- a/include/llvm/CodeGen/GlobalISel/RegisterBank.h
+++ b/include/llvm/CodeGen/GlobalISel/RegisterBank.h
@@ -42,7 +42,7 @@ private:
public:
RegisterBank(unsigned ID, const char *Name, unsigned Size,
- const uint32_t *ContainedRegClasses);
+ const uint32_t *ContainedRegClasses, unsigned NumRegClasses);
/// Get the identifier of this register bank.
unsigned getID() const { return ID; }
diff --git a/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h b/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h
index 312dc9314d45..600733ac6a2d 100644
--- a/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h
+++ b/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h
@@ -317,12 +317,18 @@ public:
/// The final mapping of the instruction.
const InstructionMapping &getInstrMapping() const { return InstrMapping; }
+
+ /// The MachineRegisterInfo we used to realize the mapping.
+ MachineRegisterInfo &getMRI() const { return MRI; }
/// @}
/// Create as many new virtual registers as needed for the mapping of the \p
/// OpIdx-th operand.
/// The number of registers is determined by the number of breakdown for the
/// related operand in the instruction mapping.
+ /// The type of the new registers is a plain scalar of the right size.
+ /// The proper type is expected to be set when the mapping is applied to
+ /// the instruction(s) that realizes the mapping.
///
/// \pre getMI().getOperand(OpIdx).isReg()
///
@@ -372,15 +378,15 @@ protected:
/// Keep dynamically allocated PartialMapping in a separate map.
/// This shouldn't be needed when everything gets TableGen'ed.
- mutable DenseMap<unsigned, const PartialMapping *> MapOfPartialMappings;
+ mutable DenseMap<unsigned, std::unique_ptr<const PartialMapping>> MapOfPartialMappings;
/// Keep dynamically allocated ValueMapping in a separate map.
/// This shouldn't be needed when everything gets TableGen'ed.
- mutable DenseMap<unsigned, const ValueMapping *> MapOfValueMappings;
+ mutable DenseMap<unsigned, std::unique_ptr<const ValueMapping> > MapOfValueMappings;
/// Keep dynamically allocated array of ValueMapping in a separate map.
/// This shouldn't be needed when everything gets TableGen'ed.
- mutable DenseMap<unsigned, ValueMapping *> MapOfOperandsMappings;
+ mutable DenseMap<unsigned, std::unique_ptr<ValueMapping[]>> MapOfOperandsMappings;
/// Create a RegisterBankInfo that can accomodate up to \p NumRegBanks
/// RegisterBank instances.
@@ -487,6 +493,12 @@ protected:
/// Basically, that means that \p OpdMapper.getMI() is left untouched
/// aside from the reassignment of the register operand that have been
/// remapped.
+ ///
+ /// The type of all the new registers that have been created by the
+ /// mapper are properly remapped to the type of the original registers
+ /// they replace. In other words, the semantic of the instruction does
+ /// not change, only the register banks.
+ ///
/// If the mapping of one of the operand spans several registers, this
/// method will abort as this is not like a default mapping anymore.
///
@@ -500,7 +512,7 @@ protected:
}
public:
- virtual ~RegisterBankInfo();
+ virtual ~RegisterBankInfo() = default;
/// Get the register bank identified by \p ID.
const RegisterBank &getRegBank(unsigned ID) const {
diff --git a/include/llvm/CodeGen/GlobalISel/Utils.h b/include/llvm/CodeGen/GlobalISel/Utils.h
index f5d5f5cdf0cd..52bf965a3cb3 100644
--- a/include/llvm/CodeGen/GlobalISel/Utils.h
+++ b/include/llvm/CodeGen/GlobalISel/Utils.h
@@ -15,15 +15,21 @@
#ifndef LLVM_CODEGEN_GLOBALISEL_UTILS_H
#define LLVM_CODEGEN_GLOBALISEL_UTILS_H
+#include "llvm/ADT/StringRef.h"
+
namespace llvm {
class MachineFunction;
class MachineInstr;
+class MachineOptimizationRemarkEmitter;
+class MachineOptimizationRemarkMissed;
class MachineRegisterInfo;
class MCInstrDesc;
class RegisterBankInfo;
class TargetInstrInfo;
+class TargetPassConfig;
class TargetRegisterInfo;
+class Twine;
/// Try to constrain Reg so that it is usable by argument OpIdx of the
/// provided MCInstrDesc \p II. If this fails, create a new virtual
@@ -39,5 +45,20 @@ unsigned constrainOperandRegClass(const MachineFunction &MF,
MachineInstr &InsertPt, const MCInstrDesc &II,
unsigned Reg, unsigned OpIdx);
+/// Check whether an instruction \p MI is dead: it only defines dead virtual
+/// registers, and doesn't have other side effects.
+bool isTriviallyDead(const MachineInstr &MI, const MachineRegisterInfo &MRI);
+
+/// Report an ISel error as a missed optimization remark to the LLVMContext's
+/// diagnostic stream. Set the FailedISel MachineFunction property.
+void reportGISelFailure(MachineFunction &MF, const TargetPassConfig &TPC,
+ MachineOptimizationRemarkEmitter &MORE,
+ MachineOptimizationRemarkMissed &R);
+
+void reportGISelFailure(MachineFunction &MF, const TargetPassConfig &TPC,
+ MachineOptimizationRemarkEmitter &MORE,
+ const char *PassName, StringRef Msg,
+ const MachineInstr &MI);
+
} // End namespace llvm.
#endif
diff --git a/include/llvm/CodeGen/ISDOpcodes.h b/include/llvm/CodeGen/ISDOpcodes.h
index df700bf0c53d..ee3fd0bdda2a 100644
--- a/include/llvm/CodeGen/ISDOpcodes.h
+++ b/include/llvm/CodeGen/ISDOpcodes.h
@@ -245,6 +245,12 @@ namespace ISD {
/// Simple binary floating point operators.
FADD, FSUB, FMUL, FDIV, FREM,
+ /// Constrained versions of the binary floating point operators.
+ /// These will be lowered to the simple operators before final selection.
+ /// They are used to limit optimizations while the DAG is being
+ /// optimized.
+ STRICT_FADD, STRICT_FSUB, STRICT_FMUL, STRICT_FDIV, STRICT_FREM,
+
/// FMA - Perform a * b + c with no intermediate rounding step.
FMA,
@@ -281,7 +287,8 @@ namespace ISD {
/// EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR
/// identified by the (potentially variable) element number IDX. If the
/// return type is an integer type larger than the element type of the
- /// vector, the result is extended to the width of the return type.
+ /// vector, the result is extended to the width of the return type. In
+ /// that case, the high bits are undefined.
EXTRACT_VECTOR_ELT,
/// CONCAT_VECTORS(VECTOR0, VECTOR1, ...) - Given a number of values of
@@ -332,6 +339,12 @@ namespace ISD {
/// Bitwise operators - logical and, logical or, logical xor.
AND, OR, XOR,
+ /// ABS - Determine the unsigned absolute value of a signed integer value of
+ /// the same bitwidth.
+ /// Note: A value of INT_MIN will return INT_MIN, no saturation or overflow
+ /// is performed.
+ ABS,
+
/// Shift and rotation operations. After legalization, the type of the
/// shift amount is known to be TLI.getShiftAmountTy(). Before legalization
/// the shift amount can be any type, but care must be taken to ensure it is
@@ -801,10 +814,11 @@ namespace ISD {
PRE_INC,
PRE_DEC,
POST_INC,
- POST_DEC,
- LAST_INDEXED_MODE
+ POST_DEC
};
+ static const int LAST_INDEXED_MODE = POST_DEC + 1;
+
//===--------------------------------------------------------------------===//
/// LoadExtType enum - This enum defines the three variants of LOADEXT
/// (load with extension).
@@ -819,10 +833,11 @@ namespace ISD {
NON_EXTLOAD = 0,
EXTLOAD,
SEXTLOAD,
- ZEXTLOAD,
- LAST_LOADEXT_TYPE
+ ZEXTLOAD
};
+ static const int LAST_LOADEXT_TYPE = ZEXTLOAD + 1;
+
NodeType getExtForLoadExtType(bool IsFP, LoadExtType);
//===--------------------------------------------------------------------===//
diff --git a/include/llvm/CodeGen/LazyMachineBlockFrequencyInfo.h b/include/llvm/CodeGen/LazyMachineBlockFrequencyInfo.h
new file mode 100644
index 000000000000..848ee1dc0dc6
--- /dev/null
+++ b/include/llvm/CodeGen/LazyMachineBlockFrequencyInfo.h
@@ -0,0 +1,76 @@
+///===- LazyMachineBlockFrequencyInfo.h - Lazy Block Frequency -*- C++ -*--===//
+///
+/// The LLVM Compiler Infrastructure
+///
+/// This file is distributed under the University of Illinois Open Source
+/// License. See LICENSE.TXT for details.
+///
+///===---------------------------------------------------------------------===//
+/// \file
+/// This is an alternative analysis pass to MachineBlockFrequencyInfo. The
+/// difference is that with this pass the block frequencies are not computed
+/// when the analysis pass is executed but rather when the BFI result is
+/// explicitly requested by the analysis client.
+///
+///===---------------------------------------------------------------------===//
+
+#ifndef LLVM_ANALYSIS_LAZYMACHINEBLOCKFREQUENCYINFO_H
+#define LLVM_ANALYSIS_LAZYMACHINEBLOCKFREQUENCYINFO_H
+
+#include "llvm/CodeGen/MachineBlockFrequencyInfo.h"
+#include "llvm/CodeGen/MachineBranchProbabilityInfo.h"
+#include "llvm/CodeGen/MachineDominators.h"
+#include "llvm/CodeGen/MachineLoopInfo.h"
+
+namespace llvm {
+/// \brief This is an alternative analysis pass to MachineBlockFrequencyInfo.
+/// The difference is that with this pass, the block frequencies are not
+/// computed when the analysis pass is executed but rather when the BFI result
+/// is explicitly requested by the analysis client.
+///
+/// This works by checking querying if MBFI is available and otherwise
+/// generating MBFI on the fly. In this case the passes required for (LI, DT)
+/// are also queried before being computed on the fly.
+///
+/// Note that it is expected that we wouldn't need this functionality for the
+/// new PM since with the new PM, analyses are executed on demand.
+
+class LazyMachineBlockFrequencyInfoPass : public MachineFunctionPass {
+private:
+ /// If generated on the fly this own the instance.
+ mutable std::unique_ptr<MachineBlockFrequencyInfo> OwnedMBFI;
+
+ /// If generated on the fly this own the instance.
+ mutable std::unique_ptr<MachineLoopInfo> OwnedMLI;
+
+ /// If generated on the fly this own the instance.
+ mutable std::unique_ptr<MachineDominatorTree> OwnedMDT;
+
+ /// The function.
+ MachineFunction *MF = nullptr;
+
+ /// \brief Calculate MBFI and all other analyses that's not available and
+ /// required by BFI.
+ MachineBlockFrequencyInfo &calculateIfNotAvailable() const;
+
+public:
+ static char ID;
+
+ LazyMachineBlockFrequencyInfoPass();
+
+ /// \brief Compute and return the block frequencies.
+ MachineBlockFrequencyInfo &getBFI() { return calculateIfNotAvailable(); }
+
+ /// \brief Compute and return the block frequencies.
+ const MachineBlockFrequencyInfo &getBFI() const {
+ return calculateIfNotAvailable();
+ }
+
+ void getAnalysisUsage(AnalysisUsage &AU) const override;
+
+ bool runOnMachineFunction(MachineFunction &F) override;
+ void releaseMemory() override;
+ void print(raw_ostream &OS, const Module *M) const override;
+};
+}
+#endif
diff --git a/include/llvm/CodeGen/LexicalScopes.h b/include/llvm/CodeGen/LexicalScopes.h
index 7d7e48af2a0f..6c35832f963c 100644
--- a/include/llvm/CodeGen/LexicalScopes.h
+++ b/include/llvm/CodeGen/LexicalScopes.h
@@ -1,4 +1,4 @@
-//===- LexicalScopes.cpp - Collecting lexical scope info -*- C++ -*--------===//
+//===- LexicalScopes.cpp - Collecting lexical scope info --------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -19,19 +19,18 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
-#include "llvm/IR/DebugLoc.h"
#include "llvm/IR/DebugInfoMetadata.h"
-#include "llvm/IR/ValueHandle.h"
+#include <cassert>
#include <unordered_map>
#include <utility>
+
namespace llvm {
-class MachineInstr;
class MachineBasicBlock;
class MachineFunction;
+class MachineInstr;
//===----------------------------------------------------------------------===//
/// InsnRange - This is used to track range of instructions with identical
@@ -43,13 +42,15 @@ typedef std::pair<const MachineInstr *, const MachineInstr *> InsnRange;
/// LexicalScope - This class is used to track scope information.
///
class LexicalScope {
-
public:
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");
+ : Parent(P), Desc(D), InlinedAtLocation(I), AbstractScope(A) {
+ assert(D);
+ assert(D->getSubprogram()->getUnit()->getEmissionKind() !=
+ DICompileUnit::NoDebug &&
+ "Don't build lexical scopes for non-debug locations");
+ assert(D->isResolved() && "Expected resolved node");
assert((!I || I->isResolved()) && "Expected resolved node");
if (Parent)
Parent->addChild(this);
@@ -127,10 +128,10 @@ private:
// Contents not owned.
SmallVector<InsnRange, 4> Ranges;
- const MachineInstr *LastInsn; // Last instruction of this scope.
- const MachineInstr *FirstInsn; // First instruction of this scope.
- unsigned DFSIn, DFSOut; // In & Out Depth use to determine
- // scope nesting.
+ const MachineInstr *LastInsn = nullptr; // Last instruction of this scope.
+ const MachineInstr *FirstInsn = nullptr; // First instruction of this scope.
+ unsigned DFSIn = 0; // In & Out Depth use to determine scope nesting.
+ unsigned DFSOut = 0;
};
//===----------------------------------------------------------------------===//
@@ -139,7 +140,7 @@ private:
///
class LexicalScopes {
public:
- LexicalScopes() : MF(nullptr), CurrentFnLexicalScope(nullptr) {}
+ LexicalScopes() = default;
/// initialize - Scan machine function and constuct lexical scope nest, resets
/// the instance if necessary.
@@ -225,8 +226,7 @@ private:
assignInstructionRanges(SmallVectorImpl<InsnRange> &MIRanges,
DenseMap<const MachineInstr *, LexicalScope *> &M);
-private:
- const MachineFunction *MF;
+ const MachineFunction *MF = nullptr;
/// LexicalScopeMap - Tracks the scopes in the current function.
// Use an unordered_map to ensure value pointer validity over insertion.
@@ -249,9 +249,9 @@ private:
/// CurrentFnLexicalScope - Top level scope for the current function.
///
- LexicalScope *CurrentFnLexicalScope;
+ LexicalScope *CurrentFnLexicalScope = nullptr;
};
-} // end llvm namespace
+} // end namespace llvm
-#endif
+#endif // LLVM_CODEGEN_LEXICALSCOPES_H
diff --git a/include/llvm/CodeGen/LiveInterval.h b/include/llvm/CodeGen/LiveInterval.h
index a86706223261..b792cba4b78a 100644
--- a/include/llvm/CodeGen/LiveInterval.h
+++ b/include/llvm/CodeGen/LiveInterval.h
@@ -227,15 +227,22 @@ namespace llvm {
LiveRange(const LiveRange &Other, BumpPtrAllocator &Allocator) {
assert(Other.segmentSet == nullptr &&
"Copying of LiveRanges with active SegmentSets is not supported");
+ assign(Other, Allocator);
+ }
+
+ /// Copies values numbers and live segments from \p Other into this range.
+ void assign(const LiveRange &Other, BumpPtrAllocator &Allocator) {
+ if (this == &Other)
+ return;
+ assert(Other.segmentSet == nullptr &&
+ "Copying of LiveRanges with active SegmentSets is not supported");
// Duplicate valnos.
- for (const VNInfo *VNI : Other.valnos) {
+ for (const VNInfo *VNI : Other.valnos)
createValueCopy(VNI, Allocator);
- }
// Now we can copy segments and remap their valnos.
- for (const Segment &S : Other.segments) {
+ for (const Segment &S : Other.segments)
segments.push_back(Segment(S.start, S.end, valnos[S.valno->id]));
- }
}
/// advanceTo - Advance the specified iterator to point to the Segment
@@ -767,6 +774,19 @@ namespace llvm {
const MachineRegisterInfo &MRI,
const SlotIndexes &Indexes) const;
+ /// Refines the subranges to support \p LaneMask. This may only be called
+ /// for LI.hasSubrange()==true. Subregister ranges are split or created
+ /// until \p LaneMask can be matched exactly. \p Mod is executed on the
+ /// matching subranges.
+ ///
+ /// Example:
+ /// Given an interval with subranges with lanemasks L0F00, L00F0 and
+ /// L000F, refining for mask L0018. Will split the L00F0 lane into
+ /// L00E0 and L0010 and the L000F lane into L0007 and L0008. The Mod
+ /// function will be applied to the L0010 and L0008 subranges.
+ void refineSubRanges(BumpPtrAllocator &Allocator, LaneBitmask LaneMask,
+ std::function<void(LiveInterval::SubRange&)> Mod);
+
bool operator<(const LiveInterval& other) const {
const SlotIndex &thisIndex = beginIndex();
const SlotIndex &otherIndex = other.beginIndex();
diff --git a/include/llvm/CodeGen/LiveIntervalAnalysis.h b/include/llvm/CodeGen/LiveIntervalAnalysis.h
index f8dc52566dc0..f5b1f87720ad 100644
--- a/include/llvm/CodeGen/LiveIntervalAnalysis.h
+++ b/include/llvm/CodeGen/LiveIntervalAnalysis.h
@@ -7,13 +7,13 @@
//
//===----------------------------------------------------------------------===//
//
-// This file implements the LiveInterval analysis pass. Given some numbering of
-// each the machine instructions (in this implemention depth-first order) an
-// interval [i, j) is said to be a live interval for register v if there is no
-// instruction with number j' > j such that v is live at j' and there is no
-// instruction with number i' < i such that v is live at i'. In this
-// implementation intervals can have holes, i.e. an interval might look like
-// [1,20), [50,65), [1000,1001).
+/// \file This file implements the LiveInterval analysis pass. Given some
+/// numbering of each the machine instructions (in this implemention depth-first
+/// order) an interval [i, j) is said to be a live interval for register v if
+/// there is no instruction with number j' > j such that v is live at j' and
+/// there is no instruction with number i' < i such that v is live at i'. In
+/// this implementation intervals can have holes, i.e. an interval might look
+/// like [1,20), [50,65), [1000,1001).
//
//===----------------------------------------------------------------------===//
@@ -60,20 +60,17 @@ extern cl::opt<bool> UseSegmentSetForPhysRegs;
LiveRangeCalc *LRCalc;
/// Special pool allocator for VNInfo's (LiveInterval val#).
- ///
VNInfo::Allocator VNInfoAllocator;
/// Live interval pointers for all the virtual registers.
IndexedMap<LiveInterval*, VirtReg2IndexFunctor> VirtRegIntervals;
- /// RegMaskSlots - Sorted list of instructions with register mask operands.
- /// Always use the 'r' slot, RegMasks are normal clobbers, not early
- /// clobbers.
+ /// Sorted list of instructions with register mask operands. Always use the
+ /// 'r' slot, RegMasks are normal clobbers, not early clobbers.
SmallVector<SlotIndex, 8> RegMaskSlots;
- /// RegMaskBits - This vector is parallel to RegMaskSlots, it holds a
- /// pointer to the corresponding register mask. This pointer can be
- /// recomputed as:
+ /// This vector is parallel to RegMaskSlots, it holds a pointer to the
+ /// corresponding register mask. This pointer can be recomputed as:
///
/// MI = Indexes->getInstructionFromIndex(RegMaskSlot[N]);
/// unsigned OpNum = findRegMaskOperand(MI);
@@ -97,11 +94,11 @@ extern cl::opt<bool> UseSegmentSetForPhysRegs;
SmallVector<LiveRange*, 0> RegUnitRanges;
public:
- static char ID; // Pass identification, replacement for typeid
+ static char ID;
LiveIntervals();
~LiveIntervals() override;
- // Calculate the spill weight to assign to a single instruction.
+ /// Calculate the spill weight to assign to a single instruction.
static float getSpillWeight(bool isDef, bool isUse,
const MachineBlockFrequencyInfo *MBFI,
const MachineInstr &Instr);
@@ -121,7 +118,7 @@ extern cl::opt<bool> UseSegmentSetForPhysRegs;
return VirtRegIntervals.inBounds(Reg) && VirtRegIntervals[Reg];
}
- // Interval creation.
+ /// Interval creation.
LiveInterval &createEmptyInterval(unsigned Reg) {
assert(!hasInterval(Reg) && "Interval already exists!");
VirtRegIntervals.grow(Reg);
@@ -135,7 +132,7 @@ extern cl::opt<bool> UseSegmentSetForPhysRegs;
return LI;
}
- // Interval removal.
+ /// Interval removal.
void removeInterval(unsigned Reg) {
delete VirtRegIntervals[Reg];
VirtRegIntervals[Reg] = nullptr;
@@ -163,16 +160,16 @@ extern cl::opt<bool> UseSegmentSetForPhysRegs;
/// LiveInterval::removeEmptySubranges() afterwards.
void shrinkToUses(LiveInterval::SubRange &SR, unsigned Reg);
- /// Extend the live range @p LR to reach all points in @p Indices. The
- /// points in the @p Indices array must be jointly dominated by the union
- /// of the existing defs in @p LR and points in @p Undefs.
+ /// Extend the live range \p LR to reach all points in \p Indices. The
+ /// points in the \p Indices array must be jointly dominated by the union
+ /// of the existing defs in \p LR and points in \p Undefs.
///
/// PHI-defs are added as needed to maintain SSA form.
///
- /// If a SlotIndex in @p Indices is the end index of a basic block, @p LR
+ /// If a SlotIndex in \p Indices is the end index of a basic block, \p LR
/// will be extended to be live out of the basic block.
- /// If a SlotIndex in @p Indices is jointy dominated only by points in
- /// @p Undefs, the live range will not be extended to that point.
+ /// If a SlotIndex in \p Indices is jointy dominated only by points in
+ /// \p Undefs, the live range will not be extended to that point.
///
/// See also LiveRangeCalc::extend().
void extendToIndices(LiveRange &LR, ArrayRef<SlotIndex> Indices,
@@ -182,7 +179,7 @@ extern cl::opt<bool> UseSegmentSetForPhysRegs;
extendToIndices(LR, Indices, /*Undefs=*/{});
}
- /// If @p LR has a live value at @p Kill, prune its live range by removing
+ /// If \p LR has a live value at \p Kill, prune its live range by removing
/// any liveness reachable from Kill. Add live range end points to
/// EndPoints such that extendToIndices(LI, EndPoints) will reconstruct the
/// value's live range.
@@ -192,6 +189,16 @@ extern cl::opt<bool> UseSegmentSetForPhysRegs;
void pruneValue(LiveRange &LR, SlotIndex Kill,
SmallVectorImpl<SlotIndex> *EndPoints);
+ /// This function should be used. Its intend is to tell you that
+ /// you are doing something wrong if you call pruveValue directly on a
+ /// LiveInterval. Indeed, you are supposed to call pruneValue on the main
+ /// LiveRange and all the LiveRange of the subranges if any.
+ LLVM_ATTRIBUTE_UNUSED void pruneValue(LiveInterval &, SlotIndex,
+ SmallVectorImpl<SlotIndex> *) {
+ llvm_unreachable(
+ "Use pruneValue on the main LiveRange and on each subrange");
+ }
+
SlotIndexes *getSlotIndexes() const {
return Indexes;
}
@@ -200,8 +207,8 @@ extern cl::opt<bool> UseSegmentSetForPhysRegs;
return AA;
}
- /// isNotInMIMap - returns true if the specified machine instr has been
- /// removed or was never entered in the map.
+ /// Returns true if the specified machine instr has been removed or was
+ /// never entered in the map.
bool isNotInMIMap(const MachineInstr &Instr) const {
return !Indexes->hasIndex(Instr);
}
@@ -270,35 +277,32 @@ extern cl::opt<bool> UseSegmentSetForPhysRegs;
void getAnalysisUsage(AnalysisUsage &AU) const override;
void releaseMemory() override;
- /// runOnMachineFunction - pass entry point
+ /// Pass entry point; Calculates LiveIntervals.
bool runOnMachineFunction(MachineFunction&) override;
- /// print - Implement the dump method.
+ /// Implement the dump method.
void print(raw_ostream &O, const Module* = nullptr) const override;
- /// intervalIsInOneMBB - If LI is confined to a single basic block, return
- /// a pointer to that block. If LI is live in to or out of any block,
- /// return NULL.
+ /// If LI is confined to a single basic block, return a pointer to that
+ /// block. If LI is live in to or out of any block, return NULL.
MachineBasicBlock *intervalIsInOneMBB(const LiveInterval &LI) const;
/// Returns true if VNI is killed by any PHI-def values in LI.
/// This may conservatively return true to avoid expensive computations.
bool hasPHIKill(const LiveInterval &LI, const VNInfo *VNI) const;
- /// addKillFlags - Add kill flags to any instruction that kills a virtual
- /// register.
+ /// Add kill flags to any instruction that kills a virtual register.
void addKillFlags(const VirtRegMap*);
- /// handleMove - call this method to notify LiveIntervals that
- /// instruction 'mi' has been moved within a basic block. This will update
- /// the live intervals for all operands of mi. Moves between basic blocks
- /// are not supported.
+ /// Call this method to notify LiveIntervals that instruction \p MI has been
+ /// moved within a basic block. This will update the live intervals for all
+ /// operands of \p MI. Moves between basic blocks are not supported.
///
/// \param UpdateFlags Update live intervals for nonallocatable physregs.
void handleMove(MachineInstr &MI, bool UpdateFlags = false);
- /// moveIntoBundle - Update intervals for operands of MI so that they
- /// begin/end on the SlotIndex for BundleStart.
+ /// Update intervals for operands of \p MI so that they begin/end on the
+ /// SlotIndex for \p BundleStart.
///
/// \param UpdateFlags Update live intervals for nonallocatable physregs.
///
@@ -308,10 +312,9 @@ extern cl::opt<bool> UseSegmentSetForPhysRegs;
void handleMoveIntoBundle(MachineInstr &MI, MachineInstr &BundleStart,
bool UpdateFlags = false);
- /// repairIntervalsInRange - Update live intervals for instructions in a
- /// range of iterators. It is intended for use after target hooks that may
- /// insert or remove instructions, and is only efficient for a small number
- /// of instructions.
+ /// Update live intervals for instructions in a range of iterators. It is
+ /// intended for use after target hooks that may insert or remove
+ /// instructions, and is only efficient for a small number of instructions.
///
/// OrigRegs is a vector of registers that were originally used by the
/// instructions in the range between the two iterators.
@@ -334,34 +337,33 @@ extern cl::opt<bool> UseSegmentSetForPhysRegs;
// LiveIntervalAnalysis maintains a sorted list of instructions with
// register mask operands.
- /// getRegMaskSlots - Returns a sorted array of slot indices of all
- /// instructions with register mask operands.
+ /// Returns a sorted array of slot indices of all instructions with
+ /// register mask operands.
ArrayRef<SlotIndex> getRegMaskSlots() const { return RegMaskSlots; }
- /// getRegMaskSlotsInBlock - Returns a sorted array of slot indices of all
- /// instructions with register mask operands in the basic block numbered
- /// MBBNum.
+ /// Returns a sorted array of slot indices of all instructions with register
+ /// mask operands in the basic block numbered \p MBBNum.
ArrayRef<SlotIndex> getRegMaskSlotsInBlock(unsigned MBBNum) const {
std::pair<unsigned, unsigned> P = RegMaskBlocks[MBBNum];
return getRegMaskSlots().slice(P.first, P.second);
}
- /// getRegMaskBits() - Returns an array of register mask pointers
- /// corresponding to getRegMaskSlots().
+ /// Returns an array of register mask pointers corresponding to
+ /// getRegMaskSlots().
ArrayRef<const uint32_t*> getRegMaskBits() const { return RegMaskBits; }
- /// getRegMaskBitsInBlock - Returns an array of mask pointers corresponding
- /// to getRegMaskSlotsInBlock(MBBNum).
+ /// Returns an array of mask pointers corresponding to
+ /// getRegMaskSlotsInBlock(MBBNum).
ArrayRef<const uint32_t*> getRegMaskBitsInBlock(unsigned MBBNum) const {
std::pair<unsigned, unsigned> P = RegMaskBlocks[MBBNum];
return getRegMaskBits().slice(P.first, P.second);
}
- /// checkRegMaskInterference - Test if LI is live across any register mask
- /// instructions, and compute a bit mask of physical registers that are not
- /// clobbered by any of them.
+ /// Test if \p LI is live across any register mask instructions, and
+ /// compute a bit mask of physical registers that are not clobbered by any
+ /// of them.
///
- /// Returns false if LI doesn't cross any register mask instructions. In
+ /// Returns false if \p LI doesn't cross any register mask instructions. In
/// that case, the bit vector is not filled in.
bool checkRegMaskInterference(LiveInterval &LI,
BitVector &UsableRegs);
@@ -377,8 +379,8 @@ extern cl::opt<bool> UseSegmentSetForPhysRegs;
// track liveness per register unit to handle aliasing registers more
// efficiently.
- /// getRegUnit - Return the live range for Unit.
- /// It will be computed if it doesn't exist.
+ /// Return the live range for register unit \p Unit. It will be computed if
+ /// it doesn't exist.
LiveRange &getRegUnit(unsigned Unit) {
LiveRange *LR = RegUnitRanges[Unit];
if (!LR) {
@@ -390,8 +392,8 @@ extern cl::opt<bool> UseSegmentSetForPhysRegs;
return *LR;
}
- /// getCachedRegUnit - Return the live range for Unit if it has already
- /// been computed, or NULL if it hasn't been computed yet.
+ /// Return the live range for register unit \p Unit if it has already been
+ /// computed, or nullptr if it hasn't been computed yet.
LiveRange *getCachedRegUnit(unsigned Unit) {
return RegUnitRanges[Unit];
}
@@ -400,7 +402,7 @@ extern cl::opt<bool> UseSegmentSetForPhysRegs;
return RegUnitRanges[Unit];
}
- /// removeRegUnit - Remove computed live range for Unit. Subsequent uses
+ /// Remove computed live range for register unit \p Unit. Subsequent uses
/// should rely on on-demand recomputation.
void removeRegUnit(unsigned Unit) {
delete RegUnitRanges[Unit];
@@ -408,12 +410,12 @@ extern cl::opt<bool> UseSegmentSetForPhysRegs;
}
/// 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
+ /// \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.
+ /// 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);
/// Split separate components in LiveInterval \p LI into separate intervals.
@@ -432,10 +434,10 @@ extern cl::opt<bool> UseSegmentSetForPhysRegs;
/// Compute RegMaskSlots and RegMaskBits.
void computeRegMasks();
- /// Walk the values in @p LI and check for dead values:
+ /// Walk the values in \p LI and check for dead values:
/// - Dead PHIDef values are marked as unused.
/// - Dead operands are marked as such.
- /// - Completely dead machine instructions are added to the @p dead vector
+ /// - Completely dead machine instructions are added to the \p dead vector
/// if it is not nullptr.
/// Returns true if any PHI value numbers have been removed which may
/// have separated the interval into multiple connected components.
@@ -453,8 +455,8 @@ extern cl::opt<bool> UseSegmentSetForPhysRegs;
/// Helper function for repairIntervalsInRange(), walks backwards and
- /// creates/modifies live segments in @p LR to match the operands found.
- /// Only full operands or operands with subregisters matching @p LaneMask
+ /// creates/modifies live segments in \p LR to match the operands found.
+ /// Only full operands or operands with subregisters matching \p LaneMask
/// are considered.
void repairOldRegInRange(MachineBasicBlock::iterator Begin,
MachineBasicBlock::iterator End,
diff --git a/include/llvm/CodeGen/LiveIntervalUnion.h b/include/llvm/CodeGen/LiveIntervalUnion.h
index f0f1637dc92d..57e3deb038af 100644
--- a/include/llvm/CodeGen/LiveIntervalUnion.h
+++ b/include/llvm/CodeGen/LiveIntervalUnion.h
@@ -1,4 +1,4 @@
-//===-- LiveIntervalUnion.h - Live interval union data struct --*- C++ -*--===//
+//===- LiveIntervalUnion.h - Live interval union data struct ---*- C++ -*--===//
//
// The LLVM Compiler Infrastructure
//
@@ -18,7 +18,11 @@
#define LLVM_CODEGEN_LIVEINTERVALUNION_H
#include "llvm/ADT/IntervalMap.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/CodeGen/LiveInterval.h"
+#include "llvm/CodeGen/SlotIndexes.h"
+#include <cassert>
+#include <limits>
namespace llvm {
@@ -30,13 +34,6 @@ template <unsigned Element> class SparseBitVector;
typedef SparseBitVector<128> LiveVirtRegBitSet;
#endif
-/// Compare a live virtual register segment to a LiveIntervalUnion segment.
-inline bool
-overlap(const LiveInterval::Segment &VRSeg,
- const IntervalMap<SlotIndex, LiveInterval*>::const_iterator &LUSeg) {
- return VRSeg.start < LUSeg.stop() && LUSeg.start() < VRSeg.end;
-}
-
/// Union of live intervals that are strong candidates for coalescing into a
/// single register (either physical or virtual depending on the context). We
/// expect the constituent live intervals to be disjoint, although we may
@@ -53,29 +50,34 @@ public:
// to reach the current segment's containing virtual register.
typedef LiveSegments::iterator SegmentIter;
+ /// Const version of SegmentIter.
+ typedef LiveSegments::const_iterator ConstSegmentIter;
+
// LiveIntervalUnions share an external allocator.
typedef LiveSegments::Allocator Allocator;
- class Query;
-
private:
- unsigned Tag; // unique tag for current contents.
+ unsigned Tag = 0; // unique tag for current contents.
LiveSegments Segments; // union of virtual reg segments
public:
- explicit LiveIntervalUnion(Allocator &a) : Tag(0), Segments(a) {}
+ explicit LiveIntervalUnion(Allocator &a) : Segments(a) {}
// Iterate over all segments in the union of live virtual registers ordered
// by their starting position.
SegmentIter begin() { return Segments.begin(); }
SegmentIter end() { return Segments.end(); }
SegmentIter find(SlotIndex x) { return Segments.find(x); }
+ ConstSegmentIter begin() const { return Segments.begin(); }
+ ConstSegmentIter end() const { return Segments.end(); }
+ ConstSegmentIter find(SlotIndex x) const { return Segments.find(x); }
+
bool empty() const { return Segments.empty(); }
SlotIndex startIndex() const { return Segments.start(); }
// Provide public access to the underlying map to allow overlap iteration.
typedef LiveSegments Map;
- const Map &getMap() { return Segments; }
+ const Map &getMap() const { return Segments; }
/// getTag - Return an opaque tag representing the current state of the union.
unsigned getTag() const { return Tag; }
@@ -85,15 +87,9 @@ public:
// Add a live virtual register to this union and merge its segments.
void unify(LiveInterval &VirtReg, const LiveRange &Range);
- void unify(LiveInterval &VirtReg) {
- unify(VirtReg, VirtReg);
- }
// Remove a live virtual register's segments from this union.
void extract(LiveInterval &VirtReg, const LiveRange &Range);
- void extract(LiveInterval &VirtReg) {
- extract(VirtReg, VirtReg);
- }
// Remove all inserted virtual registers.
void clear() { Segments.clear(); ++Tag; }
@@ -109,52 +105,42 @@ public:
/// Query interferences between a single live virtual register and a live
/// interval union.
class Query {
- LiveIntervalUnion *LiveUnion;
- LiveInterval *VirtReg;
- LiveInterval::iterator VirtRegI; // current position in VirtReg
- SegmentIter LiveUnionI; // current position in LiveUnion
+ const LiveIntervalUnion *LiveUnion = nullptr;
+ const LiveRange *LR = nullptr;
+ LiveRange::const_iterator LRI; ///< current position in LR
+ ConstSegmentIter LiveUnionI; ///< current position in LiveUnion
SmallVector<LiveInterval*,4> InterferingVRegs;
- bool CheckedFirstInterference;
- bool SeenAllInterferences;
- bool SeenUnspillableVReg;
- unsigned Tag, UserTag;
-
- public:
- Query(): LiveUnion(), VirtReg(), Tag(0), UserTag(0) {}
-
- Query(LiveInterval *VReg, LiveIntervalUnion *LIU):
- LiveUnion(LIU), VirtReg(VReg), CheckedFirstInterference(false),
- SeenAllInterferences(false), SeenUnspillableVReg(false)
- {}
-
- void clear() {
- LiveUnion = nullptr;
- VirtReg = nullptr;
+ bool CheckedFirstInterference = false;
+ bool SeenAllInterferences = false;
+ unsigned Tag = 0;
+ unsigned UserTag = 0;
+
+ void reset(unsigned NewUserTag, const LiveRange &NewLR,
+ const LiveIntervalUnion &NewLiveUnion) {
+ LiveUnion = &NewLiveUnion;
+ LR = &NewLR;
InterferingVRegs.clear();
CheckedFirstInterference = false;
SeenAllInterferences = false;
- SeenUnspillableVReg = false;
- Tag = 0;
- UserTag = 0;
+ Tag = NewLiveUnion.getTag();
+ UserTag = NewUserTag;
}
- void init(unsigned UTag, LiveInterval *VReg, LiveIntervalUnion *LIU) {
- assert(VReg && LIU && "Invalid arguments");
- if (UserTag == UTag && VirtReg == VReg &&
- LiveUnion == LIU && !LIU->changedSince(Tag)) {
+ public:
+ Query() = default;
+ Query(const LiveRange &LR, const LiveIntervalUnion &LIU):
+ LiveUnion(&LIU), LR(&LR) {}
+ Query(const Query &) = delete;
+ Query &operator=(const Query &) = delete;
+
+ void init(unsigned NewUserTag, const LiveRange &NewLR,
+ const LiveIntervalUnion &NewLiveUnion) {
+ if (UserTag == NewUserTag && LR == &NewLR && LiveUnion == &NewLiveUnion &&
+ !NewLiveUnion.changedSince(Tag)) {
// Retain cached results, e.g. firstInterference.
return;
}
- clear();
- LiveUnion = LIU;
- VirtReg = VReg;
- Tag = LIU->getTag();
- UserTag = UTag;
- }
-
- LiveInterval &virtReg() const {
- assert(VirtReg && "uninitialized");
- return *VirtReg;
+ reset(NewUserTag, NewLR, NewLiveUnion);
}
// Does this live virtual register interfere with the union?
@@ -162,7 +148,8 @@ public:
// Count the virtual registers in this union that interfere with this
// query's live virtual register, up to maxInterferingRegs.
- unsigned collectInterferingVRegs(unsigned MaxInterferingRegs = UINT_MAX);
+ unsigned collectInterferingVRegs(
+ unsigned MaxInterferingRegs = std::numeric_limits<unsigned>::max());
// Was this virtual register visited during collectInterferingVRegs?
bool isSeenInterference(LiveInterval *VReg) const;
@@ -170,25 +157,19 @@ public:
// Did collectInterferingVRegs collect all interferences?
bool seenAllInterferences() const { return SeenAllInterferences; }
- // Did collectInterferingVRegs encounter an unspillable vreg?
- bool seenUnspillableVReg() const { return SeenUnspillableVReg; }
-
// Vector generated by collectInterferingVRegs.
const SmallVectorImpl<LiveInterval*> &interferingVRegs() const {
return InterferingVRegs;
}
-
- private:
- Query(const Query&) = delete;
- void operator=(const Query&) = delete;
};
// Array of LiveIntervalUnions.
class Array {
- unsigned Size;
- LiveIntervalUnion *LIUs;
+ unsigned Size = 0;
+ LiveIntervalUnion *LIUs = nullptr;
+
public:
- Array() : Size(0), LIUs(nullptr) {}
+ Array() = default;
~Array() { clear(); }
// Initialize the array to have Size entries.
@@ -213,4 +194,4 @@ public:
} // end namespace llvm
-#endif // !defined(LLVM_CODEGEN_LIVEINTERVALUNION_H)
+#endif // LLVM_CODEGEN_LIVEINTERVALUNION_H
diff --git a/include/llvm/CodeGen/LiveRegMatrix.h b/include/llvm/CodeGen/LiveRegMatrix.h
index e169058ca563..fa6827f6b1f9 100644
--- a/include/llvm/CodeGen/LiveRegMatrix.h
+++ b/include/llvm/CodeGen/LiveRegMatrix.h
@@ -1,4 +1,4 @@
-//===-- LiveRegMatrix.h - Track register interference ---------*- C++ -*---===//
+//===- LiveRegMatrix.h - Track register interference ----------*- C++ -*---===//
//
// The LLVM Compiler Infrastructure
//
@@ -27,11 +27,14 @@
#include "llvm/ADT/BitVector.h"
#include "llvm/CodeGen/LiveIntervalUnion.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
+#include <memory>
namespace llvm {
+class AnalysisUsage;
class LiveInterval;
-class LiveIntervalAnalysis;
+class LiveIntervals;
+class MachineFunction;
class TargetRegisterInfo;
class VirtRegMap;
@@ -41,7 +44,7 @@ class LiveRegMatrix : public MachineFunctionPass {
VirtRegMap *VRM;
// UserTag changes whenever virtual registers have been modified.
- unsigned UserTag;
+ unsigned UserTag = 0;
// The matrix is represented as a LiveIntervalUnion per register unit.
LiveIntervalUnion::Allocator LIUAlloc;
@@ -51,16 +54,18 @@ class LiveRegMatrix : public MachineFunctionPass {
std::unique_ptr<LiveIntervalUnion::Query[]> Queries;
// Cached register mask interference info.
- unsigned RegMaskTag;
- unsigned RegMaskVirtReg;
+ unsigned RegMaskTag = 0;
+ unsigned RegMaskVirtReg = 0;
BitVector RegMaskUsable;
// MachineFunctionPass boilerplate.
- void getAnalysisUsage(AnalysisUsage&) const override;
- bool runOnMachineFunction(MachineFunction&) override;
+ void getAnalysisUsage(AnalysisUsage &) const override;
+ bool runOnMachineFunction(MachineFunction &) override;
void releaseMemory() override;
+
public:
static char ID;
+
LiveRegMatrix();
//===--------------------------------------------------------------------===//
@@ -136,7 +141,7 @@ public:
/// Use MCRegUnitIterator to enumerate all regunits in the desired PhysReg.
/// This returns a reference to an internal Query data structure that is only
/// valid until the next query() call.
- LiveIntervalUnion::Query &query(LiveInterval &VirtReg, unsigned RegUnit);
+ LiveIntervalUnion::Query &query(const LiveRange &LR, unsigned RegUnit);
/// Directly access the live interval unions per regunit.
/// This returns an array indexed by the regunit number.
diff --git a/include/llvm/CodeGen/LiveRegUnits.h b/include/llvm/CodeGen/LiveRegUnits.h
new file mode 100644
index 000000000000..5de76c8b87bf
--- /dev/null
+++ b/include/llvm/CodeGen/LiveRegUnits.h
@@ -0,0 +1,128 @@
+//===- llvm/CodeGen/LiveRegUnits.h - Register Unit Set ----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+/// \file
+/// A set of register units. It is intended for register liveness tracking.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CODEGEN_LIVEREGUNITS_H
+#define LLVM_CODEGEN_LIVEREGUNITS_H
+
+#include "llvm/ADT/BitVector.h"
+#include "llvm/Target/TargetRegisterInfo.h"
+#include "llvm/MC/LaneBitmask.h"
+#include "llvm/MC/MCRegisterInfo.h"
+#include <cstdint>
+
+namespace llvm {
+
+class MachineInstr;
+class MachineBasicBlock;
+
+/// A set of register units used to track register liveness.
+class LiveRegUnits {
+ const TargetRegisterInfo *TRI = nullptr;
+ BitVector Units;
+
+public:
+ /// Constructs a new empty LiveRegUnits set.
+ LiveRegUnits() = default;
+
+ /// Constructs and initialize an empty LiveRegUnits set.
+ LiveRegUnits(const TargetRegisterInfo &TRI) {
+ init(TRI);
+ }
+
+ /// Initialize and clear the set.
+ void init(const TargetRegisterInfo &TRI) {
+ this->TRI = &TRI;
+ Units.reset();
+ Units.resize(TRI.getNumRegUnits());
+ }
+
+ /// Clears the set.
+ void clear() { Units.reset(); }
+
+ /// Returns true if the set is empty.
+ bool empty() const { return Units.empty(); }
+
+ /// Adds register units covered by physical register \p Reg.
+ void addReg(unsigned Reg) {
+ for (MCRegUnitIterator Unit(Reg, TRI); Unit.isValid(); ++Unit)
+ Units.set(*Unit);
+ }
+
+ /// \brief Adds register units covered by physical register \p Reg that are
+ /// part of the lanemask \p Mask.
+ void addRegMasked(unsigned Reg, LaneBitmask Mask) {
+ for (MCRegUnitMaskIterator Unit(Reg, TRI); Unit.isValid(); ++Unit) {
+ LaneBitmask UnitMask = (*Unit).second;
+ if (UnitMask.none() || (UnitMask & Mask).any())
+ Units.set((*Unit).first);
+ }
+ }
+
+ /// Removes all register units covered by physical register \p Reg.
+ void removeReg(unsigned Reg) {
+ for (MCRegUnitIterator Unit(Reg, TRI); Unit.isValid(); ++Unit)
+ Units.reset(*Unit);
+ }
+
+ /// Removes register units not preserved by the regmask \p RegMask.
+ /// The regmask has the same format as the one in the RegMask machine operand.
+ void removeRegsNotPreserved(const uint32_t *RegMask);
+
+ /// Adds register units not preserved by the regmask \p RegMask.
+ /// The regmask has the same format as the one in the RegMask machine operand.
+ void addRegsInMask(const uint32_t *RegMask);
+
+ /// Returns true if no part of physical register \p Reg is live.
+ bool available(unsigned Reg) const {
+ for (MCRegUnitIterator Unit(Reg, TRI); Unit.isValid(); ++Unit) {
+ if (Units.test(*Unit))
+ return false;
+ }
+ return true;
+ }
+
+ /// Updates liveness when stepping backwards over the instruction \p MI.
+ void stepBackward(const MachineInstr &MI);
+
+ /// Mark all register units live during instruction \p MI.
+ /// This can be used to accumulate live/unoccupied registers over a range of
+ /// instructions.
+ void accumulateBackward(const MachineInstr &MI);
+
+ /// Adds registers living out of block \p MBB.
+ /// Live out registers are the union of the live-in registers of the successor
+ /// blocks and pristine registers. Live out registers of the end block are the
+ /// callee saved registers.
+ void addLiveOuts(const MachineBasicBlock &MBB);
+
+ /// Adds registers living into block \p MBB.
+ void addLiveIns(const MachineBasicBlock &MBB);
+
+ /// Adds all register units marked in the bitvector \p RegUnits.
+ void addUnits(const BitVector &RegUnits) {
+ Units |= RegUnits;
+ }
+ /// Removes all register units marked in the bitvector \p RegUnits.
+ void removeUnits(const BitVector &RegUnits) {
+ Units.reset(RegUnits);
+ }
+ /// Return the internal bitvector representation of the set.
+ const BitVector &getBitVector() const {
+ return Units;
+ }
+};
+
+} // end namespace llvm
+
+#endif // LLVM_CODEGEN_LIVEREGUNITS_H
diff --git a/include/llvm/CodeGen/LowLevelType.h b/include/llvm/CodeGen/LowLevelType.h
index b8885c3a95fd..a3c5c9329f53 100644
--- a/include/llvm/CodeGen/LowLevelType.h
+++ b/include/llvm/CodeGen/LowLevelType.h
@@ -1,4 +1,4 @@
-//== llvm/CodeGen/GlobalISel/LowLevelType.h -------------------- -*- C++ -*-==//
+//== llvm/CodeGen/LowLevelType.h ------------------------------- -*- C++ -*-==//
//
// The LLVM Compiler Infrastructure
//
@@ -10,197 +10,23 @@
/// Implement a low-level type suitable for MachineInstr level instruction
/// selection.
///
-/// For a type attached to a MachineInstr, we only care about 2 details: total
-/// size and the number of vector lanes (if any). Accordingly, there are 4
-/// possible valid type-kinds:
-///
-/// * `sN` for scalars and aggregates
-/// * `<N x sM>` for vectors, which must have at least 2 elements.
-/// * `pN` for pointers
-///
-/// Other information required for correct selection is expected to be carried
-/// by the opcode, or non-type flags. For example the distinction between G_ADD
-/// and G_FADD for int/float or fast-math flags.
+/// This provides the CodeGen aspects of LowLevelType, such as Type conversion.
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CODEGEN_GLOBALISEL_LOWLEVELTYPE_H
-#define LLVM_CODEGEN_GLOBALISEL_LOWLEVELTYPE_H
+#ifndef LLVM_CODEGEN_LOWLEVELTYPE_H
+#define LLVM_CODEGEN_LOWLEVELTYPE_H
-#include <cassert>
-#include "llvm/ADT/DenseMapInfo.h"
-#include "llvm/CodeGen/ValueTypes.h"
+#include "llvm/Support/LowLevelTypeImpl.h"
namespace llvm {
class DataLayout;
-class LLVMContext;
class Type;
-class raw_ostream;
-
-class LLT {
-public:
- enum TypeKind : uint16_t {
- Invalid,
- Scalar,
- Pointer,
- Vector,
- };
-
- /// Get a low-level scalar or aggregate "bag of bits".
- static LLT scalar(unsigned SizeInBits) {
- assert(SizeInBits > 0 && "invalid scalar size");
- return LLT{Scalar, 1, SizeInBits};
- }
-
- /// Get a low-level pointer in the given address space (defaulting to 0).
- static LLT pointer(uint16_t AddressSpace, unsigned SizeInBits) {
- return LLT{Pointer, AddressSpace, SizeInBits};
- }
-
- /// Get a low-level vector of some number of elements and element width.
- /// \p NumElements must be at least 2.
- static LLT vector(uint16_t NumElements, unsigned ScalarSizeInBits) {
- assert(NumElements > 1 && "invalid number of vector elements");
- return LLT{Vector, NumElements, ScalarSizeInBits};
- }
-
- /// Get a low-level vector of some number of elements and element type.
- static LLT vector(uint16_t NumElements, LLT ScalarTy) {
- assert(NumElements > 1 && "invalid number of vector elements");
- assert(ScalarTy.isScalar() && "invalid vector element type");
- return LLT{Vector, NumElements, ScalarTy.getSizeInBits()};
- }
-
- explicit LLT(TypeKind Kind, uint16_t NumElements, unsigned SizeInBits)
- : SizeInBits(SizeInBits), ElementsOrAddrSpace(NumElements), Kind(Kind) {
- assert((Kind != Vector || ElementsOrAddrSpace > 1) &&
- "invalid number of vector elements");
- }
-
- explicit LLT() : SizeInBits(0), ElementsOrAddrSpace(0), Kind(Invalid) {}
-
- /// Construct a low-level type based on an LLVM type.
- explicit LLT(Type &Ty, const DataLayout &DL);
-
- explicit LLT(MVT VT);
-
- bool isValid() const { return Kind != Invalid; }
-
- bool isScalar() const { return Kind == Scalar; }
-
- bool isPointer() const { return Kind == Pointer; }
-
- bool isVector() const { return Kind == Vector; }
-
- /// Returns the number of elements in a vector LLT. Must only be called on
- /// vector types.
- uint16_t getNumElements() const {
- assert(isVector() && "cannot get number of elements on scalar/aggregate");
- return ElementsOrAddrSpace;
- }
-
- /// Returns the total size of the type. Must only be called on sized types.
- unsigned getSizeInBits() const {
- if (isPointer() || isScalar())
- return SizeInBits;
- return SizeInBits * ElementsOrAddrSpace;
- }
-
- unsigned getScalarSizeInBits() const {
- return SizeInBits;
- }
-
- unsigned getAddressSpace() const {
- assert(isPointer() && "cannot get address space of non-pointer type");
- return ElementsOrAddrSpace;
- }
-
- /// Returns the vector's element type. Only valid for vector types.
- LLT getElementType() const {
- assert(isVector() && "cannot get element type of scalar/aggregate");
- return scalar(SizeInBits);
- }
-
- /// Get a low-level type with half the size of the original, by halving the
- /// size of the scalar type involved. For example `s32` will become `s16`,
- /// `<2 x s32>` will become `<2 x s16>`.
- LLT halfScalarSize() const {
- assert(!isPointer() && getScalarSizeInBits() > 1 &&
- getScalarSizeInBits() % 2 == 0 && "cannot half size of this type");
- return LLT{Kind, ElementsOrAddrSpace, SizeInBits / 2};
- }
-
- /// Get a low-level type with twice the size of the original, by doubling the
- /// size of the scalar type involved. For example `s32` will become `s64`,
- /// `<2 x s32>` will become `<2 x s64>`.
- LLT doubleScalarSize() const {
- assert(!isPointer() && "cannot change size of this type");
- return LLT{Kind, ElementsOrAddrSpace, SizeInBits * 2};
- }
-
- /// Get a low-level type with half the size of the original, by halving the
- /// number of vector elements of the scalar type involved. The source must be
- /// a vector type with an even number of elements. For example `<4 x s32>`
- /// will become `<2 x s32>`, `<2 x s32>` will become `s32`.
- LLT halfElements() const {
- assert(isVector() && ElementsOrAddrSpace % 2 == 0 &&
- "cannot half odd vector");
- if (ElementsOrAddrSpace == 2)
- return scalar(SizeInBits);
-
- return LLT{Vector, static_cast<uint16_t>(ElementsOrAddrSpace / 2),
- SizeInBits};
- }
-
- /// Get a low-level type with twice the size of the original, by doubling the
- /// number of vector elements of the scalar type involved. The source must be
- /// a vector type. For example `<2 x s32>` will become `<4 x s32>`. Doubling
- /// the number of elements in sN produces <2 x sN>.
- LLT doubleElements() const {
- assert(!isPointer() && "cannot double elements in pointer");
- return LLT{Vector, static_cast<uint16_t>(ElementsOrAddrSpace * 2),
- SizeInBits};
- }
-
- void print(raw_ostream &OS) const;
-
- bool operator==(const LLT &RHS) const {
- return Kind == RHS.Kind && SizeInBits == RHS.SizeInBits &&
- ElementsOrAddrSpace == RHS.ElementsOrAddrSpace;
- }
-
- bool operator!=(const LLT &RHS) const { return !(*this == RHS); }
-
- friend struct DenseMapInfo<LLT>;
-private:
- unsigned SizeInBits;
- uint16_t ElementsOrAddrSpace;
- TypeKind Kind;
-};
-
-inline raw_ostream& operator<<(raw_ostream &OS, const LLT &Ty) {
- Ty.print(OS);
- return OS;
-}
-template<> struct DenseMapInfo<LLT> {
- static inline LLT getEmptyKey() {
- return LLT{LLT::Invalid, 0, -1u};
- }
- static inline LLT getTombstoneKey() {
- return LLT{LLT::Invalid, 0, -2u};
- }
- static inline unsigned getHashValue(const LLT &Ty) {
- uint64_t Val = ((uint64_t)Ty.SizeInBits << 32) |
- ((uint64_t)Ty.ElementsOrAddrSpace << 16) | (uint64_t)Ty.Kind;
- return DenseMapInfo<uint64_t>::getHashValue(Val);
- }
- static bool isEqual(const LLT &LHS, const LLT &RHS) {
- return LHS == RHS;
- }
-};
+/// Construct a low-level type based on an LLVM type.
+LLT getLLTForType(Type &Ty, const DataLayout &DL);
}
-#endif
+#endif // LLVM_CODEGEN_LOWLEVELTYPE_H
diff --git a/include/llvm/CodeGen/MIRYamlMapping.h b/include/llvm/CodeGen/MIRYamlMapping.h
index 778f72c06e65..38cf8aa165a4 100644
--- a/include/llvm/CodeGen/MIRYamlMapping.h
+++ b/include/llvm/CodeGen/MIRYamlMapping.h
@@ -55,7 +55,7 @@ template <> struct ScalarTraits<StringValue> {
struct FlowStringValue : StringValue {
FlowStringValue() {}
- FlowStringValue(std::string Value) : StringValue(Value) {}
+ FlowStringValue(std::string Value) : StringValue(std::move(Value)) {}
};
template <> struct ScalarTraits<FlowStringValue> {
@@ -381,6 +381,7 @@ struct MachineFunction {
StringRef Name;
unsigned Alignment = 0;
bool ExposesReturnsTwice = false;
+ bool NoVRegs;
// GISel MachineFunctionProperties.
bool Legalized = false;
bool RegBankSelected = false;
@@ -405,6 +406,7 @@ template <> struct MappingTraits<MachineFunction> {
YamlIO.mapRequired("name", MF.Name);
YamlIO.mapOptional("alignment", MF.Alignment);
YamlIO.mapOptional("exposesReturnsTwice", MF.ExposesReturnsTwice);
+ YamlIO.mapOptional("noVRegs", MF.NoVRegs);
YamlIO.mapOptional("legalized", MF.Legalized);
YamlIO.mapOptional("regBankSelected", MF.RegBankSelected);
YamlIO.mapOptional("selected", MF.Selected);
diff --git a/include/llvm/CodeGen/MachineBasicBlock.h b/include/llvm/CodeGen/MachineBasicBlock.h
index f3f5e324d76a..18d40564856d 100644
--- a/include/llvm/CodeGen/MachineBasicBlock.h
+++ b/include/llvm/CodeGen/MachineBasicBlock.h
@@ -128,7 +128,7 @@ public:
/// to an LLVM basic block.
const BasicBlock *getBasicBlock() const { return BB; }
- /// Return the name of the corresponding LLVM basic block, or "(null)".
+ /// Return the name of the corresponding LLVM basic block, or an empty string.
StringRef getName() const;
/// Return a formatted string to identify this block and its parent function.
@@ -455,10 +455,19 @@ public:
/// other block.
bool isLayoutSuccessor(const MachineBasicBlock *MBB) const;
- /// Return true if the block can implicitly transfer control to the block
- /// after it by falling off the end of it. This should return false if it can
- /// reach the block after it, but it uses an explicit branch to do so (e.g., a
- /// table jump). True is a conservative answer.
+
+ /// Return the fallthrough block if the block can implicitly
+ /// transfer control to the block after it by falling off the end of
+ /// it. This should return null if it can reach the block after
+ /// it, but it uses an explicit branch to do so (e.g., a table
+ /// jump). Non-null return is a conservative answer.
+ MachineBasicBlock *getFallThrough();
+
+ /// Return true if the block can implicitly transfer control to the
+ /// block after it by falling off the end of it. This should return
+ /// false if it can reach the block after it, but it uses an
+ /// explicit branch to do so (e.g., a table jump). True is a
+ /// conservative answer.
bool canFallThrough();
/// Returns a pointer to the first instruction in this block that is not a
@@ -664,6 +673,10 @@ public:
return findDebugLoc(MBBI.getInstrIterator());
}
+ /// Find and return the merged DebugLoc of the branch instructions of the
+ /// block. Return UnknownLoc if there is none.
+ DebugLoc findBranchDebugLoc();
+
/// Possible outcome of a register liveness query to computeRegisterLiveness()
enum LivenessQueryResult {
LQR_Live, ///< Register is known to be (at least partially) live.
diff --git a/include/llvm/CodeGen/MachineBlockFrequencyInfo.h b/include/llvm/CodeGen/MachineBlockFrequencyInfo.h
index bfa5bf6c2845..cd1c204981ed 100644
--- a/include/llvm/CodeGen/MachineBlockFrequencyInfo.h
+++ b/include/llvm/CodeGen/MachineBlockFrequencyInfo.h
@@ -23,6 +23,7 @@ namespace llvm {
class MachineBasicBlock;
class MachineBranchProbabilityInfo;
+class MachineLoopInfo;
template <class BlockT> class BlockFrequencyInfoImpl;
/// MachineBlockFrequencyInfo pass uses BlockFrequencyInfoImpl implementation
@@ -42,6 +43,11 @@ public:
bool runOnMachineFunction(MachineFunction &F) override;
+ /// calculate - compute block frequency info for the given function.
+ void calculate(const MachineFunction &F,
+ const MachineBranchProbabilityInfo &MBPI,
+ const MachineLoopInfo &MLI);
+
void releaseMemory() override;
/// getblockFreq - Return block frequency. Return 0 if we don't have the
@@ -56,7 +62,7 @@ public:
const MachineFunction *getFunction() const;
const MachineBranchProbabilityInfo *getMBPI() const;
- void view() const;
+ void view(const Twine &Name, bool isSimple = true) const;
// Print the block frequency Freq to OS using the current functions entry
// frequency to convert freq into a relative decimal form.
diff --git a/include/llvm/CodeGen/MachineDominators.h b/include/llvm/CodeGen/MachineDominators.h
index 21ecef587aa5..30b6cfdd1c36 100644
--- a/include/llvm/CodeGen/MachineDominators.h
+++ b/include/llvm/CodeGen/MachineDominators.h
@@ -21,6 +21,7 @@
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/Support/GenericDomTree.h"
#include "llvm/Support/GenericDomTreeConstruction.h"
+#include <memory>
namespace llvm {
@@ -60,7 +61,7 @@ class MachineDominatorTree : public MachineFunctionPass {
mutable SmallSet<MachineBasicBlock *, 32> NewBBs;
/// The DominatorTreeBase that is used to compute a normal dominator tree
- DominatorTreeBase<MachineBasicBlock>* DT;
+ std::unique_ptr<DominatorTreeBase<MachineBasicBlock>> DT;
/// \brief Apply all the recorded critical edges to the DT.
/// This updates the underlying DT information in a way that uses
@@ -74,9 +75,9 @@ public:
MachineDominatorTree();
- ~MachineDominatorTree() override;
-
DominatorTreeBase<MachineBasicBlock> &getBase() {
+ if (!DT)
+ DT.reset(new DominatorTreeBase<MachineBasicBlock>(false));
applySplitCriticalEdges();
return *DT;
}
@@ -244,21 +245,6 @@ public:
CriticalEdgesToSplit.push_back({FromBB, ToBB, NewBB});
}
- /// \brief Returns *false* if the other dominator tree matches this dominator
- /// tree.
- inline bool compare(const MachineDominatorTree &Other) const {
- const MachineDomTreeNode *R = getRootNode();
- const MachineDomTreeNode *OtherR = Other.getRootNode();
-
- if (!R || !OtherR || R->getBlock() != OtherR->getBlock())
- return true;
-
- if (DT->compare(*Other.DT))
- return true;
-
- return false;
- }
-
/// \brief Verify the correctness of the domtree by re-computing it.
///
/// This should only be used for debugging as it aborts the program if the
diff --git a/include/llvm/CodeGen/MachineFrameInfo.h b/include/llvm/CodeGen/MachineFrameInfo.h
index 4600c2c0f10c..5c9728b0a51e 100644
--- a/include/llvm/CodeGen/MachineFrameInfo.h
+++ b/include/llvm/CodeGen/MachineFrameInfo.h
@@ -559,8 +559,7 @@ public:
return Objects[ObjectIdx+NumFixedObjects].isAliased;
}
- /// isImmutableObjectIndex - Returns true if the specified index corresponds
- /// to an immutable object.
+ /// 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)
@@ -570,6 +569,13 @@ public:
return Objects[ObjectIdx+NumFixedObjects].isImmutable;
}
+ /// Marks the immutability of an object.
+ void setIsImmutableObjectIndex(int ObjectIdx, bool Immutable) {
+ assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() &&
+ "Invalid Object Idx!");
+ Objects[ObjectIdx+NumFixedObjects].isImmutable = Immutable;
+ }
+
/// Returns true if the specified index corresponds to a spill slot.
bool isSpillSlotObjectIndex(int ObjectIdx) const {
assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() &&
diff --git a/include/llvm/CodeGen/MachineFunction.h b/include/llvm/CodeGen/MachineFunction.h
index 0c21b3254631..5859a4e61fdd 100644
--- a/include/llvm/CodeGen/MachineFunction.h
+++ b/include/llvm/CodeGen/MachineFunction.h
@@ -475,9 +475,8 @@ public:
/// getBlockNumbered - MachineBasicBlocks are automatically numbered when they
/// are inserted into the machine function. The block number for a machine
- /// basic block can be found by using the MBB::getBlockNumber method, this
- /// method provides the inverse mapping.
- ///
+ /// basic block can be found by using the MBB::getNumber method, this method
+ /// provides the inverse mapping.
MachineBasicBlock *getBlockNumbered(unsigned N) const {
assert(N < MBBNumbering.size() && "Illegal block number");
assert(MBBNumbering[N] && "Block was removed from the machine function!");
diff --git a/include/llvm/CodeGen/MachineFunctionInitializer.h b/include/llvm/CodeGen/MachineFunctionInitializer.h
index ff4c29cc014d..c644c9783e2f 100644
--- a/include/llvm/CodeGen/MachineFunctionInitializer.h
+++ b/include/llvm/CodeGen/MachineFunctionInitializer.h
@@ -1,4 +1,4 @@
-//===- MachineFunctionInitalizer.h - machine function initializer ---------===//
+//===- MachineFunctionInitializer.h - machine function initializer ---------===//
//
// The LLVM Compiler Infrastructure
//
diff --git a/include/llvm/CodeGen/MachineInstr.h b/include/llvm/CodeGen/MachineInstr.h
index bac93e5d3a4c..e7e728c1be28 100644
--- a/include/llvm/CodeGen/MachineInstr.h
+++ b/include/llvm/CodeGen/MachineInstr.h
@@ -1108,6 +1108,18 @@ public:
/// the instruction's location and its intended destination.
bool isSafeToMove(AliasAnalysis *AA, bool &SawStore) const;
+ /// Returns true if this instruction's memory access aliases the memory
+ /// access of Other.
+ //
+ /// Assumes any physical registers used to compute addresses
+ /// have the same value for both instructions. Returns false if neither
+ /// instruction writes to memory.
+ ///
+ /// @param AA Optional alias analysis, used to compare memory operands.
+ /// @param Other MachineInstr to check aliasing against.
+ /// @param UseTBAA Whether to pass TBAA information to alias analysis.
+ bool mayAlias(AliasAnalysis *AA, MachineInstr &Other, bool UseTBAA);
+
/// 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
@@ -1146,14 +1158,21 @@ public:
/// instruction to this instruction.
void copyImplicitOps(MachineFunction &MF, const MachineInstr &MI);
- //
- // Debugging support
- //
- void print(raw_ostream &OS, bool SkipOpers = false,
+ /// Debugging support
+ /// @{
+ /// Print this MI to \p OS.
+ /// Only print the defs and the opcode if \p SkipOpers is true.
+ /// Otherwise, also print operands if \p SkipDebugLoc is true.
+ /// Otherwise, also print the debug loc, with a terminating newline.
+ /// \p TII is used to print the opcode name. If it's not present, but the
+ /// MI is in a function, the opcode will be printed using the function's TII.
+ void print(raw_ostream &OS, bool SkipOpers = false, bool SkipDebugLoc = false,
const TargetInstrInfo *TII = nullptr) const;
void print(raw_ostream &OS, ModuleSlotTracker &MST, bool SkipOpers = false,
+ bool SkipDebugLoc = false,
const TargetInstrInfo *TII = nullptr) const;
- void dump(const TargetInstrInfo *TII = nullptr) const;
+ void dump() const;
+ /// @}
//===--------------------------------------------------------------------===//
// Accessors used to build up machine instructions.
diff --git a/include/llvm/CodeGen/MachineInstrBuilder.h b/include/llvm/CodeGen/MachineInstrBuilder.h
index 3c8a3626f364..ef4226d30fe3 100644
--- a/include/llvm/CodeGen/MachineInstrBuilder.h
+++ b/include/llvm/CodeGen/MachineInstrBuilder.h
@@ -1,4 +1,4 @@
-//===-- CodeGen/MachineInstBuilder.h - Simplify creation of MIs -*- C++ -*-===//
+//===- CodeGen/MachineInstrBuilder.h - Simplify creation of MIs --*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -19,9 +19,18 @@
#ifndef LLVM_CODEGEN_MACHINEINSTRBUILDER_H
#define LLVM_CODEGEN_MACHINEINSTRBUILDER_H
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineInstrBundle.h"
+#include "llvm/CodeGen/MachineOperand.h"
+#include "llvm/IR/InstrTypes.h"
+#include "llvm/IR/Intrinsics.h"
#include "llvm/Support/ErrorHandling.h"
+#include <cassert>
+#include <cstdint>
+#include <utility>
namespace llvm {
@@ -29,6 +38,7 @@ class MCInstrDesc;
class MDNode;
namespace RegState {
+
enum {
Define = 0x2,
Implicit = 0x4,
@@ -42,13 +52,15 @@ namespace RegState {
ImplicitDefine = Implicit | Define,
ImplicitKill = Implicit | Kill
};
-}
+
+} // end namespace RegState
class MachineInstrBuilder {
- MachineFunction *MF;
- MachineInstr *MI;
+ MachineFunction *MF = nullptr;
+ MachineInstr *MI = nullptr;
+
public:
- MachineInstrBuilder() : MF(nullptr), MI(nullptr) {}
+ MachineInstrBuilder() = default;
/// Create a MachineInstrBuilder for manipulating an existing instruction.
/// F must be the machine function that was used to allocate I.
@@ -187,11 +199,18 @@ public:
return *this;
}
- const MachineInstrBuilder &addOperand(const MachineOperand &MO) const {
+ const MachineInstrBuilder &add(const MachineOperand &MO) const {
MI->addOperand(*MF, MO);
return *this;
}
+ const MachineInstrBuilder &add(ArrayRef<MachineOperand> MOs) const {
+ for (const MachineOperand &MO : MOs) {
+ MI->addOperand(*MF, MO);
+ }
+ return *this;
+ }
+
const MachineInstrBuilder &addMetadata(const MDNode *MD) const {
MI->addOperand(*MF, MachineOperand::CreateMetadata(MD));
assert((MI->isDebugValue() ? static_cast<bool>(MI->getDebugVariable())
@@ -511,6 +530,6 @@ public:
}
};
-} // End llvm namespace
+} // end namespace llvm
-#endif
+#endif // LLVM_CODEGEN_MACHINEINSTRBUILDER_H
diff --git a/include/llvm/CodeGen/MachineLoopInfo.h b/include/llvm/CodeGen/MachineLoopInfo.h
index dc72ae1810ee..5c814f22f99b 100644
--- a/include/llvm/CodeGen/MachineLoopInfo.h
+++ b/include/llvm/CodeGen/MachineLoopInfo.h
@@ -60,6 +60,13 @@ public:
/// multiple exiting blocks are present.
MachineBasicBlock *findLoopControlBlock();
+ /// Return the debug location of the start of this loop.
+ /// This looks for a BB terminating instruction with a known debug
+ /// location by looking at the preheader and header blocks. If it
+ /// cannot find a terminating instruction with location information,
+ /// it returns an unknown location.
+ DebugLoc getStartLoc() const;
+
void dump() const;
private:
diff --git a/include/llvm/CodeGen/MachineModuleInfoImpls.h b/include/llvm/CodeGen/MachineModuleInfoImpls.h
index f9fa6999073f..f28a79c5b5cc 100644
--- a/include/llvm/CodeGen/MachineModuleInfoImpls.h
+++ b/include/llvm/CodeGen/MachineModuleInfoImpls.h
@@ -15,7 +15,9 @@
#ifndef LLVM_CODEGEN_MACHINEMODULEINFOIMPLS_H
#define LLVM_CODEGEN_MACHINEMODULEINFOIMPLS_H
+#include "llvm/CodeGen/ValueTypes.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
+#include "llvm/Support/Wasm.h"
namespace llvm {
class MCSymbol;
@@ -75,6 +77,33 @@ public:
SymbolListTy GetGVStubList() { return getSortedStubs(GVStubs); }
};
+/// MachineModuleInfoWasm - This is a MachineModuleInfoImpl implementation
+/// for Wasm targets.
+class MachineModuleInfoWasm : public MachineModuleInfoImpl {
+ /// WebAssembly global variables defined by CodeGen.
+ std::vector<wasm::Global> Globals;
+
+ /// The WebAssembly global variable which is the stack pointer.
+ unsigned StackPointerGlobal;
+
+ virtual void anchor(); // Out of line virtual method.
+public:
+ MachineModuleInfoWasm(const MachineModuleInfo &)
+ : StackPointerGlobal(-1U) {}
+
+ void addGlobal(const wasm::Global &G) { Globals.push_back(G); }
+ const std::vector<wasm::Global> &getGlobals() const { return Globals; }
+
+ bool hasStackPointerGlobal() const {
+ return StackPointerGlobal != -1U;
+ }
+ unsigned getStackPointerGlobal() const {
+ assert(hasStackPointerGlobal() && "Stack ptr global hasn't been set");
+ return StackPointerGlobal;
+ }
+ void setStackPointerGlobal(unsigned Global) { StackPointerGlobal = Global; }
+};
+
} // end namespace llvm
#endif
diff --git a/include/llvm/CodeGen/MachineOperand.h b/include/llvm/CodeGen/MachineOperand.h
index 5df99a6c807e..81b43126adeb 100644
--- a/include/llvm/CodeGen/MachineOperand.h
+++ b/include/llvm/CodeGen/MachineOperand.h
@@ -65,6 +65,7 @@ public:
MO_CFIIndex, ///< MCCFIInstruction index.
MO_IntrinsicID, ///< Intrinsic ID for ISel
MO_Predicate, ///< Generic predicate for ISel
+ MO_Placeholder, ///< Placeholder for GlobalISel ComplexPattern result.
};
private:
@@ -229,7 +230,7 @@ public:
void print(raw_ostream &os, ModuleSlotTracker &MST,
const TargetRegisterInfo *TRI = nullptr,
const TargetIntrinsicInfo *IntrinsicInfo = nullptr) const;
- LLVM_DUMP_METHOD void dump() const;
+ void dump() const;
//===--------------------------------------------------------------------===//
// Accessors that tell you what kind of MachineOperand you're looking at.
@@ -355,7 +356,7 @@ public:
void setReg(unsigned Reg);
void setSubReg(unsigned subReg) {
- assert(isReg() && "Wrong MachineOperand accessor");
+ assert(isReg() && "Wrong MachineOperand mutator");
SubReg_TargetFlags = subReg;
assert(SubReg_TargetFlags == subReg && "SubReg out of range");
}
@@ -378,38 +379,38 @@ public:
void setIsDef(bool Val = true);
void setImplicit(bool Val = true) {
- assert(isReg() && "Wrong MachineOperand accessor");
+ assert(isReg() && "Wrong MachineOperand mutator");
IsImp = Val;
}
void setIsKill(bool Val = true) {
- assert(isReg() && !IsDef && "Wrong MachineOperand accessor");
+ assert(isReg() && !IsDef && "Wrong MachineOperand mutator");
assert((!Val || !isDebug()) && "Marking a debug operation as kill");
IsKill = Val;
}
void setIsDead(bool Val = true) {
- assert(isReg() && IsDef && "Wrong MachineOperand accessor");
+ assert(isReg() && IsDef && "Wrong MachineOperand mutator");
IsDead = Val;
}
void setIsUndef(bool Val = true) {
- assert(isReg() && "Wrong MachineOperand accessor");
+ assert(isReg() && "Wrong MachineOperand mutator");
IsUndef = Val;
}
void setIsInternalRead(bool Val = true) {
- assert(isReg() && "Wrong MachineOperand accessor");
+ assert(isReg() && "Wrong MachineOperand mutator");
IsInternalRead = Val;
}
void setIsEarlyClobber(bool Val = true) {
- assert(isReg() && IsDef && "Wrong MachineOperand accessor");
+ assert(isReg() && IsDef && "Wrong MachineOperand mutator");
IsEarlyClobber = Val;
}
void setIsDebug(bool Val = true) {
- assert(isReg() && !IsDef && "Wrong MachineOperand accessor");
+ assert(isReg() && !IsDef && "Wrong MachineOperand mutator");
IsDebug = Val;
}
@@ -538,19 +539,19 @@ public:
void setOffset(int64_t Offset) {
assert((isGlobal() || isSymbol() || isMCSymbol() || isCPI() ||
isTargetIndex() || isBlockAddress()) &&
- "Wrong MachineOperand accessor");
+ "Wrong MachineOperand mutator");
SmallContents.OffsetLo = unsigned(Offset);
Contents.OffsetedInfo.OffsetHi = int(Offset >> 32);
}
void setIndex(int Idx) {
assert((isFI() || isCPI() || isTargetIndex() || isJTI()) &&
- "Wrong MachineOperand accessor");
+ "Wrong MachineOperand mutator");
Contents.OffsetedInfo.Val.Index = Idx;
}
void setMBB(MachineBasicBlock *MBB) {
- assert(isMBB() && "Wrong MachineOperand accessor");
+ assert(isMBB() && "Wrong MachineOperand mutator");
Contents.MBB = MBB;
}
@@ -767,6 +768,11 @@ public:
return Op;
}
+ static MachineOperand CreatePlaceholder() {
+ MachineOperand Op(MachineOperand::MO_Placeholder);
+ return Op;
+ }
+
friend class MachineInstr;
friend class MachineRegisterInfo;
private:
diff --git a/include/llvm/CodeGen/MachineOptimizationRemarkEmitter.h b/include/llvm/CodeGen/MachineOptimizationRemarkEmitter.h
new file mode 100644
index 000000000000..da8fdcdf5a33
--- /dev/null
+++ b/include/llvm/CodeGen/MachineOptimizationRemarkEmitter.h
@@ -0,0 +1,203 @@
+///===- MachineOptimizationRemarkEmitter.h - Opt Diagnostics -*- C++ -*----===//
+///
+/// The LLVM Compiler Infrastructure
+///
+/// This file is distributed under the University of Illinois Open Source
+/// License. See LICENSE.TXT for details.
+///
+///===---------------------------------------------------------------------===//
+/// \file
+/// Optimization diagnostic interfaces for machine passes. It's packaged as an
+/// analysis pass so that by using this service passes become dependent on MBFI
+/// as well. MBFI is used to compute the "hotness" of the diagnostic message.
+///
+///===---------------------------------------------------------------------===//
+
+#ifndef LLVM_CODEGEN_MACHINEOPTIMIZATIONREMARKEMITTER_H
+#define LLVM_CODEGEN_MACHINEOPTIMIZATIONREMARKEMITTER_H
+
+#include "llvm/Analysis/OptimizationDiagnosticInfo.h"
+#include "llvm/CodeGen/MachineFunctionPass.h"
+
+namespace llvm {
+class MachineBasicBlock;
+class MachineBlockFrequencyInfo;
+class MachineInstr;
+
+/// \brief Common features for diagnostics dealing with optimization remarks
+/// that are used by machine passes.
+class DiagnosticInfoMIROptimization : public DiagnosticInfoOptimizationBase {
+public:
+ DiagnosticInfoMIROptimization(enum DiagnosticKind Kind, const char *PassName,
+ StringRef RemarkName,
+ const DiagnosticLocation &Loc,
+ const MachineBasicBlock *MBB)
+ : DiagnosticInfoOptimizationBase(Kind, DS_Remark, PassName, RemarkName,
+ *MBB->getParent()->getFunction(), Loc),
+ MBB(MBB) {}
+
+ /// MI-specific kinds of diagnostic Arguments.
+ struct MachineArgument : public DiagnosticInfoOptimizationBase::Argument {
+ /// Print an entire MachineInstr.
+ MachineArgument(StringRef Key, const MachineInstr &MI);
+ };
+
+ static bool classof(const DiagnosticInfo *DI) {
+ return DI->getKind() >= DK_FirstMachineRemark &&
+ DI->getKind() <= DK_LastMachineRemark;
+ }
+
+ const MachineBasicBlock *getBlock() const { return MBB; }
+
+private:
+ const MachineBasicBlock *MBB;
+};
+
+/// Diagnostic information for applied optimization remarks.
+class MachineOptimizationRemark : public DiagnosticInfoMIROptimization {
+public:
+ /// \p PassName is the name of the pass emitting this diagnostic. If this name
+ /// matches the regular expression given in -Rpass=, then the diagnostic will
+ /// be emitted. \p RemarkName is a textual identifier for the remark. \p
+ /// Loc is the debug location and \p MBB is the block that the optimization
+ /// operates in.
+ MachineOptimizationRemark(const char *PassName, StringRef RemarkName,
+ const DiagnosticLocation &Loc,
+ const MachineBasicBlock *MBB)
+ : DiagnosticInfoMIROptimization(DK_MachineOptimizationRemark, PassName,
+ RemarkName, Loc, MBB) {}
+
+ static bool classof(const DiagnosticInfo *DI) {
+ return DI->getKind() == DK_MachineOptimizationRemark;
+ }
+
+ /// \see DiagnosticInfoOptimizationBase::isEnabled.
+ bool isEnabled() const override {
+ return OptimizationRemark::isEnabled(getPassName());
+ }
+};
+
+/// Diagnostic information for missed-optimization remarks.
+class MachineOptimizationRemarkMissed : public DiagnosticInfoMIROptimization {
+public:
+ /// \p PassName is the name of the pass emitting this diagnostic. If this name
+ /// matches the regular expression given in -Rpass-missed=, then the
+ /// diagnostic will be emitted. \p RemarkName is a textual identifier for the
+ /// remark. \p Loc is the debug location and \p MBB is the block that the
+ /// optimization operates in.
+ MachineOptimizationRemarkMissed(const char *PassName, StringRef RemarkName,
+ const DiagnosticLocation &Loc,
+ const MachineBasicBlock *MBB)
+ : DiagnosticInfoMIROptimization(DK_MachineOptimizationRemarkMissed,
+ PassName, RemarkName, Loc, MBB) {}
+
+ static bool classof(const DiagnosticInfo *DI) {
+ return DI->getKind() == DK_MachineOptimizationRemarkMissed;
+ }
+
+ /// \see DiagnosticInfoOptimizationBase::isEnabled.
+ bool isEnabled() const override {
+ return OptimizationRemarkMissed::isEnabled(getPassName());
+ }
+};
+
+/// Diagnostic information for optimization analysis remarks.
+class MachineOptimizationRemarkAnalysis : public DiagnosticInfoMIROptimization {
+public:
+ /// \p PassName is the name of the pass emitting this diagnostic. If this name
+ /// matches the regular expression given in -Rpass-analysis=, then the
+ /// diagnostic will be emitted. \p RemarkName is a textual identifier for the
+ /// remark. \p Loc is the debug location and \p MBB is the block that the
+ /// optimization operates in.
+ MachineOptimizationRemarkAnalysis(const char *PassName, StringRef RemarkName,
+ const DiagnosticLocation &Loc,
+ const MachineBasicBlock *MBB)
+ : DiagnosticInfoMIROptimization(DK_MachineOptimizationRemarkAnalysis,
+ PassName, RemarkName, Loc, MBB) {}
+
+ static bool classof(const DiagnosticInfo *DI) {
+ return DI->getKind() == DK_MachineOptimizationRemarkAnalysis;
+ }
+
+ /// \see DiagnosticInfoOptimizationBase::isEnabled.
+ bool isEnabled() const override {
+ return OptimizationRemarkAnalysis::isEnabled(getPassName());
+ }
+};
+
+/// Extend llvm::ore:: with MI-specific helper names.
+namespace ore {
+using MNV = DiagnosticInfoMIROptimization::MachineArgument;
+}
+
+/// The optimization diagnostic interface.
+///
+/// It allows reporting when optimizations are performed and when they are not
+/// along with the reasons for it. Hotness information of the corresponding
+/// code region can be included in the remark if DiagnosticHotnessRequested is
+/// enabled in the LLVM context.
+class MachineOptimizationRemarkEmitter {
+public:
+ MachineOptimizationRemarkEmitter(MachineFunction &MF,
+ MachineBlockFrequencyInfo *MBFI)
+ : MF(MF), MBFI(MBFI) {}
+
+ /// Emit an optimization remark.
+ void emit(DiagnosticInfoOptimizationBase &OptDiag);
+
+ /// \brief Whether we allow for extra compile-time budget to perform more
+ /// analysis to be more informative.
+ ///
+ /// This is useful to enable additional missed optimizations to be reported
+ /// that are normally too noisy. In this mode, we can use the extra analysis
+ /// (1) to filter trivial false positives or (2) to provide more context so
+ /// that non-trivial false positives can be quickly detected by the user.
+ bool allowExtraAnalysis() const {
+ // For now, only allow this with -fsave-optimization-record since the -Rpass
+ // options are handled in the front-end.
+ return MF.getFunction()->getContext().getDiagnosticsOutputFile();
+ }
+
+private:
+ MachineFunction &MF;
+
+ /// MBFI is only set if hotness is requested.
+ MachineBlockFrequencyInfo *MBFI;
+
+ /// Compute hotness from IR value (currently assumed to be a block) if PGO is
+ /// available.
+ Optional<uint64_t> computeHotness(const MachineBasicBlock &MBB);
+
+ /// Similar but use value from \p OptDiag and update hotness there.
+ void computeHotness(DiagnosticInfoMIROptimization &Remark);
+
+ /// \brief Only allow verbose messages if we know we're filtering by hotness
+ /// (BFI is only set in this case).
+ bool shouldEmitVerbose() { return MBFI != nullptr; }
+};
+
+/// The analysis pass
+///
+/// Note that this pass shouldn't generally be marked as preserved by other
+/// passes. It's holding onto BFI, so if the pass does not preserve BFI, BFI
+/// could be freed.
+class MachineOptimizationRemarkEmitterPass : public MachineFunctionPass {
+ std::unique_ptr<MachineOptimizationRemarkEmitter> ORE;
+
+public:
+ MachineOptimizationRemarkEmitterPass();
+
+ bool runOnMachineFunction(MachineFunction &MF) override;
+
+ void getAnalysisUsage(AnalysisUsage &AU) const override;
+
+ MachineOptimizationRemarkEmitter &getORE() {
+ assert(ORE && "pass not run yet");
+ return *ORE;
+ }
+
+ static char ID;
+};
+}
+
+#endif
diff --git a/include/llvm/CodeGen/MachineRegisterInfo.h b/include/llvm/CodeGen/MachineRegisterInfo.h
index c599caf7535d..6e5c6473ff4a 100644
--- a/include/llvm/CodeGen/MachineRegisterInfo.h
+++ b/include/llvm/CodeGen/MachineRegisterInfo.h
@@ -1,4 +1,4 @@
-//===-- llvm/CodeGen/MachineRegisterInfo.h ----------------------*- C++ -*-===//
+//===- llvm/CodeGen/MachineRegisterInfo.h -----------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -15,19 +15,29 @@
#define LLVM_CODEGEN_MACHINEREGISTERINFO_H
#include "llvm/ADT/BitVector.h"
+#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/IndexedMap.h"
-#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/iterator_range.h"
-// PointerUnion needs to have access to the full RegisterBank type.
+#include "llvm/ADT/PointerUnion.h"
#include "llvm/CodeGen/GlobalISel/RegisterBank.h"
#include "llvm/CodeGen/LowLevelType.h"
+#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstrBundle.h"
+#include "llvm/CodeGen/MachineOperand.h"
+#include "llvm/MC/LaneBitmask.h"
#include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/Target/TargetSubtargetInfo.h"
#include <vector>
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <iterator>
+#include <memory>
+#include <utility>
namespace llvm {
+
class PSetIterator;
/// Convenient type to represent either a register class or a register bank.
@@ -41,15 +51,16 @@ class MachineRegisterInfo {
public:
class Delegate {
virtual void anchor();
+
public:
- virtual void MRI_NoteNewVirtualRegister(unsigned Reg) = 0;
+ virtual ~Delegate() = default;
- virtual ~Delegate() {}
+ virtual void MRI_NoteNewVirtualRegister(unsigned Reg) = 0;
};
private:
MachineFunction *MF;
- Delegate *TheDelegate;
+ Delegate *TheDelegate = nullptr;
/// True if subregister liveness is tracked.
const bool TracksSubRegLiveness;
@@ -62,6 +73,15 @@ private:
VirtReg2IndexFunctor>
VRegInfo;
+ /// The flag is true upon \p UpdatedCSRs initialization
+ /// and false otherwise.
+ bool IsUpdatedCSRsInitialized;
+
+ /// Contains the updated callee saved register list.
+ /// As opposed to the static list defined in register info,
+ /// all registers that were disabled are removed from the list.
+ SmallVector<MCPhysReg, 16> UpdatedCSRs;
+
/// RegAllocHints - This vector records register allocation hints for virtual
/// registers. For each virtual register, it keeps a register and hint type
/// pair making up the allocation hint. Hint type is target specific except
@@ -113,12 +133,12 @@ private:
/// Live in values are typically arguments in registers. LiveIn values are
/// allowed to have virtual registers associated with them, stored in the
/// second element.
- std::vector<std::pair<unsigned, unsigned> > LiveIns;
+ std::vector<std::pair<unsigned, unsigned>> LiveIns;
- MachineRegisterInfo(const MachineRegisterInfo&) = delete;
- void operator=(const MachineRegisterInfo&) = delete;
public:
explicit MachineRegisterInfo(MachineFunction *MF);
+ MachineRegisterInfo(const MachineRegisterInfo &) = delete;
+ MachineRegisterInfo &operator=(const MachineRegisterInfo &) = delete;
const TargetRegisterInfo *getTargetRegisterInfo() const {
return MF->getSubtarget().getRegisterInfo();
@@ -196,6 +216,23 @@ public:
// Register Info
//===--------------------------------------------------------------------===//
+ /// Returns true if the updated CSR list was initialized and false otherwise.
+ bool isUpdatedCSRsInitialized() const { return IsUpdatedCSRsInitialized; }
+
+ /// Disables the register from the list of CSRs.
+ /// I.e. the register will not appear as part of the CSR mask.
+ /// \see UpdatedCalleeSavedRegs.
+ void disableCalleeSavedRegister(unsigned Reg);
+
+ /// Returns list of callee saved registers.
+ /// The function returns the updated CSR list (after taking into account
+ /// registers that are disabled from the CSR list).
+ const MCPhysReg *getCalleeSavedRegs() const;
+
+ /// Sets the updated Callee Saved Registers list.
+ /// Notice that it will override ant previously disabled/saved CSRs.
+ void setCalleeSavedRegs(ArrayRef<MCPhysReg> CSRs);
+
// Strictly for use by MachineInstr.cpp.
void addRegOperandToUseList(MachineOperand *MO);
@@ -227,8 +264,6 @@ public:
template<bool, bool, bool, bool, bool, bool>
friend class defusechain_instr_iterator;
-
-
/// reg_iterator/reg_begin/reg_end - Walk all defs and uses of the specified
/// register.
typedef defusechain_iterator<true,true,false,true,false,false>
@@ -727,8 +762,6 @@ public:
const BitVector &getUsedPhysRegsMask() const { return UsedPhysRegMask; }
- void setUsedPhysRegMask(BitVector &Mask) { UsedPhysRegMask = Mask; }
-
//===--------------------------------------------------------------------===//
// Reserved Register Info
//===--------------------------------------------------------------------===//
@@ -800,7 +833,7 @@ public:
// Iteration support for the live-ins set. It's kept in sorted order
// by register number.
- typedef std::vector<std::pair<unsigned,unsigned> >::const_iterator
+ typedef std::vector<std::pair<unsigned,unsigned>>::const_iterator
livein_iterator;
livein_iterator livein_begin() const { return LiveIns.begin(); }
livein_iterator livein_end() const { return LiveIns.end(); }
@@ -836,7 +869,10 @@ public:
bool ByOperand, bool ByInstr, bool ByBundle>
class defusechain_iterator
: public std::iterator<std::forward_iterator_tag, MachineInstr, ptrdiff_t> {
- MachineOperand *Op;
+ friend class MachineRegisterInfo;
+
+ MachineOperand *Op = nullptr;
+
explicit defusechain_iterator(MachineOperand *op) : Op(op) {
// If the first node isn't one we're interested in, advance to one that
// we are interested in.
@@ -847,7 +883,6 @@ public:
advance();
}
}
- friend class MachineRegisterInfo;
void advance() {
assert(Op && "Cannot increment end iterator!");
@@ -868,13 +903,14 @@ public:
Op = getNextOperandForReg(Op);
}
}
+
public:
typedef std::iterator<std::forward_iterator_tag,
MachineInstr, ptrdiff_t>::reference reference;
typedef std::iterator<std::forward_iterator_tag,
MachineInstr, ptrdiff_t>::pointer pointer;
- defusechain_iterator() : Op(nullptr) {}
+ defusechain_iterator() = default;
bool operator==(const defusechain_iterator &x) const {
return Op == x.Op;
@@ -939,7 +975,10 @@ public:
bool ByOperand, bool ByInstr, bool ByBundle>
class defusechain_instr_iterator
: public std::iterator<std::forward_iterator_tag, MachineInstr, ptrdiff_t> {
- MachineOperand *Op;
+ friend class MachineRegisterInfo;
+
+ MachineOperand *Op = nullptr;
+
explicit defusechain_instr_iterator(MachineOperand *op) : Op(op) {
// If the first node isn't one we're interested in, advance to one that
// we are interested in.
@@ -950,7 +989,6 @@ public:
advance();
}
}
- friend class MachineRegisterInfo;
void advance() {
assert(Op && "Cannot increment end iterator!");
@@ -971,13 +1009,14 @@ public:
Op = getNextOperandForReg(Op);
}
}
+
public:
typedef std::iterator<std::forward_iterator_tag,
MachineInstr, ptrdiff_t>::reference reference;
typedef std::iterator<std::forward_iterator_tag,
MachineInstr, ptrdiff_t>::pointer pointer;
- defusechain_instr_iterator() : Op(nullptr) {}
+ defusechain_instr_iterator() = default;
bool operator==(const defusechain_instr_iterator &x) const {
return Op == x.Op;
@@ -1029,10 +1068,12 @@ public:
/// register. If Reg is physical, it must be a register unit (from
/// MCRegUnitIterator).
class PSetIterator {
- const int *PSet;
- unsigned Weight;
+ const int *PSet = nullptr;
+ unsigned Weight = 0;
+
public:
- PSetIterator(): PSet(nullptr), Weight(0) {}
+ PSetIterator() = default;
+
PSetIterator(unsigned RegUnit, const MachineRegisterInfo *MRI) {
const TargetRegisterInfo *TRI = MRI->getTargetRegisterInfo();
if (TargetRegisterInfo::isVirtualRegister(RegUnit)) {
@@ -1047,6 +1088,7 @@ public:
if (*PSet == -1)
PSet = nullptr;
}
+
bool isValid() const { return PSet; }
unsigned getWeight() const { return Weight; }
@@ -1066,6 +1108,6 @@ getPressureSets(unsigned RegUnit) const {
return PSetIterator(RegUnit, this);
}
-} // End llvm namespace
+} // end namespace llvm
-#endif
+#endif // LLVM_CODEGEN_MACHINEREGISTERINFO_H
diff --git a/include/llvm/CodeGen/MachineScheduler.h b/include/llvm/CodeGen/MachineScheduler.h
index 81b8741fea27..6b2a16e1d36e 100644
--- a/include/llvm/CodeGen/MachineScheduler.h
+++ b/include/llvm/CodeGen/MachineScheduler.h
@@ -1,4 +1,4 @@
-//==- MachineScheduler.h - MachineInstr Scheduling Pass ----------*- C++ -*-==//
+//===- MachineScheduler.h - MachineInstr Scheduling Pass --------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -112,12 +112,12 @@ class ScheduleHazardRecognizer;
/// MachineSchedContext provides enough context from the MachineScheduler pass
/// for the target to instantiate a scheduler.
struct MachineSchedContext {
- MachineFunction *MF;
- const MachineLoopInfo *MLI;
- const MachineDominatorTree *MDT;
- const TargetPassConfig *PassConfig;
- AliasAnalysis *AA;
- LiveIntervals *LIS;
+ MachineFunction *MF = nullptr;
+ const MachineLoopInfo *MLI = nullptr;
+ const MachineDominatorTree *MDT = nullptr;
+ const TargetPassConfig *PassConfig = nullptr;
+ AliasAnalysis *AA = nullptr;
+ LiveIntervals *LIS = nullptr;
RegisterClassInfo *RegClassInfo;
@@ -165,22 +165,21 @@ class ScheduleDAGMI;
/// before building the DAG.
struct MachineSchedPolicy {
// Allow the scheduler to disable register pressure tracking.
- bool ShouldTrackPressure;
+ bool ShouldTrackPressure = false;
/// Track LaneMasks to allow reordering of independent subregister writes
/// of the same vreg. \sa MachineSchedStrategy::shouldTrackLaneMasks()
- bool ShouldTrackLaneMasks;
+ bool ShouldTrackLaneMasks = false;
// Allow the scheduler to force top-down or bottom-up scheduling. If neither
// is true, the scheduler runs in both directions and converges.
- bool OnlyTopDown;
- bool OnlyBottomUp;
+ bool OnlyTopDown = false;
+ bool OnlyBottomUp = false;
// Disable heuristic that tries to fetch nodes from long dependency chains
// first.
- bool DisableLatencyHeuristic;
+ bool DisableLatencyHeuristic = false;
- MachineSchedPolicy(): ShouldTrackPressure(false), ShouldTrackLaneMasks(false),
- OnlyTopDown(false), OnlyBottomUp(false), DisableLatencyHeuristic(false) {}
+ MachineSchedPolicy() = default;
};
/// MachineSchedStrategy - Interface to the scheduling algorithm used by
@@ -232,6 +231,7 @@ public:
/// When all predecessor dependencies have been resolved, free this node for
/// top-down scheduling.
virtual void releaseTopNode(SUnit *SU) = 0;
+
/// When all successor dependencies have been resolved, free this node for
/// bottom-up scheduling.
virtual void releaseBottomNode(SUnit *SU) = 0;
@@ -261,24 +261,20 @@ protected:
MachineBasicBlock::iterator CurrentBottom;
/// Record the next node in a scheduled cluster.
- const SUnit *NextClusterPred;
- const SUnit *NextClusterSucc;
+ const SUnit *NextClusterPred = nullptr;
+ const SUnit *NextClusterSucc = nullptr;
#ifndef NDEBUG
/// The number of instructions scheduled so far. Used to cut off the
/// scheduler at the point determined by misched-cutoff.
- unsigned NumInstrsScheduled;
+ unsigned NumInstrsScheduled = 0;
#endif
+
public:
ScheduleDAGMI(MachineSchedContext *C, std::unique_ptr<MachineSchedStrategy> S,
bool RemoveKillFlags)
: ScheduleDAGInstrs(*C->MF, C->MLI, RemoveKillFlags), AA(C->AA),
- LIS(C->LIS), SchedImpl(std::move(S)), Topo(SUnits, &ExitSU),
- NextClusterPred(nullptr), NextClusterSucc(nullptr) {
-#ifndef NDEBUG
- NumInstrsScheduled = 0;
-#endif
- }
+ LIS(C->LIS), SchedImpl(std::move(S)), Topo(SUnits, &ExitSU) {}
// Provide a vtable anchor
~ScheduleDAGMI() override;
@@ -375,7 +371,7 @@ protected:
/// Information about DAG subtrees. If DFSResult is NULL, then SchedulerTrees
/// will be empty.
- SchedDFSResult *DFSResult;
+ SchedDFSResult *DFSResult = nullptr;
BitVector ScheduledTrees;
MachineBasicBlock::iterator LiveRegionEnd;
@@ -389,8 +385,8 @@ protected:
PressureDiffs SUPressureDiffs;
/// Register pressure in this region computed by initRegPressure.
- bool ShouldTrackPressure;
- bool ShouldTrackLaneMasks;
+ bool ShouldTrackPressure = false;
+ bool ShouldTrackLaneMasks = false;
IntervalPressure RegPressure;
RegPressureTracker RPTracker;
@@ -409,16 +405,14 @@ protected:
/// True if disconnected subregister components are already renamed.
/// The renaming is only done on demand if lane masks are tracked.
- bool DisconnectedComponentsRenamed;
+ bool DisconnectedComponentsRenamed = false;
public:
ScheduleDAGMILive(MachineSchedContext *C,
std::unique_ptr<MachineSchedStrategy> S)
: ScheduleDAGMI(C, std::move(S), /*RemoveKillFlags=*/false),
- RegClassInfo(C->RegClassInfo), DFSResult(nullptr),
- ShouldTrackPressure(false), ShouldTrackLaneMasks(false),
- RPTracker(RegPressure), TopRPTracker(TopPressure),
- BotRPTracker(BotPressure), DisconnectedComponentsRenamed(false) {}
+ RegClassInfo(C->RegClassInfo), RPTracker(RegPressure),
+ TopRPTracker(TopPressure), BotRPTracker(BotPressure) {}
~ScheduleDAGMILive() override;
@@ -573,6 +567,8 @@ struct SchedRemainder {
// Unscheduled resources
SmallVector<unsigned, 16> RemainingCounts;
+ SchedRemainder() { reset(); }
+
void reset() {
CriticalPath = 0;
CyclicCritPath = 0;
@@ -581,8 +577,6 @@ struct SchedRemainder {
RemainingCounts.clear();
}
- SchedRemainder() { reset(); }
-
void init(ScheduleDAGMI *DAG, const TargetSchedModel *SchedModel);
};
@@ -598,14 +592,14 @@ public:
LogMaxQID = 2
};
- ScheduleDAGMI *DAG;
- const TargetSchedModel *SchedModel;
- SchedRemainder *Rem;
+ ScheduleDAGMI *DAG = nullptr;
+ const TargetSchedModel *SchedModel = nullptr;
+ SchedRemainder *Rem = nullptr;
ReadyQueue Available;
ReadyQueue Pending;
- ScheduleHazardRecognizer *HazardRec;
+ ScheduleHazardRecognizer *HazardRec = nullptr;
private:
/// True if the pending Q should be checked/updated before scheduling another
@@ -665,9 +659,7 @@ public:
/// Pending queues extend the ready queues with the same ID and the
/// PendingFlag set.
SchedBoundary(unsigned ID, const Twine &Name):
- DAG(nullptr), SchedModel(nullptr), Rem(nullptr), Available(ID, Name+".A"),
- Pending(ID << LogMaxQID, Name+".P"),
- HazardRec(nullptr) {
+ Available(ID, Name+".A"), Pending(ID << LogMaxQID, Name+".P") {
reset();
}
@@ -781,11 +773,11 @@ public:
/// Policy for scheduling the next instruction in the candidate's zone.
struct CandPolicy {
- bool ReduceLatency;
- unsigned ReduceResIdx;
- unsigned DemandResIdx;
+ bool ReduceLatency = false;
+ unsigned ReduceResIdx = 0;
+ unsigned DemandResIdx = 0;
- CandPolicy(): ReduceLatency(false), ReduceResIdx(0), DemandResIdx(0) {}
+ CandPolicy() = default;
bool operator==(const CandPolicy &RHS) const {
return ReduceLatency == RHS.ReduceLatency &&
@@ -800,12 +792,12 @@ public:
/// Status of an instruction's critical resource consumption.
struct SchedResourceDelta {
// Count critical resources in the scheduled region required by SU.
- unsigned CritResources;
+ unsigned CritResources = 0;
// Count critical resources from another region consumed by SU.
- unsigned DemandedResources;
+ unsigned DemandedResources = 0;
- SchedResourceDelta(): CritResources(0), DemandedResources(0) {}
+ SchedResourceDelta() = default;
bool operator==(const SchedResourceDelta &RHS) const {
return CritResources == RHS.CritResources
@@ -866,13 +858,12 @@ public:
protected:
const MachineSchedContext *Context;
- const TargetSchedModel *SchedModel;
- const TargetRegisterInfo *TRI;
+ const TargetSchedModel *SchedModel = nullptr;
+ const TargetRegisterInfo *TRI = nullptr;
SchedRemainder Rem;
- GenericSchedulerBase(const MachineSchedContext *C):
- Context(C), SchedModel(nullptr), TRI(nullptr) {}
+ GenericSchedulerBase(const MachineSchedContext *C) : Context(C) {}
void setPolicy(CandPolicy &Policy, bool IsPostRA, SchedBoundary &CurrZone,
SchedBoundary *OtherZone);
@@ -887,7 +878,7 @@ protected:
class GenericScheduler : public GenericSchedulerBase {
public:
GenericScheduler(const MachineSchedContext *C):
- GenericSchedulerBase(C), DAG(nullptr), Top(SchedBoundary::TopQID, "TopQ"),
+ GenericSchedulerBase(C), Top(SchedBoundary::TopQID, "TopQ"),
Bot(SchedBoundary::BotQID, "BotQ") {}
void initPolicy(MachineBasicBlock::iterator Begin,
@@ -929,7 +920,7 @@ public:
void registerRoots() override;
protected:
- ScheduleDAGMILive *DAG;
+ ScheduleDAGMILive *DAG = nullptr;
MachineSchedPolicy RegionPolicy;
@@ -1033,9 +1024,6 @@ createStoreClusterDAGMutation(const TargetInstrInfo *TII,
const TargetRegisterInfo *TRI);
std::unique_ptr<ScheduleDAGMutation>
-createMacroFusionDAGMutation(const TargetInstrInfo *TII);
-
-std::unique_ptr<ScheduleDAGMutation>
createCopyConstrainDAGMutation(const TargetInstrInfo *TII,
const TargetRegisterInfo *TRI);
diff --git a/include/llvm/CodeGen/MachineTraceMetrics.h b/include/llvm/CodeGen/MachineTraceMetrics.h
index 06db17abaed9..284f8c197607 100644
--- a/include/llvm/CodeGen/MachineTraceMetrics.h
+++ b/include/llvm/CodeGen/MachineTraceMetrics.h
@@ -49,54 +49,59 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
-#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/TargetSchedule.h"
namespace llvm {
-class InstrItineraryData;
+class AnalysisUsage;
class MachineBasicBlock;
+class MachineFunction;
class MachineInstr;
class MachineLoop;
class MachineLoopInfo;
class MachineRegisterInfo;
+struct MCSchedClassDesc;
+class raw_ostream;
class TargetInstrInfo;
class TargetRegisterInfo;
-class raw_ostream;
class MachineTraceMetrics : public MachineFunctionPass {
- const MachineFunction *MF;
- const TargetInstrInfo *TII;
- const TargetRegisterInfo *TRI;
- const MachineRegisterInfo *MRI;
- const MachineLoopInfo *Loops;
+ const MachineFunction *MF = nullptr;
+ const TargetInstrInfo *TII = nullptr;
+ const TargetRegisterInfo *TRI = nullptr;
+ const MachineRegisterInfo *MRI = nullptr;
+ const MachineLoopInfo *Loops = nullptr;
TargetSchedModel SchedModel;
public:
+ friend class Ensemble;
+ friend class Trace;
+
class Ensemble;
- class Trace;
+
static char ID;
+
MachineTraceMetrics();
+
void getAnalysisUsage(AnalysisUsage&) const override;
bool runOnMachineFunction(MachineFunction&) override;
void releaseMemory() override;
void verifyAnalysis() const override;
- friend class Ensemble;
- friend class Trace;
-
/// Per-basic block information that doesn't depend on the trace through the
/// block.
struct FixedBlockInfo {
/// The number of non-trivial instructions in the block.
/// Doesn't count PHI and COPY instructions that are likely to be removed.
- unsigned InstrCount;
+ unsigned InstrCount = ~0u;
/// True when the block contains calls.
- bool HasCalls;
+ bool HasCalls = false;
- FixedBlockInfo() : InstrCount(~0u), HasCalls(false) {}
+ FixedBlockInfo() = default;
/// Returns true when resource information for this block has been computed.
bool hasResources() const { return InstrCount != ~0u; }
@@ -134,11 +139,11 @@ public:
struct TraceBlockInfo {
/// Trace predecessor, or NULL for the first block in the trace.
/// Valid when hasValidDepth().
- const MachineBasicBlock *Pred;
+ const MachineBasicBlock *Pred = nullptr;
/// Trace successor, or NULL for the last block in the trace.
/// Valid when hasValidHeight().
- const MachineBasicBlock *Succ;
+ const MachineBasicBlock *Succ = nullptr;
/// The block number of the head of the trace. (When hasValidDepth()).
unsigned Head;
@@ -148,16 +153,13 @@ public:
/// Accumulated number of instructions in the trace above this block.
/// Does not include instructions in this block.
- unsigned InstrDepth;
+ unsigned InstrDepth = ~0u;
/// Accumulated number of instructions in the trace below this block.
/// Includes instructions in this block.
- unsigned InstrHeight;
+ unsigned InstrHeight = ~0u;
- TraceBlockInfo() :
- Pred(nullptr), Succ(nullptr),
- InstrDepth(~0u), InstrHeight(~0u),
- HasValidInstrDepths(false), HasValidInstrHeights(false) {}
+ TraceBlockInfo() = default;
/// Returns true if the depth resources have been computed from the trace
/// above this block.
@@ -199,10 +201,10 @@ public:
// itinerary data.
/// Instruction depths have been computed. This implies hasValidDepth().
- bool HasValidInstrDepths;
+ bool HasValidInstrDepths = false;
/// Instruction heights have been computed. This implies hasValidHeight().
- bool HasValidInstrHeights;
+ bool HasValidInstrHeights = false;
/// Critical path length. This is the number of cycles in the longest data
/// dependency chain through the trace. This is only valid when both
@@ -242,6 +244,7 @@ public:
public:
explicit Trace(Ensemble &te, TraceBlockInfo &tbi) : TE(te), TBI(tbi) {}
+
void print(raw_ostream&) const;
/// Compute the total number of instructions in the trace.
@@ -300,11 +303,12 @@ public:
/// strategy, for example 'minimum resource height'. There is one trace for
/// every block in the function.
class Ensemble {
+ friend class Trace;
+
SmallVector<TraceBlockInfo, 4> BlockInfo;
DenseMap<const MachineInstr*, InstrCycles> Cycles;
SmallVector<unsigned, 0> ProcResourceDepths;
SmallVector<unsigned, 0> ProcResourceHeights;
- friend class Trace;
void computeTrace(const MachineBasicBlock*);
void computeDepthResources(const MachineBasicBlock*);
@@ -317,9 +321,11 @@ public:
protected:
MachineTraceMetrics &MTM;
+
+ explicit Ensemble(MachineTraceMetrics*);
+
virtual const MachineBasicBlock *pickTracePred(const MachineBasicBlock*) =0;
virtual const MachineBasicBlock *pickTraceSucc(const MachineBasicBlock*) =0;
- explicit Ensemble(MachineTraceMetrics*);
const MachineLoop *getLoopFor(const MachineBasicBlock*) const;
const TraceBlockInfo *getDepthResources(const MachineBasicBlock*) const;
const TraceBlockInfo *getHeightResources(const MachineBasicBlock*) const;
@@ -328,7 +334,8 @@ public:
public:
virtual ~Ensemble();
- virtual const char *getName() const =0;
+
+ virtual const char *getName() const = 0;
void print(raw_ostream&) const;
void invalidate(const MachineBasicBlock *MBB);
void verify() const;
@@ -394,6 +401,7 @@ inline raw_ostream &operator<<(raw_ostream &OS,
En.print(OS);
return OS;
}
+
} // end namespace llvm
-#endif
+#endif // LLVM_CODEGEN_MACHINETRACEMETRICS_H
diff --git a/include/llvm/CodeGen/MachineValueType.h b/include/llvm/CodeGen/MachineValueType.h
index de7064f07c3e..e4744fd5e260 100644
--- a/include/llvm/CodeGen/MachineValueType.h
+++ b/include/llvm/CodeGen/MachineValueType.h
@@ -23,14 +23,13 @@ namespace llvm {
class Type;
- /// MVT - Machine Value Type. Every type that is supported natively by some
+ /// 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 {
public:
enum SimpleValueType : int8_t {
- // INVALID_SIMPLE_VALUE_TYPE - Simple value types less than zero are
- // considered extended value types.
+ // Simple value types less than zero are considered extended value types.
INVALID_SIMPLE_VALUE_TYPE = -1,
// If you change this numbering, you must change the values in
@@ -141,37 +140,37 @@ class MVT {
// This value must be a multiple of 32.
MAX_ALLOWED_VALUETYPE = 96,
- // Token - A value of type llvm::TokenTy
+ // A value of type llvm::TokenTy
token = 120,
- // Metadata - This is MDNode or MDString.
+ // This is MDNode or MDString.
Metadata = 121,
- // iPTRAny - An int value the size of the pointer of the current
+ // An int value the size of the pointer of the current
// target to any address space. This must only be used internal to
// tblgen. Other than for overloading, we treat iPTRAny the same as iPTR.
iPTRAny = 122,
- // vAny - A vector with any length and element size. This is used
+ // A vector with any length and element size. This is used
// for intrinsics that have overloadings based on vector types.
// This is only for tblgen's consumption!
vAny = 123,
- // fAny - Any floating-point or vector floating-point value. This is used
+ // Any floating-point or vector floating-point value. This is used
// for intrinsics that have overloadings based on floating-point types.
// This is only for tblgen's consumption!
fAny = 124,
- // iAny - An integer or vector integer value of any bit width. This is
+ // An integer or vector integer value of any bit width. This is
// used for intrinsics that have overloadings based on integer bit widths.
// This is only for tblgen's consumption!
iAny = 125,
- // iPTR - An int value the size of the pointer of the current
+ // An int value the size of the pointer of the current
// target. This should only be used internal to tblgen!
iPTR = 126,
- // Any - Any type. This is used for intrinsics that have overloadings.
+ // Any type. This is used for intrinsics that have overloadings.
// This is only for tblgen's consumption!
Any = 127
};
@@ -188,13 +187,13 @@ class MVT {
bool operator>=(const MVT& S) const { return SimpleTy >= S.SimpleTy; }
bool operator<=(const MVT& S) const { return SimpleTy <= S.SimpleTy; }
- /// isValid - Return true if this is a valid simple valuetype.
+ /// Return true if this is a valid simple valuetype.
bool isValid() const {
return (SimpleTy >= MVT::FIRST_VALUETYPE &&
SimpleTy < MVT::LAST_VALUETYPE);
}
- /// isFloatingPoint - Return true if this is a FP, or a vector FP type.
+ /// Return true if this is a FP or a vector FP type.
bool isFloatingPoint() const {
return ((SimpleTy >= MVT::FIRST_FP_VALUETYPE &&
SimpleTy <= MVT::LAST_FP_VALUETYPE) ||
@@ -202,7 +201,7 @@ class MVT {
SimpleTy <= MVT::LAST_FP_VECTOR_VALUETYPE));
}
- /// isInteger - Return true if this is an integer, or a vector integer type.
+ /// Return true if this is an integer or a vector integer type.
bool isInteger() const {
return ((SimpleTy >= MVT::FIRST_INTEGER_VALUETYPE &&
SimpleTy <= MVT::LAST_INTEGER_VALUETYPE) ||
@@ -210,41 +209,40 @@ class MVT {
SimpleTy <= MVT::LAST_INTEGER_VECTOR_VALUETYPE));
}
- /// isScalarInteger - Return true if this is an integer, not including
- /// vectors.
+ /// Return true if this is an integer, not including vectors.
bool isScalarInteger() const {
return (SimpleTy >= MVT::FIRST_INTEGER_VALUETYPE &&
SimpleTy <= MVT::LAST_INTEGER_VALUETYPE);
}
- /// isVector - Return true if this is a vector value type.
+ /// Return true if this is a vector value type.
bool isVector() const {
return (SimpleTy >= MVT::FIRST_VECTOR_VALUETYPE &&
SimpleTy <= MVT::LAST_VECTOR_VALUETYPE);
}
- /// is16BitVector - Return true if this is a 16-bit vector type.
+ /// Return true if this is a 16-bit vector type.
bool is16BitVector() const {
return (SimpleTy == MVT::v2i8 || SimpleTy == MVT::v1i16 ||
SimpleTy == MVT::v16i1);
}
- /// is32BitVector - Return true if this is a 32-bit vector type.
+ /// Return true if this is a 32-bit vector type.
bool is32BitVector() const {
- return (SimpleTy == MVT::v4i8 || SimpleTy == MVT::v2i16 ||
- SimpleTy == MVT::v1i32 || SimpleTy == MVT::v2f16 ||
- SimpleTy == MVT::v1f32);
+ return (SimpleTy == MVT::v32i1 || SimpleTy == MVT::v4i8 ||
+ SimpleTy == MVT::v2i16 || SimpleTy == MVT::v1i32 ||
+ SimpleTy == MVT::v2f16 || SimpleTy == MVT::v1f32);
}
- /// is64BitVector - Return true if this is a 64-bit vector type.
+ /// Return true if this is a 64-bit vector type.
bool is64BitVector() const {
- return (SimpleTy == MVT::v8i8 || SimpleTy == MVT::v4i16 ||
- SimpleTy == MVT::v2i32 || SimpleTy == MVT::v1i64 ||
- SimpleTy == MVT::v4f16 || SimpleTy == MVT::v2f32 ||
- SimpleTy == MVT::v1f64);
+ return (SimpleTy == MVT::v64i1 || SimpleTy == MVT::v8i8 ||
+ SimpleTy == MVT::v4i16 || SimpleTy == MVT::v2i32 ||
+ SimpleTy == MVT::v1i64 || SimpleTy == MVT::v4f16 ||
+ SimpleTy == MVT::v2f32 || SimpleTy == MVT::v1f64);
}
- /// is128BitVector - Return true if this is a 128-bit vector type.
+ /// 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 ||
@@ -252,14 +250,14 @@ class MVT {
SimpleTy == MVT::v4f32 || SimpleTy == MVT::v2f64);
}
- /// is256BitVector - Return true if this is a 256-bit vector type.
+ /// Return true if this is a 256-bit vector type.
bool is256BitVector() const {
return (SimpleTy == MVT::v8f32 || SimpleTy == MVT::v4f64 ||
SimpleTy == MVT::v32i8 || SimpleTy == MVT::v16i16 ||
SimpleTy == MVT::v8i32 || SimpleTy == MVT::v4i64);
}
- /// is512BitVector - Return true if this is a 512-bit vector type.
+ /// Return true if this is a 512-bit vector type.
bool is512BitVector() const {
return (SimpleTy == MVT::v16f32 || SimpleTy == MVT::v8f64 ||
SimpleTy == MVT::v512i1 || SimpleTy == MVT::v64i8 ||
@@ -267,34 +265,34 @@ class MVT {
SimpleTy == MVT::v8i64);
}
- /// is1024BitVector - Return true if this is a 1024-bit vector type.
+ /// Return true if this is a 1024-bit vector type.
bool is1024BitVector() const {
return (SimpleTy == MVT::v1024i1 || SimpleTy == MVT::v128i8 ||
SimpleTy == MVT::v64i16 || SimpleTy == MVT::v32i32 ||
SimpleTy == MVT::v16i64);
}
- /// is2048BitVector - Return true if this is a 1024-bit vector type.
+ /// Return true if this is a 1024-bit vector type.
bool is2048BitVector() const {
return (SimpleTy == MVT::v256i8 || SimpleTy == MVT::v128i16 ||
SimpleTy == MVT::v64i32 || SimpleTy == MVT::v32i64);
}
- /// isOverloaded - Return true if this is an overloaded type for TableGen.
+ /// Return true if this is an overloaded type for TableGen.
bool isOverloaded() const {
return (SimpleTy==MVT::Any ||
SimpleTy==MVT::iAny || SimpleTy==MVT::fAny ||
SimpleTy==MVT::vAny || SimpleTy==MVT::iPTRAny);
}
- /// isPow2VectorType - Returns true if the given vector is a power of 2.
+ /// Returns true if the given vector is a power of 2.
bool isPow2VectorType() const {
unsigned NElts = getVectorNumElements();
return !(NElts & (NElts - 1));
}
- /// getPow2VectorType - Widens the length of the given vector MVT up to
- /// the nearest power of 2 and returns that type.
+ /// Widens the length of the given vector MVT up to the nearest power of 2
+ /// and returns that type.
MVT getPow2VectorType() const {
if (isPow2VectorType())
return *this;
@@ -304,8 +302,7 @@ class MVT {
return MVT::getVectorVT(getVectorElementType(), Pow2NElts);
}
- /// getScalarType - If this is a vector type, return the element type,
- /// otherwise return this.
+ /// If this is a vector, return the element type, otherwise return this.
MVT getScalarType() const {
return isVector() ? getVectorElementType() : *this;
}
@@ -516,14 +513,14 @@ class MVT {
return getScalarType().getSizeInBits();
}
- /// getStoreSize - Return the number of bytes overwritten by a store
- /// of the specified value type.
+ /// Return the number of bytes overwritten by a store of the specified value
+ /// type.
unsigned getStoreSize() const {
return (getSizeInBits() + 7) / 8;
}
- /// getStoreSizeInBits - Return the number of bits overwritten by a store
- /// of the specified value type.
+ /// Return the number of bits overwritten by a store of the specified value
+ /// type.
unsigned getStoreSizeInBits() const {
return getStoreSize() * 8;
}
diff --git a/include/llvm/CodeGen/PBQP/Solution.h b/include/llvm/CodeGen/PBQP/Solution.h
index bd74805a2397..d96b5eac4520 100644
--- a/include/llvm/CodeGen/PBQP/Solution.h
+++ b/include/llvm/CodeGen/PBQP/Solution.h
@@ -1,4 +1,4 @@
-//===-- Solution.h ------- PBQP Solution ------------------------*- C++ -*-===//
+//===- Solution.h - PBQP Solution -------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -14,8 +14,8 @@
#ifndef LLVM_CODEGEN_PBQP_SOLUTION_H
#define LLVM_CODEGEN_PBQP_SOLUTION_H
-#include "Graph.h"
-#include "Math.h"
+#include "llvm/CodeGen/PBQP/Graph.h"
+#include <cassert>
#include <map>
namespace llvm {
@@ -26,17 +26,17 @@ namespace PBQP {
/// To get the selection for each node in the problem use the getSelection method.
class Solution {
private:
-
typedef std::map<GraphBase::NodeId, unsigned> SelectionsMap;
SelectionsMap selections;
- unsigned r0Reductions, r1Reductions, r2Reductions, rNReductions;
+ unsigned r0Reductions = 0;
+ unsigned r1Reductions = 0;
+ unsigned r2Reductions = 0;
+ unsigned rNReductions = 0;
public:
-
/// \brief Initialise an empty solution.
- Solution()
- : r0Reductions(0), r1Reductions(0), r2Reductions(0), rNReductions(0) {}
+ Solution() = default;
/// \brief Set the selection for a given node.
/// @param nodeId Node id.
@@ -53,10 +53,9 @@ namespace PBQP {
assert(sItr != selections.end() && "No selection for node.");
return sItr->second;
}
-
};
-} // namespace PBQP
-} // namespace llvm
+} // end namespace PBQP
+} // end namespace llvm
#endif // LLVM_CODEGEN_PBQP_SOLUTION_H
diff --git a/include/llvm/CodeGen/Passes.h b/include/llvm/CodeGen/Passes.h
index a9fd301691d6..42299b529410 100644
--- a/include/llvm/CodeGen/Passes.h
+++ b/include/llvm/CodeGen/Passes.h
@@ -60,7 +60,9 @@ namespace llvm {
/// as if it was just created.
/// If EmitFallbackDiag is true, the pass will emit a
/// DiagnosticInfoISelFallback for every MachineFunction it resets.
- MachineFunctionPass *createResetMachineFunctionPass(bool EmitFallbackDiag);
+ /// If AbortOnFailedISel is true, abort compilation instead of resetting.
+ MachineFunctionPass *createResetMachineFunctionPass(bool EmitFallbackDiag,
+ bool AbortOnFailedISel);
/// createCodeGenPreparePass - Transform the code to expose more pattern
/// matching during instruction selection.
@@ -79,6 +81,9 @@ namespace llvm {
/// MachineDominanaceFrontier - This pass is a machine dominators analysis pass.
extern char &MachineDominanceFrontierID;
+ /// MachineRegionInfo - This pass computes SESE regions for machine functions.
+ extern char &MachineRegionInfoPassID;
+
/// EdgeBundles analysis - Bundle machine CFG edges.
extern char &EdgeBundlesID;
@@ -284,6 +289,9 @@ namespace llvm {
/// the target platform.
extern char &XRayInstrumentationID;
+ /// This pass inserts FEntry calls
+ extern char &FEntryInserterID;
+
/// \brief This pass implements the "patchable-function" attribute.
extern char &PatchableFunctionID;
@@ -318,14 +326,6 @@ namespace llvm {
/// ExpandISelPseudos - This pass expands pseudo-instructions.
extern char &ExpandISelPseudosID;
- /// createExecutionDependencyFixPass - This pass fixes execution time
- /// problems with dependent instructions, such as switching execution
- /// domains to match.
- ///
- /// The pass will examine instructions using and defining registers in RC.
- ///
- FunctionPass *createExecutionDependencyFixPass(const TargetRegisterClass *RC);
-
/// UnpackMachineBundles - This pass unpack machine instruction bundles.
extern char &UnpackMachineBundlesID;
@@ -397,6 +397,14 @@ namespace llvm {
/// This pass frees the memory occupied by the MachineFunction.
FunctionPass *createFreeMachineFunctionPass();
+
+ /// This pass combine basic blocks guarded by the same branch.
+ extern char &BranchCoalescingID;
+
+ /// This pass performs outlining on machine instructions directly before
+ /// printing assembly.
+ ModulePass *createMachineOutlinerPass();
+
} // End llvm namespace
/// Target machine pass initializer for passes with dependencies. Use with
@@ -413,7 +421,7 @@ namespace llvm {
Registry.registerPass(*PI, true); \
return PI; \
} \
- LLVM_DEFINE_ONCE_FLAG(Initialize##passName##PassFlag); \
+ static llvm::once_flag Initialize##passName##PassFlag; \
void llvm::initialize##passName##Pass(PassRegistry &Registry) { \
llvm::call_once(Initialize##passName##PassFlag, \
initialize##passName##PassOnce, std::ref(Registry)); \
diff --git a/include/llvm/CodeGen/RegAllocPBQP.h b/include/llvm/CodeGen/RegAllocPBQP.h
index 2cad90bbb703..8872a5dc54a1 100644
--- a/include/llvm/CodeGen/RegAllocPBQP.h
+++ b/include/llvm/CodeGen/RegAllocPBQP.h
@@ -1,4 +1,4 @@
-//===-- RegAllocPBQP.h ------------------------------------------*- C++ -*-===//
+//===- RegAllocPBQP.h -------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -16,15 +16,28 @@
#ifndef LLVM_CODEGEN_REGALLOCPBQP_H
#define LLVM_CODEGEN_REGALLOCPBQP_H
-#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/Hashing.h"
#include "llvm/CodeGen/PBQP/CostAllocator.h"
+#include "llvm/CodeGen/PBQP/Graph.h"
+#include "llvm/CodeGen/PBQP/Math.h"
#include "llvm/CodeGen/PBQP/ReductionRules.h"
-#include "llvm/CodeGen/PBQPRAConstraint.h"
+#include "llvm/CodeGen/PBQP/Solution.h"
#include "llvm/Support/ErrorHandling.h"
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <limits>
+#include <memory>
#include <set>
+#include <vector>
namespace llvm {
+class FunctionPass;
+class LiveIntervals;
+class MachineBlockFrequencyInfo;
+class MachineFunction;
class raw_ostream;
namespace PBQP {
@@ -37,15 +50,10 @@ inline unsigned getSpillOptionIdx() { return 0; }
///
/// Keeps track of the number of infinities in each row and column.
class MatrixMetadata {
-private:
- MatrixMetadata(const MatrixMetadata&);
- void operator=(const MatrixMetadata&);
public:
MatrixMetadata(const Matrix& M)
- : WorstRow(0), WorstCol(0),
- UnsafeRows(new bool[M.getRows() - 1]()),
+ : UnsafeRows(new bool[M.getRows() - 1]()),
UnsafeCols(new bool[M.getCols() - 1]()) {
-
unsigned* ColCounts = new unsigned[M.getCols() - 1]();
for (unsigned i = 1; i < M.getRows(); ++i) {
@@ -66,13 +74,17 @@ public:
delete[] ColCounts;
}
+ MatrixMetadata(const MatrixMetadata &) = delete;
+ MatrixMetadata &operator=(const MatrixMetadata &) = delete;
+
unsigned getWorstRow() const { return WorstRow; }
unsigned getWorstCol() const { return WorstCol; }
const bool* getUnsafeRows() const { return UnsafeRows.get(); }
const bool* getUnsafeCols() const { return UnsafeCols.get(); }
private:
- unsigned WorstRow, WorstCol;
+ unsigned WorstRow = 0;
+ unsigned WorstCol = 0;
std::unique_ptr<bool[]> UnsafeRows;
std::unique_ptr<bool[]> UnsafeCols;
};
@@ -80,17 +92,16 @@ private:
/// \brief Holds a vector of the allowed physical regs for a vreg.
class AllowedRegVector {
friend hash_code hash_value(const AllowedRegVector &);
-public:
- AllowedRegVector() : NumOpts(0), Opts(nullptr) {}
+public:
+ AllowedRegVector() = default;
+ AllowedRegVector(AllowedRegVector &&) = default;
AllowedRegVector(const std::vector<unsigned> &OptVec)
: NumOpts(OptVec.size()), Opts(new unsigned[NumOpts]) {
std::copy(OptVec.begin(), OptVec.end(), Opts.get());
}
- AllowedRegVector(AllowedRegVector &&) = default;
-
unsigned size() const { return NumOpts; }
unsigned operator[](size_t I) const { return Opts[I]; }
@@ -105,7 +116,7 @@ public:
}
private:
- unsigned NumOpts;
+ unsigned NumOpts = 0;
std::unique_ptr<unsigned[]> Opts;
};
@@ -120,8 +131,8 @@ inline hash_code hash_value(const AllowedRegVector &OptRegs) {
class GraphMetadata {
private:
typedef ValuePool<AllowedRegVector> AllowedRegVecPool;
-public:
+public:
typedef AllowedRegVecPool::PoolRef AllowedRegVecRef;
GraphMetadata(MachineFunction &MF,
@@ -168,13 +179,7 @@ public:
OptimallyReducible
} ReductionState;
- NodeMetadata()
- : RS(Unprocessed), NumOpts(0), DeniedOpts(0), OptUnsafeEdges(nullptr),
- VReg(0)
-#ifndef NDEBUG
- , everConservativelyAllocatable(false)
-#endif
- {}
+ NodeMetadata() = default;
NodeMetadata(const NodeMetadata &Other)
: RS(Other.RS), NumOpts(Other.NumOpts), DeniedOpts(Other.DeniedOpts),
@@ -190,9 +195,8 @@ public:
}
}
- NodeMetadata(NodeMetadata &&Other) = default;
-
- NodeMetadata& operator=(NodeMetadata &&Other) = default;
+ NodeMetadata(NodeMetadata &&) = default;
+ NodeMetadata& operator=(NodeMetadata &&) = default;
void setVReg(unsigned VReg) { this->VReg = VReg; }
unsigned getVReg() const { return VReg; }
@@ -249,21 +253,22 @@ public:
#endif
private:
- ReductionState RS;
- unsigned NumOpts;
- unsigned DeniedOpts;
+ ReductionState RS = Unprocessed;
+ unsigned NumOpts = 0;
+ unsigned DeniedOpts = 0;
std::unique_ptr<unsigned[]> OptUnsafeEdges;
- unsigned VReg;
+ unsigned VReg = 0;
GraphMetadata::AllowedRegVecRef AllowedRegs;
#ifndef NDEBUG
- bool everConservativelyAllocatable;
+ bool everConservativelyAllocatable = false;
#endif
};
class RegAllocSolverImpl {
private:
typedef MDMatrix<MatrixMetadata> RAMatrix;
+
public:
typedef PBQP::Vector RawVector;
typedef PBQP::Matrix RawMatrix;
@@ -296,6 +301,7 @@ public:
"PBQP Graph should not contain single or zero-option nodes");
G.getNodeMetadata(NId).setup(G.getNodeCosts(NId));
}
+
void handleRemoveNode(NodeId NId) {}
void handleSetNodeCosts(NodeId NId, const Vector& newCosts) {}
@@ -342,7 +348,6 @@ public:
}
private:
-
void promote(NodeId NId, NodeMetadata& NMd) {
if (G.getNodeDegree(NId) == 3) {
// This node is becoming optimally reducible.
@@ -474,6 +479,7 @@ private:
class SpillCostComparator {
public:
SpillCostComparator(const Graph& G) : G(G) {}
+
bool operator()(NodeId N1Id, NodeId N2Id) {
PBQPNum N1SC = G.getNodeCosts(N1Id)[0];
PBQPNum N2SC = G.getNodeCosts(N2Id)[0];
@@ -481,6 +487,7 @@ private:
return G.getNodeDegree(N1Id) < G.getNodeDegree(N2Id);
return N1SC < N2SC;
}
+
private:
const Graph& G;
};
@@ -495,8 +502,9 @@ private:
class PBQPRAGraph : public PBQP::Graph<RegAllocSolverImpl> {
private:
typedef PBQP::Graph<RegAllocSolverImpl> BaseT;
+
public:
- PBQPRAGraph(GraphMetadata Metadata) : BaseT(Metadata) {}
+ PBQPRAGraph(GraphMetadata Metadata) : BaseT(std::move(Metadata)) {}
/// @brief Dump this graph to dbgs().
void dump() const;
@@ -517,13 +525,13 @@ inline Solution solve(PBQPRAGraph& G) {
return RegAllocSolver.solve();
}
-} // namespace RegAlloc
-} // namespace PBQP
+} // end namespace RegAlloc
+} // end namespace PBQP
/// @brief Create a PBQP register allocator instance.
FunctionPass *
createPBQPRegisterAllocator(char *customPassID = nullptr);
-} // namespace llvm
+} // end namespace llvm
-#endif /* LLVM_CODEGEN_REGALLOCPBQP_H */
+#endif // LLVM_CODEGEN_REGALLOCPBQP_H
diff --git a/include/llvm/CodeGen/RegisterClassInfo.h b/include/llvm/CodeGen/RegisterClassInfo.h
index d784dfbda7ec..355c9f9b2f1e 100644
--- a/include/llvm/CodeGen/RegisterClassInfo.h
+++ b/include/llvm/CodeGen/RegisterClassInfo.h
@@ -1,4 +1,4 @@
-//===-- RegisterClassInfo.h - Dynamic Register Class Info -*- C++ -*-------===//
+//===- RegisterClassInfo.h - Dynamic Register Class Info --------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -19,22 +19,25 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/BitVector.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/Target/TargetRegisterInfo.h"
+#include <cassert>
+#include <cstdint>
+#include <memory>
namespace llvm {
class RegisterClassInfo {
struct RCInfo {
- unsigned Tag;
- unsigned NumRegs;
- bool ProperSubClass;
- uint8_t MinCost;
- uint16_t LastCostChange;
+ unsigned Tag = 0;
+ unsigned NumRegs = 0;
+ bool ProperSubClass = false;
+ uint8_t MinCost = 0;
+ uint16_t LastCostChange = 0;
std::unique_ptr<MCPhysReg[]> Order;
- RCInfo()
- : Tag(0), NumRegs(0), ProperSubClass(false), MinCost(0),
- LastCostChange(0) {}
+ RCInfo() = default;
operator ArrayRef<MCPhysReg>() const {
return makeArrayRef(Order.get(), NumRegs);
@@ -46,17 +49,18 @@ class RegisterClassInfo {
// Tag changes whenever cached information needs to be recomputed. An RCInfo
// entry is valid when its tag matches.
- unsigned Tag;
+ unsigned Tag = 0;
- const MachineFunction *MF;
- const TargetRegisterInfo *TRI;
+ const MachineFunction *MF = nullptr;
+ const TargetRegisterInfo *TRI = nullptr;
// Callee saved registers of last MF. Assumed to be valid until the next
// runOnFunction() call.
- const MCPhysReg *CalleeSaved;
+ // Used only to determine if an update was made to CalleeSavedAliases.
+ const MCPhysReg *CalleeSavedRegs = nullptr;
- // Map register number to CalleeSaved index + 1;
- SmallVector<uint8_t, 4> CSRNum;
+ // Map register alias to the callee saved Register.
+ SmallVector<MCPhysReg, 4> CalleeSavedAliases;
// Reserved registers in the current MF.
BitVector Reserved;
@@ -105,11 +109,11 @@ public:
}
/// getLastCalleeSavedAlias - Returns the last callee saved register that
- /// overlaps PhysReg, or 0 if Reg doesn't overlap a CSR.
+ /// overlaps PhysReg, or 0 if Reg doesn't overlap a CalleeSavedAliases.
unsigned getLastCalleeSavedAlias(unsigned PhysReg) const {
assert(TargetRegisterInfo::isPhysicalRegister(PhysReg));
- if (unsigned N = CSRNum[PhysReg])
- return CalleeSaved[N-1];
+ if (PhysReg < CalleeSavedAliases.size())
+ return CalleeSavedAliases[PhysReg];
return 0;
}
@@ -140,6 +144,7 @@ public:
protected:
unsigned computePSetLimit(unsigned Idx) const;
};
+
} // end namespace llvm
-#endif
+#endif // LLVM_CODEGEN_REGISTERCLASSINFO_H
diff --git a/include/llvm/CodeGen/RegisterPressure.h b/include/llvm/CodeGen/RegisterPressure.h
index 313be355e7d7..a3ea41d5236e 100644
--- a/include/llvm/CodeGen/RegisterPressure.h
+++ b/include/llvm/CodeGen/RegisterPressure.h
@@ -1,4 +1,4 @@
-//===-- RegisterPressure.h - Dynamic Register Pressure -*- C++ -*-------===//
+//===- RegisterPressure.h - Dynamic Register Pressure -----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -15,16 +15,25 @@
#ifndef LLVM_CODEGEN_REGISTERPRESSURE_H
#define LLVM_CODEGEN_REGISTERPRESSURE_H
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/SparseSet.h"
+#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/SlotIndexes.h"
+#include "llvm/MC/LaneBitmask.h"
#include "llvm/Target/TargetRegisterInfo.h"
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <cstdlib>
+#include <limits>
+#include <vector>
namespace llvm {
class LiveIntervals;
-class LiveRange;
-class RegisterClassInfo;
class MachineInstr;
+class RegisterClassInfo;
struct RegisterMaskPair {
unsigned RegUnit; ///< Virtual register or register unit.
@@ -91,12 +100,13 @@ struct RegionPressure : RegisterPressure {
/// higher level assert that pressure is consistent within a region. We also
/// effectively ignore dead defs which don't affect heuristics much.
class PressureChange {
- uint16_t PSetID; // ID+1. 0=Invalid.
- int16_t UnitInc;
+ uint16_t PSetID = 0; // ID+1. 0=Invalid.
+ int16_t UnitInc = 0;
+
public:
- PressureChange(): PSetID(0), UnitInc(0) {}
- PressureChange(unsigned id): PSetID(id+1), UnitInc(0) {
- assert(id < UINT16_MAX && "PSetID overflow.");
+ PressureChange() = default;
+ PressureChange(unsigned id): PSetID(id + 1) {
+ assert(id < std::numeric_limits<uint16_t>::max() && "PSetID overflow.");
}
bool isValid() const { return PSetID > 0; }
@@ -105,8 +115,11 @@ public:
assert(isValid() && "invalid PressureChange");
return PSetID - 1;
}
+
// If PSetID is invalid, return UINT16_MAX to give it lowest priority.
- unsigned getPSetOrMax() const { return (PSetID - 1) & UINT16_MAX; }
+ unsigned getPSetOrMax() const {
+ return (PSetID - 1) & std::numeric_limits<uint16_t>::max();
+ }
int getUnitInc() const { return UnitInc; }
@@ -146,7 +159,7 @@ public:
void addPressureChange(unsigned RegUnit, bool IsDec,
const MachineRegisterInfo *MRI);
- LLVM_DUMP_METHOD void dump(const TargetRegisterInfo &TRI) const;
+ void dump(const TargetRegisterInfo &TRI) const;
};
/// List of registers defined and used by a machine instruction.
@@ -182,11 +195,12 @@ public:
/// Array of PressureDiffs.
class PressureDiffs {
- PressureDiff *PDiffArray;
- unsigned Size;
- unsigned Max;
+ PressureDiff *PDiffArray = nullptr;
+ unsigned Size = 0;
+ unsigned Max = 0;
+
public:
- PressureDiffs(): PDiffArray(nullptr), Size(0), Max(0) {}
+ PressureDiffs() = default;
~PressureDiffs() { free(PDiffArray); }
void clear() { Size = 0; }
@@ -200,6 +214,7 @@ public:
const PressureDiff &operator[](unsigned Idx) const {
return const_cast<PressureDiffs*>(this)->operator[](Idx);
}
+
/// \brief Record pressure difference induced by the given operand list to
/// node with index \p Idx.
void addInstruction(unsigned Idx, const RegisterOperands &RegOpers,
@@ -225,7 +240,7 @@ struct RegPressureDelta {
PressureChange CriticalMax;
PressureChange CurrentMax;
- RegPressureDelta() {}
+ RegPressureDelta() = default;
bool operator==(const RegPressureDelta &RHS) const {
return Excess == RHS.Excess && CriticalMax == RHS.CriticalMax
@@ -264,6 +279,7 @@ private:
assert(Reg < NumRegUnits);
return Reg;
}
+
unsigned getRegFromSparseIndex(unsigned SparseIndex) const {
if (SparseIndex >= NumRegUnits)
return TargetRegisterInfo::index2VirtReg(SparseIndex-NumRegUnits);
@@ -338,14 +354,14 @@ public:
/// tracking. Changing direction has the side effect of closing region, and
/// traversing past TopIdx or BottomIdx reopens it.
class RegPressureTracker {
- const MachineFunction *MF;
- const TargetRegisterInfo *TRI;
- const RegisterClassInfo *RCI;
+ const MachineFunction *MF = nullptr;
+ const TargetRegisterInfo *TRI = nullptr;
+ const RegisterClassInfo *RCI = nullptr;
const MachineRegisterInfo *MRI;
- const LiveIntervals *LIS;
+ const LiveIntervals *LIS = nullptr;
/// We currently only allow pressure tracking within a block.
- const MachineBasicBlock *MBB;
+ const MachineBasicBlock *MBB = nullptr;
/// Track the max pressure within the region traversed so far.
RegisterPressure &P;
@@ -355,10 +371,10 @@ class RegPressureTracker {
bool RequireIntervals;
/// True if UntiedDefs will be populated.
- bool TrackUntiedDefs;
+ bool TrackUntiedDefs = false;
/// True if lanemasks should be tracked.
- bool TrackLaneMasks;
+ bool TrackLaneMasks = false;
/// Register pressure corresponds to liveness before this instruction
/// iterator. It may point to the end of the block or a DebugValue rather than
@@ -377,13 +393,8 @@ class RegPressureTracker {
std::vector<unsigned> LiveThruPressure;
public:
- RegPressureTracker(IntervalPressure &rp) :
- MF(nullptr), TRI(nullptr), RCI(nullptr), LIS(nullptr), MBB(nullptr), P(rp),
- RequireIntervals(true), TrackUntiedDefs(false), TrackLaneMasks(false) {}
-
- RegPressureTracker(RegionPressure &rp) :
- MF(nullptr), TRI(nullptr), RCI(nullptr), LIS(nullptr), MBB(nullptr), P(rp),
- RequireIntervals(false), TrackUntiedDefs(false), TrackLaneMasks(false) {}
+ RegPressureTracker(IntervalPressure &rp) : P(rp), RequireIntervals(true) {}
+ RegPressureTracker(RegionPressure &rp) : P(rp), RequireIntervals(false) {}
void reset();
@@ -555,6 +566,7 @@ protected:
void dumpRegSetPressure(ArrayRef<unsigned> SetPressure,
const TargetRegisterInfo *TRI);
+
} // end namespace llvm
-#endif
+#endif // LLVM_CODEGEN_REGISTERPRESSURE_H
diff --git a/include/llvm/CodeGen/RegisterScavenging.h b/include/llvm/CodeGen/RegisterScavenging.h
index 1b9232b90193..1f939e72e139 100644
--- a/include/llvm/CodeGen/RegisterScavenging.h
+++ b/include/llvm/CodeGen/RegisterScavenging.h
@@ -1,4 +1,4 @@
-//===-- RegisterScavenging.h - Machine register scavenging ------*- C++ -*-===//
+//===- RegisterScavenging.h - Machine register scavenging -------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -19,49 +19,49 @@
#define LLVM_CODEGEN_REGISTERSCAVENGING_H
#include "llvm/ADT/BitVector.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/CodeGen/LiveRegUnits.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/MC/LaneBitmask.h"
namespace llvm {
-class MachineRegisterInfo;
-class TargetRegisterInfo;
+class MachineInstr;
class TargetInstrInfo;
class TargetRegisterClass;
+class TargetRegisterInfo;
class RegScavenger {
const TargetRegisterInfo *TRI;
const TargetInstrInfo *TII;
MachineRegisterInfo* MRI;
- MachineBasicBlock *MBB;
+ MachineBasicBlock *MBB = nullptr;
MachineBasicBlock::iterator MBBI;
- unsigned NumRegUnits;
+ unsigned NumRegUnits = 0;
/// True if RegScavenger is currently tracking the liveness of registers.
- bool Tracking;
+ bool Tracking = false;
/// Information on scavenged registers (held in a spill slot).
struct ScavengedInfo {
- ScavengedInfo(int FI = -1) : FrameIndex(FI), Reg(0), Restore(nullptr) {}
+ ScavengedInfo(int FI = -1) : FrameIndex(FI) {}
/// A spill slot used for scavenging a register post register allocation.
int FrameIndex;
/// If non-zero, the specific register is currently being
/// scavenged. That is, it is spilled to this scavenging stack slot.
- unsigned Reg;
+ unsigned Reg = 0;
/// The instruction that restores the scavenged register from stack.
- const MachineInstr *Restore;
+ const MachineInstr *Restore = nullptr;
};
/// A vector of information on scavenged registers.
SmallVector<ScavengedInfo, 2> Scavenged;
- /// 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;
+ LiveRegUnits LiveUnits;
// These BitVectors are only used internally to forward(). They are members
// to avoid frequent reallocations.
@@ -69,8 +69,7 @@ class RegScavenger {
BitVector TmpRegUnits;
public:
- RegScavenger()
- : MBB(nullptr), NumRegUnits(0), Tracking(false) {}
+ RegScavenger() = default;
/// Start tracking liveness from the begin of basic block \p MBB.
void enterBasicBlock(MachineBasicBlock &MBB);
@@ -165,17 +164,18 @@ public:
/// Tell the scavenger a register is used.
void setRegUsed(unsigned Reg, LaneBitmask LaneMask = LaneBitmask::getAll());
+
private:
/// 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.
///
- void setUsed(BitVector &RegUnits) {
- RegUnitsAvailable.reset(RegUnits);
+ void setUsed(const BitVector &RegUnits) {
+ LiveUnits.addUnits(RegUnits);
}
- void setUnused(BitVector &RegUnits) {
- RegUnitsAvailable |= RegUnits;
+ void setUnused(const BitVector &RegUnits) {
+ LiveUnits.removeUnits(RegUnits);
}
/// Processes the current instruction and fill the KillRegUnits and
@@ -204,6 +204,6 @@ private:
void setLiveInsUsed(const MachineBasicBlock &MBB);
};
-} // End llvm namespace
+} // end namespace llvm
-#endif
+#endif // LLVM_CODEGEN_REGISTERSCAVENGING_H
diff --git a/include/llvm/CodeGen/ScheduleDAG.h b/include/llvm/CodeGen/ScheduleDAG.h
index ed4e0bc8a4a1..99afd8c5c9ab 100644
--- a/include/llvm/CodeGen/ScheduleDAG.h
+++ b/include/llvm/CodeGen/ScheduleDAG.h
@@ -1,4 +1,4 @@
-//===------- llvm/CodeGen/ScheduleDAG.h - Common Base Class------*- C++ -*-===//
+//===- llvm/CodeGen/ScheduleDAG.h - Common Base Class -----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,9 +7,9 @@
//
//===----------------------------------------------------------------------===//
//
-// This file implements the ScheduleDAG class, which is used as the common
-// base class for instruction schedulers. This encapsulates the scheduling DAG,
-// which is shared between SelectionDAG and MachineInstr scheduling.
+/// \file Implements the ScheduleDAG class, which is used as the common base
+/// class for instruction schedulers. This encapsulates the scheduling DAG,
+/// which is shared between SelectionDAG and MachineInstr scheduling.
//
//===----------------------------------------------------------------------===//
@@ -18,33 +18,38 @@
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/GraphTraits.h"
+#include "llvm/ADT/iterator.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/SmallVector.h"
-#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/CodeGen/MachineInstr.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Target/TargetLowering.h"
+#include <cassert>
+#include <cstddef>
+#include <iterator>
+#include <string>
+#include <vector>
namespace llvm {
- class SUnit;
- class MachineConstantPool;
- class MachineFunction;
- class MachineRegisterInfo;
- class MachineInstr;
- struct MCSchedClassDesc;
- class TargetRegisterInfo;
- class ScheduleDAG;
- class SDNode;
- class TargetInstrInfo;
- class MCInstrDesc;
- class TargetMachine;
- class TargetRegisterClass;
- template<class Graph> class GraphWriter;
-
- /// SDep - Scheduling dependency. This represents one direction of an
- /// edge in the scheduling DAG.
+
+template<class Graph> class GraphWriter;
+class MachineFunction;
+class MachineRegisterInfo;
+class MCInstrDesc;
+struct MCSchedClassDesc;
+class ScheduleDAG;
+class SDNode;
+class SUnit;
+class TargetInstrInfo;
+class TargetMachine;
+class TargetRegisterClass;
+class TargetRegisterInfo;
+
+ /// Scheduling dependency. This represents one direction of an edge in the
+ /// scheduling DAG.
class SDep {
public:
- /// Kind - These are the different kinds of scheduling dependencies.
+ /// These are the different kinds of scheduling dependencies.
enum Kind {
Data, ///< Regular data dependence (aka true-dependence).
Anti, ///< A register anti-dependedence (aka WAR).
@@ -71,33 +76,32 @@ namespace llvm {
};
private:
- /// Dep - A pointer to the depending/depended-on SUnit, and an enum
+ /// \brief A pointer to the depending/depended-on SUnit, and an enum
/// indicating the kind of the dependency.
PointerIntPair<SUnit *, 2, Kind> Dep;
- /// Contents - A union discriminated by the dependence kind.
+ /// A union discriminated by the dependence kind.
union {
- /// Reg - For Data, Anti, and Output dependencies, the associated
- /// register. For Data dependencies that don't currently have a register
- /// assigned, this is set to zero.
+ /// For Data, Anti, and Output dependencies, the associated register. For
+ /// Data dependencies that don't currently have a register/ assigned, this
+ /// is set to zero.
unsigned Reg;
- /// Order - Additional information about Order dependencies.
+ /// Additional information about Order dependencies.
unsigned OrdKind; // enum OrderKind
} Contents;
- /// Latency - The time associated with this edge. Often this is just
- /// the value of the Latency field of the predecessor, however advanced
- /// models may provide additional information about specific edges.
+ /// The time associated with this edge. Often this is just the value of the
+ /// Latency field of the predecessor, however advanced models may provide
+ /// additional information about specific edges.
unsigned Latency;
public:
- /// SDep - Construct a null SDep. This is only for use by container
- /// classes which require default constructors. SUnits may not
- /// have null SDep edges.
+ /// Constructs a null SDep. This is only for use by container classes which
+ /// require default constructors. SUnits may not/ have null SDep edges.
SDep() : Dep(nullptr, Data) {}
- /// SDep - Construct an SDep with the specified values.
+ /// Constructs an SDep with the specified values.
SDep(SUnit *S, Kind kind, unsigned Reg)
: Dep(S, kind), Contents() {
switch (kind) {
@@ -116,12 +120,13 @@ namespace llvm {
break;
}
}
+
SDep(SUnit *S, OrderKind kind)
: Dep(S, Order), Contents(), Latency(0) {
Contents.OrdKind = kind;
}
- /// Return true if the specified SDep is equivalent except for latency.
+ /// Returns true if the specified SDep is equivalent except for latency.
bool overlaps(const SDep &Other) const;
bool operator==(const SDep &Other) const {
@@ -132,100 +137,95 @@ namespace llvm {
return !operator==(Other);
}
- /// getLatency - Return the latency value for this edge, which roughly
- /// means the minimum number of cycles that must elapse between the
- /// predecessor and the successor, given that they have this edge
- /// between them.
+ /// \brief Returns the latency value for this edge, which roughly means the
+ /// minimum number of cycles that must elapse between the predecessor and
+ /// the successor, given that they have this edge between them.
unsigned getLatency() const {
return Latency;
}
- /// setLatency - Set the latency for this edge.
+ /// Sets the latency for this edge.
void setLatency(unsigned Lat) {
Latency = Lat;
}
- //// getSUnit - Return the SUnit to which this edge points.
+ //// Returns the SUnit to which this edge points.
SUnit *getSUnit() const;
- //// setSUnit - Assign the SUnit to which this edge points.
+ //// Assigns the SUnit to which this edge points.
void setSUnit(SUnit *SU);
- /// getKind - Return an enum value representing the kind of the dependence.
+ /// Returns an enum value representing the kind of the dependence.
Kind getKind() const;
- /// isCtrl - Shorthand for getKind() != SDep::Data.
+ /// Shorthand for getKind() != SDep::Data.
bool isCtrl() const {
return getKind() != Data;
}
- /// isNormalMemory - Test if this is an Order dependence between two
- /// memory accesses where both sides of the dependence access memory
- /// in non-volatile and fully modeled ways.
+ /// \brief Tests if this is an Order dependence between two memory accesses
+ /// where both sides of the dependence access memory in non-volatile and
+ /// fully modeled ways.
bool isNormalMemory() const {
return getKind() == Order && (Contents.OrdKind == MayAliasMem
|| Contents.OrdKind == MustAliasMem);
}
- /// isBarrier - Test if this is an Order dependence that is marked
- /// as a barrier.
+ /// Tests if this is an Order dependence that is marked as a barrier.
bool isBarrier() const {
return getKind() == Order && Contents.OrdKind == Barrier;
}
- /// isNormalMemoryOrBarrier - Test if this is could be any kind of memory
- /// dependence.
+ /// Tests if this is could be any kind of memory dependence.
bool isNormalMemoryOrBarrier() const {
return (isNormalMemory() || isBarrier());
}
- /// isMustAlias - Test if this is an Order dependence that is marked
- /// as "must alias", meaning that the SUnits at either end of the edge
- /// have a memory dependence on a known memory location.
+ /// \brief Tests if this is an Order dependence that is marked as
+ /// "must alias", meaning that the SUnits at either end of the edge have a
+ /// memory dependence on a known memory location.
bool isMustAlias() const {
return getKind() == Order && Contents.OrdKind == MustAliasMem;
}
- /// isWeak - Test if this a weak dependence. Weak dependencies are
- /// considered DAG edges for height computation and other heuristics, but do
- /// not force ordering. Breaking a weak edge may require the scheduler to
- /// compensate, for example by inserting a copy.
+ /// Tests if this a weak dependence. Weak dependencies are considered DAG
+ /// edges for height computation and other heuristics, but do not force
+ /// ordering. Breaking a weak edge may require the scheduler to compensate,
+ /// for example by inserting a copy.
bool isWeak() const {
return getKind() == Order && Contents.OrdKind >= Weak;
}
- /// isArtificial - Test if this is an Order dependence that is marked
- /// as "artificial", meaning it isn't necessary for correctness.
+ /// \brief Tests if this is an Order dependence that is marked as
+ /// "artificial", meaning it isn't necessary for correctness.
bool isArtificial() const {
return getKind() == Order && Contents.OrdKind == Artificial;
}
- /// isCluster - Test if this is an Order dependence that is marked
- /// as "cluster", meaning it is artificial and wants to be adjacent.
+ /// \brief Tests if this is an Order dependence that is marked as "cluster",
+ /// meaning it is artificial and wants to be adjacent.
bool isCluster() const {
return getKind() == Order && Contents.OrdKind == Cluster;
}
- /// isAssignedRegDep - Test if this is a Data dependence that is
- /// associated with a register.
+ /// Tests if this is a Data dependence that is associated with a register.
bool isAssignedRegDep() const {
return getKind() == Data && Contents.Reg != 0;
}
- /// getReg - Return the register associated with this edge. This is
- /// only valid on Data, Anti, and Output edges. On Data edges, this
- /// value may be zero, meaning there is no associated register.
+ /// Returns the register associated with this edge. This is only valid on
+ /// Data, Anti, and Output edges. On Data edges, this value may be zero,
+ /// meaning there is no associated register.
unsigned getReg() const {
assert((getKind() == Data || getKind() == Anti || getKind() == Output) &&
"getReg called on non-register dependence edge!");
return Contents.Reg;
}
- /// setReg - Assign the associated register for this edge. This is
- /// only valid on Data, Anti, and Output edges. On Anti and Output
- /// edges, this value must not be zero. On Data edges, the value may
- /// be zero, which would mean that no specific register is associated
- /// with this edge.
+ /// Assigns the associated register for this edge. This is only valid on
+ /// Data, Anti, and Output edges. On Anti and Output edges, this value must
+ /// not be zero. On Data edges, the value may be zero, which would mean that
+ /// no specific register is associated with this edge.
void setReg(unsigned Reg) {
assert((getKind() == Data || getKind() == Anti || getKind() == Output) &&
"setReg called on non-register dependence edge!");
@@ -240,115 +240,101 @@ namespace llvm {
template <>
struct isPodLike<SDep> { static const bool value = true; };
- /// SUnit - Scheduling unit. This is a node in the scheduling DAG.
+ /// Scheduling unit. This is a node in the scheduling DAG.
class SUnit {
private:
enum : unsigned { BoundaryID = ~0u };
- SDNode *Node; // Representative node.
- MachineInstr *Instr; // Alternatively, a MachineInstr.
+ SDNode *Node = nullptr; ///< Representative node.
+ MachineInstr *Instr = nullptr; ///< Alternatively, a MachineInstr.
+
public:
- SUnit *OrigNode; // If not this, the node from which
- // this node was cloned.
- // (SD scheduling only)
+ SUnit *OrigNode = nullptr; ///< If not this, the node from which this node
+ /// was cloned. (SD scheduling only)
- const MCSchedClassDesc *SchedClass; // NULL or resolved SchedClass.
+ const MCSchedClassDesc *SchedClass =
+ nullptr; ///< nullptr or resolved SchedClass.
- // Preds/Succs - The SUnits before/after us in the graph.
- SmallVector<SDep, 4> Preds; // All sunit predecessors.
- SmallVector<SDep, 4> Succs; // All sunit successors.
+ SmallVector<SDep, 4> Preds; ///< All sunit predecessors.
+ SmallVector<SDep, 4> Succs; ///< All sunit successors.
typedef SmallVectorImpl<SDep>::iterator pred_iterator;
typedef SmallVectorImpl<SDep>::iterator succ_iterator;
typedef SmallVectorImpl<SDep>::const_iterator const_pred_iterator;
typedef SmallVectorImpl<SDep>::const_iterator const_succ_iterator;
- unsigned NodeNum; // Entry # of node in the node vector.
- unsigned NodeQueueId; // Queue id of node.
- unsigned NumPreds; // # of SDep::Data preds.
- unsigned NumSuccs; // # of SDep::Data sucss.
- unsigned NumPredsLeft; // # of preds not scheduled.
- unsigned NumSuccsLeft; // # of succs not scheduled.
- unsigned WeakPredsLeft; // # of weak preds not scheduled.
- unsigned WeakSuccsLeft; // # of weak succs not scheduled.
- unsigned short NumRegDefsLeft; // # of reg defs with no scheduled use.
- unsigned short Latency; // Node latency.
- bool isVRegCycle : 1; // May use and def the same vreg.
- bool isCall : 1; // Is a function call.
- bool isCallOp : 1; // Is a function call operand.
- bool isTwoAddress : 1; // Is a two-address instruction.
- bool isCommutable : 1; // Is a commutable instruction.
- bool hasPhysRegUses : 1; // Has physreg uses.
- bool hasPhysRegDefs : 1; // Has physreg defs that are being used.
- bool hasPhysRegClobbers : 1; // Has any physreg defs, used or not.
- bool isPending : 1; // True once pending.
- bool isAvailable : 1; // True once available.
- bool isScheduled : 1; // True once scheduled.
- bool isScheduleHigh : 1; // True if preferable to schedule high.
- bool isScheduleLow : 1; // True if preferable to schedule low.
- bool isCloned : 1; // True if this node has been cloned.
- bool isUnbuffered : 1; // Uses an unbuffered resource.
- bool hasReservedResource : 1; // Uses a reserved resource.
- Sched::Preference SchedulingPref; // Scheduling preference.
+ unsigned NodeNum = BoundaryID; ///< Entry # of node in the node vector.
+ unsigned NodeQueueId = 0; ///< Queue id of node.
+ unsigned NumPreds = 0; ///< # of SDep::Data preds.
+ unsigned NumSuccs = 0; ///< # of SDep::Data sucss.
+ unsigned NumPredsLeft = 0; ///< # of preds not scheduled.
+ unsigned NumSuccsLeft = 0; ///< # of succs not scheduled.
+ unsigned WeakPredsLeft = 0; ///< # of weak preds not scheduled.
+ unsigned WeakSuccsLeft = 0; ///< # of weak succs not scheduled.
+ unsigned short NumRegDefsLeft = 0; ///< # of reg defs with no scheduled use.
+ unsigned short Latency = 0; ///< Node latency.
+ bool isVRegCycle : 1; ///< May use and def the same vreg.
+ bool isCall : 1; ///< Is a function call.
+ bool isCallOp : 1; ///< Is a function call operand.
+ bool isTwoAddress : 1; ///< Is a two-address instruction.
+ bool isCommutable : 1; ///< Is a commutable instruction.
+ bool hasPhysRegUses : 1; ///< Has physreg uses.
+ bool hasPhysRegDefs : 1; ///< Has physreg defs that are being used.
+ bool hasPhysRegClobbers : 1; ///< Has any physreg defs, used or not.
+ bool isPending : 1; ///< True once pending.
+ bool isAvailable : 1; ///< True once available.
+ bool isScheduled : 1; ///< True once scheduled.
+ bool isScheduleHigh : 1; ///< True if preferable to schedule high.
+ bool isScheduleLow : 1; ///< True if preferable to schedule low.
+ bool isCloned : 1; ///< True if this node has been cloned.
+ bool isUnbuffered : 1; ///< Uses an unbuffered resource.
+ bool hasReservedResource : 1; ///< Uses a reserved resource.
+ Sched::Preference SchedulingPref = Sched::None; ///< Scheduling preference.
private:
- bool isDepthCurrent : 1; // True if Depth is current.
- bool isHeightCurrent : 1; // True if Height is current.
- unsigned Depth; // Node depth.
- unsigned Height; // Node height.
+ bool isDepthCurrent : 1; ///< True if Depth is current.
+ bool isHeightCurrent : 1; ///< True if Height is current.
+ unsigned Depth = 0; ///< Node depth.
+ unsigned Height = 0; ///< Node height.
+
public:
- unsigned TopReadyCycle; // Cycle relative to start when node is ready.
- unsigned BotReadyCycle; // Cycle relative to end when node is ready.
+ unsigned TopReadyCycle = 0; ///< Cycle relative to start when node is ready.
+ unsigned BotReadyCycle = 0; ///< Cycle relative to end when node is ready.
- const TargetRegisterClass *CopyDstRC; // Is a special copy node if not null.
- const TargetRegisterClass *CopySrcRC;
+ const TargetRegisterClass *CopyDstRC =
+ nullptr; ///< Is a special copy node if != nullptr.
+ const TargetRegisterClass *CopySrcRC = nullptr;
- /// SUnit - Construct an SUnit for pre-regalloc scheduling to represent
- /// an SDNode and any nodes flagged to it.
+ /// \brief Constructs an SUnit for pre-regalloc scheduling to represent an
+ /// SDNode and any nodes flagged to it.
SUnit(SDNode *node, unsigned nodenum)
- : Node(node), Instr(nullptr), OrigNode(nullptr), SchedClass(nullptr),
- NodeNum(nodenum), NodeQueueId(0), NumPreds(0), NumSuccs(0),
- NumPredsLeft(0), NumSuccsLeft(0), WeakPredsLeft(0), WeakSuccsLeft(0),
- NumRegDefsLeft(0), Latency(0), isVRegCycle(false), isCall(false),
+ : Node(node), NodeNum(nodenum), isVRegCycle(false), isCall(false),
isCallOp(false), isTwoAddress(false), isCommutable(false),
hasPhysRegUses(false), hasPhysRegDefs(false), hasPhysRegClobbers(false),
isPending(false), isAvailable(false), isScheduled(false),
isScheduleHigh(false), isScheduleLow(false), isCloned(false),
- isUnbuffered(false), hasReservedResource(false),
- SchedulingPref(Sched::None), isDepthCurrent(false),
- isHeightCurrent(false), Depth(0), Height(0), TopReadyCycle(0),
- BotReadyCycle(0), CopyDstRC(nullptr), CopySrcRC(nullptr) {}
+ isUnbuffered(false), hasReservedResource(false), isDepthCurrent(false),
+ isHeightCurrent(false) {}
- /// SUnit - Construct an SUnit for post-regalloc scheduling to represent
- /// a MachineInstr.
+ /// \brief Constructs an SUnit for post-regalloc scheduling to represent a
+ /// MachineInstr.
SUnit(MachineInstr *instr, unsigned nodenum)
- : Node(nullptr), Instr(instr), OrigNode(nullptr), SchedClass(nullptr),
- NodeNum(nodenum), NodeQueueId(0), NumPreds(0), NumSuccs(0),
- NumPredsLeft(0), NumSuccsLeft(0), WeakPredsLeft(0), WeakSuccsLeft(0),
- NumRegDefsLeft(0), Latency(0), isVRegCycle(false), isCall(false),
+ : Instr(instr), NodeNum(nodenum), isVRegCycle(false), isCall(false),
isCallOp(false), isTwoAddress(false), isCommutable(false),
hasPhysRegUses(false), hasPhysRegDefs(false), hasPhysRegClobbers(false),
isPending(false), isAvailable(false), isScheduled(false),
isScheduleHigh(false), isScheduleLow(false), isCloned(false),
- isUnbuffered(false), hasReservedResource(false),
- SchedulingPref(Sched::None), isDepthCurrent(false),
- isHeightCurrent(false), Depth(0), Height(0), TopReadyCycle(0),
- BotReadyCycle(0), CopyDstRC(nullptr), CopySrcRC(nullptr) {}
+ isUnbuffered(false), hasReservedResource(false), isDepthCurrent(false),
+ isHeightCurrent(false) {}
- /// SUnit - Construct a placeholder SUnit.
+ /// \brief Constructs a placeholder SUnit.
SUnit()
- : Node(nullptr), Instr(nullptr), OrigNode(nullptr), SchedClass(nullptr),
- NodeNum(BoundaryID), NodeQueueId(0), NumPreds(0), NumSuccs(0),
- NumPredsLeft(0), NumSuccsLeft(0), WeakPredsLeft(0), WeakSuccsLeft(0),
- NumRegDefsLeft(0), Latency(0), isVRegCycle(false), isCall(false),
- isCallOp(false), isTwoAddress(false), isCommutable(false),
- hasPhysRegUses(false), hasPhysRegDefs(false), hasPhysRegClobbers(false),
- isPending(false), isAvailable(false), isScheduled(false),
- isScheduleHigh(false), isScheduleLow(false), isCloned(false),
- isUnbuffered(false), hasReservedResource(false),
- SchedulingPref(Sched::None), isDepthCurrent(false),
- isHeightCurrent(false), Depth(0), Height(0), TopReadyCycle(0),
- BotReadyCycle(0), CopyDstRC(nullptr), CopySrcRC(nullptr) {}
+ : isVRegCycle(false), isCall(false), isCallOp(false), isTwoAddress(false),
+ isCommutable(false), hasPhysRegUses(false), hasPhysRegDefs(false),
+ hasPhysRegClobbers(false), isPending(false), isAvailable(false),
+ isScheduled(false), isScheduleHigh(false), isScheduleLow(false),
+ isCloned(false), isUnbuffered(false), hasReservedResource(false),
+ isDepthCurrent(false), isHeightCurrent(false) {}
/// \brief Boundary nodes are placeholders for the boundary of the
/// scheduling region.
@@ -359,46 +345,44 @@ namespace llvm {
/// an assoicative data structure keyed on node ID.
bool isBoundaryNode() const { return NodeNum == BoundaryID; }
- /// setNode - Assign the representative SDNode for this SUnit.
- /// This may be used during pre-regalloc scheduling.
+ /// Assigns the representative SDNode for this SUnit. This may be used
+ /// during pre-regalloc scheduling.
void setNode(SDNode *N) {
assert(!Instr && "Setting SDNode of SUnit with MachineInstr!");
Node = N;
}
- /// getNode - Return the representative SDNode for this SUnit.
- /// This may be used during pre-regalloc scheduling.
+ /// Returns the representative SDNode for this SUnit. This may be used
+ /// during pre-regalloc scheduling.
SDNode *getNode() const {
assert(!Instr && "Reading SDNode of SUnit with MachineInstr!");
return Node;
}
- /// isInstr - Return true if this SUnit refers to a machine instruction as
+ /// \brief Returns true if this SUnit refers to a machine instruction as
/// opposed to an SDNode.
bool isInstr() const { return Instr; }
- /// setInstr - Assign the instruction for the SUnit.
- /// This may be used during post-regalloc scheduling.
+ /// Assigns the instruction for the SUnit. This may be used during
+ /// post-regalloc scheduling.
void setInstr(MachineInstr *MI) {
assert(!Node && "Setting MachineInstr of SUnit with SDNode!");
Instr = MI;
}
- /// getInstr - Return the representative MachineInstr for this SUnit.
- /// This may be used during post-regalloc scheduling.
+ /// Returns the representative MachineInstr for this SUnit. This may be used
+ /// during post-regalloc scheduling.
MachineInstr *getInstr() const {
assert(!Node && "Reading MachineInstr of SUnit with SDNode!");
return Instr;
}
- /// addPred - This adds the specified edge as a pred of the current node if
- /// not already. It also adds the current node as a successor of the
- /// specified node.
+ /// Adds the specified edge as a pred of the current node if not already.
+ /// It also adds the current node as a successor of the specified node.
bool addPred(const SDep &D, bool Required = true);
- /// addPredBarrier - This adds a barrier edge to SU by calling
- /// addPred(), with latency 0 generally or latency 1 for a store
- /// followed by a load.
+ /// \brief Adds a barrier edge to SU by calling addPred(), with latency 0
+ /// generally or latency 1 for a store followed by a load.
bool addPredBarrier(SUnit *SU) {
SDep Dep(SU, SDep::Barrier);
unsigned TrueMemOrderLatency =
@@ -407,20 +391,19 @@ namespace llvm {
return addPred(Dep);
}
- /// removePred - This removes the specified edge as a pred of the current
- /// node if it exists. It also removes the current node as a successor of
- /// the specified node.
+ /// Removes the specified edge as a pred of the current node if it exists.
+ /// It also removes the current node as a successor of the specified node.
void removePred(const SDep &D);
- /// getDepth - Return the depth of this node, which is the length of the
- /// maximum path up to any node which has no predecessors.
+ /// Returns the depth of this node, which is the length of the maximum path
+ /// up to any node which has no predecessors.
unsigned getDepth() const {
if (!isDepthCurrent)
const_cast<SUnit *>(this)->ComputeDepth();
return Depth;
}
- /// getHeight - Return the height of this node, which is the length of the
+ /// \brief Returns the height of this node, which is the length of the
/// maximum path down to any node which has no successors.
unsigned getHeight() const {
if (!isHeightCurrent)
@@ -428,38 +411,36 @@ namespace llvm {
return Height;
}
- /// setDepthToAtLeast - If NewDepth is greater than this node's
- /// depth value, set it to be the new depth value. This also
- /// recursively marks successor nodes dirty.
+ /// \brief If NewDepth is greater than this node's depth value, sets it to
+ /// be the new depth value. This also recursively marks successor nodes
+ /// dirty.
void setDepthToAtLeast(unsigned NewDepth);
- /// setDepthToAtLeast - If NewDepth is greater than this node's
- /// depth value, set it to be the new height value. This also
- /// recursively marks predecessor nodes dirty.
+ /// \brief If NewDepth is greater than this node's depth value, set it to be
+ /// the new height value. This also recursively marks predecessor nodes
+ /// dirty.
void setHeightToAtLeast(unsigned NewHeight);
- /// setDepthDirty - Set a flag in this node to indicate that its
- /// stored Depth value will require recomputation the next time
- /// getDepth() is called.
+ /// \brief Sets a flag in this node to indicate that its stored Depth value
+ /// will require recomputation the next time getDepth() is called.
void setDepthDirty();
- /// setHeightDirty - Set a flag in this node to indicate that its
- /// stored Height value will require recomputation the next time
- /// getHeight() is called.
+ /// \brief Sets a flag in this node to indicate that its stored Height value
+ /// will require recomputation the next time getHeight() is called.
void setHeightDirty();
- /// isPred - Test if node N is a predecessor of this node.
- bool isPred(SUnit *N) {
- for (unsigned i = 0, e = (unsigned)Preds.size(); i != e; ++i)
- if (Preds[i].getSUnit() == N)
+ /// Tests if node N is a predecessor of this node.
+ bool isPred(const SUnit *N) const {
+ for (const SDep &Pred : Preds)
+ if (Pred.getSUnit() == N)
return true;
return false;
}
- /// isSucc - Test if node N is a successor of this node.
- bool isSucc(SUnit *N) {
- for (unsigned i = 0, e = (unsigned)Succs.size(); i != e; ++i)
- if (Succs[i].getSUnit() == N)
+ /// Tests if node N is a successor of this node.
+ bool isSucc(const SUnit *N) const {
+ for (const SDep &Succ : Succs)
+ if (Succ.getSUnit() == N)
return true;
return false;
}
@@ -471,7 +452,7 @@ namespace llvm {
return NumSuccsLeft == 0;
}
- /// \brief Order this node's predecessor edges such that the critical path
+ /// \brief Orders this node's predecessor edges such that the critical path
/// edge occurs first.
void biasCriticalPath();
@@ -484,7 +465,7 @@ namespace llvm {
void ComputeHeight();
};
- /// Return true if the specified SDep is equivalent except for latency.
+ /// Returns true if the specified SDep is equivalent except for latency.
inline bool SDep::overlaps(const SDep &Other) const {
if (Dep != Other.Dep)
return false;
@@ -499,31 +480,33 @@ namespace llvm {
llvm_unreachable("Invalid dependency kind!");
}
- //// getSUnit - Return the SUnit to which this edge points.
+ //// Returns the SUnit to which this edge points.
inline SUnit *SDep::getSUnit() const { return Dep.getPointer(); }
- //// setSUnit - Assign the SUnit to which this edge points.
+ //// Assigns the SUnit to which this edge points.
inline void SDep::setSUnit(SUnit *SU) { Dep.setPointer(SU); }
- /// getKind - Return an enum value representing the kind of the dependence.
+ /// Returns an enum value representing the kind of the dependence.
inline SDep::Kind SDep::getKind() const { return Dep.getInt(); }
//===--------------------------------------------------------------------===//
- /// SchedulingPriorityQueue - This interface is used to plug different
- /// priorities computation algorithms into the list scheduler. It implements
- /// the interface of a standard priority queue, where nodes are inserted in
- /// arbitrary order and returned in priority order. The computation of the
- /// priority and the representation of the queue are totally up to the
- /// implementation to decide.
- ///
+
+ /// \brief This interface is used to plug different priorities computation
+ /// algorithms into the list scheduler. It implements the interface of a
+ /// standard priority queue, where nodes are inserted in arbitrary order and
+ /// returned in priority order. The computation of the priority and the
+ /// representation of the queue are totally up to the implementation to
+ /// decide.
class SchedulingPriorityQueue {
virtual void anchor();
- unsigned CurCycle;
+
+ unsigned CurCycle = 0;
bool HasReadyFilter;
+
public:
- SchedulingPriorityQueue(bool rf = false):
- CurCycle(0), HasReadyFilter(rf) {}
- virtual ~SchedulingPriorityQueue() {}
+ SchedulingPriorityQueue(bool rf = false) : HasReadyFilter(rf) {}
+
+ virtual ~SchedulingPriorityQueue() = default;
virtual bool isBottomUp() const = 0;
@@ -542,6 +525,7 @@ namespace llvm {
assert(!HasReadyFilter && "The ready filter must override isReady()");
return true;
}
+
virtual void push(SUnit *U) = 0;
void push_all(const std::vector<SUnit *> &Nodes) {
@@ -556,10 +540,9 @@ namespace llvm {
virtual void dump(ScheduleDAG *) const {}
- /// scheduledNode - As each node is scheduled, this method is invoked. This
- /// allows the priority function to adjust the priority of related
- /// unscheduled nodes, for example.
- ///
+ /// As each node is scheduled, this method is invoked. This allows the
+ /// priority function to adjust the priority of related unscheduled nodes,
+ /// for example.
virtual void scheduledNode(SUnit *) {}
virtual void unscheduledNode(SUnit *) {}
@@ -575,14 +558,14 @@ namespace llvm {
class ScheduleDAG {
public:
- const TargetMachine &TM; // Target processor
- const TargetInstrInfo *TII; // Target instruction information
- const TargetRegisterInfo *TRI; // Target processor register info
- MachineFunction &MF; // Machine function
- MachineRegisterInfo &MRI; // Virtual/real register map
- std::vector<SUnit> SUnits; // The scheduling units.
- SUnit EntrySU; // Special node for the region entry.
- SUnit ExitSU; // Special node for the region exit.
+ const TargetMachine &TM; ///< Target processor
+ const TargetInstrInfo *TII; ///< Target instruction information
+ const TargetRegisterInfo *TRI; ///< Target processor register info
+ MachineFunction &MF; ///< Machine function
+ MachineRegisterInfo &MRI; ///< Virtual/real register map
+ std::vector<SUnit> SUnits; ///< The scheduling units.
+ SUnit EntrySU; ///< Special node for the region entry.
+ SUnit ExitSU; ///< Special node for the region exit.
#ifdef NDEBUG
static const bool StressSched = false;
@@ -594,43 +577,39 @@ namespace llvm {
virtual ~ScheduleDAG();
- /// clearDAG - clear the DAG state (between regions).
+ /// Clears the DAG state (between regions).
void clearDAG();
- /// getInstrDesc - Return the MCInstrDesc of this SUnit.
- /// Return NULL for SDNodes without a machine opcode.
+ /// Returns the MCInstrDesc of this SUnit.
+ /// Returns NULL for SDNodes without a machine opcode.
const MCInstrDesc *getInstrDesc(const SUnit *SU) const {
if (SU->isInstr()) return &SU->getInstr()->getDesc();
return getNodeDesc(SU->getNode());
}
- /// viewGraph - Pop up a GraphViz/gv window with the ScheduleDAG rendered
- /// using 'dot'.
- ///
+ /// Pops up a GraphViz/gv window with the ScheduleDAG rendered using 'dot'.
virtual void viewGraph(const Twine &Name, const Twine &Title);
virtual void viewGraph();
virtual void dumpNode(const SUnit *SU) const = 0;
- /// getGraphNodeLabel - Return a label for an SUnit node in a visualization
- /// of the ScheduleDAG.
+ /// Returns a label for an SUnit node in a visualization of the ScheduleDAG.
virtual std::string getGraphNodeLabel(const SUnit *SU) const = 0;
- /// getDAGLabel - Return a label for the region of code covered by the DAG.
+ /// Returns a label for the region of code covered by the DAG.
virtual std::string getDAGName() const = 0;
- /// addCustomGraphFeatures - Add custom features for a visualization of
- /// the ScheduleDAG.
+ /// Adds custom features for a visualization of the ScheduleDAG.
virtual void addCustomGraphFeatures(GraphWriter<ScheduleDAG*> &) const {}
#ifndef NDEBUG
- /// VerifyScheduledDAG - Verify that all SUnits were scheduled and that
- /// their state is consistent. Return the number of scheduled SUnits.
+ /// \brief Verifies that all SUnits were scheduled and that their state is
+ /// consistent. Returns the number of scheduled SUnits.
unsigned VerifyScheduledDAG(bool isBottomUp);
#endif
private:
- // Return the MCInstrDesc of this SDNode or NULL.
+ /// Returns the MCInstrDesc of this SDNode or NULL.
const MCInstrDesc *getNodeDesc(const SDNode *Node) const;
};
@@ -640,6 +619,7 @@ namespace llvm {
unsigned Operand;
SUnitIterator(SUnit *N, unsigned Op) : Node(N), Operand(Op) {}
+
public:
bool operator==(const SUnitIterator& x) const {
return Operand == x.Operand;
@@ -666,7 +646,8 @@ namespace llvm {
unsigned getOperand() const { return Operand; }
const SUnit *getNode() const { return Node; }
- /// isCtrlDep - Test if this is not an SDep::Data dependence.
+
+ /// Tests if this is not an SDep::Data dependence.
bool isCtrlDep() const {
return getSDep().isCtrl();
}
@@ -700,56 +681,61 @@ namespace llvm {
}
};
- /// ScheduleDAGTopologicalSort is a class that computes a topological
- /// ordering for SUnits and provides methods for dynamically updating
- /// the ordering as new edges are added.
+ /// This class can compute a topological ordering for SUnits and provides
+ /// methods for dynamically updating the ordering as new edges are added.
///
/// This allows a very fast implementation of IsReachable, for example.
- ///
class ScheduleDAGTopologicalSort {
- /// SUnits - A reference to the ScheduleDAG's SUnits.
+ /// A reference to the ScheduleDAG's SUnits.
std::vector<SUnit> &SUnits;
SUnit *ExitSU;
- /// Index2Node - Maps topological index to the node number.
+ /// Maps topological index to the node number.
std::vector<int> Index2Node;
- /// Node2Index - Maps the node number to its topological index.
+ /// Maps the node number to its topological index.
std::vector<int> Node2Index;
- /// Visited - a set of nodes visited during a DFS traversal.
+ /// a set of nodes visited during a DFS traversal.
BitVector Visited;
- /// DFS - make a DFS traversal and mark all nodes affected by the
- /// edge insertion. These nodes will later get new topological indexes
- /// by means of the Shift method.
+ /// Makes a DFS traversal and mark all nodes affected by the edge insertion.
+ /// These nodes will later get new topological indexes by means of the Shift
+ /// method.
void DFS(const SUnit *SU, int UpperBound, bool& HasLoop);
- /// Shift - reassign topological indexes for the nodes in the DAG
- /// to preserve the topological ordering.
+ /// \brief Reassigns topological indexes for the nodes in the DAG to
+ /// preserve the topological ordering.
void Shift(BitVector& Visited, int LowerBound, int UpperBound);
- /// Allocate - assign the topological index to the node n.
+ /// Assigns the topological index to the node n.
void Allocate(int n, int index);
public:
ScheduleDAGTopologicalSort(std::vector<SUnit> &SUnits, SUnit *ExitSU);
- /// InitDAGTopologicalSorting - create the initial topological
- /// ordering from the DAG to be scheduled.
+ /// Creates the initial topological ordering from the DAG to be scheduled.
void InitDAGTopologicalSorting();
- /// IsReachable - Checks if SU is reachable from TargetSU.
+ /// Returns an array of SUs that are both in the successor
+ /// subtree of StartSU and in the predecessor subtree of TargetSU.
+ /// StartSU and TargetSU are not in the array.
+ /// Success is false if TargetSU is not in the successor subtree of
+ /// StartSU, else it is true.
+ std::vector<int> GetSubGraph(const SUnit &StartSU, const SUnit &TargetSU,
+ bool &Success);
+
+ /// Checks if \p SU is reachable from \p TargetSU.
bool IsReachable(const SUnit *SU, const SUnit *TargetSU);
- /// WillCreateCycle - Return true if addPred(TargetSU, SU) creates a cycle.
+ /// Returns true if addPred(TargetSU, SU) creates a cycle.
bool WillCreateCycle(SUnit *TargetSU, SUnit *SU);
- /// AddPred - Updates the topological ordering to accommodate an edge
- /// to be added from SUnit X to SUnit Y.
+ /// \brief Updates the topological ordering to accommodate an edge to be
+ /// added from SUnit \p X to SUnit \p Y.
void AddPred(SUnit *Y, SUnit *X);
- /// RemovePred - Updates the topological ordering to accommodate an
- /// an edge to be removed from the specified node N from the predecessors
- /// of the current node M.
+ /// \brief Updates the topological ordering to accommodate an an edge to be
+ /// removed from the specified node \p N from the predecessors of the
+ /// current node \p M.
void RemovePred(SUnit *M, SUnit *N);
typedef std::vector<int>::iterator iterator;
@@ -766,6 +752,7 @@ namespace llvm {
reverse_iterator rend() { return Index2Node.rend(); }
const_reverse_iterator rend() const { return Index2Node.rend(); }
};
-}
-#endif
+} // end namespace llvm
+
+#endif // LLVM_CODEGEN_SCHEDULEDAG_H
diff --git a/include/llvm/CodeGen/ScheduleDAGInstrs.h b/include/llvm/CodeGen/ScheduleDAGInstrs.h
index 2746765f6e45..21e1740aa6b8 100644
--- a/include/llvm/CodeGen/ScheduleDAGInstrs.h
+++ b/include/llvm/CodeGen/ScheduleDAGInstrs.h
@@ -7,8 +7,8 @@
//
//===----------------------------------------------------------------------===//
//
-// This file implements the ScheduleDAGInstrs class, which implements
-// scheduling for a MachineInstr-based dependency graph.
+/// \file Implements the ScheduleDAGInstrs class, which implements scheduling
+/// for a MachineInstr-based dependency graph.
//
//===----------------------------------------------------------------------===//
@@ -95,8 +95,7 @@ namespace llvm {
};
typedef SmallVector<UnderlyingObject, 4> UnderlyingObjectsVector;
- /// ScheduleDAGInstrs - A ScheduleDAG subclass for scheduling lists of
- /// MachineInstrs.
+ /// A ScheduleDAG for scheduling lists of MachineInstr.
class ScheduleDAGInstrs : public ScheduleDAG {
protected:
const MachineLoopInfo *MLI;
@@ -119,8 +118,8 @@ namespace llvm {
/// Whether lane masks should get tracked.
bool TrackLaneMasks;
- /// State specific to the current scheduling region.
- /// ------------------------------------------------
+ // State specific to the current scheduling region.
+ // ------------------------------------------------
/// The block in which to insert instructions
MachineBasicBlock *BB;
@@ -138,8 +137,8 @@ namespace llvm {
/// scheduling region is mapped to an SUnit.
DenseMap<MachineInstr*, SUnit*> MISUnitMap;
- /// State internal to DAG building.
- /// -------------------------------
+ // State internal to DAG building.
+ // -------------------------------
/// Defs, Uses - Remember where defs and uses of each register are as we
/// iterate upward through the instructions. This is allocated here instead
@@ -163,64 +162,64 @@ namespace llvm {
SUnit *BarrierChain;
public:
-
/// A list of SUnits, used in Value2SUsMap, during DAG construction.
/// Note: to gain speed it might be worth investigating an optimized
/// implementation of this data structure, such as a singly linked list
/// with a memory pool (SmallVector was tried but slow and SparseSet is not
/// applicable).
typedef std::list<SUnit *> SUList;
+
protected:
- /// A map from ValueType to SUList, used during DAG construction,
- /// as a means of remembering which SUs depend on which memory
- /// locations.
+ /// \brief A map from ValueType to SUList, used during DAG construction, as
+ /// a means of remembering which SUs depend on which memory locations.
class Value2SUsMap;
- /// Remove in FIFO order some SUs from huge maps.
+ /// Reduces maps in FIFO order, by N SUs. This is better than turning
+ /// every Nth memory SU into BarrierChain in buildSchedGraph(), since
+ /// it avoids unnecessary edges between seen SUs above the new BarrierChain,
+ /// and those below it.
void reduceHugeMemNodeMaps(Value2SUsMap &stores,
Value2SUsMap &loads, unsigned N);
- /// Add a chain edge between SUa and SUb, but only if both AliasAnalysis
- /// and Target fail to deny the dependency.
+ /// \brief Adds a chain edge between SUa and SUb, but only if both
+ /// AliasAnalysis and Target fail to deny the dependency.
void addChainDependency(SUnit *SUa, SUnit *SUb,
unsigned Latency = 0);
- /// Add dependencies as needed from all SUs in list to SU.
- void addChainDependencies(SUnit *SU, SUList &sus, unsigned Latency) {
- for (auto *su : sus)
- addChainDependency(SU, su, Latency);
+ /// Adds dependencies as needed from all SUs in list to SU.
+ void addChainDependencies(SUnit *SU, SUList &SUs, unsigned Latency) {
+ for (SUnit *Entry : SUs)
+ addChainDependency(SU, Entry, Latency);
}
- /// Add dependencies as needed from all SUs in map, to SU.
+ /// Adds dependencies as needed from all SUs in map, to SU.
void addChainDependencies(SUnit *SU, Value2SUsMap &Val2SUsMap);
- /// Add dependencies as needed to SU, from all SUs mapped to V.
+ /// Adds dependencies as needed to SU, from all SUs mapped to V.
void addChainDependencies(SUnit *SU, Value2SUsMap &Val2SUsMap,
ValueType V);
- /// Add barrier chain edges from all SUs in map, and then clear
- /// the map. This is equivalent to insertBarrierChain(), but
- /// optimized for the common case where the new BarrierChain (a
- /// global memory object) has a higher NodeNum than all SUs in
- /// map. It is assumed BarrierChain has been set before calling
- /// this.
+ /// Adds barrier chain edges from all SUs in map, and then clear the map.
+ /// This is equivalent to insertBarrierChain(), but optimized for the common
+ /// case where the new BarrierChain (a global memory object) has a higher
+ /// NodeNum than all SUs in map. It is assumed BarrierChain has been set
+ /// before calling this.
void addBarrierChain(Value2SUsMap &map);
- /// Insert a barrier chain in a huge region, far below current
- /// SU. Add barrier chain edges from all SUs in map with higher
- /// NodeNums than this new BarrierChain, and remove them from
- /// map. It is assumed BarrierChain has been set before calling
- /// this.
+ /// Inserts a barrier chain in a huge region, far below current SU.
+ /// Adds barrier chain edges from all SUs in map with higher NodeNums than
+ /// this new BarrierChain, and remove them from map. It is assumed
+ /// BarrierChain has been set before calling this.
void insertBarrierChain(Value2SUsMap &map);
/// For an unanalyzable memory access, this Value is used in maps.
UndefValue *UnknownValue;
- /// DbgValues - Remember instruction that precedes DBG_VALUE.
+ typedef std::vector<std::pair<MachineInstr *, MachineInstr *>>
+ DbgValueVector;
+ /// Remember instruction that precedes DBG_VALUE.
/// These are generated by buildSchedGraph but persist so they can be
/// referenced when emitting the final schedule.
- typedef std::vector<std::pair<MachineInstr *, MachineInstr *> >
- DbgValueVector;
DbgValueVector DbgValues;
MachineInstr *FirstDbgValue;
@@ -234,81 +233,86 @@ namespace llvm {
~ScheduleDAGInstrs() override {}
- /// \brief Get the machine model for instruction scheduling.
+ /// Gets the machine model for instruction scheduling.
const TargetSchedModel *getSchedModel() const { return &SchedModel; }
- /// \brief Resolve and cache a resolved scheduling class for an SUnit.
+ /// Resolves and cache a resolved scheduling class for an SUnit.
const MCSchedClassDesc *getSchedClass(SUnit *SU) const {
if (!SU->SchedClass && SchedModel.hasInstrSchedModel())
SU->SchedClass = SchedModel.resolveSchedClass(SU->getInstr());
return SU->SchedClass;
}
- /// begin - Return an iterator to the top of the current scheduling region.
+ /// Returns an iterator to the top of the current scheduling region.
MachineBasicBlock::iterator begin() const { return RegionBegin; }
- /// end - Return an iterator to the bottom of the current scheduling region.
+ /// Returns an iterator to the bottom of the current scheduling region.
MachineBasicBlock::iterator end() const { return RegionEnd; }
- /// newSUnit - Creates a new SUnit and return a ptr to it.
+ /// Creates a new SUnit and return a ptr to it.
SUnit *newSUnit(MachineInstr *MI);
- /// getSUnit - Return an existing SUnit for this MI, or NULL.
+ /// Returns an existing SUnit for this MI, or nullptr.
SUnit *getSUnit(MachineInstr *MI) const;
- /// startBlock - Prepare to perform scheduling in the given block.
+ /// Prepares to perform scheduling in the given block.
virtual void startBlock(MachineBasicBlock *BB);
- /// finishBlock - Clean up after scheduling in the given block.
+ /// Cleans up after scheduling in the given block.
virtual void finishBlock();
- /// Initialize the scheduler state for the next scheduling region.
+ /// \brief Initialize the DAG and common scheduler state for a new
+ /// scheduling region. This does not actually create the DAG, only clears
+ /// it. The scheduling driver may call BuildSchedGraph multiple times per
+ /// scheduling region.
virtual void enterRegion(MachineBasicBlock *bb,
MachineBasicBlock::iterator begin,
MachineBasicBlock::iterator end,
unsigned regioninstrs);
- /// Notify that the scheduler has finished scheduling the current region.
+ /// Called when the scheduler has finished scheduling the current region.
virtual void exitRegion();
- /// buildSchedGraph - Build SUnits from the MachineBasicBlock that we are
- /// input.
+ /// Builds SUnits for the current region.
+ /// If \p RPTracker is non-null, compute register pressure as a side effect.
+ /// The DAG builder is an efficient place to do it because it already visits
+ /// operands.
void buildSchedGraph(AliasAnalysis *AA,
RegPressureTracker *RPTracker = nullptr,
PressureDiffs *PDiffs = nullptr,
LiveIntervals *LIS = nullptr,
bool TrackLaneMasks = false);
- /// addSchedBarrierDeps - Add dependencies from instructions in the current
- /// list of instructions being scheduled to scheduling barrier. We want to
- /// make sure instructions which define registers that are either used by
- /// the terminator or are live-out are properly scheduled. This is
- /// especially important when the definition latency of the return value(s)
- /// are too high to be hidden by the branch or when the liveout registers
- /// used by instructions in the fallthrough block.
+ /// \brief Adds dependencies from instructions in the current list of
+ /// instructions being scheduled to scheduling barrier. We want to make sure
+ /// instructions which define registers that are either used by the
+ /// terminator or are live-out are properly scheduled. This is especially
+ /// important when the definition latency of the return value(s) are too
+ /// high to be hidden by the branch or when the liveout registers used by
+ /// instructions in the fallthrough block.
void addSchedBarrierDeps();
- /// schedule - Order nodes according to selected style, filling
- /// in the Sequence member.
+ /// Orders nodes according to selected style.
///
/// Typically, a scheduling algorithm will implement schedule() without
/// overriding enterRegion() or exitRegion().
virtual void schedule() = 0;
- /// finalizeSchedule - Allow targets to perform final scheduling actions at
- /// the level of the whole MachineFunction. By default does nothing.
+ /// Allow targets to perform final scheduling actions at the level of the
+ /// whole MachineFunction. By default does nothing.
virtual void finalizeSchedule() {}
void dumpNode(const SUnit *SU) const override;
- /// Return a label for a DAG node that points to an instruction.
+ /// Returns a label for a DAG node that points to an instruction.
std::string getGraphNodeLabel(const SUnit *SU) const override;
- /// Return a label for the region of code covered by the DAG.
+ /// Returns a label for the region of code covered by the DAG.
std::string getDAGName() const override;
- /// \brief Fix register kill flags that scheduling has made invalid.
+ /// Fixes register kill flags that scheduling has made invalid.
void fixupKills(MachineBasicBlock *MBB);
+
protected:
void initSUnits();
void addPhysRegDataDeps(SUnit *SU, unsigned OperIdx);
@@ -316,21 +320,22 @@ namespace llvm {
void addVRegDefDeps(SUnit *SU, unsigned OperIdx);
void addVRegUseDeps(SUnit *SU, unsigned OperIdx);
- /// \brief PostRA helper for rewriting kill flags.
+ /// Initializes register live-range state for updating kills.
+ /// PostRA helper for rewriting kill flags.
void startBlockForKills(MachineBasicBlock *BB);
- /// \brief Toggle a register operand kill flag.
+ /// Toggles a register operand kill flag.
///
/// Other adjustments may be made to the instruction if necessary. Return
/// true if the operand has been deleted, false if not.
- bool toggleKillFlag(MachineInstr *MI, MachineOperand &MO);
+ void toggleKillFlag(MachineInstr &MI, MachineOperand &MO);
/// Returns a mask for which lanes get read/written by the given (register)
/// machine operand.
LaneBitmask getLaneMaskForMO(const MachineOperand &MO) const;
};
- /// newSUnit - Creates a new SUnit and return a ptr to it.
+ /// Creates a new SUnit and return a ptr to it.
inline SUnit *ScheduleDAGInstrs::newSUnit(MachineInstr *MI) {
#ifndef NDEBUG
const SUnit *Addr = SUnits.empty() ? nullptr : &SUnits[0];
@@ -341,13 +346,13 @@ namespace llvm {
return &SUnits.back();
}
- /// getSUnit - Return an existing SUnit for this MI, or NULL.
+ /// Returns an existing SUnit for this MI, or nullptr.
inline SUnit *ScheduleDAGInstrs::getSUnit(MachineInstr *MI) const {
DenseMap<MachineInstr*, SUnit*>::const_iterator I = MISUnitMap.find(MI);
if (I == MISUnitMap.end())
return nullptr;
return I->second;
}
-} // namespace llvm
+} // end namespace llvm
#endif
diff --git a/include/llvm/CodeGen/ScheduleDAGMutation.h b/include/llvm/CodeGen/ScheduleDAGMutation.h
index 02fe2294815c..5c236427e0b8 100644
--- a/include/llvm/CodeGen/ScheduleDAGMutation.h
+++ b/include/llvm/CodeGen/ScheduleDAGMutation.h
@@ -1,4 +1,4 @@
-//==- ScheduleDAGMutation.h - MachineInstr Scheduling ------------*- C++ -*-==//
+//===- ScheduleDAGMutation.h - MachineInstr Scheduling ----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -16,16 +16,19 @@
#define LLVM_CODEGEN_SCHEDULEDAGMUTATION_H
namespace llvm {
- class ScheduleDAGInstrs;
- /// Mutate the DAG as a postpass after normal DAG building.
- class ScheduleDAGMutation {
- virtual void anchor();
- public:
- virtual ~ScheduleDAGMutation() {}
+class ScheduleDAGInstrs;
- virtual void apply(ScheduleDAGInstrs *DAG) = 0;
- };
-}
+/// Mutate the DAG as a postpass after normal DAG building.
+class ScheduleDAGMutation {
+ virtual void anchor();
-#endif
+public:
+ virtual ~ScheduleDAGMutation() = default;
+
+ virtual void apply(ScheduleDAGInstrs *DAG) = 0;
+};
+
+} // end namespace llvm
+
+#endif // LLVM_CODEGEN_SCHEDULEDAGMUTATION_H
diff --git a/include/llvm/CodeGen/ScheduleDFS.h b/include/llvm/CodeGen/ScheduleDFS.h
index b2108ad3bedb..c2013661cfff 100644
--- a/include/llvm/CodeGen/ScheduleDFS.h
+++ b/include/llvm/CodeGen/ScheduleDFS.h
@@ -14,16 +14,16 @@
#ifndef LLVM_CODEGEN_SCHEDULEDFS_H
#define LLVM_CODEGEN_SCHEDULEDFS_H
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/CodeGen/ScheduleDAG.h"
-#include "llvm/Support/DataTypes.h"
#include <vector>
+#include <cassert>
+#include <cstdint>
namespace llvm {
class raw_ostream;
-class IntEqClasses;
-class ScheduleDAGInstrs;
-class SUnit;
/// \brief Represent the ILP of the subDAG rooted at a DAG node.
///
@@ -75,18 +75,18 @@ class SchedDFSResult {
/// interior node. Finally, it is set to a representative subtree ID during
/// finalization.
struct NodeData {
- unsigned InstrCount;
- unsigned SubtreeID;
+ unsigned InstrCount = 0;
+ unsigned SubtreeID = InvalidSubtreeID;
- NodeData(): InstrCount(0), SubtreeID(InvalidSubtreeID) {}
+ NodeData() = default;
};
/// \brief Per-Subtree data computed during DFS.
struct TreeData {
- unsigned ParentTreeID;
- unsigned SubInstrCount;
+ unsigned ParentTreeID = InvalidSubtreeID;
+ unsigned SubInstrCount = 0;
- TreeData(): ParentTreeID(InvalidSubtreeID), SubInstrCount(0) {}
+ TreeData() = default;
};
/// \brief Record a connection between subtrees and the connection level.
@@ -107,7 +107,7 @@ class SchedDFSResult {
// For each subtree discovered during DFS, record its connections to other
// subtrees.
- std::vector<SmallVector<Connection, 4> > SubtreeConnections;
+ std::vector<SmallVector<Connection, 4>> SubtreeConnections;
/// Cache the current connection level of each subtree.
/// This mutable array is updated during scheduling.
@@ -189,6 +189,6 @@ public:
raw_ostream &operator<<(raw_ostream &OS, const ILPValue &Val);
-} // namespace llvm
+} // end namespace llvm
-#endif
+#endif // LLVM_CODEGEN_SCHEDULEDFS_H
diff --git a/include/llvm/CodeGen/ScheduleHazardRecognizer.h b/include/llvm/CodeGen/ScheduleHazardRecognizer.h
index 214be2794ba3..ace4a2d836ca 100644
--- a/include/llvm/CodeGen/ScheduleHazardRecognizer.h
+++ b/include/llvm/CodeGen/ScheduleHazardRecognizer.h
@@ -29,10 +29,10 @@ protected:
/// state. Important to restore the state after backtracking. Additionally,
/// MaxLookAhead=0 identifies a fake recognizer, allowing the client to
/// bypass virtual calls. Currently the PostRA scheduler ignores it.
- unsigned MaxLookAhead;
+ unsigned MaxLookAhead = 0;
public:
- ScheduleHazardRecognizer(): MaxLookAhead(0) {}
+ ScheduleHazardRecognizer() = default;
virtual ~ScheduleHazardRecognizer();
enum HazardType {
@@ -117,6 +117,6 @@ public:
}
};
-}
+} // end namespace llvm
-#endif
+#endif // LLVM_CODEGEN_SCHEDULEHAZARDRECOGNIZER_H
diff --git a/include/llvm/CodeGen/ScoreboardHazardRecognizer.h b/include/llvm/CodeGen/ScoreboardHazardRecognizer.h
index e0c30fe4d82a..466ab532030c 100644
--- a/include/llvm/CodeGen/ScoreboardHazardRecognizer.h
+++ b/include/llvm/CodeGen/ScoreboardHazardRecognizer.h
@@ -17,8 +17,8 @@
#define LLVM_CODEGEN_SCOREBOARDHAZARDRECOGNIZER_H
#include "llvm/CodeGen/ScheduleHazardRecognizer.h"
-#include "llvm/Support/DataTypes.h"
#include <cassert>
+#include <cstddef>
#include <cstring>
namespace llvm {
@@ -38,21 +38,25 @@ class ScoreboardHazardRecognizer : public ScheduleHazardRecognizer {
// bottom-up scheduler, then the scoreboard cycles are the inverse of the
// scheduler's cycles.
class Scoreboard {
- unsigned *Data;
+ unsigned *Data = nullptr;
// The maximum number of cycles monitored by the Scoreboard. This
// value is determined based on the target itineraries to ensure
// that all hazards can be tracked.
- size_t Depth;
+ size_t Depth = 0;
+
// Indices into the Scoreboard that represent the current cycle.
- size_t Head;
+ size_t Head = 0;
+
public:
- Scoreboard():Data(nullptr), Depth(0), Head(0) { }
+ Scoreboard() = default;
+
~Scoreboard() {
delete[] Data;
}
size_t getDepth() const { return Depth; }
+
unsigned& operator[](size_t idx) const {
// Depth is expected to be a power-of-2.
assert(Depth && !(Depth & (Depth - 1)) &&
@@ -93,10 +97,10 @@ class ScoreboardHazardRecognizer : public ScheduleHazardRecognizer {
const ScheduleDAG *DAG;
/// IssueWidth - Max issue per cycle. 0=Unknown.
- unsigned IssueWidth;
+ unsigned IssueWidth = 0;
/// IssueCount - Count instructions issued in this cycle.
- unsigned IssueCount;
+ unsigned IssueCount = 0;
Scoreboard ReservedScoreboard;
Scoreboard RequiredScoreboard;
@@ -119,6 +123,6 @@ public:
void RecedeCycle() override;
};
-}
+} // end namespace llvm
-#endif //!LLVM_CODEGEN_SCOREBOARDHAZARDRECOGNIZER_H
+#endif // LLVM_CODEGEN_SCOREBOARDHAZARDRECOGNIZER_H
diff --git a/include/llvm/CodeGen/SelectionDAG.h b/include/llvm/CodeGen/SelectionDAG.h
index 54d0436e4ab8..6f0509543e7d 100644
--- a/include/llvm/CodeGen/SelectionDAG.h
+++ b/include/llvm/CodeGen/SelectionDAG.h
@@ -36,6 +36,7 @@ namespace llvm {
class MachineConstantPoolValue;
class MachineFunction;
class MDNode;
+class OptimizationRemarkEmitter;
class SDDbgValue;
class TargetLowering;
class SelectionDAGTargetInfo;
@@ -171,6 +172,10 @@ class SelectionDAG {
LLVMContext *Context;
CodeGenOpt::Level OptLevel;
+ /// The function-level optimization remark emitter. Used to emit remarks
+ /// whenever manipulating the DAG.
+ OptimizationRemarkEmitter *ORE;
+
/// The starting token.
SDNode EntryNode;
@@ -239,7 +244,7 @@ public:
std::function<void(SDNode *, SDNode *)> Callback;
DAGNodeDeletedListener(SelectionDAG &DAG,
std::function<void(SDNode *, SDNode *)> Callback)
- : DAGUpdateListener(DAG), Callback(Callback) {}
+ : DAGUpdateListener(DAG), Callback(std::move(Callback)) {}
void NodeDeleted(SDNode *N, SDNode *E) override { Callback(N, E); }
};
@@ -318,7 +323,7 @@ public:
~SelectionDAG();
/// Prepare this SelectionDAG to process code in the given MachineFunction.
- void init(MachineFunction &mf);
+ void init(MachineFunction &NewMF, OptimizationRemarkEmitter &NewORE);
/// Clear state and free memory necessary to make this
/// SelectionDAG ready to process a new block.
@@ -331,6 +336,7 @@ public:
const TargetLowering &getTargetLoweringInfo() const { return *TLI; }
const SelectionDAGTargetInfo &getSelectionDAGInfo() const { return *TSI; }
LLVMContext *getContext() const {return Context; }
+ OptimizationRemarkEmitter &getORE() const { return *ORE; }
/// Pop up a GraphViz/gv window with the DAG rendered using 'dot'.
void viewGraph(const std::string &Title);
@@ -480,6 +486,13 @@ public:
bool isTarget = false, bool isOpaque = false);
SDValue getConstant(const APInt &Val, const SDLoc &DL, EVT VT,
bool isTarget = false, bool isOpaque = false);
+
+ SDValue getAllOnesConstant(const SDLoc &DL, EVT VT, bool IsTarget = false,
+ bool IsOpaque = false) {
+ return getConstant(APInt::getAllOnesValue(VT.getScalarSizeInBits()), DL,
+ VT, IsTarget, IsOpaque);
+ }
+
SDValue getConstant(const ConstantInt &Val, const SDLoc &DL, EVT VT,
bool isTarget = false, bool isOpaque = false);
SDValue getIntPtrConstant(uint64_t Val, const SDLoc &DL,
@@ -733,6 +746,9 @@ public:
return getNode(ISD::CALLSEQ_END, DL, NodeTys, Ops);
}
+ /// Return true if the result of this operation is always undefined.
+ bool isUndef(unsigned Opcode, ArrayRef<SDValue> Ops);
+
/// Return an UNDEF node. UNDEF does not have a useful SDLoc.
SDValue getUNDEF(EVT VT) {
return getNode(ISD::UNDEF, SDLoc(), VT);
@@ -1274,6 +1290,19 @@ public:
void computeKnownBits(SDValue Op, APInt &KnownZero, APInt &KnownOne,
const APInt &DemandedElts, unsigned Depth = 0) const;
+ /// Used to represent the possible overflow behavior of an operation.
+ /// Never: the operation cannot overflow.
+ /// Always: the operation will always overflow.
+ /// Sometime: the operation may or may not overflow.
+ enum OverflowKind {
+ OFK_Never,
+ OFK_Sometime,
+ OFK_Always,
+ };
+
+ /// Determine if the result of the addition of 2 node can overflow.
+ OverflowKind computeOverflowKind(SDValue N0, SDValue N1) const;
+
/// Test if the given value is known to have exactly one bit set. This differs
/// from computeKnownBits in that it doesn't necessarily determine which bit
/// is set.
@@ -1288,6 +1317,17 @@ public:
/// target nodes to be understood.
unsigned ComputeNumSignBits(SDValue Op, unsigned Depth = 0) const;
+ /// 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 the top 3 bits are all equal
+ /// to each other, so we return 3. The DemandedElts argument allows
+ /// us to only collect the minimum sign bits of the requested vector elements.
+ /// Targets can implement the ComputeNumSignBitsForTarget method in the
+ /// TargetLowering class to allow target nodes to be understood.
+ unsigned ComputeNumSignBits(SDValue Op, const APInt &DemandedElts,
+ unsigned Depth = 0) const;
+
/// 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
diff --git a/include/llvm/CodeGen/SelectionDAGISel.h b/include/llvm/CodeGen/SelectionDAGISel.h
index 61d7ec4ecf5b..591b2f773344 100644
--- a/include/llvm/CodeGen/SelectionDAGISel.h
+++ b/include/llvm/CodeGen/SelectionDAGISel.h
@@ -20,6 +20,7 @@
#include "llvm/IR/BasicBlock.h"
#include "llvm/Pass.h"
#include "llvm/Target/TargetSubtargetInfo.h"
+#include <memory>
namespace llvm {
class FastISel;
@@ -29,6 +30,7 @@ namespace llvm {
class MachineBasicBlock;
class MachineFunction;
class MachineInstr;
+ class OptimizationRemarkEmitter;
class TargetLowering;
class TargetLibraryInfo;
class FunctionLoweringInfo;
@@ -53,6 +55,12 @@ public:
CodeGenOpt::Level OptLevel;
const TargetInstrInfo *TII;
const TargetLowering *TLI;
+ bool FastISelFailed;
+ SmallPtrSet<const Instruction *, 4> ElidedArgCopyInstrs;
+
+ /// Current optimization remark emitter.
+ /// Used to report things like combines and FastISel failures.
+ std::unique_ptr<OptimizationRemarkEmitter> ORE;
static char ID;
@@ -151,7 +159,9 @@ public:
OPC_MorphNodeTo,
// Space-optimized forms that implicitly encode number of result VTs.
OPC_MorphNodeTo0, OPC_MorphNodeTo1, OPC_MorphNodeTo2,
- OPC_CompleteMatch
+ OPC_CompleteMatch,
+ // Contains offset in table for pattern being selected
+ OPC_Coverage
};
enum {
@@ -213,6 +223,15 @@ protected:
void SelectInlineAsmMemoryOperands(std::vector<SDValue> &Ops,
const SDLoc &DL);
+ /// getPatternForIndex - Patterns selected by tablegen during ISEL
+ virtual StringRef getPatternForIndex(unsigned index) {
+ llvm_unreachable("Tblgen should generate the implementation of this!");
+ }
+
+ /// getIncludePathForIndex - get the td source location of pattern instantiation
+ virtual StringRef getIncludePathForIndex(unsigned index) {
+ llvm_unreachable("Tblgen should generate the implementation of this!");
+ }
public:
// Calls to these predicates are generated by tblgen.
bool CheckAndMask(SDValue LHS, ConstantSDNode *RHS,
@@ -270,6 +289,8 @@ private:
SDNode *MorphNode(SDNode *Node, unsigned TargetOpc, SDVTList VTs,
ArrayRef<SDValue> Ops, unsigned EmitNodeInfo);
+ SDNode *MutateStrictFPToFP(SDNode *Node, unsigned NewOpc);
+
/// 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.
diff --git a/include/llvm/CodeGen/SelectionDAGNodes.h b/include/llvm/CodeGen/SelectionDAGNodes.h
index b6f5424dbbd7..81cc0b39cf87 100644
--- a/include/llvm/CodeGen/SelectionDAGNodes.h
+++ b/include/llvm/CodeGen/SelectionDAGNodes.h
@@ -1,4 +1,4 @@
-//===-- llvm/CodeGen/SelectionDAGNodes.h - SelectionDAG Nodes ---*- C++ -*-===//
+//===- llvm/CodeGen/SelectionDAGNodes.h - SelectionDAG Nodes ----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -118,11 +118,11 @@ namespace ISD {
class SDValue {
friend struct DenseMapInfo<SDValue>;
- SDNode *Node; // The node defining the value we are using.
- unsigned ResNo; // Which return value of the node we are using.
+ SDNode *Node = nullptr; // The node defining the value we are using.
+ unsigned ResNo = 0; // Which return value of the node we are using.
public:
- SDValue() : Node(nullptr), ResNo(0) {}
+ SDValue() = default;
SDValue(SDNode *node, unsigned resno);
/// get the index which selects a specific result in the SDNode
@@ -250,16 +250,16 @@ class SDUse {
/// Val - The value being used.
SDValue Val;
/// User - The user of this value.
- SDNode *User;
+ SDNode *User = nullptr;
/// Prev, Next - Pointers to the uses list of the SDNode referred by
/// this operand.
- SDUse **Prev, *Next;
-
- SDUse(const SDUse &U) = delete;
- void operator=(const SDUse &U) = delete;
+ SDUse **Prev = nullptr;
+ SDUse *Next = nullptr;
public:
- SDUse() : User(nullptr), Prev(nullptr), Next(nullptr) {}
+ SDUse() = default;
+ SDUse(const SDUse &U) = delete;
+ SDUse &operator=(const SDUse &) = delete;
/// Normally SDUse will just implicitly convert to an SDValue that it holds.
operator const SDValue&() const { return Val; }
@@ -350,20 +350,15 @@ private:
bool NoSignedZeros : 1;
bool AllowReciprocal : 1;
bool VectorReduction : 1;
+ bool AllowContract : 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;
- VectorReduction = false;
- }
+ SDNodeFlags()
+ : NoUnsignedWrap(false), NoSignedWrap(false), Exact(false),
+ UnsafeAlgebra(false), NoNaNs(false), NoInfs(false),
+ NoSignedZeros(false), AllowReciprocal(false), VectorReduction(false),
+ AllowContract(false) {}
// These are mutators for each flag.
void setNoUnsignedWrap(bool b) { NoUnsignedWrap = b; }
@@ -375,6 +370,7 @@ public:
void setNoSignedZeros(bool b) { NoSignedZeros = b; }
void setAllowReciprocal(bool b) { AllowReciprocal = b; }
void setVectorReduction(bool b) { VectorReduction = b; }
+ void setAllowContract(bool b) { AllowContract = b; }
// These are accessors for each flag.
bool hasNoUnsignedWrap() const { return NoUnsignedWrap; }
@@ -386,6 +382,7 @@ public:
bool hasNoSignedZeros() const { return NoSignedZeros; }
bool hasAllowReciprocal() const { return AllowReciprocal; }
bool hasVectorReduction() const { return VectorReduction; }
+ bool hasAllowContract() const { return AllowContract; }
/// Clear any flags in this flag set that aren't also set in Flags.
void intersectWith(const SDNodeFlags *Flags) {
@@ -397,6 +394,8 @@ public:
NoInfs &= Flags->NoInfs;
NoSignedZeros &= Flags->NoSignedZeros;
AllowReciprocal &= Flags->AllowReciprocal;
+ VectorReduction &= Flags->VectorReduction;
+ AllowContract &= Flags->AllowContract;
}
};
@@ -446,6 +445,7 @@ protected:
class LSBaseSDNodeBitfields {
friend class LSBaseSDNode;
+
uint16_t : NumMemSDNodeBits;
uint16_t AddressingMode : 3; // enum ISD::MemIndexedMode
@@ -493,21 +493,26 @@ protected:
static_assert(sizeof(StoreSDNodeBitfields) <= 2, "field too wide");
private:
+ friend class SelectionDAG;
+ // TODO: unfriend HandleSDNode once we fix its operand handling.
+ friend class HandleSDNode;
+
/// Unique id per SDNode in the DAG.
- int NodeId;
+ int NodeId = -1;
/// The values that are used by this operation.
- SDUse *OperandList;
+ SDUse *OperandList = nullptr;
/// The types of the values this node defines. SDNode's may
/// define multiple values simultaneously.
const EVT *ValueList;
/// List of uses for this SDNode.
- SDUse *UseList;
+ SDUse *UseList = nullptr;
/// The number of entries in the Operand/Value list.
- unsigned short NumOperands, NumValues;
+ unsigned short NumOperands = 0;
+ unsigned short NumValues;
// The ordering of the SDNodes. It roughly corresponds to the ordering of the
// original LLVM instructions.
@@ -522,10 +527,6 @@ private:
/// Return a pointer to the specified value type.
static const EVT *getValueTypeList(EVT VT);
- friend class SelectionDAG;
- // TODO: unfriend HandleSDNode once we fix its operand handling.
- friend class HandleSDNode;
-
public:
/// Unique and persistent id per SDNode in the DAG.
/// Used for debug printing.
@@ -616,10 +617,10 @@ public:
/// operands that use a specific SDNode.
class use_iterator
: public std::iterator<std::forward_iterator_tag, SDUse, ptrdiff_t> {
- SDUse *Op;
-
friend class SDNode;
+ SDUse *Op = nullptr;
+
explicit use_iterator(SDUse *op) : Op(op) {}
public:
@@ -628,8 +629,8 @@ public:
typedef std::iterator<std::forward_iterator_tag,
SDUse, ptrdiff_t>::pointer pointer;
+ use_iterator() = default;
use_iterator(const use_iterator &I) : Op(I.Op) {}
- use_iterator() : Op(nullptr) {}
bool operator==(const use_iterator &x) const {
return Op == x.Op;
@@ -737,11 +738,15 @@ public:
return false;
}
+ /// Return true if all the users of N are contained in Nodes.
+ /// NOTE: Requires at least one match, but doesn't require them all.
+ static bool areOnlyUsersOf(ArrayRef<const SDNode *> Nodes, const SDNode *N);
+
/// Return the number of values used by this operation.
unsigned getNumOperands() const { return NumOperands; }
/// Helper method returns the integer value of a ConstantSDNode operand.
- uint64_t getConstantOperandVal(unsigned Num) const;
+ inline uint64_t getConstantOperandVal(unsigned Num) const;
const SDValue &getOperand(unsigned Num) const {
assert(Num < NumOperands && "Invalid child # of SDNode!");
@@ -896,9 +901,8 @@ protected:
/// SDNodes are created without any operands, and never own the operand
/// storage. To add operands, see SelectionDAG::createOperands.
SDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTs)
- : NodeType(Opc), NodeId(-1), OperandList(nullptr), ValueList(VTs.VTs),
- UseList(nullptr), NumOperands(0), NumValues(VTs.NumVTs), IROrder(Order),
- debugLoc(std::move(dl)) {
+ : NodeType(Opc), ValueList(VTs.VTs), NumValues(VTs.NumVTs),
+ IROrder(Order), debugLoc(std::move(dl)) {
memset(&RawSDNodeBits, 0, sizeof(RawSDNodeBits));
assert(debugLoc.hasTrivialDestructor() && "Expected trivial destructor");
assert(NumValues == VTs.NumVTs &&
@@ -1366,10 +1370,10 @@ public:
};
class ConstantSDNode : public SDNode {
- const ConstantInt *Value;
-
friend class SelectionDAG;
+ const ConstantInt *Value;
+
ConstantSDNode(bool isTarget, bool isOpaque, const ConstantInt *val,
const DebugLoc &DL, EVT VT)
: SDNode(isTarget ? ISD::TargetConstant : ISD::Constant, 0, DL,
@@ -1396,11 +1400,15 @@ public:
}
};
-class ConstantFPSDNode : public SDNode {
- const ConstantFP *Value;
+uint64_t SDNode::getConstantOperandVal(unsigned Num) const {
+ return cast<ConstantSDNode>(getOperand(Num))->getZExtValue();
+}
+class ConstantFPSDNode : public SDNode {
friend class SelectionDAG;
+ const ConstantFP *Value;
+
ConstantFPSDNode(bool isTarget, const ConstantFP *val, const DebugLoc &DL,
EVT VT)
: SDNode(isTarget ? ISD::TargetConstantFP : ISD::ConstantFP, 0, DL,
@@ -1471,10 +1479,12 @@ ConstantSDNode *isConstOrConstSplat(SDValue V);
ConstantFPSDNode *isConstOrConstSplatFP(SDValue V);
class GlobalAddressSDNode : public SDNode {
+ friend class SelectionDAG;
+
const GlobalValue *TheGlobal;
int64_t Offset;
unsigned char TargetFlags;
- friend class SelectionDAG;
+
GlobalAddressSDNode(unsigned Opc, unsigned Order, const DebugLoc &DL,
const GlobalValue *GA, EVT VT, int64_t o,
unsigned char TargetFlags);
@@ -1495,10 +1505,10 @@ public:
};
class FrameIndexSDNode : public SDNode {
- int FI;
-
friend class SelectionDAG;
+ int FI;
+
FrameIndexSDNode(int fi, EVT VT, bool isTarg)
: SDNode(isTarg ? ISD::TargetFrameIndex : ISD::FrameIndex,
0, DebugLoc(), getSDVTList(VT)), FI(fi) {
@@ -1514,11 +1524,11 @@ public:
};
class JumpTableSDNode : public SDNode {
+ friend class SelectionDAG;
+
int JTI;
unsigned char TargetFlags;
- friend class SelectionDAG;
-
JumpTableSDNode(int jti, EVT VT, bool isTarg, unsigned char TF)
: SDNode(isTarg ? ISD::TargetJumpTable : ISD::JumpTable,
0, DebugLoc(), getSDVTList(VT)), JTI(jti), TargetFlags(TF) {
@@ -1535,6 +1545,8 @@ public:
};
class ConstantPoolSDNode : public SDNode {
+ friend class SelectionDAG;
+
union {
const Constant *ConstVal;
MachineConstantPoolValue *MachineCPVal;
@@ -1543,8 +1555,6 @@ class ConstantPoolSDNode : public SDNode {
unsigned Alignment; // Minimum alignment requirement of CP (not log2 value).
unsigned char TargetFlags;
- friend class SelectionDAG;
-
ConstantPoolSDNode(bool isTarget, const Constant *c, EVT VT, int o,
unsigned Align, unsigned char TF)
: SDNode(isTarget ? ISD::TargetConstantPool : ISD::ConstantPool, 0,
@@ -1598,12 +1608,12 @@ public:
/// Completely target-dependent object reference.
class TargetIndexSDNode : public SDNode {
+ friend class SelectionDAG;
+
unsigned char TargetFlags;
int Index;
int64_t Offset;
- friend class SelectionDAG;
-
public:
TargetIndexSDNode(int Idx, EVT VT, int64_t Ofs, unsigned char TF)
: SDNode(ISD::TargetIndex, 0, DebugLoc(), getSDVTList(VT)),
@@ -1619,10 +1629,10 @@ public:
};
class BasicBlockSDNode : public SDNode {
- MachineBasicBlock *MBB;
-
friend class SelectionDAG;
+ MachineBasicBlock *MBB;
+
/// Debug info is meaningful and potentially useful here, but we create
/// blocks out of order when they're jumped to, which makes it a bit
/// harder. Let's see if we need it first.
@@ -1640,10 +1650,10 @@ public:
/// A "pseudo-class" with methods for operating on BUILD_VECTORs.
class BuildVectorSDNode : public SDNode {
+public:
// These are constructed as SDNodes and then cast to BuildVectorSDNodes.
explicit BuildVectorSDNode() = delete;
-public:
/// 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
@@ -1700,10 +1710,10 @@ public:
/// in the LLVM IR representation.
///
class SrcValueSDNode : public SDNode {
- const Value *V;
-
friend class SelectionDAG;
+ const Value *V;
+
/// Create a SrcValue for a general value.
explicit SrcValueSDNode(const Value *v)
: SDNode(ISD::SRCVALUE, 0, DebugLoc(), getSDVTList(MVT::Other)), V(v) {}
@@ -1718,10 +1728,10 @@ public:
};
class MDNodeSDNode : public SDNode {
- const MDNode *MD;
-
friend class SelectionDAG;
+ const MDNode *MD;
+
explicit MDNodeSDNode(const MDNode *md)
: SDNode(ISD::MDNODE_SDNODE, 0, DebugLoc(), getSDVTList(MVT::Other)), MD(md)
{}
@@ -1735,10 +1745,10 @@ public:
};
class RegisterSDNode : public SDNode {
- unsigned Reg;
-
friend class SelectionDAG;
+ unsigned Reg;
+
RegisterSDNode(unsigned reg, EVT VT)
: SDNode(ISD::Register, 0, DebugLoc(), getSDVTList(VT)), Reg(reg) {}
@@ -1751,11 +1761,11 @@ public:
};
class RegisterMaskSDNode : public SDNode {
+ friend class SelectionDAG;
+
// The memory for RegMask is not owned by the node.
const uint32_t *RegMask;
- friend class SelectionDAG;
-
RegisterMaskSDNode(const uint32_t *mask)
: SDNode(ISD::RegisterMask, 0, DebugLoc(), getSDVTList(MVT::Untyped)),
RegMask(mask) {}
@@ -1769,12 +1779,12 @@ public:
};
class BlockAddressSDNode : public SDNode {
+ friend class SelectionDAG;
+
const BlockAddress *BA;
int64_t Offset;
unsigned char TargetFlags;
- friend class SelectionDAG;
-
BlockAddressSDNode(unsigned NodeTy, EVT VT, const BlockAddress *ba,
int64_t o, unsigned char Flags)
: SDNode(NodeTy, 0, DebugLoc(), getSDVTList(VT)),
@@ -1793,10 +1803,10 @@ public:
};
class EHLabelSDNode : public SDNode {
- MCSymbol *Label;
-
friend class SelectionDAG;
+ MCSymbol *Label;
+
EHLabelSDNode(unsigned Order, const DebugLoc &dl, MCSymbol *L)
: SDNode(ISD::EH_LABEL, Order, dl, getSDVTList(MVT::Other)), Label(L) {}
@@ -1809,11 +1819,11 @@ public:
};
class ExternalSymbolSDNode : public SDNode {
+ friend class SelectionDAG;
+
const char *Symbol;
unsigned char TargetFlags;
- friend class SelectionDAG;
-
ExternalSymbolSDNode(bool isTarget, const char *Sym, unsigned char TF, EVT VT)
: SDNode(isTarget ? ISD::TargetExternalSymbol : ISD::ExternalSymbol,
0, DebugLoc(), getSDVTList(VT)), Symbol(Sym), TargetFlags(TF) {}
@@ -1829,9 +1839,10 @@ public:
};
class MCSymbolSDNode : public SDNode {
+ friend class SelectionDAG;
+
MCSymbol *Symbol;
- friend class SelectionDAG;
MCSymbolSDNode(MCSymbol *Symbol, EVT VT)
: SDNode(ISD::MCSymbol, 0, DebugLoc(), getSDVTList(VT)), Symbol(Symbol) {}
@@ -1844,10 +1855,10 @@ public:
};
class CondCodeSDNode : public SDNode {
- ISD::CondCode Condition;
-
friend class SelectionDAG;
+ ISD::CondCode Condition;
+
explicit CondCodeSDNode(ISD::CondCode Cond)
: SDNode(ISD::CONDCODE, 0, DebugLoc(), getSDVTList(MVT::Other)),
Condition(Cond) {}
@@ -1863,10 +1874,10 @@ public:
/// This class is used to represent EVT's, which are used
/// to parameterize some operations.
class VTSDNode : public SDNode {
- EVT ValueType;
-
friend class SelectionDAG;
+ EVT ValueType;
+
explicit VTSDNode(EVT VT)
: SDNode(ISD::VALUETYPE, 0, DebugLoc(), getSDVTList(MVT::Other)),
ValueType(VT) {}
@@ -1995,6 +2006,7 @@ public:
class MaskedLoadSDNode : public MaskedLoadStoreSDNode {
public:
friend class SelectionDAG;
+
MaskedLoadSDNode(unsigned Order, const DebugLoc &dl, SDVTList VTs,
ISD::LoadExtType ETy, bool IsExpanding, EVT MemVT,
MachineMemOperand *MMO)
@@ -2114,11 +2126,11 @@ private:
friend class SelectionDAG;
MachineSDNode(unsigned Opc, unsigned Order, const DebugLoc &DL, SDVTList VTs)
- : SDNode(Opc, Order, DL, VTs), MemRefs(nullptr), MemRefsEnd(nullptr) {}
+ : SDNode(Opc, Order, DL, VTs) {}
/// Memory reference descriptions for this instruction.
- mmo_iterator MemRefs;
- mmo_iterator MemRefsEnd;
+ mmo_iterator MemRefs = nullptr;
+ mmo_iterator MemRefsEnd = nullptr;
public:
mmo_iterator memoperands_begin() const { return MemRefs; }
@@ -2184,9 +2196,11 @@ template <> struct GraphTraits<SDNode*> {
typedef SDNodeIterator ChildIteratorType;
static NodeRef getEntryNode(SDNode *N) { return N; }
+
static ChildIteratorType child_begin(NodeRef N) {
return SDNodeIterator::begin(N);
}
+
static ChildIteratorType child_end(NodeRef N) {
return SDNodeIterator::end(N);
}
diff --git a/include/llvm/CodeGen/SlotIndexes.h b/include/llvm/CodeGen/SlotIndexes.h
index 2ac3b3d86cb6..14fc3a499a08 100644
--- a/include/llvm/CodeGen/SlotIndexes.h
+++ b/include/llvm/CodeGen/SlotIndexes.h
@@ -602,19 +602,15 @@ namespace llvm {
return newIndex;
}
- /// Remove the given machine instruction from the mapping.
- void removeMachineInstrFromMaps(MachineInstr &MI) {
- // remove index -> MachineInstr and
- // MachineInstr -> index mappings
- Mi2IndexMap::iterator mi2iItr = mi2iMap.find(&MI);
- if (mi2iItr != mi2iMap.end()) {
- IndexListEntry *miEntry(mi2iItr->second.listEntry());
- assert(miEntry->getInstr() == &MI && "Instruction indexes broken.");
- // FIXME: Eventually we want to actually delete these indexes.
- miEntry->setInstr(nullptr);
- mi2iMap.erase(mi2iItr);
- }
- }
+ /// Removes machine instruction (bundle) \p MI from the mapping.
+ /// This should be called before MachineInstr::eraseFromParent() is used to
+ /// remove a whole bundle or an unbundled instruction.
+ void removeMachineInstrFromMaps(MachineInstr &MI);
+
+ /// Removes a single machine instruction \p MI from the mapping.
+ /// This should be called before MachineInstr::eraseFromBundle() is used to
+ /// remove a single instruction (out of a bundle).
+ void removeSingleMachineInstrFromMaps(MachineInstr &MI);
/// ReplaceMachineInstrInMaps - Replacing a machine instr with a new one in
/// maps used by register allocator. \returns the index where the new
diff --git a/include/llvm/CodeGen/StackMaps.h b/include/llvm/CodeGen/StackMaps.h
index 7b55b7968635..a18936feea7b 100644
--- a/include/llvm/CodeGen/StackMaps.h
+++ b/include/llvm/CodeGen/StackMaps.h
@@ -1,4 +1,4 @@
-//===------------------- StackMaps.h - StackMaps ----------------*- C++ -*-===//
+//===- StackMaps.h - StackMaps ----------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -13,7 +13,11 @@
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/CodeGen/MachineInstr.h"
-#include "llvm/MC/MCSymbol.h"
+#include "llvm/IR/CallingConv.h"
+#include "llvm/Support/Debug.h"
+#include <algorithm>
+#include <cassert>
+#include <cstdint>
#include <vector>
namespace llvm {
@@ -21,6 +25,9 @@ namespace llvm {
class AsmPrinter;
class MCExpr;
class MCStreamer;
+class MCSymbol;
+class raw_ostream;
+class TargetRegisterInfo;
/// \brief MI-level stackmap operands.
///
@@ -189,21 +196,22 @@ public:
Constant,
ConstantIndex
};
- LocationType Type;
- unsigned Size;
- unsigned Reg;
- int64_t Offset;
- Location() : Type(Unprocessed), Size(0), Reg(0), Offset(0) {}
+ LocationType Type = Unprocessed;
+ unsigned Size = 0;
+ unsigned Reg = 0;
+ int64_t Offset = 0;
+
+ Location() = default;
Location(LocationType Type, unsigned Size, unsigned Reg, int64_t Offset)
: Type(Type), Size(Size), Reg(Reg), Offset(Offset) {}
};
struct LiveOutReg {
- unsigned short Reg;
- unsigned short DwarfRegNum;
- unsigned short Size;
+ unsigned short Reg = 0;
+ unsigned short DwarfRegNum = 0;
+ unsigned short Size = 0;
- LiveOutReg() : Reg(0), DwarfRegNum(0), Size(0) {}
+ LiveOutReg() = default;
LiveOutReg(unsigned short Reg, unsigned short DwarfRegNum,
unsigned short Size)
: Reg(Reg), DwarfRegNum(DwarfRegNum), Size(Size) {}
@@ -245,18 +253,20 @@ private:
typedef MapVector<uint64_t, uint64_t> ConstantPool;
struct FunctionInfo {
- uint64_t StackSize;
- uint64_t RecordCount;
- FunctionInfo() : StackSize(0), RecordCount(1) {}
- explicit FunctionInfo(uint64_t StackSize) : StackSize(StackSize), RecordCount(1) {}
+ uint64_t StackSize = 0;
+ uint64_t RecordCount = 1;
+
+ FunctionInfo() = default;
+ explicit FunctionInfo(uint64_t StackSize) : StackSize(StackSize) {}
};
struct CallsiteInfo {
- const MCExpr *CSOffsetExpr;
- uint64_t ID;
+ const MCExpr *CSOffsetExpr = nullptr;
+ uint64_t ID = 0;
LocationVec Locations;
LiveOutVec LiveOuts;
- CallsiteInfo() : CSOffsetExpr(nullptr), ID(0) {}
+
+ CallsiteInfo() = default;
CallsiteInfo(const MCExpr *CSOffsetExpr, uint64_t ID,
LocationVec &&Locations, LiveOutVec &&LiveOuts)
: CSOffsetExpr(CSOffsetExpr), ID(ID), Locations(std::move(Locations)),
@@ -309,6 +319,7 @@ private:
void print(raw_ostream &OS);
void debug() { print(dbgs()); }
};
-}
-#endif
+} // end namespace llvm
+
+#endif // LLVM_CODEGEN_STACKMAPS_H
diff --git a/include/llvm/CodeGen/StackProtector.h b/include/llvm/CodeGen/StackProtector.h
index 1b3c0eb4a4d0..0655f19a323e 100644
--- a/include/llvm/CodeGen/StackProtector.h
+++ b/include/llvm/CodeGen/StackProtector.h
@@ -1,4 +1,4 @@
-//===-- StackProtector.h - Stack Protector Insertion ----------------------===//
+//===- StackProtector.h - Stack Protector Insertion -------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -23,8 +23,10 @@
#include "llvm/IR/ValueMap.h"
#include "llvm/Pass.h"
#include "llvm/Target/TargetLowering.h"
+#include "llvm/Target/TargetMachine.h"
namespace llvm {
+
class Function;
class Module;
class PHINode;
@@ -48,11 +50,11 @@ public:
typedef ValueMap<const AllocaInst *, SSPLayoutKind> SSPLayoutMap;
private:
- const TargetMachine *TM;
+ const TargetMachine *TM = nullptr;
/// TLI - Keep a pointer of a TargetLowering to consult for determining
/// target type sizes.
- const TargetLoweringBase *TLI;
+ const TargetLoweringBase *TLI = nullptr;
const Triple Trip;
Function *F;
@@ -67,7 +69,7 @@ private:
/// \brief The minimum size of buffers that will receive stack smashing
/// protection when -fstack-protection is used.
- unsigned SSPBufferSize;
+ unsigned SSPBufferSize = 0;
/// VisitedPHIs - The set of PHI nodes visited when determining
/// if a variable's reference has been taken. This set
@@ -111,12 +113,13 @@ private:
public:
static char ID; // Pass identification, replacement for typeid.
- StackProtector()
- : FunctionPass(ID), TM(nullptr), TLI(nullptr), SSPBufferSize(0) {
+
+ StackProtector() : FunctionPass(ID) {
initializeStackProtectorPass(*PassRegistry::getPassRegistry());
}
+
StackProtector(const TargetMachine *TM)
- : FunctionPass(ID), TM(TM), TLI(nullptr), Trip(TM->getTargetTriple()),
+ : FunctionPass(ID), TM(TM), Trip(TM->getTargetTriple()),
SSPBufferSize(8) {
initializeStackProtectorPass(*PassRegistry::getPassRegistry());
}
@@ -134,6 +137,7 @@ public:
bool runOnFunction(Function &Fn) override;
};
+
} // end namespace llvm
#endif // LLVM_CODEGEN_STACKPROTECTOR_H
diff --git a/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h b/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
index cc71fa3918a1..adf2b3ea1c9b 100644
--- a/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
+++ b/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
@@ -1,4 +1,4 @@
-//==-- llvm/CodeGen/TargetLoweringObjectFileImpl.h - Object Info -*- C++ -*-==//
+//==- llvm/CodeGen/TargetLoweringObjectFileImpl.h - Object Info --*- C++ -*-==//
//
// The LLVM Compiler Infrastructure
//
@@ -15,24 +15,22 @@
#ifndef LLVM_CODEGEN_TARGETLOWERINGOBJECTFILEIMPL_H
#define LLVM_CODEGEN_TARGETLOWERINGOBJECTFILEIMPL_H
+#include "llvm/IR/Module.h"
#include "llvm/MC/MCExpr.h"
-#include "llvm/MC/SectionKind.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
namespace llvm {
- class MachineModuleInfo;
- class Mangler;
- class MCAsmInfo;
- class MCSection;
- class MCSectionMachO;
- class MCSymbol;
- class MCContext;
- class GlobalValue;
- class TargetMachine;
+class GlobalValue;
+class MachineModuleInfo;
+class Mangler;
+class MCContext;
+class MCSection;
+class MCSymbol;
+class TargetMachine;
class TargetLoweringObjectFileELF : public TargetLoweringObjectFile {
- bool UseInitArray;
+ bool UseInitArray = false;
mutable unsigned NextUniqueID = 1; // ID 0 is reserved for execute-only sections
protected:
@@ -40,9 +38,8 @@ protected:
MCSymbolRefExpr::VK_None;
public:
- TargetLoweringObjectFileELF() : UseInitArray(false) {}
-
- ~TargetLoweringObjectFileELF() override {}
+ TargetLoweringObjectFileELF() = default;
+ ~TargetLoweringObjectFileELF() override = default;
void emitPersonalityValue(MCStreamer &Streamer, const DataLayout &TM,
const MCSymbol *Sym) const override;
@@ -89,12 +86,10 @@ public:
const TargetMachine &TM) const override;
};
-
-
class TargetLoweringObjectFileMachO : public TargetLoweringObjectFile {
public:
- ~TargetLoweringObjectFileMachO() override {}
TargetLoweringObjectFileMachO();
+ ~TargetLoweringObjectFileMachO() override = default;
void Initialize(MCContext &Ctx, const TargetMachine &TM) override;
@@ -135,13 +130,11 @@ public:
const TargetMachine &TM) const override;
};
-
-
class TargetLoweringObjectFileCOFF : public TargetLoweringObjectFile {
mutable unsigned NextUniqueID = 0;
public:
- ~TargetLoweringObjectFileCOFF() override {}
+ ~TargetLoweringObjectFileCOFF() override = default;
void Initialize(MCContext &Ctx, const TargetMachine &TM) override;
MCSection *getExplicitSectionGlobal(const GlobalObject *GO, SectionKind Kind,
@@ -171,6 +164,29 @@ public:
const GlobalValue *GV) const override;
};
+class TargetLoweringObjectFileWasm : public TargetLoweringObjectFile {
+ mutable unsigned NextUniqueID = 0;
+
+public:
+ TargetLoweringObjectFileWasm() = default;
+ ~TargetLoweringObjectFileWasm() override = default;
+
+ MCSection *getExplicitSectionGlobal(const GlobalObject *GO, SectionKind Kind,
+ const TargetMachine &TM) const override;
+
+ MCSection *SelectSectionForGlobal(const GlobalObject *GO, SectionKind Kind,
+ const TargetMachine &TM) const override;
+
+ bool shouldPutJumpTableInFunctionSection(bool UsesLabelDifference,
+ const Function &F) const override;
+
+ void InitializeWasm();
+
+ const MCExpr *lowerRelativeReference(const GlobalValue *LHS,
+ const GlobalValue *RHS,
+ const TargetMachine &TM) const override;
+};
+
} // end namespace llvm
-#endif
+#endif // LLVM_CODEGEN_TARGETLOWERINGOBJECTFILEIMPL_H
diff --git a/include/llvm/CodeGen/TargetPassConfig.h b/include/llvm/CodeGen/TargetPassConfig.h
index 2287f9aca4bf..f0c826dc1d45 100644
--- a/include/llvm/CodeGen/TargetPassConfig.h
+++ b/include/llvm/CodeGen/TargetPassConfig.h
@@ -115,6 +115,10 @@ protected:
/// Default setting for -enable-tail-merge on this target.
bool EnableTailMerge;
+ /// Require processing of functions such that callees are generated before
+ /// callers.
+ bool RequireCodeGenSCCOrder;
+
public:
TargetPassConfig(TargetMachine *tm, PassManagerBase &pm);
// Dummy constructor.
@@ -162,6 +166,11 @@ public:
bool getEnableTailMerge() const { return EnableTailMerge; }
void setEnableTailMerge(bool Enable) { setOpt(EnableTailMerge, Enable); }
+ bool requiresCodeGenSCCOrder() const { return RequireCodeGenSCCOrder; }
+ void setRequiresCodeGenSCCOrder(bool Enable = true) {
+ setOpt(RequireCodeGenSCCOrder, Enable);
+ }
+
/// Allow the target to override a specific pass without overriding the pass
/// pipeline. When passes are added to the standard pipeline at the
/// point where StandardID is expected, add TargetID in its place.
@@ -286,6 +295,10 @@ public:
/// verification is enabled.
void addVerifyPass(const std::string &Banner);
+ /// Check whether or not GlobalISel should be enabled by default.
+ /// Fallback/abort behavior is controlled via other methods.
+ virtual bool isGlobalISelEnabled() const;
+
/// Check whether or not GlobalISel should abort on error.
/// When this is disable, GlobalISel will fall back on SDISel instead of
/// erroring out.
diff --git a/include/llvm/CodeGen/TargetSchedule.h b/include/llvm/CodeGen/TargetSchedule.h
index 81054aba066f..1992412120aa 100644
--- a/include/llvm/CodeGen/TargetSchedule.h
+++ b/include/llvm/CodeGen/TargetSchedule.h
@@ -1,4 +1,4 @@
-//===-- llvm/CodeGen/TargetSchedule.h - Sched Machine Model -----*- C++ -*-===//
+//===- llvm/CodeGen/TargetSchedule.h - Sched Machine Model ------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -23,10 +23,8 @@
namespace llvm {
-class TargetRegisterInfo;
-class TargetSubtargetInfo;
-class TargetInstrInfo;
class MachineInstr;
+class TargetInstrInfo;
/// Provide an instruction scheduling machine model to CodeGen passes.
class TargetSchedModel {
@@ -34,8 +32,8 @@ class TargetSchedModel {
// processor.
MCSchedModel SchedModel;
InstrItineraryData InstrItins;
- const TargetSubtargetInfo *STI;
- const TargetInstrInfo *TII;
+ const TargetSubtargetInfo *STI = nullptr;
+ const TargetInstrInfo *TII = nullptr;
SmallVector<unsigned, 16> ResourceFactors;
unsigned MicroOpFactor; // Multiply to normalize microops to resource units.
@@ -44,7 +42,7 @@ class TargetSchedModel {
unsigned computeInstrLatency(const MCSchedClassDesc &SCDesc) const;
public:
- TargetSchedModel(): SchedModel(MCSchedModel::GetDefaultSchedModel()), STI(nullptr), TII(nullptr) {}
+ TargetSchedModel() : SchedModel(MCSchedModel::GetDefaultSchedModel()) {}
/// \brief Initialize the machine model for instruction scheduling.
///
@@ -93,6 +91,13 @@ public:
/// \brief Maximum number of micro-ops that may be scheduled per cycle.
unsigned getIssueWidth() const { return SchedModel.IssueWidth; }
+ /// \brief Return true if new group must begin.
+ bool mustBeginGroup(const MachineInstr *MI,
+ const MCSchedClassDesc *SC = nullptr) const;
+ /// \brief Return true if current group must end.
+ bool mustEndGroup(const MachineInstr *MI,
+ const MCSchedClassDesc *SC = nullptr) const;
+
/// \brief Return the number of issue slots required for this MI.
unsigned getNumMicroOps(const MachineInstr *MI,
const MCSchedClassDesc *SC = nullptr) const;
@@ -178,13 +183,18 @@ public:
bool UseDefaultDefLatency = true) const;
unsigned computeInstrLatency(unsigned Opcode) const;
+
/// \brief Output dependency latency of a pair of defs of the same register.
///
/// This is typically one cycle.
unsigned computeOutputLatency(const MachineInstr *DefMI, unsigned DefIdx,
const MachineInstr *DepMI) const;
+
+ /// \brief Compute the reciprocal throughput of the given instruction.
+ Optional<double> computeInstrRThroughput(const MachineInstr *MI) const;
+ Optional<double> computeInstrRThroughput(unsigned Opcode) const;
};
-} // namespace llvm
+} // end namespace llvm
-#endif
+#endif // LLVM_CODEGEN_TARGETSCHEDULE_H
diff --git a/include/llvm/CodeGen/ValueTypes.h b/include/llvm/CodeGen/ValueTypes.h
index 2699fa28f0f1..0a3063663cef 100644
--- a/include/llvm/CodeGen/ValueTypes.h
+++ b/include/llvm/CodeGen/ValueTypes.h
@@ -25,9 +25,9 @@ namespace llvm {
class LLVMContext;
class Type;
- /// EVT - Extended Value Type. Capable of holding value types which are not
- /// native for any processor (such as the i12345 type), as well as the types
- /// a MVT can represent.
+ /// Extended Value Type. Capable of holding value types which are not native
+ /// for any processor (such as the i12345 type), as well as the types an MVT
+ /// can represent.
struct EVT {
private:
MVT V;
@@ -49,15 +49,15 @@ namespace llvm {
return false;
}
- /// getFloatingPointVT - Returns the EVT that represents a floating point
- /// type with the given number of bits. There are two floating point types
- /// with 128 bits - this returns f128 rather than ppcf128.
+ /// Returns the EVT that represents a floating-point type with the given
+ /// number of bits. There are two floating-point types with 128 bits - this
+ /// returns f128 rather than ppcf128.
static EVT getFloatingPointVT(unsigned BitWidth) {
return MVT::getFloatingPointVT(BitWidth);
}
- /// getIntegerVT - Returns the EVT that represents an integer with the given
- /// number of bits.
+ /// Returns the EVT that represents an integer with the given number of
+ /// bits.
static EVT getIntegerVT(LLVMContext &Context, unsigned BitWidth) {
MVT M = MVT::getIntegerVT(BitWidth);
if (M.SimpleTy >= 0)
@@ -65,8 +65,8 @@ namespace llvm {
return getExtendedIntegerVT(Context, BitWidth);
}
- /// getVectorVT - Returns the EVT that represents a vector NumElements in
- /// length, where each element is of type VT.
+ /// Returns the EVT that represents a vector NumElements in length, where
+ /// each element is of type VT.
static EVT getVectorVT(LLVMContext &Context, EVT VT, unsigned NumElements) {
MVT M = MVT::getVectorVT(VT.V, NumElements);
if (M.SimpleTy >= 0)
@@ -74,9 +74,9 @@ namespace llvm {
return getExtendedVectorVT(Context, VT, NumElements);
}
- /// changeVectorElementTypeToInteger - Return a vector with the same number
- /// of elements as this vector, but with the element type converted to an
- /// integer type with the same bitwidth.
+ /// Return a vector with the same number of elements as this vector, but
+ /// with the element type converted to an integer type with the same
+ /// bitwidth.
EVT changeVectorElementTypeToInteger() const {
if (!isSimple())
return changeExtendedVectorElementTypeToInteger();
@@ -102,140 +102,136 @@ namespace llvm {
return changeExtendedTypeToInteger();
}
- /// isSimple - Test if the given EVT is simple (as opposed to being
- /// extended).
+ /// Test if the given EVT is simple (as opposed to being extended).
bool isSimple() const {
return V.SimpleTy >= 0;
}
- /// isExtended - Test if the given EVT is extended (as opposed to
- /// being simple).
+ /// Test if the given EVT is extended (as opposed to being simple).
bool isExtended() const {
return !isSimple();
}
- /// isFloatingPoint - Return true if this is a FP, or a vector FP type.
+ /// Return true if this is a FP or a vector FP type.
bool isFloatingPoint() const {
return isSimple() ? V.isFloatingPoint() : isExtendedFloatingPoint();
}
- /// isInteger - Return true if this is an integer, or a vector integer type.
+ /// Return true if this is an integer or a vector integer type.
bool isInteger() const {
return isSimple() ? V.isInteger() : isExtendedInteger();
}
- /// isScalarInteger - Return true if this is an integer, but not a vector.
+ /// Return true if this is an integer, but not a vector.
bool isScalarInteger() const {
return isSimple() ? V.isScalarInteger() : isExtendedScalarInteger();
}
- /// isVector - Return true if this is a vector value type.
+ /// Return true if this is a vector value type.
bool isVector() const {
return isSimple() ? V.isVector() : isExtendedVector();
}
- /// is16BitVector - Return true if this is a 16-bit vector type.
+ /// Return true if this is a 16-bit vector type.
bool is16BitVector() const {
return isSimple() ? V.is16BitVector() : isExtended16BitVector();
}
- /// is32BitVector - Return true if this is a 32-bit vector type.
+ /// Return true if this is a 32-bit vector type.
bool is32BitVector() const {
return isSimple() ? V.is32BitVector() : isExtended32BitVector();
}
- /// is64BitVector - Return true if this is a 64-bit vector type.
+ /// Return true if this is a 64-bit vector type.
bool is64BitVector() const {
return isSimple() ? V.is64BitVector() : isExtended64BitVector();
}
- /// is128BitVector - Return true if this is a 128-bit vector type.
+ /// Return true if this is a 128-bit vector type.
bool is128BitVector() const {
return isSimple() ? V.is128BitVector() : isExtended128BitVector();
}
- /// is256BitVector - Return true if this is a 256-bit vector type.
+ /// Return true if this is a 256-bit vector type.
bool is256BitVector() const {
return isSimple() ? V.is256BitVector() : isExtended256BitVector();
}
- /// is512BitVector - Return true if this is a 512-bit vector type.
+ /// Return true if this is a 512-bit vector type.
bool is512BitVector() const {
return isSimple() ? V.is512BitVector() : isExtended512BitVector();
}
- /// is1024BitVector - Return true if this is a 1024-bit vector type.
+ /// Return true if this is a 1024-bit vector type.
bool is1024BitVector() const {
return isSimple() ? V.is1024BitVector() : isExtended1024BitVector();
}
- /// is2048BitVector - Return true if this is a 2048-bit vector type.
+ /// Return true if this is a 2048-bit vector type.
bool is2048BitVector() const {
return isSimple() ? V.is2048BitVector() : isExtended2048BitVector();
}
- /// isOverloaded - Return true if this is an overloaded type for TableGen.
+ /// Return true if this is an overloaded type for TableGen.
bool isOverloaded() const {
return (V==MVT::iAny || V==MVT::fAny || V==MVT::vAny || V==MVT::iPTRAny);
}
- /// isByteSized - Return true if the bit size is a multiple of 8.
+ /// Return true if the bit size is a multiple of 8.
bool isByteSized() const {
return (getSizeInBits() & 7) == 0;
}
- /// isRound - Return true if the size is a power-of-two number of bytes.
+ /// Return true if the size is a power-of-two number of bytes.
bool isRound() const {
unsigned BitSize = getSizeInBits();
return BitSize >= 8 && !(BitSize & (BitSize - 1));
}
- /// bitsEq - Return true if this has the same number of bits as VT.
+ /// Return true if this has the same number of bits as VT.
bool bitsEq(EVT VT) const {
if (EVT::operator==(VT)) return true;
return getSizeInBits() == VT.getSizeInBits();
}
- /// bitsGT - Return true if this has more bits than VT.
+ /// Return true if this has more bits than VT.
bool bitsGT(EVT VT) const {
if (EVT::operator==(VT)) return false;
return getSizeInBits() > VT.getSizeInBits();
}
- /// bitsGE - Return true if this has no less bits than VT.
+ /// Return true if this has no less bits than VT.
bool bitsGE(EVT VT) const {
if (EVT::operator==(VT)) return true;
return getSizeInBits() >= VT.getSizeInBits();
}
- /// bitsLT - Return true if this has less bits than VT.
+ /// Return true if this has less bits than VT.
bool bitsLT(EVT VT) const {
if (EVT::operator==(VT)) return false;
return getSizeInBits() < VT.getSizeInBits();
}
- /// bitsLE - Return true if this has no more bits than VT.
+ /// Return true if this has no more bits than VT.
bool bitsLE(EVT VT) const {
if (EVT::operator==(VT)) return true;
return getSizeInBits() <= VT.getSizeInBits();
}
- /// getSimpleVT - Return the SimpleValueType held in the specified
- /// simple EVT.
+ /// Return the SimpleValueType held in the specified simple EVT.
MVT getSimpleVT() const {
assert(isSimple() && "Expected a SimpleValueType!");
return V;
}
- /// getScalarType - If this is a vector type, return the element type,
- /// otherwise return this.
+ /// If this is a vector type, return the element type, otherwise return
+ /// this.
EVT getScalarType() const {
return isVector() ? getVectorElementType() : *this;
}
- /// getVectorElementType - Given a vector type, return the type of
- /// each element.
+ /// Given a vector type, return the type of each element.
EVT getVectorElementType() const {
assert(isVector() && "Invalid vector type!");
if (isSimple())
@@ -243,8 +239,7 @@ namespace llvm {
return getExtendedVectorElementType();
}
- /// getVectorNumElements - Given a vector type, return the number of
- /// elements it contains.
+ /// Given a vector type, return the number of elements it contains.
unsigned getVectorNumElements() const {
assert(isVector() && "Invalid vector type!");
if (isSimple())
@@ -252,7 +247,7 @@ namespace llvm {
return getExtendedVectorNumElements();
}
- /// getSizeInBits - Return the size of the specified value type in bits.
+ /// Return the size of the specified value type in bits.
unsigned getSizeInBits() const {
if (isSimple())
return V.getSizeInBits();
@@ -263,21 +258,21 @@ namespace llvm {
return getScalarType().getSizeInBits();
}
- /// getStoreSize - Return the number of bytes overwritten by a store
- /// of the specified value type.
+ /// Return the number of bytes overwritten by a store of the specified value
+ /// type.
unsigned getStoreSize() const {
return (getSizeInBits() + 7) / 8;
}
- /// getStoreSizeInBits - Return the number of bits overwritten by a store
- /// of the specified value type.
+ /// Return the number of bits overwritten by a store of the specified value
+ /// type.
unsigned getStoreSizeInBits() const {
return getStoreSize() * 8;
}
- /// getRoundIntegerType - Rounds the bit-width of the given integer EVT up
- /// to the nearest power of two (and at least to eight), and returns the
- /// integer EVT with that number of bits.
+ /// Rounds the bit-width of the given integer EVT up to the nearest power of
+ /// two (and at least to eight), and returns the integer EVT with that
+ /// number of bits.
EVT getRoundIntegerType(LLVMContext &Context) const {
assert(isInteger() && !isVector() && "Invalid integer type!");
unsigned BitWidth = getSizeInBits();
@@ -286,10 +281,9 @@ namespace llvm {
return getIntegerVT(Context, 1 << Log2_32_Ceil(BitWidth));
}
- /// getHalfSizedIntegerVT - Finds the smallest simple value type that is
- /// greater than or equal to half the width of this EVT. If no simple
- /// value type can be found, an extended integer value type of half the
- /// size (rounded up) is returned.
+ /// Finds the smallest simple value type that is greater than or equal to
+ /// half the width of this EVT. If no simple value type can be found, an
+ /// extended integer value type of half the size (rounded up) is returned.
EVT getHalfSizedIntegerVT(LLVMContext &Context) const {
assert(isInteger() && !isVector() && "Invalid integer type!");
unsigned EVTSize = getSizeInBits();
@@ -302,7 +296,7 @@ namespace llvm {
return getIntegerVT(Context, (EVTSize + 1) / 2);
}
- /// \brief Return a VT for an integer vector type with the size of the
+ /// Return a VT for an integer vector type with the size of the
/// elements doubled. The typed returned may be an extended type.
EVT widenIntegerVectorElementType(LLVMContext &Context) const {
EVT EltVT = getVectorElementType();
@@ -310,14 +304,14 @@ namespace llvm {
return EVT::getVectorVT(Context, EltVT, getVectorNumElements());
}
- /// isPow2VectorType - Returns true if the given vector is a power of 2.
+ /// Returns true if the given vector is a power of 2.
bool isPow2VectorType() const {
unsigned NElts = getVectorNumElements();
return !(NElts & (NElts - 1));
}
- /// getPow2VectorType - Widens the length of the given vector EVT up to
- /// the nearest power of 2 and returns that type.
+ /// Widens the length of the given vector EVT up to the nearest power of 2
+ /// and returns that type.
EVT getPow2VectorType(LLVMContext &Context) const {
if (!isPow2VectorType()) {
unsigned NElts = getVectorNumElements();
@@ -329,16 +323,15 @@ namespace llvm {
}
}
- /// getEVTString - This function returns value type as a string,
- /// e.g. "i32".
+ /// This function returns value type as a string, e.g. "i32".
std::string getEVTString() const;
- /// getTypeForEVT - This method returns an LLVM type corresponding to the
- /// specified EVT. For integer types, this returns an unsigned type. Note
- /// that this will abort for types that cannot be represented.
+ /// This method returns an LLVM type corresponding to the specified EVT.
+ /// For integer types, this returns an unsigned type. Note that this will
+ /// abort for types that cannot be represented.
Type *getTypeForEVT(LLVMContext &Context) const;
- /// getEVT - Return the value type corresponding to the specified type.
+ /// Return the value type corresponding to the specified type.
/// This returns all pointers as iPTR. If HandleUnknown is true, unknown
/// types are returned as Other, otherwise they are invalid.
static EVT getEVT(Type *Ty, bool HandleUnknown = false);
@@ -350,8 +343,8 @@ namespace llvm {
return (intptr_t)(LLVMTy);
}
- /// compareRawBits - A meaningless but well-behaved order, useful for
- /// constructing containers.
+ /// A meaningless but well-behaved order, useful for constructing
+ /// containers.
struct compareRawBits {
bool operator()(EVT L, EVT R) const {
if (L.V.SimpleTy == R.V.SimpleTy)
diff --git a/include/llvm/Config/abi-breaking.h.cmake b/include/llvm/Config/abi-breaking.h.cmake
index e5697f79e93d..4ce487b8f5f3 100644
--- a/include/llvm/Config/abi-breaking.h.cmake
+++ b/include/llvm/Config/abi-breaking.h.cmake
@@ -15,9 +15,8 @@
/* Define to enable checks that alter the LLVM C++ ABI */
#cmakedefine01 LLVM_ENABLE_ABI_BREAKING_CHECKS
-/* Define to disable the link-time checking of mismatch for
- LLVM_ENABLE_ABI_BREAKING_CHECKS */
-#cmakedefine01 LLVM_DISABLE_ABI_BREAKING_CHECKS_ENFORCING
+/* Allow selectively disabling link-time mismatch checking so that header-only
+ ADT content from LLVM can be used without linking libSupport. */
#if !LLVM_DISABLE_ABI_BREAKING_CHECKS_ENFORCING
// ABI_BREAKING_CHECKS protection: provides link-time failure when clients build
diff --git a/include/llvm/Config/config.h.cmake b/include/llvm/Config/config.h.cmake
index ff41d75373c8..a3c919d39804 100644
--- a/include/llvm/Config/config.h.cmake
+++ b/include/llvm/Config/config.h.cmake
@@ -16,6 +16,8 @@
/* Define to 1 if you have the `backtrace' function. */
#cmakedefine HAVE_BACKTRACE ${HAVE_BACKTRACE}
+#define BACKTRACE_HEADER <${BACKTRACE_HEADER}>
+
/* Define to 1 if you have the <CrashReporterClient.h> header file. */
#cmakedefine HAVE_CRASHREPORTERCLIENT_H
@@ -51,6 +53,9 @@
/* Define if dlopen() is available on this platform. */
#cmakedefine HAVE_DLOPEN ${HAVE_DLOPEN}
+/* Define if dladdr() is available on this platform. */
+#cmakedefine HAVE_DLADDR ${HAVE_DLADDR}
+
/* Define to 1 if you have the <errno.h> header file. */
#cmakedefine HAVE_ERRNO_H ${HAVE_ERRNO_H}
@@ -375,9 +380,6 @@
/* Define if this is Win32ish platform */
#cmakedefine LLVM_ON_WIN32 ${LLVM_ON_WIN32}
-/* Installation prefix directory */
-#cmakedefine LLVM_PREFIX "${LLVM_PREFIX}"
-
/* Define if we have the Intel JIT API runtime support library */
#cmakedefine01 LLVM_USE_INTEL_JITEVENTS
diff --git a/include/llvm/Config/llvm-config.h.cmake b/include/llvm/Config/llvm-config.h.cmake
index 359997057618..4b0c59460619 100644
--- a/include/llvm/Config/llvm-config.h.cmake
+++ b/include/llvm/Config/llvm-config.h.cmake
@@ -56,9 +56,6 @@
/* Define if this is Win32ish platform */
#cmakedefine LLVM_ON_WIN32 ${LLVM_ON_WIN32}
-/* Installation prefix directory */
-#cmakedefine LLVM_PREFIX "${LLVM_PREFIX}"
-
/* Define if we have the Intel JIT API runtime support library */
#cmakedefine01 LLVM_USE_INTEL_JITEVENTS
diff --git a/include/llvm/DebugInfo/CodeView/CVRecord.h b/include/llvm/DebugInfo/CodeView/CVRecord.h
index a327d450db55..487f3b6446fa 100644
--- a/include/llvm/DebugInfo/CodeView/CVRecord.h
+++ b/include/llvm/DebugInfo/CodeView/CVRecord.h
@@ -14,8 +14,8 @@
#include "llvm/ADT/Optional.h"
#include "llvm/DebugInfo/CodeView/CodeViewError.h"
#include "llvm/DebugInfo/CodeView/RecordSerialization.h"
-#include "llvm/DebugInfo/MSF/StreamReader.h"
-#include "llvm/DebugInfo/MSF/StreamRef.h"
+#include "llvm/Support/BinaryStreamReader.h"
+#include "llvm/Support/BinaryStreamRef.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/Error.h"
#include <cstdint>
@@ -48,15 +48,13 @@ public:
} // end namespace codeview
-namespace msf {
-
template <typename Kind>
struct VarStreamArrayExtractor<codeview::CVRecord<Kind>> {
- Error operator()(ReadableStreamRef Stream, uint32_t &Len,
+ Error operator()(BinaryStreamRef Stream, uint32_t &Len,
codeview::CVRecord<Kind> &Item) const {
using namespace codeview;
const RecordPrefix *Prefix = nullptr;
- StreamReader Reader(Stream);
+ BinaryStreamReader Reader(Stream);
uint32_t Offset = Reader.getOffset();
if (auto EC = Reader.readObject(Prefix))
@@ -76,8 +74,6 @@ struct VarStreamArrayExtractor<codeview::CVRecord<Kind>> {
}
};
-} // end namespace msf
-
} // end namespace llvm
#endif // LLVM_DEBUGINFO_CODEVIEW_RECORDITERATOR_H
diff --git a/include/llvm/DebugInfo/CodeView/CVTypeDumper.h b/include/llvm/DebugInfo/CodeView/CVTypeDumper.h
index e1dd6a10b5a1..02f14ea2107b 100644
--- a/include/llvm/DebugInfo/CodeView/CVTypeDumper.h
+++ b/include/llvm/DebugInfo/CodeView/CVTypeDumper.h
@@ -22,10 +22,14 @@ namespace llvm {
namespace codeview {
+class TypeServerHandler;
+
/// Dumper for CodeView type streams found in COFF object files and PDB files.
class CVTypeDumper {
public:
- explicit CVTypeDumper(TypeDatabase &TypeDB) : TypeDB(TypeDB) {}
+ explicit CVTypeDumper(TypeDatabase &TypeDB,
+ TypeServerHandler *Handler = nullptr)
+ : TypeDB(TypeDB), Handler(Handler) {}
/// Dumps one type record. Returns false if there was a type parsing error,
/// and true otherwise. This should be called in order, since the dumper
@@ -48,6 +52,7 @@ public:
private:
TypeDatabase &TypeDB;
+ TypeServerHandler *Handler;
};
} // end namespace codeview
diff --git a/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h b/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h
index d1b0363a4133..e9012db7602d 100644
--- a/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h
+++ b/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h
@@ -10,9 +10,10 @@
#ifndef LLVM_DEBUGINFO_CODEVIEW_CVTYPEVISITOR_H
#define LLVM_DEBUGINFO_CODEVIEW_CVTYPEVISITOR_H
-#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/TinyPtrVector.h"
#include "llvm/DebugInfo/CodeView/CVRecord.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
+#include "llvm/DebugInfo/CodeView/TypeServerHandler.h"
#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
#include "llvm/Support/Error.h"
@@ -23,18 +24,23 @@ class CVTypeVisitor {
public:
explicit CVTypeVisitor(TypeVisitorCallbacks &Callbacks);
+ void addTypeServerHandler(TypeServerHandler &Handler);
+
Error visitTypeRecord(CVType &Record);
Error visitMemberRecord(CVMemberRecord &Record);
/// Visits the type records in Data. Sets the error flag on parse failures.
Error visitTypeStream(const CVTypeArray &Types);
+ Error visitTypeStream(CVTypeRange Types);
Error visitFieldListMemberStream(ArrayRef<uint8_t> FieldList);
- Error visitFieldListMemberStream(msf::StreamReader Reader);
+ Error visitFieldListMemberStream(BinaryStreamReader Reader);
private:
/// The interface to the class that gets notified of each visitation.
TypeVisitorCallbacks &Callbacks;
+
+ TinyPtrVector<TypeServerHandler *> Handlers;
};
} // end namespace codeview
diff --git a/include/llvm/DebugInfo/CodeView/CodeView.h b/include/llvm/DebugInfo/CodeView/CodeView.h
index e21cfa3d030a..2791c9dc3746 100644
--- a/include/llvm/DebugInfo/CodeView/CodeView.h
+++ b/include/llvm/DebugInfo/CodeView/CodeView.h
@@ -275,6 +275,12 @@ enum class MethodOptions : uint16_t {
};
CV_DEFINE_ENUM_CLASS_FLAGS_OPERATORS(MethodOptions)
+/// Equivalent to CV_LABEL_TYPE_e.
+enum class LabelType : uint16_t {
+ Near = 0x0,
+ Far = 0x4,
+};
+
/// Equivalent to CV_modifier_t.
/// TODO: Add flag for _Atomic modifier
enum class ModifierOptions : uint16_t {
diff --git a/include/llvm/DebugInfo/CodeView/CodeViewError.h b/include/llvm/DebugInfo/CodeView/CodeViewError.h
index 0556fd0e19f2..586a720ce6e4 100644
--- a/include/llvm/DebugInfo/CodeView/CodeViewError.h
+++ b/include/llvm/DebugInfo/CodeView/CodeViewError.h
@@ -21,6 +21,7 @@ enum class cv_error_code {
insufficient_buffer,
operation_unsupported,
corrupt_record,
+ no_records,
unknown_member_record,
};
diff --git a/include/llvm/DebugInfo/CodeView/CodeViewRecordIO.h b/include/llvm/DebugInfo/CodeView/CodeViewRecordIO.h
index 5a036b9d5b6c..b3976826a316 100644
--- a/include/llvm/DebugInfo/CodeView/CodeViewRecordIO.h
+++ b/include/llvm/DebugInfo/CodeView/CodeViewRecordIO.h
@@ -17,8 +17,8 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/DebugInfo/CodeView/CodeViewError.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
-#include "llvm/DebugInfo/MSF/StreamReader.h"
-#include "llvm/DebugInfo/MSF/StreamWriter.h"
+#include "llvm/Support/BinaryStreamReader.h"
+#include "llvm/Support/BinaryStreamWriter.h"
#include "llvm/Support/Error.h"
#include <cassert>
#include <cstdint>
@@ -33,8 +33,8 @@ class CodeViewRecordIO {
}
public:
- explicit CodeViewRecordIO(msf::StreamReader &Reader) : Reader(&Reader) {}
- explicit CodeViewRecordIO(msf::StreamWriter &Writer) : Writer(&Writer) {}
+ explicit CodeViewRecordIO(BinaryStreamReader &Reader) : Reader(&Reader) {}
+ explicit CodeViewRecordIO(BinaryStreamWriter &Writer) : Writer(&Writer) {}
Error beginRecord(Optional<uint32_t> MaxLength);
Error endRecord();
@@ -160,8 +160,8 @@ private:
SmallVector<RecordLimit, 2> Limits;
- msf::StreamReader *Reader = nullptr;
- msf::StreamWriter *Writer = nullptr;
+ BinaryStreamReader *Reader = nullptr;
+ BinaryStreamWriter *Writer = nullptr;
};
} // end namespace codeview
diff --git a/include/llvm/DebugInfo/CodeView/Formatters.h b/include/llvm/DebugInfo/CodeView/Formatters.h
new file mode 100644
index 000000000000..37a91098a8b6
--- /dev/null
+++ b/include/llvm/DebugInfo/CodeView/Formatters.h
@@ -0,0 +1,40 @@
+//===- Formatters.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_CODEVIEW_FORMATTERS_H
+#define LLVM_DEBUGINFO_CODEVIEW_FORMATTERS_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/FormatAdapters.h"
+
+namespace llvm {
+namespace codeview {
+namespace detail {
+class GuidAdapter final : public llvm::FormatAdapter<ArrayRef<uint8_t>> {
+ ArrayRef<uint8_t> Guid;
+
+public:
+ explicit GuidAdapter(ArrayRef<uint8_t> Guid);
+ explicit GuidAdapter(StringRef Guid);
+ void format(llvm::raw_ostream &Stream, StringRef Style);
+};
+}
+
+inline detail::GuidAdapter fmt_guid(StringRef Item) {
+ return detail::GuidAdapter(Item);
+}
+
+inline detail::GuidAdapter fmt_guid(ArrayRef<uint8_t> Item) {
+ return detail::GuidAdapter(Item);
+}
+}
+}
+
+#endif
diff --git a/include/llvm/DebugInfo/CodeView/ModuleSubstream.h b/include/llvm/DebugInfo/CodeView/ModuleSubstream.h
index 8860ae42fc09..a1c5c93cc3f8 100644
--- a/include/llvm/DebugInfo/CodeView/ModuleSubstream.h
+++ b/include/llvm/DebugInfo/CodeView/ModuleSubstream.h
@@ -11,8 +11,8 @@
#define LLVM_DEBUGINFO_CODEVIEW_MODULESUBSTREAM_H
#include "llvm/DebugInfo/CodeView/CodeView.h"
-#include "llvm/DebugInfo/MSF/StreamArray.h"
-#include "llvm/DebugInfo/MSF/StreamRef.h"
+#include "llvm/Support/BinaryStreamArray.h"
+#include "llvm/Support/BinaryStreamRef.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/Error.h"
@@ -59,23 +59,22 @@ struct ColumnNumberEntry {
class ModuleSubstream {
public:
ModuleSubstream();
- ModuleSubstream(ModuleSubstreamKind Kind, msf::ReadableStreamRef Data);
- static Error initialize(msf::ReadableStreamRef Stream, ModuleSubstream &Info);
+ ModuleSubstream(ModuleSubstreamKind Kind, BinaryStreamRef Data);
+ static Error initialize(BinaryStreamRef Stream, ModuleSubstream &Info);
uint32_t getRecordLength() const;
ModuleSubstreamKind getSubstreamKind() const;
- msf::ReadableStreamRef getRecordData() const;
+ BinaryStreamRef getRecordData() const;
private:
ModuleSubstreamKind Kind;
- msf::ReadableStreamRef Data;
+ BinaryStreamRef Data;
};
-typedef msf::VarStreamArray<ModuleSubstream> ModuleSubstreamArray;
+typedef VarStreamArray<ModuleSubstream> ModuleSubstreamArray;
} // namespace codeview
-namespace msf {
template <> struct VarStreamArrayExtractor<codeview::ModuleSubstream> {
- Error operator()(ReadableStreamRef Stream, uint32_t &Length,
+ Error operator()(BinaryStreamRef Stream, uint32_t &Length,
codeview::ModuleSubstream &Info) const {
if (auto EC = codeview::ModuleSubstream::initialize(Stream, Info))
return EC;
@@ -83,7 +82,6 @@ template <> struct VarStreamArrayExtractor<codeview::ModuleSubstream> {
return Error::success();
}
};
-} // namespace msf
} // namespace llvm
#endif // LLVM_DEBUGINFO_CODEVIEW_MODULESUBSTREAM_H
diff --git a/include/llvm/DebugInfo/CodeView/ModuleSubstreamVisitor.h b/include/llvm/DebugInfo/CodeView/ModuleSubstreamVisitor.h
index f9927d660933..1a40654a3f33 100644
--- a/include/llvm/DebugInfo/CodeView/ModuleSubstreamVisitor.h
+++ b/include/llvm/DebugInfo/CodeView/ModuleSubstreamVisitor.h
@@ -15,9 +15,9 @@
#include "llvm/DebugInfo/CodeView/CodeViewError.h"
#include "llvm/DebugInfo/CodeView/Line.h"
#include "llvm/DebugInfo/CodeView/ModuleSubstream.h"
-#include "llvm/DebugInfo/MSF/StreamArray.h"
-#include "llvm/DebugInfo/MSF/StreamReader.h"
-#include "llvm/DebugInfo/MSF/StreamRef.h"
+#include "llvm/Support/BinaryStreamArray.h"
+#include "llvm/Support/BinaryStreamReader.h"
+#include "llvm/Support/BinaryStreamRef.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/Error.h"
#include <cstdint>
@@ -28,8 +28,8 @@ namespace codeview {
struct LineColumnEntry {
support::ulittle32_t NameIndex;
- msf::FixedStreamArray<LineNumberEntry> LineNumbers;
- msf::FixedStreamArray<ColumnNumberEntry> Columns;
+ FixedStreamArray<LineNumberEntry> LineNumbers;
+ FixedStreamArray<ColumnNumberEntry> Columns;
};
struct FileChecksumEntry {
@@ -38,49 +38,47 @@ struct FileChecksumEntry {
ArrayRef<uint8_t> Checksum; // The bytes of the checksum.
};
-typedef msf::VarStreamArray<LineColumnEntry> LineInfoArray;
-typedef msf::VarStreamArray<FileChecksumEntry> FileChecksumArray;
+typedef VarStreamArray<LineColumnEntry> LineInfoArray;
+typedef VarStreamArray<FileChecksumEntry> FileChecksumArray;
class IModuleSubstreamVisitor {
public:
virtual ~IModuleSubstreamVisitor() = default;
virtual Error visitUnknown(ModuleSubstreamKind Kind,
- msf::ReadableStreamRef Data) = 0;
- virtual Error visitSymbols(msf::ReadableStreamRef Data);
- virtual Error visitLines(msf::ReadableStreamRef Data,
+ BinaryStreamRef Data) = 0;
+ virtual Error visitSymbols(BinaryStreamRef Data);
+ virtual Error visitLines(BinaryStreamRef Data,
const LineSubstreamHeader *Header,
const LineInfoArray &Lines);
- virtual Error visitStringTable(msf::ReadableStreamRef Data);
- virtual Error visitFileChecksums(msf::ReadableStreamRef Data,
+ virtual Error visitStringTable(BinaryStreamRef Data);
+ virtual Error visitFileChecksums(BinaryStreamRef Data,
const FileChecksumArray &Checksums);
- virtual Error visitFrameData(msf::ReadableStreamRef Data);
- virtual Error visitInlineeLines(msf::ReadableStreamRef Data);
- virtual Error visitCrossScopeImports(msf::ReadableStreamRef Data);
- virtual Error visitCrossScopeExports(msf::ReadableStreamRef Data);
- virtual Error visitILLines(msf::ReadableStreamRef Data);
- virtual Error visitFuncMDTokenMap(msf::ReadableStreamRef Data);
- virtual Error visitTypeMDTokenMap(msf::ReadableStreamRef Data);
- virtual Error visitMergedAssemblyInput(msf::ReadableStreamRef Data);
- virtual Error visitCoffSymbolRVA(msf::ReadableStreamRef Data);
+ virtual Error visitFrameData(BinaryStreamRef Data);
+ virtual Error visitInlineeLines(BinaryStreamRef Data);
+ virtual Error visitCrossScopeImports(BinaryStreamRef Data);
+ virtual Error visitCrossScopeExports(BinaryStreamRef Data);
+ virtual Error visitILLines(BinaryStreamRef Data);
+ virtual Error visitFuncMDTokenMap(BinaryStreamRef Data);
+ virtual Error visitTypeMDTokenMap(BinaryStreamRef Data);
+ virtual Error visitMergedAssemblyInput(BinaryStreamRef Data);
+ virtual Error visitCoffSymbolRVA(BinaryStreamRef Data);
};
Error visitModuleSubstream(const ModuleSubstream &R,
IModuleSubstreamVisitor &V);
} // end namespace codeview
-namespace msf {
-
template <> class VarStreamArrayExtractor<codeview::LineColumnEntry> {
public:
VarStreamArrayExtractor(const codeview::LineSubstreamHeader *Header)
: Header(Header) {}
- Error operator()(ReadableStreamRef Stream, uint32_t &Len,
+ Error operator()(BinaryStreamRef Stream, uint32_t &Len,
codeview::LineColumnEntry &Item) const {
using namespace codeview;
const LineFileBlockHeader *BlockHeader;
- StreamReader Reader(Stream);
+ BinaryStreamReader Reader(Stream);
if (auto EC = Reader.readObject(BlockHeader))
return EC;
bool HasColumn = Header->Flags & LineFlags::HaveColumns;
@@ -113,11 +111,11 @@ private:
template <> class VarStreamArrayExtractor<codeview::FileChecksumEntry> {
public:
- Error operator()(ReadableStreamRef Stream, uint32_t &Len,
+ Error operator()(BinaryStreamRef Stream, uint32_t &Len,
codeview::FileChecksumEntry &Item) const {
using namespace codeview;
const FileChecksum *Header;
- StreamReader Reader(Stream);
+ BinaryStreamReader Reader(Stream);
if (auto EC = Reader.readObject(Header))
return EC;
Item.FileNameOffset = Header->FileNameOffset;
@@ -129,8 +127,6 @@ public:
}
};
-} // end namespace msf
-
} // end namespace llvm
#endif // LLVM_DEBUGINFO_CODEVIEW_MODULESUBSTREAMVISITOR_H
diff --git a/include/llvm/DebugInfo/CodeView/RecordSerialization.h b/include/llvm/DebugInfo/CodeView/RecordSerialization.h
index 97b6f561bb97..58449c2c7565 100644
--- a/include/llvm/DebugInfo/CodeView/RecordSerialization.h
+++ b/include/llvm/DebugInfo/CodeView/RecordSerialization.h
@@ -15,7 +15,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/DebugInfo/CodeView/CodeViewError.h"
-#include "llvm/DebugInfo/MSF/StreamReader.h"
+#include "llvm/Support/BinaryStreamReader.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/Error.h"
#include <cinttypes>
@@ -41,37 +41,37 @@ struct RecordPrefix {
StringRef getBytesAsCharacters(ArrayRef<uint8_t> LeafData);
StringRef getBytesAsCString(ArrayRef<uint8_t> LeafData);
-inline Error consume(msf::StreamReader &Reader) { return Error::success(); }
+inline Error consume(BinaryStreamReader &Reader) { return Error::success(); }
/// Decodes a numeric "leaf" value. These are integer literals encountered in
/// the type stream. If the value is positive and less than LF_NUMERIC (1 <<
/// 15), it is emitted directly in Data. Otherwise, it has a tag like LF_CHAR
/// that indicates the bitwidth and sign of the numeric data.
-Error consume(msf::StreamReader &Reader, APSInt &Num);
+Error consume(BinaryStreamReader &Reader, APSInt &Num);
/// Decodes a numeric leaf value that is known to be a particular type.
-Error consume_numeric(msf::StreamReader &Reader, uint64_t &Value);
+Error consume_numeric(BinaryStreamReader &Reader, uint64_t &Value);
/// Decodes signed and unsigned fixed-length integers.
-Error consume(msf::StreamReader &Reader, uint32_t &Item);
-Error consume(msf::StreamReader &Reader, int32_t &Item);
+Error consume(BinaryStreamReader &Reader, uint32_t &Item);
+Error consume(BinaryStreamReader &Reader, int32_t &Item);
/// Decodes a null terminated string.
-Error consume(msf::StreamReader &Reader, StringRef &Item);
+Error consume(BinaryStreamReader &Reader, StringRef &Item);
Error consume(StringRef &Data, APSInt &Num);
Error consume(StringRef &Data, uint32_t &Item);
/// Decodes an arbitrary object whose layout matches that of the underlying
/// byte sequence, and returns a pointer to the object.
-template <typename T> Error consume(msf::StreamReader &Reader, T *&Item) {
+template <typename T> Error consume(BinaryStreamReader &Reader, T *&Item) {
return Reader.readObject(Item);
}
template <typename T, typename U> struct serialize_conditional_impl {
serialize_conditional_impl(T &Item, U Func) : Item(Item), Func(Func) {}
- Error deserialize(msf::StreamReader &Reader) const {
+ Error deserialize(BinaryStreamReader &Reader) const {
if (!Func())
return Error::success();
return consume(Reader, Item);
@@ -89,7 +89,7 @@ serialize_conditional_impl<T, U> serialize_conditional(T &Item, U Func) {
template <typename T, typename U> struct serialize_array_impl {
serialize_array_impl(ArrayRef<T> &Item, U Func) : Item(Item), Func(Func) {}
- Error deserialize(msf::StreamReader &Reader) const {
+ Error deserialize(BinaryStreamReader &Reader) const {
return Reader.readArray(Item, Func());
}
@@ -100,7 +100,7 @@ template <typename T, typename U> struct serialize_array_impl {
template <typename T> struct serialize_vector_tail_impl {
serialize_vector_tail_impl(std::vector<T> &Item) : Item(Item) {}
- Error deserialize(msf::StreamReader &Reader) const {
+ Error deserialize(BinaryStreamReader &Reader) const {
T Field;
// Stop when we run out of bytes or we hit record padding bytes.
while (!Reader.empty() && Reader.peek() < LF_PAD0) {
@@ -118,14 +118,14 @@ struct serialize_null_term_string_array_impl {
serialize_null_term_string_array_impl(std::vector<StringRef> &Item)
: Item(Item) {}
- Error deserialize(msf::StreamReader &Reader) const {
+ Error deserialize(BinaryStreamReader &Reader) const {
if (Reader.empty())
return make_error<CodeViewError>(cv_error_code::insufficient_buffer,
"Null terminated string is empty!");
while (Reader.peek() != 0) {
StringRef Field;
- if (auto EC = Reader.readZeroString(Field))
+ if (auto EC = Reader.readCString(Field))
return EC;
Item.push_back(Field);
}
@@ -138,7 +138,7 @@ struct serialize_null_term_string_array_impl {
template <typename T> struct serialize_arrayref_tail_impl {
serialize_arrayref_tail_impl(ArrayRef<T> &Item) : Item(Item) {}
- Error deserialize(msf::StreamReader &Reader) const {
+ Error deserialize(BinaryStreamReader &Reader) const {
uint32_t Count = Reader.bytesRemaining() / sizeof(T);
return Reader.readArray(Item, Count);
}
@@ -149,7 +149,7 @@ template <typename T> struct serialize_arrayref_tail_impl {
template <typename T> struct serialize_numeric_impl {
serialize_numeric_impl(T &Item) : Item(Item) {}
- Error deserialize(msf::StreamReader &Reader) const {
+ Error deserialize(BinaryStreamReader &Reader) const {
return consume_numeric(Reader, Item);
}
@@ -201,42 +201,42 @@ template <typename T> serialize_numeric_impl<T> serialize_numeric(T &Item) {
#define CV_NUMERIC_FIELD(I) serialize_numeric(I)
template <typename T, typename U>
-Error consume(msf::StreamReader &Reader,
+Error consume(BinaryStreamReader &Reader,
const serialize_conditional_impl<T, U> &Item) {
return Item.deserialize(Reader);
}
template <typename T, typename U>
-Error consume(msf::StreamReader &Reader,
+Error consume(BinaryStreamReader &Reader,
const serialize_array_impl<T, U> &Item) {
return Item.deserialize(Reader);
}
-inline Error consume(msf::StreamReader &Reader,
+inline Error consume(BinaryStreamReader &Reader,
const serialize_null_term_string_array_impl &Item) {
return Item.deserialize(Reader);
}
template <typename T>
-Error consume(msf::StreamReader &Reader,
+Error consume(BinaryStreamReader &Reader,
const serialize_vector_tail_impl<T> &Item) {
return Item.deserialize(Reader);
}
template <typename T>
-Error consume(msf::StreamReader &Reader,
+Error consume(BinaryStreamReader &Reader,
const serialize_arrayref_tail_impl<T> &Item) {
return Item.deserialize(Reader);
}
template <typename T>
-Error consume(msf::StreamReader &Reader,
+Error consume(BinaryStreamReader &Reader,
const serialize_numeric_impl<T> &Item) {
return Item.deserialize(Reader);
}
template <typename T, typename U, typename... Args>
-Error consume(msf::StreamReader &Reader, T &&X, U &&Y, Args &&... Rest) {
+Error consume(BinaryStreamReader &Reader, T &&X, U &&Y, Args &&... Rest) {
if (auto EC = consume(Reader, X))
return EC;
return consume(Reader, Y, std::forward<Args>(Rest)...);
diff --git a/include/llvm/DebugInfo/CodeView/SymbolDeserializer.h b/include/llvm/DebugInfo/CodeView/SymbolDeserializer.h
index 13c2bb14ecf5..c1a5152930ff 100644
--- a/include/llvm/DebugInfo/CodeView/SymbolDeserializer.h
+++ b/include/llvm/DebugInfo/CodeView/SymbolDeserializer.h
@@ -15,8 +15,8 @@
#include "llvm/DebugInfo/CodeView/SymbolRecordMapping.h"
#include "llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h"
#include "llvm/DebugInfo/CodeView/SymbolVisitorDelegate.h"
-#include "llvm/DebugInfo/MSF/ByteStream.h"
-#include "llvm/DebugInfo/MSF/StreamReader.h"
+#include "llvm/Support/BinaryByteStream.h"
+#include "llvm/Support/BinaryStreamReader.h"
#include "llvm/Support/Error.h"
namespace llvm {
@@ -25,10 +25,11 @@ class SymbolVisitorDelegate;
class SymbolDeserializer : public SymbolVisitorCallbacks {
struct MappingInfo {
explicit MappingInfo(ArrayRef<uint8_t> RecordData)
- : Stream(RecordData), Reader(Stream), Mapping(Reader) {}
+ : Stream(RecordData, llvm::support::little), Reader(Stream),
+ Mapping(Reader) {}
- msf::ByteStream Stream;
- msf::StreamReader Reader;
+ BinaryByteStream Stream;
+ BinaryStreamReader Reader;
SymbolRecordMapping Mapping;
};
diff --git a/include/llvm/DebugInfo/CodeView/SymbolRecord.h b/include/llvm/DebugInfo/CodeView/SymbolRecord.h
index 57772d39e972..c5a5549bf818 100644
--- a/include/llvm/DebugInfo/CodeView/SymbolRecord.h
+++ b/include/llvm/DebugInfo/CodeView/SymbolRecord.h
@@ -13,13 +13,13 @@
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/Optional.h"
-#include "llvm/ADT/iterator_range.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/iterator_range.h"
#include "llvm/DebugInfo/CodeView/CVRecord.h"
#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/DebugInfo/CodeView/RecordSerialization.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
-#include "llvm/DebugInfo/MSF/StreamArray.h"
+#include "llvm/Support/BinaryStreamArray.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/Error.h"
#include <cstddef>
@@ -176,7 +176,7 @@ struct BinaryAnnotationIterator {
return Data == Other.Data;
}
- bool operator!=(BinaryAnnotationIterator Other) const {
+ bool operator!=(const BinaryAnnotationIterator &Other) const {
return !(*this == Other);
}
@@ -938,7 +938,7 @@ public:
};
typedef CVRecord<SymbolKind> CVSymbol;
-typedef msf::VarStreamArray<CVSymbol> CVSymbolArray;
+typedef VarStreamArray<CVSymbol> CVSymbolArray;
} // end namespace codeview
} // end namespace llvm
diff --git a/include/llvm/DebugInfo/CodeView/SymbolRecordMapping.h b/include/llvm/DebugInfo/CodeView/SymbolRecordMapping.h
index 1bd14ed1347a..0a1837a0d935 100644
--- a/include/llvm/DebugInfo/CodeView/SymbolRecordMapping.h
+++ b/include/llvm/DebugInfo/CodeView/SymbolRecordMapping.h
@@ -14,16 +14,14 @@
#include "llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h"
namespace llvm {
-namespace msf {
-class StreamReader;
-class StreamWriter;
-}
+class BinaryStreamReader;
+class BinaryStreamWriter;
namespace codeview {
class SymbolRecordMapping : public SymbolVisitorCallbacks {
public:
- explicit SymbolRecordMapping(msf::StreamReader &Reader) : IO(Reader) {}
- explicit SymbolRecordMapping(msf::StreamWriter &Writer) : IO(Writer) {}
+ explicit SymbolRecordMapping(BinaryStreamReader &Reader) : IO(Reader) {}
+ explicit SymbolRecordMapping(BinaryStreamWriter &Writer) : IO(Writer) {}
Error visitSymbolBegin(CVSymbol &Record) override;
Error visitSymbolEnd(CVSymbol &Record) override;
diff --git a/include/llvm/DebugInfo/CodeView/SymbolSerializer.h b/include/llvm/DebugInfo/CodeView/SymbolSerializer.h
index 4eb914e7ae6b..f2e99bd83326 100644
--- a/include/llvm/DebugInfo/CodeView/SymbolSerializer.h
+++ b/include/llvm/DebugInfo/CodeView/SymbolSerializer.h
@@ -12,8 +12,6 @@
#include "llvm/DebugInfo/CodeView/SymbolRecordMapping.h"
#include "llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h"
-#include "llvm/DebugInfo/MSF/ByteStream.h"
-#include "llvm/DebugInfo/MSF/StreamWriter.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallVector.h"
@@ -21,14 +19,19 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/Allocator.h"
+#include "llvm/Support/BinaryByteStream.h"
+#include "llvm/Support/BinaryStreamWriter.h"
#include "llvm/Support/Error.h"
namespace llvm {
+class BinaryStreamWriter;
namespace codeview {
class SymbolSerializer : public SymbolVisitorCallbacks {
- uint32_t RecordStart = 0;
- msf::StreamWriter &Writer;
+ BumpPtrAllocator &Storage;
+ std::vector<uint8_t> RecordBuffer;
+ MutableBinaryByteStream Stream;
+ BinaryStreamWriter Writer;
SymbolRecordMapping Mapping;
Optional<SymbolKind> CurrentSymbol;
@@ -42,40 +45,10 @@ class SymbolSerializer : public SymbolVisitorCallbacks {
}
public:
- explicit SymbolSerializer(msf::StreamWriter &Writer)
- : Writer(Writer), Mapping(Writer) {}
+ explicit SymbolSerializer(BumpPtrAllocator &Storage);
- virtual Error visitSymbolBegin(CVSymbol &Record) override {
- assert(!CurrentSymbol.hasValue() && "Already in a symbol mapping!");
-
- RecordStart = Writer.getOffset();
- if (auto EC = writeRecordPrefix(Record.kind()))
- return EC;
-
- CurrentSymbol = Record.kind();
- if (auto EC = Mapping.visitSymbolBegin(Record))
- return EC;
-
- return Error::success();
- }
-
- virtual Error visitSymbolEnd(CVSymbol &Record) override {
- assert(CurrentSymbol.hasValue() && "Not in a symbol mapping!");
-
- if (auto EC = Mapping.visitSymbolEnd(Record))
- return EC;
-
- uint32_t RecordEnd = Writer.getOffset();
- Writer.setOffset(RecordStart);
- uint16_t Length = RecordEnd - Writer.getOffset() - 2;
- if (auto EC = Writer.writeInteger(Length))
- return EC;
-
- Writer.setOffset(RecordEnd);
- CurrentSymbol.reset();
-
- return Error::success();
- }
+ virtual Error visitSymbolBegin(CVSymbol &Record) override;
+ virtual Error visitSymbolEnd(CVSymbol &Record) override;
#define SYMBOL_RECORD(EnumName, EnumVal, Name) \
virtual Error visitKnownRecord(CVSymbol &CVR, Name &Record) override { \
diff --git a/include/llvm/DebugInfo/CodeView/SymbolVisitorDelegate.h b/include/llvm/DebugInfo/CodeView/SymbolVisitorDelegate.h
index 2b468a289fd8..2bef3f61adfc 100644
--- a/include/llvm/DebugInfo/CodeView/SymbolVisitorDelegate.h
+++ b/include/llvm/DebugInfo/CodeView/SymbolVisitorDelegate.h
@@ -15,9 +15,7 @@
namespace llvm {
-namespace msf {
-class StreamReader;
-} // end namespace msf
+class BinaryStreamReader;
namespace codeview {
@@ -25,7 +23,7 @@ class SymbolVisitorDelegate {
public:
virtual ~SymbolVisitorDelegate() = default;
- virtual uint32_t getRecordOffset(msf::StreamReader Reader) = 0;
+ virtual uint32_t getRecordOffset(BinaryStreamReader Reader) = 0;
virtual StringRef getFileNameForFileOffset(uint32_t FileOffset) = 0;
virtual StringRef getStringTable() = 0;
};
diff --git a/include/llvm/DebugInfo/CodeView/TypeDatabase.h b/include/llvm/DebugInfo/CodeView/TypeDatabase.h
index cccc2868ffb5..54ad862cfa7e 100644
--- a/include/llvm/DebugInfo/CodeView/TypeDatabase.h
+++ b/include/llvm/DebugInfo/CodeView/TypeDatabase.h
@@ -27,13 +27,15 @@ public:
TypeIndex getNextTypeIndex() const;
/// Records the name of a type, and reserves its type index.
- void recordType(StringRef Name, CVType Data);
+ void recordType(StringRef Name, const CVType &Data);
/// Saves the name in a StringSet and creates a stable StringRef.
StringRef saveTypeName(StringRef TypeName);
StringRef getTypeName(TypeIndex Index) const;
+ const CVType &getTypeRecord(TypeIndex Index) const;
+
bool containsTypeIndex(TypeIndex Index) const;
uint32_t size() const;
diff --git a/include/llvm/DebugInfo/CodeView/TypeDeserializer.h b/include/llvm/DebugInfo/CodeView/TypeDeserializer.h
index dc5eaf82845b..0e3443789170 100644
--- a/include/llvm/DebugInfo/CodeView/TypeDeserializer.h
+++ b/include/llvm/DebugInfo/CodeView/TypeDeserializer.h
@@ -16,8 +16,8 @@
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/DebugInfo/CodeView/TypeRecordMapping.h"
#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
-#include "llvm/DebugInfo/MSF/ByteStream.h"
-#include "llvm/DebugInfo/MSF/StreamReader.h"
+#include "llvm/Support/BinaryByteStream.h"
+#include "llvm/Support/BinaryStreamReader.h"
#include "llvm/Support/Error.h"
#include <cassert>
#include <cstdint>
@@ -29,10 +29,11 @@ namespace codeview {
class TypeDeserializer : public TypeVisitorCallbacks {
struct MappingInfo {
explicit MappingInfo(ArrayRef<uint8_t> RecordData)
- : Stream(RecordData), Reader(Stream), Mapping(Reader) {}
+ : Stream(RecordData, llvm::support::little), Reader(Stream),
+ Mapping(Reader) {}
- msf::ByteStream Stream;
- msf::StreamReader Reader;
+ BinaryByteStream Stream;
+ BinaryStreamReader Reader;
TypeRecordMapping Mapping;
};
@@ -72,16 +73,16 @@ private:
class FieldListDeserializer : public TypeVisitorCallbacks {
struct MappingInfo {
- explicit MappingInfo(msf::StreamReader &R)
+ explicit MappingInfo(BinaryStreamReader &R)
: Reader(R), Mapping(Reader), StartOffset(0) {}
- msf::StreamReader &Reader;
+ BinaryStreamReader &Reader;
TypeRecordMapping Mapping;
uint32_t StartOffset;
};
public:
- explicit FieldListDeserializer(msf::StreamReader &Reader) : Mapping(Reader) {
+ explicit FieldListDeserializer(BinaryStreamReader &Reader) : Mapping(Reader) {
CVType FieldList;
FieldList.Type = TypeLeafKind::LF_FIELDLIST;
consumeError(Mapping.Mapping.visitTypeBegin(FieldList));
diff --git a/include/llvm/DebugInfo/CodeView/TypeDumpVisitor.h b/include/llvm/DebugInfo/CodeView/TypeDumpVisitor.h
index a466e4298158..00bb09137e48 100644
--- a/include/llvm/DebugInfo/CodeView/TypeDumpVisitor.h
+++ b/include/llvm/DebugInfo/CodeView/TypeDumpVisitor.h
@@ -28,8 +28,16 @@ public:
TypeDumpVisitor(TypeDatabase &TypeDB, ScopedPrinter *W, bool PrintRecordBytes)
: W(W), PrintRecordBytes(PrintRecordBytes), TypeDB(TypeDB) {}
+ /// When dumping types from an IPI stream in a PDB, a type index may refer to
+ /// a type or an item ID. The dumper will lookup the "name" of the index in
+ /// the item database if appropriate. If ItemDB is null, it will use TypeDB,
+ /// which is correct when dumping types from an object file (/Z7).
+ void setItemDB(TypeDatabase &DB) { ItemDB = &DB; }
+
void printTypeIndex(StringRef FieldName, TypeIndex TI) const;
+ void printItemIndex(StringRef FieldName, TypeIndex TI) const;
+
/// Action to take on unknown types. By default, they are ignored.
Error visitUnknownType(CVType &Record) override;
Error visitUnknownMember(CVMemberRecord &Record) override;
@@ -54,11 +62,17 @@ private:
void printMemberAttributes(MemberAccess Access, MethodKind Kind,
MethodOptions Options);
+ /// Get the database of indices for the stream that we are dumping. If ItemDB
+ /// is set, then we must be dumping an item (IPI) stream. This will also
+ /// always get the appropriate DB for printing item names.
+ TypeDatabase &getSourceDB() const { return ItemDB ? *ItemDB : TypeDB; }
+
ScopedPrinter *W;
bool PrintRecordBytes = false;
TypeDatabase &TypeDB;
+ TypeDatabase *ItemDB = nullptr;
};
} // end namespace codeview
diff --git a/include/llvm/DebugInfo/CodeView/TypeRecord.h b/include/llvm/DebugInfo/CodeView/TypeRecord.h
index 4f1c047815d2..1f10872c8768 100644
--- a/include/llvm/DebugInfo/CodeView/TypeRecord.h
+++ b/include/llvm/DebugInfo/CodeView/TypeRecord.h
@@ -18,7 +18,7 @@
#include "llvm/DebugInfo/CodeView/CVRecord.h"
#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
-#include "llvm/DebugInfo/MSF/StreamArray.h"
+#include "llvm/Support/BinaryStreamArray.h"
#include "llvm/Support/Endian.h"
#include <algorithm>
#include <cstdint>
@@ -26,9 +26,7 @@
namespace llvm {
-namespace msf {
-class StreamReader;
-} // end namespace msf
+class BinaryStreamReader;
namespace codeview {
@@ -42,7 +40,8 @@ struct CVMemberRecord {
TypeLeafKind Kind;
ArrayRef<uint8_t> Data;
};
-typedef msf::VarStreamArray<CVType> CVTypeArray;
+typedef VarStreamArray<CVType> CVTypeArray;
+typedef iterator_range<CVTypeArray::Iterator> CVTypeRange;
/// Equvalent to CV_fldattr_t in cvinfo.h.
struct MemberAttributes {
@@ -106,10 +105,6 @@ public:
PointerToMemberRepresentation Representation)
: ContainingType(ContainingType), Representation(Representation) {}
- /// Rewrite member type indices with IndexMap. Returns false if a type index
- /// is not in the map.
- bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
-
TypeIndex getContainingType() const { return ContainingType; }
PointerToMemberRepresentation getRepresentation() const {
return Representation;
@@ -139,10 +134,6 @@ public:
: TypeRecord(TypeRecordKind::Modifier), ModifiedType(ModifiedType),
Modifiers(Modifiers) {}
- /// Rewrite member type indices with IndexMap. Returns false if a type index
- /// is not in the map.
- bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
-
TypeIndex getModifiedType() const { return ModifiedType; }
ModifierOptions getModifiers() const { return Modifiers; }
@@ -161,10 +152,6 @@ public:
CallConv(CallConv), Options(Options), ParameterCount(ParameterCount),
ArgumentList(ArgumentList) {}
- /// Rewrite member type indices with IndexMap. Returns false if a type index
- /// is not in the map.
- bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
-
TypeIndex getReturnType() const { return ReturnType; }
CallingConvention getCallConv() const { return CallConv; }
FunctionOptions getOptions() const { return Options; }
@@ -193,10 +180,6 @@ public:
ArgumentList(ArgumentList),
ThisPointerAdjustment(ThisPointerAdjustment) {}
- /// Rewrite member type indices with IndexMap. Returns false if a type index
- /// is not in the map.
- bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
-
TypeIndex getReturnType() const { return ReturnType; }
TypeIndex getClassType() const { return ClassType; }
TypeIndex getThisType() const { return ThisType; }
@@ -216,6 +199,16 @@ public:
int32_t ThisPointerAdjustment;
};
+// LF_LABEL
+class LabelRecord : public TypeRecord {
+public:
+ explicit LabelRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
+
+ LabelRecord(LabelType Mode) : TypeRecord(TypeRecordKind::Label), Mode(Mode) {}
+
+ LabelType Mode;
+};
+
// LF_MFUNC_ID
class MemberFuncIdRecord : public TypeRecord {
public:
@@ -225,10 +218,6 @@ public:
: TypeRecord(TypeRecordKind::MemberFuncId), ClassType(ClassType),
FunctionType(FunctionType), Name(Name) {}
- /// Rewrite member type indices with IndexMap. Returns false if a type index
- /// is not in the map.
- bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
-
TypeIndex getClassType() const { return ClassType; }
TypeIndex getFunctionType() const { return FunctionType; }
StringRef getName() const { return Name; }
@@ -237,17 +226,26 @@ public:
StringRef Name;
};
-// LF_ARGLIST, LF_SUBSTR_LIST
+// LF_ARGLIST
class ArgListRecord : public TypeRecord {
public:
explicit ArgListRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
ArgListRecord(TypeRecordKind Kind, ArrayRef<TypeIndex> Indices)
- : TypeRecord(Kind), StringIndices(Indices) {}
+ : TypeRecord(Kind), ArgIndices(Indices) {}
- /// Rewrite member type indices with IndexMap. Returns false if a type index
- /// is not in the map.
- bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
+ ArrayRef<TypeIndex> getIndices() const { return ArgIndices; }
+
+ std::vector<TypeIndex> ArgIndices;
+};
+
+// LF_SUBSTR_LIST
+class StringListRecord : public TypeRecord {
+public:
+ explicit StringListRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
+
+ StringListRecord(TypeRecordKind Kind, ArrayRef<TypeIndex> Indices)
+ : TypeRecord(Kind), StringIndices(Indices) {}
ArrayRef<TypeIndex> getIndices() const { return StringIndices; }
@@ -290,10 +288,6 @@ public:
: TypeRecord(TypeRecordKind::Pointer), ReferentType(ReferentType),
Attrs(Attrs), MemberInfo(Member) {}
- /// Rewrite member type indices with IndexMap. Returns false if a type index
- /// is not in the map.
- bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
-
TypeIndex getReferentType() const { return ReferentType; }
PointerKind getPointerKind() const {
@@ -356,10 +350,6 @@ public:
NestedTypeRecord(TypeIndex Type, StringRef Name)
: TypeRecord(TypeRecordKind::NestedType), Type(Type), Name(Name) {}
- /// Rewrite member type indices with IndexMap. Returns false if a type index
- /// is not in the map.
- bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
-
TypeIndex getNestedType() const { return Type; }
StringRef getName() const { return Name; }
@@ -374,10 +364,6 @@ public:
explicit FieldListRecord(ArrayRef<uint8_t> Data)
: TypeRecord(TypeRecordKind::FieldList), Data(Data) {}
- /// Rewrite member type indices with IndexMap. Returns false if a type index
- /// is not in the map.
- bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap) { return false; }
-
ArrayRef<uint8_t> Data;
};
@@ -390,10 +376,6 @@ public:
: TypeRecord(TypeRecordKind::Array), ElementType(ElementType),
IndexType(IndexType), Size(Size), Name(Name) {}
- /// Rewrite member type indices with IndexMap. Returns false if a type index
- /// is not in the map.
- bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
-
TypeIndex getElementType() const { return ElementType; }
TypeIndex getIndexType() const { return IndexType; }
uint64_t getSize() const { return Size; }
@@ -414,10 +396,6 @@ protected:
FieldList(FieldList), Name(Name), UniqueName(UniqueName) {}
public:
- /// Rewrite member type indices with IndexMap. Returns false if a type index
- /// is not in the map.
- bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
-
static const int HfaKindShift = 11;
static const int HfaKindMask = 0x1800;
static const int WinRTKindShift = 14;
@@ -451,10 +429,6 @@ public:
: TagRecord(Kind, MemberCount, Options, FieldList, Name, UniqueName),
DerivationList(DerivationList), VTableShape(VTableShape), Size(Size) {}
- /// Rewrite member type indices with IndexMap. Returns false if a type index
- /// is not in the map.
- bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
-
HfaKind getHfa() const {
uint16_t Value = static_cast<uint16_t>(Options);
Value = (Value & HfaKindMask) >> HfaKindShift;
@@ -506,9 +480,6 @@ public:
UniqueName),
UnderlyingType(UnderlyingType) {}
- /// Rewrite member type indices with IndexMap. Returns false if a type index is not in the map.
- bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
-
TypeIndex getUnderlyingType() const { return UnderlyingType; }
TypeIndex UnderlyingType;
};
@@ -521,10 +492,6 @@ public:
: TypeRecord(TypeRecordKind::BitField), Type(Type), BitSize(BitSize),
BitOffset(BitOffset) {}
- /// Rewrite member type indices with IndexMap. Returns false if a type index
- /// is not in the map.
- bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
-
TypeIndex getType() const { return Type; }
uint8_t getBitOffset() const { return BitOffset; }
uint8_t getBitSize() const { return BitSize; }
@@ -542,10 +509,6 @@ public:
explicit VFTableShapeRecord(std::vector<VFTableSlotKind> Slots)
: TypeRecord(TypeRecordKind::VFTableShape), Slots(std::move(Slots)) {}
- /// Rewrite member type indices with IndexMap. Returns false if a type index
- /// is not in the map.
- bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
-
ArrayRef<VFTableSlotKind> getSlots() const {
if (!SlotsRef.empty())
return SlotsRef;
@@ -565,10 +528,6 @@ public:
: TypeRecord(TypeRecordKind::TypeServer2), Guid(Guid), Age(Age),
Name(Name) {}
- /// Rewrite member type indices with IndexMap. Returns false if a type index
- /// is not in the map.
- bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
-
StringRef getGuid() const { return Guid; }
uint32_t getAge() const { return Age; }
@@ -587,10 +546,6 @@ public:
StringIdRecord(TypeIndex Id, StringRef String)
: TypeRecord(TypeRecordKind::StringId), Id(Id), String(String) {}
- /// Rewrite member type indices with IndexMap. Returns false if a type index
- /// is not in the map.
- bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
-
TypeIndex getId() const { return Id; }
StringRef getString() const { return String; }
@@ -606,10 +561,6 @@ public:
: TypeRecord(TypeRecordKind::FuncId), ParentScope(ParentScope),
FunctionType(FunctionType), Name(Name) {}
- /// Rewrite member type indices with IndexMap. Returns false if a type index
- /// is not in the map.
- bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
-
TypeIndex getParentScope() const { return ParentScope; }
TypeIndex getFunctionType() const { return FunctionType; }
@@ -629,10 +580,6 @@ public:
: TypeRecord(TypeRecordKind::UdtSourceLine), UDT(UDT),
SourceFile(SourceFile), LineNumber(LineNumber) {}
- /// Rewrite member type indices with IndexMap. Returns false if a type index
- /// is not in the map.
- bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
-
TypeIndex getUDT() const { return UDT; }
TypeIndex getSourceFile() const { return SourceFile; }
uint32_t getLineNumber() const { return LineNumber; }
@@ -651,8 +598,6 @@ public:
: TypeRecord(TypeRecordKind::UdtSourceLine), UDT(UDT),
SourceFile(SourceFile), LineNumber(LineNumber), Module(Module) {}
- bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
-
TypeIndex getUDT() const { return UDT; }
TypeIndex getSourceFile() const { return SourceFile; }
uint32_t getLineNumber() const { return LineNumber; }
@@ -672,10 +617,6 @@ public:
: TypeRecord(TypeRecordKind::BuildInfo),
ArgIndices(ArgIndices.begin(), ArgIndices.end()) {}
- /// Rewrite member type indices with IndexMap. Returns false if a type index
- /// is not in the map.
- bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
-
ArrayRef<TypeIndex> getArgs() const { return ArgIndices; }
SmallVector<TypeIndex, 4> ArgIndices;
};
@@ -693,10 +634,6 @@ public:
MethodNames.insert(MethodNames.end(), Methods.begin(), Methods.end());
}
- /// Rewrite member type indices with IndexMap. Returns false if a type index
- /// is not in the map.
- bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
-
TypeIndex getCompleteClass() const { return CompleteClass; }
TypeIndex getOverriddenVTable() const { return OverriddenVFTable; }
uint32_t getVFPtrOffset() const { return VFPtrOffset; }
@@ -725,10 +662,6 @@ public:
: TypeRecord(TypeRecordKind::OneMethod), Type(Type),
Attrs(Access, MK, Options), VFTableOffset(VFTableOffset), Name(Name) {}
- /// Rewrite member type indices with IndexMap. Returns false if a type index
- /// is not in the map.
- bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
-
TypeIndex getType() const { return Type; }
MethodKind getMethodKind() const { return Attrs.getMethodKind(); }
MethodOptions getOptions() const { return Attrs.getFlags(); }
@@ -754,10 +687,6 @@ public:
MethodOverloadListRecord(ArrayRef<OneMethodRecord> Methods)
: TypeRecord(TypeRecordKind::MethodOverloadList), Methods(Methods) {}
- /// Rewrite member type indices with IndexMap. Returns false if a type index
- /// is not in the map.
- bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
-
ArrayRef<OneMethodRecord> getMethods() const { return Methods; }
std::vector<OneMethodRecord> Methods;
};
@@ -771,10 +700,6 @@ public:
: TypeRecord(TypeRecordKind::OverloadedMethod),
NumOverloads(NumOverloads), MethodList(MethodList), Name(Name) {}
- /// Rewrite member type indices with IndexMap. Returns false if a type index
- /// is not in the map.
- bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
-
uint16_t getNumOverloads() const { return NumOverloads; }
TypeIndex getMethodList() const { return MethodList; }
StringRef getName() const { return Name; }
@@ -796,10 +721,6 @@ public:
: TypeRecord(TypeRecordKind::DataMember), Attrs(Access), Type(Type),
FieldOffset(Offset), Name(Name) {}
- /// Rewrite member type indices with IndexMap. Returns false if a type index
- /// is not in the map.
- bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
-
MemberAccess getAccess() const { return Attrs.getAccess(); }
TypeIndex getType() const { return Type; }
uint64_t getFieldOffset() const { return FieldOffset; }
@@ -822,10 +743,6 @@ public:
: TypeRecord(TypeRecordKind::StaticDataMember), Attrs(Access), Type(Type),
Name(Name) {}
- /// Rewrite member type indices with IndexMap. Returns false if a type index
- /// is not in the map.
- bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
-
MemberAccess getAccess() const { return Attrs.getAccess(); }
TypeIndex getType() const { return Type; }
StringRef getName() const { return Name; }
@@ -846,10 +763,6 @@ public:
: TypeRecord(TypeRecordKind::Enumerator), Attrs(Access),
Value(std::move(Value)), Name(Name) {}
- /// Rewrite member type indices with IndexMap. Returns false if a type index
- /// is not in the map.
- bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
-
MemberAccess getAccess() const { return Attrs.getAccess(); }
APSInt getValue() const { return Value; }
StringRef getName() const { return Name; }
@@ -866,10 +779,6 @@ public:
VFPtrRecord(TypeIndex Type)
: TypeRecord(TypeRecordKind::VFPtr), Type(Type) {}
- /// Rewrite member type indices with IndexMap. Returns false if a type index
- /// is not in the map.
- bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
-
TypeIndex getType() const { return Type; }
TypeIndex Type;
@@ -886,10 +795,6 @@ public:
: TypeRecord(TypeRecordKind::BaseClass), Attrs(Access), Type(Type),
Offset(Offset) {}
- /// Rewrite member type indices with IndexMap. Returns false if a type index
- /// is not in the map.
- bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
-
MemberAccess getAccess() const { return Attrs.getAccess(); }
TypeIndex getBaseType() const { return Type; }
uint64_t getBaseOffset() const { return Offset; }
@@ -914,10 +819,6 @@ public:
: TypeRecord(Kind), Attrs(Access), BaseType(BaseType),
VBPtrType(VBPtrType), VBPtrOffset(Offset), VTableIndex(Index) {}
- /// Rewrite member type indices with IndexMap. Returns false if a type index
- /// is not in the map.
- bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
-
MemberAccess getAccess() const { return Attrs.getAccess(); }
TypeIndex getBaseType() const { return BaseType; }
TypeIndex getVBPtrType() const { return VBPtrType; }
@@ -942,8 +843,6 @@ public:
TypeIndex getContinuationIndex() const { return ContinuationIndex; }
- bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap);
-
TypeIndex ContinuationIndex;
};
diff --git a/include/llvm/DebugInfo/CodeView/TypeRecordMapping.h b/include/llvm/DebugInfo/CodeView/TypeRecordMapping.h
index fe470a72abbb..924ca0470fad 100644
--- a/include/llvm/DebugInfo/CodeView/TypeRecordMapping.h
+++ b/include/llvm/DebugInfo/CodeView/TypeRecordMapping.h
@@ -16,15 +16,14 @@
#include "llvm/Support/Error.h"
namespace llvm {
-namespace msf {
-class StreamReader;
-class StreamWriter;
-}
+class BinaryStreamReader;
+class BinaryStreamWriter;
+
namespace codeview {
class TypeRecordMapping : public TypeVisitorCallbacks {
public:
- explicit TypeRecordMapping(msf::StreamReader &Reader) : IO(Reader) {}
- explicit TypeRecordMapping(msf::StreamWriter &Writer) : IO(Writer) {}
+ explicit TypeRecordMapping(BinaryStreamReader &Reader) : IO(Reader) {}
+ explicit TypeRecordMapping(BinaryStreamWriter &Writer) : IO(Writer) {}
Error visitTypeBegin(CVType &Record) override;
Error visitTypeEnd(CVType &Record) override;
diff --git a/include/llvm/DebugInfo/CodeView/TypeRecords.def b/include/llvm/DebugInfo/CodeView/TypeRecords.def
index c98dbac21a7a..8c193bb13cb7 100644
--- a/include/llvm/DebugInfo/CodeView/TypeRecords.def
+++ b/include/llvm/DebugInfo/CodeView/TypeRecords.def
@@ -41,6 +41,7 @@ TYPE_RECORD(LF_POINTER, 0x1002, Pointer)
TYPE_RECORD(LF_MODIFIER, 0x1001, Modifier)
TYPE_RECORD(LF_PROCEDURE, 0x1008, Procedure)
TYPE_RECORD(LF_MFUNCTION, 0x1009, MemberFunction)
+TYPE_RECORD(LF_LABEL, 0x000e, Label)
TYPE_RECORD(LF_ARGLIST, 0x1201, ArgList)
TYPE_RECORD(LF_FIELDLIST, 0x1203, FieldList)
@@ -79,9 +80,7 @@ MEMBER_RECORD(LF_INDEX, 0x1404, ListContinuation)
TYPE_RECORD(LF_FUNC_ID, 0x1601, FuncId)
TYPE_RECORD(LF_MFUNC_ID, 0x1602, MemberFuncId)
TYPE_RECORD(LF_BUILDINFO, 0x1603, BuildInfo)
-// FIXME: We reuse the structure of ArgListRecord for substring lists, but it
-// makes for confusing dumper output.
-TYPE_RECORD_ALIAS(LF_SUBSTR_LIST, 0x1604, StringList, ArgList)
+TYPE_RECORD(LF_SUBSTR_LIST, 0x1604, StringList)
TYPE_RECORD(LF_STRING_ID, 0x1605, StringId)
TYPE_RECORD(LF_UDT_SRC_LINE, 0x1606, UdtSourceLine)
TYPE_RECORD(LF_UDT_MOD_SRC_LINE, 0x1607, UdtModSourceLine)
@@ -103,7 +102,6 @@ CV_TYPE(LF_MFUNCTION_16t, 0x0009)
CV_TYPE(LF_COBOL0_16t, 0x000b)
CV_TYPE(LF_COBOL1, 0x000c)
CV_TYPE(LF_BARRAY_16t, 0x000d)
-CV_TYPE(LF_LABEL, 0x000e)
CV_TYPE(LF_NULLLEAF, 0x000f) // LF_NULL
CV_TYPE(LF_NOTTRAN, 0x0010)
CV_TYPE(LF_DIMARRAY_16t, 0x0011)
diff --git a/include/llvm/DebugInfo/CodeView/TypeSerializer.h b/include/llvm/DebugInfo/CodeView/TypeSerializer.h
index e05922194638..1f4873c4f969 100644
--- a/include/llvm/DebugInfo/CodeView/TypeSerializer.h
+++ b/include/llvm/DebugInfo/CodeView/TypeSerializer.h
@@ -12,8 +12,8 @@
#include "llvm/DebugInfo/CodeView/TypeRecordMapping.h"
#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
-#include "llvm/DebugInfo/MSF/ByteStream.h"
-#include "llvm/DebugInfo/MSF/StreamWriter.h"
+#include "llvm/Support/BinaryByteStream.h"
+#include "llvm/Support/BinaryStreamWriter.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallVector.h"
@@ -56,8 +56,8 @@ class TypeSerializer : public TypeVisitorCallbacks {
Optional<TypeLeafKind> TypeKind;
Optional<TypeLeafKind> MemberKind;
std::vector<uint8_t> RecordBuffer;
- msf::MutableByteStream Stream;
- msf::StreamWriter Writer;
+ MutableBinaryByteStream Stream;
+ BinaryStreamWriter Writer;
TypeRecordMapping Mapping;
RecordList SeenRecords;
diff --git a/include/llvm/DebugInfo/CodeView/TypeServerHandler.h b/include/llvm/DebugInfo/CodeView/TypeServerHandler.h
new file mode 100644
index 000000000000..35f06eaf6eb4
--- /dev/null
+++ b/include/llvm/DebugInfo/CodeView/TypeServerHandler.h
@@ -0,0 +1,36 @@
+//===- TypeServerHandler.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_CODEVIEW_TYPESERVERHANDLER_H
+#define LLVM_DEBUGINFO_CODEVIEW_TYPESERVERHANDLER_H
+
+#include "llvm/DebugInfo/CodeView/TypeRecord.h"
+#include "llvm/Support/Error.h"
+
+namespace llvm {
+namespace codeview {
+class TypeVisitorCallbacks;
+
+class TypeServerHandler {
+public:
+ virtual ~TypeServerHandler() {}
+
+ /// Handle a TypeServer record. If the implementation returns true
+ /// the record will not be processed by the top-level visitor. If
+ /// it returns false, it will be processed. If it returns an Error,
+ /// then the top-level visitor will fail.
+ virtual Expected<bool> handle(TypeServer2Record &TS,
+ TypeVisitorCallbacks &Callbacks) {
+ return false;
+ }
+};
+}
+}
+
+#endif
diff --git a/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h b/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h
index af396c79d074..2246f197e784 100644
--- a/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h
+++ b/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h
@@ -13,12 +13,17 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/DebugInfo/CodeView/TypeTableBuilder.h"
+#include "llvm/Support/Error.h"
namespace llvm {
namespace codeview {
+class TypeServerHandler;
+
/// Merges one type stream into another. Returns true on success.
-bool mergeTypeStreams(TypeTableBuilder &DestStream, const CVTypeArray &Types);
+Error mergeTypeStreams(TypeTableBuilder &DestIdStream,
+ TypeTableBuilder &DestTypeStream,
+ TypeServerHandler *Handler, const CVTypeArray &Types);
} // end namespace codeview
} // end namespace llvm
diff --git a/include/llvm/DebugInfo/CodeView/TypeTableBuilder.h b/include/llvm/DebugInfo/CodeView/TypeTableBuilder.h
index 4e6d81ece318..102bee4b0801 100644
--- a/include/llvm/DebugInfo/CodeView/TypeTableBuilder.h
+++ b/include/llvm/DebugInfo/CodeView/TypeTableBuilder.h
@@ -121,6 +121,12 @@ public:
}
return Index;
}
+
+ /// Stop building the record.
+ void reset() {
+ if (auto EC = TempSerializer.visitTypeEnd(Type))
+ consumeError(std::move(EC));
+ }
};
} // end namespace codeview
diff --git a/include/llvm/DebugInfo/DIContext.h b/include/llvm/DebugInfo/DIContext.h
index 804419c517df..e3386a8dcd24 100644
--- a/include/llvm/DebugInfo/DIContext.h
+++ b/include/llvm/DebugInfo/DIContext.h
@@ -1,4 +1,4 @@
-//===-- DIContext.h ---------------------------------------------*- C++ -*-===//
+//===- DIContext.h ----------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -32,26 +32,28 @@ class raw_ostream;
struct DILineInfo {
std::string FileName;
std::string FunctionName;
- uint32_t Line;
- uint32_t Column;
+ uint32_t Line = 0;
+ uint32_t Column = 0;
+ uint32_t StartLine = 0;
// DWARF-specific.
- uint32_t Discriminator;
+ uint32_t Discriminator = 0;
- DILineInfo()
- : FileName("<invalid>"), FunctionName("<invalid>"), Line(0), Column(0),
- Discriminator(0) {}
+ DILineInfo() : FileName("<invalid>"), FunctionName("<invalid>") {}
bool operator==(const DILineInfo &RHS) const {
return Line == RHS.Line && Column == RHS.Column &&
- FileName == RHS.FileName && FunctionName == RHS.FunctionName;
+ FileName == RHS.FileName && FunctionName == RHS.FunctionName &&
+ StartLine == RHS.StartLine && Discriminator == RHS.Discriminator;
}
bool operator!=(const DILineInfo &RHS) const {
return !(*this == RHS);
}
bool operator<(const DILineInfo &RHS) const {
- return std::tie(FileName, FunctionName, Line, Column) <
- std::tie(RHS.FileName, RHS.FunctionName, RHS.Line, RHS.Column);
+ return std::tie(FileName, FunctionName, Line, Column, StartLine,
+ Discriminator) <
+ std::tie(RHS.FileName, RHS.FunctionName, RHS.Line, RHS.Column,
+ RHS.StartLine, RHS.Discriminator);
}
};
@@ -86,10 +88,10 @@ public:
/// DIGlobal - container for description of a global variable.
struct DIGlobal {
std::string Name;
- uint64_t Start;
- uint64_t Size;
+ uint64_t Start = 0;
+ uint64_t Size = 0;
- DIGlobal() : Name("<invalid>"), Start(0), Size(0) {}
+ DIGlobal() : Name("<invalid>") {}
};
/// A DINameKind is passed to name search methods to specify a
@@ -175,8 +177,8 @@ private:
/// on the fly.
class LoadedObjectInfo {
protected:
- LoadedObjectInfo(const LoadedObjectInfo &) = default;
LoadedObjectInfo() = default;
+ LoadedObjectInfo(const LoadedObjectInfo &) = default;
public:
virtual ~LoadedObjectInfo() = default;
diff --git a/include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h b/include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h
index db9bd506be89..7324f6e3eb38 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h
@@ -1,4 +1,4 @@
-//===-- DWARFAbbreviationDeclaration.h --------------------------*- C++ -*-===//
+//===- DWARFAbbreviationDeclaration.h ---------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,17 +7,22 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_LIB_DEBUGINFO_DWARFABBREVIATIONDECLARATION_H
-#define LLVM_LIB_DEBUGINFO_DWARFABBREVIATIONDECLARATION_H
+#ifndef LLVM_DEBUGINFO_DWARFABBREVIATIONDECLARATION_H
+#define LLVM_DEBUGINFO_DWARFABBREVIATIONDECLARATION_H
+#include "llvm/ADT/iterator_range.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/DataExtractor.h"
#include "llvm/Support/Dwarf.h"
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+
namespace llvm {
-class DWARFUnit;
class DWARFFormValue;
+class DWARFUnit;
class raw_ostream;
class DWARFAbbreviationDeclaration {
@@ -25,6 +30,7 @@ public:
struct AttributeSpec {
AttributeSpec(dwarf::Attribute A, dwarf::Form F, Optional<int64_t> V)
: Attr(A), Form(F), ByteSizeOrValue(V) {}
+
dwarf::Attribute Attr;
dwarf::Form Form;
/// The following field is used for ByteSize for non-implicit_const
@@ -41,9 +47,11 @@ public:
/// * Form == DW_FORM_implicit_const:
/// ByteSizeOrValue contains value for the implicit_const attribute.
Optional<int64_t> ByteSizeOrValue;
+
bool isImplicitConst() const {
return Form == dwarf::DW_FORM_implicit_const;
}
+
/// Get the fixed byte size of this Form if possible. This function might
/// use the DWARFUnit to calculate the size of the Form, like for
/// DW_AT_address and DW_AT_ref_addr, so this isn't just an accessor for
@@ -55,6 +63,7 @@ public:
DWARFAbbreviationDeclaration();
uint32_t getCode() const { return Code; }
+ uint8_t getCodeByteSize() const { return CodeByteSize; }
dwarf::Tag getTag() const { return Tag; }
bool hasChildren() const { return HasChildren; }
@@ -66,9 +75,17 @@ public:
}
dwarf::Form getFormByIndex(uint32_t idx) const {
- if (idx < AttributeSpecs.size())
- return AttributeSpecs[idx].Form;
- return dwarf::Form(0);
+ assert(idx < AttributeSpecs.size());
+ return AttributeSpecs[idx].Form;
+ }
+
+ size_t getNumAttributes() const {
+ return AttributeSpecs.size();
+ }
+
+ dwarf::Attribute getAttrByIndex(uint32_t idx) const {
+ assert(idx < AttributeSpecs.size());
+ return AttributeSpecs[idx].Attr;
}
/// Get the index of the specified attribute.
@@ -109,16 +126,16 @@ private:
/// abbreviation declaration.
struct FixedSizeInfo {
/// The fixed byte size for fixed size forms.
- uint16_t NumBytes;
+ uint16_t NumBytes = 0;
/// Number of DW_FORM_address forms in this abbrevation declaration.
- uint8_t NumAddrs;
+ uint8_t NumAddrs = 0;
/// Number of DW_FORM_ref_addr forms in this abbrevation declaration.
- uint8_t NumRefAddrs;
+ uint8_t NumRefAddrs = 0;
/// Number of 4 byte in DWARF32 and 8 byte in DWARF64 forms.
- uint8_t NumDwarfOffsets;
- /// Constructor
- FixedSizeInfo()
- : NumBytes(0), NumAddrs(0), NumRefAddrs(0), NumDwarfOffsets(0) {}
+ uint8_t NumDwarfOffsets = 0;
+
+ FixedSizeInfo() = default;
+
/// Calculate the fixed size in bytes given a DWARFUnit.
///
/// \param U the DWARFUnit to use when determing the byte size.
@@ -138,6 +155,6 @@ private:
Optional<FixedSizeInfo> FixedAttributeSize;
};
-}
+} // end namespace llvm
-#endif
+#endif // LLVM_DEBUGINFO_DWARFABBREVIATIONDECLARATION_H
diff --git a/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h b/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h
index 63343728fa99..f95a013d7552 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h
@@ -1,4 +1,4 @@
-//===--- DWARFAcceleratorTable.h --------------------------------*- C++ -*-===//
+//===- DWARFAcceleratorTable.h ----------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,19 +7,21 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_LIB_DEBUGINFO_DWARFACCELERATORTABLE_H
-#define LLVM_LIB_DEBUGINFO_DWARFACCELERATORTABLE_H
+#ifndef LLVM_DEBUGINFO_DWARFACCELERATORTABLE_H
+#define LLVM_DEBUGINFO_DWARFACCELERATORTABLE_H
#include "llvm/ADT/SmallVector.h"
-#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
#include "llvm/DebugInfo/DWARF/DWARFRelocMap.h"
+#include "llvm/Support/DataExtractor.h"
#include "llvm/Support/Dwarf.h"
#include <cstdint>
+#include <utility>
namespace llvm {
-class DWARFAcceleratorTable {
+class raw_ostream;
+class DWARFAcceleratorTable {
struct Header {
uint32_t Magic;
uint16_t Version;
@@ -41,6 +43,7 @@ class DWARFAcceleratorTable {
DataExtractor AccelSection;
DataExtractor StringSection;
const RelocAddrMap& Relocs;
+
public:
DWARFAcceleratorTable(DataExtractor AccelSection, DataExtractor StringSection,
const RelocAddrMap &Relocs)
@@ -50,6 +53,6 @@ public:
void dump(raw_ostream &OS) const;
};
-}
+} // end namespace llvm
-#endif
+#endif // LLVM_DEBUGINFO_DWARFACCELERATORTABLE_H
diff --git a/include/llvm/DebugInfo/DWARF/DWARFAttribute.h b/include/llvm/DebugInfo/DWARF/DWARFAttribute.h
new file mode 100644
index 000000000000..5919aaddea40
--- /dev/null
+++ b/include/llvm/DebugInfo/DWARF/DWARFAttribute.h
@@ -0,0 +1,56 @@
+//===- DWARFAttribute.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_DWARFATTRIBUTE_H
+#define LLVM_DEBUGINFO_DWARFATTRIBUTE_H
+
+#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
+#include "llvm/Support/Dwarf.h"
+#include <cstdint>
+
+namespace llvm {
+
+//===----------------------------------------------------------------------===//
+/// Encapsulates a DWARF attribute value and all of the data required to
+/// describe the attribute value.
+///
+/// This class is designed to be used by clients that want to iterate across all
+/// attributes in a DWARFDie.
+struct DWARFAttribute {
+ /// The debug info/types offset for this attribute.
+ uint32_t Offset = 0;
+ /// The debug info/types section byte size of the data for this attribute.
+ uint32_t ByteSize = 0;
+ /// The attribute enumeration of this attribute.
+ dwarf::Attribute Attr;
+ /// The form and value for this attribute.
+ DWARFFormValue Value;
+
+ DWARFAttribute(uint32_t O, dwarf::Attribute A = dwarf::Attribute(0),
+ dwarf::Form F = dwarf::Form(0)) : Attr(A), Value(F) {}
+
+ bool isValid() const {
+ return Offset != 0 && Attr != dwarf::Attribute(0);
+ }
+
+ explicit operator bool() const {
+ return isValid();
+ }
+
+ void clear() {
+ Offset = 0;
+ ByteSize = 0;
+ Attr = dwarf::Attribute(0);
+ Value = DWARFFormValue();
+ }
+};
+
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_DWARFATTRIBUTE_H
diff --git a/include/llvm/DebugInfo/DWARF/DWARFCompileUnit.h b/include/llvm/DebugInfo/DWARF/DWARFCompileUnit.h
index bba3abe6e9e9..b2a4d247ccc6 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFCompileUnit.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFCompileUnit.h
@@ -1,4 +1,4 @@
-//===-- DWARFCompileUnit.h --------------------------------------*- C++ -*-===//
+//===- DWARFCompileUnit.h ---------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,10 +7,11 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_LIB_DEBUGINFO_DWARFCOMPILEUNIT_H
-#define LLVM_LIB_DEBUGINFO_DWARFCOMPILEUNIT_H
+#ifndef LLVM_DEBUGINFO_DWARFCOMPILEUNIT_H
+#define LLVM_DEBUGINFO_DWARFCOMPILEUNIT_H
#include "llvm/DebugInfo/DWARF/DWARFUnit.h"
+#include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h"
namespace llvm {
@@ -23,12 +24,15 @@ public:
const DWARFUnitIndex::Entry *Entry)
: DWARFUnit(Context, Section, DA, RS, SS, SOS, AOS, LS, LE, IsDWO,
UnitSection, Entry) {}
- void dump(raw_ostream &OS);
- static const DWARFSectionKind Section = DW_SECT_INFO;
+
// VTable anchor.
~DWARFCompileUnit() override;
+
+ void dump(raw_ostream &OS);
+
+ static const DWARFSectionKind Section = DW_SECT_INFO;
};
-}
+} // end namespace llvm
-#endif
+#endif // LLVM_DEBUGINFO_DWARFCOMPILEUNIT_H
diff --git a/include/llvm/DebugInfo/DWARF/DWARFContext.h b/include/llvm/DebugInfo/DWARF/DWARFContext.h
index ef310e704005..f941cdd1060a 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFContext.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFContext.h
@@ -1,4 +1,4 @@
-//===-- DWARFContext.h ------------------------------------------*- C++ -*-===//
+//===- DWARFContext.h -------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,14 +7,15 @@
//
//===----------------------------------------------------------------------===/
-#ifndef LLVM_LIB_DEBUGINFO_DWARFCONTEXT_H
-#define LLVM_LIB_DEBUGINFO_DWARFCONTEXT_H
+#ifndef LLVM_DEBUGINFO_DWARF_DWARFCONTEXT_H
+#define LLVM_DEBUGINFO_DWARF_DWARFCONTEXT_H
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/DebugInfo/DIContext.h"
#include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"
@@ -30,6 +31,7 @@
#include "llvm/DebugInfo/DWARF/DWARFUnit.h"
#include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h"
#include "llvm/Object/ObjectFile.h"
+#include "llvm/Support/Host.h"
#include <cstdint>
#include <deque>
#include <map>
@@ -38,6 +40,9 @@
namespace llvm {
+class MemoryBuffer;
+class raw_ostream;
+
// 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
@@ -293,10 +298,16 @@ class DWARFContextInMemory : public DWARFContext {
SmallVector<SmallString<32>, 4> UncompressedSections;
+ StringRef *MapSectionToMember(StringRef Name);
+
public:
DWARFContextInMemory(const object::ObjectFile &Obj,
const LoadedObjectInfo *L = nullptr);
+ DWARFContextInMemory(const StringMap<std::unique_ptr<MemoryBuffer>> &Sections,
+ uint8_t AddrSize,
+ bool isLittleEndian = sys::IsLittleEndianHost);
+
bool isLittleEndian() const override { return IsLittleEndian; }
uint8_t getAddressSize() const override { return AddressSize; }
const DWARFSection &getInfoSection() override { return InfoSection; }
@@ -321,20 +332,26 @@ public:
// Sections for DWARF5 split dwarf proposal.
const DWARFSection &getInfoDWOSection() override { return InfoDWOSection; }
+
const TypeSectionMap &getTypesDWOSections() override {
return TypesDWOSections;
}
+
StringRef getAbbrevDWOSection() override { return AbbrevDWOSection; }
const DWARFSection &getLineDWOSection() override { return LineDWOSection; }
const DWARFSection &getLocDWOSection() override { return LocDWOSection; }
StringRef getStringDWOSection() override { return StringDWOSection; }
+
StringRef getStringOffsetDWOSection() override {
return StringOffsetDWOSection;
}
+
StringRef getRangeDWOSection() override { return RangeDWOSection; }
+
StringRef getAddrSection() override {
return AddrSection;
}
+
StringRef getCUIndexSection() override { return CUIndexSection; }
StringRef getGdbIndexSection() override { return GdbIndexSection; }
StringRef getTUIndexSection() override { return TUIndexSection; }
@@ -342,4 +359,4 @@ public:
} // end namespace llvm
-#endif // LLVM_LIB_DEBUGINFO_DWARFCONTEXT_H
+#endif // LLVM_DEBUGINFO_DWARF_DWARFCONTEXT_H
diff --git a/include/llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h b/include/llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h
index f732deef548c..9f86fe508389 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h
@@ -1,4 +1,4 @@
-//===-- DWARFDebugAbbrev.h --------------------------------------*- C++ -*-===//
+//===- DWARFDebugAbbrev.h ---------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,10 +7,12 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_LIB_DEBUGINFO_DWARFDEBUGABBREV_H
-#define LLVM_LIB_DEBUGINFO_DWARFDEBUGABBREV_H
+#ifndef LLVM_DEBUGINFO_DWARFDEBUGABBREV_H
+#define LLVM_DEBUGINFO_DWARFDEBUGABBREV_H
#include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h"
+#include "llvm/Support/DataExtractor.h"
+#include <cstdint>
#include <map>
#include <vector>
@@ -76,6 +78,6 @@ private:
void clear();
};
-}
+} // end namespace llvm
-#endif
+#endif // LLVM_DEBUGINFO_DWARFDEBUGABBREV_H
diff --git a/include/llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h b/include/llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h
index 5a602392add8..40eb7e9a8836 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h
@@ -1,4 +1,4 @@
-//===-- DWARFDebugArangeSet.h -----------------------------------*- C++ -*-===//
+//===- DWARFDebugArangeSet.h ------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,11 +7,12 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_LIB_DEBUGINFO_DWARFDEBUGARANGESET_H
-#define LLVM_LIB_DEBUGINFO_DWARFDEBUGARANGESET_H
+#ifndef LLVM_DEBUGINFO_DWARFDEBUGARANGESET_H
+#define LLVM_DEBUGINFO_DWARFDEBUGARANGESET_H
#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/DataExtractor.h"
+#include <cstdint>
#include <vector>
namespace llvm {
@@ -40,6 +41,7 @@ public:
struct Descriptor {
uint64_t Address;
uint64_t Length;
+
uint64_t getEndAddress() const { return Address + Length; }
};
@@ -53,6 +55,7 @@ private:
public:
DWARFDebugArangeSet() { clear(); }
+
void clear();
bool extract(DataExtractor data, uint32_t *offset_ptr);
void dump(raw_ostream &OS) const;
@@ -67,6 +70,6 @@ public:
}
};
-}
+} // end namespace llvm
-#endif
+#endif // LLVM_DEBUGINFO_DWARFDEBUGARANGESET_H
diff --git a/include/llvm/DebugInfo/DWARF/DWARFDebugAranges.h b/include/llvm/DebugInfo/DWARF/DWARFDebugAranges.h
index 791f010a8892..c06771d6afb4 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFDebugAranges.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFDebugAranges.h
@@ -1,4 +1,4 @@
-//===-- DWARFDebugAranges.h -------------------------------------*- C++ -*-===//
+//===- DWARFDebugAranges.h --------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,11 +7,12 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_LIB_DEBUGINFO_DWARFDEBUGARANGES_H
-#define LLVM_LIB_DEBUGINFO_DWARFDEBUGARANGES_H
+#ifndef LLVM_DEBUGINFO_DWARFDEBUGARANGES_H
+#define LLVM_DEBUGINFO_DWARFDEBUGARANGES_H
#include "llvm/ADT/DenseSet.h"
#include "llvm/Support/DataExtractor.h"
+#include <cstdint>
#include <vector>
namespace llvm {
@@ -42,6 +43,7 @@ private:
else
Length = HighPC - LowPC;
}
+
uint64_t HighPC() const {
if (Length)
return LowPC + Length;
@@ -51,6 +53,7 @@ private:
bool containsAddress(uint64_t Address) const {
return LowPC <= Address && Address < HighPC();
}
+
bool operator<(const Range &other) const {
return LowPC < other.LowPC;
}
@@ -73,7 +76,6 @@ private:
}
};
-
typedef std::vector<Range> RangeColl;
typedef RangeColl::const_iterator RangeCollIterator;
@@ -82,6 +84,6 @@ private:
DenseSet<uint32_t> ParsedCUOffsets;
};
-}
+} // end namespace llvm
-#endif
+#endif // LLVM_DEBUGINFO_DWARFDEBUGARANGES_H
diff --git a/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h b/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h
index cd76c909ddae..e0a779bb8182 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h
@@ -1,4 +1,4 @@
-//===-- DWARFDebugFrame.h - Parsing of .debug_frame -------------*- C++ -*-===//
+//===- DWARFDebugFrame.h - Parsing of .debug_frame --------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,23 +7,24 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_LIB_DEBUGINFO_DWARFDEBUGFRAME_H
-#define LLVM_LIB_DEBUGINFO_DWARFDEBUGFRAME_H
+#ifndef LLVM_DEBUGINFO_DWARF_DWARFDEBUGFRAME_H
+#define LLVM_DEBUGINFO_DWARF_DWARFDEBUGFRAME_H
#include "llvm/Support/DataExtractor.h"
-#include "llvm/Support/raw_ostream.h"
#include <memory>
#include <vector>
namespace llvm {
class FrameEntry;
+class raw_ostream;
/// \brief A parsed .debug_frame or .eh_frame section
///
class DWARFDebugFrame {
// True if this is parsing an eh_frame section.
bool IsEH;
+
public:
DWARFDebugFrame(bool IsEH);
~DWARFDebugFrame();
@@ -39,7 +40,6 @@ private:
std::vector<std::unique_ptr<FrameEntry>> Entries;
};
+} // end namespace llvm
-} // namespace llvm
-
-#endif
+#endif // LLVM_DEBUGINFO_DWARF_DWARFDEBUGFRAME_H
diff --git a/include/llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h b/include/llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h
index f36f470980b1..fc2423a2708b 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h
@@ -1,4 +1,4 @@
-//===-- DWARFDebugInfoEntry.h -----------------------------------*- C++ -*-===//
+//===- DWARFDebugInfoEntry.h ------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,43 +7,37 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_LIB_DEBUGINFO_DWARFDEBUGINFOENTRY_H
-#define LLVM_LIB_DEBUGINFO_DWARFDEBUGINFOENTRY_H
+#ifndef LLVM_DEBUGINFO_DWARFDEBUGINFOENTRY_H
+#define LLVM_DEBUGINFO_DWARFDEBUGINFOENTRY_H
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/DebugInfo/DIContext.h"
#include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h"
-#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h"
-#include "llvm/Support/DataTypes.h"
#include "llvm/Support/Dwarf.h"
+#include <cstdint>
namespace llvm {
-class DWARFDebugAranges;
-class DWARFCompileUnit;
+class DataExtractor;
class DWARFUnit;
-class DWARFContext;
-class DWARFFormValue;
-struct DWARFDebugInfoEntryInlinedChain;
/// DWARFDebugInfoEntry - A DIE with only the minimum required data.
class DWARFDebugInfoEntry {
/// Offset within the .debug_info of the start of this entry.
- uint32_t Offset;
+ uint32_t Offset = 0;
/// The integer depth of this DIE within the compile unit DIEs where the
/// compile/type unit DIE has a depth of zero.
- uint32_t Depth;
+ uint32_t Depth = 0;
+
+ const DWARFAbbreviationDeclaration *AbbrevDecl = nullptr;
- const DWARFAbbreviationDeclaration *AbbrevDecl;
public:
- DWARFDebugInfoEntry()
- : Offset(0), Depth(0), AbbrevDecl(nullptr) {}
+ DWARFDebugInfoEntry() = default;
/// Extracts a debug info entry, which is a child of a given unit,
/// starting at a given offset. If DIE can't be extracted, returns false and
/// doesn't change OffsetPtr.
bool extractFast(const DWARFUnit &U, uint32_t *OffsetPtr);
+
/// High performance extraction should use this call.
bool extractFast(const DWARFUnit &U, uint32_t *OffsetPtr,
const DataExtractor &DebugInfoData,
@@ -52,15 +46,18 @@ public:
uint32_t getOffset() const { return Offset; }
uint32_t getDepth() const { return Depth; }
+
dwarf::Tag getTag() const {
return AbbrevDecl ? AbbrevDecl->getTag() : dwarf::DW_TAG_null;
}
+
bool hasChildren() const { return AbbrevDecl && AbbrevDecl->hasChildren(); }
+
const DWARFAbbreviationDeclaration *getAbbreviationDeclarationPtr() const {
return AbbrevDecl;
}
};
-}
+} // end namespace llvm
-#endif
+#endif // LLVM_DEBUGINFO_DWARFDEBUGINFOENTRY_H
diff --git a/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h b/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h
index 878f1c76ebf6..e5bb24707b63 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h
@@ -1,4 +1,4 @@
-//===-- DWARFDebugLine.h ----------------------------------------*- C++ -*-===//
+//===- DWARFDebugLine.h -----------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,12 +7,13 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_LIB_DEBUGINFO_DWARFDEBUGLINE_H
-#define LLVM_LIB_DEBUGINFO_DWARFDEBUGLINE_H
+#ifndef LLVM_DEBUGINFO_DWARFDEBUGLINE_H
+#define LLVM_DEBUGINFO_DWARFDEBUGLINE_H
#include "llvm/DebugInfo/DIContext.h"
#include "llvm/DebugInfo/DWARF/DWARFRelocMap.h"
#include "llvm/Support/DataExtractor.h"
+#include <cstdint>
#include <map>
#include <string>
#include <vector>
@@ -24,13 +25,14 @@ class raw_ostream;
class DWARFDebugLine {
public:
DWARFDebugLine(const RelocAddrMap* LineInfoRelocMap) : RelocMap(LineInfoRelocMap) {}
+
struct FileNameEntry {
- FileNameEntry() : Name(nullptr), DirIdx(0), ModTime(0), Length(0) {}
+ FileNameEntry() = default;
- const char *Name;
- uint64_t DirIdx;
- uint64_t ModTime;
- uint64_t Length;
+ const char *Name = nullptr;
+ uint64_t DirIdx = 0;
+ uint64_t ModTime = 0;
+ uint64_t Length = 0;
};
struct Prologue {
@@ -64,9 +66,11 @@ public:
std::vector<FileNameEntry> FileNames;
bool IsDWARF64;
+
uint32_t sizeofTotalLength() const {
return IsDWARF64 ? 12 : 4;
}
+
uint32_t sizeofPrologueLength() const {
return IsDWARF64 ? 8 : 4;
}
@@ -76,10 +80,12 @@ public:
return PrologueLength + sizeofTotalLength() + sizeof(Version) +
sizeofPrologueLength();
}
+
// Length of the line table data in bytes (not including the prologue).
uint32_t getStatementTableLength() const {
return TotalLength + sizeofTotalLength() - getLength();
}
+
int32_t getMaxLineIncrementForSpecialOpcode() const {
return LineBase + (int8_t)LineRange - 1;
}
@@ -146,6 +152,8 @@ public:
// compilation unit may consist of multiple sequences, which are not
// guaranteed to be in the order of ascending instruction address.
struct Sequence {
+ Sequence();
+
// Sequence describes instructions at address range [LowPC, HighPC)
// and is described by line table rows [FirstRowIndex, LastRowIndex).
uint64_t LowPC;
@@ -154,15 +162,16 @@ public:
unsigned LastRowIndex;
bool Empty;
- Sequence();
void reset();
static bool orderByLowPC(const Sequence& LHS, const Sequence& RHS) {
return LHS.LowPC < RHS.LowPC;
}
+
bool isValid() const {
return !Empty && (LowPC < HighPC) && (FirstRowIndex < LastRowIndex);
}
+
bool containsPC(uint64_t pc) const {
return (LowPC <= pc && pc < HighPC);
}
@@ -177,6 +186,7 @@ public:
void appendRow(const DWARFDebugLine::Row &R) {
Rows.push_back(R);
}
+
void appendSequence(const DWARFDebugLine::Sequence &S) {
Sequences.push_back(S);
}
@@ -249,6 +259,7 @@ private:
const RelocAddrMap *RelocMap;
LineTableMapTy LineTableMap;
};
-}
-#endif
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_DWARFDEBUGLINE_H
diff --git a/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h b/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h
index bd44c2e5aab9..6d4cd8d1b5a3 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h
@@ -1,4 +1,4 @@
-//===-- DWARFDebugLoc.h -----------------------------------------*- C++ -*-===//
+//===- DWARFDebugLoc.h ------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,12 +7,13 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_LIB_DEBUGINFO_DWARFDEBUGLOC_H
-#define LLVM_LIB_DEBUGINFO_DWARFDEBUGLOC_H
+#ifndef LLVM_DEBUGINFO_DWARF_DWARFDEBUGLOC_H
+#define LLVM_DEBUGINFO_DWARF_DWARFDEBUGLOC_H
#include "llvm/ADT/SmallVector.h"
#include "llvm/DebugInfo/DWARF/DWARFRelocMap.h"
#include "llvm/Support/DataExtractor.h"
+#include <cstdint>
namespace llvm {
@@ -49,8 +50,10 @@ class DWARFDebugLoc {
public:
DWARFDebugLoc(const RelocAddrMap &LocRelocMap) : RelocMap(LocRelocMap) {}
+
/// Print the location lists found within the debug_loc section.
void dump(raw_ostream &OS) const;
+
/// Parse the debug_loc section accessible via the 'data' parameter using the
/// specified address size to interpret the address ranges.
void parse(DataExtractor data, unsigned AddressSize);
@@ -76,6 +79,7 @@ public:
void parse(DataExtractor data);
void dump(raw_ostream &OS) const;
};
-}
-#endif
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_DWARF_DWARFDEBUGLOC_H
diff --git a/include/llvm/DebugInfo/DWARF/DWARFDebugMacro.h b/include/llvm/DebugInfo/DWARF/DWARFDebugMacro.h
index 5a0352dacdb9..85d98b45afcd 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFDebugMacro.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFDebugMacro.h
@@ -1,4 +1,4 @@
-//===-- DWARFDebugMacro.h ---------------------------------------*- C++ -*-===//
+//===- DWARFDebugMacro.h ----------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -50,6 +50,7 @@ public:
/// Print the macro list found within the debug_macinfo section.
void dump(raw_ostream &OS) const;
+
/// Parse the debug_macinfo section accessible via the 'data' parameter.
void parse(DataExtractor data);
};
diff --git a/include/llvm/DebugInfo/DWARF/DWARFDebugPubTable.h b/include/llvm/DebugInfo/DWARF/DWARFDebugPubTable.h
index 2b23837e32d6..9d36bb7ad211 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFDebugPubTable.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFDebugPubTable.h
@@ -1,4 +1,4 @@
-//===-- DWARFDebugPubTable.h ------------------------------------*- C++ -*-===//
+//===- DWARFDebugPubTable.h -------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,13 +7,13 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_LIB_DEBUGINFO_DWARFDEBUGPUBTABLE_H
-#define LLVM_LIB_DEBUGINFO_DWARFDEBUGPUBTABLE_H
+#ifndef LLVM_DEBUGINFO_DWARF_DWARFDEBUGPUBTABLE_H
+#define LLVM_DEBUGINFO_DWARF_DWARFDEBUGPUBTABLE_H
-#include "llvm/ADT/iterator_range.h"
#include "llvm/ADT/ArrayRef.h"
-#include "llvm/Support/DataExtractor.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Dwarf.h"
+#include <cstdint>
#include <vector>
namespace llvm {
@@ -28,7 +28,7 @@ public:
uint32_t SecOffset;
/// An entry of the various gnu_pub* debug sections.
- llvm::dwarf::PubIndexEntryDescriptor Descriptor;
+ dwarf::PubIndexEntryDescriptor Descriptor;
/// The name of the object as given by the DW_AT_name attribute of the
/// referenced DIE.
@@ -68,10 +68,12 @@ private:
public:
DWARFDebugPubTable(StringRef Data, bool LittleEndian, bool GnuStyle);
+
void dump(StringRef Name, raw_ostream &OS) const;
ArrayRef<Set> getData() { return Sets; }
};
-}
-#endif
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_DWARF_DWARFDEBUGPUBTABLE_H
diff --git a/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h b/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h
index c930bd603d4d..018a049a3ed8 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h
@@ -1,4 +1,4 @@
-//===-- DWARFDebugRangeList.h -----------------------------------*- C++ -*-===//
+//===- DWARFDebugRangeList.h ------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,10 +7,13 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_LIB_DEBUGINFO_DWARFDEBUGRANGELIST_H
-#define LLVM_LIB_DEBUGINFO_DWARFDEBUGRANGELIST_H
+#ifndef LLVM_DEBUGINFO_DWARF_DWARFDEBUGRANGELIST_H
+#define LLVM_DEBUGINFO_DWARF_DWARFDEBUGRANGELIST_H
#include "llvm/Support/DataExtractor.h"
+#include <cassert>
+#include <cstdint>
+#include <utility>
#include <vector>
namespace llvm {
@@ -34,12 +37,14 @@ public:
// address past the end of the address range. The ending address must
// be greater than or equal to the beginning address.
uint64_t EndAddress;
+
// The end of any given range list is marked by an end of list entry,
// which consists of a 0 for the beginning address offset
// and a 0 for the ending address offset.
bool isEndOfListEntry() const {
return (StartAddress == 0) && (EndAddress == 0);
}
+
// A base address selection entry consists of:
// 1. The value of the largest representable address offset
// (for example, 0xffffffff when the size of an address is 32 bits).
@@ -63,6 +68,7 @@ private:
public:
DWARFDebugRangeList() { clear(); }
+
void clear();
void dump(raw_ostream &OS) const;
bool extract(DataExtractor data, uint32_t *offset_ptr);
@@ -74,6 +80,6 @@ public:
DWARFAddressRangesVector getAbsoluteRanges(uint64_t BaseAddress) const;
};
-} // namespace llvm
+} // end namespace llvm
-#endif // LLVM_DEBUGINFO_DWARFDEBUGRANGELIST_H
+#endif // LLVM_DEBUGINFO_DWARF_DWARFDEBUGRANGELIST_H
diff --git a/include/llvm/DebugInfo/DWARF/DWARFDie.h b/include/llvm/DebugInfo/DWARF/DWARFDie.h
index e335e28b39d7..33e24fe3adc9 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFDie.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFDie.h
@@ -1,4 +1,4 @@
-//===-- DWARFDie.h --------------------------------------------------------===//
+//===- DWARFDie.h -----------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,18 +7,25 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_LIB_DEBUGINFO_DWARFDIE_H
-#define LLVM_LIB_DEBUGINFO_DWARFDIE_H
+#ifndef LLVM_DEBUGINFO_DWARFDIE_H
+#define LLVM_DEBUGINFO_DWARFDIE_H
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/iterator.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/ADT/Optional.h"
+#include "llvm/DebugInfo/DIContext.h"
+#include "llvm/DebugInfo/DWARF/DWARFAttribute.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h"
+#include "llvm/Support/Dwarf.h"
+#include <cassert>
+#include <cstdint>
+#include <iterator>
namespace llvm {
class DWARFUnit;
-class DWARFDebugInfoEntry;
class raw_ostream;
//===----------------------------------------------------------------------===//
@@ -34,10 +41,11 @@ class raw_ostream;
/// also simplifies the attribute extraction calls by not having to specify the
/// DWARFUnit for each call.
class DWARFDie {
- DWARFUnit *U;
- const DWARFDebugInfoEntry *Die;
+ DWARFUnit *U = nullptr;
+ const DWARFDebugInfoEntry *Die = nullptr;
+
public:
- DWARFDie() : U(nullptr), Die(nullptr) {}
+ DWARFDie() = default;
DWARFDie(DWARFUnit *Unit, const DWARFDebugInfoEntry * D) : U(Unit), Die(D) {}
bool isValid() const { return U && Die; }
@@ -45,7 +53,6 @@ public:
const DWARFDebugInfoEntry *getDebugInfoEntry() const { return Die; }
DWARFUnit *getDwarfUnit() const { return U; }
-
/// Get the abbreviation declaration for this DIE.
///
/// \returns the abbreviation declaration or NULL for null tags.
@@ -78,6 +85,7 @@ public:
bool isNULL() const {
return getAbbreviationDeclarationPtr() == nullptr;
}
+
/// Returns true if DIE represents a subprogram (not inlined).
bool isSubprogramDIE() const;
@@ -123,76 +131,33 @@ public:
/// \param Attr the attribute to extract.
/// \returns an optional DWARFFormValue that will have the form value if the
/// attribute was successfully extracted.
- Optional<DWARFFormValue> getAttributeValue(dwarf::Attribute Attr) const;
-
- /// Extract the specified attribute from this DIE as a C string.
- ///
- /// Extract an attribute value from this DIE only. This call doesn't look
- /// for the attribute value in any DW_AT_specification or
- /// DW_AT_abstract_origin referenced DIEs.
- ///
- /// \param Attr the attribute to extract.
- /// \param FailValue the value to return if this DIE doesn't have this
- /// attribute.
- /// \returns the NULL terminated C string value owned by the DWARF section
- /// that contains the string or FailValue if the attribute doesn't exist or
- /// if the attribute's form isn't a form that describes an string.
- const char *getAttributeValueAsString(dwarf::Attribute Attr,
- const char *FailValue) const;
+ Optional<DWARFFormValue> find(dwarf::Attribute Attr) const;
- /// Extract the specified attribute from this DIE as an address.
- ///
- /// Extract an attribute value from this DIE only. This call doesn't look
- /// for the attribute value in any DW_AT_specification or
- /// DW_AT_abstract_origin referenced DIEs.
- ///
- /// \param Attr the attribute to extract.
- /// \returns an optional value for the attribute.
- Optional<uint64_t> getAttributeValueAsAddress(dwarf::Attribute Attr) const;
-
- /// Extract the specified attribute from this DIE as a signed integer.
- ///
- /// Extract an attribute value from this DIE only. This call doesn't look
- /// for the attribute value in any DW_AT_specification or
- /// DW_AT_abstract_origin referenced DIEs.
- ///
- /// \param Attr the attribute to extract.
- /// \returns an optional value for the attribute.
- Optional<int64_t>
- getAttributeValueAsSignedConstant(dwarf::Attribute Attr) const;
-
- /// Extract the specified attribute from this DIE as an unsigned integer.
- ///
- /// Extract an attribute value from this DIE only. This call doesn't look
- /// for the attribute value in any DW_AT_specification or
- /// DW_AT_abstract_origin referenced DIEs.
- ///
- /// \param Attr the attribute to extract.
- /// \returns an optional value for the attribute.
- Optional<uint64_t>
- getAttributeValueAsUnsignedConstant(dwarf::Attribute Attr) const;
+ /// Extract the first value of any attribute in Attrs from this DIE.
+ ///
+ /// Extract the first attribute that matches from this DIE only. This call
+ /// doesn't look for the attribute value in any DW_AT_specification or
+ /// DW_AT_abstract_origin referenced DIEs. The attributes will be searched
+ /// linearly in the order they are specified within Attrs.
+ ///
+ /// \param Attrs an array of DWARF attribute to look for.
+ /// \returns an optional that has a valid DWARFFormValue for the first
+ /// matching attribute in Attrs, or None if none of the attributes in Attrs
+ /// exist in this DIE.
+ Optional<DWARFFormValue> find(ArrayRef<dwarf::Attribute> Attrs) const;
+
+ /// Extract the first value of any attribute in Attrs from this DIE and
+ /// recurse into any DW_AT_specification or DW_AT_abstract_origin referenced
+ /// DIEs.
+ ///
+ /// \param Attrs an array of DWARF attribute to look for.
+ /// \returns an optional that has a valid DWARFFormValue for the first
+ /// matching attribute in Attrs, or None if none of the attributes in Attrs
+ /// exist in this DIE or in any DW_AT_specification or DW_AT_abstract_origin
+ /// DIEs.
+ Optional<DWARFFormValue>
+ findRecursively(ArrayRef<dwarf::Attribute> Attrs) const;
- /// Extract the specified attribute from this DIE as absolute DIE Offset.
- ///
- /// Extract an attribute value from this DIE only. This call doesn't look
- /// for the attribute value in any DW_AT_specification or
- /// DW_AT_abstract_origin referenced DIEs.
- ///
- /// \param Attr the attribute to extract.
- /// \returns an optional value for the attribute.
- Optional<uint64_t> getAttributeValueAsReference(dwarf::Attribute Attr) const;
-
- /// Extract the specified attribute from this DIE as absolute section offset.
- ///
- /// Extract an attribute value from this DIE only. This call doesn't look
- /// for the attribute value in any DW_AT_specification or
- /// DW_AT_abstract_origin referenced DIEs.
- ///
- /// \param Attr the attribute to extract.
- /// \returns an optional value for the attribute.
- Optional<uint64_t>
- getAttributeValueAsSectionOffset(dwarf::Attribute Attr) const;
-
/// Extract the specified attribute from this DIE as the referenced DIE.
///
/// Regardless of the reference type, return the correct DWARFDie instance if
@@ -266,6 +231,12 @@ public:
/// references if necessary. Returns null if no name is found.
const char *getName(DINameKind Kind) const;
+ /// Returns the declaration line (start line) for a DIE, assuming it specifies
+ /// a subprogram. This may be fetched from specification or abstract origin
+ /// for this subprogram by resolving DW_AT_sepcification or
+ /// DW_AT_abstract_origin references if necessary.
+ uint64_t getDeclLine() const;
+
/// Retrieves values of DW_AT_call_file, DW_AT_call_line and DW_AT_call_column
/// from DIE (or zeroes if they are missing). This function looks for
/// DW_AT_call attributes in this DIE only, it will not resolve the attribute
@@ -286,14 +257,47 @@ public:
getInlinedChainForAddress(const uint64_t Address,
SmallVectorImpl<DWARFDie> &InlinedChain) const;
+ class attribute_iterator;
+
+ /// Get an iterator range to all attributes in the current DIE only.
+ ///
+ /// \returns an iterator range for the attributes of the current DIE.
+ iterator_range<attribute_iterator> attributes() const;
+
class iterator;
iterator begin() const;
iterator end() const;
iterator_range<iterator> children() const;
};
-
+class DWARFDie::attribute_iterator :
+ public iterator_facade_base<attribute_iterator, std::forward_iterator_tag,
+ const DWARFAttribute> {
+ /// The DWARF DIE we are extracting attributes from.
+ DWARFDie Die;
+ /// The value vended to clients via the operator*() or operator->().
+ DWARFAttribute AttrValue;
+ /// The attribute index within the abbreviation declaration in Die.
+ uint32_t Index;
+
+ /// Update the attribute index and attempt to read the attribute value. If the
+ /// attribute is able to be read, update AttrValue and the Index member
+ /// variable. If the attribute value is not able to be read, an appropriate
+ /// error will be set if the Err member variable is non-NULL and the iterator
+ /// will be set to the end value so iteration stops.
+ void updateForIndex(const DWARFAbbreviationDeclaration &AbbrDecl, uint32_t I);
+
+public:
+ attribute_iterator() = delete;
+ explicit attribute_iterator(DWARFDie D, bool End);
+
+ attribute_iterator &operator++();
+ explicit operator bool() const { return AttrValue.isValid(); }
+ const DWARFAttribute &operator*() const { return AttrValue; }
+ bool operator==(const attribute_iterator &X) const { return Index == X.Index; }
+};
+
inline bool operator==(const DWARFDie &LHS, const DWARFDie &RHS) {
return LHS.getDebugInfoEntry() == RHS.getDebugInfoEntry() &&
LHS.getDwarfUnit() == RHS.getDwarfUnit();
@@ -313,16 +317,19 @@ class DWARFDie::iterator : public iterator_facade_base<iterator,
}
public:
iterator() = default;
+
explicit iterator(DWARFDie D) : Die(D) {
// If we start out with only a Null DIE then invalidate.
skipNull();
}
+
iterator &operator++() {
Die = Die.getSibling();
// Don't include the NULL die when iterating.
skipNull();
return *this;
}
+
explicit operator bool() const { return Die.isValid(); }
const DWARFDie &operator*() const { return Die; }
bool operator==(const iterator &X) const { return Die == X.Die; }
@@ -344,4 +351,4 @@ inline iterator_range<DWARFDie::iterator> DWARFDie::children() const {
} // end namespace llvm
-#endif // LLVM_LIB_DEBUGINFO_DWARFDIE_H
+#endif // LLVM_DEBUGINFO_DWARFDIE_H
diff --git a/include/llvm/DebugInfo/DWARF/DWARFFormValue.h b/include/llvm/DebugInfo/DWARF/DWARFFormValue.h
index 1b7659dfb04a..c8d7a0c1ac7a 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFFormValue.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFFormValue.h
@@ -1,4 +1,4 @@
-//===-- DWARFFormValue.h ----------------------------------------*- C++ -*-===//
+//===- DWARFFormValue.h -----------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -10,13 +10,15 @@
#ifndef LLVM_DEBUGINFO_DWARFFORMVALUE_H
#define LLVM_DEBUGINFO_DWARFFORMVALUE_H
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/None.h"
#include "llvm/ADT/Optional.h"
#include "llvm/Support/DataExtractor.h"
#include "llvm/Support/Dwarf.h"
+#include <cstdint>
namespace llvm {
-template <typename T> class ArrayRef;
class DWARFUnit;
class raw_ostream;
@@ -37,7 +39,7 @@ public:
private:
struct ValueType {
- ValueType() : data(nullptr) {
+ ValueType() {
uval = 0;
}
@@ -46,20 +48,27 @@ private:
int64_t sval;
const char* cstr;
};
- const uint8_t* data;
+ const uint8_t* data = nullptr;
};
dwarf::Form Form; // Form for this value.
ValueType Value; // Contains all data for the form.
- const DWARFUnit *U; // Remember the DWARFUnit at extract time.
+ const DWARFUnit *U = nullptr; // Remember the DWARFUnit at extract time.
public:
- DWARFFormValue(dwarf::Form F = dwarf::Form(0)) : Form(F), U(nullptr) {}
+ DWARFFormValue(dwarf::Form F = dwarf::Form(0)) : Form(F) {}
+
dwarf::Form getForm() const { return Form; }
void setForm(dwarf::Form F) { Form = F; }
void setUValue(uint64_t V) { Value.uval = V; }
void setSValue(int64_t V) { Value.sval = V; }
void setPValue(const char *V) { Value.cstr = V; }
+
+ void setBlockValue(const ArrayRef<uint8_t> &Data) {
+ Value.data = Data.data();
+ setUValue(Data.size());
+ }
+
bool isFormClass(FormClass FC) const;
const DWARFUnit *getUnit() const { return U; }
void dump(raw_ostream &OS) const;
@@ -72,6 +81,7 @@ public:
/// \returns whether the extraction succeeded.
bool extractValue(const DataExtractor &Data, uint32_t *OffsetPtr,
const DWARFUnit *U);
+
bool isInlinedCStr() const {
return Value.data != nullptr && Value.data == (const uint8_t*)Value.cstr;
}
@@ -87,6 +97,7 @@ public:
Optional<ArrayRef<uint8_t>> getAsBlock() const;
Optional<uint64_t> getAsCStringOffset() const;
Optional<uint64_t> getAsReferenceUVal() const;
+
/// Get the fixed byte size for a given form.
///
/// If the form always has a fixed valid byte size that doesn't depend on a
@@ -105,6 +116,7 @@ public:
/// and was needed to calculate the byte size.
static Optional<uint8_t> getFixedByteSize(dwarf::Form Form,
const DWARFUnit *U = nullptr);
+
/// Get the fixed byte size for a given form.
///
/// If the form has a fixed byte size given a valid DWARF version and address
@@ -133,6 +145,7 @@ public:
/// \returns true on success, false if the form was not skipped.
bool skipValue(DataExtractor debug_info_data, uint32_t *offset_ptr,
const DWARFUnit *U) const;
+
/// Skip a form in \p debug_info_data at offset specified by \p offset_ptr.
///
/// Skips the bytes for this form in the debug info and updates the offset.
@@ -145,6 +158,7 @@ public:
/// \returns true on success, false if the form was not skipped.
static bool skipValue(dwarf::Form form, DataExtractor debug_info_data,
uint32_t *offset_ptr, const DWARFUnit *U);
+
/// Skip a form in \p debug_info_data at offset specified by \p offset_ptr.
///
/// Skips the bytes for this form in the debug info and updates the offset.
@@ -164,6 +178,154 @@ private:
void dumpString(raw_ostream &OS) const;
};
-}
+namespace dwarf {
+
+ /// Take an optional DWARFFormValue and try to extract a string value from it.
+ ///
+ /// \param V and optional DWARFFormValue to attempt to extract the value from.
+ /// \returns an optional value that contains a value if the form value
+ /// was valid and was a string.
+ inline Optional<const char*> toString(const Optional<DWARFFormValue>& V) {
+ if (V)
+ return V->getAsCString();
+ return None;
+ }
+
+ /// Take an optional DWARFFormValue and extract a string value from it.
+ ///
+ /// \param V and optional DWARFFormValue to attempt to extract the value from.
+ /// \param Default the default value to return in case of failure.
+ /// \returns the string value or Default if the V doesn't have a value or the
+ /// form value's encoding wasn't a string.
+ inline const char*
+ toString(const Optional<DWARFFormValue>& V, const char *Default) {
+ return toString(V).getValueOr(Default);
+ }
+
+ /// Take an optional DWARFFormValue and try to extract an unsigned constant.
+ ///
+ /// \param V and optional DWARFFormValue to attempt to extract the value from.
+ /// \returns an optional value that contains a value if the form value
+ /// was valid and has a unsigned constant form.
+ inline Optional<uint64_t> toUnsigned(const Optional<DWARFFormValue>& V) {
+ if (V)
+ return V->getAsUnsignedConstant();
+ return None;
+ }
+
+ /// Take an optional DWARFFormValue and extract a unsigned constant.
+ ///
+ /// \param V and optional DWARFFormValue to attempt to extract the value from.
+ /// \param Default the default value to return in case of failure.
+ /// \returns the extracted unsigned value or Default if the V doesn't have a
+ /// value or the form value's encoding wasn't an unsigned constant form.
+ inline uint64_t
+ toUnsigned(const Optional<DWARFFormValue>& V, uint64_t Default) {
+ return toUnsigned(V).getValueOr(Default);
+ }
+
+ /// Take an optional DWARFFormValue and try to extract an reference.
+ ///
+ /// \param V and optional DWARFFormValue to attempt to extract the value from.
+ /// \returns an optional value that contains a value if the form value
+ /// was valid and has a reference form.
+ inline Optional<uint64_t> toReference(const Optional<DWARFFormValue>& V) {
+ if (V)
+ return V->getAsReference();
+ return None;
+ }
+
+ /// Take an optional DWARFFormValue and extract a reference.
+ ///
+ /// \param V and optional DWARFFormValue to attempt to extract the value from.
+ /// \param Default the default value to return in case of failure.
+ /// \returns the extracted reference value or Default if the V doesn't have a
+ /// value or the form value's encoding wasn't a reference form.
+ inline uint64_t
+ toReference(const Optional<DWARFFormValue>& V, uint64_t Default) {
+ return toReference(V).getValueOr(Default);
+ }
+
+ /// Take an optional DWARFFormValue and try to extract an signed constant.
+ ///
+ /// \param V and optional DWARFFormValue to attempt to extract the value from.
+ /// \returns an optional value that contains a value if the form value
+ /// was valid and has a signed constant form.
+ inline Optional<int64_t> toSigned(const Optional<DWARFFormValue>& V) {
+ if (V)
+ return V->getAsSignedConstant();
+ return None;
+ }
+
+ /// Take an optional DWARFFormValue and extract a signed integer.
+ ///
+ /// \param V and optional DWARFFormValue to attempt to extract the value from.
+ /// \param Default the default value to return in case of failure.
+ /// \returns the extracted signed integer value or Default if the V doesn't
+ /// have a value or the form value's encoding wasn't a signed integer form.
+ inline int64_t
+ toSigned(const Optional<DWARFFormValue>& V, int64_t Default) {
+ return toSigned(V).getValueOr(Default);
+ }
+
+ /// Take an optional DWARFFormValue and try to extract an address.
+ ///
+ /// \param V and optional DWARFFormValue to attempt to extract the value from.
+ /// \returns an optional value that contains a value if the form value
+ /// was valid and has a address form.
+ inline Optional<uint64_t> toAddress(const Optional<DWARFFormValue>& V) {
+ if (V)
+ return V->getAsAddress();
+ return None;
+ }
+
+ /// Take an optional DWARFFormValue and extract a address.
+ ///
+ /// \param V and optional DWARFFormValue to attempt to extract the value from.
+ /// \param Default the default value to return in case of failure.
+ /// \returns the extracted address value or Default if the V doesn't have a
+ /// value or the form value's encoding wasn't an address form.
+ inline uint64_t
+ toAddress(const Optional<DWARFFormValue>& V, uint64_t Default) {
+ return toAddress(V).getValueOr(Default);
+ }
+
+ /// Take an optional DWARFFormValue and try to extract an section offset.
+ ///
+ /// \param V and optional DWARFFormValue to attempt to extract the value from.
+ /// \returns an optional value that contains a value if the form value
+ /// was valid and has a section offset form.
+ inline Optional<uint64_t> toSectionOffset(const Optional<DWARFFormValue>& V) {
+ if (V)
+ return V->getAsSectionOffset();
+ return None;
+ }
+
+ /// Take an optional DWARFFormValue and extract a section offset.
+ ///
+ /// \param V and optional DWARFFormValue to attempt to extract the value from.
+ /// \param Default the default value to return in case of failure.
+ /// \returns the extracted section offset value or Default if the V doesn't
+ /// have a value or the form value's encoding wasn't a section offset form.
+ inline uint64_t
+ toSectionOffset(const Optional<DWARFFormValue>& V, uint64_t Default) {
+ return toSectionOffset(V).getValueOr(Default);
+ }
+
+ /// Take an optional DWARFFormValue and try to extract block data.
+ ///
+ /// \param V and optional DWARFFormValue to attempt to extract the value from.
+ /// \returns an optional value that contains a value if the form value
+ /// was valid and has a block form.
+ inline Optional<ArrayRef<uint8_t>>
+ toBlock(const Optional<DWARFFormValue>& V) {
+ if (V)
+ return V->getAsBlock();
+ return None;
+ }
+
+} // end namespace dwarf
+
+} // end namespace llvm
-#endif
+#endif // LLVM_DEBUGINFO_DWARFFORMVALUE_H
diff --git a/include/llvm/DebugInfo/DWARF/DWARFGdbIndex.h b/include/llvm/DebugInfo/DWARF/DWARFGdbIndex.h
index 66041be96566..7a52218663b9 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFGdbIndex.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFGdbIndex.h
@@ -1,4 +1,4 @@
-//===-- DWARFGdbIndex.h -----------------------------------------*- C++ -*-===//
+//===- DWARFGdbIndex.h ------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,14 +7,19 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_LIB_DEBUGINFO_DWARFGDBINDEX_H
-#define LLVM_LIB_DEBUGINFO_DWARFGDBINDEX_H
+#ifndef LLVM_DEBUGINFO_DWARF_DWARFGDBINDEX_H
+#define LLVM_DEBUGINFO_DWARF_DWARFGDBINDEX_H
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/Support/DataExtractor.h"
-#include "llvm/Support/Error.h"
-#include "llvm/Support/raw_ostream.h"
+#include <cstdint>
+#include <utility>
namespace llvm {
+
+class raw_ostream;
+
class DWARFGdbIndex {
uint32_t Version;
@@ -63,6 +68,7 @@ public:
bool HasContent = false;
bool HasError = false;
};
-}
-#endif // LLVM_LIB_DEBUGINFO_DWARFGDBINDEX_H
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_DWARF_DWARFGDBINDEX_H
diff --git a/include/llvm/DebugInfo/DWARF/DWARFRelocMap.h b/include/llvm/DebugInfo/DWARF/DWARFRelocMap.h
index d7fe3032e505..af01bddeed15 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFRelocMap.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFRelocMap.h
@@ -1,4 +1,4 @@
-//===-- DWARFRelocMap.h -----------------------------------------*- C++ -*-===//
+//===- DWARFRelocMap.h ------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,16 +7,17 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_LIB_DEBUGINFO_DWARFRELOCMAP_H
-#define LLVM_LIB_DEBUGINFO_DWARFRELOCMAP_H
+#ifndef LLVM_DEBUGINFO_DWARF_DWARFRELOCMAP_H
+#define LLVM_DEBUGINFO_DWARF_DWARFRELOCMAP_H
#include "llvm/ADT/DenseMap.h"
+#include <cstdint>
+#include <utility>
namespace llvm {
-typedef DenseMap<uint64_t, std::pair<uint8_t, int64_t> > RelocAddrMap;
+typedef DenseMap<uint64_t, std::pair<uint8_t, int64_t>> RelocAddrMap;
-} // namespace llvm
-
-#endif
+} // end namespace llvm
+#endif // LLVM_DEBUGINFO_DWARF_DWARFRELOCMAP_H
diff --git a/include/llvm/DebugInfo/DWARF/DWARFSection.h b/include/llvm/DebugInfo/DWARF/DWARFSection.h
index 3e27b529e97b..2b8a53a4c93e 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFSection.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFSection.h
@@ -1,4 +1,4 @@
-//===-- DWARFSection.h ------------------------------------------*- C++ -*-===//
+//===- DWARFSection.h -------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,11 +7,11 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_LIB_DEBUGINFO_DWARFSECTION_H
-#define LLVM_LIB_DEBUGINFO_DWARFSECTION_H
+#ifndef LLVM_DEBUGINFO_DWARF_DWARFSECTION_H
+#define LLVM_DEBUGINFO_DWARF_DWARFSECTION_H
-#include "llvm/DebugInfo/DWARF/DWARFRelocMap.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/DebugInfo/DWARF/DWARFRelocMap.h"
namespace llvm {
@@ -20,6 +20,6 @@ struct DWARFSection {
RelocAddrMap Relocs;
};
-}
+} // end namespace llvm
-#endif
+#endif // LLVM_DEBUGINFO_DWARF_DWARFSECTION_H
diff --git a/include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h b/include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h
index 4f1e1292a1f1..703316005887 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h
@@ -1,4 +1,4 @@
-//===-- DWARFTypeUnit.h -----------------------------------------*- C++ -*-===//
+//===- DWARFTypeUnit.h ------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,17 +7,27 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_LIB_DEBUGINFO_DWARFTYPEUNIT_H
-#define LLVM_LIB_DEBUGINFO_DWARFTYPEUNIT_H
+#ifndef LLVM_DEBUGINFO_DWARF_DWARFTYPEUNIT_H
+#define LLVM_DEBUGINFO_DWARF_DWARFTYPEUNIT_H
+#include "llvm/ADT/StringRef.h"
#include "llvm/DebugInfo/DWARF/DWARFUnit.h"
+#include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h"
+#include "llvm/Support/DataExtractor.h"
+#include <cstdint>
namespace llvm {
+class DWARFContext;
+class DWARFDebugAbbrev;
+struct DWARFSection;
+class raw_ostream;
+
class DWARFTypeUnit : public DWARFUnit {
private:
uint64_t TypeHash;
uint32_t TypeOffset;
+
public:
DWARFTypeUnit(DWARFContext &Context, const DWARFSection &Section,
const DWARFDebugAbbrev *DA, StringRef RS, StringRef SS,
@@ -26,9 +36,11 @@ public:
const DWARFUnitIndex::Entry *Entry)
: DWARFUnit(Context, Section, DA, RS, SS, SOS, AOS, LS, LE, IsDWO,
UnitSection, Entry) {}
+
uint32_t getHeaderSize() const override {
return DWARFUnit::getHeaderSize() + 12;
}
+
void dump(raw_ostream &OS, bool Brief = false);
static const DWARFSectionKind Section = DW_SECT_TYPES;
@@ -36,7 +48,6 @@ protected:
bool extractImpl(DataExtractor debug_info, uint32_t *offset_ptr) override;
};
-}
-
-#endif
+} // end namespace llvm
+#endif // LLVM_DEBUGINFO_DWARF_DWARFTYPEUNIT_H
diff --git a/include/llvm/DebugInfo/DWARF/DWARFUnit.h b/include/llvm/DebugInfo/DWARF/DWARFUnit.h
index db7b59be90c2..40eb4434bd61 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFUnit.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFUnit.h
@@ -1,4 +1,4 @@
-//===-- DWARFUnit.h ---------------------------------------------*- C++ -*-===//
+//===- DWARFUnit.h ----------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,32 +7,37 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_LIB_DEBUGINFO_DWARFUNIT_H
-#define LLVM_LIB_DEBUGINFO_DWARFUNIT_H
+#ifndef LLVM_DEBUGINFO_DWARF_DWARFUNIT_H
+#define LLVM_DEBUGINFO_DWARF_DWARFUNIT_H
-#include "llvm/ADT/Optional.h"
#include "llvm/ADT/iterator_range.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/STLExtras.h"
-#include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h"
#include "llvm/DebugInfo/DWARF/DWARFDie.h"
#include "llvm/DebugInfo/DWARF/DWARFRelocMap.h"
#include "llvm/DebugInfo/DWARF/DWARFSection.h"
#include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h"
+#include "llvm/Object/Binary.h"
+#include "llvm/Object/ObjectFile.h"
+#include "llvm/Support/DataExtractor.h"
+#include "llvm/Support/Dwarf.h"
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <memory>
#include <vector>
namespace llvm {
-namespace object {
-class ObjectFile;
-}
-
+class DWARFAbbreviationDeclarationSet;
class DWARFContext;
class DWARFDebugAbbrev;
class DWARFUnit;
-class StringRef;
-class raw_ostream;
/// Base class for all DWARFUnitSection classes. This provides the
/// functionality common to all unit types.
@@ -47,12 +52,12 @@ public:
DWARFUnitIndex *Index = nullptr);
protected:
+ ~DWARFUnitSectionBase() = default;
+
virtual void parseImpl(DWARFContext &Context, const DWARFSection &Section,
const DWARFDebugAbbrev *DA, StringRef RS, StringRef SS,
StringRef SOS, StringRef AOS, StringRef LS,
bool isLittleEndian, bool isDWO) = 0;
-
- ~DWARFUnitSectionBase() = default;
};
const DWARFUnitIndex &getDWARFUnitIndex(DWARFContext &Context,
@@ -65,7 +70,7 @@ class DWARFUnitSection final : public SmallVector<std::unique_ptr<UnitType>, 1>,
bool Parsed = false;
public:
- typedef llvm::SmallVectorImpl<std::unique_ptr<UnitType>> UnitVector;
+ typedef SmallVectorImpl<std::unique_ptr<UnitType>> UnitVector;
typedef typename UnitVector::iterator iterator;
typedef llvm::iterator_range<typename UnitVector::iterator> iterator_range;
@@ -122,8 +127,9 @@ class DWARFUnit {
uint32_t Offset;
uint32_t Length;
- uint16_t Version;
const DWARFAbbreviationDeclarationSet *Abbrevs;
+ uint16_t Version;
+ uint8_t UnitType;
uint8_t AddrSize;
uint64_t BaseAddr;
// The compile unit debug information entry items.
@@ -134,9 +140,11 @@ class DWARFUnit {
class DWOHolder {
object::OwningBinary<object::ObjectFile> DWOFile;
std::unique_ptr<DWARFContext> DWOContext;
- DWARFUnit *DWOU;
+ DWARFUnit *DWOU = nullptr;
+
public:
DWOHolder(StringRef DWOPath);
+
DWARFUnit *getUnit() const { return DWOU; }
};
std::unique_ptr<DWOHolder> DWO;
@@ -151,8 +159,9 @@ class DWARFUnit {
protected:
virtual bool extractImpl(DataExtractor debug_info, uint32_t *offset_ptr);
+
/// Size in bytes of the unit header.
- virtual uint32_t getHeaderSize() const { return 11; }
+ virtual uint32_t getHeaderSize() const { return Version <= 4 ? 11 : 12; }
public:
DWARFUnit(DWARFContext &Context, const DWARFSection &Section,
@@ -168,10 +177,12 @@ public:
StringRef getLineSection() const { return LineSection; }
StringRef getStringSection() const { return StringSection; }
StringRef getStringOffsetSection() const { return StringOffsetSection; }
+
void setAddrOffsetSection(StringRef AOS, uint32_t Base) {
AddrOffsetSection = AOS;
AddrOffsetSectionBase = Base;
}
+
void setRangesSection(StringRef RS, uint32_t Base) {
RangeSection = RS;
RangeSectionBase = Base;
@@ -184,6 +195,7 @@ public:
DataExtractor getDebugInfoExtractor() const {
return DataExtractor(InfoSection.Data, isLittleEndian, AddrSize);
}
+
DataExtractor getStringExtractor() const {
return DataExtractor(StringSection, false, 0);
}
@@ -202,23 +214,30 @@ public:
uint32_t getNextUnitOffset() const { return Offset + Length + 4; }
uint32_t getLength() const { return Length; }
uint16_t getVersion() const { return Version; }
+
dwarf::DwarfFormat getFormat() const {
return dwarf::DwarfFormat::DWARF32; // FIXME: Support DWARF64.
}
+
const DWARFAbbreviationDeclarationSet *getAbbreviations() const {
return Abbrevs;
}
+
+ uint8_t getUnitType() const { return UnitType; }
uint8_t getAddressByteSize() const { return AddrSize; }
+
uint8_t getRefAddrByteSize() const {
if (Version == 2)
return AddrSize;
return getDwarfOffsetByteSize();
}
+
uint8_t getDwarfOffsetByteSize() const {
if (getFormat() == dwarf::DwarfFormat::DWARF64)
return 8;
return 4;
}
+
uint64_t getBaseAddress() const { return BaseAddr; }
void setBaseAddress(uint64_t base_addr) {
@@ -308,9 +327,11 @@ private:
/// extractDIEsIfNeeded - Parses a compile unit and indexes its DIEs if it
/// hasn't already been done. Returns the number of DIEs parsed at this call.
size_t extractDIEsIfNeeded(bool CUDieOnly);
+
/// extractDIEsToVector - Appends all parsed DIEs to a vector.
void extractDIEsToVector(bool AppendCUDie, bool AppendNonCUDIEs,
std::vector<DWARFDebugInfoEntry> &DIEs) const;
+
/// clearDIEs - Clear parsed DIEs to keep memory usage low.
void clearDIEs(bool KeepCUDie);
@@ -324,6 +345,6 @@ private:
DWARFDie getSubprogramForAddress(uint64_t Address);
};
-}
+} // end namespace llvm
-#endif
+#endif // LLVM_DEBUGINFO_DWARF_DWARFUNIT_H
diff --git a/include/llvm/DebugInfo/DWARF/DWARFUnitIndex.h b/include/llvm/DebugInfo/DWARF/DWARFUnitIndex.h
index 9f051cd7081c..8e2ce023695b 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFUnitIndex.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFUnitIndex.h
@@ -1,4 +1,4 @@
-//===-- DWARFUnitIndex.h --------------------------------------------------===//
+//===- DWARFUnitIndex.h -----------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,17 +7,19 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_LIB_DEBUGINFO_DWARFUNITINDEX_H
-#define LLVM_LIB_DEBUGINFO_DWARFUNITINDEX_H
+#ifndef LLVM_DEBUGINFO_DWARF_DWARFUNITINDEX_H
+#define LLVM_DEBUGINFO_DWARF_DWARFUNITINDEX_H
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/Support/DataExtractor.h"
-#include "llvm/Support/Format.h"
-#include "llvm/Support/raw_ostream.h"
#include <cstdint>
+#include <memory>
namespace llvm {
+class raw_ostream;
+
enum DWARFSectionKind {
DW_SECT_INFO = 1,
DW_SECT_TYPES,
@@ -57,9 +59,11 @@ public:
public:
const SectionContribution *getOffset(DWARFSectionKind Sec) const;
const SectionContribution *getOffset() const;
+
const SectionContribution *getOffsets() const {
return Contributions.get();
}
+
uint64_t getSignature() const { return Signature; }
};
@@ -72,21 +76,26 @@ private:
std::unique_ptr<Entry[]> Rows;
static StringRef getColumnHeader(DWARFSectionKind DS);
+
bool parseImpl(DataExtractor IndexData);
public:
- bool parse(DataExtractor IndexData);
DWARFUnitIndex(DWARFSectionKind InfoColumnKind)
: InfoColumnKind(InfoColumnKind) {}
+
+ bool parse(DataExtractor IndexData);
void dump(raw_ostream &OS) const;
const Entry *getFromOffset(uint32_t Offset) const;
+
ArrayRef<DWARFSectionKind> getColumnKinds() const {
return makeArrayRef(ColumnKinds.get(), Header.NumColumns);
}
+
ArrayRef<Entry> getRows() const {
return makeArrayRef(Rows.get(), Header.NumBuckets);
}
};
-}
-#endif
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_DWARF_DWARFUNITINDEX_H
diff --git a/include/llvm/DebugInfo/MSF/ByteStream.h b/include/llvm/DebugInfo/MSF/ByteStream.h
deleted file mode 100644
index 547844be5e5d..000000000000
--- a/include/llvm/DebugInfo/MSF/ByteStream.h
+++ /dev/null
@@ -1,169 +0,0 @@
-//===- ByteStream.h - Reads stream data from a byte sequence ----*- 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_MSF_BYTESTREAM_H
-#define LLVM_DEBUGINFO_MSF_BYTESTREAM_H
-
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/DebugInfo/MSF/MSFError.h"
-#include "llvm/DebugInfo/MSF/StreamInterface.h"
-#include "llvm/Support/Error.h"
-#include "llvm/Support/FileOutputBuffer.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include <algorithm>
-#include <cstdint>
-#include <cstring>
-#include <memory>
-
-namespace llvm {
-namespace msf {
-
-class ByteStream : public ReadableStream {
-public:
- ByteStream() = default;
- explicit ByteStream(ArrayRef<uint8_t> Data) : Data(Data) {}
- explicit ByteStream(StringRef Data)
- : Data(Data.bytes_begin(), Data.bytes_end()) {}
-
- Error readBytes(uint32_t Offset, uint32_t Size,
- ArrayRef<uint8_t> &Buffer) const override {
- if (Offset > Data.size())
- return make_error<MSFError>(msf_error_code::insufficient_buffer);
- if (Data.size() < Size + Offset)
- return make_error<MSFError>(msf_error_code::insufficient_buffer);
- Buffer = Data.slice(Offset, Size);
- return Error::success();
- }
-
- Error readLongestContiguousChunk(uint32_t Offset,
- ArrayRef<uint8_t> &Buffer) const override {
- if (Offset >= Data.size())
- return make_error<MSFError>(msf_error_code::insufficient_buffer);
- Buffer = Data.slice(Offset);
- return Error::success();
- }
-
- uint32_t getLength() const override { return Data.size(); }
-
- ArrayRef<uint8_t> data() const { return Data; }
-
- StringRef str() const {
- const char *CharData = reinterpret_cast<const char *>(Data.data());
- return StringRef(CharData, Data.size());
- }
-
-protected:
- ArrayRef<uint8_t> Data;
-};
-
-// MemoryBufferByteStream behaves like a read-only ByteStream, but has its data
-// backed by an llvm::MemoryBuffer. It also owns the underlying MemoryBuffer.
-class MemoryBufferByteStream : public ByteStream {
-public:
- explicit MemoryBufferByteStream(std::unique_ptr<MemoryBuffer> Buffer)
- : ByteStream(ArrayRef<uint8_t>(Buffer->getBuffer().bytes_begin(),
- Buffer->getBuffer().bytes_end())),
- MemBuffer(std::move(Buffer)) {}
-
- std::unique_ptr<MemoryBuffer> MemBuffer;
-};
-
-class MutableByteStream : public WritableStream {
-public:
- MutableByteStream() = default;
- explicit MutableByteStream(MutableArrayRef<uint8_t> Data)
- : Data(Data), ImmutableStream(Data) {}
-
- Error readBytes(uint32_t Offset, uint32_t Size,
- ArrayRef<uint8_t> &Buffer) const override {
- return ImmutableStream.readBytes(Offset, Size, Buffer);
- }
-
- Error readLongestContiguousChunk(uint32_t Offset,
- ArrayRef<uint8_t> &Buffer) const override {
- return ImmutableStream.readLongestContiguousChunk(Offset, Buffer);
- }
-
- uint32_t getLength() const override { return ImmutableStream.getLength(); }
-
- Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> Buffer) const override {
- if (Buffer.empty())
- return Error::success();
-
- if (Data.size() < Buffer.size())
- return make_error<MSFError>(msf_error_code::insufficient_buffer);
- if (Offset > Buffer.size() - Data.size())
- return make_error<MSFError>(msf_error_code::insufficient_buffer);
-
- uint8_t *DataPtr = const_cast<uint8_t *>(Data.data());
- ::memcpy(DataPtr + Offset, Buffer.data(), Buffer.size());
- return Error::success();
- }
-
- Error commit() const override { return Error::success(); }
-
- MutableArrayRef<uint8_t> data() const { return Data; }
-
-private:
- MutableArrayRef<uint8_t> Data;
- ByteStream ImmutableStream;
-};
-
-// A simple adapter that acts like a ByteStream but holds ownership over
-// and underlying FileOutputBuffer.
-class FileBufferByteStream : public WritableStream {
-private:
- class StreamImpl : public MutableByteStream {
- public:
- StreamImpl(std::unique_ptr<FileOutputBuffer> Buffer)
- : MutableByteStream(MutableArrayRef<uint8_t>(Buffer->getBufferStart(),
- Buffer->getBufferEnd())),
- FileBuffer(std::move(Buffer)) {}
-
- Error commit() const override {
- if (FileBuffer->commit())
- return llvm::make_error<MSFError>(msf_error_code::not_writable);
- return Error::success();
- }
-
- private:
- std::unique_ptr<FileOutputBuffer> FileBuffer;
- };
-
-public:
- explicit FileBufferByteStream(std::unique_ptr<FileOutputBuffer> Buffer)
- : Impl(std::move(Buffer)) {}
-
- Error readBytes(uint32_t Offset, uint32_t Size,
- ArrayRef<uint8_t> &Buffer) const override {
- return Impl.readBytes(Offset, Size, Buffer);
- }
-
- Error readLongestContiguousChunk(uint32_t Offset,
- ArrayRef<uint8_t> &Buffer) const override {
- return Impl.readLongestContiguousChunk(Offset, Buffer);
- }
-
- uint32_t getLength() const override { return Impl.getLength(); }
-
- Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> Data) const override {
- return Impl.writeBytes(Offset, Data);
- }
-
- Error commit() const override { return Impl.commit(); }
-
-private:
- StreamImpl Impl;
-};
-
-} // end namespace msf
-} // end namespace llvm
-
-#endif // LLVM_DEBUGINFO_MSF_BYTESTREAM_H
diff --git a/include/llvm/DebugInfo/MSF/MappedBlockStream.h b/include/llvm/DebugInfo/MSF/MappedBlockStream.h
index fff4e9cecef5..c91f6f725c80 100644
--- a/include/llvm/DebugInfo/MSF/MappedBlockStream.h
+++ b/include/llvm/DebugInfo/MSF/MappedBlockStream.h
@@ -15,8 +15,10 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/DebugInfo/MSF/MSFStreamLayout.h"
-#include "llvm/DebugInfo/MSF/StreamInterface.h"
#include "llvm/Support/Allocator.h"
+#include "llvm/Support/BinaryStream.h"
+#include "llvm/Support/BinaryStream.h"
+#include "llvm/Support/BinaryStreamRef.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/Error.h"
#include <cstdint>
@@ -37,29 +39,33 @@ struct MSFLayout;
/// the MSF. MappedBlockStream provides methods for reading from and writing
/// to one of these streams transparently, as if it were a contiguous sequence
/// of bytes.
-class MappedBlockStream : public ReadableStream {
+class MappedBlockStream : public BinaryStream {
friend class WritableMappedBlockStream;
public:
static std::unique_ptr<MappedBlockStream>
createStream(uint32_t BlockSize, uint32_t NumBlocks,
- const MSFStreamLayout &Layout, const ReadableStream &MsfData);
+ const MSFStreamLayout &Layout, BinaryStreamRef MsfData);
static std::unique_ptr<MappedBlockStream>
- createIndexedStream(const MSFLayout &Layout, const ReadableStream &MsfData,
+ createIndexedStream(const MSFLayout &Layout, BinaryStreamRef MsfData,
uint32_t StreamIndex);
static std::unique_ptr<MappedBlockStream>
- createFpmStream(const MSFLayout &Layout, const ReadableStream &MsfData);
+ createFpmStream(const MSFLayout &Layout, BinaryStreamRef MsfData);
static std::unique_ptr<MappedBlockStream>
- createDirectoryStream(const MSFLayout &Layout, const ReadableStream &MsfData);
+ createDirectoryStream(const MSFLayout &Layout, BinaryStreamRef MsfData);
+
+ llvm::support::endianness getEndian() const override {
+ return llvm::support::little;
+ }
Error readBytes(uint32_t Offset, uint32_t Size,
- ArrayRef<uint8_t> &Buffer) const override;
+ ArrayRef<uint8_t> &Buffer) override;
Error readLongestContiguousChunk(uint32_t Offset,
- ArrayRef<uint8_t> &Buffer) const override;
+ ArrayRef<uint8_t> &Buffer) override;
- uint32_t getLength() const override;
+ uint32_t getLength() override;
uint32_t getNumBytesCopied() const;
@@ -74,51 +80,56 @@ public:
protected:
MappedBlockStream(uint32_t BlockSize, uint32_t NumBlocks,
const MSFStreamLayout &StreamLayout,
- const ReadableStream &MsfData);
+ BinaryStreamRef MsfData);
private:
const MSFStreamLayout &getStreamLayout() const { return StreamLayout; }
void fixCacheAfterWrite(uint32_t Offset, ArrayRef<uint8_t> Data) const;
- Error readBytes(uint32_t Offset, MutableArrayRef<uint8_t> Buffer) const;
+ Error readBytes(uint32_t Offset, MutableArrayRef<uint8_t> Buffer);
bool tryReadContiguously(uint32_t Offset, uint32_t Size,
- ArrayRef<uint8_t> &Buffer) const;
+ ArrayRef<uint8_t> &Buffer);
const uint32_t BlockSize;
const uint32_t NumBlocks;
const MSFStreamLayout StreamLayout;
- const ReadableStream &MsfData;
+ BinaryStreamRef MsfData;
typedef MutableArrayRef<uint8_t> CacheEntry;
- mutable llvm::BumpPtrAllocator Pool;
- mutable DenseMap<uint32_t, std::vector<CacheEntry>> CacheMap;
+ llvm::BumpPtrAllocator Pool;
+ DenseMap<uint32_t, std::vector<CacheEntry>> CacheMap;
};
-class WritableMappedBlockStream : public WritableStream {
+class WritableMappedBlockStream : public WritableBinaryStream {
public:
static std::unique_ptr<WritableMappedBlockStream>
createStream(uint32_t BlockSize, uint32_t NumBlocks,
- const MSFStreamLayout &Layout, const WritableStream &MsfData);
+ const MSFStreamLayout &Layout, WritableBinaryStreamRef MsfData);
static std::unique_ptr<WritableMappedBlockStream>
- createIndexedStream(const MSFLayout &Layout, const WritableStream &MsfData,
+ createIndexedStream(const MSFLayout &Layout, WritableBinaryStreamRef MsfData,
uint32_t StreamIndex);
static std::unique_ptr<WritableMappedBlockStream>
- createDirectoryStream(const MSFLayout &Layout, const WritableStream &MsfData);
+ createDirectoryStream(const MSFLayout &Layout,
+ WritableBinaryStreamRef MsfData);
static std::unique_ptr<WritableMappedBlockStream>
- createFpmStream(const MSFLayout &Layout, const WritableStream &MsfData);
+ createFpmStream(const MSFLayout &Layout, WritableBinaryStreamRef MsfData);
+
+ llvm::support::endianness getEndian() const override {
+ return llvm::support::little;
+ }
Error readBytes(uint32_t Offset, uint32_t Size,
- ArrayRef<uint8_t> &Buffer) const override;
+ ArrayRef<uint8_t> &Buffer) override;
Error readLongestContiguousChunk(uint32_t Offset,
- ArrayRef<uint8_t> &Buffer) const override;
- uint32_t getLength() const override;
+ ArrayRef<uint8_t> &Buffer) override;
+ uint32_t getLength() override;
- Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> Buffer) const override;
+ Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> Buffer) override;
- Error commit() const override;
+ Error commit() override;
const MSFStreamLayout &getStreamLayout() const {
return ReadInterface.getStreamLayout();
@@ -130,12 +141,12 @@ public:
protected:
WritableMappedBlockStream(uint32_t BlockSize, uint32_t NumBlocks,
const MSFStreamLayout &StreamLayout,
- const WritableStream &MsfData);
+ WritableBinaryStreamRef MsfData);
private:
MappedBlockStream ReadInterface;
- const WritableStream &WriteInterface;
+ WritableBinaryStreamRef WriteInterface;
};
} // end namespace pdb
diff --git a/include/llvm/DebugInfo/MSF/StreamInterface.h b/include/llvm/DebugInfo/MSF/StreamInterface.h
deleted file mode 100644
index 09782d8e3b30..000000000000
--- a/include/llvm/DebugInfo/MSF/StreamInterface.h
+++ /dev/null
@@ -1,53 +0,0 @@
-//===- StreamInterface.h - Base interface for a stream of data --*- 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_MSF_STREAMINTERFACE_H
-#define LLVM_DEBUGINFO_MSF_STREAMINTERFACE_H
-
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/Support/Error.h"
-#include <cstdint>
-
-namespace llvm {
-namespace msf {
-
-class ReadableStream {
-public:
- virtual ~ReadableStream() = default;
-
- // Given an offset into the stream and a number of bytes, attempt to read
- // the bytes and set the output ArrayRef to point to a reference into the
- // stream, without copying any data.
- virtual Error readBytes(uint32_t Offset, uint32_t Size,
- ArrayRef<uint8_t> &Buffer) const = 0;
-
- // Given an offset into the stream, read as much as possible without copying
- // any data.
- virtual Error readLongestContiguousChunk(uint32_t Offset,
- ArrayRef<uint8_t> &Buffer) const = 0;
-
- virtual uint32_t getLength() const = 0;
-};
-
-class WritableStream : public ReadableStream {
-public:
- ~WritableStream() override = default;
-
- // Attempt to write the given bytes into the stream at the desired offset.
- // This will always necessitate a copy. Cannot shrink or grow the stream,
- // only writes into existing allocated space.
- virtual Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> Data) const = 0;
-
- virtual Error commit() const = 0;
-};
-
-} // end namespace msf
-} // end namespace llvm
-
-#endif // LLVM_DEBUGINFO_MSF_STREAMINTERFACE_H
diff --git a/include/llvm/DebugInfo/MSF/StreamReader.h b/include/llvm/DebugInfo/MSF/StreamReader.h
deleted file mode 100644
index fc2ca78dc18f..000000000000
--- a/include/llvm/DebugInfo/MSF/StreamReader.h
+++ /dev/null
@@ -1,121 +0,0 @@
-//===- StreamReader.h - Reads bytes and objects from a stream ---*- 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_MSF_STREAMREADER_H
-#define LLVM_DEBUGINFO_MSF_STREAMREADER_H
-
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/DebugInfo/MSF/MSFError.h"
-#include "llvm/DebugInfo/MSF/StreamArray.h"
-#include "llvm/DebugInfo/MSF/StreamInterface.h"
-#include "llvm/DebugInfo/MSF/StreamRef.h"
-#include "llvm/Support/Endian.h"
-#include "llvm/Support/Error.h"
-
-#include <string>
-
-namespace llvm {
-namespace msf {
-
-class StreamReader {
-public:
- StreamReader(ReadableStreamRef Stream);
-
- Error readLongestContiguousChunk(ArrayRef<uint8_t> &Buffer);
- Error readBytes(ArrayRef<uint8_t> &Buffer, uint32_t Size);
- Error readInteger(uint8_t &Dest);
- Error readInteger(uint16_t &Dest);
- Error readInteger(uint32_t &Dest);
- Error readInteger(uint64_t &Dest);
- Error readInteger(int8_t &Dest);
- Error readInteger(int16_t &Dest);
- Error readInteger(int32_t &Dest);
- Error readInteger(int64_t &Dest);
- Error readZeroString(StringRef &Dest);
- Error readFixedString(StringRef &Dest, uint32_t Length);
- Error readStreamRef(ReadableStreamRef &Ref);
- Error readStreamRef(ReadableStreamRef &Ref, uint32_t Length);
-
- template <typename T> Error readEnum(T &Dest) {
- typename std::underlying_type<T>::type N;
- if (auto EC = readInteger(N))
- return EC;
- Dest = static_cast<T>(N);
- return Error::success();
- }
-
- template <typename T> Error readObject(const T *&Dest) {
- ArrayRef<uint8_t> Buffer;
- if (auto EC = readBytes(Buffer, sizeof(T)))
- return EC;
- Dest = reinterpret_cast<const T *>(Buffer.data());
- return Error::success();
- }
-
- template <typename T>
- Error readArray(ArrayRef<T> &Array, uint32_t NumElements) {
- ArrayRef<uint8_t> Bytes;
- if (NumElements == 0) {
- Array = ArrayRef<T>();
- return Error::success();
- }
-
- if (NumElements > UINT32_MAX / sizeof(T))
- return make_error<MSFError>(msf_error_code::insufficient_buffer);
-
- if (auto EC = readBytes(Bytes, NumElements * sizeof(T)))
- return EC;
- Array = ArrayRef<T>(reinterpret_cast<const T *>(Bytes.data()), NumElements);
- return Error::success();
- }
-
- template <typename T, typename U>
- Error readArray(VarStreamArray<T, U> &Array, uint32_t Size) {
- ReadableStreamRef S;
- if (auto EC = readStreamRef(S, Size))
- return EC;
- Array = VarStreamArray<T, U>(S, Array.getExtractor());
- return Error::success();
- }
-
- template <typename T>
- Error readArray(FixedStreamArray<T> &Array, uint32_t NumItems) {
- if (NumItems == 0) {
- Array = FixedStreamArray<T>();
- return Error::success();
- }
- uint32_t Length = NumItems * sizeof(T);
- if (Length / sizeof(T) != NumItems)
- return make_error<MSFError>(msf_error_code::invalid_format);
- if (Offset + Length > Stream.getLength())
- return make_error<MSFError>(msf_error_code::insufficient_buffer);
- ReadableStreamRef View = Stream.slice(Offset, Length);
- Array = FixedStreamArray<T>(View);
- Offset += Length;
- return Error::success();
- }
-
- bool empty() const { return bytesRemaining() == 0; }
- void setOffset(uint32_t Off) { Offset = Off; }
- uint32_t getOffset() const { return Offset; }
- uint32_t getLength() const { return Stream.getLength(); }
- uint32_t bytesRemaining() const { return getLength() - getOffset(); }
-
- Error skip(uint32_t Amount);
-
- uint8_t peek() const;
-
-private:
- ReadableStreamRef Stream;
- uint32_t Offset;
-};
-} // namespace msf
-} // namespace llvm
-
-#endif // LLVM_DEBUGINFO_MSF_STREAMREADER_H
diff --git a/include/llvm/DebugInfo/MSF/StreamRef.h b/include/llvm/DebugInfo/MSF/StreamRef.h
deleted file mode 100644
index eee71e53a39b..000000000000
--- a/include/llvm/DebugInfo/MSF/StreamRef.h
+++ /dev/null
@@ -1,135 +0,0 @@
-//===- StreamRef.h - A copyable reference to a stream -----------*- 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_MSF_STREAMREF_H
-#define LLVM_DEBUGINFO_MSF_STREAMREF_H
-
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/DebugInfo/MSF/MSFError.h"
-#include "llvm/DebugInfo/MSF/StreamInterface.h"
-#include "llvm/Support/Error.h"
-#include <algorithm>
-#include <cstdint>
-
-namespace llvm {
-namespace msf {
-
-template <class StreamType, class RefType> class StreamRefBase {
-public:
- StreamRefBase() : Stream(nullptr), ViewOffset(0), Length(0) {}
- StreamRefBase(const StreamType &Stream, uint32_t Offset, uint32_t Length)
- : Stream(&Stream), ViewOffset(Offset), Length(Length) {}
-
- uint32_t getLength() const { return Length; }
- const StreamType *getStream() const { return Stream; }
-
- RefType drop_front(uint32_t N) const {
- if (!Stream)
- return RefType();
-
- N = std::min(N, Length);
- return RefType(*Stream, ViewOffset + N, Length - N);
- }
-
- RefType keep_front(uint32_t N) const {
- if (!Stream)
- return RefType();
- N = std::min(N, Length);
- return RefType(*Stream, ViewOffset, N);
- }
-
- RefType slice(uint32_t Offset, uint32_t Len) const {
- return drop_front(Offset).keep_front(Len);
- }
-
- bool operator==(const RefType &Other) const {
- if (Stream != Other.Stream)
- return false;
- if (ViewOffset != Other.ViewOffset)
- return false;
- if (Length != Other.Length)
- return false;
- return true;
- }
-
-protected:
- const StreamType *Stream;
- uint32_t ViewOffset;
- uint32_t Length;
-};
-
-class ReadableStreamRef
- : public StreamRefBase<ReadableStream, ReadableStreamRef> {
-public:
- ReadableStreamRef() = default;
- ReadableStreamRef(const ReadableStream &Stream)
- : StreamRefBase(Stream, 0, Stream.getLength()) {}
- ReadableStreamRef(const ReadableStream &Stream, uint32_t Offset,
- uint32_t Length)
- : StreamRefBase(Stream, Offset, Length) {}
-
- // Use StreamRef.slice() instead.
- ReadableStreamRef(const ReadableStreamRef &S, uint32_t Offset,
- uint32_t Length) = delete;
-
- Error readBytes(uint32_t Offset, uint32_t Size,
- ArrayRef<uint8_t> &Buffer) const {
- if (ViewOffset + Offset < Offset)
- return make_error<MSFError>(msf_error_code::insufficient_buffer);
- if (Size + Offset > Length)
- return make_error<MSFError>(msf_error_code::insufficient_buffer);
- return Stream->readBytes(ViewOffset + Offset, Size, Buffer);
- }
-
- // Given an offset into the stream, read as much as possible without copying
- // any data.
- Error readLongestContiguousChunk(uint32_t Offset,
- ArrayRef<uint8_t> &Buffer) const {
- if (Offset >= Length)
- return make_error<MSFError>(msf_error_code::insufficient_buffer);
-
- if (auto EC = Stream->readLongestContiguousChunk(Offset, Buffer))
- return EC;
- // This StreamRef might refer to a smaller window over a larger stream. In
- // that case we will have read out more bytes than we should return, because
- // we should not read past the end of the current view.
- uint32_t MaxLength = Length - Offset;
- if (Buffer.size() > MaxLength)
- Buffer = Buffer.slice(0, MaxLength);
- return Error::success();
- }
-};
-
-class WritableStreamRef
- : public StreamRefBase<WritableStream, WritableStreamRef> {
-public:
- WritableStreamRef() = default;
- WritableStreamRef(const WritableStream &Stream)
- : StreamRefBase(Stream, 0, Stream.getLength()) {}
- WritableStreamRef(const WritableStream &Stream, uint32_t Offset,
- uint32_t Length)
- : StreamRefBase(Stream, Offset, Length) {}
-
- // Use StreamRef.slice() instead.
- WritableStreamRef(const WritableStreamRef &S, uint32_t Offset,
- uint32_t Length) = delete;
-
- Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> Data) const {
- if (Data.size() + Offset > Length)
- return make_error<MSFError>(msf_error_code::insufficient_buffer);
- return Stream->writeBytes(ViewOffset + Offset, Data);
- }
-
- Error commit() const { return Stream->commit(); }
-};
-
-} // end namespace msf
-} // end namespace llvm
-
-#endif // LLVM_DEBUGINFO_MSF_STREAMREF_H
diff --git a/include/llvm/DebugInfo/MSF/StreamWriter.h b/include/llvm/DebugInfo/MSF/StreamWriter.h
deleted file mode 100644
index 2bb14434dd83..000000000000
--- a/include/llvm/DebugInfo/MSF/StreamWriter.h
+++ /dev/null
@@ -1,92 +0,0 @@
-//===- StreamWriter.h - Writes bytes and objects to a stream ----*- 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_MSF_STREAMWRITER_H
-#define LLVM_DEBUGINFO_MSF_STREAMWRITER_H
-
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/DebugInfo/MSF/MSFError.h"
-#include "llvm/DebugInfo/MSF/StreamArray.h"
-#include "llvm/DebugInfo/MSF/StreamRef.h"
-#include "llvm/Support/Error.h"
-#include <cstdint>
-#include <type_traits>
-
-namespace llvm {
-namespace msf {
-
-class StreamWriter {
-public:
- StreamWriter() = default;
- explicit StreamWriter(WritableStreamRef Stream);
-
- Error writeBytes(ArrayRef<uint8_t> Buffer);
- Error writeInteger(uint8_t Int);
- Error writeInteger(uint16_t Dest);
- Error writeInteger(uint32_t Dest);
- Error writeInteger(uint64_t Dest);
- Error writeInteger(int8_t Int);
- Error writeInteger(int16_t Dest);
- Error writeInteger(int32_t Dest);
- Error writeInteger(int64_t Dest);
- Error writeZeroString(StringRef Str);
- Error writeFixedString(StringRef Str);
- Error writeStreamRef(ReadableStreamRef Ref);
- Error writeStreamRef(ReadableStreamRef Ref, uint32_t Size);
-
- template <typename T> Error writeEnum(T Num) {
- return writeInteger(
- static_cast<typename std::underlying_type<T>::type>(Num));
- }
-
- template <typename T> Error writeObject(const T &Obj) {
- static_assert(!std::is_pointer<T>::value,
- "writeObject should not be used with pointers, to write "
- "the pointed-to value dereference the pointer before calling "
- "writeObject");
- return writeBytes(
- ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(&Obj), sizeof(T)));
- }
-
- template <typename T> Error writeArray(ArrayRef<T> Array) {
- if (Array.empty())
- return Error::success();
-
- if (Array.size() > UINT32_MAX / sizeof(T))
- return make_error<MSFError>(msf_error_code::insufficient_buffer);
-
- return writeBytes(
- ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Array.data()),
- Array.size() * sizeof(T)));
- }
-
- template <typename T, typename U>
- Error writeArray(VarStreamArray<T, U> Array) {
- return writeStreamRef(Array.getUnderlyingStream());
- }
-
- template <typename T> Error writeArray(FixedStreamArray<T> Array) {
- return writeStreamRef(Array.getUnderlyingStream());
- }
-
- void setOffset(uint32_t Off) { Offset = Off; }
- uint32_t getOffset() const { return Offset; }
- uint32_t getLength() const { return Stream.getLength(); }
- uint32_t bytesRemaining() const { return getLength() - getOffset(); }
-
-private:
- WritableStreamRef Stream;
- uint32_t Offset = 0;
-};
-
-} // end namespace msf
-} // end namespace llvm
-
-#endif // LLVM_DEBUGINFO_MSF_STREAMWRITER_H
diff --git a/include/llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h b/include/llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h
index 9bf073831565..9713dce362d2 100644
--- a/include/llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h
+++ b/include/llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h
@@ -34,12 +34,11 @@ public:
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));
+ return unique_dyn_cast_or_null<ChildType>(Child);
}
std::unique_ptr<ChildType> getNext() override {
- std::unique_ptr<PDBSymbol> Child = Enumerator->getNext();
- return make_concrete_child(std::move(Child));
+ return unique_dyn_cast_or_null<ChildType>(Enumerator->getNext());
}
void reset() override { Enumerator->reset(); }
@@ -50,11 +49,6 @@ public:
}
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;
};
diff --git a/include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h b/include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h
index 1e40c46f8a27..c0633cbdfa52 100644
--- a/include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h
+++ b/include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h
@@ -102,6 +102,7 @@ public:
uint32_t getVirtualBaseDispIndex() const override;
uint32_t getVirtualBaseOffset() const override;
uint32_t getVirtualTableShapeId() const override;
+ std::unique_ptr<PDBSymbolTypeVTable> getVirtualBaseTableType() const override;
PDB_DataKind getDataKind() const override;
PDB_SymType getSymTag() const override;
PDB_UniqueId getGuid() const override;
diff --git a/include/llvm/DebugInfo/PDB/IPDBRawSymbol.h b/include/llvm/DebugInfo/PDB/IPDBRawSymbol.h
index 49866b8bb2f2..4c28e194bc70 100644
--- a/include/llvm/DebugInfo/PDB/IPDBRawSymbol.h
+++ b/include/llvm/DebugInfo/PDB/IPDBRawSymbol.h
@@ -21,6 +21,9 @@ class raw_ostream;
namespace pdb {
+class PDBSymbolTypeVTable;
+class PDBSymbolTypeVTableShape;
+
/// 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
@@ -110,6 +113,8 @@ public:
virtual Variant getValue() const = 0;
virtual uint32_t getVirtualBaseDispIndex() const = 0;
virtual uint32_t getVirtualBaseOffset() const = 0;
+ virtual std::unique_ptr<PDBSymbolTypeVTable>
+ getVirtualBaseTableType() const = 0;
virtual uint32_t getVirtualTableShapeId() const = 0;
virtual PDB_DataKind getDataKind() const = 0;
virtual PDB_SymType getSymTag() const = 0;
diff --git a/include/llvm/DebugInfo/PDB/IPDBSession.h b/include/llvm/DebugInfo/PDB/IPDBSession.h
index 15e97ac198e5..85d9fe124859 100644
--- a/include/llvm/DebugInfo/PDB/IPDBSession.h
+++ b/include/llvm/DebugInfo/PDB/IPDBSession.h
@@ -10,6 +10,7 @@
#ifndef LLVM_DEBUGINFO_PDB_IPDBSESSION_H
#define LLVM_DEBUGINFO_PDB_IPDBSESSION_H
+#include "PDBSymbol.h"
#include "PDBTypes.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Casting.h"
@@ -33,15 +34,7 @@ public:
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;
- (void)Symbol.release();
- return std::unique_ptr<T>(ConcreteSymbol);
+ return unique_dyn_cast_or_null<T>(getSymbolById(SymbolId));
}
virtual std::unique_ptr<PDBSymbol>
diff --git a/include/llvm/DebugInfo/PDB/Raw/DbiStream.h b/include/llvm/DebugInfo/PDB/Native/DbiStream.h
index c97ca32ab43d..f49f5aaefaca 100644
--- a/include/llvm/DebugInfo/PDB/Raw/DbiStream.h
+++ b/include/llvm/DebugInfo/PDB/Native/DbiStream.h
@@ -12,13 +12,15 @@
#include "llvm/DebugInfo/CodeView/ModuleSubstream.h"
#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
-#include "llvm/DebugInfo/MSF/StreamArray.h"
-#include "llvm/DebugInfo/MSF/StreamRef.h"
+#include "llvm/DebugInfo/PDB/Native/ModInfo.h"
+#include "llvm/DebugInfo/PDB/Native/RawConstants.h"
+#include "llvm/DebugInfo/PDB/Native/RawTypes.h"
+#include "llvm/DebugInfo/PDB/Native/StringTable.h"
#include "llvm/DebugInfo/PDB/PDBTypes.h"
-#include "llvm/DebugInfo/PDB/Raw/ModInfo.h"
-#include "llvm/DebugInfo/PDB/Raw/NameHashTable.h"
-#include "llvm/DebugInfo/PDB/Raw/RawConstants.h"
-#include "llvm/DebugInfo/PDB/Raw/RawTypes.h"
+#include "llvm/Support/BinaryStreamArray.h"
+#include "llvm/Support/BinaryStreamArray.h"
+#include "llvm/Support/BinaryStreamRef.h"
+#include "llvm/Support/BinaryStreamRef.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/Error.h"
@@ -70,11 +72,11 @@ public:
Expected<StringRef> getFileNameForIndex(uint32_t Index) const;
- msf::FixedStreamArray<object::coff_section> getSectionHeaders();
+ FixedStreamArray<object::coff_section> getSectionHeaders();
- msf::FixedStreamArray<object::FpoData> getFpoRecords();
+ FixedStreamArray<object::FpoData> getFpoRecords();
- msf::FixedStreamArray<SecMapEntry> getSectionMap() const;
+ FixedStreamArray<SecMapEntry> getSectionMap() const;
void visitSectionContributions(ISectionContribVisitor &Visitor) const;
private:
@@ -89,30 +91,30 @@ private:
std::unique_ptr<msf::MappedBlockStream> Stream;
std::vector<ModuleInfoEx> ModuleInfos;
- NameHashTable ECNames;
+ StringTable ECNames;
- msf::ReadableStreamRef ModInfoSubstream;
- msf::ReadableStreamRef SecContrSubstream;
- msf::ReadableStreamRef SecMapSubstream;
- msf::ReadableStreamRef FileInfoSubstream;
- msf::ReadableStreamRef TypeServerMapSubstream;
- msf::ReadableStreamRef ECSubstream;
+ BinaryStreamRef ModInfoSubstream;
+ BinaryStreamRef SecContrSubstream;
+ BinaryStreamRef SecMapSubstream;
+ BinaryStreamRef FileInfoSubstream;
+ BinaryStreamRef TypeServerMapSubstream;
+ BinaryStreamRef ECSubstream;
- msf::ReadableStreamRef NamesBuffer;
+ BinaryStreamRef NamesBuffer;
- msf::FixedStreamArray<support::ulittle16_t> DbgStreams;
+ FixedStreamArray<support::ulittle16_t> DbgStreams;
PdbRaw_DbiSecContribVer SectionContribVersion;
- msf::FixedStreamArray<SectionContrib> SectionContribs;
- msf::FixedStreamArray<SectionContrib2> SectionContribs2;
- msf::FixedStreamArray<SecMapEntry> SectionMap;
- msf::FixedStreamArray<support::little32_t> FileNameOffsets;
+ FixedStreamArray<SectionContrib> SectionContribs;
+ FixedStreamArray<SectionContrib2> SectionContribs2;
+ FixedStreamArray<SecMapEntry> SectionMap;
+ FixedStreamArray<support::little32_t> FileNameOffsets;
std::unique_ptr<msf::MappedBlockStream> SectionHeaderStream;
- msf::FixedStreamArray<object::coff_section> SectionHeaders;
+ FixedStreamArray<object::coff_section> SectionHeaders;
std::unique_ptr<msf::MappedBlockStream> FpoStream;
- msf::FixedStreamArray<object::FpoData> FpoRecords;
+ FixedStreamArray<object::FpoData> FpoRecords;
const DbiStreamHeader *Header;
};
diff --git a/include/llvm/DebugInfo/PDB/Raw/DbiStreamBuilder.h b/include/llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h
index 99a3ac7fb1da..16426bd93847 100644
--- a/include/llvm/DebugInfo/PDB/Raw/DbiStreamBuilder.h
+++ b/include/llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h
@@ -14,11 +14,11 @@
#include "llvm/ADT/StringSet.h"
#include "llvm/Support/Error.h"
-#include "llvm/DebugInfo/MSF/ByteStream.h"
-#include "llvm/DebugInfo/MSF/StreamReader.h"
+#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
+#include "llvm/DebugInfo/PDB/Native/RawConstants.h"
#include "llvm/DebugInfo/PDB/PDBTypes.h"
-#include "llvm/DebugInfo/PDB/Raw/PDBFile.h"
-#include "llvm/DebugInfo/PDB/Raw/RawConstants.h"
+#include "llvm/Support/BinaryByteStream.h"
+#include "llvm/Support/BinaryStreamReader.h"
#include "llvm/Support/Endian.h"
namespace llvm {
@@ -31,11 +31,13 @@ struct coff_section;
namespace pdb {
class DbiStream;
struct DbiStreamHeader;
+class ModInfoBuilder;
class PDBFile;
class DbiStreamBuilder {
public:
DbiStreamBuilder(msf::MSFBuilder &Msf);
+ ~DbiStreamBuilder();
DbiStreamBuilder(const DbiStreamBuilder &) = delete;
DbiStreamBuilder &operator=(const DbiStreamBuilder &) = delete;
@@ -55,13 +57,12 @@ public:
uint32_t calculateSerializedLength() const;
- Error addModuleInfo(StringRef ObjFile, StringRef Module);
+ Expected<ModInfoBuilder &> addModuleInfo(StringRef ModuleName);
Error addModuleSourceFile(StringRef Module, StringRef File);
Error finalizeMsfLayout();
- Error commit(const msf::MSFLayout &Layout,
- const msf::WritableStream &Buffer);
+ Error commit(const msf::MSFLayout &Layout, WritableBinaryStreamRef MsfBuffer);
// A helper function to create Section Contributions from COFF input
// section headers.
@@ -89,12 +90,6 @@ private:
Error generateModiSubstream();
Error generateFileInfoSubstream();
- struct ModuleInfo {
- std::vector<StringRef> SourceFiles;
- StringRef Obj;
- StringRef Mod;
- };
-
msf::MSFBuilder &Msf;
BumpPtrAllocator &Allocator;
@@ -108,14 +103,13 @@ private:
const DbiStreamHeader *Header;
- StringMap<std::unique_ptr<ModuleInfo>> ModuleInfos;
- std::vector<ModuleInfo *> ModuleInfoList;
+ StringMap<std::unique_ptr<ModInfoBuilder>> ModiMap;
+ std::vector<ModInfoBuilder *> ModiList;
StringMap<uint32_t> SourceFileNames;
- msf::WritableStreamRef NamesBuffer;
- msf::MutableByteStream ModInfoBuffer;
- msf::MutableByteStream FileInfoBuffer;
+ WritableBinaryStreamRef NamesBuffer;
+ MutableBinaryByteStream FileInfoBuffer;
ArrayRef<SectionContrib> SectionContribs;
ArrayRef<SecMapEntry> SectionMap;
llvm::SmallVector<DebugStream, (int)DbgHeaderType::Max> DbgStreams;
diff --git a/include/llvm/DebugInfo/PDB/Raw/EnumTables.h b/include/llvm/DebugInfo/PDB/Native/EnumTables.h
index c018445630fe..c018445630fe 100644
--- a/include/llvm/DebugInfo/PDB/Raw/EnumTables.h
+++ b/include/llvm/DebugInfo/PDB/Native/EnumTables.h
diff --git a/include/llvm/DebugInfo/PDB/Native/Formatters.h b/include/llvm/DebugInfo/PDB/Native/Formatters.h
new file mode 100644
index 000000000000..183f0ad8307e
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/Native/Formatters.h
@@ -0,0 +1,52 @@
+//===- Formatters.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_NATIVE_FORMATTERS_H
+#define LLVM_DEBUGINFO_PDB_NATIVE_FORMATTERS_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/DebugInfo/CodeView/Formatters.h"
+#include "llvm/DebugInfo/PDB/Native/RawConstants.h"
+#include "llvm/DebugInfo/PDB/Native/RawTypes.h"
+#include "llvm/Support/FormatProviders.h"
+
+#define FORMAT_CASE(Value, Name) \
+ case Value: \
+ Stream << Name; \
+ break;
+
+namespace llvm {
+template <> struct format_provider<pdb::PDB_UniqueId> {
+ static void format(const pdb::PDB_UniqueId &V, llvm::raw_ostream &Stream,
+ StringRef Style) {
+ codeview::fmt_guid(V.Guid).format(Stream, Style);
+ }
+};
+
+template <> struct format_provider<pdb::PdbRaw_ImplVer> {
+ static void format(const pdb::PdbRaw_ImplVer &V, llvm::raw_ostream &Stream,
+ StringRef Style) {
+ switch (V) {
+ FORMAT_CASE(pdb::PdbRaw_ImplVer::PdbImplVC110, "VC110")
+ FORMAT_CASE(pdb::PdbRaw_ImplVer::PdbImplVC140, "VC140")
+ FORMAT_CASE(pdb::PdbRaw_ImplVer::PdbImplVC2, "VC2")
+ FORMAT_CASE(pdb::PdbRaw_ImplVer::PdbImplVC4, "VC4")
+ FORMAT_CASE(pdb::PdbRaw_ImplVer::PdbImplVC41, "VC41")
+ FORMAT_CASE(pdb::PdbRaw_ImplVer::PdbImplVC50, "VC50")
+ FORMAT_CASE(pdb::PdbRaw_ImplVer::PdbImplVC70, "VC70")
+ FORMAT_CASE(pdb::PdbRaw_ImplVer::PdbImplVC70Dep, "VC70Dep")
+ FORMAT_CASE(pdb::PdbRaw_ImplVer::PdbImplVC80, "VC80")
+ FORMAT_CASE(pdb::PdbRaw_ImplVer::PdbImplVC98, "VC98")
+ }
+ }
+};
+}
+
+#endif
diff --git a/include/llvm/DebugInfo/PDB/Raw/GlobalsStream.h b/include/llvm/DebugInfo/PDB/Native/GlobalsStream.h
index 175f093cf53c..dcea3d3be0ab 100644
--- a/include/llvm/DebugInfo/PDB/Raw/GlobalsStream.h
+++ b/include/llvm/DebugInfo/PDB/Native/GlobalsStream.h
@@ -11,10 +11,10 @@
#define LLVM_DEBUGINFO_PDB_RAW_GLOBALS_STREAM_H
#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
-#include "llvm/DebugInfo/MSF/StreamArray.h"
+#include "llvm/DebugInfo/PDB/Native/RawConstants.h"
+#include "llvm/DebugInfo/PDB/Native/RawTypes.h"
#include "llvm/DebugInfo/PDB/PDBTypes.h"
-#include "llvm/DebugInfo/PDB/Raw/RawConstants.h"
-#include "llvm/DebugInfo/PDB/Raw/RawTypes.h"
+#include "llvm/Support/BinaryStreamArray.h"
#include "llvm/Support/Error.h"
namespace llvm {
@@ -27,15 +27,15 @@ public:
explicit GlobalsStream(std::unique_ptr<msf::MappedBlockStream> Stream);
~GlobalsStream();
Error commit();
- msf::FixedStreamArray<support::ulittle32_t> getHashBuckets() const {
+ FixedStreamArray<support::ulittle32_t> getHashBuckets() const {
return HashBuckets;
}
uint32_t getNumBuckets() const { return NumBuckets; }
Error reload();
private:
- msf::FixedStreamArray<support::ulittle32_t> HashBuckets;
- msf::FixedStreamArray<PSHashRecord> HashRecords;
+ FixedStreamArray<support::ulittle32_t> HashBuckets;
+ FixedStreamArray<PSHashRecord> HashRecords;
uint32_t NumBuckets;
std::unique_ptr<msf::MappedBlockStream> Stream;
};
diff --git a/include/llvm/DebugInfo/PDB/Raw/Hash.h b/include/llvm/DebugInfo/PDB/Native/Hash.h
index 0340554d7b0b..0340554d7b0b 100644
--- a/include/llvm/DebugInfo/PDB/Raw/Hash.h
+++ b/include/llvm/DebugInfo/PDB/Native/Hash.h
diff --git a/include/llvm/DebugInfo/PDB/Native/HashTable.h b/include/llvm/DebugInfo/PDB/Native/HashTable.h
new file mode 100644
index 000000000000..46eefa968e52
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/Native/HashTable.h
@@ -0,0 +1,106 @@
+//===- HashTable.h - PDB Hash Table -----------------------------*- 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_RAW_HASHTABLE_H
+#define LLVM_DEBUGINFO_PDB_RAW_HASHTABLE_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/SparseBitVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/iterator.h"
+#include "llvm/Support/BinaryStreamArray.h"
+#include "llvm/Support/BinaryStreamReader.h"
+#include "llvm/Support/BinaryStreamWriter.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/MathExtras.h"
+
+#include <cstdint>
+#include <utility>
+
+namespace llvm {
+namespace pdb {
+
+class HashTableIterator;
+
+class HashTable {
+ friend class HashTableIterator;
+ struct Header {
+ support::ulittle32_t Size;
+ support::ulittle32_t Capacity;
+ };
+
+ typedef std::vector<std::pair<uint32_t, uint32_t>> BucketList;
+
+public:
+ HashTable();
+ explicit HashTable(uint32_t Capacity);
+
+ Error load(BinaryStreamReader &Stream);
+
+ uint32_t calculateSerializedLength() const;
+ Error commit(BinaryStreamWriter &Writer) const;
+
+ void clear();
+
+ uint32_t capacity() const;
+ uint32_t size() const;
+
+ HashTableIterator begin() const;
+ HashTableIterator end() const;
+ HashTableIterator find(uint32_t K);
+
+ void set(uint32_t K, uint32_t V);
+ void remove(uint32_t K);
+ uint32_t get(uint32_t K);
+
+protected:
+ bool isPresent(uint32_t K) const { return Present.test(K); }
+ bool isDeleted(uint32_t K) const { return Deleted.test(K); }
+ BucketList Buckets;
+ mutable SparseBitVector<> Present;
+ mutable SparseBitVector<> Deleted;
+
+private:
+ static uint32_t maxLoad(uint32_t capacity);
+ void grow();
+
+ static Error readSparseBitVector(BinaryStreamReader &Stream,
+ SparseBitVector<> &V);
+ static Error writeSparseBitVector(BinaryStreamWriter &Writer,
+ SparseBitVector<> &Vec);
+};
+
+class HashTableIterator
+ : public iterator_facade_base<HashTableIterator, std::forward_iterator_tag,
+ std::pair<uint32_t, uint32_t>> {
+ friend class HashTable;
+ HashTableIterator(const HashTable &Map, uint32_t Index, bool IsEnd);
+
+public:
+ HashTableIterator(const HashTable &Map);
+
+ HashTableIterator &operator=(const HashTableIterator &R);
+ bool operator==(const HashTableIterator &R) const;
+ const std::pair<uint32_t, uint32_t> &operator*() const;
+ HashTableIterator &operator++();
+
+private:
+ bool isEnd() const { return IsEnd; }
+ uint32_t index() const { return Index; }
+
+ const HashTable *Map;
+ uint32_t Index;
+ bool IsEnd;
+};
+
+} // end namespace pdb
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_PDB_RAW_HASHTABLE_H
diff --git a/include/llvm/DebugInfo/PDB/Raw/ISectionContribVisitor.h b/include/llvm/DebugInfo/PDB/Native/ISectionContribVisitor.h
index fb00d6ad4bc7..fb00d6ad4bc7 100644
--- a/include/llvm/DebugInfo/PDB/Raw/ISectionContribVisitor.h
+++ b/include/llvm/DebugInfo/PDB/Native/ISectionContribVisitor.h
diff --git a/include/llvm/DebugInfo/PDB/Raw/InfoStream.h b/include/llvm/DebugInfo/PDB/Native/InfoStream.h
index 6b8b94ff1a36..1c38c2b6194f 100644
--- a/include/llvm/DebugInfo/PDB/Raw/InfoStream.h
+++ b/include/llvm/DebugInfo/PDB/Native/InfoStream.h
@@ -10,11 +10,12 @@
#ifndef LLVM_DEBUGINFO_PDB_RAW_PDBINFOSTREAM_H
#define LLVM_DEBUGINFO_PDB_RAW_PDBINFOSTREAM_H
+#include "llvm/ADT/BitmaskEnum.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
+#include "llvm/DebugInfo/PDB/Native/NamedStreamMap.h"
+#include "llvm/DebugInfo/PDB/Native/RawConstants.h"
#include "llvm/DebugInfo/PDB/PDBTypes.h"
-#include "llvm/DebugInfo/PDB/Raw/NameMap.h"
-#include "llvm/DebugInfo/PDB/Raw/RawConstants.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/Error.h"
@@ -32,10 +33,18 @@ public:
Error reload();
+ uint32_t getStreamSize() const;
+
PdbRaw_ImplVer getVersion() const;
uint32_t getSignature() const;
uint32_t getAge() const;
PDB_UniqueId getGuid() const;
+ uint32_t getNamedStreamMapByteSize() const;
+
+ PdbRaw_Features getFeatures() const;
+ ArrayRef<PdbRaw_FeatureSig> getFeatureSignatures() const;
+
+ const NamedStreamMap &getNamedStreams() const;
uint32_t getNamedStreamIndex(llvm::StringRef Name) const;
iterator_range<StringMapConstIterator<uint32_t>> named_streams() const;
@@ -61,7 +70,12 @@ private:
// universally unique.
PDB_UniqueId Guid;
- NameMap NamedStreams;
+ std::vector<PdbRaw_FeatureSig> FeatureSignatures;
+ PdbRaw_Features Features = PdbFeatureNone;
+
+ uint32_t NamedStreamMapByteSize = 0;
+
+ NamedStreamMap NamedStreams;
};
}
}
diff --git a/include/llvm/DebugInfo/PDB/Raw/InfoStreamBuilder.h b/include/llvm/DebugInfo/PDB/Native/InfoStreamBuilder.h
index cb60b1eb69bd..90c28a90d252 100644
--- a/include/llvm/DebugInfo/PDB/Raw/InfoStreamBuilder.h
+++ b/include/llvm/DebugInfo/PDB/Native/InfoStreamBuilder.h
@@ -13,22 +13,24 @@
#include "llvm/ADT/Optional.h"
#include "llvm/Support/Error.h"
+#include "llvm/DebugInfo/PDB/Native/NamedStreamMap.h"
+#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
+#include "llvm/DebugInfo/PDB/Native/RawConstants.h"
#include "llvm/DebugInfo/PDB/PDBTypes.h"
-#include "llvm/DebugInfo/PDB/Raw/NameMapBuilder.h"
-#include "llvm/DebugInfo/PDB/Raw/PDBFile.h"
-#include "llvm/DebugInfo/PDB/Raw/RawConstants.h"
namespace llvm {
+class WritableBinaryStreamRef;
+
namespace msf {
class MSFBuilder;
-class StreamWriter;
}
namespace pdb {
class PDBFile;
+class NamedStreamMap;
class InfoStreamBuilder {
public:
- InfoStreamBuilder(msf::MSFBuilder &Msf);
+ InfoStreamBuilder(msf::MSFBuilder &Msf, NamedStreamMap &NamedStreams);
InfoStreamBuilder(const InfoStreamBuilder &) = delete;
InfoStreamBuilder &operator=(const InfoStreamBuilder &) = delete;
@@ -36,25 +38,25 @@ public:
void setSignature(uint32_t S);
void setAge(uint32_t A);
void setGuid(PDB_UniqueId G);
+ void addFeature(PdbRaw_FeatureSig Sig);
- NameMapBuilder &getNamedStreamsBuilder();
-
- uint32_t calculateSerializedLength() const;
+ uint32_t finalize();
Error finalizeMsfLayout();
Error commit(const msf::MSFLayout &Layout,
- const msf::WritableStream &Buffer) const;
+ WritableBinaryStreamRef Buffer) const;
private:
msf::MSFBuilder &Msf;
+ std::vector<PdbRaw_FeatureSig> Features;
PdbRaw_ImplVer Ver;
uint32_t Sig;
uint32_t Age;
PDB_UniqueId Guid;
- NameMapBuilder NamedStreams;
+ NamedStreamMap &NamedStreams;
};
}
}
diff --git a/include/llvm/DebugInfo/PDB/Raw/ModInfo.h b/include/llvm/DebugInfo/PDB/Native/ModInfo.h
index bf5cf53b3313..d26d0d618449 100644
--- a/include/llvm/DebugInfo/PDB/Raw/ModInfo.h
+++ b/include/llvm/DebugInfo/PDB/Native/ModInfo.h
@@ -11,9 +11,9 @@
#define LLVM_DEBUGINFO_PDB_RAW_MODINFO_H
#include "llvm/ADT/StringRef.h"
-#include "llvm/DebugInfo/MSF/StreamArray.h"
-#include "llvm/DebugInfo/MSF/StreamRef.h"
-#include "llvm/DebugInfo/PDB/Raw/RawTypes.h"
+#include "llvm/DebugInfo/PDB/Native/RawTypes.h"
+#include "llvm/Support/BinaryStreamArray.h"
+#include "llvm/Support/BinaryStreamRef.h"
#include "llvm/Support/Error.h"
#include <cstdint>
#include <vector>
@@ -30,7 +30,7 @@ public:
ModInfo(const ModInfo &Info);
~ModInfo();
- static Error initialize(msf::ReadableStreamRef Stream, ModInfo &Info);
+ static Error initialize(BinaryStreamRef Stream, ModInfo &Info);
bool hasECInfo() const;
uint16_t getTypeServerIndex() const;
@@ -63,10 +63,8 @@ struct ModuleInfoEx {
} // end namespace pdb
-namespace msf {
-
template <> struct VarStreamArrayExtractor<pdb::ModInfo> {
- Error operator()(ReadableStreamRef Stream, uint32_t &Length,
+ Error operator()(BinaryStreamRef Stream, uint32_t &Length,
pdb::ModInfo &Info) const {
if (auto EC = pdb::ModInfo::initialize(Stream, Info))
return EC;
@@ -75,8 +73,6 @@ template <> struct VarStreamArrayExtractor<pdb::ModInfo> {
}
};
-} // end namespace msf
-
} // end namespace llvm
#endif // LLVM_DEBUGINFO_PDB_RAW_MODINFO_H
diff --git a/include/llvm/DebugInfo/PDB/Native/ModInfoBuilder.h b/include/llvm/DebugInfo/PDB/Native/ModInfoBuilder.h
new file mode 100644
index 000000000000..605fd2483c3b
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/Native/ModInfoBuilder.h
@@ -0,0 +1,74 @@
+//===- ModInfoBuilder.h - PDB module 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_RAW_MODINFOBUILDER_H
+#define LLVM_DEBUGINFO_PDB_RAW_MODINFOBUILDER_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
+#include "llvm/DebugInfo/PDB/Native/RawTypes.h"
+#include "llvm/Support/Error.h"
+#include <cstdint>
+#include <string>
+#include <vector>
+
+namespace llvm {
+class BinaryStreamWriter;
+
+namespace msf {
+class MSFBuilder;
+struct MSFLayout;
+}
+namespace pdb {
+
+class ModInfoBuilder {
+ friend class DbiStreamBuilder;
+
+public:
+ ModInfoBuilder(StringRef ModuleName, uint32_t ModIndex, msf::MSFBuilder &Msf);
+
+ ModInfoBuilder(const ModInfoBuilder &) = delete;
+ ModInfoBuilder &operator=(const ModInfoBuilder &) = delete;
+
+ void setObjFileName(StringRef Name);
+ void addSymbol(codeview::CVSymbol Symbol);
+
+ uint16_t getStreamIndex() const;
+ StringRef getModuleName() const { return ModuleName; }
+ StringRef getObjFileName() const { return ObjFileName; }
+
+ ArrayRef<std::string> source_files() const {
+ return makeArrayRef(SourceFiles);
+ }
+
+ uint32_t calculateSerializedLength() const;
+
+ void finalize();
+ Error finalizeMsfLayout();
+
+ Error commit(BinaryStreamWriter &ModiWriter, const msf::MSFLayout &MsfLayout,
+ WritableBinaryStreamRef MsfBuffer);
+
+private:
+ void addSourceFile(StringRef Path);
+ msf::MSFBuilder &MSF;
+
+ uint32_t SymbolByteSize = 0;
+ std::string ModuleName;
+ std::string ObjFileName;
+ std::vector<std::string> SourceFiles;
+ std::vector<codeview::CVSymbol> Symbols;
+ ModuleInfoHeader Layout;
+};
+
+} // end namespace pdb
+
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_PDB_RAW_MODINFOBUILDER_H
diff --git a/include/llvm/DebugInfo/PDB/Raw/ModStream.h b/include/llvm/DebugInfo/PDB/Native/ModStream.h
index d5e7a6830d8d..d65e195dbb95 100644
--- a/include/llvm/DebugInfo/PDB/Raw/ModStream.h
+++ b/include/llvm/DebugInfo/PDB/Native/ModStream.h
@@ -15,8 +15,8 @@
#include "llvm/DebugInfo/CodeView/ModuleSubstream.h"
#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
-#include "llvm/DebugInfo/MSF/StreamArray.h"
-#include "llvm/DebugInfo/MSF/StreamRef.h"
+#include "llvm/Support/BinaryStreamArray.h"
+#include "llvm/Support/BinaryStreamRef.h"
#include "llvm/Support/Error.h"
namespace llvm {
@@ -50,9 +50,9 @@ private:
std::unique_ptr<msf::MappedBlockStream> Stream;
codeview::CVSymbolArray SymbolsSubstream;
- msf::ReadableStreamRef LinesSubstream;
- msf::ReadableStreamRef C13LinesSubstream;
- msf::ReadableStreamRef GlobalRefsSubstream;
+ BinaryStreamRef LinesSubstream;
+ BinaryStreamRef C13LinesSubstream;
+ BinaryStreamRef GlobalRefsSubstream;
codeview::ModuleSubstreamArray LineInfo;
};
diff --git a/include/llvm/DebugInfo/PDB/Native/NamedStreamMap.h b/include/llvm/DebugInfo/PDB/Native/NamedStreamMap.h
new file mode 100644
index 000000000000..d4206503e7dc
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/Native/NamedStreamMap.h
@@ -0,0 +1,55 @@
+//===- NamedStreamMap.h - PDB Named Stream Map ------------------*- 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_RAW_PDBNAMEDSTREAMMAP_H
+#define LLVM_DEBUGINFO_PDB_RAW_PDBNAMEDSTREAMMAP_H
+
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/DebugInfo/PDB/Native/HashTable.h"
+#include "llvm/Support/Error.h"
+#include <cstdint>
+
+namespace llvm {
+class BinaryStreamReader;
+class BinaryStreamWriter;
+
+namespace pdb {
+class NamedStreamMapBuilder;
+class NamedStreamMap {
+ struct FinalizationInfo {
+ uint32_t StringDataBytes = 0;
+ uint32_t SerializedLength = 0;
+ };
+ friend NamedStreamMapBuilder;
+
+public:
+ NamedStreamMap();
+
+ Error load(BinaryStreamReader &Stream);
+ Error commit(BinaryStreamWriter &Writer) const;
+ uint32_t finalize();
+
+ uint32_t size() const;
+ bool get(StringRef Stream, uint32_t &StreamNo) const;
+ void set(StringRef Stream, uint32_t StreamNo);
+ void remove(StringRef Stream);
+
+ iterator_range<StringMapConstIterator<uint32_t>> entries() const;
+
+private:
+ Optional<FinalizationInfo> FinalizedInfo;
+ HashTable FinalizedHashTable;
+ StringMap<uint32_t> Mapping;
+};
+
+} // end namespace pdb
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_PDB_RAW_PDBNAMEDSTREAMMAP_H
diff --git a/include/llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h b/include/llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h
new file mode 100644
index 000000000000..8eeaf3e0ea49
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h
@@ -0,0 +1,35 @@
+//===- NativeCompilandSymbol.h - native impl for compiland syms -*- 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_NATIVE_NATIVECOMPILANDSYMBOL_H
+#define LLVM_DEBUGINFO_PDB_NATIVE_NATIVECOMPILANDSYMBOL_H
+
+#include "llvm/DebugInfo/PDB/Native/ModInfo.h"
+#include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h"
+
+namespace llvm {
+namespace pdb {
+
+class NativeCompilandSymbol : public NativeRawSymbol {
+public:
+ NativeCompilandSymbol(NativeSession &Session, const ModuleInfoEx &MI);
+ PDB_SymType getSymTag() const override;
+ bool isEditAndContinueEnabled() const override;
+ uint32_t getLexicalParentId() const override;
+ std::string getLibraryName() const override;
+ std::string getName() const override;
+
+private:
+ ModuleInfoEx Module;
+};
+
+} // namespace pdb
+} // namespace llvm
+
+#endif
diff --git a/include/llvm/DebugInfo/PDB/Native/NativeEnumModules.h b/include/llvm/DebugInfo/PDB/Native/NativeEnumModules.h
new file mode 100644
index 000000000000..60a55ee50cc4
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/Native/NativeEnumModules.h
@@ -0,0 +1,41 @@
+//==- NativeEnumModules.h - Native Module 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_NATIVE_NATIVEENUMMODULES_H
+#define LLVM_DEBUGINFO_PDB_NATIVE_NATIVEENUMMODULES_H
+
+#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
+#include "llvm/DebugInfo/PDB/Native/ModInfo.h"
+#include "llvm/DebugInfo/PDB/PDBSymbol.h"
+namespace llvm {
+namespace pdb {
+
+class NativeSession;
+
+class NativeEnumModules : public IPDBEnumChildren<PDBSymbol> {
+public:
+ explicit NativeEnumModules(NativeSession &Session,
+ ArrayRef<ModuleInfoEx> Modules,
+ uint32_t Index = 0);
+
+ uint32_t getChildCount() const override;
+ std::unique_ptr<PDBSymbol> getChildAtIndex(uint32_t Index) const override;
+ std::unique_ptr<PDBSymbol> getNext() override;
+ void reset() override;
+ NativeEnumModules *clone() const override;
+
+private:
+ NativeSession &Session;
+ ArrayRef<ModuleInfoEx> Modules;
+ uint32_t Index;
+};
+}
+}
+
+#endif
diff --git a/include/llvm/DebugInfo/PDB/Native/NativeExeSymbol.h b/include/llvm/DebugInfo/PDB/Native/NativeExeSymbol.h
new file mode 100644
index 000000000000..9516810539b6
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/Native/NativeExeSymbol.h
@@ -0,0 +1,39 @@
+//===- NativeExeSymbol.h - native impl for PDBSymbolExe ---------*- 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_NATIVE_NATIVEEXESYMBOL_H
+#define LLVM_DEBUGINFO_PDB_NATIVE_NATIVEEXESYMBOL_H
+
+#include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h"
+#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
+
+namespace llvm {
+namespace pdb {
+
+class NativeExeSymbol : public NativeRawSymbol {
+public:
+ NativeExeSymbol(NativeSession &Session);
+
+ std::unique_ptr<IPDBEnumSymbols>
+ findChildren(PDB_SymType Type) const override;
+
+ uint32_t getAge() const override;
+ std::string getSymbolsFileName() const override;
+ PDB_UniqueId getGuid() const override;
+ bool hasCTypes() const override;
+ bool hasPrivateSymbols() const override;
+
+private:
+ PDBFile &File;
+};
+
+} // namespace pdb
+} // namespace llvm
+
+#endif
diff --git a/include/llvm/DebugInfo/PDB/Native/NativeRawSymbol.h b/include/llvm/DebugInfo/PDB/Native/NativeRawSymbol.h
new file mode 100644
index 000000000000..cffb5d09d225
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/Native/NativeRawSymbol.h
@@ -0,0 +1,208 @@
+//===- NativeRawSymbol.h - Native 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_NATIVE_NATIVERAWSYMBOL_H
+#define LLVM_DEBUGINFO_PDB_NATIVE_NATIVERAWSYMBOL_H
+
+#include "llvm/DebugInfo/PDB/IPDBRawSymbol.h"
+
+namespace llvm {
+namespace pdb {
+
+class NativeSession;
+
+class NativeRawSymbol : public IPDBRawSymbol {
+public:
+ explicit NativeRawSymbol(NativeSession &PDBSession);
+
+ void dump(raw_ostream &OS, int Indent) const override;
+
+ 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;
+ codeview::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;
+ codeview::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;
+ std::unique_ptr<PDBSymbolTypeVTable> getVirtualBaseTableType() 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;
+ codeview::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;
+
+protected:
+ NativeSession &Session;
+};
+
+}
+}
+
+#endif
diff --git a/include/llvm/DebugInfo/PDB/Raw/RawSession.h b/include/llvm/DebugInfo/PDB/Native/NativeSession.h
index 5a6c469fcc8e..e6da266f796d 100644
--- a/include/llvm/DebugInfo/PDB/Raw/RawSession.h
+++ b/include/llvm/DebugInfo/PDB/Native/NativeSession.h
@@ -1,4 +1,4 @@
-//===- RawSession.h - Native implementation of IPDBSession ------*- C++ -*-===//
+//===- NativeSession.h - Native implementation of IPDBSession ---*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -19,11 +19,11 @@ namespace llvm {
namespace pdb {
class PDBFile;
-class RawSession : public IPDBSession {
+class NativeSession : public IPDBSession {
public:
- RawSession(std::unique_ptr<PDBFile> PdbFile,
- std::unique_ptr<BumpPtrAllocator> Allocator);
- ~RawSession() override;
+ NativeSession(std::unique_ptr<PDBFile> PdbFile,
+ std::unique_ptr<BumpPtrAllocator> Allocator);
+ ~NativeSession() override;
static Error createFromPdb(StringRef Path,
std::unique_ptr<IPDBSession> &Session);
diff --git a/include/llvm/DebugInfo/PDB/Raw/PDBFile.h b/include/llvm/DebugInfo/PDB/Native/PDBFile.h
index 29f5b2163d83..fbca62d6e9d9 100644
--- a/include/llvm/DebugInfo/PDB/Raw/PDBFile.h
+++ b/include/llvm/DebugInfo/PDB/Native/PDBFile.h
@@ -13,9 +13,8 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/DebugInfo/MSF/IMSFFile.h"
#include "llvm/DebugInfo/MSF/MSFCommon.h"
-#include "llvm/DebugInfo/MSF/StreamArray.h"
-#include "llvm/DebugInfo/MSF/StreamInterface.h"
#include "llvm/Support/Allocator.h"
+#include "llvm/Support/BinaryStreamRef.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/MathExtras.h"
@@ -24,6 +23,8 @@
namespace llvm {
+class BinaryStream;
+
namespace msf {
class MappedBlockStream;
}
@@ -32,7 +33,7 @@ namespace pdb {
class DbiStream;
class GlobalsStream;
class InfoStream;
-class NameHashTable;
+class StringTable;
class PDBFileBuilder;
class PublicsStream;
class SymbolStream;
@@ -42,10 +43,13 @@ class PDBFile : public msf::IMSFFile {
friend PDBFileBuilder;
public:
- PDBFile(std::unique_ptr<msf::ReadableStream> PdbFileBuffer,
+ PDBFile(StringRef Path, std::unique_ptr<BinaryStream> PdbFileBuffer,
BumpPtrAllocator &Allocator);
~PDBFile() override;
+ StringRef getFileDirectory() const;
+ StringRef getFilePath() const;
+
uint32_t getFreeBlockMapBlock() const;
uint32_t getUnknown1() const;
@@ -77,7 +81,7 @@ public:
}
const msf::MSFLayout &getMsfLayout() const { return ContainerLayout; }
- const msf::ReadableStream &getMsfBuffer() const { return *Buffer; }
+ BinaryStreamRef getMsfBuffer() const { return *Buffer; }
ArrayRef<support::ulittle32_t> getDirectoryBlockArray() const;
@@ -91,7 +95,7 @@ public:
Expected<TpiStream &> getPDBIpiStream();
Expected<PublicsStream &> getPDBPublicsStream();
Expected<SymbolStream &> getPDBSymbolStream();
- Expected<NameHashTable &> getStringTable();
+ Expected<StringTable &> getStringTable();
BumpPtrAllocator &getAllocator() { return Allocator; }
@@ -104,14 +108,16 @@ public:
bool hasPDBTpiStream() const;
bool hasStringTable();
- private:
- Expected<std::unique_ptr<msf::MappedBlockStream>> safelyCreateIndexedStream(
- const msf::MSFLayout &Layout, const msf::ReadableStream &MsfData,
- uint32_t StreamIndex) const;
+private:
+ Expected<std::unique_ptr<msf::MappedBlockStream>>
+ safelyCreateIndexedStream(const msf::MSFLayout &Layout,
+ BinaryStreamRef MsfData,
+ uint32_t StreamIndex) const;
+ std::string FilePath;
BumpPtrAllocator &Allocator;
- std::unique_ptr<msf::ReadableStream> Buffer;
+ std::unique_ptr<BinaryStream> Buffer;
std::vector<uint32_t> FpmPages;
msf::MSFLayout ContainerLayout;
@@ -125,7 +131,7 @@ public:
std::unique_ptr<SymbolStream> Symbols;
std::unique_ptr<msf::MappedBlockStream> DirectoryStream;
std::unique_ptr<msf::MappedBlockStream> StringTableStream;
- std::unique_ptr<NameHashTable> StringTable;
+ std::unique_ptr<StringTable> Strings;
};
}
}
diff --git a/include/llvm/DebugInfo/PDB/Raw/PDBFileBuilder.h b/include/llvm/DebugInfo/PDB/Native/PDBFileBuilder.h
index 27fc4b53b649..3898af5afc9e 100644
--- a/include/llvm/DebugInfo/PDB/Raw/PDBFileBuilder.h
+++ b/include/llvm/DebugInfo/PDB/Native/PDBFileBuilder.h
@@ -13,8 +13,10 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/Optional.h"
-#include "llvm/DebugInfo/PDB/Raw/PDBFile.h"
-#include "llvm/DebugInfo/PDB/Raw/RawConstants.h"
+#include "llvm/DebugInfo/PDB/Native/NamedStreamMap.h"
+#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
+#include "llvm/DebugInfo/PDB/Native/RawConstants.h"
+#include "llvm/DebugInfo/PDB/Native/StringTableBuilder.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/Error.h"
@@ -44,11 +46,13 @@ public:
DbiStreamBuilder &getDbiBuilder();
TpiStreamBuilder &getTpiBuilder();
TpiStreamBuilder &getIpiBuilder();
+ StringTableBuilder &getStringTableBuilder();
Error commit(StringRef Filename);
private:
- Expected<msf::MSFLayout> finalizeMsfLayout() const;
+ Error addNamedStream(StringRef Name, uint32_t Size);
+ Expected<msf::MSFLayout> finalizeMsfLayout();
BumpPtrAllocator &Allocator;
@@ -57,6 +61,9 @@ private:
std::unique_ptr<DbiStreamBuilder> Dbi;
std::unique_ptr<TpiStreamBuilder> Tpi;
std::unique_ptr<TpiStreamBuilder> Ipi;
+
+ StringTableBuilder Strings;
+ NamedStreamMap NamedStreams;
};
}
}
diff --git a/include/llvm/DebugInfo/PDB/Native/PDBTypeServerHandler.h b/include/llvm/DebugInfo/PDB/Native/PDBTypeServerHandler.h
new file mode 100644
index 000000000000..d965e1008e95
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/Native/PDBTypeServerHandler.h
@@ -0,0 +1,48 @@
+//===- PDBTypeServerHandler.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_PDBTYPESERVERHANDLER_H
+#define LLVM_DEBUGINFO_PDB_PDBTYPESERVERHANDLER_H
+
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
+#include "llvm/DebugInfo/CodeView/TypeRecord.h"
+#include "llvm/DebugInfo/CodeView/TypeServerHandler.h"
+#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
+#include "llvm/DebugInfo/PDB/PDBTypes.h"
+
+#include <memory>
+#include <string>
+
+namespace llvm {
+namespace pdb {
+class NativeSession;
+
+class PDBTypeServerHandler : public codeview::TypeServerHandler {
+public:
+ PDBTypeServerHandler(bool RevisitAlways = false);
+
+ void addSearchPath(StringRef Path);
+ Expected<bool> handle(codeview::TypeServer2Record &TS,
+ codeview::TypeVisitorCallbacks &Callbacks) override;
+
+private:
+ Expected<bool> handleInternal(PDBFile &File,
+ codeview::TypeVisitorCallbacks &Callbacks);
+
+ bool RevisitAlways;
+ std::unique_ptr<NativeSession> Session;
+ SmallVector<SmallString<64>, 4> SearchPaths;
+};
+}
+}
+
+#endif
diff --git a/include/llvm/DebugInfo/PDB/Raw/PublicsStream.h b/include/llvm/DebugInfo/PDB/Native/PublicsStream.h
index 577f2986ff24..4a541edd6a7b 100644
--- a/include/llvm/DebugInfo/PDB/Raw/PublicsStream.h
+++ b/include/llvm/DebugInfo/PDB/Native/PublicsStream.h
@@ -12,11 +12,10 @@
#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
-#include "llvm/DebugInfo/MSF/StreamArray.h"
+#include "llvm/DebugInfo/PDB/Native/RawConstants.h"
+#include "llvm/DebugInfo/PDB/Native/RawTypes.h"
#include "llvm/DebugInfo/PDB/PDBTypes.h"
-#include "llvm/DebugInfo/PDB/Raw/RawConstants.h"
-#include "llvm/DebugInfo/PDB/Raw/RawTypes.h"
-
+#include "llvm/Support/BinaryStreamArray.h"
#include "llvm/Support/Error.h"
namespace llvm {
@@ -38,16 +37,16 @@ public:
uint32_t getNumBuckets() const { return NumBuckets; }
iterator_range<codeview::CVSymbolArray::Iterator>
getSymbols(bool *HadError) const;
- msf::FixedStreamArray<support::ulittle32_t> getHashBuckets() const {
+ FixedStreamArray<support::ulittle32_t> getHashBuckets() const {
return HashBuckets;
}
- msf::FixedStreamArray<support::ulittle32_t> getAddressMap() const {
+ FixedStreamArray<support::ulittle32_t> getAddressMap() const {
return AddressMap;
}
- msf::FixedStreamArray<support::ulittle32_t> getThunkMap() const {
+ FixedStreamArray<support::ulittle32_t> getThunkMap() const {
return ThunkMap;
}
- msf::FixedStreamArray<SectionOffset> getSectionOffsets() const {
+ FixedStreamArray<SectionOffset> getSectionOffsets() const {
return SectionOffsets;
}
@@ -59,11 +58,11 @@ private:
std::unique_ptr<msf::MappedBlockStream> Stream;
uint32_t NumBuckets = 0;
ArrayRef<uint8_t> Bitmap;
- msf::FixedStreamArray<PSHashRecord> HashRecords;
- msf::FixedStreamArray<support::ulittle32_t> HashBuckets;
- msf::FixedStreamArray<support::ulittle32_t> AddressMap;
- msf::FixedStreamArray<support::ulittle32_t> ThunkMap;
- msf::FixedStreamArray<SectionOffset> SectionOffsets;
+ FixedStreamArray<PSHashRecord> HashRecords;
+ FixedStreamArray<support::ulittle32_t> HashBuckets;
+ FixedStreamArray<support::ulittle32_t> AddressMap;
+ FixedStreamArray<support::ulittle32_t> ThunkMap;
+ FixedStreamArray<SectionOffset> SectionOffsets;
const HeaderInfo *Header;
const GSIHashHeader *HashHdr;
diff --git a/include/llvm/DebugInfo/PDB/Raw/RawConstants.h b/include/llvm/DebugInfo/PDB/Native/RawConstants.h
index af114ff52491..f5d4df8feb2e 100644
--- a/include/llvm/DebugInfo/PDB/Raw/RawConstants.h
+++ b/include/llvm/DebugInfo/PDB/Native/RawConstants.h
@@ -10,6 +10,7 @@
#ifndef LLVM_DEBUGINFO_PDB_RAW_PDBRAWCONSTANTS_H
#define LLVM_DEBUGINFO_PDB_RAW_PDBRAWCONSTANTS_H
+#include "llvm/ADT/BitmaskEnum.h"
#include "llvm/DebugInfo/CodeView/CodeView.h"
#include <cstdint>
@@ -32,6 +33,21 @@ enum PdbRaw_ImplVer : uint32_t {
PdbImplVC140 = 20140508,
};
+enum class PdbRaw_FeatureSig : uint32_t {
+ VC110 = PdbImplVC110,
+ VC140 = PdbImplVC140,
+ NoTypeMerge = 0x4D544F4E,
+ MinimalDebugInfo = 0x494E494D,
+};
+
+enum PdbRaw_Features : uint32_t {
+ PdbFeatureNone = 0x0,
+ PdbFeatureContainsIdStream = 0x1,
+ PdbFeatureMinimalDebugInfo = 0x2,
+ PdbFeatureNoTypeMerging = 0x4,
+ LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ PdbFeatureNoTypeMerging)
+};
+
enum PdbRaw_DbiVer : uint32_t {
PdbDbiVC41 = 930803,
PdbDbiV50 = 19960307,
diff --git a/include/llvm/DebugInfo/PDB/Raw/RawError.h b/include/llvm/DebugInfo/PDB/Native/RawError.h
index f96b8066bbe5..3624a7682e38 100644
--- a/include/llvm/DebugInfo/PDB/Raw/RawError.h
+++ b/include/llvm/DebugInfo/PDB/Native/RawError.h
@@ -28,6 +28,7 @@ enum class raw_error_code {
duplicate_entry,
no_entry,
not_writable,
+ stream_too_long,
invalid_tpi_hash,
};
diff --git a/include/llvm/DebugInfo/PDB/Raw/RawTypes.h b/include/llvm/DebugInfo/PDB/Native/RawTypes.h
index d404b3994dbc..1b2631efce70 100644
--- a/include/llvm/DebugInfo/PDB/Raw/RawTypes.h
+++ b/include/llvm/DebugInfo/PDB/Native/RawTypes.h
@@ -266,6 +266,10 @@ struct PDB_UniqueId {
uint8_t Guid[16];
};
+inline bool operator==(const PDB_UniqueId &LHS, const PDB_UniqueId &RHS) {
+ return 0 == ::memcmp(LHS.Guid, RHS.Guid, sizeof(LHS.Guid));
+}
+
// The header preceeding the global TPI stream.
// This corresponds to `HDR` in PDB/dbi/tpi.h.
struct TpiStreamHeader {
@@ -302,6 +306,15 @@ struct InfoStreamHeader {
PDB_UniqueId Guid;
};
+/// The header preceeding the /names stream.
+struct StringTableHeader {
+ support::ulittle32_t Signature;
+ support::ulittle32_t HashVersion;
+ support::ulittle32_t ByteSize;
+};
+
+const uint32_t StringTableSignature = 0xEFFEEFFE;
+
} // namespace pdb
} // namespace llvm
diff --git a/include/llvm/DebugInfo/PDB/Raw/NameHashTable.h b/include/llvm/DebugInfo/PDB/Native/StringTable.h
index 00d022d4d8e2..dd5e30e61827 100644
--- a/include/llvm/DebugInfo/PDB/Raw/NameHashTable.h
+++ b/include/llvm/DebugInfo/PDB/Native/StringTable.h
@@ -1,4 +1,4 @@
-//===- NameHashTable.h - PDB Name Hash Table --------------------*- C++ -*-===//
+//===- StringTable.h - PDB String Table -------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,29 +7,30 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_DEBUGINFO_PDB_RAW_NAMEHASHTABLE_H
-#define LLVM_DEBUGINFO_PDB_RAW_NAMEHASHTABLE_H
+#ifndef LLVM_DEBUGINFO_PDB_RAW_STRINGTABLE_H
+#define LLVM_DEBUGINFO_PDB_RAW_STRINGTABLE_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
-#include "llvm/DebugInfo/MSF/StreamArray.h"
-#include "llvm/DebugInfo/MSF/StreamRef.h"
+#include "llvm/Support/BinaryStreamArray.h"
+#include "llvm/Support/BinaryStreamRef.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/Error.h"
#include <cstdint>
#include <vector>
namespace llvm {
-namespace msf {
-class StreamReader;
-}
+class BinaryStreamReader;
+
namespace pdb {
-class NameHashTable {
+class StringTable {
public:
- NameHashTable();
+ StringTable();
+
+ Error load(BinaryStreamReader &Stream);
- Error load(msf::StreamReader &Stream);
+ uint32_t getByteSize() const;
uint32_t getNameCount() const { return NameCount; }
uint32_t getHashVersion() const { return HashVersion; }
@@ -38,17 +39,18 @@ public:
StringRef getStringForID(uint32_t ID) const;
uint32_t getIDForString(StringRef Str) const;
- msf::FixedStreamArray<support::ulittle32_t> name_ids() const;
+ FixedStreamArray<support::ulittle32_t> name_ids() const;
private:
- msf::ReadableStreamRef NamesBuffer;
- msf::FixedStreamArray<support::ulittle32_t> IDs;
- uint32_t Signature;
- uint32_t HashVersion;
- uint32_t NameCount;
+ BinaryStreamRef NamesBuffer;
+ FixedStreamArray<support::ulittle32_t> IDs;
+ uint32_t ByteSize = 0;
+ uint32_t Signature = 0;
+ uint32_t HashVersion = 0;
+ uint32_t NameCount = 0;
};
} // end namespace pdb
} // end namespace llvm
-#endif // LLVM_DEBUGINFO_PDB_RAW_NAMEHASHTABLE_H
+#endif // LLVM_DEBUGINFO_PDB_RAW_STRINGTABLE_H
diff --git a/include/llvm/DebugInfo/PDB/Native/StringTableBuilder.h b/include/llvm/DebugInfo/PDB/Native/StringTableBuilder.h
new file mode 100644
index 000000000000..dd0f40b1978d
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/Native/StringTableBuilder.h
@@ -0,0 +1,44 @@
+//===- StringTableBuilder.h - PDB String Table Builder ----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file creates the "/names" stream.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_RAW_STRINGTABLEBUILDER_H
+#define LLVM_DEBUGINFO_PDB_RAW_STRINGTABLEBUILDER_H
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Error.h"
+#include <vector>
+
+namespace llvm {
+class BinaryStreamWriter;
+
+namespace pdb {
+
+class StringTableBuilder {
+public:
+ // If string S does not exist in the string table, insert it.
+ // Returns the ID for S.
+ uint32_t insert(StringRef S);
+
+ uint32_t finalize();
+ Error commit(BinaryStreamWriter &Writer) const;
+
+private:
+ DenseMap<StringRef, uint32_t> Strings;
+ uint32_t StringSize = 1;
+};
+
+} // end namespace pdb
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_PDB_RAW_STRINGTABLEBUILDER_H
diff --git a/include/llvm/DebugInfo/PDB/Raw/SymbolStream.h b/include/llvm/DebugInfo/PDB/Native/SymbolStream.h
index 41d5e6ad64a0..41d5e6ad64a0 100644
--- a/include/llvm/DebugInfo/PDB/Raw/SymbolStream.h
+++ b/include/llvm/DebugInfo/PDB/Native/SymbolStream.h
diff --git a/include/llvm/DebugInfo/PDB/Raw/TpiHashing.h b/include/llvm/DebugInfo/PDB/Native/TpiHashing.h
index 67a4952fcdfe..dd2698c354a2 100644
--- a/include/llvm/DebugInfo/PDB/Raw/TpiHashing.h
+++ b/include/llvm/DebugInfo/PDB/Native/TpiHashing.h
@@ -15,8 +15,8 @@
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
-#include "llvm/DebugInfo/MSF/StreamArray.h"
-#include "llvm/DebugInfo/PDB/Raw/RawError.h"
+#include "llvm/DebugInfo/PDB/Native/RawError.h"
+#include "llvm/Support/BinaryStreamArray.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/Error.h"
#include <cstdint>
@@ -57,7 +57,7 @@ private:
class TpiHashVerifier : public codeview::TypeVisitorCallbacks {
public:
- TpiHashVerifier(msf::FixedStreamArray<support::ulittle32_t> &HashValues,
+ TpiHashVerifier(FixedStreamArray<support::ulittle32_t> &HashValues,
uint32_t NumHashBuckets)
: HashValues(HashValues), NumHashBuckets(NumHashBuckets) {}
@@ -83,7 +83,7 @@ private:
utohexstr(codeview::TypeIndex::FirstNonSimpleIndex + Index));
}
- msf::FixedStreamArray<support::ulittle32_t> HashValues;
+ FixedStreamArray<support::ulittle32_t> HashValues;
codeview::CVType RawRecord;
uint32_t NumHashBuckets;
uint32_t Index = -1;
diff --git a/include/llvm/DebugInfo/PDB/Raw/TpiStream.h b/include/llvm/DebugInfo/PDB/Native/TpiStream.h
index de21abe4c817..62dde0ef08b7 100644
--- a/include/llvm/DebugInfo/PDB/Raw/TpiStream.h
+++ b/include/llvm/DebugInfo/PDB/Native/TpiStream.h
@@ -11,10 +11,11 @@
#define LLVM_DEBUGINFO_PDB_RAW_PDBTPISTREAM_H
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
-#include "llvm/DebugInfo/MSF/StreamArray.h"
+#include "llvm/DebugInfo/PDB/Native/HashTable.h"
+#include "llvm/DebugInfo/PDB/Native/RawConstants.h"
+#include "llvm/DebugInfo/PDB/Native/RawTypes.h"
#include "llvm/DebugInfo/PDB/PDBTypes.h"
-#include "llvm/DebugInfo/PDB/Raw/RawConstants.h"
-#include "llvm/DebugInfo/PDB/Raw/RawTypes.h"
+#include "llvm/Support/BinaryStreamArray.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/Error.h"
@@ -45,11 +46,11 @@ public:
uint32_t getHashKeySize() const;
uint32_t NumHashBuckets() const;
- msf::FixedStreamArray<support::ulittle32_t> getHashValues() const;
- msf::FixedStreamArray<TypeIndexOffset> getTypeIndexOffsets() const;
- msf::FixedStreamArray<TypeIndexOffset> getHashAdjustments() const;
+ FixedStreamArray<support::ulittle32_t> getHashValues() const;
+ FixedStreamArray<TypeIndexOffset> getTypeIndexOffsets() const;
+ HashTable &getHashAdjusters();
- iterator_range<codeview::CVTypeArray::Iterator> types(bool *HadError) const;
+ codeview::CVTypeRange types(bool *HadError) const;
Error commit();
@@ -61,10 +62,10 @@ private:
codeview::CVTypeArray TypeRecords;
- std::unique_ptr<msf::ReadableStream> HashStream;
- msf::FixedStreamArray<support::ulittle32_t> HashValues;
- msf::FixedStreamArray<TypeIndexOffset> TypeIndexOffsets;
- msf::FixedStreamArray<TypeIndexOffset> HashAdjustments;
+ std::unique_ptr<BinaryStream> HashStream;
+ FixedStreamArray<support::ulittle32_t> HashValues;
+ FixedStreamArray<TypeIndexOffset> TypeIndexOffsets;
+ HashTable HashAdjusters;
const TpiStreamHeader *Header;
};
diff --git a/include/llvm/DebugInfo/PDB/Raw/TpiStreamBuilder.h b/include/llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h
index f9a642126f53..a29ed0b610d3 100644
--- a/include/llvm/DebugInfo/PDB/Raw/TpiStreamBuilder.h
+++ b/include/llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h
@@ -12,31 +12,33 @@
#include "llvm/ADT/Optional.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
-#include "llvm/DebugInfo/MSF/ByteStream.h"
-#include "llvm/DebugInfo/MSF/SequencedItemStream.h"
-#include "llvm/DebugInfo/PDB/Raw/RawConstants.h"
+#include "llvm/DebugInfo/PDB/Native/RawConstants.h"
+#include "llvm/DebugInfo/PDB/Native/RawTypes.h"
#include "llvm/Support/Allocator.h"
+#include "llvm/Support/BinaryByteStream.h"
+#include "llvm/Support/BinaryItemStream.h"
+#include "llvm/Support/BinaryStreamRef.h"
#include "llvm/Support/Error.h"
#include <vector>
namespace llvm {
-namespace codeview {
-class TypeRecord;
-}
-namespace msf {
-class ByteStream;
-class MSFBuilder;
-struct MSFLayout;
-class ReadableStreamRef;
-class WritableStream;
+class BinaryByteStream;
+class WritableBinaryStreamRef;
-template <> struct SequencedItemTraits<llvm::codeview::CVType> {
+template <> struct BinaryItemTraits<llvm::codeview::CVType> {
static size_t length(const codeview::CVType &Item) { return Item.length(); }
static ArrayRef<uint8_t> bytes(const codeview::CVType &Item) {
return Item.data();
}
};
+
+namespace codeview {
+class TypeRecord;
+}
+namespace msf {
+class MSFBuilder;
+struct MSFLayout;
}
namespace pdb {
class PDBFile;
@@ -52,26 +54,30 @@ public:
TpiStreamBuilder &operator=(const TpiStreamBuilder &) = delete;
void setVersionHeader(PdbRaw_TpiVer Version);
- void addTypeRecord(const codeview::CVType &Record);
+ void addTypeRecord(ArrayRef<uint8_t> Type, Optional<uint32_t> Hash);
Error finalizeMsfLayout();
- Error commit(const msf::MSFLayout &Layout, const msf::WritableStream &Buffer);
+ Error commit(const msf::MSFLayout &Layout, WritableBinaryStreamRef Buffer);
- uint32_t calculateSerializedLength() const;
+ uint32_t calculateSerializedLength();
private:
uint32_t calculateHashBufferSize() const;
+ uint32_t calculateIndexOffsetSize() const;
Error finalize();
msf::MSFBuilder &Msf;
BumpPtrAllocator &Allocator;
+ size_t TypeRecordBytes = 0;
+
Optional<PdbRaw_TpiVer> VerHeader;
- std::vector<codeview::CVType> TypeRecords;
- msf::SequencedItemStream<codeview::CVType> TypeRecordStream;
+ std::vector<ArrayRef<uint8_t>> TypeRecords;
+ std::vector<uint32_t> TypeHashes;
+ std::vector<TypeIndexOffset> TypeIndexOffsets;
uint32_t HashStreamIndex = kInvalidStreamIndex;
- std::unique_ptr<msf::ByteStream> HashValueStream;
+ std::unique_ptr<BinaryByteStream> HashValueStream;
const TpiStreamHeader *Header;
uint32_t Idx;
diff --git a/include/llvm/DebugInfo/PDB/PDBExtras.h b/include/llvm/DebugInfo/PDB/PDBExtras.h
index 5a7422d9e9e4..fc5787556a6d 100644
--- a/include/llvm/DebugInfo/PDB/PDBExtras.h
+++ b/include/llvm/DebugInfo/PDB/PDBExtras.h
@@ -30,8 +30,8 @@ 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_UniqueId &Guid);
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 PDB_Machine &Machine);
raw_ostream &operator<<(raw_ostream &OS, const Variant &Value);
diff --git a/include/llvm/DebugInfo/PDB/PDBSymDumper.h b/include/llvm/DebugInfo/PDB/PDBSymDumper.h
index 095c33cfe8b5..c976935c48e0 100644
--- a/include/llvm/DebugInfo/PDB/PDBSymDumper.h
+++ b/include/llvm/DebugInfo/PDB/PDBSymDumper.h
@@ -54,6 +54,22 @@ public:
virtual void dump(const PDBSymbolUnknown &Symbol);
virtual void dump(const PDBSymbolUsingNamespace &Symbol);
+ virtual void dumpRight(const PDBSymbolTypeArray &Symbol) {}
+ virtual void dumpRight(const PDBSymbolTypeBaseClass &Symbol) {}
+ virtual void dumpRight(const PDBSymbolTypeBuiltin &Symbol) {}
+ virtual void dumpRight(const PDBSymbolTypeCustom &Symbol) {}
+ virtual void dumpRight(const PDBSymbolTypeDimension &Symbol) {}
+ virtual void dumpRight(const PDBSymbolTypeEnum &Symbol) {}
+ virtual void dumpRight(const PDBSymbolTypeFriend &Symbol) {}
+ virtual void dumpRight(const PDBSymbolTypeFunctionArg &Symbol) {}
+ virtual void dumpRight(const PDBSymbolTypeFunctionSig &Symbol) {}
+ virtual void dumpRight(const PDBSymbolTypeManaged &Symbol) {}
+ virtual void dumpRight(const PDBSymbolTypePointer &Symbol) {}
+ virtual void dumpRight(const PDBSymbolTypeTypedef &Symbol) {}
+ virtual void dumpRight(const PDBSymbolTypeUDT &Symbol) {}
+ virtual void dumpRight(const PDBSymbolTypeVTable &Symbol) {}
+ virtual void dumpRight(const PDBSymbolTypeVTableShape &Symbol) {}
+
private:
bool RequireImpl;
};
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbol.h b/include/llvm/DebugInfo/PDB/PDBSymbol.h
index bf5118806540..b114b7afb0b0 100644
--- a/include/llvm/DebugInfo/PDB/PDBSymbol.h
+++ b/include/llvm/DebugInfo/PDB/PDBSymbol.h
@@ -22,6 +22,23 @@
return RawSymbol->MethodName(); \
}
+#define FORWARD_CONCRETE_SYMBOL_ID_METHOD_WITH_NAME(ConcreteType, PrivateName, \
+ PublicName) \
+ auto PublicName##Id() const->decltype(RawSymbol->PrivateName##Id()) { \
+ return RawSymbol->PrivateName##Id(); \
+ } \
+ std::unique_ptr<ConcreteType> PublicName() const { \
+ uint32_t Id = PublicName##Id(); \
+ return getConcreteSymbolByIdHelper<ConcreteType>(Id); \
+ }
+
+#define FORWARD_SYMBOL_ID_METHOD_WITH_NAME(PrivateName, PublicName) \
+ FORWARD_CONCRETE_SYMBOL_ID_METHOD_WITH_NAME(PDBSymbol, PrivateName, \
+ PublicName)
+
+#define FORWARD_SYMBOL_ID_METHOD(MethodName) \
+ FORWARD_SYMBOL_ID_METHOD_WITH_NAME(MethodName, MethodName)
+
namespace llvm {
class StringRef;
@@ -29,6 +46,7 @@ class raw_ostream;
namespace pdb {
class IPDBRawSymbol;
+class IPDBSession;
#define DECLARE_PDB_SYMBOL_CONCRETE_TYPE(TagValue) \
static const PDB_SymType Tag = TagValue; \
@@ -44,6 +62,7 @@ class PDBSymbol {
protected:
PDBSymbol(const IPDBSession &PDBSession,
std::unique_ptr<IPDBRawSymbol> Symbol);
+ PDBSymbol(PDBSymbol &Symbol);
public:
static std::unique_ptr<PDBSymbol>
@@ -56,7 +75,14 @@ public:
/// unknown properties, but individual implementations of PDBSymbol may
/// override the behavior to only dump known fields.
virtual void dump(PDBSymDumper &Dumper) const = 0;
+
+ /// For certain PDBSymbolTypes, dumps additional information for the type that
+ /// normally goes on the right side of the symbol.
+ virtual void dumpRight(PDBSymDumper &Dumper) const {}
+
void defaultDump(raw_ostream &OS, int Indent) const;
+ void dumpProperties() const;
+ void dumpChildStats() const;
PDB_SymType getSymTag() const;
uint32_t getSymIndexId() const;
@@ -66,6 +92,8 @@ public:
return Enumerator->getNext();
}
+ std::unique_ptr<PDBSymbol> clone() const;
+
template <typename T>
std::unique_ptr<ConcreteSymbolEnumerator<T>> findAllChildren() const {
auto BaseIter = RawSymbol->findChildren(T::Tag);
@@ -91,8 +119,15 @@ public:
std::unique_ptr<IPDBEnumSymbols> getChildStats(TagStats &Stats) const;
protected:
+ std::unique_ptr<PDBSymbol> getSymbolByIdHelper(uint32_t Id) const;
+
+ template <typename ConcreteType>
+ std::unique_ptr<ConcreteType> getConcreteSymbolByIdHelper(uint32_t Id) const {
+ return unique_dyn_cast_or_null<ConcreteType>(getSymbolByIdHelper(Id));
+ }
+
const IPDBSession &Session;
- const std::unique_ptr<IPDBRawSymbol> RawSymbol;
+ std::unique_ptr<IPDBRawSymbol> RawSymbol;
};
} // namespace llvm
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolBlock.h b/include/llvm/DebugInfo/PDB/PDBSymbolBlock.h
index d0ff62ca7c3f..d81da1eaa023 100644
--- a/include/llvm/DebugInfo/PDB/PDBSymbolBlock.h
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolBlock.h
@@ -30,7 +30,7 @@ public:
FORWARD_SYMBOL_METHOD(getAddressOffset)
FORWARD_SYMBOL_METHOD(getAddressSection)
FORWARD_SYMBOL_METHOD(getLength)
- FORWARD_SYMBOL_METHOD(getLexicalParentId)
+ FORWARD_SYMBOL_ID_METHOD(getLexicalParent)
FORWARD_SYMBOL_METHOD(getLocationType)
FORWARD_SYMBOL_METHOD(getName)
FORWARD_SYMBOL_METHOD(getRelativeVirtualAddress)
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolCompiland.h b/include/llvm/DebugInfo/PDB/PDBSymbolCompiland.h
index f1983b3f7bf5..26788017cf32 100644
--- a/include/llvm/DebugInfo/PDB/PDBSymbolCompiland.h
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolCompiland.h
@@ -29,7 +29,7 @@ public:
void dump(PDBSymDumper &Dumper) const override;
FORWARD_SYMBOL_METHOD(isEditAndContinueEnabled)
- FORWARD_SYMBOL_METHOD(getLexicalParentId)
+ FORWARD_SYMBOL_ID_METHOD(getLexicalParent)
FORWARD_SYMBOL_METHOD(getLibraryName)
FORWARD_SYMBOL_METHOD(getName)
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolCompilandDetails.h b/include/llvm/DebugInfo/PDB/PDBSymbolCompilandDetails.h
index bb4a78f68e2f..dba50c42cf81 100644
--- a/include/llvm/DebugInfo/PDB/PDBSymbolCompilandDetails.h
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolCompilandDetails.h
@@ -46,7 +46,7 @@ public:
FORWARD_SYMBOL_METHOD(isLTCG)
FORWARD_SYMBOL_METHOD(isMSILNetmodule)
FORWARD_SYMBOL_METHOD(getLanguage)
- FORWARD_SYMBOL_METHOD(getLexicalParentId)
+ FORWARD_SYMBOL_ID_METHOD(getLexicalParent)
FORWARD_SYMBOL_METHOD(getPlatform)
FORWARD_SYMBOL_METHOD(getSourceFileName)
};
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolCompilandEnv.h b/include/llvm/DebugInfo/PDB/PDBSymbolCompilandEnv.h
index a71a0ba2df58..7868f0459086 100644
--- a/include/llvm/DebugInfo/PDB/PDBSymbolCompilandEnv.h
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolCompilandEnv.h
@@ -26,7 +26,7 @@ public:
void dump(PDBSymDumper &Dumper) const override;
- FORWARD_SYMBOL_METHOD(getLexicalParentId)
+ FORWARD_SYMBOL_ID_METHOD(getLexicalParent)
FORWARD_SYMBOL_METHOD(getName)
std::string getValue() const;
};
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolData.h b/include/llvm/DebugInfo/PDB/PDBSymbolData.h
index 36f32ab51c11..ad4285df4d44 100644
--- a/include/llvm/DebugInfo/PDB/PDBSymbolData.h
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolData.h
@@ -26,8 +26,6 @@ public:
DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Data)
- std::unique_ptr<PDBSymbol> getType() const;
-
void dump(PDBSymDumper &Dumper) const override;
FORWARD_SYMBOL_METHOD(getAccess)
@@ -35,14 +33,14 @@ public:
FORWARD_SYMBOL_METHOD(getAddressSection)
FORWARD_SYMBOL_METHOD(getAddressTaken)
FORWARD_SYMBOL_METHOD(getBitPosition)
- FORWARD_SYMBOL_METHOD(getClassParentId)
+ FORWARD_SYMBOL_ID_METHOD(getClassParent)
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_ID_METHOD(getLexicalParent)
FORWARD_SYMBOL_METHOD(getLocationType)
FORWARD_SYMBOL_METHOD(getName)
FORWARD_SYMBOL_METHOD(getOffset)
@@ -50,7 +48,7 @@ public:
FORWARD_SYMBOL_METHOD(getRelativeVirtualAddress)
FORWARD_SYMBOL_METHOD(getSlot)
FORWARD_SYMBOL_METHOD(getToken)
- FORWARD_SYMBOL_METHOD(getTypeId)
+ FORWARD_SYMBOL_ID_METHOD(getType)
FORWARD_SYMBOL_METHOD(isUnalignedType)
FORWARD_SYMBOL_METHOD(getValue)
FORWARD_SYMBOL_METHOD(getVirtualAddress)
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolExe.h b/include/llvm/DebugInfo/PDB/PDBSymbolExe.h
index 5b3f50d153eb..2c2d74665040 100644
--- a/include/llvm/DebugInfo/PDB/PDBSymbolExe.h
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolExe.h
@@ -37,6 +37,8 @@ public:
FORWARD_SYMBOL_METHOD(getSignature)
FORWARD_SYMBOL_METHOD(getSymbolsFileName)
+ uint32_t getPointerByteSize() const;
+
private:
void dumpChildren(raw_ostream &OS, StringRef Label, PDB_SymType ChildType,
int Indent) const;
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolFunc.h b/include/llvm/DebugInfo/PDB/PDBSymbolFunc.h
index 7170bcbe846c..c2f02ea6f126 100644
--- a/include/llvm/DebugInfo/PDB/PDBSymbolFunc.h
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolFunc.h
@@ -11,6 +11,7 @@
#define LLVM_DEBUGINFO_PDB_PDBSYMBOLFUNC_H
#include "PDBSymbol.h"
+#include "PDBSymbolTypeFunctionSig.h"
#include "PDBTypes.h"
namespace llvm {
@@ -26,8 +27,8 @@ public:
void dump(PDBSymDumper &Dumper) const override;
- std::unique_ptr<PDBSymbolTypeFunctionSig> getSignature() const;
- std::unique_ptr<PDBSymbolTypeUDT> getClassParent() const;
+ bool isDestructor() const;
+
std::unique_ptr<IPDBEnumChildren<PDBSymbolData>> getArguments() const;
DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Function)
@@ -35,7 +36,7 @@ public:
FORWARD_SYMBOL_METHOD(getAccess)
FORWARD_SYMBOL_METHOD(getAddressOffset)
FORWARD_SYMBOL_METHOD(getAddressSection)
- FORWARD_SYMBOL_METHOD(getClassParentId)
+ FORWARD_SYMBOL_ID_METHOD(getClassParent)
FORWARD_SYMBOL_METHOD(isCompilerGenerated)
FORWARD_SYMBOL_METHOD(isConstType)
FORWARD_SYMBOL_METHOD(hasCustomCallingConvention)
@@ -54,7 +55,7 @@ public:
FORWARD_SYMBOL_METHOD(isNaked)
FORWARD_SYMBOL_METHOD(isStatic)
FORWARD_SYMBOL_METHOD(getLength)
- FORWARD_SYMBOL_METHOD(getLexicalParentId)
+ FORWARD_SYMBOL_ID_METHOD(getLexicalParent)
FORWARD_SYMBOL_METHOD(getLocalBasePointerRegisterId)
FORWARD_SYMBOL_METHOD(getLocationType)
FORWARD_SYMBOL_METHOD(getName)
@@ -67,7 +68,8 @@ public:
FORWARD_SYMBOL_METHOD(isPureVirtual)
FORWARD_SYMBOL_METHOD(getRelativeVirtualAddress)
FORWARD_SYMBOL_METHOD(getToken)
- FORWARD_SYMBOL_METHOD(getTypeId)
+ FORWARD_CONCRETE_SYMBOL_ID_METHOD_WITH_NAME(PDBSymbolTypeFunctionSig, getType,
+ getSignature)
FORWARD_SYMBOL_METHOD(isUnalignedType)
FORWARD_SYMBOL_METHOD(getUndecoratedName)
FORWARD_SYMBOL_METHOD(isVirtual)
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h b/include/llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h
index 464389503bef..3341bd9b30fd 100644
--- a/include/llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h
@@ -34,7 +34,7 @@ public:
FORWARD_SYMBOL_METHOD(hasFarReturn)
FORWARD_SYMBOL_METHOD(hasInterruptReturn)
FORWARD_SYMBOL_METHOD(isStatic)
- FORWARD_SYMBOL_METHOD(getLexicalParentId)
+ FORWARD_SYMBOL_ID_METHOD(getLexicalParent)
FORWARD_SYMBOL_METHOD(getLocationType)
FORWARD_SYMBOL_METHOD(hasNoInlineAttribute)
FORWARD_SYMBOL_METHOD(hasNoReturnAttribute)
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h b/include/llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h
index c2e3dd39be6c..6729838597c8 100644
--- a/include/llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h
@@ -33,7 +33,7 @@ public:
FORWARD_SYMBOL_METHOD(hasFarReturn)
FORWARD_SYMBOL_METHOD(hasInterruptReturn)
FORWARD_SYMBOL_METHOD(isStatic)
- FORWARD_SYMBOL_METHOD(getLexicalParentId)
+ FORWARD_SYMBOL_ID_METHOD(getLexicalParent)
FORWARD_SYMBOL_METHOD(getLocationType)
FORWARD_SYMBOL_METHOD(hasNoInlineAttribute)
FORWARD_SYMBOL_METHOD(hasNoReturnAttribute)
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolLabel.h b/include/llvm/DebugInfo/PDB/PDBSymbolLabel.h
index 3aeae10b47bc..c2b1c28c929e 100644
--- a/include/llvm/DebugInfo/PDB/PDBSymbolLabel.h
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolLabel.h
@@ -32,7 +32,7 @@ public:
FORWARD_SYMBOL_METHOD(hasCustomCallingConvention)
FORWARD_SYMBOL_METHOD(hasFarReturn)
FORWARD_SYMBOL_METHOD(hasInterruptReturn)
- FORWARD_SYMBOL_METHOD(getLexicalParentId)
+ FORWARD_SYMBOL_ID_METHOD(getLexicalParent)
FORWARD_SYMBOL_METHOD(getLocationType)
FORWARD_SYMBOL_METHOD(getName)
FORWARD_SYMBOL_METHOD(hasNoInlineAttribute)
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h b/include/llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h
index be0734445973..c9e6ee67c575 100644
--- a/include/llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h
@@ -32,7 +32,7 @@ public:
FORWARD_SYMBOL_METHOD(isCode)
FORWARD_SYMBOL_METHOD(isFunction)
FORWARD_SYMBOL_METHOD(getLength)
- FORWARD_SYMBOL_METHOD(getLexicalParentId)
+ FORWARD_SYMBOL_ID_METHOD(getLexicalParent)
FORWARD_SYMBOL_METHOD(getLocationType)
FORWARD_SYMBOL_METHOD(isManagedCode)
FORWARD_SYMBOL_METHOD(isMSILCode)
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolThunk.h b/include/llvm/DebugInfo/PDB/PDBSymbolThunk.h
index 63f7a09fc881..614fad86caa8 100644
--- a/include/llvm/DebugInfo/PDB/PDBSymbolThunk.h
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolThunk.h
@@ -30,12 +30,12 @@ public:
FORWARD_SYMBOL_METHOD(getAccess)
FORWARD_SYMBOL_METHOD(getAddressOffset)
FORWARD_SYMBOL_METHOD(getAddressSection)
- FORWARD_SYMBOL_METHOD(getClassParentId)
+ FORWARD_SYMBOL_ID_METHOD(getClassParent)
FORWARD_SYMBOL_METHOD(isConstType)
FORWARD_SYMBOL_METHOD(isIntroVirtualFunction)
FORWARD_SYMBOL_METHOD(isStatic)
FORWARD_SYMBOL_METHOD(getLength)
- FORWARD_SYMBOL_METHOD(getLexicalParentId)
+ FORWARD_SYMBOL_ID_METHOD(getLexicalParent)
FORWARD_SYMBOL_METHOD(getName)
FORWARD_SYMBOL_METHOD(isPureVirtual)
FORWARD_SYMBOL_METHOD(getRelativeVirtualAddress)
@@ -44,7 +44,7 @@ public:
FORWARD_SYMBOL_METHOD(getTargetVirtualAddress)
FORWARD_SYMBOL_METHOD(getTargetSection)
FORWARD_SYMBOL_METHOD(getThunkOrdinal)
- FORWARD_SYMBOL_METHOD(getTypeId)
+ FORWARD_SYMBOL_ID_METHOD(getType)
FORWARD_SYMBOL_METHOD(isUnalignedType)
FORWARD_SYMBOL_METHOD(isVirtual)
FORWARD_SYMBOL_METHOD(getVirtualAddress)
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeArray.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeArray.h
index 57db03661fb7..39b7d3b300ea 100644
--- a/include/llvm/DebugInfo/PDB/PDBSymbolTypeArray.h
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeArray.h
@@ -25,17 +25,16 @@ public:
DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::ArrayType)
- std::unique_ptr<PDBSymbol> getElementType() const;
-
void dump(PDBSymDumper &Dumper) const override;
+ void dumpRight(PDBSymDumper &Dumper) const override;
- FORWARD_SYMBOL_METHOD(getArrayIndexTypeId)
+ FORWARD_SYMBOL_ID_METHOD(getArrayIndexType)
FORWARD_SYMBOL_METHOD(isConstType)
FORWARD_SYMBOL_METHOD(getCount)
FORWARD_SYMBOL_METHOD(getLength)
- FORWARD_SYMBOL_METHOD(getLexicalParentId)
+ FORWARD_SYMBOL_ID_METHOD(getLexicalParent)
FORWARD_SYMBOL_METHOD(getRank)
- FORWARD_SYMBOL_METHOD(getTypeId)
+ FORWARD_SYMBOL_ID_METHOD_WITH_NAME(getType, getElementType)
FORWARD_SYMBOL_METHOD(isUnalignedType)
FORWARD_SYMBOL_METHOD(isVolatileType)
};
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h
index aaa3ab7988d7..d607a3d81170 100644
--- a/include/llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h
@@ -13,6 +13,9 @@
#include "PDBSymbol.h"
#include "PDBTypes.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeVTableShape.h"
+
namespace llvm {
class raw_ostream;
@@ -28,7 +31,7 @@ public:
void dump(PDBSymDumper &Dumper) const override;
FORWARD_SYMBOL_METHOD(getAccess)
- FORWARD_SYMBOL_METHOD(getClassParentId)
+ FORWARD_SYMBOL_ID_METHOD(getClassParent)
FORWARD_SYMBOL_METHOD(hasConstructor)
FORWARD_SYMBOL_METHOD(isConstType)
FORWARD_SYMBOL_METHOD(hasAssignmentOperator)
@@ -36,14 +39,14 @@ public:
FORWARD_SYMBOL_METHOD(hasNestedTypes)
FORWARD_SYMBOL_METHOD(isIndirectVirtualBaseClass)
FORWARD_SYMBOL_METHOD(getLength)
- FORWARD_SYMBOL_METHOD(getLexicalParentId)
+ FORWARD_SYMBOL_ID_METHOD(getLexicalParent)
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(getTypeId)
+ FORWARD_SYMBOL_ID_METHOD(getType)
FORWARD_SYMBOL_METHOD(getUdtKind)
FORWARD_SYMBOL_METHOD(isUnalignedType)
@@ -51,7 +54,7 @@ public:
FORWARD_SYMBOL_METHOD(getVirtualBaseDispIndex)
FORWARD_SYMBOL_METHOD(getVirtualBasePointerOffset)
// FORWARD_SYMBOL_METHOD(getVirtualBaseTableType)
- FORWARD_SYMBOL_METHOD(getVirtualTableShapeId)
+ FORWARD_SYMBOL_ID_METHOD(getVirtualTableShape)
FORWARD_SYMBOL_METHOD(isVolatileType)
};
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h
index c8f59f1f140a..5b1863c42a04 100644
--- a/include/llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h
@@ -30,7 +30,7 @@ public:
FORWARD_SYMBOL_METHOD(getBuiltinType)
FORWARD_SYMBOL_METHOD(isConstType)
FORWARD_SYMBOL_METHOD(getLength)
- FORWARD_SYMBOL_METHOD(getLexicalParentId)
+ FORWARD_SYMBOL_ID_METHOD(getLexicalParent)
FORWARD_SYMBOL_METHOD(isUnalignedType)
FORWARD_SYMBOL_METHOD(isVolatileType)
};
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h
index ade2887bac14..c5ae3c51162c 100644
--- a/include/llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h
@@ -11,6 +11,7 @@
#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEENUM_H
#include "PDBSymbol.h"
+#include "PDBSymbolTypeBuiltin.h"
#include "PDBTypes.h"
namespace llvm {
@@ -27,25 +28,22 @@ public:
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_ID_METHOD(getClassParent)
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_ID_METHOD(getLexicalParent)
FORWARD_SYMBOL_METHOD(getName)
FORWARD_SYMBOL_METHOD(isNested)
FORWARD_SYMBOL_METHOD(hasOverloadedOperator)
FORWARD_SYMBOL_METHOD(isPacked)
FORWARD_SYMBOL_METHOD(isScoped)
- FORWARD_SYMBOL_METHOD(getTypeId)
+ FORWARD_CONCRETE_SYMBOL_ID_METHOD_WITH_NAME(PDBSymbolTypeBuiltin, getType,
+ getUnderlyingType)
FORWARD_SYMBOL_METHOD(isUnalignedType)
FORWARD_SYMBOL_METHOD(isVolatileType)
};
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeFriend.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeFriend.h
index 196d149ed2a2..24c13128111f 100644
--- a/include/llvm/DebugInfo/PDB/PDBSymbolTypeFriend.h
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeFriend.h
@@ -27,9 +27,9 @@ public:
void dump(PDBSymDumper &Dumper) const override;
- FORWARD_SYMBOL_METHOD(getClassParentId)
+ FORWARD_SYMBOL_ID_METHOD(getClassParent)
FORWARD_SYMBOL_METHOD(getName)
- FORWARD_SYMBOL_METHOD(getTypeId)
+ FORWARD_SYMBOL_ID_METHOD(getType)
};
} // namespace llvm
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h
index 5561341d7e77..3855999c473f 100644
--- a/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h
@@ -27,9 +27,9 @@ public:
void dump(PDBSymDumper &Dumper) const override;
- FORWARD_SYMBOL_METHOD(getClassParentId)
- FORWARD_SYMBOL_METHOD(getLexicalParentId)
- FORWARD_SYMBOL_METHOD(getTypeId)
+ FORWARD_SYMBOL_ID_METHOD(getClassParent)
+ FORWARD_SYMBOL_ID_METHOD(getLexicalParent)
+ FORWARD_SYMBOL_ID_METHOD(getType)
};
} // namespace llvm
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h
index 516011ff8b3d..8de54e70701d 100644
--- a/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h
@@ -25,22 +25,21 @@ public:
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 dumpRight(PDBSymDumper &Dumper) const override;
void dumpArgList(raw_ostream &OS) const;
FORWARD_SYMBOL_METHOD(getCallingConvention)
- FORWARD_SYMBOL_METHOD(getClassParentId)
- FORWARD_SYMBOL_METHOD(getUnmodifiedTypeId)
+ FORWARD_SYMBOL_ID_METHOD(getClassParent)
+ FORWARD_SYMBOL_ID_METHOD(getUnmodifiedType)
FORWARD_SYMBOL_METHOD(isConstType)
FORWARD_SYMBOL_METHOD(getCount)
- FORWARD_SYMBOL_METHOD(getLexicalParentId)
+ FORWARD_SYMBOL_ID_METHOD(getLexicalParent)
// FORWARD_SYMBOL_METHOD(getObjectPointerType)
FORWARD_SYMBOL_METHOD(getThisAdjust)
- FORWARD_SYMBOL_METHOD(getTypeId)
+ FORWARD_SYMBOL_ID_METHOD_WITH_NAME(getType, getReturnType)
FORWARD_SYMBOL_METHOD(isUnalignedType)
FORWARD_SYMBOL_METHOD(isVolatileType)
};
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypePointer.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypePointer.h
index 7a57272adb79..c502d4e77afe 100644
--- a/include/llvm/DebugInfo/PDB/PDBSymbolTypePointer.h
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypePointer.h
@@ -25,15 +25,14 @@ public:
DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::PointerType)
- std::unique_ptr<PDBSymbol> getPointeeType() const;
-
void dump(PDBSymDumper &Dumper) const override;
+ void dumpRight(PDBSymDumper &Dumper) const override;
FORWARD_SYMBOL_METHOD(isConstType)
FORWARD_SYMBOL_METHOD(getLength)
- FORWARD_SYMBOL_METHOD(getLexicalParentId)
+ FORWARD_SYMBOL_ID_METHOD(getLexicalParent)
FORWARD_SYMBOL_METHOD(isReference)
- FORWARD_SYMBOL_METHOD(getTypeId)
+ FORWARD_SYMBOL_ID_METHOD_WITH_NAME(getType, getPointeeType)
FORWARD_SYMBOL_METHOD(isUnalignedType)
FORWARD_SYMBOL_METHOD(isVolatileType)
};
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h
index 5ed4f8d21d90..16c1d1b88c6d 100644
--- a/include/llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h
@@ -28,24 +28,24 @@ public:
void dump(PDBSymDumper &Dumper) const override;
FORWARD_SYMBOL_METHOD(getBuiltinType)
- FORWARD_SYMBOL_METHOD(getClassParentId)
+ FORWARD_SYMBOL_ID_METHOD(getClassParent)
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_ID_METHOD(getLexicalParent)
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(getTypeId)
+ FORWARD_SYMBOL_ID_METHOD(getType)
FORWARD_SYMBOL_METHOD(getUdtKind)
FORWARD_SYMBOL_METHOD(isUnalignedType)
- FORWARD_SYMBOL_METHOD(getVirtualTableShapeId)
+ FORWARD_SYMBOL_ID_METHOD(getVirtualTableShape)
FORWARD_SYMBOL_METHOD(isVolatileType)
};
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h
index 1874dfef34f7..e9e7fe8c9865 100644
--- a/include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h
@@ -10,7 +10,9 @@
#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEUDT_H
#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEUDT_H
+#include "IPDBSession.h"
#include "PDBSymbol.h"
+#include "PDBSymbolTypeBaseClass.h"
#include "PDBTypes.h"
namespace llvm {
@@ -18,24 +20,30 @@ namespace llvm {
class raw_ostream;
namespace pdb {
+
class PDBSymbolTypeUDT : public PDBSymbol {
public:
PDBSymbolTypeUDT(const IPDBSession &PDBSession,
std::unique_ptr<IPDBRawSymbol> UDTSymbol);
+ std::unique_ptr<PDBSymbolTypeUDT> clone() const {
+ return getSession().getConcreteSymbolById<PDBSymbolTypeUDT>(
+ getSymIndexId());
+ }
+
DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::UDT)
void dump(PDBSymDumper &Dumper) const override;
- FORWARD_SYMBOL_METHOD(getClassParentId)
- FORWARD_SYMBOL_METHOD(getUnmodifiedTypeId)
+ FORWARD_SYMBOL_ID_METHOD(getClassParent)
+ FORWARD_SYMBOL_ID_METHOD(getUnmodifiedType)
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_ID_METHOD(getLexicalParent)
FORWARD_SYMBOL_METHOD(getName)
FORWARD_SYMBOL_METHOD(isNested)
FORWARD_SYMBOL_METHOD(hasOverloadedOperator)
@@ -43,7 +51,7 @@ public:
FORWARD_SYMBOL_METHOD(isScoped)
FORWARD_SYMBOL_METHOD(getUdtKind)
FORWARD_SYMBOL_METHOD(isUnalignedType)
- FORWARD_SYMBOL_METHOD(getVirtualTableShapeId)
+ FORWARD_SYMBOL_ID_METHOD(getVirtualTableShape)
FORWARD_SYMBOL_METHOD(isVolatileType)
};
}
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h
index baf7ab79d60e..e270c2b7eb95 100644
--- a/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h
@@ -27,10 +27,11 @@ public:
void dump(PDBSymDumper &Dumper) const override;
- FORWARD_SYMBOL_METHOD(getClassParentId)
+ FORWARD_SYMBOL_ID_METHOD(getClassParent)
+ FORWARD_SYMBOL_METHOD(getOffset)
FORWARD_SYMBOL_METHOD(isConstType)
- FORWARD_SYMBOL_METHOD(getLexicalParentId)
- FORWARD_SYMBOL_METHOD(getTypeId)
+ FORWARD_SYMBOL_ID_METHOD(getLexicalParent)
+ FORWARD_SYMBOL_ID_METHOD(getType)
FORWARD_SYMBOL_METHOD(isUnalignedType)
FORWARD_SYMBOL_METHOD(isVolatileType)
};
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTableShape.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTableShape.h
index 431fc1ac8625..8acaabea5bb8 100644
--- a/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTableShape.h
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTableShape.h
@@ -29,7 +29,7 @@ public:
FORWARD_SYMBOL_METHOD(isConstType)
FORWARD_SYMBOL_METHOD(getCount)
- FORWARD_SYMBOL_METHOD(getLexicalParentId)
+ FORWARD_SYMBOL_ID_METHOD(getLexicalParent)
FORWARD_SYMBOL_METHOD(isUnalignedType)
FORWARD_SYMBOL_METHOD(isVolatileType)
};
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolUsingNamespace.h b/include/llvm/DebugInfo/PDB/PDBSymbolUsingNamespace.h
index a273fe159c12..70fbd5b84c34 100644
--- a/include/llvm/DebugInfo/PDB/PDBSymbolUsingNamespace.h
+++ b/include/llvm/DebugInfo/PDB/PDBSymbolUsingNamespace.h
@@ -27,7 +27,7 @@ public:
void dump(PDBSymDumper &Dumper) const override;
- FORWARD_SYMBOL_METHOD(getLexicalParentId)
+ FORWARD_SYMBOL_ID_METHOD(getLexicalParent)
FORWARD_SYMBOL_METHOD(getName)
};
diff --git a/include/llvm/DebugInfo/PDB/PDBTypes.h b/include/llvm/DebugInfo/PDB/PDBTypes.h
index 0d232f15d745..dd2fc4f2c55f 100644
--- a/include/llvm/DebugInfo/PDB/PDBTypes.h
+++ b/include/llvm/DebugInfo/PDB/PDBTypes.h
@@ -12,7 +12,7 @@
#include "llvm/Config/llvm-config.h"
#include "llvm/DebugInfo/CodeView/CodeView.h"
-#include "llvm/DebugInfo/PDB/Raw/RawTypes.h"
+#include "llvm/DebugInfo/PDB/Native/RawTypes.h"
#include <cstdint>
#include <cstring>
#include <functional>
@@ -68,10 +68,10 @@ class PDBSymbolTypeDimension;
class PDBSymbolUnknown;
/// Specifies which PDB reader implementation is to be used. Only a value
-/// of PDB_ReaderType::DIA is supported.
+/// of PDB_ReaderType::DIA is currently supported, but Native is in the works.
enum class PDB_ReaderType {
DIA = 0,
- Raw = 1,
+ Native = 1,
};
/// An enumeration indicating the type of data contained in this table.
diff --git a/include/llvm/DebugInfo/PDB/Raw/NameMap.h b/include/llvm/DebugInfo/PDB/Raw/NameMap.h
deleted file mode 100644
index de1163bc3079..000000000000
--- a/include/llvm/DebugInfo/PDB/Raw/NameMap.h
+++ /dev/null
@@ -1,44 +0,0 @@
-//===- NameMap.h - PDB Name Map ---------------------------------*- 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_RAW_PDBNAMEMAP_H
-#define LLVM_DEBUGINFO_PDB_RAW_PDBNAMEMAP_H
-
-#include "llvm/ADT/StringMap.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/Error.h"
-#include <cstdint>
-
-namespace llvm {
-namespace msf {
-class StreamReader;
-class StreamWriter;
-}
-namespace pdb {
-class NameMapBuilder;
-class NameMap {
- friend NameMapBuilder;
-
-public:
- NameMap();
-
- Error load(msf::StreamReader &Stream);
-
- bool tryGetValue(StringRef Name, uint32_t &Value) const;
-
- iterator_range<StringMapConstIterator<uint32_t>> entries() const;
-
-private:
- StringMap<uint32_t> Mapping;
-};
-
-} // end namespace pdb
-} // end namespace llvm
-
-#endif // LLVM_DEBUGINFO_PDB_RAW_PDBNAMEMAP_H
diff --git a/include/llvm/DebugInfo/PDB/Raw/NameMapBuilder.h b/include/llvm/DebugInfo/PDB/Raw/NameMapBuilder.h
deleted file mode 100644
index f5244ac21808..000000000000
--- a/include/llvm/DebugInfo/PDB/Raw/NameMapBuilder.h
+++ /dev/null
@@ -1,45 +0,0 @@
-//===- NameMapBuilder.h - PDB Name Map Builder ------------------*- 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_RAW_PDBNAMEMAPBUILDER_H
-#define LLVM_DEBUGINFO_PDB_RAW_PDBNAMEMAPBUILDER_H
-
-#include "llvm/ADT/StringMap.h"
-#include "llvm/Support/Error.h"
-
-#include <cstdint>
-#include <memory>
-
-namespace llvm {
-namespace msf {
-class StreamWriter;
-}
-namespace pdb {
-class NameMap;
-
-class NameMapBuilder {
-public:
- NameMapBuilder();
-
- void addMapping(StringRef Name, uint32_t Mapping);
-
- Expected<std::unique_ptr<NameMap>> build();
- Error commit(msf::StreamWriter &Writer) const;
-
- uint32_t calculateSerializedLength() const;
-
-private:
- StringMap<uint32_t> Map;
- uint32_t StringDataBytes = 0;
-};
-
-} // end namespace pdb
-} // end namespace llvm
-
-#endif // LLVM_DEBUGINFO_PDB_RAW_PDBNAMEMAPBUILDER_H
diff --git a/include/llvm/DebugInfo/PDB/UDTLayout.h b/include/llvm/DebugInfo/PDB/UDTLayout.h
new file mode 100644
index 000000000000..e3dcba50bd1a
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/UDTLayout.h
@@ -0,0 +1,180 @@
+//===- UDTLayout.h - UDT layout 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_UDTLAYOUT_H
+#define LLVM_DEBUGINFO_PDB_UDTLAYOUT_H
+
+#include "PDBSymbol.h"
+#include "PDBTypes.h"
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/BitVector.h"
+
+#include <list>
+#include <memory>
+
+namespace llvm {
+
+class raw_ostream;
+
+namespace pdb {
+
+class PDBSymTypeBaseClass;
+class PDBSymbolData;
+class PDBSymbolTypeUDT;
+class PDBSymbolTypeVTable;
+
+class ClassLayout;
+class BaseClassLayout;
+class StorageItemBase;
+class UDTLayoutBase;
+
+class StorageItemBase {
+public:
+ StorageItemBase(const UDTLayoutBase &Parent, const PDBSymbol &Symbol,
+ const std::string &Name, uint32_t OffsetInParent,
+ uint32_t Size);
+ virtual ~StorageItemBase() {}
+
+ virtual uint32_t deepPaddingSize() const;
+
+ const UDTLayoutBase &getParent() const { return Parent; }
+ StringRef getName() const { return Name; }
+ uint32_t getOffsetInParent() const { return OffsetInParent; }
+ uint32_t getSize() const { return SizeOf; }
+ const PDBSymbol &getSymbol() const { return Symbol; }
+
+protected:
+ const UDTLayoutBase &Parent;
+ const PDBSymbol &Symbol;
+ BitVector UsedBytes;
+ std::string Name;
+ uint32_t OffsetInParent = 0;
+ uint32_t SizeOf = 0;
+};
+
+class DataMemberLayoutItem : public StorageItemBase {
+public:
+ DataMemberLayoutItem(const UDTLayoutBase &Parent,
+ std::unique_ptr<PDBSymbolData> DataMember);
+
+ virtual uint32_t deepPaddingSize() const;
+
+ const PDBSymbolData &getDataMember();
+ bool hasUDTLayout() const;
+ const ClassLayout &getUDTLayout() const;
+
+private:
+ std::unique_ptr<PDBSymbolData> DataMember;
+ std::unique_ptr<ClassLayout> UdtLayout;
+};
+
+class VTableLayoutItem : public StorageItemBase {
+public:
+ VTableLayoutItem(const UDTLayoutBase &Parent,
+ std::unique_ptr<PDBSymbolTypeVTable> VTable);
+ ArrayRef<PDBSymbolFunc *> funcs() const { return VTableFuncs; }
+
+ uint32_t getElementSize() const { return ElementSize; }
+
+ void setFunction(uint32_t Index, PDBSymbolFunc &Func) {
+ VTableFuncs[Index] = &Func;
+ }
+
+private:
+ uint32_t ElementSize = 0;
+ std::unique_ptr<PDBSymbolTypeVTableShape> Shape;
+ std::unique_ptr<PDBSymbolTypeVTable> VTable;
+ std::vector<PDBSymbolFunc *> VTableFuncs;
+};
+
+class UDTLayoutBase {
+ template <typename T> using UniquePtrVector = std::vector<std::unique_ptr<T>>;
+
+public:
+ UDTLayoutBase(const PDBSymbol &Symbol, const std::string &Name,
+ uint32_t Size);
+
+ uint32_t shallowPaddingSize() const;
+ uint32_t deepPaddingSize() const;
+
+ const BitVector &usedBytes() const { return UsedBytes; }
+
+ uint32_t getClassSize() const { return SizeOf; }
+
+ ArrayRef<std::unique_ptr<StorageItemBase>> layout_items() const {
+ return ChildStorage;
+ }
+
+ VTableLayoutItem *findVTableAtOffset(uint32_t RelativeOffset);
+
+ StringRef getUDTName() const { return Name; }
+
+ ArrayRef<BaseClassLayout *> bases() const { return BaseClasses; }
+ ArrayRef<std::unique_ptr<PDBSymbolTypeBaseClass>> vbases() const {
+ return VirtualBases;
+ }
+
+ ArrayRef<std::unique_ptr<PDBSymbolFunc>> funcs() const { return Funcs; }
+
+ ArrayRef<std::unique_ptr<PDBSymbol>> other_items() const { return Other; }
+
+ const PDBSymbol &getSymbolBase() const { return SymbolBase; }
+
+protected:
+ void initializeChildren(const PDBSymbol &Sym);
+
+ void addChildToLayout(std::unique_ptr<StorageItemBase> Child);
+ void addVirtualOverride(PDBSymbolFunc &Func);
+ void addVirtualIntro(PDBSymbolFunc &Func);
+
+ const PDBSymbol &SymbolBase;
+ std::string Name;
+ uint32_t SizeOf = 0;
+
+ BitVector UsedBytes;
+ UniquePtrVector<PDBSymbol> Other;
+ UniquePtrVector<PDBSymbolFunc> Funcs;
+ UniquePtrVector<PDBSymbolTypeBaseClass> VirtualBases;
+ UniquePtrVector<StorageItemBase> ChildStorage;
+ std::vector<std::list<StorageItemBase *>> ChildrenPerByte;
+ std::vector<BaseClassLayout *> BaseClasses;
+ VTableLayoutItem *VTable = nullptr;
+};
+
+class ClassLayout : public UDTLayoutBase {
+public:
+ explicit ClassLayout(const PDBSymbolTypeUDT &UDT);
+ explicit ClassLayout(std::unique_ptr<PDBSymbolTypeUDT> UDT);
+
+ ClassLayout(ClassLayout &&Other) = default;
+
+ const PDBSymbolTypeUDT &getClass() const { return UDT; }
+
+private:
+ std::unique_ptr<PDBSymbolTypeUDT> OwnedStorage;
+ const PDBSymbolTypeUDT &UDT;
+};
+
+class BaseClassLayout : public UDTLayoutBase, public StorageItemBase {
+public:
+ BaseClassLayout(const UDTLayoutBase &Parent,
+ std::unique_ptr<PDBSymbolTypeBaseClass> Base);
+
+ const PDBSymbolTypeBaseClass &getBase() const { return *Base; }
+ bool isVirtualBase() const { return IsVirtualBase; }
+
+private:
+ std::unique_ptr<PDBSymbolTypeBaseClass> Base;
+ bool IsVirtualBase;
+};
+}
+} // namespace llvm
+
+#endif // LLVM_DEBUGINFO_PDB_UDTLAYOUT_H
diff --git a/include/llvm/DebugInfo/Symbolize/DIPrinter.h b/include/llvm/DebugInfo/Symbolize/DIPrinter.h
index 49f86eae01cf..ab82be3706d8 100644
--- a/include/llvm/DebugInfo/Symbolize/DIPrinter.h
+++ b/include/llvm/DebugInfo/Symbolize/DIPrinter.h
@@ -29,15 +29,18 @@ class DIPrinter {
bool PrintFunctionNames;
bool PrintPretty;
int PrintSourceContext;
+ bool Verbose;
void print(const DILineInfo &Info, bool Inlined);
void printContext(const std::string &FileName, int64_t Line);
public:
DIPrinter(raw_ostream &OS, bool PrintFunctionNames = true,
- bool PrintPretty = false, int PrintSourceContext = 0)
+ bool PrintPretty = false, int PrintSourceContext = 0,
+ bool Verbose = false)
: OS(OS), PrintFunctionNames(PrintFunctionNames),
- PrintPretty(PrintPretty), PrintSourceContext(PrintSourceContext) {}
+ PrintPretty(PrintPretty), PrintSourceContext(PrintSourceContext),
+ Verbose(Verbose) {}
DIPrinter &operator<<(const DILineInfo &Info);
DIPrinter &operator<<(const DIInliningInfo &Info);
diff --git a/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h b/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h
index aa096478cd9e..7e7f7358938a 100644
--- a/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h
+++ b/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h
@@ -376,7 +376,7 @@ private:
// Initializers may refer to functions declared (but not defined) in this
// module. Build a materializer to clone decls on demand.
auto Materializer = createLambdaMaterializer(
- [this, &LD, &GVsM](Value *V) -> Value* {
+ [&LD, &GVsM](Value *V) -> Value* {
if (auto *F = dyn_cast<Function>(V)) {
// Decls in the original module just get cloned.
if (F->isDeclaration())
@@ -419,7 +419,7 @@ private:
// Build a resolver for the globals module and add it to the base layer.
auto GVsResolver = createLambdaResolver(
- [this, &LD, LMId](const std::string &Name) {
+ [this, &LD](const std::string &Name) {
if (auto Sym = LD.StubsMgr->findStub(Name, false))
return Sym;
if (auto Sym = LD.findSymbol(BaseLayer, Name, false))
@@ -499,8 +499,8 @@ private:
M->setDataLayout(SrcM.getDataLayout());
ValueToValueMapTy VMap;
- auto Materializer = createLambdaMaterializer([this, &LD, &LMId, &M,
- &VMap](Value *V) -> Value * {
+ auto Materializer = createLambdaMaterializer([&LD, &LMId,
+ &M](Value *V) -> Value * {
if (auto *GV = dyn_cast<GlobalVariable>(V))
return cloneGlobalVariableDecl(*M, *GV);
@@ -546,12 +546,12 @@ private:
// Create memory manager and symbol resolver.
auto Resolver = createLambdaResolver(
- [this, &LD, LMId](const std::string &Name) {
+ [this, &LD](const std::string &Name) {
if (auto Sym = LD.findSymbol(BaseLayer, Name, false))
return Sym;
return LD.ExternalSymbolResolver->findSymbolInLogicalDylib(Name);
},
- [this, &LD](const std::string &Name) {
+ [&LD](const std::string &Name) {
return LD.ExternalSymbolResolver->findSymbol(Name);
});
diff --git a/include/llvm/ExecutionEngine/Orc/OrcError.h b/include/llvm/ExecutionEngine/Orc/OrcError.h
index b74988cce2fb..cbb40fad0223 100644
--- a/include/llvm/ExecutionEngine/Orc/OrcError.h
+++ b/include/llvm/ExecutionEngine/Orc/OrcError.h
@@ -27,13 +27,15 @@ enum class OrcErrorCode : int {
RemoteMProtectAddrUnrecognized,
RemoteIndirectStubsOwnerDoesNotExist,
RemoteIndirectStubsOwnerIdAlreadyInUse,
+ RPCConnectionClosed,
+ RPCCouldNotNegotiateFunction,
RPCResponseAbandoned,
UnexpectedRPCCall,
UnexpectedRPCResponse,
- UnknownRPCFunction
+ UnknownErrorCodeFromRemote
};
-Error orcError(OrcErrorCode ErrCode);
+std::error_code orcError(OrcErrorCode ErrCode);
} // End namespace orc.
} // End namespace llvm.
diff --git a/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h b/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h
index 8647db56cd2f..02f59d6a831a 100644
--- a/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h
+++ b/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h
@@ -18,6 +18,7 @@
#include "IndirectionUtils.h"
#include "OrcRemoteTargetRPCAPI.h"
+#include "llvm/ExecutionEngine/RuntimeDyld.h"
#include <system_error>
#define DEBUG_TYPE "orc-remote"
diff --git a/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h b/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h
index 506330fe3a5e..a61ff102be0b 100644
--- a/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h
+++ b/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h
@@ -132,7 +132,7 @@ private:
Error setProtections(void *block, unsigned Flags) {
auto I = Allocs.find(block);
if (I == Allocs.end())
- return orcError(OrcErrorCode::RemoteMProtectAddrUnrecognized);
+ return errorCodeToError(orcError(OrcErrorCode::RemoteMProtectAddrUnrecognized));
return errorCodeToError(
sys::Memory::protectMappedMemory(I->second, Flags));
}
@@ -198,7 +198,8 @@ private:
Error handleCreateRemoteAllocator(ResourceIdMgr::ResourceId Id) {
auto I = Allocators.find(Id);
if (I != Allocators.end())
- return orcError(OrcErrorCode::RemoteAllocatorIdAlreadyInUse);
+ return errorCodeToError(
+ orcError(OrcErrorCode::RemoteAllocatorIdAlreadyInUse));
DEBUG(dbgs() << " Created allocator " << Id << "\n");
Allocators[Id] = Allocator();
return Error::success();
@@ -207,7 +208,8 @@ private:
Error handleCreateIndirectStubsOwner(ResourceIdMgr::ResourceId Id) {
auto I = IndirectStubsOwners.find(Id);
if (I != IndirectStubsOwners.end())
- return orcError(OrcErrorCode::RemoteIndirectStubsOwnerIdAlreadyInUse);
+ return errorCodeToError(
+ orcError(OrcErrorCode::RemoteIndirectStubsOwnerIdAlreadyInUse));
DEBUG(dbgs() << " Create indirect stubs owner " << Id << "\n");
IndirectStubsOwners[Id] = ISBlockOwnerList();
return Error::success();
@@ -224,7 +226,8 @@ private:
Error handleDestroyRemoteAllocator(ResourceIdMgr::ResourceId Id) {
auto I = Allocators.find(Id);
if (I == Allocators.end())
- return orcError(OrcErrorCode::RemoteAllocatorDoesNotExist);
+ return errorCodeToError(
+ orcError(OrcErrorCode::RemoteAllocatorDoesNotExist));
Allocators.erase(I);
DEBUG(dbgs() << " Destroyed allocator " << Id << "\n");
return Error::success();
@@ -233,7 +236,8 @@ private:
Error handleDestroyIndirectStubsOwner(ResourceIdMgr::ResourceId Id) {
auto I = IndirectStubsOwners.find(Id);
if (I == IndirectStubsOwners.end())
- return orcError(OrcErrorCode::RemoteIndirectStubsOwnerDoesNotExist);
+ return errorCodeToError(
+ orcError(OrcErrorCode::RemoteIndirectStubsOwnerDoesNotExist));
IndirectStubsOwners.erase(I);
return Error::success();
}
@@ -246,7 +250,8 @@ private:
auto StubOwnerItr = IndirectStubsOwners.find(Id);
if (StubOwnerItr == IndirectStubsOwners.end())
- return orcError(OrcErrorCode::RemoteIndirectStubsOwnerDoesNotExist);
+ return errorCodeToError(
+ orcError(OrcErrorCode::RemoteIndirectStubsOwnerDoesNotExist));
typename TargetT::IndirectStubsInfo IS;
if (auto Err =
@@ -361,7 +366,8 @@ private:
uint64_t Size, uint32_t Align) {
auto I = Allocators.find(Id);
if (I == Allocators.end())
- return orcError(OrcErrorCode::RemoteAllocatorDoesNotExist);
+ return errorCodeToError(
+ orcError(OrcErrorCode::RemoteAllocatorDoesNotExist));
auto &Allocator = I->second;
void *LocalAllocAddr = nullptr;
if (auto Err = Allocator.allocate(LocalAllocAddr, Size, Align))
@@ -380,7 +386,8 @@ private:
JITTargetAddress Addr, uint32_t Flags) {
auto I = Allocators.find(Id);
if (I == Allocators.end())
- return orcError(OrcErrorCode::RemoteAllocatorDoesNotExist);
+ return errorCodeToError(
+ orcError(OrcErrorCode::RemoteAllocatorDoesNotExist));
auto &Allocator = I->second;
void *LocalAddr = reinterpret_cast<void *>(static_cast<uintptr_t>(Addr));
DEBUG(dbgs() << " Allocator " << Id << " set permissions on " << LocalAddr
diff --git a/include/llvm/ExecutionEngine/Orc/RPCSerialization.h b/include/llvm/ExecutionEngine/Orc/RPCSerialization.h
index 359a9d81b22b..84a037b2f998 100644
--- a/include/llvm/ExecutionEngine/Orc/RPCSerialization.h
+++ b/include/llvm/ExecutionEngine/Orc/RPCSerialization.h
@@ -12,6 +12,7 @@
#include "OrcError.h"
#include "llvm/Support/thread.h"
+#include <map>
#include <mutex>
#include <sstream>
@@ -114,6 +115,35 @@ public:
static const char* getName() { return "std::string"; }
};
+template <>
+class RPCTypeName<Error> {
+public:
+ static const char* getName() { return "Error"; }
+};
+
+template <typename T>
+class RPCTypeName<Expected<T>> {
+public:
+ static const char* getName() {
+ std::lock_guard<std::mutex> Lock(NameMutex);
+ if (Name.empty())
+ raw_string_ostream(Name) << "Expected<"
+ << RPCTypeNameSequence<T>()
+ << ">";
+ return Name.data();
+ }
+
+private:
+ static std::mutex NameMutex;
+ static std::string Name;
+};
+
+template <typename T>
+std::mutex RPCTypeName<Expected<T>>::NameMutex;
+
+template <typename T>
+std::string RPCTypeName<Expected<T>>::Name;
+
template <typename T1, typename T2>
class RPCTypeName<std::pair<T1, T2>> {
public:
@@ -243,8 +273,10 @@ class SequenceSerialization<ChannelT, ArgT> {
public:
template <typename CArgT>
- static Error serialize(ChannelT &C, const CArgT &CArg) {
- return SerializationTraits<ChannelT, ArgT, CArgT>::serialize(C, CArg);
+ static Error serialize(ChannelT &C, CArgT &&CArg) {
+ return SerializationTraits<ChannelT, ArgT,
+ typename std::decay<CArgT>::type>::
+ serialize(C, std::forward<CArgT>(CArg));
}
template <typename CArgT>
@@ -258,19 +290,21 @@ class SequenceSerialization<ChannelT, ArgT, ArgTs...> {
public:
template <typename CArgT, typename... CArgTs>
- static Error serialize(ChannelT &C, const CArgT &CArg,
- const CArgTs&... CArgs) {
+ static Error serialize(ChannelT &C, CArgT &&CArg,
+ CArgTs &&... CArgs) {
if (auto Err =
- SerializationTraits<ChannelT, ArgT, CArgT>::serialize(C, CArg))
+ SerializationTraits<ChannelT, ArgT, typename std::decay<CArgT>::type>::
+ serialize(C, std::forward<CArgT>(CArg)))
return Err;
if (auto Err = SequenceTraits<ChannelT>::emitSeparator(C))
return Err;
- return SequenceSerialization<ChannelT, ArgTs...>::serialize(C, CArgs...);
+ return SequenceSerialization<ChannelT, ArgTs...>::
+ serialize(C, std::forward<CArgTs>(CArgs)...);
}
template <typename CArgT, typename... CArgTs>
static Error deserialize(ChannelT &C, CArgT &CArg,
- CArgTs&... CArgs) {
+ CArgTs &... CArgs) {
if (auto Err =
SerializationTraits<ChannelT, ArgT, CArgT>::deserialize(C, CArg))
return Err;
@@ -281,8 +315,9 @@ public:
};
template <typename ChannelT, typename... ArgTs>
-Error serializeSeq(ChannelT &C, const ArgTs &... Args) {
- return SequenceSerialization<ChannelT, ArgTs...>::serialize(C, Args...);
+Error serializeSeq(ChannelT &C, ArgTs &&... Args) {
+ return SequenceSerialization<ChannelT, typename std::decay<ArgTs>::type...>::
+ serialize(C, std::forward<ArgTs>(Args)...);
}
template <typename ChannelT, typename... ArgTs>
@@ -290,6 +325,196 @@ Error deserializeSeq(ChannelT &C, ArgTs &... Args) {
return SequenceSerialization<ChannelT, ArgTs...>::deserialize(C, Args...);
}
+template <typename ChannelT>
+class SerializationTraits<ChannelT, Error> {
+public:
+
+ using WrappedErrorSerializer =
+ std::function<Error(ChannelT &C, const ErrorInfoBase&)>;
+
+ using WrappedErrorDeserializer =
+ std::function<Error(ChannelT &C, Error &Err)>;
+
+ template <typename ErrorInfoT, typename SerializeFtor,
+ typename DeserializeFtor>
+ static void registerErrorType(std::string Name, SerializeFtor Serialize,
+ DeserializeFtor Deserialize) {
+ assert(!Name.empty() &&
+ "The empty string is reserved for the Success value");
+
+ const std::string *KeyName = nullptr;
+ {
+ // We're abusing the stability of std::map here: We take a reference to the
+ // key of the deserializers map to save us from duplicating the string in
+ // the serializer. This should be changed to use a stringpool if we switch
+ // to a map type that may move keys in memory.
+ std::lock_guard<std::mutex> Lock(DeserializersMutex);
+ auto I =
+ Deserializers.insert(Deserializers.begin(),
+ std::make_pair(std::move(Name),
+ std::move(Deserialize)));
+ KeyName = &I->first;
+ }
+
+ {
+ assert(KeyName != nullptr && "No keyname pointer");
+ std::lock_guard<std::mutex> Lock(SerializersMutex);
+ // FIXME: Move capture Serialize once we have C++14.
+ Serializers[ErrorInfoT::classID()] =
+ [KeyName, Serialize](ChannelT &C, const ErrorInfoBase &EIB) -> Error {
+ assert(EIB.dynamicClassID() == ErrorInfoT::classID() &&
+ "Serializer called for wrong error type");
+ if (auto Err = serializeSeq(C, *KeyName))
+ return Err;
+ return Serialize(C, static_cast<const ErrorInfoT&>(EIB));
+ };
+ }
+ }
+
+ static Error serialize(ChannelT &C, Error &&Err) {
+ std::lock_guard<std::mutex> Lock(SerializersMutex);
+ if (!Err)
+ return serializeSeq(C, std::string());
+
+ return handleErrors(std::move(Err),
+ [&C](const ErrorInfoBase &EIB) {
+ auto SI = Serializers.find(EIB.dynamicClassID());
+ if (SI == Serializers.end())
+ return serializeAsStringError(C, EIB);
+ return (SI->second)(C, EIB);
+ });
+ }
+
+ static Error deserialize(ChannelT &C, Error &Err) {
+ std::lock_guard<std::mutex> Lock(DeserializersMutex);
+
+ std::string Key;
+ if (auto Err = deserializeSeq(C, Key))
+ return Err;
+
+ if (Key.empty()) {
+ ErrorAsOutParameter EAO(&Err);
+ Err = Error::success();
+ return Error::success();
+ }
+
+ auto DI = Deserializers.find(Key);
+ assert(DI != Deserializers.end() && "No deserializer for error type");
+ return (DI->second)(C, Err);
+ }
+
+private:
+
+ static Error serializeAsStringError(ChannelT &C, const ErrorInfoBase &EIB) {
+ assert(EIB.dynamicClassID() != StringError::classID() &&
+ "StringError serialization not registered");
+ std::string ErrMsg;
+ {
+ raw_string_ostream ErrMsgStream(ErrMsg);
+ EIB.log(ErrMsgStream);
+ }
+ return serialize(C, make_error<StringError>(std::move(ErrMsg),
+ inconvertibleErrorCode()));
+ }
+
+ static std::mutex SerializersMutex;
+ static std::mutex DeserializersMutex;
+ static std::map<const void*, WrappedErrorSerializer> Serializers;
+ static std::map<std::string, WrappedErrorDeserializer> Deserializers;
+};
+
+template <typename ChannelT>
+std::mutex SerializationTraits<ChannelT, Error>::SerializersMutex;
+
+template <typename ChannelT>
+std::mutex SerializationTraits<ChannelT, Error>::DeserializersMutex;
+
+template <typename ChannelT>
+std::map<const void*,
+ typename SerializationTraits<ChannelT, Error>::WrappedErrorSerializer>
+SerializationTraits<ChannelT, Error>::Serializers;
+
+template <typename ChannelT>
+std::map<std::string,
+ typename SerializationTraits<ChannelT, Error>::WrappedErrorDeserializer>
+SerializationTraits<ChannelT, Error>::Deserializers;
+
+template <typename ChannelT>
+void registerStringError() {
+ static bool AlreadyRegistered = false;
+ if (!AlreadyRegistered) {
+ SerializationTraits<ChannelT, Error>::
+ template registerErrorType<StringError>(
+ "StringError",
+ [](ChannelT &C, const StringError &SE) {
+ return serializeSeq(C, SE.getMessage());
+ },
+ [](ChannelT &C, Error &Err) {
+ ErrorAsOutParameter EAO(&Err);
+ std::string Msg;
+ if (auto E2 = deserializeSeq(C, Msg))
+ return E2;
+ Err =
+ make_error<StringError>(std::move(Msg),
+ orcError(
+ OrcErrorCode::UnknownErrorCodeFromRemote));
+ return Error::success();
+ });
+ AlreadyRegistered = true;
+ }
+}
+
+/// SerializationTraits for Expected<T1> from an Expected<T2>.
+template <typename ChannelT, typename T1, typename T2>
+class SerializationTraits<ChannelT, Expected<T1>, Expected<T2>> {
+public:
+
+ static Error serialize(ChannelT &C, Expected<T2> &&ValOrErr) {
+ if (ValOrErr) {
+ if (auto Err = serializeSeq(C, true))
+ return Err;
+ return SerializationTraits<ChannelT, T1, T2>::serialize(C, *ValOrErr);
+ }
+ if (auto Err = serializeSeq(C, false))
+ return Err;
+ return serializeSeq(C, ValOrErr.takeError());
+ }
+
+ static Error deserialize(ChannelT &C, Expected<T2> &ValOrErr) {
+ ExpectedAsOutParameter<T2> EAO(&ValOrErr);
+ bool HasValue;
+ if (auto Err = deserializeSeq(C, HasValue))
+ return Err;
+ if (HasValue)
+ return SerializationTraits<ChannelT, T1, T2>::deserialize(C, *ValOrErr);
+ Error Err = Error::success();
+ if (auto E2 = deserializeSeq(C, Err))
+ return E2;
+ ValOrErr = std::move(Err);
+ return Error::success();
+ }
+};
+
+/// SerializationTraits for Expected<T1> from a T2.
+template <typename ChannelT, typename T1, typename T2>
+class SerializationTraits<ChannelT, Expected<T1>, T2> {
+public:
+
+ static Error serialize(ChannelT &C, T2 &&Val) {
+ return serializeSeq(C, Expected<T2>(std::forward<T2>(Val)));
+ }
+};
+
+/// SerializationTraits for Expected<T1> from an Error.
+template <typename ChannelT, typename T>
+class SerializationTraits<ChannelT, Expected<T>, Error> {
+public:
+
+ static Error serialize(ChannelT &C, Error &&Err) {
+ return serializeSeq(C, Expected<T>(std::move(Err)));
+ }
+};
+
/// SerializationTraits default specialization for std::pair.
template <typename ChannelT, typename T1, typename T2>
class SerializationTraits<ChannelT, std::pair<T1, T2>> {
diff --git a/include/llvm/ExecutionEngine/Orc/RPCUtils.h b/include/llvm/ExecutionEngine/Orc/RPCUtils.h
index 37e2e66e5af4..6212f64ff319 100644
--- a/include/llvm/ExecutionEngine/Orc/RPCUtils.h
+++ b/include/llvm/ExecutionEngine/Orc/RPCUtils.h
@@ -26,27 +26,115 @@
#include "llvm/ExecutionEngine/Orc/OrcError.h"
#include "llvm/ExecutionEngine/Orc/RPCSerialization.h"
-#ifdef _MSC_VER
-// concrt.h depends on eh.h for __uncaught_exception declaration
-// even if we disable exceptions.
-#include <eh.h>
-
-// Disable warnings from ppltasks.h transitively included by <future>.
-#pragma warning(push)
-#pragma warning(disable : 4530)
-#pragma warning(disable : 4062)
-#endif
-
#include <future>
-#ifdef _MSC_VER
-#pragma warning(pop)
-#endif
-
namespace llvm {
namespace orc {
namespace rpc {
+/// Base class of all fatal RPC errors (those that necessarily result in the
+/// termination of the RPC session).
+class RPCFatalError : public ErrorInfo<RPCFatalError> {
+public:
+ static char ID;
+};
+
+/// RPCConnectionClosed is returned from RPC operations if the RPC connection
+/// has already been closed due to either an error or graceful disconnection.
+class ConnectionClosed : public ErrorInfo<ConnectionClosed> {
+public:
+ static char ID;
+ std::error_code convertToErrorCode() const override;
+ void log(raw_ostream &OS) const override;
+};
+
+/// BadFunctionCall is returned from handleOne when the remote makes a call with
+/// an unrecognized function id.
+///
+/// This error is fatal because Orc RPC needs to know how to parse a function
+/// call to know where the next call starts, and if it doesn't recognize the
+/// function id it cannot parse the call.
+template <typename FnIdT, typename SeqNoT>
+class BadFunctionCall
+ : public ErrorInfo<BadFunctionCall<FnIdT, SeqNoT>, RPCFatalError> {
+public:
+ static char ID;
+
+ BadFunctionCall(FnIdT FnId, SeqNoT SeqNo)
+ : FnId(std::move(FnId)), SeqNo(std::move(SeqNo)) {}
+
+ std::error_code convertToErrorCode() const override {
+ return orcError(OrcErrorCode::UnexpectedRPCCall);
+ }
+
+ void log(raw_ostream &OS) const override {
+ OS << "Call to invalid RPC function id '" << FnId << "' with "
+ "sequence number " << SeqNo;
+ }
+
+private:
+ FnIdT FnId;
+ SeqNoT SeqNo;
+};
+
+template <typename FnIdT, typename SeqNoT>
+char BadFunctionCall<FnIdT, SeqNoT>::ID = 0;
+
+/// InvalidSequenceNumberForResponse is returned from handleOne when a response
+/// call arrives with a sequence number that doesn't correspond to any in-flight
+/// function call.
+///
+/// This error is fatal because Orc RPC needs to know how to parse the rest of
+/// the response call to know where the next call starts, and if it doesn't have
+/// a result parser for this sequence number it can't do that.
+template <typename SeqNoT>
+class InvalidSequenceNumberForResponse
+ : public ErrorInfo<InvalidSequenceNumberForResponse<SeqNoT>, RPCFatalError> {
+public:
+ static char ID;
+
+ InvalidSequenceNumberForResponse(SeqNoT SeqNo)
+ : SeqNo(std::move(SeqNo)) {}
+
+ std::error_code convertToErrorCode() const override {
+ return orcError(OrcErrorCode::UnexpectedRPCCall);
+ };
+
+ void log(raw_ostream &OS) const override {
+ OS << "Response has unknown sequence number " << SeqNo;
+ }
+private:
+ SeqNoT SeqNo;
+};
+
+template <typename SeqNoT>
+char InvalidSequenceNumberForResponse<SeqNoT>::ID = 0;
+
+/// This non-fatal error will be passed to asynchronous result handlers in place
+/// of a result if the connection goes down before a result returns, or if the
+/// function to be called cannot be negotiated with the remote.
+class ResponseAbandoned : public ErrorInfo<ResponseAbandoned> {
+public:
+ static char ID;
+
+ std::error_code convertToErrorCode() const override;
+ void log(raw_ostream &OS) const override;
+};
+
+/// This error is returned if the remote does not have a handler installed for
+/// the given RPC function.
+class CouldNotNegotiate : public ErrorInfo<CouldNotNegotiate> {
+public:
+ static char ID;
+
+ CouldNotNegotiate(std::string Signature);
+ std::error_code convertToErrorCode() const override;
+ void log(raw_ostream &OS) const override;
+ const std::string &getSignature() const { return Signature; }
+private:
+ std::string Signature;
+};
+
template <typename DerivedFunc, typename FnT> class Function;
// RPC Function class.
@@ -82,16 +170,6 @@ std::mutex Function<DerivedFunc, RetT(ArgTs...)>::NameMutex;
template <typename DerivedFunc, typename RetT, typename... ArgTs>
std::string Function<DerivedFunc, RetT(ArgTs...)>::Name;
-/// Provides a typedef for a tuple containing the decayed argument types.
-template <typename T> class FunctionArgsTuple;
-
-template <typename RetT, typename... ArgTs>
-class FunctionArgsTuple<RetT(ArgTs...)> {
-public:
- using Type = std::tuple<typename std::decay<
- typename std::remove_reference<ArgTs>::type>::type...>;
-};
-
/// Allocates RPC function ids during autonegotiation.
/// Specializations of this class must provide four members:
///
@@ -196,6 +274,16 @@ public:
#endif // _MSC_VER
+/// Provides a typedef for a tuple containing the decayed argument types.
+template <typename T> class FunctionArgsTuple;
+
+template <typename RetT, typename... ArgTs>
+class FunctionArgsTuple<RetT(ArgTs...)> {
+public:
+ using Type = std::tuple<typename std::decay<
+ typename std::remove_reference<ArgTs>::type>::type...>;
+};
+
// ResultTraits provides typedefs and utilities specific to the return type
// of functions.
template <typename RetT> class ResultTraits {
@@ -274,43 +362,132 @@ template <> class ResultTraits<Error> : public ResultTraits<void> {};
template <typename RetT>
class ResultTraits<Expected<RetT>> : public ResultTraits<RetT> {};
+// Determines whether an RPC function's defined error return type supports
+// error return value.
+template <typename T>
+class SupportsErrorReturn {
+public:
+ static const bool value = false;
+};
+
+template <>
+class SupportsErrorReturn<Error> {
+public:
+ static const bool value = true;
+};
+
+template <typename T>
+class SupportsErrorReturn<Expected<T>> {
+public:
+ static const bool value = true;
+};
+
+// RespondHelper packages return values based on whether or not the declared
+// RPC function return type supports error returns.
+template <bool FuncSupportsErrorReturn>
+class RespondHelper;
+
+// RespondHelper specialization for functions that support error returns.
+template <>
+class RespondHelper<true> {
+public:
+
+ // Send Expected<T>.
+ template <typename WireRetT, typename HandlerRetT, typename ChannelT,
+ typename FunctionIdT, typename SequenceNumberT>
+ static Error sendResult(ChannelT &C, const FunctionIdT &ResponseId,
+ SequenceNumberT SeqNo,
+ Expected<HandlerRetT> ResultOrErr) {
+ if (!ResultOrErr && ResultOrErr.template errorIsA<RPCFatalError>())
+ return ResultOrErr.takeError();
+
+ // Open the response message.
+ if (auto Err = C.startSendMessage(ResponseId, SeqNo))
+ return Err;
+
+ // Serialize the result.
+ if (auto Err =
+ SerializationTraits<ChannelT, WireRetT,
+ Expected<HandlerRetT>>::serialize(
+ C, std::move(ResultOrErr)))
+ return Err;
+
+ // Close the response message.
+ return C.endSendMessage();
+ }
+
+ template <typename ChannelT, typename FunctionIdT, typename SequenceNumberT>
+ static Error sendResult(ChannelT &C, const FunctionIdT &ResponseId,
+ SequenceNumberT SeqNo, Error Err) {
+ if (Err && Err.isA<RPCFatalError>())
+ return Err;
+ if (auto Err2 = C.startSendMessage(ResponseId, SeqNo))
+ return Err2;
+ if (auto Err2 = serializeSeq(C, std::move(Err)))
+ return Err2;
+ return C.endSendMessage();
+ }
+
+};
+
+// RespondHelper specialization for functions that do not support error returns.
+template <>
+class RespondHelper<false> {
+public:
+
+ template <typename WireRetT, typename HandlerRetT, typename ChannelT,
+ typename FunctionIdT, typename SequenceNumberT>
+ static Error sendResult(ChannelT &C, const FunctionIdT &ResponseId,
+ SequenceNumberT SeqNo,
+ Expected<HandlerRetT> ResultOrErr) {
+ if (auto Err = ResultOrErr.takeError())
+ return Err;
+
+ // Open the response message.
+ if (auto Err = C.startSendMessage(ResponseId, SeqNo))
+ return Err;
+
+ // Serialize the result.
+ if (auto Err =
+ SerializationTraits<ChannelT, WireRetT, HandlerRetT>::serialize(
+ C, *ResultOrErr))
+ return Err;
+
+ // Close the response message.
+ return C.endSendMessage();
+ }
+
+ template <typename ChannelT, typename FunctionIdT, typename SequenceNumberT>
+ static Error sendResult(ChannelT &C, const FunctionIdT &ResponseId,
+ SequenceNumberT SeqNo, Error Err) {
+ if (Err)
+ return Err;
+ if (auto Err2 = C.startSendMessage(ResponseId, SeqNo))
+ return Err2;
+ return C.endSendMessage();
+ }
+
+};
+
+
// Send a response of the given wire return type (WireRetT) over the
// channel, with the given sequence number.
template <typename WireRetT, typename HandlerRetT, typename ChannelT,
typename FunctionIdT, typename SequenceNumberT>
-static Error respond(ChannelT &C, const FunctionIdT &ResponseId,
- SequenceNumberT SeqNo, Expected<HandlerRetT> ResultOrErr) {
- // If this was an error bail out.
- // FIXME: Send an "error" message to the client if this is not a channel
- // failure?
- if (auto Err = ResultOrErr.takeError())
- return Err;
-
- // Open the response message.
- if (auto Err = C.startSendMessage(ResponseId, SeqNo))
- return Err;
-
- // Serialize the result.
- if (auto Err =
- SerializationTraits<ChannelT, WireRetT, HandlerRetT>::serialize(
- C, *ResultOrErr))
- return Err;
-
- // Close the response message.
- return C.endSendMessage();
+Error respond(ChannelT &C, const FunctionIdT &ResponseId,
+ SequenceNumberT SeqNo, Expected<HandlerRetT> ResultOrErr) {
+ return RespondHelper<SupportsErrorReturn<WireRetT>::value>::
+ template sendResult<WireRetT>(C, ResponseId, SeqNo, std::move(ResultOrErr));
}
// Send an empty response message on the given channel to indicate that
// the handler ran.
template <typename WireRetT, typename ChannelT, typename FunctionIdT,
typename SequenceNumberT>
-static Error respond(ChannelT &C, const FunctionIdT &ResponseId,
- SequenceNumberT SeqNo, Error Err) {
- if (Err)
- return Err;
- if (auto Err2 = C.startSendMessage(ResponseId, SeqNo))
- return Err2;
- return C.endSendMessage();
+Error respond(ChannelT &C, const FunctionIdT &ResponseId, SequenceNumberT SeqNo,
+ Error Err) {
+ return RespondHelper<SupportsErrorReturn<WireRetT>::value>::
+ sendResult(C, ResponseId, SeqNo, std::move(Err));
}
// Converts a given type to the equivalent error return type.
@@ -339,6 +516,29 @@ public:
using Type = Error;
};
+// Traits class that strips the response function from the list of handler
+// arguments.
+template <typename FnT> class AsyncHandlerTraits;
+
+template <typename ResultT, typename... ArgTs>
+class AsyncHandlerTraits<Error(std::function<Error(Expected<ResultT>)>, ArgTs...)> {
+public:
+ using Type = Error(ArgTs...);
+ using ResultType = Expected<ResultT>;
+};
+
+template <typename... ArgTs>
+class AsyncHandlerTraits<Error(std::function<Error(Error)>, ArgTs...)> {
+public:
+ using Type = Error(ArgTs...);
+ using ResultType = Error;
+};
+
+template <typename ResponseHandlerT, typename... ArgTs>
+class AsyncHandlerTraits<Error(ResponseHandlerT, ArgTs...)> :
+ public AsyncHandlerTraits<Error(typename std::decay<ResponseHandlerT>::type,
+ ArgTs...)> {};
+
// This template class provides utilities related to RPC function handlers.
// The base case applies to non-function types (the template class is
// specialized for function types) and inherits from the appropriate
@@ -358,15 +558,20 @@ public:
// Return type of the handler.
using ReturnType = RetT;
- // A std::tuple wrapping the handler arguments.
- using ArgStorage = typename FunctionArgsTuple<RetT(ArgTs...)>::Type;
-
// Call the given handler with the given arguments.
- template <typename HandlerT>
+ template <typename HandlerT, typename... TArgTs>
static typename WrappedHandlerReturn<RetT>::Type
- unpackAndRun(HandlerT &Handler, ArgStorage &Args) {
+ unpackAndRun(HandlerT &Handler, std::tuple<TArgTs...> &Args) {
return unpackAndRunHelper(Handler, Args,
- llvm::index_sequence_for<ArgTs...>());
+ llvm::index_sequence_for<TArgTs...>());
+ }
+
+ // Call the given handler with the given arguments.
+ template <typename HandlerT, typename ResponderT, typename... TArgTs>
+ static Error unpackAndRunAsync(HandlerT &Handler, ResponderT &Responder,
+ std::tuple<TArgTs...> &Args) {
+ return unpackAndRunAsyncHelper(Handler, Responder, Args,
+ llvm::index_sequence_for<TArgTs...>());
}
// Call the given handler with the given arguments.
@@ -379,11 +584,11 @@ public:
return Error::success();
}
- template <typename HandlerT>
+ template <typename HandlerT, typename... TArgTs>
static typename std::enable_if<
!std::is_void<typename HandlerTraits<HandlerT>::ReturnType>::value,
typename HandlerTraits<HandlerT>::ReturnType>::type
- run(HandlerT &Handler, ArgTs... Args) {
+ run(HandlerT &Handler, TArgTs... Args) {
return Handler(std::move(Args)...);
}
@@ -408,15 +613,31 @@ private:
C, std::get<Indexes>(Args)...);
}
- template <typename HandlerT, size_t... Indexes>
+ template <typename HandlerT, typename ArgTuple, size_t... Indexes>
static typename WrappedHandlerReturn<
typename HandlerTraits<HandlerT>::ReturnType>::Type
- unpackAndRunHelper(HandlerT &Handler, ArgStorage &Args,
+ unpackAndRunHelper(HandlerT &Handler, ArgTuple &Args,
llvm::index_sequence<Indexes...>) {
return run(Handler, std::move(std::get<Indexes>(Args))...);
}
+
+
+ template <typename HandlerT, typename ResponderT, typename ArgTuple,
+ size_t... Indexes>
+ static typename WrappedHandlerReturn<
+ typename HandlerTraits<HandlerT>::ReturnType>::Type
+ unpackAndRunAsyncHelper(HandlerT &Handler, ResponderT &Responder,
+ ArgTuple &Args,
+ llvm::index_sequence<Indexes...>) {
+ return run(Handler, Responder, std::move(std::get<Indexes>(Args))...);
+ }
};
+// Handler traits for free functions.
+template <typename RetT, typename... ArgTs>
+class HandlerTraits<RetT(*)(ArgTs...)>
+ : public HandlerTraits<RetT(ArgTs...)> {};
+
// Handler traits for class methods (especially call operators for lambdas).
template <typename Class, typename RetT, typename... ArgTs>
class HandlerTraits<RetT (Class::*)(ArgTs...)>
@@ -471,7 +692,7 @@ public:
// Create an error instance representing an abandoned response.
static Error createAbandonedResponseError() {
- return orcError(OrcErrorCode::RPCResponseAbandoned);
+ return make_error<ResponseAbandoned>();
}
};
@@ -493,7 +714,7 @@ public:
return Err;
if (auto Err = C.endReceiveMessage())
return Err;
- return Handler(Result);
+ return Handler(std::move(Result));
}
// Abandon this response by calling the handler with an 'abandoned response'
@@ -538,6 +759,72 @@ private:
HandlerT Handler;
};
+template <typename ChannelT, typename FuncRetT, typename HandlerT>
+class ResponseHandlerImpl<ChannelT, Expected<FuncRetT>, HandlerT>
+ : public ResponseHandler<ChannelT> {
+public:
+ ResponseHandlerImpl(HandlerT Handler) : Handler(std::move(Handler)) {}
+
+ // Handle the result by deserializing it from the channel then passing it
+ // to the user defined handler.
+ Error handleResponse(ChannelT &C) override {
+ using HandlerArgType = typename ResponseHandlerArg<
+ typename HandlerTraits<HandlerT>::Type>::ArgType;
+ HandlerArgType Result((typename HandlerArgType::value_type()));
+
+ if (auto Err =
+ SerializationTraits<ChannelT, Expected<FuncRetT>,
+ HandlerArgType>::deserialize(C, Result))
+ return Err;
+ if (auto Err = C.endReceiveMessage())
+ return Err;
+ return Handler(std::move(Result));
+ }
+
+ // Abandon this response by calling the handler with an 'abandoned response'
+ // error.
+ void abandon() override {
+ if (auto Err = Handler(this->createAbandonedResponseError())) {
+ // Handlers should not fail when passed an abandoned response error.
+ report_fatal_error(std::move(Err));
+ }
+ }
+
+private:
+ HandlerT Handler;
+};
+
+template <typename ChannelT, typename HandlerT>
+class ResponseHandlerImpl<ChannelT, Error, HandlerT>
+ : public ResponseHandler<ChannelT> {
+public:
+ ResponseHandlerImpl(HandlerT Handler) : Handler(std::move(Handler)) {}
+
+ // Handle the result by deserializing it from the channel then passing it
+ // to the user defined handler.
+ Error handleResponse(ChannelT &C) override {
+ Error Result = Error::success();
+ if (auto Err =
+ SerializationTraits<ChannelT, Error, Error>::deserialize(C, Result))
+ return Err;
+ if (auto Err = C.endReceiveMessage())
+ return Err;
+ return Handler(std::move(Result));
+ }
+
+ // Abandon this response by calling the handler with an 'abandoned response'
+ // error.
+ void abandon() override {
+ if (auto Err = Handler(this->createAbandonedResponseError())) {
+ // Handlers should not fail when passed an abandoned response error.
+ report_fatal_error(std::move(Err));
+ }
+ }
+
+private:
+ HandlerT Handler;
+};
+
// Create a ResponseHandler from a given user handler.
template <typename ChannelT, typename FuncRetT, typename HandlerT>
std::unique_ptr<ResponseHandler<ChannelT>> createResponseHandler(HandlerT H) {
@@ -758,8 +1045,13 @@ public:
auto NegotiateId = FnIdAllocator.getNegotiateId();
RemoteFunctionIds[OrcRPCNegotiate::getPrototype()] = NegotiateId;
Handlers[NegotiateId] = wrapHandler<OrcRPCNegotiate>(
- [this](const std::string &Name) { return handleNegotiate(Name); },
- LaunchPolicy());
+ [this](const std::string &Name) { return handleNegotiate(Name); });
+ }
+
+
+ /// Negotiate a function id for Func with the other end of the channel.
+ template <typename Func> Error negotiateFunction(bool Retry = false) {
+ return getRemoteFunctionId<Func>(true, Retry).takeError();
}
/// Append a call Func, does not call send on the channel.
@@ -777,14 +1069,12 @@ public:
// Look up the function ID.
FunctionIdT FnId;
- if (auto FnIdOrErr = getRemoteFunctionId<Func>())
+ if (auto FnIdOrErr = getRemoteFunctionId<Func>(LazyAutoNegotiation, false))
FnId = *FnIdOrErr;
else {
- // This isn't a channel error so we don't want to abandon other pending
- // responses, but we still need to run the user handler with an error to
- // let them know the call failed.
- if (auto Err = Handler(orcError(OrcErrorCode::UnknownRPCFunction)))
- report_fatal_error(std::move(Err));
+ // Negotiation failed. Notify the handler then return the negotiate-failed
+ // error.
+ cantFail(Handler(make_error<ResponseAbandoned>()));
return FnIdOrErr.takeError();
}
@@ -807,20 +1097,20 @@ public:
// Open the function call message.
if (auto Err = C.startSendMessage(FnId, SeqNo)) {
abandonPendingResponses();
- return joinErrors(std::move(Err), C.endSendMessage());
+ return Err;
}
// Serialize the call arguments.
if (auto Err = detail::HandlerTraits<typename Func::Type>::serializeArgs(
C, Args...)) {
abandonPendingResponses();
- return joinErrors(std::move(Err), C.endSendMessage());
+ return Err;
}
// Close the function call messagee.
if (auto Err = C.endSendMessage()) {
abandonPendingResponses();
- return std::move(Err);
+ return Err;
}
return Error::success();
@@ -839,8 +1129,10 @@ public:
Error handleOne() {
FunctionIdT FnId;
SequenceNumberT SeqNo;
- if (auto Err = C.startReceiveMessage(FnId, SeqNo))
+ if (auto Err = C.startReceiveMessage(FnId, SeqNo)) {
+ abandonPendingResponses();
return Err;
+ }
if (FnId == ResponseId)
return handleResponse(SeqNo);
auto I = Handlers.find(FnId);
@@ -848,7 +1140,8 @@ public:
return I->second(C, SeqNo);
// else: No handler found. Report error to client?
- return orcError(OrcErrorCode::UnexpectedRPCCall);
+ return make_error<BadFunctionCall<FunctionIdT, SequenceNumberT>>(FnId,
+ SeqNo);
}
/// Helper for handling setter procedures - this method returns a functor that
@@ -887,10 +1180,25 @@ public:
SequenceNumberMgr.reset();
}
+ /// Remove the handler for the given function.
+ /// A handler must currently be registered for this function.
+ template <typename Func>
+ void removeHandler() {
+ auto IdItr = LocalFunctionIds.find(Func::getPrototype());
+ assert(IdItr != LocalFunctionIds.end() &&
+ "Function does not have a registered handler");
+ auto HandlerItr = Handlers.find(IdItr->second);
+ assert(HandlerItr != Handlers.end() &&
+ "Function does not have a registered handler");
+ Handlers.erase(HandlerItr);
+ }
+
+ /// Clear all handlers.
+ void clearHandlers() {
+ Handlers.clear();
+ }
+
protected:
- // The LaunchPolicy type allows a launch policy to be specified when adding
- // a function handler. See addHandlerImpl.
- using LaunchPolicy = std::function<Error(std::function<Error()>)>;
FunctionIdT getInvalidFunctionId() const {
return FnIdAllocator.getInvalidId();
@@ -899,7 +1207,7 @@ protected:
/// Add the given handler to the handler map and make it available for
/// autonegotiation and execution.
template <typename Func, typename HandlerT>
- void addHandlerImpl(HandlerT Handler, LaunchPolicy Launch) {
+ void addHandlerImpl(HandlerT Handler) {
static_assert(detail::RPCArgTypeCheck<
CanDeserializeCheck, typename Func::Type,
@@ -908,8 +1216,22 @@ protected:
FunctionIdT NewFnId = FnIdAllocator.template allocate<Func>();
LocalFunctionIds[Func::getPrototype()] = NewFnId;
- Handlers[NewFnId] =
- wrapHandler<Func>(std::move(Handler), std::move(Launch));
+ Handlers[NewFnId] = wrapHandler<Func>(std::move(Handler));
+ }
+
+ template <typename Func, typename HandlerT>
+ void addAsyncHandlerImpl(HandlerT Handler) {
+
+ static_assert(detail::RPCArgTypeCheck<
+ CanDeserializeCheck, typename Func::Type,
+ typename detail::AsyncHandlerTraits<
+ typename detail::HandlerTraits<HandlerT>::Type
+ >::Type>::value,
+ "");
+
+ FunctionIdT NewFnId = FnIdAllocator.template allocate<Func>();
+ LocalFunctionIds[Func::getPrototype()] = NewFnId;
+ Handlers[NewFnId] = wrapAsyncHandler<Func>(std::move(Handler));
}
Error handleResponse(SequenceNumberT SeqNo) {
@@ -929,7 +1251,8 @@ protected:
// Unlock the pending results map to prevent recursive lock.
Lock.unlock();
abandonPendingResponses();
- return orcError(OrcErrorCode::UnexpectedRPCResponse);
+ return make_error<
+ InvalidSequenceNumberForResponse<SequenceNumberT>>(SeqNo);
}
}
@@ -951,41 +1274,39 @@ protected:
return I->second;
}
- // Find the remote FunctionId for the given function, which must be in the
- // RemoteFunctionIds map.
- template <typename Func> Expected<FunctionIdT> getRemoteFunctionId() {
- // Try to find the id for the given function.
- auto I = RemoteFunctionIds.find(Func::getPrototype());
+ // Find the remote FunctionId for the given function.
+ template <typename Func>
+ Expected<FunctionIdT> getRemoteFunctionId(bool NegotiateIfNotInMap,
+ bool NegotiateIfInvalid) {
+ bool DoNegotiate;
- // If we have it in the map, return it.
- if (I != RemoteFunctionIds.end())
- return I->second;
+ // Check if we already have a function id...
+ auto I = RemoteFunctionIds.find(Func::getPrototype());
+ if (I != RemoteFunctionIds.end()) {
+ // If it's valid there's nothing left to do.
+ if (I->second != getInvalidFunctionId())
+ return I->second;
+ DoNegotiate = NegotiateIfInvalid;
+ } else
+ DoNegotiate = NegotiateIfNotInMap;
- // Otherwise, if we have auto-negotiation enabled, try to negotiate it.
- if (LazyAutoNegotiation) {
+ // We don't have a function id for Func yet, but we're allowed to try to
+ // negotiate one.
+ if (DoNegotiate) {
auto &Impl = static_cast<ImplT &>(*this);
if (auto RemoteIdOrErr =
- Impl.template callB<OrcRPCNegotiate>(Func::getPrototype())) {
- auto &RemoteId = *RemoteIdOrErr;
-
- // If autonegotiation indicates that the remote end doesn't support this
- // function, return an unknown function error.
- if (RemoteId == getInvalidFunctionId())
- return orcError(OrcErrorCode::UnknownRPCFunction);
-
- // Autonegotiation succeeded and returned a valid id. Update the map and
- // return the id.
- RemoteFunctionIds[Func::getPrototype()] = RemoteId;
- return RemoteId;
- } else {
- // Autonegotiation failed. Return the error.
+ Impl.template callB<OrcRPCNegotiate>(Func::getPrototype())) {
+ RemoteFunctionIds[Func::getPrototype()] = *RemoteIdOrErr;
+ if (*RemoteIdOrErr == getInvalidFunctionId())
+ return make_error<CouldNotNegotiate>(Func::getPrototype());
+ return *RemoteIdOrErr;
+ } else
return RemoteIdOrErr.takeError();
- }
}
- // No key was available in the map and autonegotiation wasn't enabled.
- // Return an unknown function error.
- return orcError(OrcErrorCode::UnknownRPCFunction);
+ // No key was available in the map and we weren't allowed to try to
+ // negotiate one, so return an unknown function error.
+ return make_error<CouldNotNegotiate>(Func::getPrototype());
}
using WrappedHandlerFn = std::function<Error(ChannelT &, SequenceNumberT)>;
@@ -993,12 +1314,15 @@ protected:
// Wrap the given user handler in the necessary argument-deserialization code,
// result-serialization code, and call to the launch policy (if present).
template <typename Func, typename HandlerT>
- WrappedHandlerFn wrapHandler(HandlerT Handler, LaunchPolicy Launch) {
- return [this, Handler, Launch](ChannelT &Channel,
- SequenceNumberT SeqNo) mutable -> Error {
+ WrappedHandlerFn wrapHandler(HandlerT Handler) {
+ return [this, Handler](ChannelT &Channel,
+ SequenceNumberT SeqNo) mutable -> Error {
// Start by deserializing the arguments.
- auto Args = std::make_shared<
- typename detail::HandlerTraits<HandlerT>::ArgStorage>();
+ using ArgsTuple =
+ typename detail::FunctionArgsTuple<
+ typename detail::HandlerTraits<HandlerT>::Type>::Type;
+ auto Args = std::make_shared<ArgsTuple>();
+
if (auto Err =
detail::HandlerTraits<typename Func::Type>::deserializeArgs(
Channel, *Args))
@@ -1013,22 +1337,49 @@ protected:
if (auto Err = Channel.endReceiveMessage())
return Err;
- // Build the handler/responder.
- auto Responder = [this, Handler, Args, &Channel,
- SeqNo]() mutable -> Error {
- using HTraits = detail::HandlerTraits<HandlerT>;
- using FuncReturn = typename Func::ReturnType;
- return detail::respond<FuncReturn>(
- Channel, ResponseId, SeqNo, HTraits::unpackAndRun(Handler, *Args));
- };
-
- // If there is an explicit launch policy then use it to launch the
- // handler.
- if (Launch)
- return Launch(std::move(Responder));
-
- // Otherwise run the handler on the listener thread.
- return Responder();
+ using HTraits = detail::HandlerTraits<HandlerT>;
+ using FuncReturn = typename Func::ReturnType;
+ return detail::respond<FuncReturn>(Channel, ResponseId, SeqNo,
+ HTraits::unpackAndRun(Handler, *Args));
+ };
+ }
+
+ // Wrap the given user handler in the necessary argument-deserialization code,
+ // result-serialization code, and call to the launch policy (if present).
+ template <typename Func, typename HandlerT>
+ WrappedHandlerFn wrapAsyncHandler(HandlerT Handler) {
+ return [this, Handler](ChannelT &Channel,
+ SequenceNumberT SeqNo) mutable -> Error {
+ // Start by deserializing the arguments.
+ using AHTraits = detail::AsyncHandlerTraits<
+ typename detail::HandlerTraits<HandlerT>::Type>;
+ using ArgsTuple =
+ typename detail::FunctionArgsTuple<typename AHTraits::Type>::Type;
+ auto Args = std::make_shared<ArgsTuple>();
+
+ if (auto Err =
+ detail::HandlerTraits<typename Func::Type>::deserializeArgs(
+ Channel, *Args))
+ return Err;
+
+ // GCC 4.7 and 4.8 incorrectly issue a -Wunused-but-set-variable warning
+ // for RPCArgs. Void cast RPCArgs to work around this for now.
+ // FIXME: Remove this workaround once we can assume a working GCC version.
+ (void)Args;
+
+ // End receieve message, unlocking the channel for reading.
+ if (auto Err = Channel.endReceiveMessage())
+ return Err;
+
+ using HTraits = detail::HandlerTraits<HandlerT>;
+ using FuncReturn = typename Func::ReturnType;
+ auto Responder =
+ [this, SeqNo](typename AHTraits::ResultType RetVal) -> Error {
+ return detail::respond<FuncReturn>(C, ResponseId, SeqNo,
+ std::move(RetVal));
+ };
+
+ return HTraits::unpackAndRunAsync(Handler, Responder, *Args);
};
}
@@ -1068,66 +1419,31 @@ public:
MultiThreadedRPCEndpoint(ChannelT &C, bool LazyAutoNegotiation)
: BaseClass(C, LazyAutoNegotiation) {}
- /// The LaunchPolicy type allows a launch policy to be specified when adding
- /// a function handler. See addHandler.
- using LaunchPolicy = typename BaseClass::LaunchPolicy;
-
/// Add a handler for the given RPC function.
/// This installs the given handler functor for the given RPC Function, and
/// makes the RPC function available for negotiation/calling from the remote.
- ///
- /// The optional LaunchPolicy argument can be used to control how the handler
- /// is run when called:
- ///
- /// * If no LaunchPolicy is given, the handler code will be run on the RPC
- /// handler thread that is reading from the channel. This handler cannot
- /// make blocking RPC calls (since it would be blocking the thread used to
- /// get the result), but can make non-blocking calls.
- ///
- /// * If a LaunchPolicy is given, the user's handler will be wrapped in a
- /// call to serialize and send the result, and the resulting functor (with
- /// type 'Error()' will be passed to the LaunchPolicy. The user can then
- /// choose to add the wrapped handler to a work queue, spawn a new thread,
- /// or anything else.
template <typename Func, typename HandlerT>
- void addHandler(HandlerT Handler, LaunchPolicy Launch = LaunchPolicy()) {
- return this->template addHandlerImpl<Func>(std::move(Handler),
- std::move(Launch));
+ void addHandler(HandlerT Handler) {
+ return this->template addHandlerImpl<Func>(std::move(Handler));
}
/// Add a class-method as a handler.
template <typename Func, typename ClassT, typename RetT, typename... ArgTs>
- void addHandler(ClassT &Object, RetT (ClassT::*Method)(ArgTs...),
- LaunchPolicy Launch = LaunchPolicy()) {
+ void addHandler(ClassT &Object, RetT (ClassT::*Method)(ArgTs...)) {
addHandler<Func>(
- detail::MemberFnWrapper<ClassT, RetT, ArgTs...>(Object, Method),
- Launch);
+ detail::MemberFnWrapper<ClassT, RetT, ArgTs...>(Object, Method));
}
- /// Negotiate a function id for Func with the other end of the channel.
- template <typename Func> Error negotiateFunction(bool Retry = false) {
- using OrcRPCNegotiate = typename BaseClass::OrcRPCNegotiate;
-
- // Check if we already have a function id...
- auto I = this->RemoteFunctionIds.find(Func::getPrototype());
- if (I != this->RemoteFunctionIds.end()) {
- // If it's valid there's nothing left to do.
- if (I->second != this->getInvalidFunctionId())
- return Error::success();
- // If it's invalid and we can't re-attempt negotiation, throw an error.
- if (!Retry)
- return orcError(OrcErrorCode::UnknownRPCFunction);
- }
+ template <typename Func, typename HandlerT>
+ void addAsyncHandler(HandlerT Handler) {
+ return this->template addAsyncHandlerImpl<Func>(std::move(Handler));
+ }
- // We don't have a function id for Func yet, call the remote to try to
- // negotiate one.
- if (auto RemoteIdOrErr = callB<OrcRPCNegotiate>(Func::getPrototype())) {
- this->RemoteFunctionIds[Func::getPrototype()] = *RemoteIdOrErr;
- if (*RemoteIdOrErr == this->getInvalidFunctionId())
- return orcError(OrcErrorCode::UnknownRPCFunction);
- return Error::success();
- } else
- return RemoteIdOrErr.takeError();
+ /// Add a class-method as a handler.
+ template <typename Func, typename ClassT, typename RetT, typename... ArgTs>
+ void addAsyncHandler(ClassT &Object, RetT (ClassT::*Method)(ArgTs...)) {
+ addAsyncHandler<Func>(
+ detail::MemberFnWrapper<ClassT, RetT, ArgTs...>(Object, Method));
}
/// Return type for non-blocking call primitives.
@@ -1159,7 +1475,6 @@ public:
return Error::success();
},
Args...)) {
- this->abandonPendingResponses();
RTraits::consumeAbandoned(FutureResult.get());
return std::move(Err);
}
@@ -1191,15 +1506,9 @@ public:
typename AltRetT = typename Func::ReturnType>
typename detail::ResultTraits<AltRetT>::ErrorReturnType
callB(const ArgTs &... Args) {
- if (auto FutureResOrErr = callNB<Func>(Args...)) {
- if (auto Err = this->C.send()) {
- this->abandonPendingResponses();
- detail::ResultTraits<typename Func::ReturnType>::consumeAbandoned(
- std::move(FutureResOrErr->get()));
- return std::move(Err);
- }
+ if (auto FutureResOrErr = callNB<Func>(Args...))
return FutureResOrErr->get();
- } else
+ else
return FutureResOrErr.takeError();
}
@@ -1224,16 +1533,13 @@ private:
SingleThreadedRPCEndpoint<ChannelT, FunctionIdT, SequenceNumberT>,
ChannelT, FunctionIdT, SequenceNumberT>;
- using LaunchPolicy = typename BaseClass::LaunchPolicy;
-
public:
SingleThreadedRPCEndpoint(ChannelT &C, bool LazyAutoNegotiation)
: BaseClass(C, LazyAutoNegotiation) {}
template <typename Func, typename HandlerT>
void addHandler(HandlerT Handler) {
- return this->template addHandlerImpl<Func>(std::move(Handler),
- LaunchPolicy());
+ return this->template addHandlerImpl<Func>(std::move(Handler));
}
template <typename Func, typename ClassT, typename RetT, typename... ArgTs>
@@ -1242,30 +1548,16 @@ public:
detail::MemberFnWrapper<ClassT, RetT, ArgTs...>(Object, Method));
}
- /// Negotiate a function id for Func with the other end of the channel.
- template <typename Func> Error negotiateFunction(bool Retry = false) {
- using OrcRPCNegotiate = typename BaseClass::OrcRPCNegotiate;
-
- // Check if we already have a function id...
- auto I = this->RemoteFunctionIds.find(Func::getPrototype());
- if (I != this->RemoteFunctionIds.end()) {
- // If it's valid there's nothing left to do.
- if (I->second != this->getInvalidFunctionId())
- return Error::success();
- // If it's invalid and we can't re-attempt negotiation, throw an error.
- if (!Retry)
- return orcError(OrcErrorCode::UnknownRPCFunction);
- }
+ template <typename Func, typename HandlerT>
+ void addAsyncHandler(HandlerT Handler) {
+ return this->template addAsyncHandlerImpl<Func>(std::move(Handler));
+ }
- // We don't have a function id for Func yet, call the remote to try to
- // negotiate one.
- if (auto RemoteIdOrErr = callB<OrcRPCNegotiate>(Func::getPrototype())) {
- this->RemoteFunctionIds[Func::getPrototype()] = *RemoteIdOrErr;
- if (*RemoteIdOrErr == this->getInvalidFunctionId())
- return orcError(OrcErrorCode::UnknownRPCFunction);
- return Error::success();
- } else
- return RemoteIdOrErr.takeError();
+ /// Add a class-method as a handler.
+ template <typename Func, typename ClassT, typename RetT, typename... ArgTs>
+ void addAsyncHandler(ClassT &Object, RetT (ClassT::*Method)(ArgTs...)) {
+ addAsyncHandler<Func>(
+ detail::MemberFnWrapper<ClassT, RetT, ArgTs...>(Object, Method));
}
template <typename Func, typename... ArgTs,
@@ -1287,7 +1579,6 @@ public:
return Error::success();
},
Args...)) {
- this->abandonPendingResponses();
detail::ResultTraits<typename Func::ReturnType>::consumeAbandoned(
std::move(Result));
return std::move(Err);
@@ -1295,7 +1586,6 @@ public:
while (!ReceivedResponse) {
if (auto Err = this->handleOne()) {
- this->abandonPendingResponses();
detail::ResultTraits<typename Func::ReturnType>::consumeAbandoned(
std::move(Result));
return std::move(Err);
@@ -1306,24 +1596,40 @@ public:
}
};
+/// Asynchronous dispatch for a function on an RPC endpoint.
+template <typename RPCClass, typename Func>
+class RPCAsyncDispatch {
+public:
+ RPCAsyncDispatch(RPCClass &Endpoint) : Endpoint(Endpoint) {}
+
+ template <typename HandlerT, typename... ArgTs>
+ Error operator()(HandlerT Handler, const ArgTs &... Args) const {
+ return Endpoint.template appendCallAsync<Func>(std::move(Handler), Args...);
+ }
+
+private:
+ RPCClass &Endpoint;
+};
+
+/// Construct an asynchronous dispatcher from an RPC endpoint and a Func.
+template <typename Func, typename RPCEndpointT>
+RPCAsyncDispatch<RPCEndpointT, Func> rpcAsyncDispatch(RPCEndpointT &Endpoint) {
+ return RPCAsyncDispatch<RPCEndpointT, Func>(Endpoint);
+}
+
/// \brief Allows a set of asynchrounous calls to be dispatched, and then
/// waited on as a group.
-template <typename RPCClass> class ParallelCallGroup {
+class ParallelCallGroup {
public:
- /// \brief Construct a parallel call group for the given RPC.
- ParallelCallGroup(RPCClass &RPC) : RPC(RPC), NumOutstandingCalls(0) {}
-
+ ParallelCallGroup() = default;
ParallelCallGroup(const ParallelCallGroup &) = delete;
ParallelCallGroup &operator=(const ParallelCallGroup &) = delete;
/// \brief Make as asynchronous call.
- ///
- /// Does not issue a send call to the RPC's channel. The channel may use this
- /// to batch up subsequent calls. A send will automatically be sent when wait
- /// is called.
- template <typename Func, typename HandlerT, typename... ArgTs>
- Error appendCall(HandlerT Handler, const ArgTs &... Args) {
+ template <typename AsyncDispatcher, typename HandlerT, typename... ArgTs>
+ Error call(const AsyncDispatcher &AsyncDispatch, HandlerT Handler,
+ const ArgTs &... Args) {
// Increment the count of outstanding calls. This has to happen before
// we invoke the call, as the handler may (depending on scheduling)
// be run immediately on another thread, and we don't want the decrement
@@ -1346,38 +1652,21 @@ public:
return Err;
};
- return RPC.template appendCallAsync<Func>(std::move(WrappedHandler),
- Args...);
- }
-
- /// \brief Make an asynchronous call.
- ///
- /// The same as appendCall, but also calls send on the channel immediately.
- /// Prefer appendCall if you are about to issue a "wait" call shortly, as
- /// this may allow the channel to better batch the calls.
- template <typename Func, typename HandlerT, typename... ArgTs>
- Error call(HandlerT Handler, const ArgTs &... Args) {
- if (auto Err = appendCall(std::move(Handler), Args...))
- return Err;
- return RPC.sendAppendedCalls();
+ return AsyncDispatch(std::move(WrappedHandler), Args...);
}
/// \brief Blocks until all calls have been completed and their return value
/// handlers run.
- Error wait() {
- if (auto Err = RPC.sendAppendedCalls())
- return Err;
+ void wait() {
std::unique_lock<std::mutex> Lock(M);
while (NumOutstandingCalls > 0)
CV.wait(Lock);
- return Error::success();
}
private:
- RPCClass &RPC;
std::mutex M;
std::condition_variable CV;
- uint32_t NumOutstandingCalls;
+ uint32_t NumOutstandingCalls = 0;
};
/// @brief Convenience class for grouping RPC Functions into APIs that can be
diff --git a/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h b/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h
index 0588d2228598..babcc7f26aab 100644
--- a/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h
+++ b/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h
@@ -1,4 +1,4 @@
-//===- ObjectLinkingLayer.h - Add object files to a JIT process -*- C++ -*-===//
+//===-- RTDyldObjectLinkingLayer.h - RTDyld-based jit linking --*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,12 +7,12 @@
//
//===----------------------------------------------------------------------===//
//
-// Contains the definition for the object layer of the JIT.
+// Contains the definition for an RTDyld-based, in-process object linking layer.
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_EXECUTIONENGINE_ORC_OBJECTLINKINGLAYER_H
-#define LLVM_EXECUTIONENGINE_ORC_OBJECTLINKINGLAYER_H
+#ifndef LLVM_EXECUTIONENGINE_ORC_RTDYLDOBJECTLINKINGLAYER_H
+#define LLVM_EXECUTIONENGINE_ORC_RTDYLDOBJECTLINKINGLAYER_H
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringMap.h"
@@ -35,7 +35,7 @@
namespace llvm {
namespace orc {
-class ObjectLinkingLayerBase {
+class RTDyldObjectLinkingLayerBase {
protected:
/// @brief Holds a set of objects to be allocated/linked as a unit in the JIT.
///
@@ -87,7 +87,7 @@ public:
class DoNothingOnNotifyLoaded {
public:
template <typename ObjSetT, typename LoadResult>
- void operator()(ObjectLinkingLayerBase::ObjSetHandleT, const ObjSetT &,
+ void operator()(RTDyldObjectLinkingLayerBase::ObjSetHandleT, const ObjSetT &,
const LoadResult &) {}
};
@@ -98,7 +98,7 @@ public:
/// symbols queried. All objects added to this layer can see each other's
/// symbols.
template <typename NotifyLoadedFtor = DoNothingOnNotifyLoaded>
-class ObjectLinkingLayer : public ObjectLinkingLayerBase {
+class RTDyldObjectLinkingLayer : public RTDyldObjectLinkingLayerBase {
public:
/// @brief Functor for receiving finalization notifications.
typedef std::function<void(ObjSetHandleT)> NotifyFinalizedFtor;
@@ -227,7 +227,7 @@ public:
/// @brief Construct an ObjectLinkingLayer with the given NotifyLoaded,
/// and NotifyFinalized functors.
- ObjectLinkingLayer(
+ RTDyldObjectLinkingLayer(
NotifyLoadedFtor NotifyLoaded = NotifyLoadedFtor(),
NotifyFinalizedFtor NotifyFinalized = NotifyFinalizedFtor())
: NotifyLoaded(std::move(NotifyLoaded)),
@@ -359,4 +359,4 @@ private:
} // end namespace orc
} // end namespace llvm
-#endif // LLVM_EXECUTIONENGINE_ORC_OBJECTLINKINGLAYER_H
+#endif // LLVM_EXECUTIONENGINE_ORC_RTDYLDOBJECTLINKINGLAYER_H
diff --git a/include/llvm/ExecutionEngine/Orc/RawByteChannel.h b/include/llvm/ExecutionEngine/Orc/RawByteChannel.h
index 3b6c84eb1965..52a546f7c6eb 100644
--- a/include/llvm/ExecutionEngine/Orc/RawByteChannel.h
+++ b/include/llvm/ExecutionEngine/Orc/RawByteChannel.h
@@ -48,7 +48,11 @@ public:
template <typename FunctionIdT, typename SequenceIdT>
Error startSendMessage(const FunctionIdT &FnId, const SequenceIdT &SeqNo) {
writeLock.lock();
- return serializeSeq(*this, FnId, SeqNo);
+ if (auto Err = serializeSeq(*this, FnId, SeqNo)) {
+ writeLock.unlock();
+ return Err;
+ }
+ return Error::success();
}
/// Notify the channel that we're ending a message send.
@@ -63,7 +67,11 @@ public:
template <typename FunctionIdT, typename SequenceNumberT>
Error startReceiveMessage(FunctionIdT &FnId, SequenceNumberT &SeqNo) {
readLock.lock();
- return deserializeSeq(*this, FnId, SeqNo);
+ if (auto Err = deserializeSeq(*this, FnId, SeqNo)) {
+ readLock.unlock();
+ return Err;
+ }
+ return Error::success();
}
/// Notify the channel that we're ending a message receive.
@@ -113,11 +121,19 @@ class SerializationTraits<ChannelT, bool, bool,
RawByteChannel, ChannelT>::value>::type> {
public:
static Error serialize(ChannelT &C, bool V) {
- return C.appendBytes(reinterpret_cast<const char *>(&V), 1);
+ uint8_t Tmp = V ? 1 : 0;
+ if (auto Err =
+ C.appendBytes(reinterpret_cast<const char *>(&Tmp), 1))
+ return Err;
+ return Error::success();
}
static Error deserialize(ChannelT &C, bool &V) {
- return C.readBytes(reinterpret_cast<char *>(&V), 1);
+ uint8_t Tmp = 0;
+ if (auto Err = C.readBytes(reinterpret_cast<char *>(&Tmp), 1))
+ return Err;
+ V = Tmp != 0;
+ return Error::success();
}
};
@@ -134,10 +150,12 @@ public:
}
};
-template <typename ChannelT>
-class SerializationTraits<ChannelT, std::string, const char *,
- typename std::enable_if<std::is_base_of<
- RawByteChannel, ChannelT>::value>::type> {
+template <typename ChannelT, typename T>
+class SerializationTraits<ChannelT, std::string, T,
+ typename std::enable_if<
+ std::is_base_of<RawByteChannel, ChannelT>::value &&
+ (std::is_same<T, const char*>::value ||
+ std::is_same<T, char*>::value)>::type> {
public:
static Error serialize(RawByteChannel &C, const char *S) {
return SerializationTraits<ChannelT, std::string, StringRef>::serialize(C,
diff --git a/include/llvm/IR/Argument.h b/include/llvm/IR/Argument.h
index d8b280a66f18..6fc1dd2f285a 100644
--- a/include/llvm/IR/Argument.h
+++ b/include/llvm/IR/Argument.h
@@ -21,127 +21,110 @@
namespace llvm {
-template <typename NodeTy> class SymbolTableListTraits;
-
-/// \brief LLVM Argument representation
-///
/// This class represents an incoming formal argument to a Function. A formal
/// argument, since it is ``formal'', does not contain an actual value but
/// instead represents the type, argument number, and attributes of an argument
/// for a specific function. When used in the body of said function, the
/// argument of course represents the value of the actual argument that the
/// function was called with.
-class Argument : public Value, public ilist_node<Argument> {
+class Argument : public Value {
virtual void anchor();
Function *Parent;
+ unsigned ArgNo;
- friend class SymbolTableListTraits<Argument>;
+ friend class Function;
void setParent(Function *parent);
public:
- /// \brief Constructor.
- ///
- /// If \p F is specified, the argument is inserted at the end of the argument
- /// list for \p F.
- explicit Argument(Type *Ty, const Twine &Name = "", Function *F = nullptr);
+ /// Argument constructor.
+ explicit Argument(Type *Ty, const Twine &Name = "", Function *F = nullptr,
+ unsigned ArgNo = 0);
inline const Function *getParent() const { return Parent; }
inline Function *getParent() { return Parent; }
- /// \brief Return the index of this formal argument in its containing
- /// function.
+ /// Return the index of this formal argument in its containing function.
///
/// For example in "void foo(int a, float b)" a is 0 and b is 1.
- unsigned getArgNo() const;
+ unsigned getArgNo() const {
+ assert(Parent && "can't get number of unparented arg");
+ return ArgNo;
+ }
- /// \brief Return true if this argument has the nonnull attribute on it in
- /// its containing function. Also returns true if at least one byte is known
- /// to be dereferenceable and the pointer is in addrspace(0).
+ /// Return true if this argument has the nonnull attribute. Also returns true
+ /// if at least one byte is known to be dereferenceable and the pointer is in
+ /// addrspace(0).
bool hasNonNullAttr() const;
- /// \brief If this argument has the dereferenceable attribute on it in its
- /// containing function, return the number of bytes known to be
- /// dereferenceable. Otherwise, zero is returned.
+ /// If this argument has the dereferenceable attribute, 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.
+ /// If this argument has the dereferenceable_or_null attribute, 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.
+ /// Return true if this argument has the byval attribute.
bool hasByValAttr() const;
- /// \brief Return true if this argument has the swiftself attribute.
+ /// Return true if this argument has the swiftself attribute.
bool hasSwiftSelfAttr() const;
- /// \brief Return true if this argument has the swifterror attribute.
+ /// Return true if this argument has the swifterror attribute.
bool hasSwiftErrorAttr() const;
- /// \brief Return true if this argument has the byval attribute or inalloca
- /// attribute on it in its containing function. These attributes both
- /// represent arguments being passed by value.
+ /// Return true if this argument has the byval attribute or inalloca
+ /// attribute. These attributes represent arguments being passed by value.
bool hasByValOrInAllocaAttr() const;
- /// \brief If this is a byval or inalloca argument, return its alignment.
+ /// If this is a byval or inalloca argument, return its alignment.
unsigned getParamAlignment() const;
- /// \brief Return true if this argument has the nest attribute on it in its
- /// containing function.
+ /// Return true if this argument has the nest attribute.
bool hasNestAttr() const;
- /// \brief Return true if this argument has the noalias attribute on it in its
- /// containing function.
+ /// Return true if this argument has the noalias attribute.
bool hasNoAliasAttr() const;
- /// \brief Return true if this argument has the nocapture attribute on it in
- /// its containing function.
+ /// Return true if this argument has the nocapture attribute.
bool hasNoCaptureAttr() const;
- /// \brief Return true if this argument has the sret attribute on it in its
- /// containing function.
+ /// Return true if this argument has the sret attribute.
bool hasStructRetAttr() const;
- /// \brief Return true if this argument has the returned attribute on it in
- /// its containing function.
+ /// Return true if this argument has the returned attribute.
bool hasReturnedAttr() const;
- /// \brief Return true if this argument has the readonly or readnone attribute
- /// on it in its containing function.
+ /// Return true if this argument has the readonly or readnone attribute.
bool onlyReadsMemory() const;
- /// \brief Return true if this argument has the inalloca attribute on it in
- /// its containing function.
+ /// Return true if this argument has the inalloca attribute.
bool hasInAllocaAttr() const;
- /// \brief Return true if this argument has the zext attribute on it in its
- /// containing function.
+ /// Return true if this argument has the zext attribute.
bool hasZExtAttr() const;
- /// \brief Return true if this argument has the sext attribute on it in its
- /// containing function.
+ /// Return true if this argument has the sext attribute.
bool hasSExtAttr() const;
- /// \brief Add a Attribute to an argument.
- void addAttr(AttributeSet AS);
+ /// Add attributes to an argument.
+ void addAttr(AttributeList AS);
void addAttr(Attribute::AttrKind Kind) {
- addAttr(AttributeSet::get(getContext(), getArgNo() + 1, Kind));
+ addAttr(AttributeList::get(getContext(), getArgNo() + 1, Kind));
}
- /// \brief Remove a Attribute from an argument.
- void removeAttr(AttributeSet AS);
+ /// Remove attributes from an argument.
+ void removeAttr(AttributeList AS);
void removeAttr(Attribute::AttrKind Kind) {
- removeAttr(AttributeSet::get(getContext(), getArgNo() + 1, Kind));
+ removeAttr(AttributeList::get(getContext(), getArgNo() + 1, Kind));
}
- /// \brief Checks if an argument has a given attribute.
+ /// Check if an argument has a given attribute.
bool hasAttribute(Attribute::AttrKind Kind) const;
- /// \brief Method for support type inquiry through isa, cast, and
- /// dyn_cast.
+ /// Method for support type inquiry through isa, cast, and dyn_cast.
static inline bool classof(const Value *V) {
return V->getValueID() == ArgumentVal;
}
diff --git a/include/llvm/IR/Attributes.h b/include/llvm/IR/Attributes.h
index 15783858dd32..121f57a433ac 100644
--- a/include/llvm/IR/Attributes.h
+++ b/include/llvm/IR/Attributes.h
@@ -1,4 +1,4 @@
-//===-- llvm/Attributes.h - Container for Attributes ------------*- C++ -*-===//
+//===- llvm/Attributes.h - Container for Attributes -------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -18,22 +18,24 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/iterator_range.h"
#include "llvm/ADT/Optional.h"
-#include "llvm/Support/Compiler.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/Support/PointerLikeTypeTraits.h"
#include "llvm-c/Types.h"
#include <bitset>
#include <cassert>
+#include <cstdint>
#include <map>
#include <string>
+#include <utility>
namespace llvm {
class AttrBuilder;
class AttributeImpl;
-class AttributeSetImpl;
+class AttributeListImpl;
class AttributeSetNode;
-class Constant;
template<typename T> struct DenseMapInfo;
class Function;
class LLVMContext;
@@ -73,11 +75,12 @@ public:
};
private:
- AttributeImpl *pImpl;
+ AttributeImpl *pImpl = nullptr;
+
Attribute(AttributeImpl *A) : pImpl(A) {}
public:
- Attribute() : pImpl(nullptr) {}
+ Attribute() = default;
//===--------------------------------------------------------------------===//
// Attribute Construction
@@ -194,13 +197,91 @@ inline Attribute unwrap(LLVMAttributeRef Attr) {
//===----------------------------------------------------------------------===//
/// \class
+/// This class holds the attributes for a particular argument, parameter,
+/// function, or return value. It is an immutable value type that is cheap to
+/// copy. Adding and removing enum attributes is intended to be fast, but adding
+/// and removing string or integer attributes involves a FoldingSet lookup.
+class AttributeSet {
+ // TODO: Extract AvailableAttrs from AttributeSetNode and store them here.
+ // This will allow an efficient implementation of addAttribute and
+ // removeAttribute for enum attrs.
+
+ /// Private implementation pointer.
+ AttributeSetNode *SetNode = nullptr;
+
+ friend AttributeListImpl;
+ template <typename Ty> friend struct DenseMapInfo;
+
+private:
+ explicit AttributeSet(AttributeSetNode *ASN) : SetNode(ASN) {}
+
+public:
+ /// AttributeSet is a trivially copyable value type.
+ AttributeSet() = default;
+ AttributeSet(const AttributeSet &) = default;
+ ~AttributeSet() = default;
+
+ static AttributeSet get(LLVMContext &C, const AttrBuilder &B);
+ static AttributeSet get(LLVMContext &C, ArrayRef<Attribute> Attrs);
+
+ bool operator==(const AttributeSet &O) { return SetNode == O.SetNode; }
+ bool operator!=(const AttributeSet &O) { return !(*this == O); }
+
+ unsigned getNumAttributes() const;
+
+ bool hasAttributes() const { return SetNode != nullptr; }
+
+ bool hasAttribute(Attribute::AttrKind Kind) const;
+ bool hasAttribute(StringRef Kind) const;
+
+ Attribute getAttribute(Attribute::AttrKind Kind) const;
+ Attribute getAttribute(StringRef Kind) const;
+
+ unsigned getAlignment() const;
+ unsigned getStackAlignment() const;
+ uint64_t getDereferenceableBytes() const;
+ uint64_t getDereferenceableOrNullBytes() const;
+ std::pair<unsigned, Optional<unsigned>> getAllocSizeArgs() const;
+ std::string getAsString(bool InAttrGrp = false) const;
+
+ typedef const Attribute *iterator;
+ iterator begin() const;
+ iterator end() const;
+};
+
+//===----------------------------------------------------------------------===//
+/// \class
+/// \brief Provide DenseMapInfo for AttributeSet.
+template <> struct DenseMapInfo<AttributeSet> {
+ static inline AttributeSet getEmptyKey() {
+ uintptr_t Val = static_cast<uintptr_t>(-1);
+ Val <<= PointerLikeTypeTraits<void *>::NumLowBitsAvailable;
+ return AttributeSet(reinterpret_cast<AttributeSetNode *>(Val));
+ }
+
+ static inline AttributeSet getTombstoneKey() {
+ uintptr_t Val = static_cast<uintptr_t>(-2);
+ Val <<= PointerLikeTypeTraits<void *>::NumLowBitsAvailable;
+ return AttributeSet(reinterpret_cast<AttributeSetNode *>(Val));
+ }
+
+ static unsigned getHashValue(AttributeSet AS) {
+ return (unsigned((uintptr_t)AS.SetNode) >> 4) ^
+ (unsigned((uintptr_t)AS.SetNode) >> 9);
+ }
+
+ static bool isEqual(AttributeSet LHS, AttributeSet RHS) { return LHS == RHS; }
+};
+
+//===----------------------------------------------------------------------===//
+/// \class
/// \brief This class holds the attributes for a function, its return value, and
/// its parameters. You access the attributes for each of them via an index into
-/// the AttributeSet object. The function attributes are at index
-/// `AttributeSet::FunctionIndex', the return value is at index
-/// `AttributeSet::ReturnIndex', and the attributes for the parameters start at
+/// the AttributeList object. The function attributes are at index
+/// `AttributeList::FunctionIndex', the return value is at index
+/// `AttributeList::ReturnIndex', and the attributes for the parameters start at
/// index `1'.
-class AttributeSet {
+class AttributeList {
public:
enum AttrIndex : unsigned {
ReturnIndex = 0U,
@@ -209,115 +290,137 @@ public:
private:
friend class AttrBuilder;
- friend class AttributeSetImpl;
+ friend class AttributeListImpl;
+ friend class AttributeSet;
friend class AttributeSetNode;
+
template <typename Ty> friend struct DenseMapInfo;
/// \brief The attributes that we are managing. This can be null to represent
/// the empty attributes list.
- AttributeSetImpl *pImpl;
-
- /// \brief The attributes for the specified index are returned.
- AttributeSetNode *getAttributes(unsigned Index) const;
-
- /// \brief Create an AttributeSet with the specified parameters in it.
- static AttributeSet get(LLVMContext &C,
- ArrayRef<std::pair<unsigned, Attribute> > Attrs);
- static AttributeSet get(LLVMContext &C,
- ArrayRef<std::pair<unsigned,
- AttributeSetNode*> > Attrs);
+ AttributeListImpl *pImpl = nullptr;
- static AttributeSet getImpl(LLVMContext &C,
- ArrayRef<std::pair<unsigned,
- AttributeSetNode*> > Attrs);
+public:
+ /// \brief Create an AttributeList with the specified parameters in it.
+ static AttributeList get(LLVMContext &C,
+ ArrayRef<std::pair<unsigned, Attribute>> Attrs);
+ static AttributeList
+ get(LLVMContext &C, ArrayRef<std::pair<unsigned, AttributeSet>> Attrs);
+
+ /// \brief Create an AttributeList from attribute sets for a function, its
+ /// return value, and all of its arguments.
+ static AttributeList get(LLVMContext &C, AttributeSet FnAttrs,
+ AttributeSet RetAttrs,
+ ArrayRef<AttributeSet> ArgAttrs);
+
+ static AttributeList
+ getImpl(LLVMContext &C,
+ ArrayRef<std::pair<unsigned, AttributeSet>> Attrs);
- explicit AttributeSet(AttributeSetImpl *LI) : pImpl(LI) {}
+private:
+ explicit AttributeList(AttributeListImpl *LI) : pImpl(LI) {}
public:
- AttributeSet() : pImpl(nullptr) {}
+ AttributeList() = default;
//===--------------------------------------------------------------------===//
- // AttributeSet Construction and Mutation
+ // AttributeList Construction and Mutation
//===--------------------------------------------------------------------===//
- /// \brief Return an AttributeSet with the specified parameters in it.
- static AttributeSet get(LLVMContext &C, ArrayRef<AttributeSet> Attrs);
- static AttributeSet get(LLVMContext &C, unsigned Index,
- ArrayRef<Attribute::AttrKind> Kinds);
- static AttributeSet get(LLVMContext &C, unsigned Index,
- ArrayRef<StringRef> Kind);
- static AttributeSet get(LLVMContext &C, unsigned Index, const AttrBuilder &B);
+ /// \brief Return an AttributeList with the specified parameters in it.
+ static AttributeList get(LLVMContext &C, ArrayRef<AttributeList> Attrs);
+ static AttributeList get(LLVMContext &C, unsigned Index,
+ ArrayRef<Attribute::AttrKind> Kinds);
+ static AttributeList get(LLVMContext &C, unsigned Index,
+ ArrayRef<StringRef> Kind);
+ static AttributeList get(LLVMContext &C, unsigned Index,
+ const AttrBuilder &B);
/// \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 Kind) const;
+ AttributeList addAttribute(LLVMContext &C, unsigned Index,
+ Attribute::AttrKind Kind) const;
/// \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,
- StringRef Value = StringRef()) const;
+ AttributeList addAttribute(LLVMContext &C, unsigned Index, StringRef Kind,
+ StringRef Value = StringRef()) const;
/// Add an attribute to the attribute set at the given indices. Because
/// attribute sets are immutable, this returns a new set.
- AttributeSet addAttribute(LLVMContext &C, ArrayRef<unsigned> Indices,
- Attribute A) const;
+ AttributeList addAttribute(LLVMContext &C, ArrayRef<unsigned> Indices,
+ Attribute A) const;
/// \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;
+ AttributeList addAttributes(LLVMContext &C, unsigned Index,
+ AttributeList Attrs) const;
+
+ AttributeList addAttributes(LLVMContext &C, unsigned Index,
+ AttributeSet AS) const;
+
+ AttributeList addAttributes(LLVMContext &C, unsigned Index,
+ const AttrBuilder &B) const;
/// \brief Remove the specified attribute at the specified index from this
/// attribute list. Because attribute lists are immutable, this returns the
/// new list.
- AttributeSet removeAttribute(LLVMContext &C, unsigned Index,
- Attribute::AttrKind Kind) const;
+ AttributeList removeAttribute(LLVMContext &C, unsigned Index,
+ Attribute::AttrKind Kind) const;
/// \brief Remove the specified attribute at the specified index from this
/// attribute list. Because attribute lists are immutable, this returns the
/// new list.
- AttributeSet removeAttribute(LLVMContext &C, unsigned Index,
- StringRef Kind) const;
+ AttributeList removeAttribute(LLVMContext &C, unsigned Index,
+ StringRef Kind) 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,
- AttributeSet Attrs) const;
+ AttributeList removeAttributes(LLVMContext &C, unsigned Index,
+ AttributeList 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;
+ AttributeList removeAttributes(LLVMContext &C, unsigned Index,
+ const AttrBuilder &Attrs) const;
+
+ /// \brief Remove all attributes at the specified index from this
+ /// attribute list. Because attribute lists are immutable, this returns the
+ /// new list.
+ AttributeList removeAttributes(LLVMContext &C, unsigned Index) 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;
+ AttributeList 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;
+ AttributeList addDereferenceableOrNullAttr(LLVMContext &C, unsigned Index,
+ uint64_t Bytes) const;
/// Add the allocsize attribute to the attribute set at the given index.
/// Because attribute sets are immutable, this returns a new set.
- AttributeSet addAllocSizeAttr(LLVMContext &C, unsigned Index,
- unsigned ElemSizeArg,
- const Optional<unsigned> &NumElemsArg);
+ AttributeList addAllocSizeAttr(LLVMContext &C, unsigned Index,
+ unsigned ElemSizeArg,
+ const Optional<unsigned> &NumElemsArg);
//===--------------------------------------------------------------------===//
- // AttributeSet Accessors
+ // AttributeList Accessors
//===--------------------------------------------------------------------===//
/// \brief Retrieve the LLVM context.
LLVMContext &getContext() const;
/// \brief The attributes for the specified index are returned.
- AttributeSet getParamAttributes(unsigned Index) const;
+ AttributeSet getAttributes(unsigned Index) const;
+
+ /// \brief The attributes for the argument or parameter at the given index are
+ /// returned.
+ AttributeSet getParamAttributes(unsigned ArgNo) const;
/// \brief The attributes for the ret value are returned.
AttributeSet getRetAttributes() const;
@@ -334,14 +437,17 @@ public:
/// \brief Return true if attribute exists at the given index.
bool hasAttributes(unsigned Index) const;
- /// \brief Equivalent to hasAttribute(AttributeSet::FunctionIndex, Kind) but
+ /// \brief Equivalent to hasAttribute(AttributeList::FunctionIndex, Kind) but
/// may be faster.
bool hasFnAttribute(Attribute::AttrKind Kind) const;
- /// \brief Equivalent to hasAttribute(AttributeSet::FunctionIndex, Kind) but
+ /// \brief Equivalent to hasAttribute(AttributeList::FunctionIndex, Kind) but
/// may be faster.
bool hasFnAttribute(StringRef Kind) const;
+ /// \brief Equivalent to hasAttribute(ArgNo + 1, Kind).
+ bool hasParamAttribute(unsigned ArgNo, Attribute::AttrKind Kind) const;
+
/// \brief Return true if the specified attribute is set for at least one
/// parameter or for the return value. If Index is not nullptr, the index
/// of a parameter with the specified attribute is provided.
@@ -380,15 +486,11 @@ public:
iterator end(unsigned Slot) const;
/// operator==/!= - Provide equality predicates.
- bool operator==(const AttributeSet &RHS) const {
- return pImpl == RHS.pImpl;
- }
- bool operator!=(const AttributeSet &RHS) const {
- return pImpl != RHS.pImpl;
- }
+ bool operator==(const AttributeList &RHS) const { return pImpl == RHS.pImpl; }
+ bool operator!=(const AttributeList &RHS) const { return pImpl != RHS.pImpl; }
//===--------------------------------------------------------------------===//
- // AttributeSet Introspection
+ // AttributeList Introspection
//===--------------------------------------------------------------------===//
/// \brief Return a raw pointer that uniquely identifies this attribute list.
@@ -410,30 +512,35 @@ public:
unsigned getSlotIndex(unsigned Slot) const;
/// \brief Return the attributes at the given slot.
- AttributeSet getSlotAttributes(unsigned Slot) const;
+ AttributeList getSlotAttributes(unsigned Slot) const;
void dump() const;
};
//===----------------------------------------------------------------------===//
/// \class
-/// \brief Provide DenseMapInfo for AttributeSet.
-template<> struct DenseMapInfo<AttributeSet> {
- static inline AttributeSet getEmptyKey() {
+/// \brief Provide DenseMapInfo for AttributeList.
+template <> struct DenseMapInfo<AttributeList> {
+ static inline AttributeList getEmptyKey() {
uintptr_t Val = static_cast<uintptr_t>(-1);
Val <<= PointerLikeTypeTraits<void*>::NumLowBitsAvailable;
- return AttributeSet(reinterpret_cast<AttributeSetImpl*>(Val));
+ return AttributeList(reinterpret_cast<AttributeListImpl *>(Val));
}
- static inline AttributeSet getTombstoneKey() {
+
+ static inline AttributeList getTombstoneKey() {
uintptr_t Val = static_cast<uintptr_t>(-2);
Val <<= PointerLikeTypeTraits<void*>::NumLowBitsAvailable;
- return AttributeSet(reinterpret_cast<AttributeSetImpl*>(Val));
+ return AttributeList(reinterpret_cast<AttributeListImpl *>(Val));
}
- static unsigned getHashValue(AttributeSet AS) {
+
+ static unsigned getHashValue(AttributeList AS) {
return (unsigned((uintptr_t)AS.pImpl) >> 4) ^
(unsigned((uintptr_t)AS.pImpl) >> 9);
}
- static bool isEqual(AttributeSet LHS, AttributeSet RHS) { return LHS == RHS; }
+
+ static bool isEqual(AttributeList LHS, AttributeList RHS) {
+ return LHS == RHS;
+ }
};
//===----------------------------------------------------------------------===//
@@ -445,22 +552,19 @@ template<> struct DenseMapInfo<AttributeSet> {
class AttrBuilder {
std::bitset<Attribute::EndAttrKinds> Attrs;
std::map<std::string, std::string> TargetDepAttrs;
- uint64_t Alignment;
- uint64_t StackAlignment;
- uint64_t DerefBytes;
- uint64_t DerefOrNullBytes;
- uint64_t AllocSizeArgs;
+ uint64_t Alignment = 0;
+ uint64_t StackAlignment = 0;
+ uint64_t DerefBytes = 0;
+ uint64_t DerefOrNullBytes = 0;
+ uint64_t AllocSizeArgs = 0;
public:
- AttrBuilder()
- : Attrs(0), Alignment(0), StackAlignment(0), DerefBytes(0),
- DerefOrNullBytes(0), AllocSizeArgs(0) {}
- AttrBuilder(const Attribute &A)
- : Attrs(0), Alignment(0), StackAlignment(0), DerefBytes(0),
- DerefOrNullBytes(0), AllocSizeArgs(0) {
+ AttrBuilder() = default;
+ AttrBuilder(const Attribute &A) {
addAttribute(A);
}
- AttrBuilder(AttributeSet AS, unsigned Idx);
+ AttrBuilder(AttributeList AS, unsigned Idx);
+ AttrBuilder(AttributeSet AS);
void clear();
@@ -477,7 +581,7 @@ public:
AttrBuilder &removeAttribute(Attribute::AttrKind Val);
/// \brief Remove the attributes from the builder.
- AttrBuilder &removeAttributes(AttributeSet A, uint64_t Index);
+ AttrBuilder &removeAttributes(AttributeList A, uint64_t WithoutIndex);
/// \brief Remove the target-dependent attribute to the builder.
AttrBuilder &removeAttribute(StringRef A);
@@ -507,7 +611,7 @@ public:
/// \brief Return true if the builder has any attribute that's in the
/// specified attribute.
- bool hasAttributes(AttributeSet A, uint64_t Index) const;
+ bool hasAttributes(AttributeList A, uint64_t Index) const;
/// \brief Return true if the builder has an alignment attribute.
bool hasAlignmentAttr() const;
@@ -562,8 +666,8 @@ public:
typedef std::pair<std::string, std::string> td_type;
typedef std::map<std::string, std::string>::iterator td_iterator;
typedef std::map<std::string, std::string>::const_iterator td_const_iterator;
- typedef llvm::iterator_range<td_iterator> td_range;
- typedef llvm::iterator_range<td_const_iterator> td_const_range;
+ typedef iterator_range<td_iterator> td_range;
+ typedef iterator_range<td_const_iterator> td_const_range;
td_iterator td_begin() { return TargetDepAttrs.begin(); }
td_iterator td_end() { return TargetDepAttrs.end(); }
@@ -600,4 +704,4 @@ void mergeAttributesForInlining(Function &Caller, const Function &Callee);
} // end llvm namespace
-#endif
+#endif // LLVM_IR_ATTRIBUTES_H
diff --git a/include/llvm/IR/BasicBlock.h b/include/llvm/IR/BasicBlock.h
index 93dbd573ee16..bd210e1abf31 100644
--- a/include/llvm/IR/BasicBlock.h
+++ b/include/llvm/IR/BasicBlock.h
@@ -105,27 +105,35 @@ public:
///
/// Note: this is undefined behavior if the block does not have a parent.
const Module *getModule() const;
- Module *getModule();
+ Module *getModule() {
+ return const_cast<Module *>(
+ static_cast<const BasicBlock *>(this)->getModule());
+ }
/// \brief Returns the terminator instruction if the block is well formed or
/// null if the block is not well formed.
- TerminatorInst *getTerminator();
- const TerminatorInst *getTerminator() const;
+ const TerminatorInst *getTerminator() const LLVM_READONLY;
+ TerminatorInst *getTerminator() {
+ return const_cast<TerminatorInst *>(
+ static_cast<const BasicBlock *>(this)->getTerminator());
+ }
/// \brief Returns the call instruction calling @llvm.experimental.deoptimize
/// prior to the terminating return instruction of this basic block, if such a
/// call is present. Otherwise, returns null.
- CallInst *getTerminatingDeoptimizeCall();
- const CallInst *getTerminatingDeoptimizeCall() const {
- return const_cast<BasicBlock *>(this)->getTerminatingDeoptimizeCall();
+ const CallInst *getTerminatingDeoptimizeCall() const;
+ CallInst *getTerminatingDeoptimizeCall() {
+ return const_cast<CallInst *>(
+ static_cast<const BasicBlock *>(this)->getTerminatingDeoptimizeCall());
}
/// \brief Returns the call instruction marked 'musttail' prior to the
/// terminating return instruction of this basic block, if such a call is
/// present. Otherwise, returns null.
- CallInst *getTerminatingMustTailCall();
- const CallInst *getTerminatingMustTailCall() const {
- return const_cast<BasicBlock *>(this)->getTerminatingMustTailCall();
+ const CallInst *getTerminatingMustTailCall() const;
+ CallInst *getTerminatingMustTailCall() {
+ return const_cast<CallInst *>(
+ static_cast<const BasicBlock *>(this)->getTerminatingMustTailCall());
}
/// \brief Returns a pointer to the first instruction in this block that is
@@ -134,32 +142,36 @@ public:
/// When adding instructions to the beginning of the basic block, they should
/// be added before the returned value, not before the first instruction,
/// which might be PHI. Returns 0 is there's no non-PHI instruction.
- Instruction* getFirstNonPHI();
- const Instruction* getFirstNonPHI() const {
- return const_cast<BasicBlock*>(this)->getFirstNonPHI();
+ const Instruction* getFirstNonPHI() const;
+ Instruction* getFirstNonPHI() {
+ return const_cast<Instruction *>(
+ static_cast<const BasicBlock *>(this)->getFirstNonPHI());
}
/// \brief Returns a pointer to the first instruction in this block that is not
/// a PHINode or a debug intrinsic.
- Instruction* getFirstNonPHIOrDbg();
- const Instruction* getFirstNonPHIOrDbg() const {
- return const_cast<BasicBlock*>(this)->getFirstNonPHIOrDbg();
+ const Instruction* getFirstNonPHIOrDbg() const;
+ Instruction* getFirstNonPHIOrDbg() {
+ return const_cast<Instruction *>(
+ static_cast<const BasicBlock *>(this)->getFirstNonPHIOrDbg());
}
/// \brief Returns a pointer to the first instruction in this block that is not
/// a PHINode, a debug intrinsic, or a lifetime intrinsic.
- Instruction* getFirstNonPHIOrDbgOrLifetime();
- const Instruction* getFirstNonPHIOrDbgOrLifetime() const {
- return const_cast<BasicBlock*>(this)->getFirstNonPHIOrDbgOrLifetime();
+ const Instruction* getFirstNonPHIOrDbgOrLifetime() const;
+ Instruction* getFirstNonPHIOrDbgOrLifetime() {
+ return const_cast<Instruction *>(
+ static_cast<const BasicBlock *>(this)->getFirstNonPHIOrDbgOrLifetime());
}
/// \brief Returns an iterator to the first instruction in this block that is
/// suitable for inserting a non-PHI instruction.
///
/// In particular, it skips all PHIs and LandingPad instructions.
- iterator getFirstInsertionPt();
- const_iterator getFirstInsertionPt() const {
- return const_cast<BasicBlock*>(this)->getFirstInsertionPt();
+ const_iterator getFirstInsertionPt() const;
+ iterator getFirstInsertionPt() {
+ return static_cast<const BasicBlock *>(this)
+ ->getFirstInsertionPt().getNonConst();
}
/// \brief Unlink 'this' from the containing function, but do not delete it.
@@ -188,9 +200,10 @@ public:
/// \brief Return the predecessor of this block if it has a single predecessor
/// block. Otherwise return a null pointer.
- BasicBlock *getSinglePredecessor();
- const BasicBlock *getSinglePredecessor() const {
- return const_cast<BasicBlock*>(this)->getSinglePredecessor();
+ const BasicBlock *getSinglePredecessor() const;
+ BasicBlock *getSinglePredecessor() {
+ return const_cast<BasicBlock *>(
+ static_cast<const BasicBlock *>(this)->getSinglePredecessor());
}
/// \brief Return the predecessor of this block if it has a unique predecessor
@@ -199,27 +212,30 @@ public:
/// Note that unique predecessor doesn't mean single edge, there can be
/// multiple edges from the unique predecessor to this block (for example a
/// switch statement with multiple cases having the same destination).
- BasicBlock *getUniquePredecessor();
- const BasicBlock *getUniquePredecessor() const {
- return const_cast<BasicBlock*>(this)->getUniquePredecessor();
+ const BasicBlock *getUniquePredecessor() const;
+ BasicBlock *getUniquePredecessor() {
+ return const_cast<BasicBlock *>(
+ static_cast<const 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();
+ const BasicBlock *getSingleSuccessor() const;
+ BasicBlock *getSingleSuccessor() {
+ return const_cast<BasicBlock *>(
+ static_cast<const 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();
+ const BasicBlock *getUniqueSuccessor() const;
+ BasicBlock *getUniqueSuccessor() {
+ return const_cast<BasicBlock *>(
+ static_cast<const BasicBlock *>(this)->getUniqueSuccessor());
}
//===--------------------------------------------------------------------===//
@@ -321,8 +337,11 @@ public:
bool isLandingPad() const;
/// \brief Return the landingpad instruction associated with the landing pad.
- LandingPadInst *getLandingPadInst();
const LandingPadInst *getLandingPadInst() const;
+ LandingPadInst *getLandingPadInst() {
+ return const_cast<LandingPadInst *>(
+ static_cast<const BasicBlock *>(this)->getLandingPadInst());
+ }
private:
/// \brief Increment the internal refcount of the number of BlockAddresses
diff --git a/include/llvm/IR/CallSite.h b/include/llvm/IR/CallSite.h
index b02c89474146..79f59557a5d6 100644
--- a/include/llvm/IR/CallSite.h
+++ b/include/llvm/IR/CallSite.h
@@ -65,11 +65,9 @@ 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
- /// which is NOT a call site.
- ///
+ /// This static method is 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 which is NOT a call site.
static CallSiteBase get(ValTy *V) {
if (InstrTy *II = dyn_cast<InstrTy>(V)) {
if (II->getOpcode() == Instruction::Call)
@@ -81,38 +79,47 @@ private:
}
public:
- /// isCall - true if a CallInst is enclosed.
- /// Note that !isCall() does not mean it is an InvokeInst enclosed,
- /// it also could signify a NULL Instruction pointer.
+ /// Return true if a CallInst is enclosed. Note that !isCall() does not mean
+ /// an InvokeInst is enclosed. It may also signify a NULL instruction pointer.
bool isCall() const { return I.getInt(); }
- /// isInvoke - true if a InvokeInst is enclosed.
- ///
+ /// Return true if a InvokeInst is enclosed.
bool isInvoke() const { return getInstruction() && !I.getInt(); }
InstrTy *getInstruction() const { return I.getPointer(); }
InstrTy *operator->() const { return I.getPointer(); }
explicit operator bool() const { return I.getPointer(); }
- /// Get the basic block containing the call site
+ /// Get the basic block containing the call site.
BBTy* getParent() const { return getInstruction()->getParent(); }
- /// getCalledValue - Return the pointer to function that is being called.
- ///
+ /// Return the pointer to function that is being called.
ValTy *getCalledValue() const {
assert(getInstruction() && "Not a call or invoke instruction!");
return *getCallee();
}
- /// getCalledFunction - Return the function being called if this is a direct
- /// call, otherwise return null (if it's an indirect call).
- ///
+ /// Return the function being called if this is a direct call, otherwise
+ /// return null (if it's an indirect call).
FunTy *getCalledFunction() const {
return dyn_cast<FunTy>(getCalledValue());
}
- /// setCalledFunction - Set the callee to the specified value.
- ///
+ /// Return true if the callsite is an indirect call.
+ bool isIndirectCall() const {
+ Value *V = getCalledValue();
+ if (!V)
+ return false;
+ if (isa<FunTy>(V) || isa<Constant>(V))
+ return false;
+ if (CallInst *CI = dyn_cast<CallInst>(getInstruction())) {
+ if (CI->isInlineAsm())
+ return false;
+ }
+ return true;
+ }
+
+ /// Set the callee to the specified value.
void setCalledFunction(Value *V) {
assert(getInstruction() && "Not a call or invoke instruction!");
*getCallee() = V;
@@ -129,8 +136,7 @@ public:
return static_cast<Intrinsic::ID>(0);
}
- /// isCallee - Determine whether the passed iterator points to the
- /// callee operand's Use.
+ /// Determine whether the passed iterator points to the callee operand's Use.
bool isCallee(Value::const_user_iterator UI) const {
return isCallee(&UI.getUse());
}
@@ -138,24 +144,23 @@ public:
/// Determine whether this Use is the callee operand's Use.
bool isCallee(const Use *U) const { return getCallee() == U; }
- /// \brief Determine whether the passed iterator points to an argument
- /// operand.
+ /// Determine whether the passed iterator points to an argument operand.
bool isArgOperand(Value::const_user_iterator UI) const {
return isArgOperand(&UI.getUse());
}
- /// \brief Determine whether the passed use points to an argument operand.
+ /// Determine whether the passed use points to an argument operand.
bool isArgOperand(const Use *U) const {
assert(getInstruction() == U->getUser());
return arg_begin() <= U && U < arg_end();
}
- /// \brief Determine whether the passed iterator points to a bundle operand.
+ /// Determine whether the passed iterator points to a bundle operand.
bool isBundleOperand(Value::const_user_iterator UI) const {
return isBundleOperand(&UI.getUse());
}
- /// \brief Determine whether the passed use points to a bundle operand.
+ /// Determine whether the passed use points to a bundle operand.
bool isBundleOperand(const Use *U) const {
assert(getInstruction() == U->getUser());
if (!hasOperandBundles())
@@ -165,12 +170,12 @@ public:
OperandNo < getBundleOperandsEndIndex();
}
- /// \brief Determine whether the passed iterator points to a data operand.
+ /// Determine whether the passed iterator points to a data operand.
bool isDataOperand(Value::const_user_iterator UI) const {
return isDataOperand(&UI.getUse());
}
- /// \brief Determine whether the passed use points to a data operand.
+ /// Determine whether the passed use points to a data operand.
bool isDataOperand(const Use *U) const {
return data_operands_begin() <= U && U < data_operands_end();
}
@@ -200,8 +205,8 @@ public:
return U - arg_begin();
}
- /// arg_iterator - The type of iterator to use when looping over actual
- /// arguments at this call site.
+ /// The type of iterator to use when looping over actual arguments at this
+ /// call site.
typedef IterTy arg_iterator;
iterator_range<IterTy> args() const {
@@ -210,8 +215,7 @@ public:
bool arg_empty() const { return arg_end() == arg_begin(); }
unsigned arg_size() const { return unsigned(arg_end() - arg_begin()); }
- /// Given a value use iterator, returns the data operand that corresponds to
- /// it.
+ /// Given a value use iterator, return the data operand corresponding to it.
/// Iterator must actually correspond to a data operand.
unsigned getDataOperandNo(Value::const_user_iterator UI) const {
return getDataOperandNo(&UI.getUse());
@@ -253,21 +257,19 @@ public:
return std::distance(data_operands_begin(), data_operands_end());
}
- /// getType - Return the type of the instruction that generated this call site
- ///
+ /// Return the type of the instruction that generated this call site.
Type *getType() const { return (*this)->getType(); }
- /// getCaller - Return the caller function for this call site
- ///
+ /// Return the caller function for this call site.
FunTy *getCaller() const { return (*this)->getParent()->getParent(); }
- /// \brief Tests if this call site must be tail call optimized. Only a
- /// CallInst can be tail call optimized.
+ /// Tests if this call site must be tail call optimized. Only a CallInst can
+ /// be tail call optimized.
bool isMustTailCall() const {
return isCall() && cast<CallInst>(getInstruction())->isMustTailCall();
}
- /// \brief Tests if this call site is marked as a tail call.
+ /// Tests if this call site is marked as a tail call.
bool isTailCall() const {
return isCall() && cast<CallInst>(getInstruction())->isTailCall();
}
@@ -303,11 +305,11 @@ public:
return false;
}
- /// getCallingConv/setCallingConv - get or set the calling convention of the
- /// call.
+ /// Get the calling convention of the call.
CallingConv::ID getCallingConv() const {
CALLSITE_DELEGATE_GETTER(getCallingConv());
}
+ /// Set the calling convention of the call.
void setCallingConv(CallingConv::ID CC) {
CALLSITE_DELEGATE_SETTER(setCallingConv(CC));
}
@@ -320,12 +322,12 @@ public:
CALLSITE_DELEGATE_SETTER(mutateFunctionType(Ty));
}
- /// getAttributes/setAttributes - get or set the parameter attributes of
- /// the call.
- AttributeSet getAttributes() const {
+ /// Get the parameter attributes of the call.
+ AttributeList getAttributes() const {
CALLSITE_DELEGATE_GETTER(getAttributes());
}
- void setAttributes(AttributeSet PAL) {
+ /// Set the parameter attributes of the call.
+ void setAttributes(AttributeList PAL) {
CALLSITE_DELEGATE_SETTER(setAttributes(PAL));
}
@@ -345,19 +347,24 @@ public:
CALLSITE_DELEGATE_SETTER(removeAttribute(i, Kind));
}
- /// \brief Return true if this function has the given attribute.
+ /// Return true if this function has the given attribute.
bool hasFnAttr(Attribute::AttrKind Kind) const {
CALLSITE_DELEGATE_GETTER(hasFnAttr(Kind));
}
- /// \brief Return true if this function has the given attribute.
+ /// Return true if this function has the given attribute.
bool hasFnAttr(StringRef Kind) const {
CALLSITE_DELEGATE_GETTER(hasFnAttr(Kind));
}
- /// \brief Return true if the call or the callee has the given attribute.
- bool paramHasAttr(unsigned i, Attribute::AttrKind Kind) const {
- CALLSITE_DELEGATE_GETTER(paramHasAttr(i, Kind));
+ /// Return true if this return value has the given attribute.
+ bool hasRetAttr(Attribute::AttrKind Kind) const {
+ CALLSITE_DELEGATE_GETTER(hasRetAttr(Kind));
+ }
+
+ /// Return true if the call or the callee has the given attribute.
+ bool paramHasAttr(unsigned ArgNo, Attribute::AttrKind Kind) const {
+ CALLSITE_DELEGATE_GETTER(paramHasAttr(ArgNo, Kind));
}
Attribute getAttribute(unsigned i, Attribute::AttrKind Kind) const {
@@ -368,8 +375,8 @@ public:
CALLSITE_DELEGATE_GETTER(getAttribute(i, Kind));
}
- /// \brief Return true if the data operand at index \p i directly or
- /// indirectly has the attribute \p A.
+ /// Return true if the data operand at index \p i directly or indirectly has
+ /// the attribute \p A.
///
/// Normal call or invoke arguments have per operand attributes, as specified
/// in the attribute set attached to this instruction, while operand bundle
@@ -379,37 +386,36 @@ public:
CALLSITE_DELEGATE_GETTER(dataOperandHasImpliedAttr(i, Kind));
}
- /// @brief Extract the alignment for a call or parameter (0=unknown).
+ /// Extract the alignment for a call or parameter (0=unknown).
uint16_t getParamAlignment(uint16_t i) const {
CALLSITE_DELEGATE_GETTER(getParamAlignment(i));
}
- /// @brief Extract the number of dereferenceable bytes for a call or
- /// parameter (0=unknown).
+ /// Extract the number of dereferenceable bytes for a call or parameter
+ /// (0=unknown).
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
+ /// 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 Determine if the parameter or return value is marked with NoAlias
+ /// Determine if the parameter or return value is marked with NoAlias
/// attribute.
/// @param n The parameter to check. 1 is the first parameter, 0 is the return
bool doesNotAlias(unsigned n) const {
CALLSITE_DELEGATE_GETTER(doesNotAlias(n));
}
- /// \brief Return true if the call should not be treated as a call to a
- /// builtin.
+ /// Return true if the call should not be treated as a call to a builtin.
bool isNoBuiltin() const {
CALLSITE_DELEGATE_GETTER(isNoBuiltin());
}
- /// @brief Return true if the call should not be inlined.
+ /// Return true if the call should not be inlined.
bool isNoInline() const {
CALLSITE_DELEGATE_GETTER(isNoInline());
}
@@ -417,7 +423,7 @@ public:
CALLSITE_DELEGATE_SETTER(setIsNoInline(Value));
}
- /// @brief Determine if the call does not access memory.
+ /// Determine if the call does not access memory.
bool doesNotAccessMemory() const {
CALLSITE_DELEGATE_GETTER(doesNotAccessMemory());
}
@@ -425,7 +431,7 @@ public:
CALLSITE_DELEGATE_SETTER(setDoesNotAccessMemory());
}
- /// @brief Determine if the call does not access or only reads memory.
+ /// Determine if the call does not access or only reads memory.
bool onlyReadsMemory() const {
CALLSITE_DELEGATE_GETTER(onlyReadsMemory());
}
@@ -433,7 +439,7 @@ public:
CALLSITE_DELEGATE_SETTER(setOnlyReadsMemory());
}
- /// @brief Determine if the call does not access or only writes memory.
+ /// Determine if the call does not access or only writes memory.
bool doesNotReadMemory() const {
CALLSITE_DELEGATE_GETTER(doesNotReadMemory());
}
@@ -441,7 +447,7 @@ public:
CALLSITE_DELEGATE_SETTER(setDoesNotReadMemory());
}
- /// @brief Determine if the call can access memmory only using pointers based
+ /// Determine if the call can access memmory only using pointers based
/// on its arguments.
bool onlyAccessesArgMemory() const {
CALLSITE_DELEGATE_GETTER(onlyAccessesArgMemory());
@@ -450,7 +456,7 @@ public:
CALLSITE_DELEGATE_SETTER(setOnlyAccessesArgMemory());
}
- /// @brief Determine if the call cannot return.
+ /// Determine if the call cannot return.
bool doesNotReturn() const {
CALLSITE_DELEGATE_GETTER(doesNotReturn());
}
@@ -458,7 +464,7 @@ public:
CALLSITE_DELEGATE_SETTER(setDoesNotReturn());
}
- /// @brief Determine if the call cannot unwind.
+ /// Determine if the call cannot unwind.
bool doesNotThrow() const {
CALLSITE_DELEGATE_GETTER(doesNotThrow());
}
@@ -466,7 +472,7 @@ public:
CALLSITE_DELEGATE_SETTER(setDoesNotThrow());
}
- /// @brief Determine if the call can be duplicated.
+ /// Determine if the call can be duplicated.
bool cannotDuplicate() const {
CALLSITE_DELEGATE_GETTER(cannotDuplicate());
}
@@ -474,7 +480,7 @@ public:
CALLSITE_DELEGATE_GETTER(setCannotDuplicate());
}
- /// @brief Determine if the call is convergent.
+ /// Determine if the call is convergent.
bool isConvergent() const {
CALLSITE_DELEGATE_GETTER(isConvergent());
}
@@ -546,31 +552,31 @@ public:
cast<InvokeInst>(II)->getOperandBundlesAsDefs(Defs);
}
- /// @brief Determine whether this data operand is not captured.
+ /// Determine whether this data operand is not captured.
bool doesNotCapture(unsigned OpNo) const {
return dataOperandHasImpliedAttr(OpNo + 1, Attribute::NoCapture);
}
- /// @brief Determine whether this argument is passed by value.
+ /// Determine whether this argument is passed by value.
bool isByValArgument(unsigned ArgNo) const {
- return paramHasAttr(ArgNo + 1, Attribute::ByVal);
+ return paramHasAttr(ArgNo, Attribute::ByVal);
}
- /// @brief Determine whether this argument is passed in an alloca.
+ /// Determine whether this argument is passed in an alloca.
bool isInAllocaArgument(unsigned ArgNo) const {
- return paramHasAttr(ArgNo + 1, Attribute::InAlloca);
+ return paramHasAttr(ArgNo, Attribute::InAlloca);
}
- /// @brief Determine whether this argument is passed by value or in an alloca.
+ /// Determine whether this argument is passed by value or in an alloca.
bool isByValOrInAllocaArgument(unsigned ArgNo) const {
- return paramHasAttr(ArgNo + 1, Attribute::ByVal) ||
- paramHasAttr(ArgNo + 1, Attribute::InAlloca);
+ return paramHasAttr(ArgNo, Attribute::ByVal) ||
+ paramHasAttr(ArgNo, Attribute::InAlloca);
}
- /// @brief Determine if there are is an inalloca argument. Only the last
- /// argument can have the inalloca attribute.
+ /// Determine if there are is an inalloca argument. Only the last argument can
+ /// have the inalloca attribute.
bool hasInAllocaArgument() const {
- return paramHasAttr(arg_size(), Attribute::InAlloca);
+ return !arg_empty() && paramHasAttr(arg_size() - 1, Attribute::InAlloca);
}
bool doesNotAccessMemory(unsigned OpNo) const {
@@ -582,11 +588,16 @@ public:
dataOperandHasImpliedAttr(OpNo + 1, Attribute::ReadNone);
}
- /// @brief Return true if the return value is known to be not null.
+ bool doesNotReadMemory(unsigned OpNo) const {
+ return dataOperandHasImpliedAttr(OpNo + 1, Attribute::WriteOnly) ||
+ dataOperandHasImpliedAttr(OpNo + 1, Attribute::ReadNone);
+ }
+
+ /// Return true if the return value is known to be not null.
/// This may be because it has the nonnull attribute, or because at least
/// one byte is dereferenceable and the pointer is in addrspace(0).
bool isReturnNonNull() const {
- if (paramHasAttr(0, Attribute::NonNull))
+ if (hasRetAttr(Attribute::NonNull))
return true;
else if (getDereferenceableBytes(0) > 0 &&
getType()->getPointerAddressSpace() == 0)
@@ -595,8 +606,8 @@ public:
return false;
}
- /// hasArgument - Returns true if this CallSite passes the given Value* as an
- /// argument to the called function.
+ /// Returns true if this CallSite passes the given Value* as an argument to
+ /// the called function.
bool hasArgument(const Value *Arg) const {
for (arg_iterator AI = this->arg_begin(), E = this->arg_end(); AI != E;
++AI)
@@ -661,7 +672,7 @@ template <> struct DenseMapInfo<CallSite> {
}
};
-/// ImmutableCallSite - establish a view to a call site for examination
+/// Establish a view to a call site for examination.
class ImmutableCallSite : public CallSiteBase<> {
public:
ImmutableCallSite() = default;
diff --git a/include/llvm/IR/Comdat.h b/include/llvm/IR/Comdat.h
index f4a391c31ae2..fa87093ca50a 100644
--- a/include/llvm/IR/Comdat.h
+++ b/include/llvm/IR/Comdat.h
@@ -1,4 +1,4 @@
-//===-- llvm/IR/Comdat.h - Comdat definitions -------------------*- C++ -*-===//
+//===- llvm/IR/Comdat.h - Comdat definitions --------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -51,8 +51,8 @@ private:
Comdat();
// Points to the map in Module.
- StringMapEntry<Comdat> *Name;
- SelectionKind SK;
+ StringMapEntry<Comdat> *Name = nullptr;
+ SelectionKind SK = Any;
};
inline raw_ostream &operator<<(raw_ostream &OS, const Comdat &C) {
diff --git a/include/llvm/IR/Constant.h b/include/llvm/IR/Constant.h
index 99c970ebb633..3b3694e7e60d 100644
--- a/include/llvm/IR/Constant.h
+++ b/include/llvm/IR/Constant.h
@@ -152,12 +152,13 @@ public:
/// hanging off of the globals.
void removeDeadConstantUsers() const;
- Constant *stripPointerCasts() {
+ const Constant *stripPointerCasts() const {
return cast<Constant>(Value::stripPointerCasts());
}
- const Constant *stripPointerCasts() const {
- return const_cast<Constant*>(this)->stripPointerCasts();
+ Constant *stripPointerCasts() {
+ return const_cast<Constant*>(
+ static_cast<const Constant *>(this)->stripPointerCasts());
}
};
diff --git a/include/llvm/IR/ConstantRange.h b/include/llvm/IR/ConstantRange.h
index 27a9b1364448..6d704666933f 100644
--- a/include/llvm/IR/ConstantRange.h
+++ b/include/llvm/IR/ConstantRange.h
@@ -45,9 +45,6 @@ class MDNode;
class ConstantRange {
APInt Lower, Upper;
- // If we have move semantics, pass APInts by value and move them into place.
- typedef APInt APIntMoveTy;
-
public:
/// Initialize a full (the default) or empty set for the specified bit width.
///
@@ -55,12 +52,12 @@ public:
/// Initialize a range to hold the single specified value.
///
- ConstantRange(APIntMoveTy Value);
+ ConstantRange(APInt Value);
/// @brief Initialize a range of values explicitly. This will assert out if
/// Lower==Upper and Lower != Min or Max value for its type. It will also
/// assert out if the two APInt's are not the same bit width.
- ConstantRange(APIntMoveTy Lower, APIntMoveTy Upper);
+ ConstantRange(APInt Lower, APInt Upper);
/// Produce the smallest range such that all values that may satisfy the given
/// predicate with any value contained within Other is contained in the
@@ -184,6 +181,10 @@ public:
///
APInt getSetSize() const;
+ /// Compare set size of this range with the range CR.
+ ///
+ bool isSizeStrictlySmallerThanOf(const ConstantRange &CR) const;
+
/// Return the largest unsigned value contained in the ConstantRange.
///
APInt getUnsignedMax() const;
diff --git a/include/llvm/IR/Constants.h b/include/llvm/IR/Constants.h
index cbefa3f05dfc..ad83b21c7bf3 100644
--- a/include/llvm/IR/Constants.h
+++ b/include/llvm/IR/Constants.h
@@ -138,7 +138,7 @@ public:
static Constant *get(Type* Ty, const APInt& V);
/// Return the constant as an APInt value reference. This allows clients to
- /// obtain a copy of the value, with all its precision in tact.
+ /// obtain a full-precision copy of the value.
/// @brief Return the constant's value.
inline const APInt &getValue() const {
return Val;
diff --git a/include/llvm/IR/DIBuilder.h b/include/llvm/IR/DIBuilder.h
index 48cb7fe5df6f..69bd5c847a8d 100644
--- a/include/llvm/IR/DIBuilder.h
+++ b/include/llvm/IR/DIBuilder.h
@@ -105,13 +105,17 @@ namespace llvm {
/// out into.
/// \param Kind The kind of debug information to generate.
/// \param DWOId The DWOId if this is a split skeleton compile unit.
+ /// \param SplitDebugInlining Whether to emit inline debug info.
+ /// \param DebugInfoForProfiling Whether to emit extra debug info for
+ /// profile collection.
DICompileUnit *
createCompileUnit(unsigned Lang, DIFile *File, StringRef Producer,
bool isOptimized, StringRef Flags, unsigned RV,
StringRef SplitName = StringRef(),
DICompileUnit::DebugEmissionKind Kind =
DICompileUnit::DebugEmissionKind::FullDebug,
- uint64_t DWOId = 0, bool SplitDebugInlining = true);
+ uint64_t DWOId = 0, bool SplitDebugInlining = true,
+ bool DebugInfoForProfiling = false);
/// Create a file descriptor to hold debugging information for a file.
/// \param Filename File name.
@@ -164,12 +168,15 @@ namespace llvm {
DIDerivedType *createQualifiedType(unsigned Tag, DIType *FromTy);
/// 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)
+ /// \param PointeeTy Type pointed by this pointer.
+ /// \param SizeInBits Size.
+ /// \param AlignInBits Alignment. (optional)
+ /// \param DWARFAddressSpace DWARF address space. (optional)
+ /// \param Name Pointer type name. (optional)
DIDerivedType *createPointerType(DIType *PointeeTy, uint64_t SizeInBits,
uint32_t AlignInBits = 0,
+ Optional<unsigned> DWARFAddressSpace =
+ None,
StringRef Name = "");
/// Create debugging information entry for a pointer to member.
@@ -186,7 +193,9 @@ namespace llvm {
/// style reference or rvalue reference type.
DIDerivedType *createReferenceType(unsigned Tag, DIType *RTy,
uint64_t SizeInBits = 0,
- uint32_t AlignInBits = 0);
+ uint32_t AlignInBits = 0,
+ Optional<unsigned> DWARFAddressSpace =
+ None);
/// Create debugging information entry for a typedef.
/// \param Ty Original type.
@@ -431,13 +440,6 @@ namespace llvm {
DINode::DIFlags Flags = DINode::FlagZero,
unsigned CC = 0);
- /// Create an external type reference.
- /// \param Tag Dwarf TAG.
- /// \param File File in which the type is defined.
- /// \param UniqueIdentifier A unique identifier for the type.
- DICompositeType *createExternalTypeRef(unsigned Tag, DIFile *File,
- StringRef UniqueIdentifier);
-
/// Create a new DIType* with "artificial" flag set.
DIType *createArtificialType(DIType *Ty);
diff --git a/include/llvm/IR/DataLayout.h b/include/llvm/IR/DataLayout.h
index 6f37669f9768..1930d48577d4 100644
--- a/include/llvm/IR/DataLayout.h
+++ b/include/llvm/IR/DataLayout.h
@@ -104,6 +104,7 @@ private:
/// Defaults to false.
bool BigEndian;
+ unsigned AllocaAddrSpace;
unsigned StackNaturalAlign;
enum ManglingModeT {
@@ -118,8 +119,19 @@ private:
SmallVector<unsigned char, 8> LegalIntWidths;
- /// \brief Primitive type alignment data.
- SmallVector<LayoutAlignElem, 16> Alignments;
+ /// \brief Primitive type alignment data. This is sorted by type and bit
+ /// width during construction.
+ typedef SmallVector<LayoutAlignElem, 16> AlignmentsTy;
+ AlignmentsTy Alignments;
+
+ AlignmentsTy::const_iterator
+ findAlignmentLowerBound(AlignTypeEnum AlignType, uint32_t BitWidth) const {
+ return const_cast<DataLayout *>(this)->findAlignmentLowerBound(AlignType,
+ BitWidth);
+ }
+
+ AlignmentsTy::iterator
+ findAlignmentLowerBound(AlignTypeEnum AlignType, uint32_t BitWidth);
/// \brief The string representation used to create this DataLayout
std::string StringRepresentation;
@@ -134,14 +146,6 @@ private:
PointersTy::iterator findPointerLowerBound(uint32_t AddressSpace);
- /// This member is a signal that a requested alignment type and bit width were
- /// not found in the SmallVector.
- static const LayoutAlignElem InvalidAlignmentElem;
-
- /// This member is a signal that a requested pointer type and bit width were
- /// not found in the DenseSet.
- static const PointerAlignElem InvalidPointerElem;
-
// The StructType -> StructLayout map.
mutable void *LayoutMap;
@@ -159,22 +163,6 @@ private:
/// Internal helper method that returns requested alignment for type.
unsigned getAlignment(Type *Ty, bool abi_or_pref) const;
- /// \brief Valid alignment predicate.
- ///
- /// Predicate that tests a LayoutAlignElem reference returned by get() against
- /// InvalidAlignmentElem.
- bool validAlignment(const LayoutAlignElem &align) const {
- return &align != &InvalidAlignmentElem;
- }
-
- /// \brief Valid pointer predicate.
- ///
- /// Predicate that tests a PointerAlignElem reference returned by get()
- /// against \c InvalidPointerElem.
- bool validPointer(const PointerAlignElem &align) const {
- return &align != &InvalidPointerElem;
- }
-
/// Parses a target data specification string. Assert if the string is
/// malformed.
void parseSpecifier(StringRef LayoutDescription);
@@ -199,6 +187,7 @@ public:
clear();
StringRepresentation = DL.StringRepresentation;
BigEndian = DL.isBigEndian();
+ AllocaAddrSpace = DL.AllocaAddrSpace;
StackNaturalAlign = DL.StackNaturalAlign;
ManglingMode = DL.ManglingMode;
LegalIntWidths = DL.LegalIntWidths;
@@ -254,6 +243,7 @@ public:
}
unsigned getStackAlignment() const { return StackNaturalAlign; }
+ unsigned getAllocaAddrSpace() const { return AllocaAddrSpace; }
bool hasMicrosoftFastStdCallMangling() const {
return ManglingMode == MM_WinCOFFX86;
diff --git a/include/llvm/IR/DebugInfoFlags.def b/include/llvm/IR/DebugInfoFlags.def
index 87f3dc9dbdd3..7ea6346998fe 100644
--- a/include/llvm/IR/DebugInfoFlags.def
+++ b/include/llvm/IR/DebugInfoFlags.def
@@ -34,7 +34,8 @@ HANDLE_DI_FLAG((1 << 11), Vector)
HANDLE_DI_FLAG((1 << 12), StaticMember)
HANDLE_DI_FLAG((1 << 13), LValueReference)
HANDLE_DI_FLAG((1 << 14), RValueReference)
-HANDLE_DI_FLAG((1 << 15), ExternalTypeRef)
+// 15 was formerly ExternalTypeRef, but this was never used.
+HANDLE_DI_FLAG((1 << 15), Reserved)
HANDLE_DI_FLAG((1 << 16), SingleInheritance)
HANDLE_DI_FLAG((2 << 16), MultipleInheritance)
HANDLE_DI_FLAG((3 << 16), VirtualInheritance)
diff --git a/include/llvm/IR/DebugInfoMetadata.h b/include/llvm/IR/DebugInfoMetadata.h
index 187855225c50..8a924b40143a 100644
--- a/include/llvm/IR/DebugInfoMetadata.h
+++ b/include/llvm/IR/DebugInfoMetadata.h
@@ -629,7 +629,6 @@ public:
bool isStaticMember() const { return getFlags() & FlagStaticMember; }
bool isLValueReference() const { return getFlags() & FlagLValueReference; }
bool isRValueReference() const { return getFlags() & FlagRValueReference; }
- bool isExternalTypeRef() const { return getFlags() & FlagExternalTypeRef; }
static bool classof(const Metadata *MD) {
switch (MD->getMetadataID()) {
@@ -710,37 +709,45 @@ class DIDerivedType : public DIType {
friend class LLVMContextImpl;
friend class MDNode;
+ /// \brief The DWARF address space of the memory pointed to or referenced by a
+ /// pointer or reference type respectively.
+ Optional<unsigned> DWARFAddressSpace;
+
DIDerivedType(LLVMContext &C, StorageType Storage, unsigned Tag,
unsigned Line, uint64_t SizeInBits, uint32_t AlignInBits,
- uint64_t OffsetInBits, DIFlags Flags, ArrayRef<Metadata *> Ops)
+ uint64_t OffsetInBits, Optional<unsigned> DWARFAddressSpace,
+ DIFlags Flags, ArrayRef<Metadata *> Ops)
: DIType(C, DIDerivedTypeKind, Storage, Tag, Line, SizeInBits,
- AlignInBits, OffsetInBits, Flags, Ops) {}
+ AlignInBits, OffsetInBits, Flags, Ops),
+ DWARFAddressSpace(DWARFAddressSpace) {}
~DIDerivedType() = default;
static DIDerivedType *getImpl(LLVMContext &Context, unsigned Tag,
StringRef Name, DIFile *File, unsigned Line,
DIScopeRef Scope, DITypeRef BaseType,
uint64_t SizeInBits, uint32_t AlignInBits,
- uint64_t OffsetInBits, DIFlags Flags,
- Metadata *ExtraData, StorageType Storage,
- bool ShouldCreate = true) {
+ uint64_t OffsetInBits,
+ Optional<unsigned> DWARFAddressSpace,
+ DIFlags 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);
+ DWARFAddressSpace, Flags, ExtraData, Storage, ShouldCreate);
}
static DIDerivedType *getImpl(LLVMContext &Context, unsigned Tag,
MDString *Name, Metadata *File, unsigned Line,
Metadata *Scope, Metadata *BaseType,
uint64_t SizeInBits, uint32_t AlignInBits,
- uint64_t OffsetInBits, DIFlags Flags,
- Metadata *ExtraData, StorageType Storage,
- bool ShouldCreate = true);
+ uint64_t OffsetInBits,
+ Optional<unsigned> DWARFAddressSpace,
+ DIFlags 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());
+ getAlignInBits(), getOffsetInBits(),
+ getDWARFAddressSpace(), getFlags(), getExtraData());
}
public:
@@ -748,24 +755,32 @@ public:
(unsigned Tag, MDString *Name, Metadata *File,
unsigned Line, Metadata *Scope, Metadata *BaseType,
uint64_t SizeInBits, uint32_t AlignInBits,
- uint64_t OffsetInBits, DIFlags Flags,
+ uint64_t OffsetInBits,
+ Optional<unsigned> DWARFAddressSpace, DIFlags Flags,
Metadata *ExtraData = nullptr),
(Tag, Name, File, Line, Scope, BaseType, SizeInBits,
- AlignInBits, OffsetInBits, Flags, ExtraData))
+ AlignInBits, OffsetInBits, DWARFAddressSpace, Flags,
+ ExtraData))
DEFINE_MDNODE_GET(DIDerivedType,
(unsigned Tag, StringRef Name, DIFile *File, unsigned Line,
DIScopeRef Scope, DITypeRef BaseType, uint64_t SizeInBits,
uint32_t AlignInBits, uint64_t OffsetInBits,
- DIFlags Flags, Metadata *ExtraData = nullptr),
+ Optional<unsigned> DWARFAddressSpace, DIFlags Flags,
+ Metadata *ExtraData = nullptr),
(Tag, Name, File, Line, Scope, BaseType, SizeInBits,
- AlignInBits, OffsetInBits, Flags, ExtraData))
+ AlignInBits, OffsetInBits, DWARFAddressSpace, Flags,
+ ExtraData))
TempDIDerivedType clone() const { return cloneImpl(); }
- //// Get the base type this is derived from.
+ /// Get the base type this is derived from.
DITypeRef getBaseType() const { return DITypeRef(getRawBaseType()); }
Metadata *getRawBaseType() const { return getOperand(3); }
+ /// \returns The DWARF address space of the memory pointed to or referenced by
+ /// a pointer or reference type respectively.
+ Optional<unsigned> getDWARFAddressSpace() const { return DWARFAddressSpace; }
+
/// Get extra data associated with this derived type.
///
/// Class type for pointer-to-members, objective-c property node for ivars,
@@ -1044,15 +1059,17 @@ private:
unsigned EmissionKind;
uint64_t DWOId;
bool SplitDebugInlining;
+ bool DebugInfoForProfiling;
DICompileUnit(LLVMContext &C, StorageType Storage, unsigned SourceLanguage,
bool IsOptimized, unsigned RuntimeVersion,
unsigned EmissionKind, uint64_t DWOId, bool SplitDebugInlining,
- ArrayRef<Metadata *> Ops)
+ bool DebugInfoForProfiling, ArrayRef<Metadata *> Ops)
: DIScope(C, DICompileUnitKind, Storage, dwarf::DW_TAG_compile_unit, Ops),
SourceLanguage(SourceLanguage), IsOptimized(IsOptimized),
RuntimeVersion(RuntimeVersion), EmissionKind(EmissionKind),
- DWOId(DWOId), SplitDebugInlining(SplitDebugInlining) {
+ DWOId(DWOId), SplitDebugInlining(SplitDebugInlining),
+ DebugInfoForProfiling(DebugInfoForProfiling) {
assert(Storage != Uniqued);
}
~DICompileUnit() = default;
@@ -1065,15 +1082,16 @@ private:
DIScopeArray RetainedTypes,
DIGlobalVariableExpressionArray GlobalVariables,
DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros,
- uint64_t DWOId, bool SplitDebugInlining, StorageType Storage,
- bool ShouldCreate = true) {
+ uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling,
+ 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(),
GlobalVariables.get(), ImportedEntities.get(), Macros.get(),
- DWOId, SplitDebugInlining, Storage, ShouldCreate);
+ DWOId, SplitDebugInlining, DebugInfoForProfiling, Storage,
+ ShouldCreate);
}
static DICompileUnit *
getImpl(LLVMContext &Context, unsigned SourceLanguage, Metadata *File,
@@ -1082,7 +1100,8 @@ private:
unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes,
Metadata *GlobalVariables, Metadata *ImportedEntities,
Metadata *Macros, uint64_t DWOId, bool SplitDebugInlining,
- StorageType Storage, bool ShouldCreate = true);
+ bool DebugInfoForProfiling, StorageType Storage,
+ bool ShouldCreate = true);
TempDICompileUnit cloneImpl() const {
return getTemporary(getContext(), getSourceLanguage(), getFile(),
@@ -1090,7 +1109,8 @@ private:
getRuntimeVersion(), getSplitDebugFilename(),
getEmissionKind(), getEnumTypes(), getRetainedTypes(),
getGlobalVariables(), getImportedEntities(),
- getMacros(), DWOId, getSplitDebugInlining());
+ getMacros(), DWOId, getSplitDebugInlining(),
+ getDebugInfoForProfiling());
}
public:
@@ -1105,10 +1125,11 @@ public:
DICompositeTypeArray EnumTypes, DIScopeArray RetainedTypes,
DIGlobalVariableExpressionArray GlobalVariables,
DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros,
- uint64_t DWOId, bool SplitDebugInlining),
+ uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling),
(SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion,
SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes,
- GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining))
+ GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining,
+ DebugInfoForProfiling))
DEFINE_MDNODE_GET_DISTINCT_TEMPORARY(
DICompileUnit,
(unsigned SourceLanguage, Metadata *File, MDString *Producer,
@@ -1116,10 +1137,11 @@ public:
MDString *SplitDebugFilename, unsigned EmissionKind, Metadata *EnumTypes,
Metadata *RetainedTypes, Metadata *GlobalVariables,
Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId,
- bool SplitDebugInlining),
+ bool SplitDebugInlining, bool DebugInfoForProfiling),
(SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion,
SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes,
- GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining))
+ GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining,
+ DebugInfoForProfiling))
TempDICompileUnit clone() const { return cloneImpl(); }
@@ -1129,6 +1151,7 @@ public:
DebugEmissionKind getEmissionKind() const {
return (DebugEmissionKind)EmissionKind;
}
+ bool getDebugInfoForProfiling() const { return DebugInfoForProfiling; }
StringRef getProducer() const { return getStringOperand(1); }
StringRef getFlags() const { return getStringOperand(2); }
StringRef getSplitDebugFilename() const { return getStringOperand(3); }
@@ -1246,6 +1269,28 @@ class DILocation : public MDNode {
static_cast<Metadata *>(InlinedAt), Storage, ShouldCreate);
}
+ /// With a given unsigned int \p U, use up to 13 bits to represent it.
+ /// old_bit 1~5 --> new_bit 1~5
+ /// old_bit 6~12 --> new_bit 7~13
+ /// new_bit_6 is 0 if higher bits (7~13) are all 0
+ static unsigned getPrefixEncodingFromUnsigned(unsigned U) {
+ U &= 0xfff;
+ return U > 0x1f ? (((U & 0xfe0) << 1) | (U & 0x1f) | 0x20) : U;
+ }
+
+ /// Reverse transformation as getPrefixEncodingFromUnsigned.
+ static unsigned getUnsignedFromPrefixEncoding(unsigned U) {
+ return (U & 0x20) ? (((U >> 1) & 0xfe0) | (U & 0x1f)) : (U & 0x1f);
+ }
+
+ /// Returns the next component stored in discriminator.
+ static unsigned getNextComponentInDiscriminator(unsigned D) {
+ if ((D & 1) == 0)
+ return D >> ((D & 0x40) ? 14 : 7);
+ else
+ return D >> 1;
+ }
+
TempDILocation cloneImpl() const {
// Get the raw scope/inlinedAt since it is possible to invoke this on
// a DILocation containing temporary metadata.
@@ -1307,10 +1352,48 @@ public:
///
/// DWARF discriminators distinguish identical file locations between
/// instructions that are on different basic blocks.
+ ///
+ /// There are 3 components stored in discriminator, from lower bits:
+ ///
+ /// Base discriminator: assigned by AddDiscriminators pass to identify IRs
+ /// that are defined by the same source line, but
+ /// different basic blocks.
+ /// Duplication factor: assigned by optimizations that will scale down
+ /// the execution frequency of the original IR.
+ /// Copy Identifier: assigned by optimizations that clones the IR.
+ /// Each copy of the IR will be assigned an identifier.
+ ///
+ /// Encoding:
+ ///
+ /// The above 3 components are encoded into a 32bit unsigned integer in
+ /// order. If the lowest bit is 1, the current component is empty, and the
+ /// next component will start in the next bit. Otherwise, the the current
+ /// component is non-empty, and its content starts in the next bit. The
+ /// length of each components is either 5 bit or 12 bit: if the 7th bit
+ /// is 0, the bit 2~6 (5 bits) are used to represent the component; if the
+ /// 7th bit is 1, the bit 2~6 (5 bits) and 8~14 (7 bits) are combined to
+ /// represent the component.
+
inline unsigned getDiscriminator() const;
/// Returns a new DILocation with updated \p Discriminator.
- inline DILocation *cloneWithDiscriminator(unsigned Discriminator) const;
+ inline const DILocation *cloneWithDiscriminator(unsigned Discriminator) const;
+
+ /// Returns a new DILocation with updated base discriminator \p BD.
+ inline const DILocation *setBaseDiscriminator(unsigned BD) const;
+
+ /// Returns the duplication factor stored in the discriminator.
+ inline unsigned getDuplicationFactor() const;
+
+ /// Returns the copy identifier stored in the discriminator.
+ inline unsigned getCopyIdentifier() const;
+
+ /// Returns the base discriminator stored in the discriminator.
+ inline unsigned getBaseDiscriminator() const;
+
+ /// Returns a new DILocation with duplication factor \p DF encoded in the
+ /// discriminator.
+ inline const DILocation *cloneWithDuplicationFactor(unsigned DF) const;
/// When two instructions are combined into a single instruction we also
/// need to combine the original locations into a single location.
@@ -1333,6 +1416,30 @@ public:
return nullptr;
}
+ /// Returns the base discriminator for a given encoded discriminator \p D.
+ static unsigned getBaseDiscriminatorFromDiscriminator(unsigned D) {
+ if ((D & 1) == 0)
+ return getUnsignedFromPrefixEncoding(D >> 1);
+ else
+ return 0;
+ }
+
+ /// Returns the duplication factor for a given encoded discriminator \p D.
+ static unsigned getDuplicationFactorFromDiscriminator(unsigned D) {
+ D = getNextComponentInDiscriminator(D);
+ if (D == 0 || (D & 1))
+ return 1;
+ else
+ return getUnsignedFromPrefixEncoding(D >> 1);
+ }
+
+ /// Returns the copy identifier for a given encoded discriminator \p D.
+ static unsigned getCopyIdentifierFromDiscriminator(unsigned D) {
+ return getUnsignedFromPrefixEncoding(getNextComponentInDiscriminator(
+ getNextComponentInDiscriminator(D)));
+ }
+
+
Metadata *getRawScope() const { return getOperand(0); }
Metadata *getRawInlinedAt() const {
if (getNumOperands() == 2)
@@ -1343,6 +1450,7 @@ public:
static bool classof(const Metadata *MD) {
return MD->getMetadataID() == DILocationKind;
}
+
};
/// Subprogram description.
@@ -1676,7 +1784,8 @@ unsigned DILocation::getDiscriminator() const {
return 0;
}
-DILocation *DILocation::cloneWithDiscriminator(unsigned Discriminator) const {
+const DILocation *
+DILocation::cloneWithDiscriminator(unsigned Discriminator) const {
DIScope *Scope = getScope();
// Skip all parent DILexicalBlockFile that already have a discriminator
// assigned. We do not want to have nested DILexicalBlockFiles that have
@@ -1692,6 +1801,42 @@ DILocation *DILocation::cloneWithDiscriminator(unsigned Discriminator) const {
getInlinedAt());
}
+unsigned DILocation::getBaseDiscriminator() const {
+ return getBaseDiscriminatorFromDiscriminator(getDiscriminator());
+}
+
+unsigned DILocation::getDuplicationFactor() const {
+ return getDuplicationFactorFromDiscriminator(getDiscriminator());
+}
+
+unsigned DILocation::getCopyIdentifier() const {
+ return getCopyIdentifierFromDiscriminator(getDiscriminator());
+}
+
+const DILocation *DILocation::setBaseDiscriminator(unsigned D) const {
+ if (D == 0)
+ return this;
+ else
+ return cloneWithDiscriminator(getPrefixEncodingFromUnsigned(D) << 1);
+}
+
+const DILocation *DILocation::cloneWithDuplicationFactor(unsigned DF) const {
+ DF *= getDuplicationFactor();
+ if (DF <= 1)
+ return this;
+
+ unsigned BD = getBaseDiscriminator();
+ unsigned CI = getCopyIdentifier() << (DF > 0x1f ? 14 : 7);
+ unsigned D = CI | (getPrefixEncodingFromUnsigned(DF) << 1);
+
+ if (BD == 0)
+ D = (D << 1) | 1;
+ else
+ D = (D << (BD > 0x1f ? 14 : 7)) | (getPrefixEncodingFromUnsigned(BD) << 1);
+
+ return cloneWithDiscriminator(D);
+}
+
class DINamespace : public DIScope {
friend class LLVMContextImpl;
friend class MDNode;
@@ -1918,7 +2063,7 @@ protected:
DIVariable(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Line,
ArrayRef<Metadata *> Ops, uint32_t AlignInBits = 0)
: DINode(C, ID, Storage, dwarf::DW_TAG_variable, Ops), Line(Line),
- AlignInBits(AlignInBits) {}
+ AlignInBits(AlignInBits) {}
~DIVariable() = default;
public:
@@ -2108,7 +2253,7 @@ public:
/// Retrieve the details of this fragment expression.
static Optional<FragmentInfo> getFragmentInfo(expr_op_iterator Start,
- expr_op_iterator End);
+ expr_op_iterator End);
/// Retrieve the details of this fragment expression.
Optional<FragmentInfo> getFragmentInfo() const {
diff --git a/include/llvm/IR/DiagnosticInfo.h b/include/llvm/IR/DiagnosticInfo.h
index a93c180df1b5..458c3cf29b0d 100644
--- a/include/llvm/IR/DiagnosticInfo.h
+++ b/include/llvm/IR/DiagnosticInfo.h
@@ -69,6 +69,11 @@ enum DiagnosticKind {
DK_OptimizationFailure,
DK_FirstRemark = DK_OptimizationRemark,
DK_LastRemark = DK_OptimizationFailure,
+ DK_MachineOptimizationRemark,
+ DK_MachineOptimizationRemarkMissed,
+ DK_MachineOptimizationRemarkAnalysis,
+ DK_FirstMachineRemark = DK_MachineOptimizationRemark,
+ DK_LastMachineRemark = DK_MachineOptimizationRemarkAnalysis,
DK_MIRParser,
DK_PGOProfile,
DK_Unsupported,
@@ -342,19 +347,34 @@ private:
const Twine &Msg;
};
-/// Common features for diagnostics with an associated DebugLoc
-class DiagnosticInfoWithDebugLocBase : public DiagnosticInfo {
+class DiagnosticLocation {
+ StringRef Filename;
+ unsigned Line = 0;
+ unsigned Column = 0;
public:
- /// \p Fn is the function where the diagnostic is being emitted. \p DLoc is
+ DiagnosticLocation() {}
+ DiagnosticLocation(const DebugLoc &DL);
+ DiagnosticLocation(const DISubprogram *SP);
+
+ bool isValid() const { return !Filename.empty(); }
+ StringRef getFilename() const { return Filename; }
+ unsigned getLine() const { return Line; }
+ unsigned getColumn() const { return Column; }
+};
+
+/// Common features for diagnostics with an associated location.
+class DiagnosticInfoWithLocationBase : public DiagnosticInfo {
+public:
+ /// \p Fn is the function where the diagnostic is being emitted. \p Loc is
/// the location information to use in the diagnostic.
- DiagnosticInfoWithDebugLocBase(enum DiagnosticKind Kind,
+ DiagnosticInfoWithLocationBase(enum DiagnosticKind Kind,
enum DiagnosticSeverity Severity,
const Function &Fn,
- const DebugLoc &DLoc)
- : DiagnosticInfo(Kind, Severity), Fn(Fn), DLoc(DLoc) {}
+ const DiagnosticLocation &Loc)
+ : DiagnosticInfo(Kind, Severity), Fn(Fn), Loc(Loc) {}
/// Return true if location information is available for this diagnostic.
- bool isLocationAvailable() const;
+ bool isLocationAvailable() const { return Loc.isValid(); }
/// Return a string with the location information for this diagnostic
/// in the format "file:line:col". If location information is not available,
@@ -366,18 +386,19 @@ public:
void getLocation(StringRef *Filename, unsigned *Line, unsigned *Column) const;
const Function &getFunction() const { return Fn; }
- const DebugLoc &getDebugLoc() const { return DLoc; }
+ DiagnosticLocation getLocation() const { return Loc; }
private:
/// Function where this diagnostic is triggered.
const Function &Fn;
/// Debug location where this diagnostic is triggered.
- DebugLoc DLoc;
+ DiagnosticLocation Loc;
};
-/// Common features for diagnostics dealing with optimization remarks.
-class DiagnosticInfoOptimizationBase : public DiagnosticInfoWithDebugLocBase {
+/// \brief Common features for diagnostics dealing with optimization remarks
+/// that are used by both IR and MIR passes.
+class DiagnosticInfoOptimizationBase : public DiagnosticInfoWithLocationBase {
public:
/// \brief Used to set IsVerbose via the stream interface.
struct setIsVerbose {};
@@ -394,66 +415,29 @@ public:
StringRef Key;
std::string Val;
// If set, the debug location corresponding to the value.
- DebugLoc DLoc;
+ DiagnosticLocation Loc;
explicit Argument(StringRef Str = "") : Key("String"), Val(Str) {}
- Argument(StringRef Key, Value *V);
- Argument(StringRef Key, Type *T);
+ Argument(StringRef Key, const Value *V);
+ Argument(StringRef Key, const Type *T);
Argument(StringRef Key, int N);
Argument(StringRef Key, unsigned N);
Argument(StringRef Key, bool B) : Key(Key), Val(B ? "true" : "false") {}
};
/// \p PassName is the name of the pass emitting this diagnostic. \p
- /// RemarkName is a textual identifier for the remark. \p Fn is the function
- /// where the diagnostic is being emitted. \p DLoc is the location information
- /// to use in the diagnostic. If line table information is available, the
- /// diagnostic will include the source code location. \p CodeRegion is IR
- /// value (currently basic block) that the optimization operates on. This is
- /// currently used to provide run-time hotness information with PGO.
- DiagnosticInfoOptimizationBase(enum DiagnosticKind Kind,
- enum DiagnosticSeverity Severity,
- const char *PassName, StringRef RemarkName,
- const Function &Fn, const DebugLoc &DLoc,
- Value *CodeRegion = nullptr)
- : DiagnosticInfoWithDebugLocBase(Kind, Severity, Fn, DLoc),
- PassName(PassName), RemarkName(RemarkName), CodeRegion(CodeRegion) {}
-
- /// \brief This is ctor variant allows a pass to build an optimization remark
- /// from an existing remark.
- ///
- /// This is useful when a transformation pass (e.g LV) wants to emit a remark
- /// (\p Orig) generated by one of its analyses (e.g. LAA) as its own analysis
- /// remark. The string \p Prepend will be emitted before the original
- /// message.
- DiagnosticInfoOptimizationBase(const char *PassName, StringRef Prepend,
- const DiagnosticInfoOptimizationBase &Orig)
- : DiagnosticInfoWithDebugLocBase((DiagnosticKind)Orig.getKind(),
- Orig.getSeverity(), Orig.getFunction(),
- Orig.getDebugLoc()),
- PassName(PassName), RemarkName(Orig.RemarkName),
- CodeRegion(Orig.getCodeRegion()) {
- *this << Prepend;
- std::copy(Orig.Args.begin(), Orig.Args.end(), std::back_inserter(Args));
- }
-
- /// Legacy interface.
- /// \p PassName is the name of the pass emitting this diagnostic.
- /// \p Fn is the function where the diagnostic is being emitted. \p DLoc is
- /// the location information to use in the diagnostic. If line table
+ /// RemarkName is a textual identifier for the remark (single-word,
+ /// camel-case). \p Fn is the function where the diagnostic is being emitted.
+ /// \p Loc is the location information to use in the diagnostic. If line table
/// information is available, the diagnostic will include the source code
- /// location. \p Msg is the message to show. Note that this class does not
- /// copy this message, so this reference must be valid for the whole life time
- /// of the diagnostic.
+ /// location.
DiagnosticInfoOptimizationBase(enum DiagnosticKind Kind,
enum DiagnosticSeverity Severity,
- const char *PassName, const Function &Fn,
- const DebugLoc &DLoc, const Twine &Msg,
- Optional<uint64_t> Hotness = None)
- : DiagnosticInfoWithDebugLocBase(Kind, Severity, Fn, DLoc),
- PassName(PassName), Hotness(Hotness) {
- Args.push_back(Argument(Msg.str()));
- }
+ const char *PassName, StringRef RemarkName,
+ const Function &Fn,
+ const DiagnosticLocation &Loc)
+ : DiagnosticInfoWithLocationBase(Kind, Severity, Fn, Loc),
+ PassName(PassName), RemarkName(RemarkName) {}
DiagnosticInfoOptimizationBase &operator<<(StringRef S);
DiagnosticInfoOptimizationBase &operator<<(Argument A);
@@ -475,33 +459,45 @@ public:
Optional<uint64_t> getHotness() const { return Hotness; }
void setHotness(Optional<uint64_t> H) { Hotness = H; }
- Value *getCodeRegion() const { return CodeRegion; }
-
bool isVerbose() const { return IsVerbose; }
static bool classof(const DiagnosticInfo *DI) {
- return DI->getKind() >= DK_FirstRemark &&
- DI->getKind() <= DK_LastRemark;
+ return (DI->getKind() >= DK_FirstRemark &&
+ DI->getKind() <= DK_LastRemark) ||
+ (DI->getKind() >= DK_FirstMachineRemark &&
+ DI->getKind() <= DK_LastMachineRemark);
}
-private:
+ bool isPassed() const {
+ return (getKind() == DK_OptimizationRemark ||
+ getKind() == DK_MachineOptimizationRemark);
+ }
+
+ bool isMissed() const {
+ return (getKind() == DK_OptimizationRemarkMissed ||
+ getKind() == DK_MachineOptimizationRemarkMissed);
+ }
+
+ bool isAnalysis() const {
+ return (getKind() == DK_OptimizationRemarkAnalysis ||
+ getKind() == DK_MachineOptimizationRemarkAnalysis);
+ }
+
+protected:
/// Name of the pass that triggers this report. If this matches the
/// regular expression given in -Rpass=regexp, then the remark will
/// be emitted.
const char *PassName;
- /// Textual identifier for the remark. Can be used by external tools reading
- /// the YAML output file for optimization remarks to identify the remark.
+ /// Textual identifier for the remark (single-word, camel-case). Can be used
+ /// by external tools reading the YAML output file for optimization remarks to
+ /// identify the remark.
StringRef RemarkName;
/// If profile information is available, this is the number of times the
/// corresponding code was executed in a profile instrumentation run.
Optional<uint64_t> Hotness;
- /// The IR value (currently basic block) that the optimization operates on.
- /// This is currently used to provide run-time hotness information with PGO.
- Value *CodeRegion;
-
/// Arguments collected via the streaming interface.
SmallVector<Argument, 4> Args;
@@ -516,106 +512,186 @@ private:
friend struct yaml::MappingTraits<DiagnosticInfoOptimizationBase *>;
};
-/// Diagnostic information for applied optimization remarks.
-class OptimizationRemark : public DiagnosticInfoOptimizationBase {
+/// \brief Common features for diagnostics dealing with optimization remarks
+/// that are used by IR passes.
+class DiagnosticInfoIROptimization : public DiagnosticInfoOptimizationBase {
public:
- /// \p PassName is the name of the pass emitting this diagnostic. If
- /// this name matches the regular expression given in -Rpass=, then the
- /// diagnostic will be emitted. \p Fn is the function where the diagnostic
- /// is being emitted. \p DLoc is the location information to use in the
- /// diagnostic. If line table information is available, the diagnostic
- /// will include the source code location. \p Msg is the message to show.
- /// Note that this class does not copy this message, so this reference
- /// must be valid for the whole life time of the diagnostic.
- OptimizationRemark(const char *PassName, const Function &Fn,
- const DebugLoc &DLoc, const Twine &Msg,
- Optional<uint64_t> Hotness = None)
- : DiagnosticInfoOptimizationBase(DK_OptimizationRemark, DS_Remark,
- PassName, Fn, DLoc, Msg, Hotness) {}
+ /// \p PassName is the name of the pass emitting this diagnostic. \p
+ /// RemarkName is a textual identifier for the remark (single-word,
+ /// camel-case). \p Fn is the function where the diagnostic is being emitted.
+ /// \p Loc is the location information to use in the diagnostic. If line table
+ /// information is available, the diagnostic will include the source code
+ /// location. \p CodeRegion is IR value (currently basic block) that the
+ /// optimization operates on. This is currently used to provide run-time
+ /// hotness information with PGO.
+ DiagnosticInfoIROptimization(enum DiagnosticKind Kind,
+ enum DiagnosticSeverity Severity,
+ const char *PassName, StringRef RemarkName,
+ const Function &Fn,
+ const DiagnosticLocation &Loc,
+ const Value *CodeRegion = nullptr)
+ : DiagnosticInfoOptimizationBase(Kind, Severity, PassName, RemarkName, Fn,
+ Loc),
+ CodeRegion(CodeRegion) {}
+ /// \brief This is ctor variant allows a pass to build an optimization remark
+ /// from an existing remark.
+ ///
+ /// This is useful when a transformation pass (e.g LV) wants to emit a remark
+ /// (\p Orig) generated by one of its analyses (e.g. LAA) as its own analysis
+ /// remark. The string \p Prepend will be emitted before the original
+ /// message.
+ DiagnosticInfoIROptimization(const char *PassName, StringRef Prepend,
+ const DiagnosticInfoIROptimization &Orig)
+ : DiagnosticInfoOptimizationBase(
+ (DiagnosticKind)Orig.getKind(), Orig.getSeverity(), PassName,
+ Orig.RemarkName, Orig.getFunction(), Orig.getLocation()),
+ CodeRegion(Orig.getCodeRegion()) {
+ *this << Prepend;
+ std::copy(Orig.Args.begin(), Orig.Args.end(), std::back_inserter(Args));
+ }
+
+ /// Legacy interface.
+ /// \p PassName is the name of the pass emitting this diagnostic.
+ /// \p Fn is the function where the diagnostic is being emitted. \p Loc is
+ /// the location information to use in the diagnostic. If line table
+ /// information is available, the diagnostic will include the source code
+ /// location. \p Msg is the message to show. Note that this class does not
+ /// copy this message, so this reference must be valid for the whole life time
+ /// of the diagnostic.
+ DiagnosticInfoIROptimization(enum DiagnosticKind Kind,
+ enum DiagnosticSeverity Severity,
+ const char *PassName, const Function &Fn,
+ const DiagnosticLocation &Loc, const Twine &Msg)
+ : DiagnosticInfoOptimizationBase(Kind, Severity, PassName, "", Fn, Loc) {
+ *this << Msg.str();
+ }
+
+ const Value *getCodeRegion() const { return CodeRegion; }
+
+ static bool classof(const DiagnosticInfo *DI) {
+ return DI->getKind() >= DK_FirstRemark && DI->getKind() <= DK_LastRemark;
+ }
+
+private:
+ /// The IR value (currently basic block) that the optimization operates on.
+ /// This is currently used to provide run-time hotness information with PGO.
+ const Value *CodeRegion;
+};
+
+/// Diagnostic information for applied optimization remarks.
+class OptimizationRemark : public DiagnosticInfoIROptimization {
+public:
/// \p PassName is the name of the pass emitting this diagnostic. If this name
/// matches the regular expression given in -Rpass=, then the diagnostic will
- /// be emitted. \p RemarkName is a textual identifier for the remark. \p
- /// DLoc is the debug location and \p CodeRegion is the region that the
- /// optimization operates on (currently on block is supported).
+ /// be emitted. \p RemarkName is a textual identifier for the remark (single-
+ /// word, camel-case). \p Loc is the debug location and \p CodeRegion is the
+ /// region that the optimization operates on (currently only block is
+ /// supported).
OptimizationRemark(const char *PassName, StringRef RemarkName,
- const DebugLoc &DLoc, Value *CodeRegion);
+ const DiagnosticLocation &Loc, const Value *CodeRegion);
- /// Same as above but the debug location and code region is derived from \p
+ /// Same as above, but the debug location and code region are derived from \p
/// Instr.
OptimizationRemark(const char *PassName, StringRef RemarkName,
- Instruction *Inst);
+ const Instruction *Inst);
+
+ /// Same as above, but the debug location and code region are derived from \p
+ /// Func.
+ OptimizationRemark(const char *PassName, StringRef RemarkName,
+ const Function *Func);
static bool classof(const DiagnosticInfo *DI) {
return DI->getKind() == DK_OptimizationRemark;
}
+ static bool isEnabled(StringRef PassName);
+
/// \see DiagnosticInfoOptimizationBase::isEnabled.
- bool isEnabled() const override;
-};
+ bool isEnabled() const override { return isEnabled(getPassName()); }
-/// Diagnostic information for missed-optimization remarks.
-class OptimizationRemarkMissed : public DiagnosticInfoOptimizationBase {
-public:
+private:
+ /// This is deprecated now and only used by the function API below.
/// \p PassName is the name of the pass emitting this diagnostic. If
- /// this name matches the regular expression given in -Rpass-missed=, then the
+ /// this name matches the regular expression given in -Rpass=, then the
/// diagnostic will be emitted. \p Fn is the function where the diagnostic
- /// is being emitted. \p DLoc is the location information to use in the
+ /// is being emitted. \p Loc is the location information to use in the
/// diagnostic. If line table information is available, the diagnostic
/// will include the source code location. \p Msg is the message to show.
/// Note that this class does not copy this message, so this reference
/// must be valid for the whole life time of the diagnostic.
- OptimizationRemarkMissed(const char *PassName, const Function &Fn,
- const DebugLoc &DLoc, const Twine &Msg,
- Optional<uint64_t> Hotness = None)
- : DiagnosticInfoOptimizationBase(DK_OptimizationRemarkMissed, DS_Remark,
- PassName, Fn, DLoc, Msg, Hotness) {}
+ OptimizationRemark(const char *PassName, const Function &Fn,
+ const DiagnosticLocation &Loc, const Twine &Msg)
+ : DiagnosticInfoIROptimization(DK_OptimizationRemark, DS_Remark, PassName,
+ Fn, Loc, Msg) {}
+
+ friend void emitOptimizationRemark(LLVMContext &Ctx, const char *PassName,
+ const Function &Fn,
+ const DiagnosticLocation &Loc,
+ const Twine &Msg);
+};
+/// Diagnostic information for missed-optimization remarks.
+class OptimizationRemarkMissed : public DiagnosticInfoIROptimization {
+public:
/// \p PassName is the name of the pass emitting this diagnostic. If this name
/// matches the regular expression given in -Rpass-missed=, then the
- /// diagnostic will be emitted. \p RemarkName is a textual identifier for the
- /// remark. \p DLoc is the debug location and \p CodeRegion is the region
- /// that the optimization operates on (currently on block is supported).
+ /// diagnostic will be emitted. \p RemarkName is a textual identifier for the
+ /// remark (single-word, camel-case). \p Loc is the debug location and \p
+ /// CodeRegion is the region that the optimization operates on (currently only
+ /// block is supported).
OptimizationRemarkMissed(const char *PassName, StringRef RemarkName,
- const DebugLoc &DLoc, Value *CodeRegion);
+ const DiagnosticLocation &Loc,
+ const Value *CodeRegion);
/// \brief Same as above but \p Inst is used to derive code region and debug
/// location.
OptimizationRemarkMissed(const char *PassName, StringRef RemarkName,
- Instruction *Inst);
+ const Instruction *Inst);
static bool classof(const DiagnosticInfo *DI) {
return DI->getKind() == DK_OptimizationRemarkMissed;
}
+ static bool isEnabled(StringRef PassName);
+
/// \see DiagnosticInfoOptimizationBase::isEnabled.
- bool isEnabled() const override;
+ bool isEnabled() const override { return isEnabled(getPassName()); }
+
+private:
+ /// This is deprecated now and only used by the function API below.
+ /// \p PassName is the name of the pass emitting this diagnostic. If
+ /// this name matches the regular expression given in -Rpass-missed=, then the
+ /// diagnostic will be emitted. \p Fn is the function where the diagnostic
+ /// is being emitted. \p Loc is the location information to use in the
+ /// diagnostic. If line table information is available, the diagnostic
+ /// will include the source code location. \p Msg is the message to show.
+ /// Note that this class does not copy this message, so this reference
+ /// must be valid for the whole life time of the diagnostic.
+ OptimizationRemarkMissed(const char *PassName, const Function &Fn,
+ const DiagnosticLocation &Loc, const Twine &Msg)
+ : DiagnosticInfoIROptimization(DK_OptimizationRemarkMissed, DS_Remark,
+ PassName, Fn, Loc, Msg) {}
+
+ friend void emitOptimizationRemarkMissed(LLVMContext &Ctx,
+ const char *PassName,
+ const Function &Fn,
+ const DiagnosticLocation &Loc,
+ const Twine &Msg);
};
/// Diagnostic information for optimization analysis remarks.
-class OptimizationRemarkAnalysis : public DiagnosticInfoOptimizationBase {
+class OptimizationRemarkAnalysis : public DiagnosticInfoIROptimization {
public:
- /// \p PassName is the name of the pass emitting this diagnostic. If
- /// this name matches the regular expression given in -Rpass-analysis=, then
- /// the diagnostic will be emitted. \p Fn is the function where the diagnostic
- /// is being emitted. \p DLoc is the location information to use in the
- /// diagnostic. If line table information is available, the diagnostic will
- /// include the source code location. \p Msg is the message to show. Note that
- /// this class does not copy this message, so this reference must be valid for
- /// the whole life time of the diagnostic.
- OptimizationRemarkAnalysis(const char *PassName, const Function &Fn,
- const DebugLoc &DLoc, const Twine &Msg,
- Optional<uint64_t> Hotness = None)
- : DiagnosticInfoOptimizationBase(DK_OptimizationRemarkAnalysis, DS_Remark,
- PassName, Fn, DLoc, Msg, Hotness) {}
-
/// \p PassName is the name of the pass emitting this diagnostic. If this name
/// matches the regular expression given in -Rpass-analysis=, then the
- /// diagnostic will be emitted. \p RemarkName is a textual identifier for the
- /// remark. \p DLoc is the debug location and \p CodeRegion is the region
- /// that the optimization operates on (currently on block is supported).
+ /// diagnostic will be emitted. \p RemarkName is a textual identifier for the
+ /// remark (single-word, camel-case). \p Loc is the debug location and \p
+ /// CodeRegion is the region that the optimization operates on (currently only
+ /// block is supported).
OptimizationRemarkAnalysis(const char *PassName, StringRef RemarkName,
- const DebugLoc &DLoc, Value *CodeRegion);
+ const DiagnosticLocation &Loc,
+ const Value *CodeRegion);
/// \brief This is ctor variant allows a pass to build an optimization remark
/// from an existing remark.
@@ -626,19 +702,23 @@ public:
/// message.
OptimizationRemarkAnalysis(const char *PassName, StringRef Prepend,
const OptimizationRemarkAnalysis &Orig)
- : DiagnosticInfoOptimizationBase(PassName, Prepend, Orig) {}
+ : DiagnosticInfoIROptimization(PassName, Prepend, Orig) {}
/// \brief Same as above but \p Inst is used to derive code region and debug
/// location.
OptimizationRemarkAnalysis(const char *PassName, StringRef RemarkName,
- Instruction *Inst);
+ const Instruction *Inst);
static bool classof(const DiagnosticInfo *DI) {
return DI->getKind() == DK_OptimizationRemarkAnalysis;
}
+ static bool isEnabled(StringRef PassName);
+
/// \see DiagnosticInfoOptimizationBase::isEnabled.
- bool isEnabled() const override;
+ bool isEnabled() const override {
+ return shouldAlwaysPrint() || isEnabled(getPassName());
+ }
static const char *AlwaysPrint;
@@ -646,24 +726,65 @@ public:
protected:
OptimizationRemarkAnalysis(enum DiagnosticKind Kind, const char *PassName,
- const Function &Fn, const DebugLoc &DLoc,
- const Twine &Msg, Optional<uint64_t> Hotness)
- : DiagnosticInfoOptimizationBase(Kind, DS_Remark, PassName, Fn, DLoc, Msg,
- Hotness) {}
+ const Function &Fn, const DiagnosticLocation &Loc,
+ const Twine &Msg)
+ : DiagnosticInfoIROptimization(Kind, DS_Remark, PassName, Fn, Loc, Msg) {}
OptimizationRemarkAnalysis(enum DiagnosticKind Kind, const char *PassName,
- StringRef RemarkName, const DebugLoc &DLoc,
- Value *CodeRegion);
+ StringRef RemarkName,
+ const DiagnosticLocation &Loc,
+ const Value *CodeRegion);
+
+private:
+ /// This is deprecated now and only used by the function API below.
+ /// \p PassName is the name of the pass emitting this diagnostic. If
+ /// this name matches the regular expression given in -Rpass-analysis=, then
+ /// the diagnostic will be emitted. \p Fn is the function where the diagnostic
+ /// is being emitted. \p Loc is the location information to use in the
+ /// diagnostic. If line table information is available, the diagnostic will
+ /// include the source code location. \p Msg is the message to show. Note that
+ /// this class does not copy this message, so this reference must be valid for
+ /// the whole life time of the diagnostic.
+ OptimizationRemarkAnalysis(const char *PassName, const Function &Fn,
+ const DiagnosticLocation &Loc, const Twine &Msg)
+ : DiagnosticInfoIROptimization(DK_OptimizationRemarkAnalysis, DS_Remark,
+ PassName, Fn, Loc, Msg) {}
+
+ friend void emitOptimizationRemarkAnalysis(LLVMContext &Ctx,
+ const char *PassName,
+ const Function &Fn,
+ const DiagnosticLocation &Loc,
+ const Twine &Msg);
};
/// Diagnostic information for optimization analysis remarks related to
/// floating-point non-commutativity.
class OptimizationRemarkAnalysisFPCommute : public OptimizationRemarkAnalysis {
public:
+ /// \p PassName is the name of the pass emitting this diagnostic. If this name
+ /// matches the regular expression given in -Rpass-analysis=, then the
+ /// diagnostic will be emitted. \p RemarkName is a textual identifier for the
+ /// remark (single-word, camel-case). \p Loc is the debug location and \p
+ /// CodeRegion is the region that the optimization operates on (currently only
+ /// block is supported). The front-end will append its own message related to
+ /// options that address floating-point non-commutativity.
+ OptimizationRemarkAnalysisFPCommute(const char *PassName,
+ StringRef RemarkName,
+ const DiagnosticLocation &Loc,
+ const Value *CodeRegion)
+ : OptimizationRemarkAnalysis(DK_OptimizationRemarkAnalysisFPCommute,
+ PassName, RemarkName, Loc, CodeRegion) {}
+
+ static bool classof(const DiagnosticInfo *DI) {
+ return DI->getKind() == DK_OptimizationRemarkAnalysisFPCommute;
+ }
+
+private:
+ /// This is deprecated now and only used by the function API below.
/// \p PassName is the name of the pass emitting this diagnostic. If
/// this name matches the regular expression given in -Rpass-analysis=, then
/// the diagnostic will be emitted. \p Fn is the function where the diagnostic
- /// is being emitted. \p DLoc is the location information to use in the
+ /// is being emitted. \p Loc is the location information to use in the
/// diagnostic. If line table information is available, the diagnostic will
/// include the source code location. \p Msg is the message to show. The
/// front-end will append its own message related to options that address
@@ -671,37 +792,42 @@ public:
/// message, so this reference must be valid for the whole life time of the
/// diagnostic.
OptimizationRemarkAnalysisFPCommute(const char *PassName, const Function &Fn,
- const DebugLoc &DLoc, const Twine &Msg,
- Optional<uint64_t> Hotness = None)
+ const DiagnosticLocation &Loc,
+ const Twine &Msg)
: OptimizationRemarkAnalysis(DK_OptimizationRemarkAnalysisFPCommute,
- PassName, Fn, DLoc, Msg, Hotness) {}
+ PassName, Fn, Loc, Msg) {}
+ friend void emitOptimizationRemarkAnalysisFPCommute(
+ LLVMContext &Ctx, const char *PassName, const Function &Fn,
+ const DiagnosticLocation &Loc, const Twine &Msg);
+};
+/// Diagnostic information for optimization analysis remarks related to
+/// pointer aliasing.
+class OptimizationRemarkAnalysisAliasing : public OptimizationRemarkAnalysis {
+public:
/// \p PassName is the name of the pass emitting this diagnostic. If this name
/// matches the regular expression given in -Rpass-analysis=, then the
- /// diagnostic will be emitted. \p RemarkName is a textual identifier for the
- /// remark. \p DLoc is the debug location and \p CodeRegion is the region
- /// that the optimization operates on (currently on block is supported). The
- /// front-end will append its own message related to options that address
- /// floating-point non-commutativity.
- OptimizationRemarkAnalysisFPCommute(const char *PassName,
- StringRef RemarkName,
- const DebugLoc &DLoc, Value *CodeRegion)
- : OptimizationRemarkAnalysis(DK_OptimizationRemarkAnalysisFPCommute,
- PassName, RemarkName, DLoc, CodeRegion) {}
+ /// diagnostic will be emitted. \p RemarkName is a textual identifier for the
+ /// remark (single-word, camel-case). \p Loc is the debug location and \p
+ /// CodeRegion is the region that the optimization operates on (currently only
+ /// block is supported). The front-end will append its own message related to
+ /// options that address pointer aliasing legality.
+ OptimizationRemarkAnalysisAliasing(const char *PassName, StringRef RemarkName,
+ const DiagnosticLocation &Loc,
+ const Value *CodeRegion)
+ : OptimizationRemarkAnalysis(DK_OptimizationRemarkAnalysisAliasing,
+ PassName, RemarkName, Loc, CodeRegion) {}
static bool classof(const DiagnosticInfo *DI) {
- return DI->getKind() == DK_OptimizationRemarkAnalysisFPCommute;
+ return DI->getKind() == DK_OptimizationRemarkAnalysisAliasing;
}
-};
-/// Diagnostic information for optimization analysis remarks related to
-/// pointer aliasing.
-class OptimizationRemarkAnalysisAliasing : public OptimizationRemarkAnalysis {
-public:
+private:
+ /// This is deprecated now and only used by the function API below.
/// \p PassName is the name of the pass emitting this diagnostic. If
/// this name matches the regular expression given in -Rpass-analysis=, then
/// the diagnostic will be emitted. \p Fn is the function where the diagnostic
- /// is being emitted. \p DLoc is the location information to use in the
+ /// is being emitted. \p Loc is the location information to use in the
/// diagnostic. If line table information is available, the diagnostic will
/// include the source code location. \p Msg is the message to show. The
/// front-end will append its own message related to options that address
@@ -709,26 +835,14 @@ public:
/// message, so this reference must be valid for the whole life time of the
/// diagnostic.
OptimizationRemarkAnalysisAliasing(const char *PassName, const Function &Fn,
- const DebugLoc &DLoc, const Twine &Msg,
- Optional<uint64_t> Hotness = None)
- : OptimizationRemarkAnalysis(DK_OptimizationRemarkAnalysisAliasing,
- PassName, Fn, DLoc, Msg, Hotness) {}
-
- /// \p PassName is the name of the pass emitting this diagnostic. If this name
- /// matches the regular expression given in -Rpass-analysis=, then the
- /// diagnostic will be emitted. \p RemarkName is a textual identifier for the
- /// remark. \p DLoc is the debug location and \p CodeRegion is the region
- /// that the optimization operates on (currently on block is supported). The
- /// front-end will append its own message related to options that address
- /// pointer aliasing legality.
- OptimizationRemarkAnalysisAliasing(const char *PassName, StringRef RemarkName,
- const DebugLoc &DLoc, Value *CodeRegion)
+ const DiagnosticLocation &Loc,
+ const Twine &Msg)
: OptimizationRemarkAnalysis(DK_OptimizationRemarkAnalysisAliasing,
- PassName, RemarkName, DLoc, CodeRegion) {}
+ PassName, Fn, Loc, Msg) {}
- static bool classof(const DiagnosticInfo *DI) {
- return DI->getKind() == DK_OptimizationRemarkAnalysisAliasing;
- }
+ friend void emitOptimizationRemarkAnalysisAliasing(
+ LLVMContext &Ctx, const char *PassName, const Function &Fn,
+ const DiagnosticLocation &Loc, const Twine &Msg);
};
/// Diagnostic information for machine IR parser.
@@ -771,73 +885,97 @@ public:
// Create wrappers for C Binding types (see CBindingWrapping.h).
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(DiagnosticInfo, LLVMDiagnosticInfoRef)
-/// Emit an optimization-applied message. \p PassName is the name of the pass
-/// emitting the message. If -Rpass= is given and \p PassName matches the
-/// regular expression in -Rpass, then the remark will be emitted. \p Fn is
-/// the function triggering the remark, \p DLoc is the debug location where
-/// the diagnostic is generated. \p Msg is the message string to use.
+/// \brief Legacy interface to emit an optimization-applied message. Use
+/// (Machine)OptimizationRemarkEmitter instead.
+///
+/// \p PassName is the name of the pass emitting the message. If -Rpass= is
+/// given and \p PassName matches the regular expression in -Rpass, then the
+/// remark will be emitted. \p Fn is the function triggering the remark, \p Loc
+/// is the debug location where the diagnostic is generated. \p Msg is the
+/// message string to use.
void emitOptimizationRemark(LLVMContext &Ctx, const char *PassName,
- const Function &Fn, const DebugLoc &DLoc,
+ const Function &Fn, const DiagnosticLocation &Loc,
const Twine &Msg);
-/// Emit an optimization-missed message. \p PassName is the name of the
-/// pass emitting the message. If -Rpass-missed= is given and \p PassName
-/// matches the regular expression in -Rpass, then the remark will be
-/// emitted. \p Fn is the function triggering the remark, \p DLoc is the
-/// debug location where the diagnostic is generated. \p Msg is the
+/// \brief Legacy interface to emit an optimization-missed message. Use
+/// (Machine)OptimizationRemarkEmitter instead.
+///
+/// \p PassName is the name of the pass emitting the message. If -Rpass-missed=
+/// is given and \p PassName matches the regular expression in -Rpass, then the
+/// remark will be emitted. \p Fn is the function triggering the remark, \p Loc
+/// is the debug location where the diagnostic is generated. \p Msg is the
/// message string to use.
void emitOptimizationRemarkMissed(LLVMContext &Ctx, const char *PassName,
- const Function &Fn, const DebugLoc &DLoc,
+ const Function &Fn,
+ const DiagnosticLocation &Loc,
const Twine &Msg);
-/// Emit an optimization analysis remark message. \p PassName is the name of
-/// the pass emitting the message. If -Rpass-analysis= is given and \p
-/// PassName matches the regular expression in -Rpass, then the remark will be
-/// emitted. \p Fn is the function triggering the remark, \p DLoc is the debug
-/// location where the diagnostic is generated. \p Msg is the message string
-/// to use.
+/// \brief Legacy interface to emit an optimization analysis remark message.
+/// Use (Machine)OptimizationRemarkEmitter instead.
+///
+/// \p PassName is the name of the pass emitting the message. If
+/// -Rpass-analysis= is given and \p PassName matches the regular expression in
+/// -Rpass, then the remark will be emitted. \p Fn is the function triggering
+/// the remark, \p Loc is the debug location where the diagnostic is
+/// generated. \p Msg is the message string to use.
void emitOptimizationRemarkAnalysis(LLVMContext &Ctx, const char *PassName,
- const Function &Fn, const DebugLoc &DLoc,
+ const Function &Fn,
+ const DiagnosticLocation &Loc,
const Twine &Msg);
-/// Emit an optimization analysis remark related to messages about
-/// floating-point non-commutativity. \p PassName is the name of the pass
-/// emitting the message. If -Rpass-analysis= is given and \p PassName matches
-/// the regular expression in -Rpass, then the remark will be emitted. \p Fn is
-/// the function triggering the remark, \p DLoc is the debug location where the
-/// diagnostic is generated. \p Msg is the message string to use.
+/// \brief Legacy interface to emit an optimization analysis remark related to
+/// messages about floating-point non-commutativity. Use
+/// (Machine)OptimizationRemarkEmitter instead.
+///
+/// \p PassName is the name of the pass emitting the message. If
+/// -Rpass-analysis= is given and \p PassName matches the regular expression in
+/// -Rpass, then the remark will be emitted. \p Fn is the function triggering
+/// the remark, \p Loc is the debug location where the diagnostic is
+/// generated. \p Msg is the message string to use.
void emitOptimizationRemarkAnalysisFPCommute(LLVMContext &Ctx,
const char *PassName,
const Function &Fn,
- const DebugLoc &DLoc,
+ const DiagnosticLocation &Loc,
const Twine &Msg);
-/// Emit an optimization analysis remark related to messages about
-/// pointer aliasing. \p PassName is the name of the pass emitting the message.
+/// \brief Legacy interface to emit an optimization analysis remark related to
+/// messages about pointer aliasing. Use (Machine)OptimizationRemarkEmitter
+/// instead.
+///
+/// \p PassName is the name of the pass emitting the message.
/// If -Rpass-analysis= is given and \p PassName matches the regular expression
/// in -Rpass, then the remark will be emitted. \p Fn is the function triggering
-/// the remark, \p DLoc is the debug location where the diagnostic is generated.
+/// the remark, \p Loc is the debug location where the diagnostic is generated.
/// \p Msg is the message string to use.
void emitOptimizationRemarkAnalysisAliasing(LLVMContext &Ctx,
const char *PassName,
const Function &Fn,
- const DebugLoc &DLoc,
+ const DiagnosticLocation &Loc,
const Twine &Msg);
/// Diagnostic information for optimization failures.
-class DiagnosticInfoOptimizationFailure
- : public DiagnosticInfoOptimizationBase {
+class DiagnosticInfoOptimizationFailure : public DiagnosticInfoIROptimization {
public:
- /// \p Fn is the function where the diagnostic is being emitted. \p DLoc is
+ /// \p Fn is the function where the diagnostic is being emitted. \p Loc is
/// the location information to use in the diagnostic. If line table
/// information is available, the diagnostic will include the source code
/// location. \p Msg is the message to show. Note that this class does not
/// copy this message, so this reference must be valid for the whole life time
/// of the diagnostic.
- DiagnosticInfoOptimizationFailure(const Function &Fn, const DebugLoc &DLoc,
+ DiagnosticInfoOptimizationFailure(const Function &Fn,
+ const DiagnosticLocation &Loc,
const Twine &Msg)
- : DiagnosticInfoOptimizationBase(DK_OptimizationFailure, DS_Warning,
- nullptr, Fn, DLoc, Msg) {}
+ : DiagnosticInfoIROptimization(DK_OptimizationFailure, DS_Warning,
+ nullptr, Fn, Loc, Msg) {}
+
+ /// \p PassName is the name of the pass emitting this diagnostic. \p
+ /// RemarkName is a textual identifier for the remark (single-word,
+ /// camel-case). \p Loc is the debug location and \p CodeRegion is the
+ /// region that the optimization operates on (currently basic block is
+ /// supported).
+ DiagnosticInfoOptimizationFailure(const char *PassName, StringRef RemarkName,
+ const DiagnosticLocation &Loc,
+ const Value *CodeRegion);
static bool classof(const DiagnosticInfo *DI) {
return DI->getKind() == DK_OptimizationFailure;
@@ -848,22 +986,22 @@ public:
};
/// Diagnostic information for unsupported feature in backend.
-class DiagnosticInfoUnsupported
- : public DiagnosticInfoWithDebugLocBase {
+class DiagnosticInfoUnsupported : public DiagnosticInfoWithLocationBase {
private:
Twine Msg;
public:
- /// \p Fn is the function where the diagnostic is being emitted. \p DLoc is
+ /// \p Fn is the function where the diagnostic is being emitted. \p Loc is
/// the location information to use in the diagnostic. If line table
/// information is available, the diagnostic will include the source code
/// location. \p Msg is the message to show. Note that this class does not
/// copy this message, so this reference must be valid for the whole life time
/// of the diagnostic.
- DiagnosticInfoUnsupported(const Function &Fn, const Twine &Msg,
- DebugLoc DLoc = DebugLoc(),
- DiagnosticSeverity Severity = DS_Error)
- : DiagnosticInfoWithDebugLocBase(DK_Unsupported, Severity, Fn, DLoc),
+ DiagnosticInfoUnsupported(
+ const Function &Fn, const Twine &Msg,
+ const DiagnosticLocation &Loc = DiagnosticLocation(),
+ DiagnosticSeverity Severity = DS_Error)
+ : DiagnosticInfoWithLocationBase(DK_Unsupported, Severity, Fn, Loc),
Msg(Msg) {}
static bool classof(const DiagnosticInfo *DI) {
@@ -874,19 +1012,6 @@ public:
void print(DiagnosticPrinter &DP) const override;
};
-
-/// Emit a warning when loop vectorization is specified but fails. \p Fn is the
-/// function triggering the warning, \p DLoc is the debug location where the
-/// diagnostic is generated. \p Msg is the message string to use.
-void emitLoopVectorizeWarning(LLVMContext &Ctx, const Function &Fn,
- const DebugLoc &DLoc, const Twine &Msg);
-
-/// Emit a warning when loop interleaving is specified but fails. \p Fn is the
-/// function triggering the warning, \p DLoc is the debug location where the
-/// diagnostic is generated. \p Msg is the message string to use.
-void emitLoopInterleaveWarning(LLVMContext &Ctx, const Function &Fn,
- const DebugLoc &DLoc, const Twine &Msg);
-
} // end namespace llvm
#endif // LLVM_IR_DIAGNOSTICINFO_H
diff --git a/include/llvm/IR/Dominators.h b/include/llvm/IR/Dominators.h
index 7c733bac8da0..cae03d33a7ee 100644
--- a/include/llvm/IR/Dominators.h
+++ b/include/llvm/IR/Dominators.h
@@ -16,17 +16,21 @@
#define LLVM_IR_DOMINATORS_H
#include "llvm/ADT/DenseMapInfo.h"
+#include "llvm/ADT/DepthFirstIterator.h"
#include "llvm/ADT/GraphTraits.h"
-#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/Hashing.h"
+#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/CFG.h"
#include "llvm/IR/PassManager.h"
#include "llvm/Pass.h"
#include "llvm/Support/GenericDomTree.h"
+#include <utility>
namespace llvm {
class Function;
-class BasicBlock;
+class Instruction;
+class Module;
class raw_ostream;
extern template class DomTreeNodeBase<BasicBlock>;
@@ -43,24 +47,37 @@ typedef DomTreeNodeBase<BasicBlock> DomTreeNode;
class BasicBlockEdge {
const BasicBlock *Start;
const BasicBlock *End;
+
public:
BasicBlockEdge(const BasicBlock *Start_, const BasicBlock *End_) :
- Start(Start_), End(End_) { }
+ Start(Start_), End(End_) {}
+
+ BasicBlockEdge(const std::pair<BasicBlock *, BasicBlock *> &Pair)
+ : Start(Pair.first), End(Pair.second) {}
+
+ BasicBlockEdge(const std::pair<const BasicBlock *, const BasicBlock *> &Pair)
+ : Start(Pair.first), End(Pair.second) {}
+
const BasicBlock *getStart() const {
return Start;
}
+
const BasicBlock *getEnd() const {
return End;
}
+
bool isSingleEdge() const;
};
template <> struct DenseMapInfo<BasicBlockEdge> {
- static unsigned getHashValue(const BasicBlockEdge *V);
typedef DenseMapInfo<const BasicBlock *> BBInfo;
+
+ static unsigned getHashValue(const BasicBlockEdge *V);
+
static inline BasicBlockEdge getEmptyKey() {
return BasicBlockEdge(BBInfo::getEmptyKey(), BBInfo::getEmptyKey());
}
+
static inline BasicBlockEdge getTombstoneKey() {
return BasicBlockEdge(BBInfo::getTombstoneKey(), BBInfo::getTombstoneKey());
}
@@ -69,6 +86,7 @@ template <> struct DenseMapInfo<BasicBlockEdge> {
return hash_combine(BBInfo::getHashValue(Edge.getStart()),
BBInfo::getHashValue(Edge.getEnd()));
}
+
static bool isEqual(const BasicBlockEdge &LHS, const BasicBlockEdge &RHS) {
return BBInfo::isEqual(LHS.getStart(), RHS.getStart()) &&
BBInfo::isEqual(LHS.getEnd(), RHS.getEnd());
@@ -102,19 +120,17 @@ public:
recalculate(F);
}
+ /// Handle invalidation explicitly.
+ bool invalidate(Function &F, const PreservedAnalyses &PA,
+ FunctionAnalysisManager::Invalidator &);
+
/// \brief Returns *false* if the other dominator tree matches this dominator
/// tree.
inline bool compare(const DominatorTree &Other) const {
const DomTreeNode *R = getRootNode();
const DomTreeNode *OtherR = Other.getRootNode();
-
- if (!R || !OtherR || R->getBlock() != OtherR->getBlock())
- return true;
-
- if (Base::compare(Other))
- return true;
-
- return false;
+ return !R || !OtherR || R->getBlock() != OtherR->getBlock() ||
+ Base::compare(Other);
}
// Ensure base-class overloads are visible.
@@ -205,6 +221,7 @@ class DominatorTreePrinterPass
public:
explicit DominatorTreePrinterPass(raw_ostream &OS);
+
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
};
@@ -240,6 +257,6 @@ public:
void print(raw_ostream &OS, const Module *M = nullptr) const override;
};
-} // End llvm namespace
+} // end namespace llvm
-#endif
+#endif // LLVM_IR_DOMINATORS_H
diff --git a/include/llvm/IR/Function.h b/include/llvm/IR/Function.h
index 1854d413c627..a3762a44ccb6 100644
--- a/include/llvm/IR/Function.h
+++ b/include/llvm/IR/Function.h
@@ -18,6 +18,7 @@
#ifndef LLVM_IR_FUNCTION_H
#define LLVM_IR_FUNCTION_H
+#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/ilist_node.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/ADT/StringRef.h"
@@ -47,23 +48,23 @@ class DISubprogram;
class Function : public GlobalObject, public ilist_node<Function> {
public:
- typedef SymbolTableList<Argument> ArgumentListType;
typedef SymbolTableList<BasicBlock> BasicBlockListType;
// BasicBlock iterators...
typedef BasicBlockListType::iterator iterator;
typedef BasicBlockListType::const_iterator const_iterator;
- typedef ArgumentListType::iterator arg_iterator;
- typedef ArgumentListType::const_iterator const_arg_iterator;
+ typedef Argument *arg_iterator;
+ typedef const Argument *const_arg_iterator;
private:
// Important things that make up a function!
BasicBlockListType BasicBlocks; ///< The basic blocks
- mutable ArgumentListType ArgumentList; ///< The formal arguments
+ mutable Argument *Arguments; ///< The formal arguments
+ size_t NumArgs;
std::unique_ptr<ValueSymbolTable>
SymTab; ///< Symbol table of args/instructions
- AttributeSet AttributeSets; ///< Parameter attributes
+ AttributeList AttributeSets; ///< Parameter attributes
/*
* Value::SubclassData
@@ -102,6 +103,8 @@ private:
void BuildLazyArguments() const;
+ void clearArguments();
+
/// Function ctor - If the (optional) Module argument is specified, the
/// function is automatically inserted into the end of the function list for
/// the module.
@@ -121,10 +124,12 @@ public:
// Provide fast operand accessors.
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
- /// Returns the type of the ret val.
- Type *getReturnType() const;
/// Returns the FunctionType for me.
- FunctionType *getFunctionType() const;
+ FunctionType *getFunctionType() const {
+ return cast<FunctionType>(getValueType());
+ }
+ /// Returns the type of the ret val.
+ Type *getReturnType() const { return getFunctionType()->getReturnType(); }
/// getContext - Return a reference to the LLVMContext associated with this
/// function.
@@ -132,10 +137,16 @@ public:
/// isVarArg - Return true if this function takes a variable number of
/// arguments.
- bool isVarArg() const;
+ bool isVarArg() const { return getFunctionType()->isVarArg(); }
- bool isMaterializable() const;
- void setIsMaterializable(bool V);
+ bool isMaterializable() const {
+ return getGlobalObjectSubClassData() & (1 << IsMaterializableBit);
+ }
+ void setIsMaterializable(bool V) {
+ unsigned Mask = 1 << IsMaterializableBit;
+ setGlobalObjectSubClassData((~Mask & getGlobalObjectSubClassData()) |
+ (V ? Mask : 0u));
+ }
/// getIntrinsicID - This method returns the ID number of the specified
/// function, or Intrinsic::not_intrinsic if the function is not an
@@ -173,42 +184,45 @@ public:
}
/// @brief Return the attribute list for this Function.
- AttributeSet getAttributes() const { return AttributeSets; }
+ AttributeList getAttributes() const { return AttributeSets; }
/// @brief Set the attribute list for this Function.
- void setAttributes(AttributeSet Attrs) { AttributeSets = Attrs; }
+ void setAttributes(AttributeList Attrs) { AttributeSets = Attrs; }
/// @brief Add function attributes to this function.
void addFnAttr(Attribute::AttrKind Kind) {
- addAttribute(AttributeSet::FunctionIndex, Kind);
+ addAttribute(AttributeList::FunctionIndex, Kind);
}
/// @brief Add function attributes to this function.
void addFnAttr(StringRef Kind, StringRef Val = StringRef()) {
- addAttribute(AttributeSet::FunctionIndex,
+ addAttribute(AttributeList::FunctionIndex,
Attribute::get(getContext(), Kind, Val));
}
void addFnAttr(Attribute Attr) {
- addAttribute(AttributeSet::FunctionIndex, Attr);
+ addAttribute(AttributeList::FunctionIndex, Attr);
}
/// @brief Remove function attributes from this function.
void removeFnAttr(Attribute::AttrKind Kind) {
- removeAttribute(AttributeSet::FunctionIndex, Kind);
+ removeAttribute(AttributeList::FunctionIndex, Kind);
}
/// @brief Remove function attribute from this function.
void removeFnAttr(StringRef Kind) {
setAttributes(AttributeSets.removeAttribute(
- getContext(), AttributeSet::FunctionIndex, Kind));
+ getContext(), AttributeList::FunctionIndex, Kind));
}
/// \brief Set the entry count for this function.
///
/// Entry count is the number of times this function was executed based on
- /// pgo data.
- void setEntryCount(uint64_t Count);
+ /// pgo data. \p Imports points to a set of GUIDs that needs to be imported
+ /// by the function for sample PGO, to enable the same inlines as the
+ /// profiled optimized binary.
+ void setEntryCount(uint64_t Count,
+ const DenseSet<GlobalValue::GUID> *Imports = nullptr);
/// \brief Get the entry count for this function.
///
@@ -216,6 +230,10 @@ public:
/// pgo data.
Optional<uint64_t> getEntryCount() const;
+ /// Returns the set of GUIDs that needs to be imported to the function for
+ /// sample PGO, to enable the same inlines as the profiled optimized binary.
+ DenseSet<GlobalValue::GUID> getImportGUIDs() const;
+
/// Set the section prefix for this function.
void setSectionPrefix(StringRef Prefix);
@@ -232,17 +250,17 @@ public:
/// @brief Return the attribute for the given attribute kind.
Attribute getFnAttribute(Attribute::AttrKind Kind) const {
- return getAttribute(AttributeSet::FunctionIndex, Kind);
+ return getAttribute(AttributeList::FunctionIndex, Kind);
}
Attribute getFnAttribute(StringRef Kind) const {
- return getAttribute(AttributeSet::FunctionIndex, Kind);
+ return getAttribute(AttributeList::FunctionIndex, Kind);
}
/// \brief Return the stack alignment for the function.
unsigned getFnStackAlignment() const {
if (!hasFnAttribute(Attribute::StackAlignment))
return 0;
- return AttributeSets.getStackAlignment(AttributeSet::FunctionIndex);
+ return AttributeSets.getStackAlignment(AttributeList::FunctionIndex);
}
/// hasGC/getGC/setGC/clearGC - The name of the garbage collection algorithm
@@ -261,7 +279,7 @@ public:
void addAttribute(unsigned i, Attribute Attr);
/// @brief adds the attributes to the list of attributes.
- void addAttributes(unsigned i, AttributeSet Attrs);
+ void addAttributes(unsigned i, AttributeList Attrs);
/// @brief removes the attribute from the list of attributes.
void removeAttribute(unsigned i, Attribute::AttrKind Kind);
@@ -270,13 +288,18 @@ public:
void removeAttribute(unsigned i, StringRef Kind);
/// @brief removes the attributes from the list of attributes.
- void removeAttributes(unsigned i, AttributeSet Attrs);
+ void removeAttributes(unsigned i, AttributeList Attrs);
/// @brief check if an attributes is in the list of attributes.
bool hasAttribute(unsigned i, Attribute::AttrKind Kind) const {
return getAttributes().hasAttribute(i, Kind);
}
+ /// @brief check if an attributes is in the list of attributes.
+ bool hasParamAttribute(unsigned ArgNo, Attribute::AttrKind Kind) const {
+ return getAttributes().hasParamAttribute(ArgNo, Kind);
+ }
+
Attribute getAttribute(unsigned i, Attribute::AttrKind Kind) const {
return AttributeSets.getAttribute(i, Kind);
}
@@ -496,19 +519,6 @@ public:
/// Get the underlying elements of the Function... the basic block list is
/// empty for external functions.
///
- const ArgumentListType &getArgumentList() const {
- CheckLazyArguments();
- return ArgumentList;
- }
- ArgumentListType &getArgumentList() {
- CheckLazyArguments();
- return ArgumentList;
- }
-
- static ArgumentListType Function::*getSublistAccess(Argument*) {
- return &Function::ArgumentList;
- }
-
const BasicBlockListType &getBasicBlockList() const { return BasicBlocks; }
BasicBlockListType &getBasicBlockList() { return BasicBlocks; }
@@ -549,20 +559,20 @@ public:
arg_iterator arg_begin() {
CheckLazyArguments();
- return ArgumentList.begin();
+ return Arguments;
}
const_arg_iterator arg_begin() const {
CheckLazyArguments();
- return ArgumentList.begin();
+ return Arguments;
}
arg_iterator arg_end() {
CheckLazyArguments();
- return ArgumentList.end();
+ return Arguments + NumArgs;
}
const_arg_iterator arg_end() const {
CheckLazyArguments();
- return ArgumentList.end();
+ return Arguments + NumArgs;
}
iterator_range<arg_iterator> args() {
@@ -574,8 +584,8 @@ public:
/// @}
- size_t arg_size() const;
- bool arg_empty() const;
+ size_t arg_size() const { return NumArgs; }
+ bool arg_empty() const { return arg_size() == 0; }
/// \brief Check whether this function has a personality function.
bool hasPersonalityFn() const {
@@ -671,6 +681,9 @@ public:
/// to \a DISubprogram.
DISubprogram *getSubprogram() const;
+ /// Returns true if we should emit debug info for profiling.
+ bool isDebugInfoForProfiling() const;
+
private:
void allocHungoffUselist();
template<int Idx> void setHungoffOperand(Constant *C);
diff --git a/include/llvm/IR/GlobalIndirectSymbol.h b/include/llvm/IR/GlobalIndirectSymbol.h
index 671309e85d19..212703af7101 100644
--- a/include/llvm/IR/GlobalIndirectSymbol.h
+++ b/include/llvm/IR/GlobalIndirectSymbol.h
@@ -48,27 +48,31 @@ public:
setOperand(0, Symbol);
}
const Constant *getIndirectSymbol() const {
- return const_cast<GlobalIndirectSymbol *>(this)->getIndirectSymbol();
+ return getOperand(0);
}
Constant *getIndirectSymbol() {
- return getOperand(0);
+ return const_cast<Constant *>(
+ static_cast<const GlobalIndirectSymbol *>(this)->getIndirectSymbol());
}
const GlobalObject *getBaseObject() const {
- return const_cast<GlobalIndirectSymbol *>(this)->getBaseObject();
+ return dyn_cast<GlobalObject>(getIndirectSymbol()->stripInBoundsOffsets());
}
GlobalObject *getBaseObject() {
- return dyn_cast<GlobalObject>(getIndirectSymbol()->stripInBoundsOffsets());
+ return const_cast<GlobalObject *>(
+ static_cast<const GlobalIndirectSymbol *>(this)->getBaseObject());
}
const GlobalObject *getBaseObject(const DataLayout &DL, APInt &Offset) const {
- return const_cast<GlobalIndirectSymbol *>(this)->getBaseObject(DL, Offset);
- }
- GlobalObject *getBaseObject(const DataLayout &DL, APInt &Offset) {
return dyn_cast<GlobalObject>(
getIndirectSymbol()->stripAndAccumulateInBoundsConstantOffsets(DL,
Offset));
}
+ GlobalObject *getBaseObject(const DataLayout &DL, APInt &Offset) {
+ return const_cast<GlobalObject *>(
+ static_cast<const GlobalIndirectSymbol *>(this)
+ ->getBaseObject(DL, Offset));
+ }
// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const Value *V) {
diff --git a/include/llvm/IR/GlobalObject.h b/include/llvm/IR/GlobalObject.h
index 1057f564aab3..f3789bafefe3 100644
--- a/include/llvm/IR/GlobalObject.h
+++ b/include/llvm/IR/GlobalObject.h
@@ -63,8 +63,17 @@ public:
}
void setAlignment(unsigned Align);
- unsigned getGlobalObjectSubClassData() const;
- void setGlobalObjectSubClassData(unsigned Val);
+ unsigned getGlobalObjectSubClassData() const {
+ unsigned ValueData = getGlobalValueSubClassData();
+ return ValueData >> GlobalObjectBits;
+ }
+
+ void setGlobalObjectSubClassData(unsigned Val) {
+ unsigned OldData = getGlobalValueSubClassData();
+ setGlobalValueSubClassData((OldData & GlobalObjectMask) |
+ (Val << GlobalObjectBits));
+ assert(getGlobalObjectSubClassData() == Val && "representation error");
+ }
/// Check if this global has a custom object file section.
///
diff --git a/include/llvm/IR/GlobalValue.h b/include/llvm/IR/GlobalValue.h
index c6398aaa4847..bb30fa8be867 100644
--- a/include/llvm/IR/GlobalValue.h
+++ b/include/llvm/IR/GlobalValue.h
@@ -211,9 +211,10 @@ public:
}
bool hasComdat() const { return getComdat() != nullptr; }
- Comdat *getComdat();
- const Comdat *getComdat() const {
- return const_cast<GlobalValue *>(this)->getComdat();
+ const Comdat *getComdat() const;
+ Comdat *getComdat() {
+ return const_cast<Comdat *>(
+ static_cast<const GlobalValue *>(this)->getComdat());
}
VisibilityTypes getVisibility() const { return VisibilityTypes(Visibility); }
@@ -514,10 +515,11 @@ public:
// increased.
bool canIncreaseAlignment() const;
- const GlobalObject *getBaseObject() const {
- return const_cast<GlobalValue *>(this)->getBaseObject();
+ const GlobalObject *getBaseObject() const;
+ GlobalObject *getBaseObject() {
+ return const_cast<GlobalObject *>(
+ static_cast<const GlobalValue *>(this)->getBaseObject());
}
- GlobalObject *getBaseObject();
/// Returns whether this is a reference to an absolute symbol.
bool isAbsoluteSymbolRef() const;
diff --git a/include/llvm/IR/IRBuilder.h b/include/llvm/IR/IRBuilder.h
index 1d9c16989de9..bc689f3b01d7 100644
--- a/include/llvm/IR/IRBuilder.h
+++ b/include/llvm/IR/IRBuilder.h
@@ -33,6 +33,7 @@
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Module.h"
#include "llvm/IR/Operator.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/Value.h"
@@ -75,7 +76,7 @@ class IRBuilderCallbackInserter : IRBuilderDefaultInserter {
public:
IRBuilderCallbackInserter(std::function<void(Instruction *)> Callback)
- : Callback(Callback) {}
+ : Callback(std::move(Callback)) {}
protected:
void InsertHelper(Instruction *I, const Twine &Name,
@@ -560,6 +561,22 @@ public:
Type *ResultType,
const Twine &Name = "");
+ /// Create a call to intrinsic \p ID with 2 operands which is mangled on the
+ /// first type.
+ CallInst *CreateBinaryIntrinsic(Intrinsic::ID ID,
+ Value *LHS, Value *RHS,
+ const Twine &Name = "");
+
+ /// Create call to the minnum intrinsic.
+ CallInst *CreateMinNum(Value *LHS, Value *RHS, const Twine &Name = "") {
+ return CreateBinaryIntrinsic(Intrinsic::minnum, LHS, RHS, Name);
+ }
+
+ /// Create call to the maxnum intrinsic.
+ CallInst *CreateMaxNum(Value *LHS, Value *RHS, const Twine &Name = "") {
+ return CreateBinaryIntrinsic(Intrinsic::minnum, LHS, RHS, Name);
+ }
+
private:
/// \brief Create a call to a masked intrinsic with given Id.
CallInst *CreateMaskedIntrinsic(Intrinsic::ID Id, ArrayRef<Value *> Ops,
@@ -1073,9 +1090,15 @@ public:
// Instruction creation methods: Memory Instructions
//===--------------------------------------------------------------------===//
+ AllocaInst *CreateAlloca(Type *Ty, unsigned AddrSpace,
+ Value *ArraySize = nullptr, const Twine &Name = "") {
+ return Insert(new AllocaInst(Ty, AddrSpace, ArraySize), Name);
+ }
+
AllocaInst *CreateAlloca(Type *Ty, Value *ArraySize = nullptr,
const Twine &Name = "") {
- return Insert(new AllocaInst(Ty, ArraySize), Name);
+ const DataLayout &DL = BB->getParent()->getParent()->getDataLayout();
+ return Insert(new AllocaInst(Ty, DL.getAllocaAddrSpace(), ArraySize), Name);
}
// \brief Provided to resolve 'CreateLoad(Ptr, "...")' correctly, instead of
// converting the string to 'bool' for the isVolatile parameter.
@@ -1790,24 +1813,16 @@ public:
return V;
}
- /// \brief Create an assume intrinsic call that represents an alignment
- /// assumption on the provided pointer.
- ///
- /// An optional offset can be provided, and if it is provided, the offset
- /// must be subtracted from the provided pointer to get the pointer with the
- /// specified alignment.
- CallInst *CreateAlignmentAssumption(const DataLayout &DL, Value *PtrValue,
- unsigned Alignment,
- Value *OffsetValue = nullptr) {
- assert(isa<PointerType>(PtrValue->getType()) &&
- "trying to create an alignment assumption on a non-pointer?");
-
- PointerType *PtrTy = cast<PointerType>(PtrValue->getType());
- Type *IntPtrTy = getIntPtrTy(DL, PtrTy->getAddressSpace());
+private:
+ /// \brief Helper function that creates an assume intrinsic call that
+ /// represents an alignment assumption on the provided Ptr, Mask, Type
+ /// and Offset.
+ CallInst *CreateAlignmentAssumptionHelper(const DataLayout &DL,
+ Value *PtrValue, Value *Mask,
+ Type *IntPtrTy,
+ Value *OffsetValue) {
Value *PtrIntValue = CreatePtrToInt(PtrValue, IntPtrTy, "ptrint");
- Value *Mask = ConstantInt::get(IntPtrTy,
- Alignment > 0 ? Alignment - 1 : 0);
if (OffsetValue) {
bool IsOffsetZero = false;
if (ConstantInt *CI = dyn_cast<ConstantInt>(OffsetValue))
@@ -1824,9 +1839,60 @@ public:
Value *Zero = ConstantInt::get(IntPtrTy, 0);
Value *MaskedPtr = CreateAnd(PtrIntValue, Mask, "maskedptr");
Value *InvCond = CreateICmpEQ(MaskedPtr, Zero, "maskcond");
-
return CreateAssumption(InvCond);
}
+
+public:
+ /// \brief Create an assume intrinsic call that represents an alignment
+ /// assumption on the provided pointer.
+ ///
+ /// An optional offset can be provided, and if it is provided, the offset
+ /// must be subtracted from the provided pointer to get the pointer with the
+ /// specified alignment.
+ CallInst *CreateAlignmentAssumption(const DataLayout &DL, Value *PtrValue,
+ unsigned Alignment,
+ Value *OffsetValue = nullptr) {
+ assert(isa<PointerType>(PtrValue->getType()) &&
+ "trying to create an alignment assumption on a non-pointer?");
+ PointerType *PtrTy = cast<PointerType>(PtrValue->getType());
+ Type *IntPtrTy = getIntPtrTy(DL, PtrTy->getAddressSpace());
+
+ Value *Mask = ConstantInt::get(IntPtrTy, Alignment > 0 ? Alignment - 1 : 0);
+ return CreateAlignmentAssumptionHelper(DL, PtrValue, Mask, IntPtrTy,
+ OffsetValue);
+ }
+ //
+ /// \brief Create an assume intrinsic call that represents an alignment
+ /// assumption on the provided pointer.
+ ///
+ /// An optional offset can be provided, and if it is provided, the offset
+ /// must be subtracted from the provided pointer to get the pointer with the
+ /// specified alignment.
+ ///
+ /// This overload handles the condition where the Alignment is dependent
+ /// on an existing value rather than a static value.
+ CallInst *CreateAlignmentAssumption(const DataLayout &DL, Value *PtrValue,
+ Value *Alignment,
+ Value *OffsetValue = nullptr) {
+ assert(isa<PointerType>(PtrValue->getType()) &&
+ "trying to create an alignment assumption on a non-pointer?");
+ PointerType *PtrTy = cast<PointerType>(PtrValue->getType());
+ Type *IntPtrTy = getIntPtrTy(DL, PtrTy->getAddressSpace());
+
+ if (Alignment->getType() != IntPtrTy)
+ Alignment = CreateIntCast(Alignment, IntPtrTy, /*isSigned*/ true,
+ "alignmentcast");
+ Value *IsPositive =
+ CreateICmp(CmpInst::ICMP_SGT, Alignment,
+ ConstantInt::get(Alignment->getType(), 0), "ispositive");
+ Value *PositiveMask =
+ CreateSub(Alignment, ConstantInt::get(IntPtrTy, 1), "positivemask");
+ Value *Mask = CreateSelect(IsPositive, PositiveMask,
+ ConstantInt::get(IntPtrTy, 0), "mask");
+
+ return CreateAlignmentAssumptionHelper(DL, PtrValue, Mask, IntPtrTy,
+ OffsetValue);
+ }
};
// Create wrappers for C Binding types (see CBindingWrapping.h).
diff --git a/include/llvm/IR/InlineAsm.h b/include/llvm/IR/InlineAsm.h
index f95509b9b09a..5d2f72d211ff 100644
--- a/include/llvm/IR/InlineAsm.h
+++ b/include/llvm/IR/InlineAsm.h
@@ -1,4 +1,4 @@
-//===-- llvm/InlineAsm.h - Class to represent inline asm strings-*- C++ -*-===//
+//===- llvm/InlineAsm.h - Class to represent inline asm strings -*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -102,12 +102,14 @@ public:
/// input constraint is required to match it (e.g. "0"). The value is the
/// constraint number that matches this one (for example, if this is
/// constraint #0 and constraint #4 has the value "0", this will be 4).
- signed char MatchingInput;
+ signed char MatchingInput = -1;
+
/// Code - The constraint code, either the register name (in braces) or the
/// constraint letter/number.
ConstraintCodeVector Codes;
+
/// Default constructor.
- SubConstraintInfo() : MatchingInput(-1) {}
+ SubConstraintInfo() = default;
};
typedef std::vector<SubConstraintInfo> SubConstraintInfoVector;
@@ -117,17 +119,17 @@ public:
struct ConstraintInfo {
/// Type - The basic type of the constraint: input/output/clobber
///
- ConstraintPrefix Type;
+ ConstraintPrefix Type = isInput;
/// isEarlyClobber - "&": output operand writes result before inputs are all
/// read. This is only ever set for an output operand.
- bool isEarlyClobber;
+ bool isEarlyClobber = false;
/// MatchingInput - If this is not -1, this is an output constraint where an
/// input constraint is required to match it (e.g. "0"). The value is the
/// constraint number that matches this one (for example, if this is
/// constraint #0 and constraint #4 has the value "0", this will be 4).
- signed char MatchingInput;
+ signed char MatchingInput = -1;
/// hasMatchingInput - Return true if this is an output constraint that has
/// a matching input constraint.
@@ -135,30 +137,30 @@ public:
/// isCommutative - This is set to true for a constraint that is commutative
/// with the next operand.
- bool isCommutative;
+ bool isCommutative = false;
/// isIndirect - True if this operand is an indirect operand. This means
/// that the address of the source or destination is present in the call
/// instruction, instead of it being returned or passed in explicitly. This
/// is represented with a '*' in the asm string.
- bool isIndirect;
+ bool isIndirect = false;
/// Code - The constraint code, either the register name (in braces) or the
/// constraint letter/number.
ConstraintCodeVector Codes;
/// isMultipleAlternative - '|': has multiple-alternative constraints.
- bool isMultipleAlternative;
+ bool isMultipleAlternative = false;
/// multipleAlternatives - If there are multiple alternative constraints,
/// this array will contain them. Otherwise it will be empty.
SubConstraintInfoVector multipleAlternatives;
/// The currently selected alternative constraint index.
- unsigned currentAlternativeIndex;
+ unsigned currentAlternativeIndex = 0;
/// Default constructor.
- ConstraintInfo();
+ ConstraintInfo() = default;
/// Parse - Analyze the specified string (e.g. "=*&{eax}") and fill in the
/// fields in this structure. If the constraint string is not understood,
diff --git a/include/llvm/IR/InstVisitor.h b/include/llvm/IR/InstVisitor.h
index 088d3e0fbfa5..55579819fd34 100644
--- a/include/llvm/IR/InstVisitor.h
+++ b/include/llvm/IR/InstVisitor.h
@@ -116,6 +116,9 @@ public:
// visit - Finally, code to visit an instruction...
//
RetTy visit(Instruction &I) {
+ static_assert(std::is_base_of<InstVisitor, SubClass>::value,
+ "Must pass the derived type to this template!");
+
switch (I.getOpcode()) {
default: llvm_unreachable("Unknown instruction type encountered!");
// Build the switch statement using the Instruction.def file...
diff --git a/include/llvm/IR/InstrTypes.h b/include/llvm/IR/InstrTypes.h
index f2abbec64fe6..518094735d72 100644
--- a/include/llvm/IR/InstrTypes.h
+++ b/include/llvm/IR/InstrTypes.h
@@ -1061,13 +1061,13 @@ public:
/// @brief Determine if Pred1 implies Pred2 is true when two compares have
/// matching operands.
- bool isImpliedTrueByMatchingCmp(Predicate Pred2) {
+ bool isImpliedTrueByMatchingCmp(Predicate Pred2) const {
return isImpliedTrueByMatchingCmp(getPredicate(), Pred2);
}
/// @brief Determine if Pred1 implies Pred2 is false when two compares have
/// matching operands.
- bool isImpliedFalseByMatchingCmp(Predicate Pred2) {
+ bool isImpliedFalseByMatchingCmp(Predicate Pred2) const {
return isImpliedFalseByMatchingCmp(getPredicate(), Pred2);
}
diff --git a/include/llvm/IR/Instruction.h b/include/llvm/IR/Instruction.h
index fd7c54d69b63..90c3175122fd 100644
--- a/include/llvm/IR/Instruction.h
+++ b/include/llvm/IR/Instruction.h
@@ -68,14 +68,20 @@ public:
/// 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();
+ Module *getModule() {
+ return const_cast<Module *>(
+ static_cast<const Instruction *>(this)->getModule());
+ }
/// Return the function this instruction belongs to.
///
/// Note: it is undefined behavior to call this on an instruction not
/// currently inserted into a function.
const Function *getFunction() const;
- Function *getFunction();
+ Function *getFunction() {
+ return const_cast<Function *>(
+ static_cast<const Instruction *>(this)->getFunction());
+ }
/// This method unlinks 'this' from the containing basic block, but does not
/// delete it.
@@ -252,6 +258,12 @@ public:
/// Returns false if no metadata was found.
bool extractProfTotalWeight(uint64_t &TotalVal) const;
+ /// Updates branch_weights metadata by scaling it by \p S / \p T.
+ void updateProfWeight(uint64_t S, uint64_t T);
+
+ /// Sets the branch_weights metadata to \p W for CallInst.
+ void setProfWeight(uint64_t W);
+
/// Set the debug location information for this instruction.
void setDebugLoc(DebugLoc Loc) { DbgLoc = std::move(Loc); }
@@ -276,6 +288,10 @@ public:
/// Determine whether the no signed wrap flag is set.
bool hasNoSignedWrap() const;
+ /// Drops flags that may cause this instruction to evaluate to poison despite
+ /// having non-poison inputs.
+ void dropPoisonGeneratingFlags();
+
/// Determine whether the exact flag is set.
bool isExact() const;
@@ -329,6 +345,9 @@ public:
/// Determine whether the allow-reciprocal flag is set.
bool hasAllowReciprocal() const;
+ /// Determine whether the allow-contract flag is set.
+ bool hasAllowContract() const;
+
/// Convenience function for getting all the fast-math flags, which must be an
/// operator which supports these flags. See LangRef.html for the meaning of
/// these flags.
@@ -372,18 +391,30 @@ public:
///
/// In LLVM, the Add, Mul, And, Or, and Xor operators are associative.
///
- bool isAssociative() const;
- static bool isAssociative(unsigned op);
+ bool isAssociative() const LLVM_READONLY;
+ static bool isAssociative(unsigned Opcode) {
+ return Opcode == And || Opcode == Or || Opcode == Xor ||
+ Opcode == Add || Opcode == Mul;
+ }
/// Return true if the instruction is commutative:
///
/// Commutative operators satisfy: (x op y) === (y op x)
///
- /// In LLVM, these are the associative operators, plus SetEQ and SetNE, when
+ /// In LLVM, these are the commutative operators, plus SetEQ and SetNE, when
/// applied to any type.
///
bool isCommutative() const { return isCommutative(getOpcode()); }
- static bool isCommutative(unsigned op);
+ static bool isCommutative(unsigned Opcode) {
+ switch (Opcode) {
+ case Add: case FAdd:
+ case Mul: case FMul:
+ case And: case Or: case Xor:
+ return true;
+ default:
+ return false;
+ }
+ }
/// Return true if the instruction is idempotent:
///
@@ -392,7 +423,9 @@ public:
/// In LLVM, the And and Or operators are idempotent.
///
bool isIdempotent() const { return isIdempotent(getOpcode()); }
- static bool isIdempotent(unsigned op);
+ static bool isIdempotent(unsigned Opcode) {
+ return Opcode == And || Opcode == Or;
+ }
/// Return true if the instruction is nilpotent:
///
@@ -404,7 +437,9 @@ public:
/// In LLVM, the Xor operator is nilpotent.
///
bool isNilpotent() const { return isNilpotent(getOpcode()); }
- static bool isNilpotent(unsigned op);
+ static bool isNilpotent(unsigned Opcode) {
+ return Opcode == Xor;
+ }
/// Return true if this instruction may modify memory.
bool mayWriteToMemory() const;
diff --git a/include/llvm/IR/Instructions.h b/include/llvm/IR/Instructions.h
index a5d78a08171a..34dafebe0fc5 100644
--- a/include/llvm/IR/Instructions.h
+++ b/include/llvm/IR/Instructions.h
@@ -67,18 +67,21 @@ protected:
AllocaInst *cloneImpl() const;
public:
- explicit AllocaInst(Type *Ty, Value *ArraySize = nullptr,
+ explicit AllocaInst(Type *Ty, unsigned AddrSpace,
+ Value *ArraySize = nullptr,
const Twine &Name = "",
Instruction *InsertBefore = nullptr);
- AllocaInst(Type *Ty, Value *ArraySize,
+ AllocaInst(Type *Ty, unsigned AddrSpace, Value *ArraySize,
const Twine &Name, BasicBlock *InsertAtEnd);
- AllocaInst(Type *Ty, const Twine &Name, Instruction *InsertBefore = nullptr);
- AllocaInst(Type *Ty, const Twine &Name, BasicBlock *InsertAtEnd);
+ AllocaInst(Type *Ty, unsigned AddrSpace,
+ const Twine &Name, Instruction *InsertBefore = nullptr);
+ AllocaInst(Type *Ty, unsigned AddrSpace,
+ const Twine &Name, BasicBlock *InsertAtEnd);
- AllocaInst(Type *Ty, Value *ArraySize, unsigned Align,
+ AllocaInst(Type *Ty, unsigned AddrSpace, Value *ArraySize, unsigned Align,
const Twine &Name = "", Instruction *InsertBefore = nullptr);
- AllocaInst(Type *Ty, Value *ArraySize, unsigned Align,
+ AllocaInst(Type *Ty, unsigned AddrSpace, Value *ArraySize, unsigned Align,
const Twine &Name, BasicBlock *InsertAtEnd);
// Out of line virtual method, so the vtable, etc. has a home.
@@ -958,6 +961,14 @@ public:
inline op_iterator idx_end() { return op_end(); }
inline const_op_iterator idx_end() const { return op_end(); }
+ inline iterator_range<op_iterator> indices() {
+ return make_range(idx_begin(), idx_end());
+ }
+
+ inline iterator_range<const_op_iterator> indices() const {
+ return make_range(idx_begin(), idx_end());
+ }
+
Value *getPointerOperand() {
return getOperand(0);
}
@@ -1354,7 +1365,7 @@ class CallInst : public Instruction,
public OperandBundleUser<CallInst, User::op_iterator> {
friend class OperandBundleUser<CallInst, User::op_iterator>;
- AttributeSet AttributeList; ///< parameter attributes for call
+ AttributeList Attrs; ///< parameter attributes for call
FunctionType *FTy;
CallInst(const CallInst &CI);
@@ -1633,11 +1644,11 @@ public:
/// Return the parameter attributes for this call.
///
- AttributeSet getAttributes() const { return AttributeList; }
+ AttributeList getAttributes() const { return Attrs; }
/// Set the parameter attributes for this call.
///
- void setAttributes(AttributeSet Attrs) { AttributeList = Attrs; }
+ void setAttributes(AttributeList A) { Attrs = A; }
/// adds the attribute to the list of attributes.
void addAttribute(unsigned i, Attribute::AttrKind Kind);
@@ -1670,8 +1681,11 @@ public:
return hasFnAttrImpl(Kind);
}
- /// Determine whether the call or the callee has the given attributes.
- bool paramHasAttr(unsigned i, Attribute::AttrKind Kind) const;
+ /// Determine whether the return value has the given attribute.
+ bool hasRetAttr(Attribute::AttrKind Kind) const;
+
+ /// Determine whether the argument or parameter has the given attribute.
+ bool paramHasAttr(unsigned ArgNo, Attribute::AttrKind Kind) const;
/// Get the attribute of a given kind at a position.
Attribute getAttribute(unsigned i, Attribute::AttrKind Kind) const {
@@ -1700,26 +1714,26 @@ public:
/// Extract the alignment for a call or parameter (0=unknown).
unsigned getParamAlignment(unsigned i) const {
- return AttributeList.getParamAlignment(i);
+ return Attrs.getParamAlignment(i);
}
/// Extract the number of dereferenceable bytes for a call or
/// parameter (0=unknown).
uint64_t getDereferenceableBytes(unsigned i) const {
- return AttributeList.getDereferenceableBytes(i);
+ return Attrs.getDereferenceableBytes(i);
}
/// Extract the number of dereferenceable_or_null bytes for a call or
/// parameter (0=unknown).
uint64_t getDereferenceableOrNullBytes(unsigned i) const {
- return AttributeList.getDereferenceableOrNullBytes(i);
+ return Attrs.getDereferenceableOrNullBytes(i);
}
/// @brief Determine if the parameter or return value is marked with NoAlias
/// attribute.
/// @param n The parameter to check. 1 is the first parameter, 0 is the return
bool doesNotAlias(unsigned n) const {
- return AttributeList.hasAttribute(n, Attribute::NoAlias);
+ return Attrs.hasAttribute(n, Attribute::NoAlias);
}
/// Return true if the call should not be treated as a call to a
@@ -1732,7 +1746,7 @@ public:
/// Return true if the call should not be inlined.
bool isNoInline() const { return hasFnAttr(Attribute::NoInline); }
void setIsNoInline() {
- addAttribute(AttributeSet::FunctionIndex, Attribute::NoInline);
+ addAttribute(AttributeList::FunctionIndex, Attribute::NoInline);
}
/// Return true if the call can return twice
@@ -1740,7 +1754,7 @@ public:
return hasFnAttr(Attribute::ReturnsTwice);
}
void setCanReturnTwice() {
- addAttribute(AttributeSet::FunctionIndex, Attribute::ReturnsTwice);
+ addAttribute(AttributeList::FunctionIndex, Attribute::ReturnsTwice);
}
/// Determine if the call does not access memory.
@@ -1748,7 +1762,7 @@ public:
return hasFnAttr(Attribute::ReadNone);
}
void setDoesNotAccessMemory() {
- addAttribute(AttributeSet::FunctionIndex, Attribute::ReadNone);
+ addAttribute(AttributeList::FunctionIndex, Attribute::ReadNone);
}
/// Determine if the call does not access or only reads memory.
@@ -1756,7 +1770,7 @@ public:
return doesNotAccessMemory() || hasFnAttr(Attribute::ReadOnly);
}
void setOnlyReadsMemory() {
- addAttribute(AttributeSet::FunctionIndex, Attribute::ReadOnly);
+ addAttribute(AttributeList::FunctionIndex, Attribute::ReadOnly);
}
/// Determine if the call does not access or only writes memory.
@@ -1764,7 +1778,7 @@ public:
return doesNotAccessMemory() || hasFnAttr(Attribute::WriteOnly);
}
void setDoesNotReadMemory() {
- addAttribute(AttributeSet::FunctionIndex, Attribute::WriteOnly);
+ addAttribute(AttributeList::FunctionIndex, Attribute::WriteOnly);
}
/// @brief Determine if the call can access memmory only using pointers based
@@ -1773,34 +1787,34 @@ public:
return hasFnAttr(Attribute::ArgMemOnly);
}
void setOnlyAccessesArgMemory() {
- addAttribute(AttributeSet::FunctionIndex, Attribute::ArgMemOnly);
+ addAttribute(AttributeList::FunctionIndex, Attribute::ArgMemOnly);
}
/// Determine if the call cannot return.
bool doesNotReturn() const { return hasFnAttr(Attribute::NoReturn); }
void setDoesNotReturn() {
- addAttribute(AttributeSet::FunctionIndex, Attribute::NoReturn);
+ addAttribute(AttributeList::FunctionIndex, Attribute::NoReturn);
}
/// Determine if the call cannot unwind.
bool doesNotThrow() const { return hasFnAttr(Attribute::NoUnwind); }
void setDoesNotThrow() {
- addAttribute(AttributeSet::FunctionIndex, Attribute::NoUnwind);
+ addAttribute(AttributeList::FunctionIndex, Attribute::NoUnwind);
}
/// Determine if the call cannot be duplicated.
bool cannotDuplicate() const {return hasFnAttr(Attribute::NoDuplicate); }
void setCannotDuplicate() {
- addAttribute(AttributeSet::FunctionIndex, Attribute::NoDuplicate);
+ addAttribute(AttributeList::FunctionIndex, Attribute::NoDuplicate);
}
/// Determine if the call is convergent
bool isConvergent() const { return hasFnAttr(Attribute::Convergent); }
void setConvergent() {
- addAttribute(AttributeSet::FunctionIndex, Attribute::Convergent);
+ addAttribute(AttributeList::FunctionIndex, Attribute::Convergent);
}
void setNotConvergent() {
- removeAttribute(AttributeSet::FunctionIndex, Attribute::Convergent);
+ removeAttribute(AttributeList::FunctionIndex, Attribute::Convergent);
}
/// Determine if the call returns a structure through first
@@ -1810,12 +1824,12 @@ public:
return false;
// Be friendly and also check the callee.
- return paramHasAttr(1, Attribute::StructRet);
+ return paramHasAttr(0, Attribute::StructRet);
}
/// Determine if any call argument is an aggregate passed by value.
bool hasByValArgument() const {
- return AttributeList.hasAttrSomewhere(Attribute::ByVal);
+ return Attrs.hasAttrSomewhere(Attribute::ByVal);
}
/// Return the function called, or null if this is an
@@ -1858,7 +1872,7 @@ public:
private:
template <typename AttrKind> bool hasFnAttrImpl(AttrKind Kind) const {
- if (AttributeList.hasAttribute(AttributeSet::FunctionIndex, Kind))
+ if (Attrs.hasAttribute(AttributeList::FunctionIndex, Kind))
return true;
// Operand bundles override attributes on the called function, but don't
@@ -1867,7 +1881,8 @@ private:
return false;
if (const Function *F = getCalledFunction())
- return F->getAttributes().hasAttribute(AttributeSet::FunctionIndex, Kind);
+ return F->getAttributes().hasAttribute(AttributeList::FunctionIndex,
+ Kind);
return false;
}
@@ -3084,42 +3099,41 @@ public:
// -2
static const unsigned DefaultPseudoIndex = static_cast<unsigned>(~0L-1);
- template <class SwitchInstTy, class ConstantIntTy, class BasicBlockTy>
- class CaseIteratorT {
- protected:
- SwitchInstTy *SI;
- unsigned Index;
+ template <typename CaseHandleT> class CaseIteratorImpl;
- public:
- typedef CaseIteratorT<SwitchInstTy, ConstantIntTy, BasicBlockTy> Self;
+ /// A handle to a particular switch case. It exposes a convenient interface
+ /// to both the case value and the successor block.
+ ///
+ /// We define this as a template and instantiate it to form both a const and
+ /// non-const handle.
+ template <typename SwitchInstT, typename ConstantIntT, typename BasicBlockT>
+ class CaseHandleImpl {
+ // Directly befriend both const and non-const iterators.
+ friend class SwitchInst::CaseIteratorImpl<
+ CaseHandleImpl<SwitchInstT, ConstantIntT, BasicBlockT>>;
- /// Initializes case iterator for given SwitchInst and for given
- /// case number.
- CaseIteratorT(SwitchInstTy *SI, unsigned CaseNum) {
- this->SI = SI;
- Index = CaseNum;
- }
+ protected:
+ // Expose the switch type we're parameterized with to the iterator.
+ typedef SwitchInstT SwitchInstType;
- /// Initializes case iterator for given SwitchInst and for given
- /// TerminatorInst's successor index.
- static Self fromSuccessorIndex(SwitchInstTy *SI, unsigned SuccessorIndex) {
- assert(SuccessorIndex < SI->getNumSuccessors() &&
- "Successor index # out of range!");
- return SuccessorIndex != 0 ?
- Self(SI, SuccessorIndex - 1) :
- Self(SI, DefaultPseudoIndex);
- }
+ SwitchInstT *SI;
+ ptrdiff_t Index;
+
+ CaseHandleImpl() = default;
+ CaseHandleImpl(SwitchInstT *SI, ptrdiff_t Index) : SI(SI), Index(Index) {}
+ public:
/// Resolves case value for current case.
- ConstantIntTy *getCaseValue() {
- assert(Index < SI->getNumCases() && "Index out the number of cases.");
- return reinterpret_cast<ConstantIntTy*>(SI->getOperand(2 + Index*2));
+ ConstantIntT *getCaseValue() const {
+ assert((unsigned)Index < SI->getNumCases() &&
+ "Index out the number of cases.");
+ return reinterpret_cast<ConstantIntT *>(SI->getOperand(2 + Index * 2));
}
/// Resolves successor for current case.
- BasicBlockTy *getCaseSuccessor() {
- assert((Index < SI->getNumCases() ||
- Index == DefaultPseudoIndex) &&
+ BasicBlockT *getCaseSuccessor() const {
+ assert(((unsigned)Index < SI->getNumCases() ||
+ (unsigned)Index == DefaultPseudoIndex) &&
"Index out the number of cases.");
return SI->getSuccessor(getSuccessorIndex());
}
@@ -3129,63 +3143,32 @@ public:
/// Returns TerminatorInst's successor index for current case successor.
unsigned getSuccessorIndex() const {
- assert((Index == DefaultPseudoIndex || Index < SI->getNumCases()) &&
+ assert(((unsigned)Index == DefaultPseudoIndex ||
+ (unsigned)Index < SI->getNumCases()) &&
"Index out the number of cases.");
- return Index != DefaultPseudoIndex ? Index + 1 : 0;
+ return (unsigned)Index != DefaultPseudoIndex ? Index + 1 : 0;
}
- Self operator++() {
- // Check index correctness after increment.
- // Note: Index == getNumCases() means end().
- assert(Index+1 <= SI->getNumCases() && "Index out the number of cases.");
- ++Index;
- return *this;
- }
- Self operator++(int) {
- Self tmp = *this;
- ++(*this);
- return tmp;
- }
- Self operator--() {
- // Check index correctness after decrement.
- // Note: Index == getNumCases() means end().
- // Also allow "-1" iterator here. That will became valid after ++.
- assert((Index == 0 || Index-1 <= SI->getNumCases()) &&
- "Index out the number of cases.");
- --Index;
- return *this;
- }
- Self operator--(int) {
- Self tmp = *this;
- --(*this);
- return tmp;
- }
- bool operator==(const Self& RHS) const {
- assert(RHS.SI == SI && "Incompatible operators.");
- return RHS.Index == Index;
- }
- bool operator!=(const Self& RHS) const {
- assert(RHS.SI == SI && "Incompatible operators.");
- return RHS.Index != Index;
- }
- Self &operator*() {
- return *this;
+ bool operator==(const CaseHandleImpl &RHS) const {
+ assert(SI == RHS.SI && "Incompatible operators.");
+ return Index == RHS.Index;
}
};
- typedef CaseIteratorT<const SwitchInst, const ConstantInt, const BasicBlock>
- ConstCaseIt;
+ typedef CaseHandleImpl<const SwitchInst, const ConstantInt, const BasicBlock>
+ ConstCaseHandle;
- class CaseIt : public CaseIteratorT<SwitchInst, ConstantInt, BasicBlock> {
- typedef CaseIteratorT<SwitchInst, ConstantInt, BasicBlock> ParentTy;
+ class CaseHandle
+ : public CaseHandleImpl<SwitchInst, ConstantInt, BasicBlock> {
+ friend class SwitchInst::CaseIteratorImpl<CaseHandle>;
public:
- CaseIt(const ParentTy &Src) : ParentTy(Src) {}
- CaseIt(SwitchInst *SI, unsigned CaseNum) : ParentTy(SI, CaseNum) {}
+ CaseHandle(SwitchInst *SI, ptrdiff_t Index) : CaseHandleImpl(SI, Index) {}
/// Sets the new value for current case.
void setValue(ConstantInt *V) {
- assert(Index < SI->getNumCases() && "Index out the number of cases.");
+ assert((unsigned)Index < SI->getNumCases() &&
+ "Index out the number of cases.");
SI->setOperand(2 + Index*2, reinterpret_cast<Value*>(V));
}
@@ -3195,6 +3178,76 @@ public:
}
};
+ template <typename CaseHandleT>
+ class CaseIteratorImpl
+ : public iterator_facade_base<CaseIteratorImpl<CaseHandleT>,
+ std::random_access_iterator_tag,
+ CaseHandleT> {
+ typedef typename CaseHandleT::SwitchInstType SwitchInstT;
+
+ CaseHandleT Case;
+
+ public:
+ /// Default constructed iterator is in an invalid state until assigned to
+ /// a case for a particular switch.
+ CaseIteratorImpl() = default;
+
+ /// Initializes case iterator for given SwitchInst and for given
+ /// case number.
+ CaseIteratorImpl(SwitchInstT *SI, unsigned CaseNum) : Case(SI, CaseNum) {}
+
+ /// Initializes case iterator for given SwitchInst and for given
+ /// TerminatorInst's successor index.
+ static CaseIteratorImpl fromSuccessorIndex(SwitchInstT *SI,
+ unsigned SuccessorIndex) {
+ assert(SuccessorIndex < SI->getNumSuccessors() &&
+ "Successor index # out of range!");
+ return SuccessorIndex != 0 ? CaseIteratorImpl(SI, SuccessorIndex - 1)
+ : CaseIteratorImpl(SI, DefaultPseudoIndex);
+ }
+
+ /// Support converting to the const variant. This will be a no-op for const
+ /// variant.
+ operator CaseIteratorImpl<ConstCaseHandle>() const {
+ return CaseIteratorImpl<ConstCaseHandle>(Case.SI, Case.Index);
+ }
+
+ CaseIteratorImpl &operator+=(ptrdiff_t N) {
+ // Check index correctness after addition.
+ // Note: Index == getNumCases() means end().
+ assert(Case.Index + N >= 0 &&
+ (unsigned)(Case.Index + N) <= Case.SI->getNumCases() &&
+ "Case.Index out the number of cases.");
+ Case.Index += N;
+ return *this;
+ }
+ CaseIteratorImpl &operator-=(ptrdiff_t N) {
+ // Check index correctness after subtraction.
+ // Note: Case.Index == getNumCases() means end().
+ assert(Case.Index - N >= 0 &&
+ (unsigned)(Case.Index - N) <= Case.SI->getNumCases() &&
+ "Case.Index out the number of cases.");
+ Case.Index -= N;
+ return *this;
+ }
+ ptrdiff_t operator-(const CaseIteratorImpl &RHS) const {
+ assert(Case.SI == RHS.Case.SI && "Incompatible operators.");
+ return Case.Index - RHS.Case.Index;
+ }
+ bool operator==(const CaseIteratorImpl &RHS) const {
+ return Case == RHS.Case;
+ }
+ bool operator<(const CaseIteratorImpl &RHS) const {
+ assert(Case.SI == RHS.Case.SI && "Incompatible operators.");
+ return Case.Index < RHS.Case.Index;
+ }
+ CaseHandleT &operator*() { return Case; }
+ const CaseHandleT &operator*() const { return Case; }
+ };
+
+ typedef CaseIteratorImpl<CaseHandle> CaseIt;
+ typedef CaseIteratorImpl<ConstCaseHandle> ConstCaseIt;
+
static SwitchInst *Create(Value *Value, BasicBlock *Default,
unsigned NumCases,
Instruction *InsertBefore = nullptr) {
@@ -3278,30 +3331,40 @@ public:
/// default case iterator to indicate that it is handled by the default
/// handler.
CaseIt findCaseValue(const ConstantInt *C) {
- for (CaseIt i = case_begin(), e = case_end(); i != e; ++i)
- if (i.getCaseValue() == C)
- return i;
+ CaseIt I = llvm::find_if(
+ cases(), [C](CaseHandle &Case) { return Case.getCaseValue() == C; });
+ if (I != case_end())
+ return I;
+
return case_default();
}
ConstCaseIt findCaseValue(const ConstantInt *C) const {
- for (ConstCaseIt i = case_begin(), e = case_end(); i != e; ++i)
- if (i.getCaseValue() == C)
- return i;
+ ConstCaseIt I = llvm::find_if(cases(), [C](ConstCaseHandle &Case) {
+ return Case.getCaseValue() == C;
+ });
+ if (I != case_end())
+ return I;
+
return case_default();
}
/// Finds the unique case value for a given successor. Returns null if the
/// successor is not found, not unique, or is the default case.
ConstantInt *findCaseDest(BasicBlock *BB) {
- if (BB == getDefaultDest()) return nullptr;
+ if (BB == getDefaultDest())
+ return nullptr;
ConstantInt *CI = nullptr;
- for (CaseIt i = case_begin(), e = case_end(); i != e; ++i) {
- if (i.getCaseSuccessor() == BB) {
- if (CI) return nullptr; // Multiple cases lead to BB.
- else CI = i.getCaseValue();
- }
+ for (auto Case : cases()) {
+ if (Case.getCaseSuccessor() != BB)
+ continue;
+
+ if (CI)
+ return nullptr; // Multiple cases lead to BB.
+
+ CI = Case.getCaseValue();
}
+
return CI;
}
@@ -3316,8 +3379,9 @@ public:
/// index idx and above.
/// Note:
/// This action invalidates iterators for all cases following the one removed,
- /// including the case_end() iterator.
- void removeCase(CaseIt i);
+ /// including the case_end() iterator. It returns an iterator for the next
+ /// case.
+ CaseIt removeCase(CaseIt I);
unsigned getNumSuccessors() const { return getNumOperands()/2; }
BasicBlock *getSuccessor(unsigned idx) const {
@@ -3465,7 +3529,7 @@ class InvokeInst : public TerminatorInst,
public OperandBundleUser<InvokeInst, User::op_iterator> {
friend class OperandBundleUser<InvokeInst, User::op_iterator>;
- AttributeSet AttributeList;
+ AttributeList Attrs;
FunctionType *FTy;
InvokeInst(const InvokeInst &BI);
@@ -3669,11 +3733,11 @@ public:
/// Return the parameter attributes for this invoke.
///
- AttributeSet getAttributes() const { return AttributeList; }
+ AttributeList getAttributes() const { return Attrs; }
/// Set the parameter attributes for this invoke.
///
- void setAttributes(AttributeSet Attrs) { AttributeList = Attrs; }
+ void setAttributes(AttributeList A) { Attrs = A; }
/// adds the attribute to the list of attributes.
void addAttribute(unsigned i, Attribute::AttrKind Kind);
@@ -3706,8 +3770,11 @@ public:
return hasFnAttrImpl(Kind);
}
- /// Determine whether the call or the callee has the given attributes.
- bool paramHasAttr(unsigned i, Attribute::AttrKind Kind) const;
+ /// Determine whether the return value has the given attribute.
+ bool hasRetAttr(Attribute::AttrKind Kind) const;
+
+ /// Determine whether the argument or parameter has the given attribute.
+ bool paramHasAttr(unsigned ArgNo, Attribute::AttrKind Kind) const;
/// Get the attribute of a given kind at a position.
Attribute getAttribute(unsigned i, Attribute::AttrKind Kind) const {
@@ -3737,26 +3804,26 @@ public:
/// Extract the alignment for a call or parameter (0=unknown).
unsigned getParamAlignment(unsigned i) const {
- return AttributeList.getParamAlignment(i);
+ return Attrs.getParamAlignment(i);
}
/// Extract the number of dereferenceable bytes for a call or
/// parameter (0=unknown).
uint64_t getDereferenceableBytes(unsigned i) const {
- return AttributeList.getDereferenceableBytes(i);
+ return Attrs.getDereferenceableBytes(i);
}
/// Extract the number of dereferenceable_or_null bytes for a call or
/// parameter (0=unknown).
uint64_t getDereferenceableOrNullBytes(unsigned i) const {
- return AttributeList.getDereferenceableOrNullBytes(i);
+ return Attrs.getDereferenceableOrNullBytes(i);
}
/// @brief Determine if the parameter or return value is marked with NoAlias
/// attribute.
/// @param n The parameter to check. 1 is the first parameter, 0 is the return
bool doesNotAlias(unsigned n) const {
- return AttributeList.hasAttribute(n, Attribute::NoAlias);
+ return Attrs.hasAttribute(n, Attribute::NoAlias);
}
/// Return true if the call should not be treated as a call to a
@@ -3771,7 +3838,7 @@ public:
/// Return true if the call should not be inlined.
bool isNoInline() const { return hasFnAttr(Attribute::NoInline); }
void setIsNoInline() {
- addAttribute(AttributeSet::FunctionIndex, Attribute::NoInline);
+ addAttribute(AttributeList::FunctionIndex, Attribute::NoInline);
}
/// Determine if the call does not access memory.
@@ -3779,7 +3846,7 @@ public:
return hasFnAttr(Attribute::ReadNone);
}
void setDoesNotAccessMemory() {
- addAttribute(AttributeSet::FunctionIndex, Attribute::ReadNone);
+ addAttribute(AttributeList::FunctionIndex, Attribute::ReadNone);
}
/// Determine if the call does not access or only reads memory.
@@ -3787,7 +3854,7 @@ public:
return doesNotAccessMemory() || hasFnAttr(Attribute::ReadOnly);
}
void setOnlyReadsMemory() {
- addAttribute(AttributeSet::FunctionIndex, Attribute::ReadOnly);
+ addAttribute(AttributeList::FunctionIndex, Attribute::ReadOnly);
}
/// Determine if the call does not access or only writes memory.
@@ -3795,7 +3862,7 @@ public:
return doesNotAccessMemory() || hasFnAttr(Attribute::WriteOnly);
}
void setDoesNotReadMemory() {
- addAttribute(AttributeSet::FunctionIndex, Attribute::WriteOnly);
+ addAttribute(AttributeList::FunctionIndex, Attribute::WriteOnly);
}
/// @brief Determine if the call access memmory only using it's pointer
@@ -3804,34 +3871,34 @@ public:
return hasFnAttr(Attribute::ArgMemOnly);
}
void setOnlyAccessesArgMemory() {
- addAttribute(AttributeSet::FunctionIndex, Attribute::ArgMemOnly);
+ addAttribute(AttributeList::FunctionIndex, Attribute::ArgMemOnly);
}
/// Determine if the call cannot return.
bool doesNotReturn() const { return hasFnAttr(Attribute::NoReturn); }
void setDoesNotReturn() {
- addAttribute(AttributeSet::FunctionIndex, Attribute::NoReturn);
+ addAttribute(AttributeList::FunctionIndex, Attribute::NoReturn);
}
/// Determine if the call cannot unwind.
bool doesNotThrow() const { return hasFnAttr(Attribute::NoUnwind); }
void setDoesNotThrow() {
- addAttribute(AttributeSet::FunctionIndex, Attribute::NoUnwind);
+ addAttribute(AttributeList::FunctionIndex, Attribute::NoUnwind);
}
/// Determine if the invoke cannot be duplicated.
bool cannotDuplicate() const {return hasFnAttr(Attribute::NoDuplicate); }
void setCannotDuplicate() {
- addAttribute(AttributeSet::FunctionIndex, Attribute::NoDuplicate);
+ addAttribute(AttributeList::FunctionIndex, Attribute::NoDuplicate);
}
/// Determine if the invoke is convergent
bool isConvergent() const { return hasFnAttr(Attribute::Convergent); }
void setConvergent() {
- addAttribute(AttributeSet::FunctionIndex, Attribute::Convergent);
+ addAttribute(AttributeList::FunctionIndex, Attribute::Convergent);
}
void setNotConvergent() {
- removeAttribute(AttributeSet::FunctionIndex, Attribute::Convergent);
+ removeAttribute(AttributeList::FunctionIndex, Attribute::Convergent);
}
/// Determine if the call returns a structure through first
@@ -3841,12 +3908,12 @@ public:
return false;
// Be friendly and also check the callee.
- return paramHasAttr(1, Attribute::StructRet);
+ return paramHasAttr(0, Attribute::StructRet);
}
/// Determine if any call argument is an aggregate passed by value.
bool hasByValArgument() const {
- return AttributeList.hasAttrSomewhere(Attribute::ByVal);
+ return Attrs.hasAttrSomewhere(Attribute::ByVal);
}
/// Return the function called, or null if this is an
@@ -3918,7 +3985,7 @@ private:
void setSuccessorV(unsigned idx, BasicBlock *B) override;
template <typename AttrKind> bool hasFnAttrImpl(AttrKind Kind) const {
- if (AttributeList.hasAttribute(AttributeSet::FunctionIndex, Kind))
+ if (Attrs.hasAttribute(AttributeList::FunctionIndex, Kind))
return true;
// Operand bundles override attributes on the called function, but don't
@@ -3927,7 +3994,8 @@ private:
return false;
if (const Function *F = getCalledFunction())
- return F->getAttributes().hasAttribute(AttributeSet::FunctionIndex, Kind);
+ return F->getAttributes().hasAttribute(AttributeList::FunctionIndex,
+ Kind);
return false;
}
diff --git a/include/llvm/IR/IntrinsicInst.h b/include/llvm/IR/IntrinsicInst.h
index b14a54503e52..f69b5bfc0be2 100644
--- a/include/llvm/IR/IntrinsicInst.h
+++ b/include/llvm/IR/IntrinsicInst.h
@@ -152,6 +152,71 @@ namespace llvm {
}
};
+ /// This is the common base class for constrained floating point intrinsics.
+ class ConstrainedFPIntrinsic : public IntrinsicInst {
+ public:
+ enum RoundingMode {
+ rmInvalid,
+ rmDynamic,
+ rmToNearest,
+ rmDownward,
+ rmUpward,
+ rmTowardZero
+ };
+
+ enum ExceptionBehavior {
+ ebInvalid,
+ ebIgnore,
+ ebMayTrap,
+ ebStrict
+ };
+
+ RoundingMode getRoundingMode() const;
+ ExceptionBehavior getExceptionBehavior() const;
+
+ // Methods for support type inquiry through isa, cast, and dyn_cast:
+ static inline bool classof(const IntrinsicInst *I) {
+ switch (I->getIntrinsicID()) {
+ case Intrinsic::experimental_constrained_fadd:
+ case Intrinsic::experimental_constrained_fsub:
+ case Intrinsic::experimental_constrained_fmul:
+ case Intrinsic::experimental_constrained_fdiv:
+ case Intrinsic::experimental_constrained_frem:
+ return true;
+ default: return false;
+ }
+ }
+ static inline bool classof(const Value *V) {
+ return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
+ }
+ };
+
+ /// This class represents atomic memcpy intrinsic
+ /// TODO: Integrate this class into MemIntrinsic hierarchy.
+ class ElementAtomicMemCpyInst : public IntrinsicInst {
+ public:
+ Value *getRawDest() const { return getArgOperand(0); }
+ Value *getRawSource() const { return getArgOperand(1); }
+
+ Value *getNumElements() const { return getArgOperand(2); }
+ void setNumElements(Value *V) { setArgOperand(2, V); }
+
+ uint64_t getSrcAlignment() const { return getParamAlignment(1); }
+ uint64_t getDstAlignment() const { return getParamAlignment(2); }
+
+ uint64_t getElementSizeInBytes() const {
+ Value *Arg = getArgOperand(3);
+ return cast<ConstantInt>(Arg)->getZExtValue();
+ }
+
+ static inline bool classof(const IntrinsicInst *I) {
+ return I->getIntrinsicID() == Intrinsic::memcpy_element_atomic;
+ }
+ static inline bool classof(const Value *V) {
+ return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
+ }
+ };
+
/// This is the common base class for memset/memcpy/memmove.
class MemIntrinsic : public IntrinsicInst {
public:
diff --git a/include/llvm/IR/Intrinsics.h b/include/llvm/IR/Intrinsics.h
index d07358445dab..2f6bdf8ecf19 100644
--- a/include/llvm/IR/Intrinsics.h
+++ b/include/llvm/IR/Intrinsics.h
@@ -28,7 +28,7 @@ class FunctionType;
class Function;
class LLVMContext;
class Module;
-class AttributeSet;
+class AttributeList;
/// This namespace contains an enum with a value for every intrinsic/builtin
/// function known by LLVM. The enum values are returned by
@@ -69,7 +69,7 @@ namespace Intrinsic {
bool isLeaf(ID id);
/// Return the attributes for an intrinsic.
- AttributeSet getAttributes(LLVMContext &C, ID id);
+ AttributeList getAttributes(LLVMContext &C, ID id);
/// Create or insert an LLVM Function declaration for an intrinsic, and return
/// it.
diff --git a/include/llvm/IR/Intrinsics.td b/include/llvm/IR/Intrinsics.td
index 89ae94270888..309b21489224 100644
--- a/include/llvm/IR/Intrinsics.td
+++ b/include/llvm/IR/Intrinsics.td
@@ -331,13 +331,13 @@ def int_get_dynamic_area_offset : Intrinsic<[llvm_anyint_ty]>;
def int_thread_pointer : Intrinsic<[llvm_ptr_ty], [], [IntrNoMem]>,
GCCBuiltin<"__builtin_thread_pointer">;
-// IntrArgMemOnly is more pessimistic than strictly necessary for prefetch,
-// however it does conveniently prevent the prefetch from being reordered
-// with respect to nearby accesses to the same memory.
-def int_prefetch : Intrinsic<[],
- [llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty,
- llvm_i32_ty],
- [IntrArgMemOnly, NoCapture<0>]>;
+// IntrInaccessibleMemOrArgMemOnly is a little more pessimistic than strictly
+// necessary for prefetch, however it does conveniently prevent the prefetch
+// from being reordered overly much with respect to nearby access to the same
+// memory while not impeding optimization.
+def int_prefetch
+ : Intrinsic<[], [ llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty ],
+ [ IntrInaccessibleMemOrArgMemOnly, ReadOnly<0>, NoCapture<0> ]>;
def int_pcmarker : Intrinsic<[], [llvm_i32_ty]>;
def int_readcyclecounter : Intrinsic<[llvm_i64_ty]>;
@@ -389,6 +389,9 @@ def int_memset : Intrinsic<[],
llvm_i32_ty, llvm_i1_ty],
[IntrArgMemOnly, NoCapture<0>, WriteOnly<0>]>;
+// FIXME: Add version of these floating point intrinsics which allow non-default
+// rounding modes and FP exception handling.
+
let IntrProperties = [IntrNoMem] in {
def int_fma : Intrinsic<[llvm_anyfloat_ty],
[LLVMMatchType<0>, LLVMMatchType<0>,
@@ -438,10 +441,44 @@ def int_sigsetjmp : Intrinsic<[llvm_i32_ty] , [llvm_ptr_ty, llvm_i32_ty]>;
def int_siglongjmp : Intrinsic<[], [llvm_ptr_ty, llvm_i32_ty], [IntrNoReturn]>;
// Internal interface for object size checking
-def int_objectsize : Intrinsic<[llvm_anyint_ty], [llvm_anyptr_ty, llvm_i1_ty],
+def int_objectsize : Intrinsic<[llvm_anyint_ty],
+ [llvm_anyptr_ty, llvm_i1_ty, llvm_i1_ty],
[IntrNoMem]>,
GCCBuiltin<"__builtin_object_size">;
+//===--------------- Constrained Floating Point Intrinsics ----------------===//
+//
+
+let IntrProperties = [IntrInaccessibleMemOnly] in {
+ def int_experimental_constrained_fadd : Intrinsic<[ llvm_anyfloat_ty ],
+ [ LLVMMatchType<0>,
+ LLVMMatchType<0>,
+ llvm_metadata_ty,
+ llvm_metadata_ty ]>;
+ def int_experimental_constrained_fsub : Intrinsic<[ llvm_anyfloat_ty ],
+ [ LLVMMatchType<0>,
+ LLVMMatchType<0>,
+ llvm_metadata_ty,
+ llvm_metadata_ty ]>;
+ def int_experimental_constrained_fmul : Intrinsic<[ llvm_anyfloat_ty ],
+ [ LLVMMatchType<0>,
+ LLVMMatchType<0>,
+ llvm_metadata_ty,
+ llvm_metadata_ty ]>;
+ def int_experimental_constrained_fdiv : Intrinsic<[ llvm_anyfloat_ty ],
+ [ LLVMMatchType<0>,
+ LLVMMatchType<0>,
+ llvm_metadata_ty,
+ llvm_metadata_ty ]>;
+ def int_experimental_constrained_frem : Intrinsic<[ llvm_anyfloat_ty ],
+ [ LLVMMatchType<0>,
+ LLVMMatchType<0>,
+ llvm_metadata_ty,
+ llvm_metadata_ty ]>;
+}
+// FIXME: Add intrinsic for fcmp, fptrunc, fpext, fptoui and fptosi.
+
+
//===------------------------- Expect Intrinsics --------------------------===//
//
def int_expect : Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>,
@@ -565,10 +602,10 @@ def int_umul_with_overflow : Intrinsic<[llvm_anyint_ty, llvm_i1_ty],
//===------------------------- Memory Use Markers -------------------------===//
//
def int_lifetime_start : Intrinsic<[],
- [llvm_i64_ty, llvm_ptr_ty],
+ [llvm_i64_ty, llvm_anyptr_ty],
[IntrArgMemOnly, NoCapture<1>]>;
def int_lifetime_end : Intrinsic<[],
- [llvm_i64_ty, llvm_ptr_ty],
+ [llvm_i64_ty, llvm_anyptr_ty],
[IntrArgMemOnly, NoCapture<1>]>;
def int_invariant_start : Intrinsic<[llvm_descriptor_ty],
[llvm_i64_ty, llvm_anyptr_ty],
@@ -578,9 +615,16 @@ def int_invariant_end : Intrinsic<[],
llvm_anyptr_ty],
[IntrArgMemOnly, NoCapture<2>]>;
+// invariant.group.barrier can't be marked with 'readnone' (IntrNoMem),
+// because it would cause CSE of two barriers with the same argument.
+// Readonly and argmemonly says that barrier only reads its argument and
+// it can be CSE only if memory didn't change between 2 barriers call,
+// which is valid.
+// The argument also can't be marked with 'returned' attribute, because
+// it would remove barrier.
def int_invariant_group_barrier : Intrinsic<[llvm_ptr_ty],
[llvm_ptr_ty],
- [IntrNoMem]>;
+ [IntrReadMem, IntrArgMemOnly]>;
//===------------------------ Stackmap Intrinsics -------------------------===//
//
@@ -619,18 +663,18 @@ def int_experimental_gc_relocate : Intrinsic<[llvm_any_ty],
// Coroutine Structure Intrinsics.
-def int_coro_id : Intrinsic<[llvm_token_ty], [llvm_i32_ty, llvm_ptr_ty,
- llvm_ptr_ty, llvm_ptr_ty],
- [IntrArgMemOnly, IntrReadMem,
+def int_coro_id : Intrinsic<[llvm_token_ty], [llvm_i32_ty, llvm_ptr_ty,
+ llvm_ptr_ty, llvm_ptr_ty],
+ [IntrArgMemOnly, IntrReadMem,
ReadNone<1>, ReadOnly<2>, NoCapture<2>]>;
def int_coro_alloc : Intrinsic<[llvm_i1_ty], [llvm_token_ty], []>;
def int_coro_begin : Intrinsic<[llvm_ptr_ty], [llvm_token_ty, llvm_ptr_ty],
[WriteOnly<1>]>;
-def int_coro_free : Intrinsic<[llvm_ptr_ty], [llvm_token_ty, llvm_ptr_ty],
- [IntrReadMem, IntrArgMemOnly, ReadOnly<1>,
+def int_coro_free : Intrinsic<[llvm_ptr_ty], [llvm_token_ty, llvm_ptr_ty],
+ [IntrReadMem, IntrArgMemOnly, ReadOnly<1>,
NoCapture<1>]>;
-def int_coro_end : Intrinsic<[], [llvm_ptr_ty, llvm_i1_ty], []>;
+def int_coro_end : Intrinsic<[llvm_i1_ty], [llvm_ptr_ty, llvm_i1_ty], []>;
def int_coro_frame : Intrinsic<[llvm_ptr_ty], [], [IntrNoMem]>;
def int_coro_size : Intrinsic<[llvm_anyint_ty], [], [IntrNoMem]>;
@@ -745,6 +789,10 @@ def int_memcpy_element_atomic : Intrinsic<[],
[IntrArgMemOnly, NoCapture<0>, NoCapture<1>,
WriteOnly<0>, ReadOnly<1>]>;
+//===----- Intrinsics that are used to provide predicate information -----===//
+
+def int_ssa_copy : Intrinsic<[llvm_any_ty], [LLVMMatchType<0>],
+ [IntrNoMem, Returned<0>]>;
//===----------------------------------------------------------------------===//
// Target-specific intrinsics
//===----------------------------------------------------------------------===//
diff --git a/include/llvm/IR/IntrinsicsAMDGPU.td b/include/llvm/IR/IntrinsicsAMDGPU.td
index dcec3860f2ca..5415c6b0d151 100644
--- a/include/llvm/IR/IntrinsicsAMDGPU.td
+++ b/include/llvm/IR/IntrinsicsAMDGPU.td
@@ -64,6 +64,10 @@ def int_r600_recipsqrt_clamped : Intrinsic<
[llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem]
>;
+def int_r600_cube : Intrinsic<
+ [llvm_v4f32_ty], [llvm_v4f32_ty], [IntrNoMem]
+>;
+
} // End TargetPrefix = "r600"
let TargetPrefix = "amdgcn" in {
@@ -121,7 +125,8 @@ def int_amdgcn_s_barrier : GCCBuiltin<"__builtin_amdgcn_s_barrier">,
def int_amdgcn_wave_barrier : GCCBuiltin<"__builtin_amdgcn_wave_barrier">,
Intrinsic<[], [], [IntrConvergent]>;
-def int_amdgcn_s_waitcnt : Intrinsic<[], [llvm_i32_ty], []>;
+def int_amdgcn_s_waitcnt : GCCBuiltin<"__builtin_amdgcn_s_waitcnt">,
+ Intrinsic<[], [llvm_i32_ty], []>;
def int_amdgcn_div_scale : Intrinsic<
// 1st parameter: Numerator
@@ -202,10 +207,19 @@ def int_amdgcn_fract : Intrinsic<
[llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem]
>;
+def int_amdgcn_cvt_pkrtz : Intrinsic<
+ [llvm_v2f16_ty], [llvm_float_ty, llvm_float_ty], [IntrNoMem]
+>;
+
def int_amdgcn_class : Intrinsic<
[llvm_i1_ty], [llvm_anyfloat_ty, llvm_i32_ty], [IntrNoMem]
>;
+def int_amdgcn_fmed3 : GCCBuiltin<"__builtin_amdgcn_fmed3">,
+ Intrinsic<[llvm_anyfloat_ty],
+ [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem]
+>;
+
def int_amdgcn_cubeid : GCCBuiltin<"__builtin_amdgcn_cubeid">,
Intrinsic<[llvm_float_ty],
[llvm_float_ty, llvm_float_ty, llvm_float_ty], [IntrNoMem]
@@ -231,17 +245,20 @@ def int_amdgcn_cubetc : GCCBuiltin<"__builtin_amdgcn_cubetc">,
def int_amdgcn_sffbh :
Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>], [IntrNoMem]>;
-// TODO: Do we want an ordering for these?
-def int_amdgcn_atomic_inc : Intrinsic<[llvm_anyint_ty],
- [llvm_anyptr_ty, LLVMMatchType<0>],
- [IntrArgMemOnly, NoCapture<0>]
->;
-def int_amdgcn_atomic_dec : Intrinsic<[llvm_anyint_ty],
- [llvm_anyptr_ty, LLVMMatchType<0>],
+// Fields should mirror atomicrmw
+class AMDGPUAtomicIncIntrin : Intrinsic<[llvm_anyint_ty],
+ [llvm_anyptr_ty,
+ LLVMMatchType<0>,
+ llvm_i32_ty, // ordering
+ llvm_i32_ty, // scope
+ llvm_i1_ty], // isVolatile
[IntrArgMemOnly, NoCapture<0>]
>;
+def int_amdgcn_atomic_inc : AMDGPUAtomicIncIntrin;
+def int_amdgcn_atomic_dec : AMDGPUAtomicIncIntrin;
+
class AMDGPUImageLoad : Intrinsic <
[llvm_anyfloat_ty], // vdata(VGPR)
[llvm_anyint_ty, // vaddr(VGPR)
@@ -451,6 +468,32 @@ def int_amdgcn_buffer_atomic_cmpswap : Intrinsic<
llvm_i1_ty], // slc(imm)
[]>;
+// Uses that do not set the done bit should set IntrWriteMem on the
+// call site.
+def int_amdgcn_exp : Intrinsic <[], [
+ llvm_i32_ty, // tgt,
+ llvm_i32_ty, // en
+ llvm_any_ty, // src0 (f32 or i32)
+ LLVMMatchType<0>, // src1
+ LLVMMatchType<0>, // src2
+ LLVMMatchType<0>, // src3
+ llvm_i1_ty, // done
+ llvm_i1_ty // vm
+ ],
+ []
+>;
+
+// exp with compr bit set.
+def int_amdgcn_exp_compr : Intrinsic <[], [
+ llvm_i32_ty, // tgt,
+ llvm_i32_ty, // en
+ llvm_anyvector_ty, // src0 (v2f16 or v2i16)
+ LLVMMatchType<0>, // src1
+ llvm_i1_ty, // done
+ llvm_i1_ty], // vm
+ []
+>;
+
def int_amdgcn_buffer_wbinvl1_sc :
GCCBuiltin<"__builtin_amdgcn_buffer_wbinvl1_sc">,
Intrinsic<[], [], []>;
@@ -530,7 +573,14 @@ def int_amdgcn_ds_swizzle :
GCCBuiltin<"__builtin_amdgcn_ds_swizzle">,
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem, IntrConvergent]>;
-// llvm.amdgcn.lerp
+def int_amdgcn_ubfe : Intrinsic<[llvm_anyint_ty],
+ [LLVMMatchType<0>, llvm_i32_ty, llvm_i32_ty], [IntrNoMem]
+>;
+
+def int_amdgcn_sbfe : Intrinsic<[llvm_anyint_ty],
+ [LLVMMatchType<0>, llvm_i32_ty, llvm_i32_ty], [IntrNoMem]
+>;
+
def int_amdgcn_lerp :
GCCBuiltin<"__builtin_amdgcn_lerp">,
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>;
@@ -619,10 +669,51 @@ def int_amdgcn_s_memrealtime :
// llvm.amdgcn.ds.permute <index> <src>
def int_amdgcn_ds_permute :
+ GCCBuiltin<"__builtin_amdgcn_ds_permute">,
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem, IntrConvergent]>;
// llvm.amdgcn.ds.bpermute <index> <src>
def int_amdgcn_ds_bpermute :
+ GCCBuiltin<"__builtin_amdgcn_ds_bpermute">,
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem, IntrConvergent]>;
+
+//===----------------------------------------------------------------------===//
+// Special Intrinsics for backend internal use only. No frontend
+// should emit calls to these.
+// ===----------------------------------------------------------------------===//
+def int_amdgcn_if : Intrinsic<[llvm_i1_ty, llvm_i64_ty],
+ [llvm_i1_ty], [IntrConvergent]
+>;
+
+def int_amdgcn_else : Intrinsic<[llvm_i1_ty, llvm_i64_ty],
+ [llvm_i64_ty], [IntrConvergent]
+>;
+
+def int_amdgcn_break : Intrinsic<[llvm_i64_ty],
+ [llvm_i64_ty], [IntrNoMem, IntrConvergent]
+>;
+
+def int_amdgcn_if_break : Intrinsic<[llvm_i64_ty],
+ [llvm_i1_ty, llvm_i64_ty], [IntrNoMem, IntrConvergent]
+>;
+
+def int_amdgcn_else_break : Intrinsic<[llvm_i64_ty],
+ [llvm_i64_ty, llvm_i64_ty], [IntrNoMem, IntrConvergent]
+>;
+
+def int_amdgcn_loop : Intrinsic<[llvm_i1_ty],
+ [llvm_i64_ty], [IntrConvergent]
+>;
+
+def int_amdgcn_end_cf : Intrinsic<[], [llvm_i64_ty], [IntrConvergent]>;
+
+// Represent unreachable in a divergent region.
+def int_amdgcn_unreachable : Intrinsic<[], [], [IntrConvergent]>;
+
+// Emit 2.5 ulp, no denormal division. Should only be inserted by
+// pass based on !fpmath metadata.
+def int_amdgcn_fdiv_fast : Intrinsic<
+ [llvm_float_ty], [llvm_float_ty, llvm_float_ty], [IntrNoMem]
+>;
}
diff --git a/include/llvm/IR/IntrinsicsARM.td b/include/llvm/IR/IntrinsicsARM.td
index 24239689a62e..18ed24be56d4 100644
--- a/include/llvm/IR/IntrinsicsARM.td
+++ b/include/llvm/IR/IntrinsicsARM.td
@@ -67,7 +67,7 @@ def int_arm_isb : GCCBuiltin<"__builtin_arm_isb">, MSBuiltin<"__isb">,
// VFP
def int_arm_get_fpscr : GCCBuiltin<"__builtin_arm_get_fpscr">,
- Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>;
+ Intrinsic<[llvm_i32_ty], [], []>;
def int_arm_set_fpscr : GCCBuiltin<"__builtin_arm_set_fpscr">,
Intrinsic<[], [llvm_i32_ty], []>;
def int_arm_vcvtr : Intrinsic<[llvm_float_ty], [llvm_anyfloat_ty],
diff --git a/include/llvm/IR/IntrinsicsHexagon.td b/include/llvm/IR/IntrinsicsHexagon.td
index 6519f051deeb..8ac56e03be6a 100644
--- a/include/llvm/IR/IntrinsicsHexagon.td
+++ b/include/llvm/IR/IntrinsicsHexagon.td
@@ -5659,20 +5659,20 @@ class Hexagon_v2048v2048v1024v1024i_Intrinsic<string GCCIntSuffix>
[IntrNoMem]>;
//
-// Hexagon_LLiLLiLLi_Intrinsic<string GCCIntSuffix>
-// tag : M6_vabsdiffb
-class Hexagon_LLiLLiLLi_Intrinsic<string GCCIntSuffix>
+// Hexagon_vv64ivmemv512_Intrinsic<string GCCIntSuffix>
+// tag: V6_vS32b_qpred_ai
+class Hexagon_vv64ivmemv512_Intrinsic<string GCCIntSuffix>
: Hexagon_Intrinsic<GCCIntSuffix,
- [llvm_i64_ty], [llvm_i64_ty,llvm_i64_ty],
- [IntrNoMem]>;
+ [], [llvm_v512i1_ty,llvm_ptr_ty,llvm_v16i32_ty],
+ [IntrArgMemOnly]>;
//
-// Hexagon_LLii_Intrinsic<string GCCIntSuffix>
-// tag : S6_vsplatrbp
-class Hexagon_LLii_Intrinsic<string GCCIntSuffix>
+// Hexagon_vv128ivmemv1024_Intrinsic<string GCCIntSuffix>
+// tag: V6_vS32b_qpred_ai_128B
+class Hexagon_vv128ivmemv1024_Intrinsic<string GCCIntSuffix>
: Hexagon_Intrinsic<GCCIntSuffix,
- [llvm_i64_ty], [llvm_i32_ty],
- [IntrNoMem]>;
+ [], [llvm_v1024i1_ty,llvm_ptr_ty,llvm_v32i32_ty],
+ [IntrArgMemOnly]>;
//
// BUILTIN_INFO(HEXAGON.S6_rol_i_r,SI_ftype_SISI,2)
@@ -9343,6 +9343,303 @@ def int_hexagon_V6_vlutvwh_oracc_128B :
Hexagon_v2048v2048v1024v1024i_Intrinsic<"HEXAGON_V6_vlutvwh_oracc_128B">;
//
+// Masked vector stores
+//
+def int_hexagon_V6_vmaskedstoreq :
+Hexagon_vv64ivmemv512_Intrinsic<"HEXAGON_V6_vmaskedstoreq">;
+
+def int_hexagon_V6_vmaskedstorenq :
+Hexagon_vv64ivmemv512_Intrinsic<"HEXAGON_V6_vmaskedstorenq">;
+
+def int_hexagon_V6_vmaskedstorentq :
+Hexagon_vv64ivmemv512_Intrinsic<"HEXAGON_V6_vmaskedstorentq">;
+
+def int_hexagon_V6_vmaskedstorentnq :
+Hexagon_vv64ivmemv512_Intrinsic<"HEXAGON_V6_vmaskedstorentnq">;
+
+def int_hexagon_V6_vmaskedstoreq_128B :
+Hexagon_vv128ivmemv1024_Intrinsic<"HEXAGON_V6_vmaskedstoreq_128B">;
+
+def int_hexagon_V6_vmaskedstorenq_128B :
+Hexagon_vv128ivmemv1024_Intrinsic<"HEXAGON_V6_vmaskedstorenq_128B">;
+
+def int_hexagon_V6_vmaskedstorentq_128B :
+Hexagon_vv128ivmemv1024_Intrinsic<"HEXAGON_V6_vmaskedstorentq_128B">;
+
+def int_hexagon_V6_vmaskedstorentnq_128B :
+Hexagon_vv128ivmemv1024_Intrinsic<"HEXAGON_V6_vmaskedstorentnq_128B">;
+
+
+///
+/// HexagonV62 intrinsics
+///
+
+//
+// Hexagon_LLiLLiLLi_Intrinsic<string GCCIntSuffix>
+// tag : M6_vabsdiffb
+class Hexagon_LLiLLiLLi_Intrinsic<string GCCIntSuffix>
+ : Hexagon_Intrinsic<GCCIntSuffix,
+ [llvm_i64_ty], [llvm_i64_ty,llvm_i64_ty],
+ [IntrNoMem]>;
+
+//
+// Hexagon_LLii_Intrinsic<string GCCIntSuffix>
+// tag : S6_vsplatrbp
+class Hexagon_LLii_Intrinsic<string GCCIntSuffix>
+ : Hexagon_Intrinsic<GCCIntSuffix,
+ [llvm_i64_ty], [llvm_i32_ty],
+ [IntrNoMem]>;
+
+//
+// Hexagon_V62_v512v512i_Intrinsic<string GCCIntSuffix>
+// tag : V6_vlsrb
+class Hexagon_V62_v512v512i_Intrinsic<string GCCIntSuffix>
+ : Hexagon_Intrinsic<GCCIntSuffix,
+ [llvm_v16i32_ty], [llvm_v16i32_ty,llvm_i32_ty],
+ [IntrNoMem]>;
+
+//
+// Hexagon_V62_v1024v1024i_Intrinsic<string GCCIntSuffix>
+// tag : V6_vlsrb_128B
+class Hexagon_V62_v1024v1024i_Intrinsic<string GCCIntSuffix>
+ : Hexagon_Intrinsic<GCCIntSuffix,
+ [llvm_v32i32_ty], [llvm_v32i32_ty,llvm_i32_ty],
+ [IntrNoMem]>;
+
+//
+// Hexagon_V62_v512v512v512i_Intrinsic<string GCCIntSuffix>
+// tag : V6_vasrwuhrndsat
+class Hexagon_V62_v512v512v512i_Intrinsic<string GCCIntSuffix>
+ : Hexagon_Intrinsic<GCCIntSuffix,
+ [llvm_v16i32_ty], [llvm_v16i32_ty,llvm_v16i32_ty,llvm_i32_ty],
+ [IntrNoMem]>;
+
+//
+// Hexagon_V62_v1024v1024v1024i_Intrinsic<string GCCIntSuffix>
+// tag : V6_vasrwuhrndsat_128B
+class Hexagon_V62_v1024v1024v1024i_Intrinsic<string GCCIntSuffix>
+ : Hexagon_Intrinsic<GCCIntSuffix,
+ [llvm_v32i32_ty], [llvm_v32i32_ty,llvm_v32i32_ty,llvm_i32_ty],
+ [IntrNoMem]>;
+
+//
+// Hexagon_V62_v512v512v512_Intrinsic<string GCCIntSuffix>
+// tag : V6_vrounduwuh
+class Hexagon_V62_v512v512v512_Intrinsic<string GCCIntSuffix>
+ : Hexagon_Intrinsic<GCCIntSuffix,
+ [llvm_v16i32_ty], [llvm_v16i32_ty,llvm_v16i32_ty],
+ [IntrNoMem]>;
+
+//
+// Hexagon_V62_v1024v1024v1024_Intrinsic<string GCCIntSuffix>
+// tag : V6_vrounduwuh_128B
+class Hexagon_V62_v1024v1024v1024_Intrinsic<string GCCIntSuffix>
+ : Hexagon_Intrinsic<GCCIntSuffix,
+ [llvm_v32i32_ty], [llvm_v32i32_ty,llvm_v32i32_ty],
+ [IntrNoMem]>;
+
+//
+// Hexagon_V62_v2048v2048v2048_Intrinsic<string GCCIntSuffix>
+// tag : V6_vadduwsat_dv_128B
+class Hexagon_V62_v2048v2048v2048_Intrinsic<string GCCIntSuffix>
+ : Hexagon_Intrinsic<GCCIntSuffix,
+ [llvm_v64i32_ty], [llvm_v64i32_ty,llvm_v64i32_ty],
+ [IntrNoMem]>;
+
+//
+// Hexagon_V62_v1024v1024v512v512_Intrinsic<string GCCIntSuffix>
+// tag : V6_vaddhw_acc
+class Hexagon_V62_v1024v1024v512v512_Intrinsic<string GCCIntSuffix>
+ : Hexagon_Intrinsic<GCCIntSuffix,
+ [llvm_v32i32_ty], [llvm_v32i32_ty,llvm_v16i32_ty,llvm_v16i32_ty],
+ [IntrNoMem]>;
+
+//
+// Hexagon_V62_v2048v2048v1024v1024_Intrinsic<string GCCIntSuffix>
+// tag : V6_vaddhw_acc_128B
+class Hexagon_V62_v2048v2048v1024v1024_Intrinsic<string GCCIntSuffix>
+ : Hexagon_Intrinsic<GCCIntSuffix,
+ [llvm_v64i32_ty], [llvm_v64i32_ty,llvm_v32i32_ty,llvm_v32i32_ty],
+ [IntrNoMem]>;
+
+//
+// Hexagon_V62_v1024v512v512_Intrinsic<string GCCIntSuffix>
+// tag : V6_vmpyewuh_64
+class Hexagon_V62_v1024v512v512_Intrinsic<string GCCIntSuffix>
+ : Hexagon_Intrinsic<GCCIntSuffix,
+ [llvm_v32i32_ty], [llvm_v16i32_ty,llvm_v16i32_ty],
+ [IntrNoMem]>;
+
+//
+// Hexagon_V62_v2048v1024v1024_Intrinsic<string GCCIntSuffix>
+// tag : V6_vmpyewuh_64_128B
+class Hexagon_V62_v2048v1024v1024_Intrinsic<string GCCIntSuffix>
+ : Hexagon_Intrinsic<GCCIntSuffix,
+ [llvm_v64i32_ty], [llvm_v32i32_ty,llvm_v32i32_ty],
+ [IntrNoMem]>;
+
+//
+// Hexagon_V62_v2048v2048i_Intrinsic<string GCCIntSuffix>
+// tag : V6_vmpauhb_128B
+class Hexagon_V62_v2048v2048i_Intrinsic<string GCCIntSuffix>
+ : Hexagon_Intrinsic<GCCIntSuffix,
+ [llvm_v64i32_ty], [llvm_v64i32_ty,llvm_i32_ty],
+ [IntrNoMem]>;
+
+//
+// Hexagon_V62_v2048v2048v2048i_Intrinsic<string GCCIntSuffix>
+// tag : V6_vmpauhb_acc_128B
+class Hexagon_V62_v2048v2048v2048i_Intrinsic<string GCCIntSuffix>
+ : Hexagon_Intrinsic<GCCIntSuffix,
+ [llvm_v64i32_ty], [llvm_v64i32_ty,llvm_v64i32_ty,llvm_i32_ty],
+ [IntrNoMem]>;
+
+//
+// Hexagon_V62_v512v64ii_Intrinsic<string GCCIntSuffix>
+// tag : V6_vandnqrt
+class Hexagon_V62_v512v64ii_Intrinsic<string GCCIntSuffix>
+ : Hexagon_Intrinsic<GCCIntSuffix,
+ [llvm_v16i32_ty], [llvm_v512i1_ty,llvm_i32_ty],
+ [IntrNoMem]>;
+
+//
+// Hexagon_V62_v1024v128ii_Intrinsic<string GCCIntSuffix>
+// tag : V6_vandnqrt_128B
+class Hexagon_V62_v1024v128ii_Intrinsic<string GCCIntSuffix>
+ : Hexagon_Intrinsic<GCCIntSuffix,
+ [llvm_v32i32_ty], [llvm_v1024i1_ty,llvm_i32_ty],
+ [IntrNoMem]>;
+
+//
+// Hexagon_V62_v512v512v64ii_Intrinsic<string GCCIntSuffix>
+// tag : V6_vandnqrt_acc
+class Hexagon_V62_v512v512v64ii_Intrinsic<string GCCIntSuffix>
+ : Hexagon_Intrinsic<GCCIntSuffix,
+ [llvm_v16i32_ty], [llvm_v16i32_ty,llvm_v512i1_ty,llvm_i32_ty],
+ [IntrNoMem]>;
+
+//
+// Hexagon_V62_v1024v1024v128ii_Intrinsic<string GCCIntSuffix>
+// tag : V6_vandnqrt_acc_128B
+class Hexagon_V62_v1024v1024v128ii_Intrinsic<string GCCIntSuffix>
+ : Hexagon_Intrinsic<GCCIntSuffix,
+ [llvm_v32i32_ty], [llvm_v32i32_ty,llvm_v1024i1_ty,llvm_i32_ty],
+ [IntrNoMem]>;
+
+//
+// Hexagon_V62_v512v64iv512_Intrinsic<string GCCIntSuffix>
+// tag : V6_vandvqv
+class Hexagon_V62_v512v64iv512_Intrinsic<string GCCIntSuffix>
+ : Hexagon_Intrinsic<GCCIntSuffix,
+ [llvm_v16i32_ty], [llvm_v512i1_ty,llvm_v16i32_ty],
+ [IntrNoMem]>;
+
+//
+// Hexagon_V62_v1024v128iv1024_Intrinsic<string GCCIntSuffix>
+// tag : V6_vandvqv_128B
+class Hexagon_V62_v1024v128iv1024_Intrinsic<string GCCIntSuffix>
+ : Hexagon_Intrinsic<GCCIntSuffix,
+ [llvm_v32i32_ty], [llvm_v1024i1_ty,llvm_v32i32_ty],
+ [IntrNoMem]>;
+
+//
+// Hexagon_V62_v64ii_Intrinsic<string GCCIntSuffix>
+// tag : V6_pred_scalar2v2
+class Hexagon_V62_v64ii_Intrinsic<string GCCIntSuffix>
+ : Hexagon_Intrinsic<GCCIntSuffix,
+ [llvm_v512i1_ty], [llvm_i32_ty],
+ [IntrNoMem]>;
+
+//
+// Hexagon_V62_v128ii_Intrinsic<string GCCIntSuffix>
+// tag : V6_pred_scalar2v2_128B
+class Hexagon_V62_v128ii_Intrinsic<string GCCIntSuffix>
+ : Hexagon_Intrinsic<GCCIntSuffix,
+ [llvm_v1024i1_ty], [llvm_i32_ty],
+ [IntrNoMem]>;
+
+//
+// Hexagon_V62_v64iv64iv64i_Intrinsic<string GCCIntSuffix>
+// tag : V6_shuffeqw
+class Hexagon_V62_v64iv64iv64i_Intrinsic<string GCCIntSuffix>
+ : Hexagon_Intrinsic<GCCIntSuffix,
+ [llvm_v512i1_ty], [llvm_v512i1_ty,llvm_v512i1_ty],
+ [IntrNoMem]>;
+
+//
+// Hexagon_V62_v128iv128iv128i_Intrinsic<string GCCIntSuffix>
+// tag : V6_shuffeqw_128B
+class Hexagon_V62_v128iv128iv128i_Intrinsic<string GCCIntSuffix>
+ : Hexagon_Intrinsic<GCCIntSuffix,
+ [llvm_v1024i1_ty], [llvm_v1024i1_ty,llvm_v1024i1_ty],
+ [IntrNoMem]>;
+
+//
+// Hexagon_V62_v512i_Intrinsic<string GCCIntSuffix>
+// tag : V6_lvsplath
+class Hexagon_V62_v512i_Intrinsic<string GCCIntSuffix>
+ : Hexagon_Intrinsic<GCCIntSuffix,
+ [llvm_v16i32_ty], [llvm_i32_ty],
+ [IntrNoMem]>;
+
+//
+// Hexagon_V62_v1024i_Intrinsic<string GCCIntSuffix>
+// tag : V6_lvsplath_128B
+class Hexagon_V62_v1024i_Intrinsic<string GCCIntSuffix>
+ : Hexagon_Intrinsic<GCCIntSuffix,
+ [llvm_v32i32_ty], [llvm_i32_ty],
+ [IntrNoMem]>;
+
+//
+// Hexagon_V62_v512v512v512v512i_Intrinsic<string GCCIntSuffix>
+// tag : V6_vlutvvb_oracci
+class Hexagon_V62_v512v512v512v512i_Intrinsic<string GCCIntSuffix>
+ : Hexagon_Intrinsic<GCCIntSuffix,
+ [llvm_v16i32_ty], [llvm_v16i32_ty,llvm_v16i32_ty,llvm_v16i32_ty,llvm_i32_ty],
+ [IntrNoMem]>;
+
+//
+// Hexagon_V62_v1024v1024v1024v1024i_Intrinsic<string GCCIntSuffix>
+// tag : V6_vlutvvb_oracci_128B
+class Hexagon_V62_v1024v1024v1024v1024i_Intrinsic<string GCCIntSuffix>
+ : Hexagon_Intrinsic<GCCIntSuffix,
+ [llvm_v32i32_ty], [llvm_v32i32_ty,llvm_v32i32_ty,llvm_v32i32_ty,llvm_i32_ty],
+ [IntrNoMem]>;
+
+//
+// Hexagon_V62_v1024v512v512i_Intrinsic<string GCCIntSuffix>
+// tag : V6_vlutvwhi
+class Hexagon_V62_v1024v512v512i_Intrinsic<string GCCIntSuffix>
+ : Hexagon_Intrinsic<GCCIntSuffix,
+ [llvm_v32i32_ty], [llvm_v16i32_ty,llvm_v16i32_ty,llvm_i32_ty],
+ [IntrNoMem]>;
+
+//
+// Hexagon_V62_v2048v1024v1024i_Intrinsic<string GCCIntSuffix>
+// tag : V6_vlutvwhi_128B
+class Hexagon_V62_v2048v1024v1024i_Intrinsic<string GCCIntSuffix>
+ : Hexagon_Intrinsic<GCCIntSuffix,
+ [llvm_v64i32_ty], [llvm_v32i32_ty,llvm_v32i32_ty,llvm_i32_ty],
+ [IntrNoMem]>;
+
+//
+// Hexagon_V62_v1024v1024v512v512i_Intrinsic<string GCCIntSuffix>
+// tag : V6_vlutvwh_oracci
+class Hexagon_V62_v1024v1024v512v512i_Intrinsic<string GCCIntSuffix>
+ : Hexagon_Intrinsic<GCCIntSuffix,
+ [llvm_v32i32_ty], [llvm_v32i32_ty,llvm_v16i32_ty,llvm_v16i32_ty,llvm_i32_ty],
+ [IntrNoMem]>;
+
+//
+// Hexagon_V62_v2048v2048v1024v1024i_Intrinsic<string GCCIntSuffix>
+// tag : V6_vlutvwh_oracci_128B
+class Hexagon_V62_v2048v2048v1024v1024i_Intrinsic<string GCCIntSuffix>
+ : Hexagon_Intrinsic<GCCIntSuffix,
+ [llvm_v64i32_ty], [llvm_v64i32_ty,llvm_v32i32_ty,llvm_v32i32_ty,llvm_i32_ty],
+ [IntrNoMem]>;
+
+
+//
// BUILTIN_INFO(HEXAGON.M6_vabsdiffb,DI_ftype_DIDI,2)
// tag : M6_vabsdiffb
def int_hexagon_M6_vabsdiffb :
@@ -9355,12 +9652,6 @@ def int_hexagon_M6_vabsdiffub :
Hexagon_LLiLLiLLi_Intrinsic<"HEXAGON_M6_vabsdiffub">;
//
-// BUILTIN_INFO(HEXAGON.S6_vsplatrbp,DI_ftype_SI,1)
-// tag : S6_vsplatrbp
-def int_hexagon_S6_vsplatrbp :
-Hexagon_LLii_Intrinsic<"HEXAGON_S6_vsplatrbp">;
-
-//
// BUILTIN_INFO(HEXAGON.S6_vtrunehb_ppp,DI_ftype_DIDI,2)
// tag : S6_vtrunehb_ppp
def int_hexagon_S6_vtrunehb_ppp :
@@ -9371,3 +9662,550 @@ Hexagon_LLiLLiLLi_Intrinsic<"HEXAGON_S6_vtrunehb_ppp">;
// tag : S6_vtrunohb_ppp
def int_hexagon_S6_vtrunohb_ppp :
Hexagon_LLiLLiLLi_Intrinsic<"HEXAGON_S6_vtrunohb_ppp">;
+
+//
+// BUILTIN_INFO(HEXAGON.S6_vsplatrbp,DI_ftype_SI,1)
+// tag : S6_vsplatrbp
+def int_hexagon_S6_vsplatrbp :
+Hexagon_LLii_Intrinsic<"HEXAGON_S6_vsplatrbp">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vlsrb,VI_ftype_VISI,2)
+// tag : V6_vlsrb
+def int_hexagon_V6_vlsrb :
+Hexagon_V62_v512v512i_Intrinsic<"HEXAGON_V6_vlsrb">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vlsrb_128B,VI_ftype_VISI,2)
+// tag : V6_vlsrb_128B
+def int_hexagon_V6_vlsrb_128B :
+Hexagon_V62_v1024v1024i_Intrinsic<"HEXAGON_V6_vlsrb_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vasrwuhrndsat,VI_ftype_VIVISI,3)
+// tag : V6_vasrwuhrndsat
+def int_hexagon_V6_vasrwuhrndsat :
+Hexagon_V62_v512v512v512i_Intrinsic<"HEXAGON_V6_vasrwuhrndsat">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vasrwuhrndsat_128B,VI_ftype_VIVISI,3)
+// tag : V6_vasrwuhrndsat_128B
+def int_hexagon_V6_vasrwuhrndsat_128B :
+Hexagon_V62_v1024v1024v1024i_Intrinsic<"HEXAGON_V6_vasrwuhrndsat_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vasruwuhrndsat,VI_ftype_VIVISI,3)
+// tag : V6_vasruwuhrndsat
+def int_hexagon_V6_vasruwuhrndsat :
+Hexagon_V62_v512v512v512i_Intrinsic<"HEXAGON_V6_vasruwuhrndsat">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vasruwuhrndsat_128B,VI_ftype_VIVISI,3)
+// tag : V6_vasruwuhrndsat_128B
+def int_hexagon_V6_vasruwuhrndsat_128B :
+Hexagon_V62_v1024v1024v1024i_Intrinsic<"HEXAGON_V6_vasruwuhrndsat_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vasrhbsat,VI_ftype_VIVISI,3)
+// tag : V6_vasrhbsat
+def int_hexagon_V6_vasrhbsat :
+Hexagon_V62_v512v512v512i_Intrinsic<"HEXAGON_V6_vasrhbsat">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vasrhbsat_128B,VI_ftype_VIVISI,3)
+// tag : V6_vasrhbsat_128B
+def int_hexagon_V6_vasrhbsat_128B :
+Hexagon_V62_v1024v1024v1024i_Intrinsic<"HEXAGON_V6_vasrhbsat_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vrounduwuh,VI_ftype_VIVI,2)
+// tag : V6_vrounduwuh
+def int_hexagon_V6_vrounduwuh :
+Hexagon_V62_v512v512v512_Intrinsic<"HEXAGON_V6_vrounduwuh">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vrounduwuh_128B,VI_ftype_VIVI,2)
+// tag : V6_vrounduwuh_128B
+def int_hexagon_V6_vrounduwuh_128B :
+Hexagon_V62_v1024v1024v1024_Intrinsic<"HEXAGON_V6_vrounduwuh_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vrounduhub,VI_ftype_VIVI,2)
+// tag : V6_vrounduhub
+def int_hexagon_V6_vrounduhub :
+Hexagon_V62_v512v512v512_Intrinsic<"HEXAGON_V6_vrounduhub">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vrounduhub_128B,VI_ftype_VIVI,2)
+// tag : V6_vrounduhub_128B
+def int_hexagon_V6_vrounduhub_128B :
+Hexagon_V62_v1024v1024v1024_Intrinsic<"HEXAGON_V6_vrounduhub_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vadduwsat,VI_ftype_VIVI,2)
+// tag : V6_vadduwsat
+def int_hexagon_V6_vadduwsat :
+Hexagon_V62_v512v512v512_Intrinsic<"HEXAGON_V6_vadduwsat">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vadduwsat_128B,VI_ftype_VIVI,2)
+// tag : V6_vadduwsat_128B
+def int_hexagon_V6_vadduwsat_128B :
+Hexagon_V62_v1024v1024v1024_Intrinsic<"HEXAGON_V6_vadduwsat_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vadduwsat_dv,VD_ftype_VDVD,2)
+// tag : V6_vadduwsat_dv
+def int_hexagon_V6_vadduwsat_dv :
+Hexagon_V62_v1024v1024v1024_Intrinsic<"HEXAGON_V6_vadduwsat_dv">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vadduwsat_dv_128B,VD_ftype_VDVD,2)
+// tag : V6_vadduwsat_dv_128B
+def int_hexagon_V6_vadduwsat_dv_128B :
+Hexagon_V62_v2048v2048v2048_Intrinsic<"HEXAGON_V6_vadduwsat_dv_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vsubuwsat,VI_ftype_VIVI,2)
+// tag : V6_vsubuwsat
+def int_hexagon_V6_vsubuwsat :
+Hexagon_V62_v512v512v512_Intrinsic<"HEXAGON_V6_vsubuwsat">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vsubuwsat_128B,VI_ftype_VIVI,2)
+// tag : V6_vsubuwsat_128B
+def int_hexagon_V6_vsubuwsat_128B :
+Hexagon_V62_v1024v1024v1024_Intrinsic<"HEXAGON_V6_vsubuwsat_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vsubuwsat_dv,VD_ftype_VDVD,2)
+// tag : V6_vsubuwsat_dv
+def int_hexagon_V6_vsubuwsat_dv :
+Hexagon_V62_v1024v1024v1024_Intrinsic<"HEXAGON_V6_vsubuwsat_dv">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vsubuwsat_dv_128B,VD_ftype_VDVD,2)
+// tag : V6_vsubuwsat_dv_128B
+def int_hexagon_V6_vsubuwsat_dv_128B :
+Hexagon_V62_v2048v2048v2048_Intrinsic<"HEXAGON_V6_vsubuwsat_dv_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vaddbsat,VI_ftype_VIVI,2)
+// tag : V6_vaddbsat
+def int_hexagon_V6_vaddbsat :
+Hexagon_V62_v512v512v512_Intrinsic<"HEXAGON_V6_vaddbsat">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vaddbsat_128B,VI_ftype_VIVI,2)
+// tag : V6_vaddbsat_128B
+def int_hexagon_V6_vaddbsat_128B :
+Hexagon_V62_v1024v1024v1024_Intrinsic<"HEXAGON_V6_vaddbsat_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vaddbsat_dv,VD_ftype_VDVD,2)
+// tag : V6_vaddbsat_dv
+def int_hexagon_V6_vaddbsat_dv :
+Hexagon_V62_v1024v1024v1024_Intrinsic<"HEXAGON_V6_vaddbsat_dv">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vaddbsat_dv_128B,VD_ftype_VDVD,2)
+// tag : V6_vaddbsat_dv_128B
+def int_hexagon_V6_vaddbsat_dv_128B :
+Hexagon_V62_v2048v2048v2048_Intrinsic<"HEXAGON_V6_vaddbsat_dv_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vsubbsat,VI_ftype_VIVI,2)
+// tag : V6_vsubbsat
+def int_hexagon_V6_vsubbsat :
+Hexagon_V62_v512v512v512_Intrinsic<"HEXAGON_V6_vsubbsat">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vsubbsat_128B,VI_ftype_VIVI,2)
+// tag : V6_vsubbsat_128B
+def int_hexagon_V6_vsubbsat_128B :
+Hexagon_V62_v1024v1024v1024_Intrinsic<"HEXAGON_V6_vsubbsat_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vsubbsat_dv,VD_ftype_VDVD,2)
+// tag : V6_vsubbsat_dv
+def int_hexagon_V6_vsubbsat_dv :
+Hexagon_V62_v1024v1024v1024_Intrinsic<"HEXAGON_V6_vsubbsat_dv">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vsubbsat_dv_128B,VD_ftype_VDVD,2)
+// tag : V6_vsubbsat_dv_128B
+def int_hexagon_V6_vsubbsat_dv_128B :
+Hexagon_V62_v2048v2048v2048_Intrinsic<"HEXAGON_V6_vsubbsat_dv_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vaddububb_sat,VI_ftype_VIVI,2)
+// tag : V6_vaddububb_sat
+def int_hexagon_V6_vaddububb_sat :
+Hexagon_V62_v512v512v512_Intrinsic<"HEXAGON_V6_vaddububb_sat">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vaddububb_sat_128B,VI_ftype_VIVI,2)
+// tag : V6_vaddububb_sat_128B
+def int_hexagon_V6_vaddububb_sat_128B :
+Hexagon_V62_v1024v1024v1024_Intrinsic<"HEXAGON_V6_vaddububb_sat_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vsubububb_sat,VI_ftype_VIVI,2)
+// tag : V6_vsubububb_sat
+def int_hexagon_V6_vsubububb_sat :
+Hexagon_V62_v512v512v512_Intrinsic<"HEXAGON_V6_vsubububb_sat">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vsubububb_sat_128B,VI_ftype_VIVI,2)
+// tag : V6_vsubububb_sat_128B
+def int_hexagon_V6_vsubububb_sat_128B :
+Hexagon_V62_v1024v1024v1024_Intrinsic<"HEXAGON_V6_vsubububb_sat_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vaddhw_acc,VD_ftype_VDVIVI,3)
+// tag : V6_vaddhw_acc
+def int_hexagon_V6_vaddhw_acc :
+Hexagon_V62_v1024v1024v512v512_Intrinsic<"HEXAGON_V6_vaddhw_acc">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vaddhw_acc_128B,VD_ftype_VDVIVI,3)
+// tag : V6_vaddhw_acc_128B
+def int_hexagon_V6_vaddhw_acc_128B :
+Hexagon_V62_v2048v2048v1024v1024_Intrinsic<"HEXAGON_V6_vaddhw_acc_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vadduhw_acc,VD_ftype_VDVIVI,3)
+// tag : V6_vadduhw_acc
+def int_hexagon_V6_vadduhw_acc :
+Hexagon_V62_v1024v1024v512v512_Intrinsic<"HEXAGON_V6_vadduhw_acc">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vadduhw_acc_128B,VD_ftype_VDVIVI,3)
+// tag : V6_vadduhw_acc_128B
+def int_hexagon_V6_vadduhw_acc_128B :
+Hexagon_V62_v2048v2048v1024v1024_Intrinsic<"HEXAGON_V6_vadduhw_acc_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vaddubh_acc,VD_ftype_VDVIVI,3)
+// tag : V6_vaddubh_acc
+def int_hexagon_V6_vaddubh_acc :
+Hexagon_V62_v1024v1024v512v512_Intrinsic<"HEXAGON_V6_vaddubh_acc">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vaddubh_acc_128B,VD_ftype_VDVIVI,3)
+// tag : V6_vaddubh_acc_128B
+def int_hexagon_V6_vaddubh_acc_128B :
+Hexagon_V62_v2048v2048v1024v1024_Intrinsic<"HEXAGON_V6_vaddubh_acc_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vmpyewuh_64,VD_ftype_VIVI,2)
+// tag : V6_vmpyewuh_64
+def int_hexagon_V6_vmpyewuh_64 :
+Hexagon_V62_v1024v512v512_Intrinsic<"HEXAGON_V6_vmpyewuh_64">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vmpyewuh_64_128B,VD_ftype_VIVI,2)
+// tag : V6_vmpyewuh_64_128B
+def int_hexagon_V6_vmpyewuh_64_128B :
+Hexagon_V62_v2048v1024v1024_Intrinsic<"HEXAGON_V6_vmpyewuh_64_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vmpyowh_64_acc,VD_ftype_VDVIVI,3)
+// tag : V6_vmpyowh_64_acc
+def int_hexagon_V6_vmpyowh_64_acc :
+Hexagon_V62_v1024v1024v512v512_Intrinsic<"HEXAGON_V6_vmpyowh_64_acc">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vmpyowh_64_acc_128B,VD_ftype_VDVIVI,3)
+// tag : V6_vmpyowh_64_acc_128B
+def int_hexagon_V6_vmpyowh_64_acc_128B :
+Hexagon_V62_v2048v2048v1024v1024_Intrinsic<"HEXAGON_V6_vmpyowh_64_acc_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vmpauhb,VD_ftype_VDSI,2)
+// tag : V6_vmpauhb
+def int_hexagon_V6_vmpauhb :
+Hexagon_V62_v1024v1024i_Intrinsic<"HEXAGON_V6_vmpauhb">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vmpauhb_128B,VD_ftype_VDSI,2)
+// tag : V6_vmpauhb_128B
+def int_hexagon_V6_vmpauhb_128B :
+Hexagon_V62_v2048v2048i_Intrinsic<"HEXAGON_V6_vmpauhb_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vmpauhb_acc,VD_ftype_VDVDSI,3)
+// tag : V6_vmpauhb_acc
+def int_hexagon_V6_vmpauhb_acc :
+Hexagon_V62_v1024v1024v1024i_Intrinsic<"HEXAGON_V6_vmpauhb_acc">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vmpauhb_acc_128B,VD_ftype_VDVDSI,3)
+// tag : V6_vmpauhb_acc_128B
+def int_hexagon_V6_vmpauhb_acc_128B :
+Hexagon_V62_v2048v2048v2048i_Intrinsic<"HEXAGON_V6_vmpauhb_acc_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vmpyiwub,VI_ftype_VISI,2)
+// tag : V6_vmpyiwub
+def int_hexagon_V6_vmpyiwub :
+Hexagon_V62_v512v512i_Intrinsic<"HEXAGON_V6_vmpyiwub">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vmpyiwub_128B,VI_ftype_VISI,2)
+// tag : V6_vmpyiwub_128B
+def int_hexagon_V6_vmpyiwub_128B :
+Hexagon_V62_v1024v1024i_Intrinsic<"HEXAGON_V6_vmpyiwub_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vmpyiwub_acc,VI_ftype_VIVISI,3)
+// tag : V6_vmpyiwub_acc
+def int_hexagon_V6_vmpyiwub_acc :
+Hexagon_V62_v512v512v512i_Intrinsic<"HEXAGON_V6_vmpyiwub_acc">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vmpyiwub_acc_128B,VI_ftype_VIVISI,3)
+// tag : V6_vmpyiwub_acc_128B
+def int_hexagon_V6_vmpyiwub_acc_128B :
+Hexagon_V62_v1024v1024v1024i_Intrinsic<"HEXAGON_V6_vmpyiwub_acc_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vandnqrt,VI_ftype_QVSI,2)
+// tag : V6_vandnqrt
+def int_hexagon_V6_vandnqrt :
+Hexagon_V62_v512v64ii_Intrinsic<"HEXAGON_V6_vandnqrt">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vandnqrt_128B,VI_ftype_QVSI,2)
+// tag : V6_vandnqrt_128B
+def int_hexagon_V6_vandnqrt_128B :
+Hexagon_V62_v1024v128ii_Intrinsic<"HEXAGON_V6_vandnqrt_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vandnqrt_acc,VI_ftype_VIQVSI,3)
+// tag : V6_vandnqrt_acc
+def int_hexagon_V6_vandnqrt_acc :
+Hexagon_V62_v512v512v64ii_Intrinsic<"HEXAGON_V6_vandnqrt_acc">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vandnqrt_acc_128B,VI_ftype_VIQVSI,3)
+// tag : V6_vandnqrt_acc_128B
+def int_hexagon_V6_vandnqrt_acc_128B :
+Hexagon_V62_v1024v1024v128ii_Intrinsic<"HEXAGON_V6_vandnqrt_acc_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vandvqv,VI_ftype_QVVI,2)
+// tag : V6_vandvqv
+def int_hexagon_V6_vandvqv :
+Hexagon_V62_v512v64iv512_Intrinsic<"HEXAGON_V6_vandvqv">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vandvqv_128B,VI_ftype_QVVI,2)
+// tag : V6_vandvqv_128B
+def int_hexagon_V6_vandvqv_128B :
+Hexagon_V62_v1024v128iv1024_Intrinsic<"HEXAGON_V6_vandvqv_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vandvnqv,VI_ftype_QVVI,2)
+// tag : V6_vandvnqv
+def int_hexagon_V6_vandvnqv :
+Hexagon_V62_v512v64iv512_Intrinsic<"HEXAGON_V6_vandvnqv">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vandvnqv_128B,VI_ftype_QVVI,2)
+// tag : V6_vandvnqv_128B
+def int_hexagon_V6_vandvnqv_128B :
+Hexagon_V62_v1024v128iv1024_Intrinsic<"HEXAGON_V6_vandvnqv_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_pred_scalar2v2,QV_ftype_SI,1)
+// tag : V6_pred_scalar2v2
+def int_hexagon_V6_pred_scalar2v2 :
+Hexagon_V62_v64ii_Intrinsic<"HEXAGON_V6_pred_scalar2v2">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_pred_scalar2v2_128B,QV_ftype_SI,1)
+// tag : V6_pred_scalar2v2_128B
+def int_hexagon_V6_pred_scalar2v2_128B :
+Hexagon_V62_v128ii_Intrinsic<"HEXAGON_V6_pred_scalar2v2_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_shuffeqw,QV_ftype_QVQV,2)
+// tag : V6_shuffeqw
+def int_hexagon_V6_shuffeqw :
+Hexagon_V62_v64iv64iv64i_Intrinsic<"HEXAGON_V6_shuffeqw">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_shuffeqw_128B,QV_ftype_QVQV,2)
+// tag : V6_shuffeqw_128B
+def int_hexagon_V6_shuffeqw_128B :
+Hexagon_V62_v128iv128iv128i_Intrinsic<"HEXAGON_V6_shuffeqw_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_shuffeqh,QV_ftype_QVQV,2)
+// tag : V6_shuffeqh
+def int_hexagon_V6_shuffeqh :
+Hexagon_V62_v64iv64iv64i_Intrinsic<"HEXAGON_V6_shuffeqh">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_shuffeqh_128B,QV_ftype_QVQV,2)
+// tag : V6_shuffeqh_128B
+def int_hexagon_V6_shuffeqh_128B :
+Hexagon_V62_v128iv128iv128i_Intrinsic<"HEXAGON_V6_shuffeqh_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vmaxb,VI_ftype_VIVI,2)
+// tag : V6_vmaxb
+def int_hexagon_V6_vmaxb :
+Hexagon_V62_v512v512v512_Intrinsic<"HEXAGON_V6_vmaxb">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vmaxb_128B,VI_ftype_VIVI,2)
+// tag : V6_vmaxb_128B
+def int_hexagon_V6_vmaxb_128B :
+Hexagon_V62_v1024v1024v1024_Intrinsic<"HEXAGON_V6_vmaxb_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vminb,VI_ftype_VIVI,2)
+// tag : V6_vminb
+def int_hexagon_V6_vminb :
+Hexagon_V62_v512v512v512_Intrinsic<"HEXAGON_V6_vminb">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vminb_128B,VI_ftype_VIVI,2)
+// tag : V6_vminb_128B
+def int_hexagon_V6_vminb_128B :
+Hexagon_V62_v1024v1024v1024_Intrinsic<"HEXAGON_V6_vminb_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vsatuwuh,VI_ftype_VIVI,2)
+// tag : V6_vsatuwuh
+def int_hexagon_V6_vsatuwuh :
+Hexagon_V62_v512v512v512_Intrinsic<"HEXAGON_V6_vsatuwuh">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vsatuwuh_128B,VI_ftype_VIVI,2)
+// tag : V6_vsatuwuh_128B
+def int_hexagon_V6_vsatuwuh_128B :
+Hexagon_V62_v1024v1024v1024_Intrinsic<"HEXAGON_V6_vsatuwuh_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_lvsplath,VI_ftype_SI,1)
+// tag : V6_lvsplath
+def int_hexagon_V6_lvsplath :
+Hexagon_V62_v512i_Intrinsic<"HEXAGON_V6_lvsplath">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_lvsplath_128B,VI_ftype_SI,1)
+// tag : V6_lvsplath_128B
+def int_hexagon_V6_lvsplath_128B :
+Hexagon_V62_v1024i_Intrinsic<"HEXAGON_V6_lvsplath_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_lvsplatb,VI_ftype_SI,1)
+// tag : V6_lvsplatb
+def int_hexagon_V6_lvsplatb :
+Hexagon_V62_v512i_Intrinsic<"HEXAGON_V6_lvsplatb">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_lvsplatb_128B,VI_ftype_SI,1)
+// tag : V6_lvsplatb_128B
+def int_hexagon_V6_lvsplatb_128B :
+Hexagon_V62_v1024i_Intrinsic<"HEXAGON_V6_lvsplatb_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vaddclbw,VI_ftype_VIVI,2)
+// tag : V6_vaddclbw
+def int_hexagon_V6_vaddclbw :
+Hexagon_V62_v512v512v512_Intrinsic<"HEXAGON_V6_vaddclbw">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vaddclbw_128B,VI_ftype_VIVI,2)
+// tag : V6_vaddclbw_128B
+def int_hexagon_V6_vaddclbw_128B :
+Hexagon_V62_v1024v1024v1024_Intrinsic<"HEXAGON_V6_vaddclbw_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vaddclbh,VI_ftype_VIVI,2)
+// tag : V6_vaddclbh
+def int_hexagon_V6_vaddclbh :
+Hexagon_V62_v512v512v512_Intrinsic<"HEXAGON_V6_vaddclbh">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vaddclbh_128B,VI_ftype_VIVI,2)
+// tag : V6_vaddclbh_128B
+def int_hexagon_V6_vaddclbh_128B :
+Hexagon_V62_v1024v1024v1024_Intrinsic<"HEXAGON_V6_vaddclbh_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vlutvvbi,VI_ftype_VIVISI,3)
+// tag : V6_vlutvvbi
+def int_hexagon_V6_vlutvvbi :
+Hexagon_V62_v512v512v512i_Intrinsic<"HEXAGON_V6_vlutvvbi">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vlutvvbi_128B,VI_ftype_VIVISI,3)
+// tag : V6_vlutvvbi_128B
+def int_hexagon_V6_vlutvvbi_128B :
+Hexagon_V62_v1024v1024v1024i_Intrinsic<"HEXAGON_V6_vlutvvbi_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vlutvvb_oracci,VI_ftype_VIVIVISI,4)
+// tag : V6_vlutvvb_oracci
+def int_hexagon_V6_vlutvvb_oracci :
+Hexagon_V62_v512v512v512v512i_Intrinsic<"HEXAGON_V6_vlutvvb_oracci">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vlutvvb_oracci_128B,VI_ftype_VIVIVISI,4)
+// tag : V6_vlutvvb_oracci_128B
+def int_hexagon_V6_vlutvvb_oracci_128B :
+Hexagon_V62_v1024v1024v1024v1024i_Intrinsic<"HEXAGON_V6_vlutvvb_oracci_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vlutvwhi,VD_ftype_VIVISI,3)
+// tag : V6_vlutvwhi
+def int_hexagon_V6_vlutvwhi :
+Hexagon_V62_v1024v512v512i_Intrinsic<"HEXAGON_V6_vlutvwhi">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vlutvwhi_128B,VD_ftype_VIVISI,3)
+// tag : V6_vlutvwhi_128B
+def int_hexagon_V6_vlutvwhi_128B :
+Hexagon_V62_v2048v1024v1024i_Intrinsic<"HEXAGON_V6_vlutvwhi_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vlutvwh_oracci,VD_ftype_VDVIVISI,4)
+// tag : V6_vlutvwh_oracci
+def int_hexagon_V6_vlutvwh_oracci :
+Hexagon_V62_v1024v1024v512v512i_Intrinsic<"HEXAGON_V6_vlutvwh_oracci">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vlutvwh_oracci_128B,VD_ftype_VDVIVISI,4)
+// tag : V6_vlutvwh_oracci_128B
+def int_hexagon_V6_vlutvwh_oracci_128B :
+Hexagon_V62_v2048v2048v1024v1024i_Intrinsic<"HEXAGON_V6_vlutvwh_oracci_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vlutvvb_nm,VI_ftype_VIVISI,3)
+// tag : V6_vlutvvb_nm
+def int_hexagon_V6_vlutvvb_nm :
+Hexagon_V62_v512v512v512i_Intrinsic<"HEXAGON_V6_vlutvvb_nm">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vlutvvb_nm_128B,VI_ftype_VIVISI,3)
+// tag : V6_vlutvvb_nm_128B
+def int_hexagon_V6_vlutvvb_nm_128B :
+Hexagon_V62_v1024v1024v1024i_Intrinsic<"HEXAGON_V6_vlutvvb_nm_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vlutvwh_nm,VD_ftype_VIVISI,3)
+// tag : V6_vlutvwh_nm
+def int_hexagon_V6_vlutvwh_nm :
+Hexagon_V62_v1024v512v512i_Intrinsic<"HEXAGON_V6_vlutvwh_nm">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vlutvwh_nm_128B,VD_ftype_VIVISI,3)
+// tag : V6_vlutvwh_nm_128B
+def int_hexagon_V6_vlutvwh_nm_128B :
+Hexagon_V62_v2048v1024v1024i_Intrinsic<"HEXAGON_V6_vlutvwh_nm_128B">;
+
diff --git a/include/llvm/IR/IntrinsicsNVVM.td b/include/llvm/IR/IntrinsicsNVVM.td
index f035ac3c90ee..68f123df0430 100644
--- a/include/llvm/IR/IntrinsicsNVVM.td
+++ b/include/llvm/IR/IntrinsicsNVVM.td
@@ -11,6 +11,27 @@
//
//===----------------------------------------------------------------------===//
+// The following intrinsics were once defined here, but are now auto-upgraded
+// to target-generic LLVM intrinsics.
+//
+// * llvm.nvvm.brev32 --> llvm.bitreverse.i32
+// * llvm.nvvm.brev64 --> llvm.bitreverse.i64
+// * llvm.nvvm.clz.i --> llvm.ctlz.i32
+// * llvm.nvvm.clz.ll --> trunc i64 llvm.ctlz.i64(x) to i32
+// * llvm.nvvm.popc.i --> llvm.ctpop.i32
+// * llvm.nvvm.popc.ll --> trunc i64 llvm.ctpop.i64 to i32
+// * llvm.nvvm.abs.i --> select(x >= -x, x, -x)
+// * llvm.nvvm.abs.ll --> ibid.
+// * llvm.nvvm.max.i --> select(x sge y, x, y)
+// * llvm.nvvm.max.ll --> ibid.
+// * llvm.nvvm.max.ui --> select(x uge y, x, y)
+// * llvm.nvvm.max.ull --> ibid.
+// * llvm.nvvm.max.i --> select(x sle y, x, y)
+// * llvm.nvvm.max.ll --> ibid.
+// * llvm.nvvm.max.ui --> select(x ule y, x, y)
+// * llvm.nvvm.max.ull --> ibid.
+// * llvm.nvvm.h2f --> llvm.convert.to.fp16.f32
+
def llvm_anyi64ptr_ty : LLVMAnyPointerType<llvm_i64_ty>; // (space)i64*
//
@@ -18,16 +39,6 @@ def llvm_anyi64ptr_ty : LLVMAnyPointerType<llvm_i64_ty>; // (space)i64*
//
let TargetPrefix = "nvvm" in {
- def int_nvvm_clz_i : GCCBuiltin<"__nvvm_clz_i">,
- Intrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrNoMem]>;
- def int_nvvm_clz_ll : GCCBuiltin<"__nvvm_clz_ll">,
- Intrinsic<[llvm_i32_ty], [llvm_i64_ty], [IntrNoMem]>;
-
- def int_nvvm_popc_i : GCCBuiltin<"__nvvm_popc_i">,
- Intrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrNoMem]>;
- def int_nvvm_popc_ll : GCCBuiltin<"__nvvm_popc_ll">,
- Intrinsic<[llvm_i32_ty], [llvm_i64_ty], [IntrNoMem]>;
-
def int_nvvm_prmt : GCCBuiltin<"__nvvm_prmt">,
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty],
[IntrNoMem, Commutative]>;
@@ -36,34 +47,6 @@ let TargetPrefix = "nvvm" in {
// Min Max
//
- def int_nvvm_min_i : GCCBuiltin<"__nvvm_min_i">,
- Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty],
- [IntrNoMem, Commutative]>;
- def int_nvvm_min_ui : GCCBuiltin<"__nvvm_min_ui">,
- Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty],
- [IntrNoMem, Commutative]>;
-
- def int_nvvm_min_ll : GCCBuiltin<"__nvvm_min_ll">,
- Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty],
- [IntrNoMem, Commutative]>;
- def int_nvvm_min_ull : GCCBuiltin<"__nvvm_min_ull">,
- Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty],
- [IntrNoMem, Commutative]>;
-
- def int_nvvm_max_i : GCCBuiltin<"__nvvm_max_i">,
- Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty],
- [IntrNoMem, Commutative]>;
- def int_nvvm_max_ui : GCCBuiltin<"__nvvm_max_ui">,
- Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty],
- [IntrNoMem, Commutative]>;
-
- def int_nvvm_max_ll : GCCBuiltin<"__nvvm_max_ll">,
- Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty],
- [IntrNoMem, Commutative]>;
- def int_nvvm_max_ull : GCCBuiltin<"__nvvm_max_ull">,
- Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty],
- [IntrNoMem, Commutative]>;
-
def int_nvvm_fmin_f : GCCBuiltin<"__nvvm_fmin_f">,
Intrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty],
[IntrNoMem, Commutative]>;
@@ -201,15 +184,6 @@ let TargetPrefix = "nvvm" in {
[IntrNoMem, Commutative]>;
//
-// Brev
-//
-
- def int_nvvm_brev32 : GCCBuiltin<"__nvvm_brev32">,
- Intrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrNoMem]>;
- def int_nvvm_brev64 : GCCBuiltin<"__nvvm_brev64">,
- Intrinsic<[llvm_i64_ty], [llvm_i64_ty], [IntrNoMem]>;
-
-//
// Sad
//
@@ -242,16 +216,10 @@ let TargetPrefix = "nvvm" in {
// Abs
//
- def int_nvvm_abs_i : GCCBuiltin<"__nvvm_abs_i">,
- Intrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrNoMem]>;
- def int_nvvm_abs_ll : GCCBuiltin<"__nvvm_abs_ll">,
- Intrinsic<[llvm_i64_ty], [llvm_i64_ty], [IntrNoMem]>;
-
def int_nvvm_fabs_ftz_f : GCCBuiltin<"__nvvm_fabs_ftz_f">,
Intrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>;
def int_nvvm_fabs_f : GCCBuiltin<"__nvvm_fabs_f">,
Intrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>;
-
def int_nvvm_fabs_d : GCCBuiltin<"__nvvm_fabs_d">,
Intrinsic<[llvm_double_ty], [llvm_double_ty], [IntrNoMem]>;
@@ -700,9 +668,6 @@ let TargetPrefix = "nvvm" in {
def int_nvvm_f2h_rn : GCCBuiltin<"__nvvm_f2h_rn">,
Intrinsic<[llvm_i16_ty], [llvm_float_ty], [IntrNoMem]>;
- def int_nvvm_h2f : GCCBuiltin<"__nvvm_h2f">,
- Intrinsic<[llvm_float_ty], [llvm_i16_ty], [IntrNoMem]>;
-
//
// Bitcast
//
@@ -768,6 +733,13 @@ let TargetPrefix = "nvvm" in {
// intrinsics in this file, this one is a user-facing API.
def int_nvvm_barrier0 : GCCBuiltin<"__syncthreads">,
Intrinsic<[], [], [IntrConvergent]>;
+ // Synchronize all threads in the CTA at barrier 'n'.
+ def int_nvvm_barrier_n : GCCBuiltin<"__nvvm_bar_n">,
+ Intrinsic<[], [llvm_i32_ty], [IntrConvergent]>;
+ // Synchronize 'm', a multiple of warp size, (arg 2) threads in
+ // the CTA at barrier 'n' (arg 1).
+ def int_nvvm_barrier : GCCBuiltin<"__nvvm_bar">,
+ Intrinsic<[], [llvm_i32_ty, llvm_i32_ty], [IntrConvergent]>;
def int_nvvm_barrier0_popc : GCCBuiltin<"__nvvm_bar0_popc">,
Intrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrConvergent]>;
def int_nvvm_barrier0_and : GCCBuiltin<"__nvvm_bar0_and">,
diff --git a/include/llvm/IR/IntrinsicsPowerPC.td b/include/llvm/IR/IntrinsicsPowerPC.td
index 12e23b681ca4..64240a929782 100644
--- a/include/llvm/IR/IntrinsicsPowerPC.td
+++ b/include/llvm/IR/IntrinsicsPowerPC.td
@@ -203,19 +203,19 @@ let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.".
// source address with a single pointer.
def int_ppc_altivec_stvx :
Intrinsic<[], [llvm_v4i32_ty, llvm_ptr_ty],
- [IntrArgMemOnly]>;
+ [IntrWriteMem, IntrArgMemOnly]>;
def int_ppc_altivec_stvxl :
Intrinsic<[], [llvm_v4i32_ty, llvm_ptr_ty],
- [IntrArgMemOnly]>;
+ [IntrWriteMem, IntrArgMemOnly]>;
def int_ppc_altivec_stvebx :
Intrinsic<[], [llvm_v16i8_ty, llvm_ptr_ty],
- [IntrArgMemOnly]>;
+ [IntrWriteMem, IntrArgMemOnly]>;
def int_ppc_altivec_stvehx :
Intrinsic<[], [llvm_v8i16_ty, llvm_ptr_ty],
- [IntrArgMemOnly]>;
+ [IntrWriteMem, IntrArgMemOnly]>;
def int_ppc_altivec_stvewx :
Intrinsic<[], [llvm_v4i32_ty, llvm_ptr_ty],
- [IntrArgMemOnly]>;
+ [IntrWriteMem, IntrArgMemOnly]>;
// Comparisons setting a vector.
def int_ppc_altivec_vcmpbfp : GCCBuiltin<"__builtin_altivec_vcmpbfp">,
@@ -749,20 +749,20 @@ def int_ppc_vsx_lxvll :
IntrArgMemOnly]>;
def int_ppc_vsx_stxvl :
Intrinsic<[], [llvm_v4i32_ty, llvm_ptr_ty, llvm_i64_ty],
- [IntrArgMemOnly]>;
+ [IntrWriteMem, IntrArgMemOnly]>;
def int_ppc_vsx_stxvll :
Intrinsic<[], [llvm_v4i32_ty, llvm_ptr_ty, llvm_i64_ty],
- [IntrArgMemOnly]>;
+ [IntrWriteMem, IntrArgMemOnly]>;
// Vector store.
-def int_ppc_vsx_stxvw4x :
- Intrinsic<[], [llvm_v4i32_ty, llvm_ptr_ty], [IntrArgMemOnly]>;
-def int_ppc_vsx_stxvd2x :
- Intrinsic<[], [llvm_v2f64_ty, llvm_ptr_ty], [IntrArgMemOnly]>;
-def int_ppc_vsx_stxvw4x_be :
- Intrinsic<[], [llvm_v4i32_ty, llvm_ptr_ty], [IntrArgMemOnly]>;
-def int_ppc_vsx_stxvd2x_be :
- Intrinsic<[], [llvm_v2f64_ty, llvm_ptr_ty], [IntrArgMemOnly]>;
+def int_ppc_vsx_stxvw4x : Intrinsic<[], [llvm_v4i32_ty, llvm_ptr_ty],
+ [IntrWriteMem, IntrArgMemOnly]>;
+def int_ppc_vsx_stxvd2x : Intrinsic<[], [llvm_v2f64_ty, llvm_ptr_ty],
+ [IntrWriteMem, IntrArgMemOnly]>;
+def int_ppc_vsx_stxvw4x_be : Intrinsic<[], [llvm_v4i32_ty, llvm_ptr_ty],
+ [IntrWriteMem, IntrArgMemOnly]>;
+def int_ppc_vsx_stxvd2x_be : Intrinsic<[], [llvm_v2f64_ty, llvm_ptr_ty],
+ [IntrWriteMem, IntrArgMemOnly]>;
// Vector and scalar maximum.
def int_ppc_vsx_xvmaxdp : PowerPC_VSX_Vec_DDD_Intrinsic<"xvmaxdp">;
def int_ppc_vsx_xvmaxsp : PowerPC_VSX_Vec_FFF_Intrinsic<"xvmaxsp">;
@@ -953,7 +953,7 @@ class PowerPC_QPX_LoadPerm_Intrinsic<string GCCIntSuffix>
class PowerPC_QPX_Store_Intrinsic<string GCCIntSuffix>
: PowerPC_QPX_Intrinsic<GCCIntSuffix,
[], [llvm_v4f64_ty, llvm_ptr_ty],
- [IntrArgMemOnly]>;
+ [IntrWriteMem, IntrArgMemOnly]>;
//===----------------------------------------------------------------------===//
// PowerPC QPX Intrinsic Definitions.
diff --git a/include/llvm/IR/IntrinsicsWebAssembly.td b/include/llvm/IR/IntrinsicsWebAssembly.td
index 4234c466d973..3a0957dfa39b 100644
--- a/include/llvm/IR/IntrinsicsWebAssembly.td
+++ b/include/llvm/IR/IntrinsicsWebAssembly.td
@@ -17,6 +17,6 @@ let TargetPrefix = "wasm" in { // All intrinsics start with "llvm.wasm.".
// Note that current_memory is not IntrNoMem because it must be sequenced with
// respect to grow_memory calls.
def int_wasm_current_memory : Intrinsic<[llvm_anyint_ty], [], [IntrReadMem]>;
-def int_wasm_grow_memory : Intrinsic<[], [llvm_anyint_ty], []>;
+def int_wasm_grow_memory : Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>], []>;
}
diff --git a/include/llvm/IR/IntrinsicsX86.td b/include/llvm/IR/IntrinsicsX86.td
index 85966af9c820..97c756cf4b60 100644
--- a/include/llvm/IR/IntrinsicsX86.td
+++ b/include/llvm/IR/IntrinsicsX86.td
@@ -785,12 +785,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
[IntrNoMem, Commutative]>;
}
-// Cacheability support ops
-let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
- def int_x86_sse41_movntdqa : GCCBuiltin<"__builtin_ia32_movntdqa">,
- Intrinsic<[llvm_v2i64_ty], [llvm_ptr_ty], [IntrReadMem]>;
-}
-
// Test instruction with bitwise comparison.
let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
def int_x86_sse41_ptestz : GCCBuiltin<"__builtin_ia32_ptestz128">,
@@ -2346,8 +2340,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
def int_x86_avx2_mpsadbw : GCCBuiltin<"__builtin_ia32_mpsadbw256">,
Intrinsic<[llvm_v16i16_ty], [llvm_v32i8_ty, llvm_v32i8_ty,
llvm_i8_ty], [IntrNoMem, Commutative]>;
- def int_x86_avx2_movntdqa : GCCBuiltin<"__builtin_ia32_movntdqa256">,
- Intrinsic<[llvm_v4i64_ty], [llvm_ptr_ty], [IntrReadMem]>;
}
//===----------------------------------------------------------------------===//
@@ -3033,17 +3025,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
def int_x86_xop_vfrcz_ps_256 : GCCBuiltin<"__builtin_ia32_vfrczps256">,
Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty], [IntrNoMem]>;
- def int_x86_xop_vpcmov :
- GCCBuiltin<"__builtin_ia32_vpcmov">,
- Intrinsic<[llvm_v2i64_ty],
- [llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty],
- [IntrNoMem]>;
- def int_x86_xop_vpcmov_256 :
- GCCBuiltin<"__builtin_ia32_vpcmov_256">,
- Intrinsic<[llvm_v4i64_ty],
- [llvm_v4i64_ty, llvm_v4i64_ty, llvm_v4i64_ty],
- [IntrNoMem]>;
-
def int_x86_xop_vpcomb : GCCBuiltin<"__builtin_ia32_vpcomb">,
Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty,
llvm_i8_ty], [IntrNoMem]>;
@@ -3881,74 +3862,22 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
def int_x86_avx512_cvtq2mask_512 : GCCBuiltin<"__builtin_ia32_cvtq2mask512">,
Intrinsic<[llvm_i8_ty], [llvm_v8i64_ty], [IntrNoMem]>;
- def int_x86_avx512_cvtmask2b_128 : GCCBuiltin<"__builtin_ia32_cvtmask2b128">,
- Intrinsic<[llvm_v16i8_ty], [llvm_i16_ty], [IntrNoMem]>;
- def int_x86_avx512_cvtmask2b_256 : GCCBuiltin<"__builtin_ia32_cvtmask2b256">,
- Intrinsic<[llvm_v32i8_ty], [llvm_i32_ty], [IntrNoMem]>;
- def int_x86_avx512_cvtmask2b_512 : GCCBuiltin<"__builtin_ia32_cvtmask2b512">,
- Intrinsic<[llvm_v64i8_ty], [llvm_i64_ty], [IntrNoMem]>;
-
- def int_x86_avx512_cvtmask2w_128 : GCCBuiltin<"__builtin_ia32_cvtmask2w128">,
- Intrinsic<[llvm_v8i16_ty], [llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_cvtmask2w_256 : GCCBuiltin<"__builtin_ia32_cvtmask2w256">,
- Intrinsic<[llvm_v16i16_ty], [llvm_i16_ty], [IntrNoMem]>;
- def int_x86_avx512_cvtmask2w_512 : GCCBuiltin<"__builtin_ia32_cvtmask2w512">,
- Intrinsic<[llvm_v32i16_ty], [llvm_i32_ty], [IntrNoMem]>;
-
- def int_x86_avx512_cvtmask2d_128 : GCCBuiltin<"__builtin_ia32_cvtmask2d128">,
- Intrinsic<[llvm_v4i32_ty], [llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_cvtmask2d_256 : GCCBuiltin<"__builtin_ia32_cvtmask2d256">,
- Intrinsic<[llvm_v8i32_ty], [llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_cvtmask2d_512 : GCCBuiltin<"__builtin_ia32_cvtmask2d512">,
- Intrinsic<[llvm_v16i32_ty], [llvm_i16_ty], [IntrNoMem]>;
-
- def int_x86_avx512_cvtmask2q_128 : GCCBuiltin<"__builtin_ia32_cvtmask2q128">,
- Intrinsic<[llvm_v2i64_ty], [llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_cvtmask2q_256 : GCCBuiltin<"__builtin_ia32_cvtmask2q256">,
- Intrinsic<[llvm_v4i64_ty], [llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_cvtmask2q_512 : GCCBuiltin<"__builtin_ia32_cvtmask2q512">,
- Intrinsic<[llvm_v8i64_ty], [llvm_i8_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]>;
+ def int_x86_avx512_packsswb_512 : GCCBuiltin<"__builtin_ia32_packsswb512">,
+ Intrinsic<[llvm_v64i8_ty], [llvm_v32i16_ty,llvm_v32i16_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_packssdw_512 : GCCBuiltin<"__builtin_ia32_packssdw512">,
+ Intrinsic<[llvm_v32i16_ty], [llvm_v16i32_ty, llvm_v16i32_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_packuswb_512 : GCCBuiltin<"__builtin_ia32_packuswb512">,
+ Intrinsic<[llvm_v64i8_ty], [llvm_v32i16_ty,llvm_v32i16_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_packusdw_512 : GCCBuiltin<"__builtin_ia32_packusdw512">,
+ Intrinsic<[llvm_v32i16_ty], [llvm_v16i32_ty, llvm_v16i32_ty],
+ [IntrNoMem]>;
}
// Vector convert
@@ -4595,39 +4524,15 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
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]>;
@@ -5481,32 +5386,6 @@ let TargetPrefix = "x86" in {
Intrinsic<[llvm_v8i64_ty],
[llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty],
[IntrNoMem]>;
-
- def int_x86_avx512_mask_lzcnt_d_128 :
- Intrinsic<[llvm_v4i32_ty],
- [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i8_ty],
- [IntrNoMem]>;
- def int_x86_avx512_mask_lzcnt_d_256 :
- Intrinsic<[llvm_v8i32_ty],
- [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i8_ty],
- [IntrNoMem]>;
- def int_x86_avx512_mask_lzcnt_d_512 :
- Intrinsic<[llvm_v16i32_ty],
- [llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_lzcnt_q_128 :
- Intrinsic<[llvm_v2i64_ty],
- [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i8_ty],
- [IntrNoMem]>;
- def int_x86_avx512_mask_lzcnt_q_256 :
- Intrinsic<[llvm_v4i64_ty],
- [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i8_ty],
- [IntrNoMem]>;
- def int_x86_avx512_mask_lzcnt_q_512 :
- Intrinsic<[llvm_v8i64_ty],
- [llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty],
- [IntrNoMem]>;
}
// Compares
@@ -6458,10 +6337,6 @@ let TargetPrefix = "x86" in {
GCCBuiltin<"__builtin_ia32_cmpsd_mask">,
Intrinsic<[llvm_i8_ty], [llvm_v2f64_ty, llvm_v2f64_ty,
llvm_i32_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>;
-
- def int_x86_avx512_movntdqa :
- GCCBuiltin<"__builtin_ia32_movntdqa512">,
- Intrinsic<[llvm_v8i64_ty], [llvm_ptr_ty], [IntrReadMem]>;
}
//===----------------------------------------------------------------------===//
@@ -6495,3 +6370,10 @@ let TargetPrefix = "x86" in {
: GCCBuiltin<"__builtin_ia32_mwaitx">,
Intrinsic<[], [ llvm_i32_ty, llvm_i32_ty, llvm_i32_ty ], []>;
}
+
+//===----------------------------------------------------------------------===//
+// Cache-line zero
+let TargetPrefix = "x86" in {
+ def int_x86_clzero : GCCBuiltin<"__builtin_ia32_clzero">,
+ Intrinsic<[], [llvm_ptr_ty], []>;
+}
diff --git a/include/llvm/IR/LLVMContext.h b/include/llvm/IR/LLVMContext.h
index 7f43d5df3c3f..d13d5ddaeb3c 100644
--- a/include/llvm/IR/LLVMContext.h
+++ b/include/llvm/IR/LLVMContext.h
@@ -78,6 +78,7 @@ public:
MD_type = 19, // "type"
MD_section_prefix = 20, // "section_prefix"
MD_absolute_symbol = 21, // "absolute_symbol"
+ MD_associated = 22, // "associated"
};
/// Known operand bundle tag IDs, which always have the same value. All
diff --git a/include/llvm/IR/MDBuilder.h b/include/llvm/IR/MDBuilder.h
index bab8728ed49f..899976a87bc7 100644
--- a/include/llvm/IR/MDBuilder.h
+++ b/include/llvm/IR/MDBuilder.h
@@ -15,7 +15,9 @@
#ifndef LLVM_IR_MDBUILDER_H
#define LLVM_IR_MDBUILDER_H
+#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/IR/GlobalValue.h"
#include "llvm/Support/DataTypes.h"
#include <utility>
@@ -63,8 +65,11 @@ public:
/// Return metadata specifying that a branch or switch is unpredictable.
MDNode *createUnpredictable();
- /// Return metadata containing the entry count for a function.
- MDNode *createFunctionEntryCount(uint64_t Count);
+ /// Return metadata containing the entry \p Count for a function, and the
+ /// GUIDs stored in \p Imports that need to be imported for sample PGO, to
+ /// enable the same inlines as the profiled optimized binary
+ MDNode *createFunctionEntryCount(uint64_t Count,
+ const DenseSet<GlobalValue::GUID> *Imports);
/// Return metadata containing the section prefix for a function.
MDNode *createFunctionSectionPrefix(StringRef Prefix);
diff --git a/include/llvm/IR/Mangler.h b/include/llvm/IR/Mangler.h
index 0eb91a3b0600..56ee21392ccd 100644
--- a/include/llvm/IR/Mangler.h
+++ b/include/llvm/IR/Mangler.h
@@ -21,6 +21,7 @@ namespace llvm {
class DataLayout;
template <typename T> class SmallVectorImpl;
+class Triple;
class Twine;
class raw_ostream;
@@ -46,6 +47,9 @@ public:
const Twine &GVName, const DataLayout &DL);
};
+void emitLinkerFlagsForGlobalCOFF(raw_ostream &OS, const GlobalValue *GV,
+ const Triple &TT, Mangler &Mangler);
+
} // End llvm namespace
#endif
diff --git a/include/llvm/IR/Metadata.h b/include/llvm/IR/Metadata.h
index 46c785a1c05d..fd79355bff1a 100644
--- a/include/llvm/IR/Metadata.h
+++ b/include/llvm/IR/Metadata.h
@@ -78,7 +78,7 @@ public:
protected:
Metadata(unsigned ID, StorageType Storage)
: SubclassID(ID), Storage(Storage), SubclassData16(0), SubclassData32(0) {
- static_assert(sizeof(*this) == 8, "Metdata fields poorly packed");
+ static_assert(sizeof(*this) == 8, "Metadata fields poorly packed");
}
~Metadata() = default;
@@ -269,12 +269,11 @@ public:
private:
LLVMContext &Context;
- uint64_t NextIndex;
+ uint64_t NextIndex = 0;
SmallDenseMap<void *, std::pair<OwnerTy, uint64_t>, 4> UseMap;
public:
- ReplaceableMetadataImpl(LLVMContext &Context)
- : Context(Context), NextIndex(0) {}
+ ReplaceableMetadataImpl(LLVMContext &Context) : Context(Context) {}
~ReplaceableMetadataImpl() {
assert(UseMap.empty() && "Cannot destroy in-use replaceable metadata");
@@ -586,8 +585,9 @@ dyn_extract_or_null(Y &&MD) {
class MDString : public Metadata {
friend class StringMapEntry<MDString>;
- StringMapEntry<MDString> *Entry;
- MDString() : Metadata(MDStringKind, Uniqued), Entry(nullptr) {}
+ StringMapEntry<MDString> *Entry = nullptr;
+
+ MDString() : Metadata(MDStringKind, Uniqued) {}
public:
MDString(const MDString &) = delete;
@@ -1062,7 +1062,6 @@ public:
static MDNode *getMostGenericRange(MDNode *A, MDNode *B);
static MDNode *getMostGenericAliasScope(MDNode *A, MDNode *B);
static MDNode *getMostGenericAlignmentOrDereferenceable(MDNode *A, MDNode *B);
-
};
/// \brief Tuple of metadata.
@@ -1284,7 +1283,7 @@ class NamedMDNode : public ilist_node<NamedMDNode> {
friend class Module;
std::string Name;
- Module *Parent;
+ Module *Parent = nullptr;
void *Operands; // SmallVector<TrackingMDRef, 4>
void setParent(Module *M) { Parent = M; }
diff --git a/include/llvm/IR/Module.h b/include/llvm/IR/Module.h
index 79870b9455a6..70c57cf90add 100644
--- a/include/llvm/IR/Module.h
+++ b/include/llvm/IR/Module.h
@@ -311,7 +311,7 @@ public:
/// 4. Finally, the function exists but has the wrong prototype: return the
/// function with a constantexpr cast to the right prototype.
Constant *getOrInsertFunction(StringRef Name, FunctionType *T,
- AttributeSet AttributeList);
+ AttributeList AttributeList);
Constant *getOrInsertFunction(StringRef Name, FunctionType *T);
@@ -321,13 +321,22 @@ public:
/// or a ConstantExpr BitCast of that type if the named function has a
/// different type. This version of the method takes a null terminated list of
/// function arguments, which makes it easier for clients to use.
+ template<typename... ArgsTy>
Constant *getOrInsertFunction(StringRef Name,
- AttributeSet AttributeList,
- Type *RetTy, ...) LLVM_END_WITH_NULL;
+ AttributeList AttributeList,
+ Type *RetTy, ArgsTy... Args)
+ {
+ SmallVector<Type*, sizeof...(ArgsTy)> ArgTys{Args...};
+ return getOrInsertFunction(Name,
+ FunctionType::get(RetTy, ArgTys, false),
+ AttributeList);
+ }
/// Same as above, but without the attributes.
- Constant *getOrInsertFunction(StringRef Name, Type *RetTy, ...)
- LLVM_END_WITH_NULL;
+ template<typename... ArgsTy>
+ Constant *getOrInsertFunction(StringRef Name, Type *RetTy, ArgsTy... Args) {
+ return getOrInsertFunction(Name, AttributeList{}, RetTy, Args...);
+ }
/// Look up the specified function in the module symbol table. If it does not
/// exist, return null.
@@ -345,20 +354,23 @@ public:
return getGlobalVariable(Name, false);
}
- GlobalVariable *getGlobalVariable(StringRef Name, bool AllowInternal) const {
- return const_cast<Module *>(this)->getGlobalVariable(Name, AllowInternal);
- }
+ GlobalVariable *getGlobalVariable(StringRef Name, bool AllowInternal) const;
- GlobalVariable *getGlobalVariable(StringRef Name, bool AllowInternal = false);
+ GlobalVariable *getGlobalVariable(StringRef Name,
+ bool AllowInternal = false) {
+ return static_cast<const Module *>(this)->getGlobalVariable(Name,
+ AllowInternal);
+ }
/// Return the global variable in the module with the specified name, of
/// arbitrary type. This method returns null if a global with the specified
/// name is not found.
- GlobalVariable *getNamedGlobal(StringRef Name) {
+ const GlobalVariable *getNamedGlobal(StringRef Name) const {
return getGlobalVariable(Name, true);
}
- const GlobalVariable *getNamedGlobal(StringRef Name) const {
- return const_cast<Module *>(this)->getNamedGlobal(Name);
+ GlobalVariable *getNamedGlobal(StringRef Name) {
+ return const_cast<GlobalVariable *>(
+ static_cast<const Module *>(this)->getNamedGlobal(Name));
}
/// Look up the specified global in the module symbol table.
@@ -615,6 +627,32 @@ public:
return global_objects().end();
}
+ typedef concat_iterator<GlobalValue, iterator, global_iterator,
+ alias_iterator, ifunc_iterator>
+ global_value_iterator;
+ typedef concat_iterator<const GlobalValue, const_iterator,
+ const_global_iterator, const_alias_iterator,
+ const_ifunc_iterator>
+ const_global_value_iterator;
+
+ iterator_range<global_value_iterator> global_values() {
+ return concat<GlobalValue>(functions(), globals(), aliases(), ifuncs());
+ }
+ iterator_range<const_global_value_iterator> global_values() const {
+ return concat<const GlobalValue>(functions(), globals(), aliases(),
+ ifuncs());
+ }
+
+ global_value_iterator global_value_begin() { return global_values().begin(); }
+ global_value_iterator global_value_end() { return global_values().end(); }
+
+ const_global_value_iterator global_value_begin() const {
+ return global_values().begin();
+ }
+ const_global_value_iterator global_value_end() const {
+ return global_values().end();
+ }
+
/// @}
/// @name Named Metadata Iteration
/// @{
@@ -726,6 +764,10 @@ public:
/// @name Utility functions for querying Debug information.
/// @{
+ /// \brief Returns the Number of Register ParametersDwarf Version by checking
+ /// module flags.
+ unsigned getNumberRegisterParameters() const;
+
/// \brief Returns the Dwarf Version by checking module flags.
unsigned getDwarfVersion() const;
diff --git a/include/llvm/IR/ModuleSummaryIndex.h b/include/llvm/IR/ModuleSummaryIndex.h
index 83c4ae011216..09f6c1897009 100644
--- a/include/llvm/IR/ModuleSummaryIndex.h
+++ b/include/llvm/IR/ModuleSummaryIndex.h
@@ -162,7 +162,7 @@ private:
protected:
/// GlobalValueSummary constructor.
GlobalValueSummary(SummaryKind K, GVFlags Flags, std::vector<ValueInfo> Refs)
- : Kind(K), Flags(Flags), RefEdgeList(std::move(Refs)) {}
+ : Kind(K), Flags(Flags), OriginalName(0), RefEdgeList(std::move(Refs)) {}
public:
virtual ~GlobalValueSummary() = default;
@@ -233,12 +233,13 @@ public:
void setAliasee(GlobalValueSummary *Aliasee) { AliaseeSummary = Aliasee; }
const GlobalValueSummary &getAliasee() const {
- return const_cast<AliasSummary *>(this)->getAliasee();
+ assert(AliaseeSummary && "Unexpected missing aliasee summary");
+ return *AliaseeSummary;
}
GlobalValueSummary &getAliasee() {
- assert(AliaseeSummary && "Unexpected missing aliasee summary");
- return *AliaseeSummary;
+ return const_cast<GlobalValueSummary &>(
+ static_cast<const AliasSummary *>(this)->getAliasee());
}
};
@@ -249,6 +250,23 @@ public:
/// <CalleeValueInfo, CalleeInfo> call edge pair.
typedef std::pair<ValueInfo, CalleeInfo> EdgeTy;
+ /// An "identifier" for a virtual function. This contains the type identifier
+ /// represented as a GUID and the offset from the address point to the virtual
+ /// function pointer, where "address point" is as defined in the Itanium ABI:
+ /// https://mentorembedded.github.io/cxx-abi/abi.html#vtable-general
+ struct VFuncId {
+ GlobalValue::GUID GUID;
+ uint64_t Offset;
+ };
+
+ /// A specification for a virtual function call with all constant integer
+ /// arguments. This is used to perform virtual constant propagation on the
+ /// summary.
+ struct ConstVCall {
+ VFuncId VFunc;
+ std::vector<uint64_t> Args;
+ };
+
private:
/// Number of instructions (ignoring debug instructions, e.g.) computed
/// during the initial compile step when the summary index is first built.
@@ -257,17 +275,47 @@ private:
/// List of <CalleeValueInfo, CalleeInfo> call edge pairs from this function.
std::vector<EdgeTy> CallGraphEdgeList;
- /// List of type identifiers used by this function, represented as GUIDs.
- std::vector<GlobalValue::GUID> TypeIdList;
+ /// All type identifier related information. Because these fields are
+ /// relatively uncommon we only allocate space for them if necessary.
+ struct TypeIdInfo {
+ /// List of type identifiers used by this function in llvm.type.test
+ /// intrinsics other than by an llvm.assume intrinsic, represented as GUIDs.
+ std::vector<GlobalValue::GUID> TypeTests;
+
+ /// List of virtual calls made by this function using (respectively)
+ /// llvm.assume(llvm.type.test) or llvm.type.checked.load intrinsics that do
+ /// not have all constant integer arguments.
+ std::vector<VFuncId> TypeTestAssumeVCalls, TypeCheckedLoadVCalls;
+
+ /// List of virtual calls made by this function using (respectively)
+ /// llvm.assume(llvm.type.test) or llvm.type.checked.load intrinsics with
+ /// all constant integer arguments.
+ std::vector<ConstVCall> TypeTestAssumeConstVCalls,
+ TypeCheckedLoadConstVCalls;
+ };
+
+ std::unique_ptr<TypeIdInfo> TIdInfo;
public:
/// Summary constructors.
FunctionSummary(GVFlags Flags, unsigned NumInsts, std::vector<ValueInfo> Refs,
std::vector<EdgeTy> CGEdges,
- std::vector<GlobalValue::GUID> TypeIds)
+ std::vector<GlobalValue::GUID> TypeTests,
+ std::vector<VFuncId> TypeTestAssumeVCalls,
+ std::vector<VFuncId> TypeCheckedLoadVCalls,
+ std::vector<ConstVCall> TypeTestAssumeConstVCalls,
+ std::vector<ConstVCall> TypeCheckedLoadConstVCalls)
: GlobalValueSummary(FunctionKind, Flags, std::move(Refs)),
- InstCount(NumInsts), CallGraphEdgeList(std::move(CGEdges)),
- TypeIdList(std::move(TypeIds)) {}
+ InstCount(NumInsts), CallGraphEdgeList(std::move(CGEdges)) {
+ if (!TypeTests.empty() || !TypeTestAssumeVCalls.empty() ||
+ !TypeCheckedLoadVCalls.empty() || !TypeTestAssumeConstVCalls.empty() ||
+ !TypeCheckedLoadConstVCalls.empty())
+ TIdInfo = llvm::make_unique<TypeIdInfo>(TypeIdInfo{
+ std::move(TypeTests), std::move(TypeTestAssumeVCalls),
+ std::move(TypeCheckedLoadVCalls),
+ std::move(TypeTestAssumeConstVCalls),
+ std::move(TypeCheckedLoadConstVCalls)});
+ }
/// Check if this is a function summary.
static bool classof(const GlobalValueSummary *GVS) {
@@ -280,8 +328,85 @@ public:
/// Return the list of <CalleeValueInfo, CalleeInfo> pairs.
ArrayRef<EdgeTy> calls() const { return CallGraphEdgeList; }
- /// Returns the list of type identifiers used by this function.
- ArrayRef<GlobalValue::GUID> type_tests() const { return TypeIdList; }
+ /// Returns the list of type identifiers used by this function in
+ /// llvm.type.test intrinsics other than by an llvm.assume intrinsic,
+ /// represented as GUIDs.
+ ArrayRef<GlobalValue::GUID> type_tests() const {
+ if (TIdInfo)
+ return TIdInfo->TypeTests;
+ return {};
+ }
+
+ /// Returns the list of virtual calls made by this function using
+ /// llvm.assume(llvm.type.test) intrinsics that do not have all constant
+ /// integer arguments.
+ ArrayRef<VFuncId> type_test_assume_vcalls() const {
+ if (TIdInfo)
+ return TIdInfo->TypeTestAssumeVCalls;
+ return {};
+ }
+
+ /// Returns the list of virtual calls made by this function using
+ /// llvm.type.checked.load intrinsics that do not have all constant integer
+ /// arguments.
+ ArrayRef<VFuncId> type_checked_load_vcalls() const {
+ if (TIdInfo)
+ return TIdInfo->TypeCheckedLoadVCalls;
+ return {};
+ }
+
+ /// Returns the list of virtual calls made by this function using
+ /// llvm.assume(llvm.type.test) intrinsics with all constant integer
+ /// arguments.
+ ArrayRef<ConstVCall> type_test_assume_const_vcalls() const {
+ if (TIdInfo)
+ return TIdInfo->TypeTestAssumeConstVCalls;
+ return {};
+ }
+
+ /// Returns the list of virtual calls made by this function using
+ /// llvm.type.checked.load intrinsics with all constant integer arguments.
+ ArrayRef<ConstVCall> type_checked_load_const_vcalls() const {
+ if (TIdInfo)
+ return TIdInfo->TypeCheckedLoadConstVCalls;
+ return {};
+ }
+
+ /// Add a type test to the summary. This is used by WholeProgramDevirt if we
+ /// were unable to devirtualize a checked call.
+ void addTypeTest(GlobalValue::GUID Guid) {
+ if (!TIdInfo)
+ TIdInfo = llvm::make_unique<TypeIdInfo>();
+ TIdInfo->TypeTests.push_back(Guid);
+ }
+};
+
+template <> struct DenseMapInfo<FunctionSummary::VFuncId> {
+ static FunctionSummary::VFuncId getEmptyKey() { return {0, uint64_t(-1)}; }
+ static FunctionSummary::VFuncId getTombstoneKey() {
+ return {0, uint64_t(-2)};
+ }
+ static bool isEqual(FunctionSummary::VFuncId L, FunctionSummary::VFuncId R) {
+ return L.GUID == R.GUID && L.Offset == R.Offset;
+ }
+ static unsigned getHashValue(FunctionSummary::VFuncId I) { return I.GUID; }
+};
+
+template <> struct DenseMapInfo<FunctionSummary::ConstVCall> {
+ static FunctionSummary::ConstVCall getEmptyKey() {
+ return {{0, uint64_t(-1)}, {}};
+ }
+ static FunctionSummary::ConstVCall getTombstoneKey() {
+ return {{0, uint64_t(-2)}, {}};
+ }
+ static bool isEqual(FunctionSummary::ConstVCall L,
+ FunctionSummary::ConstVCall R) {
+ return DenseMapInfo<FunctionSummary::VFuncId>::isEqual(L.VFunc, R.VFunc) &&
+ L.Args == R.Args;
+ }
+ static unsigned getHashValue(FunctionSummary::ConstVCall I) {
+ return I.VFunc.GUID;
+ }
};
/// \brief Global variable summary information to aid decisions and
@@ -323,8 +448,40 @@ struct TypeTestResolution {
unsigned SizeM1BitWidth = 0;
};
+struct WholeProgramDevirtResolution {
+ enum Kind {
+ Indir, ///< Just do a regular virtual call
+ SingleImpl, ///< Single implementation devirtualization
+ } TheKind = Indir;
+
+ std::string SingleImplName;
+
+ struct ByArg {
+ enum Kind {
+ Indir, ///< Just do a regular virtual call
+ UniformRetVal, ///< Uniform return value optimization
+ UniqueRetVal, ///< Unique return value optimization
+ VirtualConstProp, ///< Virtual constant propagation
+ } TheKind = Indir;
+
+ /// Additional information for the resolution:
+ /// - UniformRetVal: the uniform return value.
+ /// - UniqueRetVal: the return value associated with the unique vtable (0 or
+ /// 1).
+ uint64_t Info = 0;
+ };
+
+ /// Resolutions for calls with all constant integer arguments (excluding the
+ /// first argument, "this"), where the key is the argument vector.
+ std::map<std::vector<uint64_t>, ByArg> ResByArg;
+};
+
struct TypeIdSummary {
TypeTestResolution TTRes;
+
+ /// Mapping from byte offset to whole-program devirt resolution for that
+ /// (typeid, byte offset) pair.
+ std::map<uint64_t, WholeProgramDevirtResolution> WPDRes;
};
/// 160 bits SHA1
@@ -372,6 +529,10 @@ private:
// FIXME: Add bitcode read/write support for this field.
std::map<std::string, TypeIdSummary> TypeIdMap;
+ /// Mapping from original ID to GUID. If original ID can map to multiple
+ /// GUIDs, it will be mapped to 0.
+ std::map<GlobalValue::GUID, GlobalValue::GUID> OidGuidMap;
+
// YAML I/O support.
friend yaml::MappingTraits<ModuleSummaryIndex>;
@@ -399,9 +560,17 @@ public:
return GlobalValueMap.find(ValueGUID);
}
+ /// Return the GUID for \p OriginalId in the OidGuidMap.
+ GlobalValue::GUID getGUIDFromOriginalID(GlobalValue::GUID OriginalID) const {
+ const auto I = OidGuidMap.find(OriginalID);
+ return I == OidGuidMap.end() ? 0 : I->second;
+ }
+
/// Add a global value summary for a value of the given name.
void addGlobalValueSummary(StringRef ValueName,
std::unique_ptr<GlobalValueSummary> Summary) {
+ addOriginalName(GlobalValue::getGUID(ValueName),
+ Summary->getOriginalName());
GlobalValueMap[GlobalValue::getGUID(ValueName)].push_back(
std::move(Summary));
}
@@ -409,9 +578,21 @@ public:
/// Add a global value summary for a value of the given GUID.
void addGlobalValueSummary(GlobalValue::GUID ValueGUID,
std::unique_ptr<GlobalValueSummary> Summary) {
+ addOriginalName(ValueGUID, Summary->getOriginalName());
GlobalValueMap[ValueGUID].push_back(std::move(Summary));
}
+ /// Add an original name for the value of the given GUID.
+ void addOriginalName(GlobalValue::GUID ValueGUID,
+ GlobalValue::GUID OrigGUID) {
+ if (OrigGUID == 0 || ValueGUID == OrigGUID)
+ return;
+ if (OidGuidMap.count(OrigGUID) && OidGuidMap[OrigGUID] != ValueGUID)
+ OidGuidMap[OrigGUID] = 0;
+ else
+ OidGuidMap[OrigGUID] = ValueGUID;
+ }
+
/// Find the summary for global \p GUID in module \p ModuleId, or nullptr if
/// not found.
GlobalValueSummary *findSummaryInModule(GlobalValue::GUID ValueGUID,
@@ -507,6 +688,25 @@ public:
return ModulePathStringTable.count(M.getModuleIdentifier());
}
+ const std::map<std::string, TypeIdSummary> &typeIds() const {
+ return TypeIdMap;
+ }
+
+ /// This accessor should only be used when exporting because it can mutate the
+ /// map.
+ TypeIdSummary &getOrInsertTypeIdSummary(StringRef TypeId) {
+ return TypeIdMap[TypeId];
+ }
+
+ /// This returns either a pointer to the type id summary (if present in the
+ /// summary map) or null (if not present). This may be used when importing.
+ const TypeIdSummary *getTypeIdSummary(StringRef TypeId) const {
+ auto I = TypeIdMap.find(TypeId);
+ if (I == TypeIdMap.end())
+ return nullptr;
+ return &I->second;
+ }
+
/// Remove entries in the GlobalValueMap that have empty summaries due to the
/// eager nature of map entry creation during VST parsing. These would
/// also be suppressed during combined index generation in mergeFrom(),
diff --git a/include/llvm/IR/ModuleSummaryIndexYAML.h b/include/llvm/IR/ModuleSummaryIndexYAML.h
index e2880ec6fec8..80719c696935 100644
--- a/include/llvm/IR/ModuleSummaryIndexYAML.h
+++ b/include/llvm/IR/ModuleSummaryIndexYAML.h
@@ -33,20 +33,135 @@ template <> struct MappingTraits<TypeTestResolution> {
}
};
+template <>
+struct ScalarEnumerationTraits<WholeProgramDevirtResolution::ByArg::Kind> {
+ static void enumeration(IO &io,
+ WholeProgramDevirtResolution::ByArg::Kind &value) {
+ io.enumCase(value, "Indir", WholeProgramDevirtResolution::ByArg::Indir);
+ io.enumCase(value, "UniformRetVal",
+ WholeProgramDevirtResolution::ByArg::UniformRetVal);
+ io.enumCase(value, "UniqueRetVal",
+ WholeProgramDevirtResolution::ByArg::UniqueRetVal);
+ io.enumCase(value, "VirtualConstProp",
+ WholeProgramDevirtResolution::ByArg::VirtualConstProp);
+ }
+};
+
+template <> struct MappingTraits<WholeProgramDevirtResolution::ByArg> {
+ static void mapping(IO &io, WholeProgramDevirtResolution::ByArg &res) {
+ io.mapOptional("Kind", res.TheKind);
+ io.mapOptional("Info", res.Info);
+ }
+};
+
+template <>
+struct CustomMappingTraits<
+ std::map<std::vector<uint64_t>, WholeProgramDevirtResolution::ByArg>> {
+ static void inputOne(
+ IO &io, StringRef Key,
+ std::map<std::vector<uint64_t>, WholeProgramDevirtResolution::ByArg> &V) {
+ std::vector<uint64_t> Args;
+ std::pair<StringRef, StringRef> P = {"", Key};
+ while (!P.second.empty()) {
+ P = P.second.split(',');
+ uint64_t Arg;
+ if (P.first.getAsInteger(0, Arg)) {
+ io.setError("key not an integer");
+ return;
+ }
+ Args.push_back(Arg);
+ }
+ io.mapRequired(Key.str().c_str(), V[Args]);
+ }
+ static void output(
+ IO &io,
+ std::map<std::vector<uint64_t>, WholeProgramDevirtResolution::ByArg> &V) {
+ for (auto &P : V) {
+ std::string Key;
+ for (uint64_t Arg : P.first) {
+ if (!Key.empty())
+ Key += ',';
+ Key += llvm::utostr(Arg);
+ }
+ io.mapRequired(Key.c_str(), P.second);
+ }
+ }
+};
+
+template <> struct ScalarEnumerationTraits<WholeProgramDevirtResolution::Kind> {
+ static void enumeration(IO &io, WholeProgramDevirtResolution::Kind &value) {
+ io.enumCase(value, "Indir", WholeProgramDevirtResolution::Indir);
+ io.enumCase(value, "SingleImpl", WholeProgramDevirtResolution::SingleImpl);
+ }
+};
+
+template <> struct MappingTraits<WholeProgramDevirtResolution> {
+ static void mapping(IO &io, WholeProgramDevirtResolution &res) {
+ io.mapOptional("Kind", res.TheKind);
+ io.mapOptional("SingleImplName", res.SingleImplName);
+ io.mapOptional("ResByArg", res.ResByArg);
+ }
+};
+
+template <>
+struct CustomMappingTraits<std::map<uint64_t, WholeProgramDevirtResolution>> {
+ static void inputOne(IO &io, StringRef Key,
+ std::map<uint64_t, WholeProgramDevirtResolution> &V) {
+ uint64_t KeyInt;
+ if (Key.getAsInteger(0, KeyInt)) {
+ io.setError("key not an integer");
+ return;
+ }
+ io.mapRequired(Key.str().c_str(), V[KeyInt]);
+ }
+ static void output(IO &io, std::map<uint64_t, WholeProgramDevirtResolution> &V) {
+ for (auto &P : V)
+ io.mapRequired(llvm::utostr(P.first).c_str(), P.second);
+ }
+};
+
template <> struct MappingTraits<TypeIdSummary> {
static void mapping(IO &io, TypeIdSummary& summary) {
io.mapOptional("TTRes", summary.TTRes);
+ io.mapOptional("WPDRes", summary.WPDRes);
}
};
struct FunctionSummaryYaml {
std::vector<uint64_t> TypeTests;
+ std::vector<FunctionSummary::VFuncId> TypeTestAssumeVCalls,
+ TypeCheckedLoadVCalls;
+ std::vector<FunctionSummary::ConstVCall> TypeTestAssumeConstVCalls,
+ TypeCheckedLoadConstVCalls;
+};
+
+} // End yaml namespace
+} // End llvm namespace
+
+LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(uint64_t)
+
+namespace llvm {
+namespace yaml {
+
+template <> struct MappingTraits<FunctionSummary::VFuncId> {
+ static void mapping(IO &io, FunctionSummary::VFuncId& id) {
+ io.mapOptional("GUID", id.GUID);
+ io.mapOptional("Offset", id.Offset);
+ }
+};
+
+template <> struct MappingTraits<FunctionSummary::ConstVCall> {
+ static void mapping(IO &io, FunctionSummary::ConstVCall& id) {
+ io.mapOptional("VFunc", id.VFunc);
+ io.mapOptional("Args", id.Args);
+ }
};
} // End yaml namespace
} // End llvm namespace
-LLVM_YAML_IS_SEQUENCE_VECTOR(uint64_t)
+LLVM_YAML_IS_SEQUENCE_VECTOR(FunctionSummary::VFuncId)
+LLVM_YAML_IS_SEQUENCE_VECTOR(FunctionSummary::ConstVCall)
namespace llvm {
namespace yaml {
@@ -54,6 +169,12 @@ namespace yaml {
template <> struct MappingTraits<FunctionSummaryYaml> {
static void mapping(IO &io, FunctionSummaryYaml& summary) {
io.mapOptional("TypeTests", summary.TypeTests);
+ io.mapOptional("TypeTestAssumeVCalls", summary.TypeTestAssumeVCalls);
+ io.mapOptional("TypeCheckedLoadVCalls", summary.TypeCheckedLoadVCalls);
+ io.mapOptional("TypeTestAssumeConstVCalls",
+ summary.TypeTestAssumeConstVCalls);
+ io.mapOptional("TypeCheckedLoadConstVCalls",
+ summary.TypeCheckedLoadConstVCalls);
}
};
@@ -82,7 +203,11 @@ template <> struct CustomMappingTraits<GlobalValueSummaryMapTy> {
false);
Elem.push_back(llvm::make_unique<FunctionSummary>(
GVFlags, 0, ArrayRef<ValueInfo>{},
- ArrayRef<FunctionSummary::EdgeTy>{}, std::move(FSum.TypeTests)));
+ ArrayRef<FunctionSummary::EdgeTy>{}, std::move(FSum.TypeTests),
+ std::move(FSum.TypeTestAssumeVCalls),
+ std::move(FSum.TypeCheckedLoadVCalls),
+ std::move(FSum.TypeTestAssumeConstVCalls),
+ std::move(FSum.TypeCheckedLoadConstVCalls)));
}
}
static void output(IO &io, GlobalValueSummaryMapTy &V) {
@@ -90,7 +215,11 @@ template <> struct CustomMappingTraits<GlobalValueSummaryMapTy> {
std::vector<FunctionSummaryYaml> FSums;
for (auto &Sum : P.second) {
if (auto *FSum = dyn_cast<FunctionSummary>(Sum.get()))
- FSums.push_back(FunctionSummaryYaml{FSum->type_tests()});
+ FSums.push_back(FunctionSummaryYaml{
+ FSum->type_tests(), FSum->type_test_assume_vcalls(),
+ FSum->type_checked_load_vcalls(),
+ FSum->type_test_assume_const_vcalls(),
+ FSum->type_checked_load_const_vcalls()});
}
if (!FSums.empty())
io.mapRequired(llvm::utostr(P.first).c_str(), FSums);
diff --git a/include/llvm/IR/Operator.h b/include/llvm/IR/Operator.h
index 444ce93921f6..997a85340c25 100644
--- a/include/llvm/IR/Operator.h
+++ b/include/llvm/IR/Operator.h
@@ -18,8 +18,6 @@
#include "llvm/ADT/None.h"
#include "llvm/ADT/Optional.h"
#include "llvm/IR/Constants.h"
-#include "llvm/IR/DataLayout.h"
-#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/Value.h"
@@ -174,12 +172,15 @@ private:
FastMathFlags(unsigned F) : Flags(F) { }
public:
+ /// This is how the bits are used in Value::SubclassOptionalData so they
+ /// should fit there too.
enum {
UnsafeAlgebra = (1 << 0),
NoNaNs = (1 << 1),
NoInfs = (1 << 2),
NoSignedZeros = (1 << 3),
- AllowReciprocal = (1 << 4)
+ AllowReciprocal = (1 << 4),
+ AllowContract = (1 << 5)
};
FastMathFlags() = default;
@@ -195,6 +196,7 @@ public:
bool noInfs() const { return 0 != (Flags & NoInfs); }
bool noSignedZeros() const { return 0 != (Flags & NoSignedZeros); }
bool allowReciprocal() const { return 0 != (Flags & AllowReciprocal); }
+ bool allowContract() const { return 0 != (Flags & AllowContract); }
bool unsafeAlgebra() const { return 0 != (Flags & UnsafeAlgebra); }
/// Flag setters
@@ -202,12 +204,16 @@ public:
void setNoInfs() { Flags |= NoInfs; }
void setNoSignedZeros() { Flags |= NoSignedZeros; }
void setAllowReciprocal() { Flags |= AllowReciprocal; }
+ void setAllowContract(bool B) {
+ Flags = (Flags & ~AllowContract) | B * AllowContract;
+ }
void setUnsafeAlgebra() {
Flags |= UnsafeAlgebra;
setNoNaNs();
setNoInfs();
setNoSignedZeros();
setAllowReciprocal();
+ setAllowContract(true);
}
void operator&=(const FastMathFlags &OtherFlags) {
@@ -259,6 +265,12 @@ private:
(B * FastMathFlags::AllowReciprocal);
}
+ void setHasAllowContract(bool B) {
+ SubclassOptionalData =
+ (SubclassOptionalData & ~FastMathFlags::AllowContract) |
+ (B * FastMathFlags::AllowContract);
+ }
+
/// Convenience function for setting multiple fast-math flags.
/// FMF is a mask of the bits to set.
void setFastMathFlags(FastMathFlags FMF) {
@@ -302,6 +314,12 @@ public:
return (SubclassOptionalData & FastMathFlags::AllowReciprocal) != 0;
}
+ /// Test whether this operation is permitted to
+ /// be floating-point contracted.
+ bool hasAllowContract() const {
+ return (SubclassOptionalData & FastMathFlags::AllowContract) != 0;
+ }
+
/// Convenience function for getting all the fast-math flags
FastMathFlags getFastMathFlags() const {
return FastMathFlags(SubclassOptionalData);
diff --git a/include/llvm/IR/OptBisect.h b/include/llvm/IR/OptBisect.h
index 9eee65e93e52..185a5ac956f5 100644
--- a/include/llvm/IR/OptBisect.h
+++ b/include/llvm/IR/OptBisect.h
@@ -51,24 +51,6 @@ public:
template <class UnitT>
bool shouldRunPass(const Pass *P, const UnitT &U);
- /// Checks the bisect limit to determine if the optimization described by the
- /// /p Desc argument should run.
- ///
- /// This function will immediate return true if bisection is disabled. If the
- /// bisect limit is set to -1, the function will print a message with the
- /// bisect number assigned to the optimization along with the /p Desc
- /// description and return true. Otherwise, the function will print a message
- /// with the bisect number assigned to the optimization and indicating whether
- /// or not the pass will be run and return true if the bisect limit has not
- /// yet been exceded or false if it has.
- ///
- /// Passes may call this function to provide more fine grained control over
- /// individual optimizations performed by the pass. Passes which cannot be
- /// skipped entirely (such as non-optional code generation passes) may still
- /// call this function to control whether or not individual optional
- /// transformations are performed.
- bool shouldRunCase(const Twine &Desc);
-
private:
bool checkPass(const StringRef PassName, const StringRef TargetDesc);
diff --git a/include/llvm/IR/PassManager.h b/include/llvm/IR/PassManager.h
index b7811fdb7504..c845112baa45 100644
--- a/include/llvm/IR/PassManager.h
+++ b/include/llvm/IR/PassManager.h
@@ -73,6 +73,46 @@ struct alignas(8) AnalysisKey {};
/// if it is, the analysis knows that it itself is preserved.
struct alignas(8) AnalysisSetKey {};
+/// This templated class represents "all analyses that operate over \<a
+/// particular IR unit\>" (e.g. a Function or a Module) in instances of
+/// PreservedAnalysis.
+///
+/// This lets a transformation say e.g. "I preserved all function analyses".
+///
+/// Note that you must provide an explicit instantiation declaration and
+/// definition for this template in order to get the correct behavior on
+/// Windows. Otherwise, the address of SetKey will not be stable.
+template <typename IRUnitT> class AllAnalysesOn {
+public:
+ static AnalysisSetKey *ID() { return &SetKey; }
+
+private:
+ static AnalysisSetKey SetKey;
+};
+
+template <typename IRUnitT> AnalysisSetKey AllAnalysesOn<IRUnitT>::SetKey;
+
+extern template class AllAnalysesOn<Module>;
+extern template class AllAnalysesOn<Function>;
+
+/// Represents analyses that only rely on functions' control flow.
+///
+/// This can be used with \c PreservedAnalyses to mark the CFG as preserved and
+/// to query whether it has been preserved.
+///
+/// The CFG of a function is defined as the set of basic blocks and the edges
+/// between them. Changing the set of basic blocks in a function is enough to
+/// mutate the CFG. Mutating the condition of a branch or argument of an
+/// invoked function does not mutate the CFG, but changing the successor labels
+/// of those instructions does.
+class CFGAnalyses {
+public:
+ static AnalysisSetKey *ID() { return &SetKey; }
+
+private:
+ static AnalysisSetKey SetKey;
+};
+
/// A set of analyses that are preserved following a run of a transformation
/// pass.
///
@@ -348,29 +388,6 @@ struct AnalysisInfoMixin : PassInfoMixin<DerivedT> {
}
};
-/// This templated class represents "all analyses that operate over \<a
-/// particular IR unit\>" (e.g. a Function or a Module) in instances of
-/// PreservedAnalysis.
-///
-/// This lets a transformation say e.g. "I preserved all function analyses".
-///
-/// Note that you must provide an explicit instantiation declaration and
-/// definition for this template in order to get the correct behavior on
-/// Windows. Otherwise, the address of SetKey will not be stable.
-template <typename IRUnitT>
-class AllAnalysesOn {
-public:
- static AnalysisSetKey *ID() { return &SetKey; }
-
-private:
- static AnalysisSetKey SetKey;
-};
-
-template <typename IRUnitT> AnalysisSetKey AllAnalysesOn<IRUnitT>::SetKey;
-
-extern template class AllAnalysesOn<Module>;
-extern template class AllAnalysesOn<Function>;
-
/// \brief Manages a sequence of passes over a particular unit of IR.
///
/// A pass manager contains a sequence of passes to run over a particular unit
@@ -780,7 +797,7 @@ public:
if (DebugLogging)
dbgs() << "Invalidating analysis: " << this->lookUpPass(ID).name()
- << "\n";
+ << " on " << IR.getName() << "\n";
I = ResultsList.erase(I);
AnalysisResults.erase({ID, &IR});
@@ -821,7 +838,8 @@ private:
if (Inserted) {
auto &P = this->lookUpPass(ID);
if (DebugLogging)
- dbgs() << "Running analysis: " << P.name() << "\n";
+ dbgs() << "Running analysis: " << P.name() << " on " << IR.getName()
+ << "\n";
AnalysisResultListT &ResultList = AnalysisResultLists[&IR];
ResultList.emplace_back(ID, P.run(IR, *this, ExtraArgs...));
@@ -852,7 +870,7 @@ private:
if (DebugLogging)
dbgs() << "Invalidating analysis: " << this->lookUpPass(ID).name()
- << "\n";
+ << " on " << IR.getName() << "\n";
AnalysisResultLists[&IR].erase(RI->second);
AnalysisResults.erase(RI);
}
diff --git a/include/llvm/IR/PassManagerInternal.h b/include/llvm/IR/PassManagerInternal.h
index 02f21675fa9d..387dc4c65c43 100644
--- a/include/llvm/IR/PassManagerInternal.h
+++ b/include/llvm/IR/PassManagerInternal.h
@@ -291,7 +291,7 @@ struct AnalysisPassModel : AnalysisPassConcept<IRUnitT, PreservedAnalysesT,
AnalysisResultConcept<IRUnitT, PreservedAnalysesT, InvalidatorT>>
run(IRUnitT &IR, AnalysisManager<IRUnitT, ExtraArgTs...> &AM,
ExtraArgTs... ExtraArgs) override {
- return make_unique<ResultModelT>(Pass.run(IR, AM, ExtraArgs...));
+ return llvm::make_unique<ResultModelT>(Pass.run(IR, AM, ExtraArgs...));
}
/// \brief The model delegates to a static \c PassT::name method.
diff --git a/include/llvm/IR/PatternMatch.h b/include/llvm/IR/PatternMatch.h
index a30fc97e98ef..40f9c21f646b 100644
--- a/include/llvm/IR/PatternMatch.h
+++ b/include/llvm/IR/PatternMatch.h
@@ -157,6 +157,19 @@ inline match_combine_or<match_zero, match_neg_zero> m_AnyZero() {
return m_CombineOr(m_Zero(), m_NegZero());
}
+struct match_nan {
+ template <typename ITy> bool match(ITy *V) {
+ if (const auto *C = dyn_cast<ConstantFP>(V)) {
+ const APFloat &APF = C->getValueAPF();
+ return APF.isNaN();
+ }
+ return false;
+ }
+};
+
+/// Match an arbitrary NaN constant. This includes quiet and signalling nans.
+inline match_nan m_NaN() { return match_nan(); }
+
struct apint_match {
const APInt *&Res;
apint_match(const APInt *&R) : Res(R) {}
@@ -814,6 +827,13 @@ inline CastClass_match<OpTy, Instruction::ZExt> m_ZExt(const OpTy &Op) {
return CastClass_match<OpTy, Instruction::ZExt>(Op);
}
+template <typename OpTy>
+inline match_combine_or<CastClass_match<OpTy, Instruction::ZExt>,
+ CastClass_match<OpTy, Instruction::SExt>>
+m_ZExtOrSExt(const OpTy &Op) {
+ return m_CombineOr(m_ZExt(Op), m_SExt(Op));
+}
+
/// \brief Matches UIToFP.
template <typename OpTy>
inline CastClass_match<OpTy, Instruction::UIToFP> m_UIToFP(const OpTy &Op) {
@@ -826,6 +846,18 @@ inline CastClass_match<OpTy, Instruction::SIToFP> m_SIToFP(const OpTy &Op) {
return CastClass_match<OpTy, Instruction::SIToFP>(Op);
}
+/// \brief Matches FPTrunc
+template <typename OpTy>
+inline CastClass_match<OpTy, Instruction::FPTrunc> m_FPTrunc(const OpTy &Op) {
+ return CastClass_match<OpTy, Instruction::FPTrunc>(Op);
+}
+
+/// \brief Matches FPExt
+template <typename OpTy>
+inline CastClass_match<OpTy, Instruction::FPExt> m_FPExt(const OpTy &Op) {
+ return CastClass_match<OpTy, Instruction::FPExt>(Op);
+}
+
//===----------------------------------------------------------------------===//
// Matchers for unary operators
//
@@ -1316,6 +1348,14 @@ template <typename Val_t> inline Signum_match<Val_t> m_Signum(const Val_t &V) {
// Matchers for two-operands operators with the operators in either order
//
+/// \brief Matches a BinaryOperator with LHS and RHS in either order.
+template<typename LHS, typename RHS>
+inline match_combine_or<AnyBinaryOp_match<LHS, RHS>,
+ AnyBinaryOp_match<RHS, LHS>>
+m_c_BinOp(const LHS &L, const RHS &R) {
+ return m_CombineOr(m_BinOp(L, R), m_BinOp(R, L));
+}
+
/// \brief Matches an ICmp with a predicate over LHS and RHS in either order.
/// Does not swap the predicate.
template<typename LHS, typename RHS>
@@ -1325,6 +1365,22 @@ m_c_ICmp(ICmpInst::Predicate &Pred, const LHS &L, const RHS &R) {
return m_CombineOr(m_ICmp(Pred, L, R), m_ICmp(Pred, R, L));
}
+/// \brief Matches a Add with LHS and RHS in either order.
+template<typename LHS, typename RHS>
+inline match_combine_or<BinaryOp_match<LHS, RHS, Instruction::Add>,
+ BinaryOp_match<RHS, LHS, Instruction::Add>>
+m_c_Add(const LHS &L, const RHS &R) {
+ return m_CombineOr(m_Add(L, R), m_Add(R, L));
+}
+
+/// \brief Matches a Mul with LHS and RHS in either order.
+template<typename LHS, typename RHS>
+inline match_combine_or<BinaryOp_match<LHS, RHS, Instruction::Mul>,
+ BinaryOp_match<RHS, LHS, Instruction::Mul>>
+m_c_Mul(const LHS &L, const RHS &R) {
+ return m_CombineOr(m_Mul(L, R), m_Mul(R, L));
+}
+
/// \brief Matches an And with LHS and RHS in either order.
template<typename LHS, typename RHS>
inline match_combine_or<BinaryOp_match<LHS, RHS, Instruction::And>,
diff --git a/include/llvm/IR/PredIteratorCache.h b/include/llvm/IR/PredIteratorCache.h
index 118310aed1d0..81f535311431 100644
--- a/include/llvm/IR/PredIteratorCache.h
+++ b/include/llvm/IR/PredIteratorCache.h
@@ -27,8 +27,8 @@ namespace llvm {
/// wants the predecessor list for the same blocks.
class PredIteratorCache {
/// BlockToPredsMap - Pointer to null-terminated list.
- DenseMap<BasicBlock *, BasicBlock **> BlockToPredsMap;
- DenseMap<BasicBlock *, unsigned> BlockToPredCountMap;
+ mutable DenseMap<BasicBlock *, BasicBlock **> BlockToPredsMap;
+ mutable DenseMap<BasicBlock *, unsigned> BlockToPredCountMap;
/// Memory - This is the space that holds cached preds.
BumpPtrAllocator Memory;
@@ -55,13 +55,15 @@ private:
return Entry;
}
- unsigned GetNumPreds(BasicBlock *BB) {
- GetPreds(BB);
- return BlockToPredCountMap[BB];
+ unsigned GetNumPreds(BasicBlock *BB) const {
+ auto Result = BlockToPredCountMap.find(BB);
+ if (Result != BlockToPredCountMap.end())
+ return Result->second;
+ return BlockToPredCountMap[BB] = std::distance(pred_begin(BB), pred_end(BB));
}
public:
- size_t size(BasicBlock *BB) { return GetNumPreds(BB); }
+ size_t size(BasicBlock *BB) const { return GetNumPreds(BB); }
ArrayRef<BasicBlock *> get(BasicBlock *BB) {
return makeArrayRef(GetPreds(BB), GetNumPreds(BB));
}
diff --git a/include/llvm/IR/Statepoint.h b/include/llvm/IR/Statepoint.h
index 916faa4b327e..03151cd7c8f7 100644
--- a/include/llvm/IR/Statepoint.h
+++ b/include/llvm/IR/Statepoint.h
@@ -454,7 +454,7 @@ struct StatepointDirectives {
/// Parse out statepoint directives from the function attributes present in \p
/// AS.
-StatepointDirectives parseStatepointDirectivesFromAttrs(AttributeSet AS);
+StatepointDirectives parseStatepointDirectivesFromAttrs(AttributeList AS);
/// Return \c true if the the \p Attr is an attribute that is a statepoint
/// directive.
diff --git a/include/llvm/IR/SymbolTableListTraits.h b/include/llvm/IR/SymbolTableListTraits.h
index 5c6d58affd7a..49a5fb21297d 100644
--- a/include/llvm/IR/SymbolTableListTraits.h
+++ b/include/llvm/IR/SymbolTableListTraits.h
@@ -1,4 +1,4 @@
-//===-- llvm/SymbolTableListTraits.h - Traits for iplist --------*- C++ -*-===//
+//===- llvm/SymbolTableListTraits.h - Traits for iplist ---------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -26,23 +26,27 @@
#define LLVM_IR_SYMBOLTABLELISTTRAITS_H
#include "llvm/ADT/ilist.h"
+#include "llvm/ADT/simple_ilist.h"
+#include <cstddef>
namespace llvm {
-class ValueSymbolTable;
-/// Template metafunction to get the parent type for a symbol table list.
-///
-/// Implementations create a typedef called \c type so that we only need a
-/// single template parameter for the list and traits.
-template <typename NodeTy> struct SymbolTableListParentType {};
class Argument;
class BasicBlock;
class Function;
-class Instruction;
-class GlobalVariable;
class GlobalAlias;
class GlobalIFunc;
+class GlobalVariable;
+class Instruction;
class Module;
+class ValueSymbolTable;
+
+/// Template metafunction to get the parent type for a symbol table list.
+///
+/// Implementations create a typedef called \c type so that we only need a
+/// single template parameter for the list and traits.
+template <typename NodeTy> struct SymbolTableListParentType {};
+
#define DEFINE_SYMBOL_TABLE_PARENT_TYPE(NODE, PARENT) \
template <> struct SymbolTableListParentType<NODE> { typedef PARENT type; };
DEFINE_SYMBOL_TABLE_PARENT_TYPE(Instruction, BasicBlock)
@@ -67,7 +71,7 @@ class SymbolTableListTraits : public ilist_alloc_traits<ValueSubClass> {
typename SymbolTableListParentType<ValueSubClass>::type ItemParentClass;
public:
- SymbolTableListTraits() {}
+ SymbolTableListTraits() = default;
private:
/// getListOwner - Return the object that owns this list. If this is a list
@@ -109,6 +113,6 @@ template <class T>
class SymbolTableList
: public iplist_impl<simple_ilist<T>, SymbolTableListTraits<T>> {};
-} // End llvm namespace
+} // end namespace llvm
-#endif
+#endif // LLVM_IR_SYMBOLTABLELISTTRAITS_H
diff --git a/include/llvm/IR/TrackingMDRef.h b/include/llvm/IR/TrackingMDRef.h
index fe513a8f9795..12b196432006 100644
--- a/include/llvm/IR/TrackingMDRef.h
+++ b/include/llvm/IR/TrackingMDRef.h
@@ -15,6 +15,8 @@
#define LLVM_IR_TRACKINGMDREF_H
#include "llvm/IR/Metadata.h"
+#include <algorithm>
+#include <cassert>
namespace llvm {
@@ -22,14 +24,15 @@ namespace llvm {
///
/// This class behaves like \a TrackingVH, but for metadata.
class TrackingMDRef {
- Metadata *MD;
+ Metadata *MD = nullptr;
public:
- TrackingMDRef() : MD(nullptr) {}
+ TrackingMDRef() = default;
explicit TrackingMDRef(Metadata *MD) : MD(MD) { track(); }
TrackingMDRef(TrackingMDRef &&X) : MD(X.MD) { retrack(X); }
TrackingMDRef(const TrackingMDRef &X) : MD(X.MD) { track(); }
+
TrackingMDRef &operator=(TrackingMDRef &&X) {
if (&X == this)
return *this;
@@ -39,6 +42,7 @@ public:
retrack(X);
return *this;
}
+
TrackingMDRef &operator=(const TrackingMDRef &X) {
if (&X == this)
return *this;
@@ -48,6 +52,7 @@ public:
track();
return *this;
}
+
~TrackingMDRef() { untrack(); }
Metadata *get() const { return MD; }
@@ -80,10 +85,12 @@ private:
if (MD)
MetadataTracking::track(MD);
}
+
void untrack() {
if (MD)
MetadataTracking::untrack(MD);
}
+
void retrack(TrackingMDRef &X) {
assert(MD == X.MD && "Expected values to match");
if (X.MD) {
@@ -101,15 +108,17 @@ template <class T> class TypedTrackingMDRef {
TrackingMDRef Ref;
public:
- TypedTrackingMDRef() {}
+ TypedTrackingMDRef() = default;
explicit TypedTrackingMDRef(T *MD) : Ref(static_cast<Metadata *>(MD)) {}
TypedTrackingMDRef(TypedTrackingMDRef &&X) : Ref(std::move(X.Ref)) {}
TypedTrackingMDRef(const TypedTrackingMDRef &X) : Ref(X.Ref) {}
+
TypedTrackingMDRef &operator=(TypedTrackingMDRef &&X) {
Ref = std::move(X.Ref);
return *this;
}
+
TypedTrackingMDRef &operator=(const TypedTrackingMDRef &X) {
Ref = X.Ref;
return *this;
@@ -162,4 +171,4 @@ template <class T> struct simplify_type<const TypedTrackingMDRef<T>> {
} // end namespace llvm
-#endif
+#endif // LLVM_IR_TRACKINGMDREF_H
diff --git a/include/llvm/IR/Type.h b/include/llvm/IR/Type.h
index 778ee06169f1..e6a0df937e9b 100644
--- a/include/llvm/IR/Type.h
+++ b/include/llvm/IR/Type.h
@@ -290,7 +290,11 @@ public:
/// If this is a vector type, return the element type, otherwise return
/// 'this'.
- Type *getScalarType() const LLVM_READONLY;
+ Type *getScalarType() const {
+ if (isVectorTy())
+ return getVectorElementType();
+ return const_cast<Type*>(this);
+ }
//===--------------------------------------------------------------------===//
// Type Iteration support.
@@ -423,7 +427,7 @@ private:
};
// Printing of types.
-static inline raw_ostream &operator<<(raw_ostream &OS, Type &T) {
+static inline raw_ostream &operator<<(raw_ostream &OS, const Type &T) {
T.print(OS);
return OS;
}
diff --git a/include/llvm/IR/TypeFinder.h b/include/llvm/IR/TypeFinder.h
index 046f85caec9d..48c4f1161aa1 100644
--- a/include/llvm/IR/TypeFinder.h
+++ b/include/llvm/IR/TypeFinder.h
@@ -1,4 +1,4 @@
-//===-- llvm/IR/TypeFinder.h - Class to find used struct types --*- C++ -*-===//
+//===- llvm/IR/TypeFinder.h - Class to find used struct types ---*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -15,8 +15,7 @@
#define LLVM_IR_TYPEFINDER_H
#include "llvm/ADT/DenseSet.h"
-#include "llvm/IR/Metadata.h"
-#include "llvm/IR/Type.h"
+#include <cstddef>
#include <vector>
namespace llvm {
@@ -24,6 +23,7 @@ namespace llvm {
class MDNode;
class Module;
class StructType;
+class Type;
class Value;
/// TypeFinder - Walk over a module, identifying all of the types that are
@@ -36,10 +36,10 @@ class TypeFinder {
DenseSet<Type*> VisitedTypes;
std::vector<StructType*> StructTypes;
- bool OnlyNamed;
+ bool OnlyNamed = false;
public:
- TypeFinder() : OnlyNamed(false) {}
+ TypeFinder() = default;
void run(const Module &M, bool onlyNamed);
void clear();
@@ -77,6 +77,6 @@ private:
void incorporateMDNode(const MDNode *V);
};
-} // end llvm namespace
+} // end namespace llvm
-#endif
+#endif // LLVM_IR_TYPEFINDER_H
diff --git a/include/llvm/IR/Use.h b/include/llvm/IR/Use.h
index ff6b2e1f1e22..05b68ccbb38e 100644
--- a/include/llvm/IR/Use.h
+++ b/include/llvm/IR/Use.h
@@ -85,7 +85,7 @@ public:
///
/// For an instruction operand, for example, this will return the
/// instruction.
- User *getUser() const;
+ User *getUser() const LLVM_READONLY;
inline void set(Value *Val);
@@ -111,7 +111,7 @@ public:
static void zap(Use *Start, const Use *Stop, bool del = false);
private:
- const Use *getImpliedUser() const;
+ const Use *getImpliedUser() const LLVM_READONLY;
Value *Val;
Use *Next;
diff --git a/include/llvm/IR/UseListOrder.h b/include/llvm/IR/UseListOrder.h
index efff208295b6..ebe99223facd 100644
--- a/include/llvm/IR/UseListOrder.h
+++ b/include/llvm/IR/UseListOrder.h
@@ -20,20 +20,19 @@
namespace llvm {
-class Module;
class Function;
class Value;
/// \brief Structure to hold a use-list order.
struct UseListOrder {
- const Value *V;
- const Function *F;
+ const Value *V = nullptr;
+ const Function *F = nullptr;
std::vector<unsigned> Shuffle;
UseListOrder(const Value *V, const Function *F, size_t ShuffleSize)
: V(V), F(F), Shuffle(ShuffleSize) {}
- UseListOrder() : V(nullptr), F(nullptr) {}
+ UseListOrder() = default;
UseListOrder(UseListOrder &&) = default;
UseListOrder &operator=(UseListOrder &&) = default;
};
diff --git a/include/llvm/IR/User.h b/include/llvm/IR/User.h
index c907d6b670b5..54758a9b6d6a 100644
--- a/include/llvm/IR/User.h
+++ b/include/llvm/IR/User.h
@@ -122,8 +122,16 @@ protected:
}
private:
+ const Use *getHungOffOperands() const {
+ return *(reinterpret_cast<const Use *const *>(this) - 1);
+ }
+
Use *&getHungOffOperands() { return *(reinterpret_cast<Use **>(this) - 1); }
+ const Use *getIntrusiveOperands() const {
+ return reinterpret_cast<const Use *>(this) - NumUserOperands;
+ }
+
Use *getIntrusiveOperands() {
return reinterpret_cast<Use *>(this) - NumUserOperands;
}
@@ -135,11 +143,11 @@ private:
}
public:
- Use *getOperandList() {
+ const Use *getOperandList() const {
return HasHungOffUses ? getHungOffOperands() : getIntrusiveOperands();
}
- const Use *getOperandList() const {
- return const_cast<User *>(this)->getOperandList();
+ Use *getOperandList() {
+ return const_cast<Use *>(static_cast<const User *>(this)->getOperandList());
}
Value *getOperand(unsigned i) const {
diff --git a/include/llvm/IR/Value.h b/include/llvm/IR/Value.h
index bdafbbf58cc4..a4b48d7f3539 100644
--- a/include/llvm/IR/Value.h
+++ b/include/llvm/IR/Value.h
@@ -294,7 +294,15 @@ public:
// when using them since you might not get all uses.
// The methods that don't start with materialized_ assert that modules is
// fully materialized.
- void assertModuleIsMaterialized() const;
+ void assertModuleIsMaterializedImpl() const;
+ // This indirection exists so we can keep assertModuleIsMaterializedImpl()
+ // around in release builds of Value.cpp to be linked with other code built
+ // in debug mode. But this avoids calling it in any of the release built code.
+ void assertModuleIsMaterialized() const {
+#ifndef NDEBUG
+ assertModuleIsMaterializedImpl();
+#endif
+ }
bool use_empty() const {
assertModuleIsMaterialized();
@@ -468,27 +476,30 @@ public:
///
/// Returns the original uncasted value. If this is called on a non-pointer
/// value, it returns 'this'.
- Value *stripPointerCasts();
- const Value *stripPointerCasts() const {
- return const_cast<Value*>(this)->stripPointerCasts();
+ const Value *stripPointerCasts() const;
+ Value *stripPointerCasts() {
+ return const_cast<Value *>(
+ static_cast<const Value *>(this)->stripPointerCasts());
}
/// \brief Strip off pointer casts and all-zero GEPs.
///
/// Returns the original uncasted value. If this is called on a non-pointer
/// value, it returns 'this'.
- Value *stripPointerCastsNoFollowAliases();
- const Value *stripPointerCastsNoFollowAliases() const {
- return const_cast<Value*>(this)->stripPointerCastsNoFollowAliases();
+ const Value *stripPointerCastsNoFollowAliases() const;
+ Value *stripPointerCastsNoFollowAliases() {
+ return const_cast<Value *>(
+ static_cast<const Value *>(this)->stripPointerCastsNoFollowAliases());
}
/// \brief Strip off pointer casts and all-constant inbounds GEPs.
///
/// Returns the original pointer value. If this is called on a non-pointer
/// value, it returns 'this'.
- Value *stripInBoundsConstantOffsets();
- const Value *stripInBoundsConstantOffsets() const {
- return const_cast<Value*>(this)->stripInBoundsConstantOffsets();
+ const Value *stripInBoundsConstantOffsets() const;
+ Value *stripInBoundsConstantOffsets() {
+ return const_cast<Value *>(
+ static_cast<const Value *>(this)->stripInBoundsConstantOffsets());
}
/// \brief Accumulate offsets from \a stripInBoundsConstantOffsets().
@@ -498,21 +509,22 @@ public:
/// correct bitwidth for an offset of this pointer type.
///
/// If this is called on a non-pointer value, it returns 'this'.
- Value *stripAndAccumulateInBoundsConstantOffsets(const DataLayout &DL,
- APInt &Offset);
const Value *stripAndAccumulateInBoundsConstantOffsets(const DataLayout &DL,
- APInt &Offset) const {
- return const_cast<Value *>(this)
- ->stripAndAccumulateInBoundsConstantOffsets(DL, Offset);
+ APInt &Offset) const;
+ Value *stripAndAccumulateInBoundsConstantOffsets(const DataLayout &DL,
+ APInt &Offset) {
+ return const_cast<Value *>(static_cast<const Value *>(this)
+ ->stripAndAccumulateInBoundsConstantOffsets(DL, Offset));
}
/// \brief Strip off pointer casts and inbounds GEPs.
///
/// Returns the original pointer value. If this is called on a non-pointer
/// value, it returns 'this'.
- Value *stripInBoundsOffsets();
- const Value *stripInBoundsOffsets() const {
- return const_cast<Value*>(this)->stripInBoundsOffsets();
+ const Value *stripInBoundsOffsets() const;
+ Value *stripInBoundsOffsets() {
+ return const_cast<Value *>(
+ static_cast<const Value *>(this)->stripInBoundsOffsets());
}
/// \brief Returns the number of bytes known to be dereferenceable for the
@@ -535,11 +547,12 @@ public:
/// the PHI node corresponding to PredBB. If not, return ourself. This is
/// useful if you want to know the value something has in a predecessor
/// block.
- Value *DoPHITranslation(const BasicBlock *CurBB, const BasicBlock *PredBB);
-
const Value *DoPHITranslation(const BasicBlock *CurBB,
- const BasicBlock *PredBB) const{
- return const_cast<Value*>(this)->DoPHITranslation(CurBB, PredBB);
+ const BasicBlock *PredBB) const;
+
+ Value *DoPHITranslation(const BasicBlock *CurBB, const BasicBlock *PredBB) {
+ return const_cast<Value *>(
+ static_cast<const Value *>(this)->DoPHITranslation(CurBB, PredBB));
}
/// \brief The maximum alignment for instructions.
diff --git a/include/llvm/IR/ValueHandle.h b/include/llvm/IR/ValueHandle.h
index a4d4893a9bc9..4838bac9e0f7 100644
--- a/include/llvm/IR/ValueHandle.h
+++ b/include/llvm/IR/ValueHandle.h
@@ -98,6 +98,15 @@ protected:
V != DenseMapInfo<Value *>::getTombstoneKey();
}
+ /// \brief Remove this ValueHandle from its current use list.
+ void RemoveFromUseList();
+
+ /// \brief Clear the underlying pointer without clearing the use list.
+ ///
+ /// This should only be used if a derived class has manually removed the
+ /// handle from the use list.
+ void clearValPtr() { V = nullptr; }
+
public:
// Callbacks made from Value.
static void ValueIsDeleted(Value *V);
@@ -120,8 +129,6 @@ private:
/// \brief Add this ValueHandle to the use list for V.
void AddToUseList();
- /// \brief Remove this ValueHandle from its current use list.
- void RemoveFromUseList();
};
/// \brief Value handle that is nullable, but tries to track the Value.
@@ -259,7 +266,6 @@ struct isPodLike<AssertingVH<T> > {
#endif
};
-
/// \brief Value handle that tracks a Value across RAUW.
///
/// TrackingVH is designed for situations where a client needs to hold a handle
@@ -370,6 +376,130 @@ public:
virtual void allUsesReplacedWith(Value *) {}
};
+/// Value handle that poisons itself if the Value is deleted.
+///
+/// This is a Value Handle that points to a value and poisons itself if the
+/// value is destroyed while the handle is still live. This is very useful for
+/// catching dangling pointer bugs where an \c AssertingVH cannot be used
+/// because the dangling handle needs to outlive the value without ever being
+/// used.
+///
+/// One particularly useful place to use this is as the Key of a map. Dangling
+/// pointer bugs often lead to really subtle bugs that only occur if another
+/// object happens to get allocated to the same address as the old one. Using
+/// a PoisoningVH ensures that an assert is triggered if looking up a new value
+/// in the map finds a handle from the old value.
+///
+/// Note that a PoisoningVH handle does *not* follow values across RAUW
+/// operations. This means that RAUW's need to explicitly update the
+/// PoisoningVH's as it moves. This is required because in non-assert mode this
+/// class turns into a trivial wrapper around a pointer.
+template <typename ValueTy>
+class PoisoningVH
+#ifndef NDEBUG
+ final : public CallbackVH
+#endif
+{
+ friend struct DenseMapInfo<PoisoningVH<ValueTy>>;
+
+ // Convert a ValueTy*, which may be const, to the raw Value*.
+ static Value *GetAsValue(Value *V) { return V; }
+ static Value *GetAsValue(const Value *V) { return const_cast<Value *>(V); }
+
+#ifndef NDEBUG
+ /// A flag tracking whether this value has been poisoned.
+ ///
+ /// On delete and RAUW, we leave the value pointer alone so that as a raw
+ /// pointer it produces the same value (and we fit into the same key of
+ /// a hash table, etc), but we poison the handle so that any top-level usage
+ /// will fail.
+ bool Poisoned = false;
+
+ Value *getRawValPtr() const { return ValueHandleBase::getValPtr(); }
+ void setRawValPtr(Value *P) { ValueHandleBase::operator=(P); }
+
+ /// Handle deletion by poisoning the handle.
+ void deleted() override {
+ assert(!Poisoned && "Tried to delete an already poisoned handle!");
+ Poisoned = true;
+ RemoveFromUseList();
+ }
+
+ /// Handle RAUW by poisoning the handle.
+ void allUsesReplacedWith(Value *) override {
+ assert(!Poisoned && "Tried to RAUW an already poisoned handle!");
+ Poisoned = true;
+ RemoveFromUseList();
+ }
+#else // NDEBUG
+ Value *ThePtr = nullptr;
+
+ Value *getRawValPtr() const { return ThePtr; }
+ void setRawValPtr(Value *P) { ThePtr = P; }
+#endif
+
+ ValueTy *getValPtr() const {
+ assert(!Poisoned && "Accessed a poisoned value handle!");
+ return static_cast<ValueTy *>(getRawValPtr());
+ }
+ void setValPtr(ValueTy *P) { setRawValPtr(GetAsValue(P)); }
+
+public:
+ PoisoningVH() = default;
+#ifndef NDEBUG
+ PoisoningVH(ValueTy *P) : CallbackVH(GetAsValue(P)) {}
+ PoisoningVH(const PoisoningVH &RHS)
+ : CallbackVH(RHS), Poisoned(RHS.Poisoned) {}
+ ~PoisoningVH() {
+ if (Poisoned)
+ clearValPtr();
+ }
+ PoisoningVH &operator=(const PoisoningVH &RHS) {
+ if (Poisoned)
+ clearValPtr();
+ CallbackVH::operator=(RHS);
+ Poisoned = RHS.Poisoned;
+ return *this;
+ }
+#else
+ PoisoningVH(ValueTy *P) : ThePtr(GetAsValue(P)) {}
+#endif
+
+ operator ValueTy *() const { return getValPtr(); }
+
+ ValueTy *operator->() const { return getValPtr(); }
+ ValueTy &operator*() const { return *getValPtr(); }
+};
+
+// Specialize DenseMapInfo to allow PoisoningVH to participate in DenseMap.
+template <typename T> struct DenseMapInfo<PoisoningVH<T>> {
+ static inline PoisoningVH<T> getEmptyKey() {
+ PoisoningVH<T> Res;
+ Res.setRawValPtr(DenseMapInfo<Value *>::getEmptyKey());
+ return Res;
+ }
+ static inline PoisoningVH<T> getTombstoneKey() {
+ PoisoningVH<T> Res;
+ Res.setRawValPtr(DenseMapInfo<Value *>::getTombstoneKey());
+ return Res;
+ }
+ static unsigned getHashValue(const PoisoningVH<T> &Val) {
+ return DenseMapInfo<Value *>::getHashValue(Val.getRawValPtr());
+ }
+ static bool isEqual(const PoisoningVH<T> &LHS, const PoisoningVH<T> &RHS) {
+ return DenseMapInfo<Value *>::isEqual(LHS.getRawValPtr(),
+ RHS.getRawValPtr());
+ }
+};
+
+template <typename T> struct isPodLike<PoisoningVH<T>> {
+#ifdef NDEBUG
+ static const bool value = true;
+#else
+ static const bool value = false;
+#endif
+};
+
} // End llvm namespace
#endif
diff --git a/include/llvm/IR/ValueSymbolTable.h b/include/llvm/IR/ValueSymbolTable.h
index 61a12db403ea..9e86751dae6f 100644
--- a/include/llvm/IR/ValueSymbolTable.h
+++ b/include/llvm/IR/ValueSymbolTable.h
@@ -1,4 +1,4 @@
-//===-- llvm/ValueSymbolTable.h - Implement a Value Symtab ------*- C++ -*-===//
+//===- llvm/ValueSymbolTable.h - Implement a Value Symtab -------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -15,31 +15,36 @@
#define LLVM_IR_VALUESYMBOLTABLE_H
#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/IR/Value.h"
-#include "llvm/Support/DataTypes.h"
+#include <cstdint>
namespace llvm {
- template <typename ValueSubClass> class SymbolTableListTraits;
- template <unsigned InternalLen> class SmallString;
- class BasicBlock;
- class Function;
- class NamedMDNode;
- class Module;
- class StringRef;
+
+class Argument;
+class BasicBlock;
+class Function;
+class GlobalAlias;
+class GlobalIFunc;
+class GlobalVariable;
+class Instruction;
+template <unsigned InternalLen> class SmallString;
+template <typename ValueSubClass> class SymbolTableListTraits;
/// This class provides a symbol table of name/value pairs. It is essentially
/// a std::map<std::string,Value*> but has a controlled interface provided by
/// LLVM as well as ensuring uniqueness of names.
///
class ValueSymbolTable {
- friend class Value;
friend class SymbolTableListTraits<Argument>;
friend class SymbolTableListTraits<BasicBlock>;
- friend class SymbolTableListTraits<Instruction>;
friend class SymbolTableListTraits<Function>;
- friend class SymbolTableListTraits<GlobalVariable>;
friend class SymbolTableListTraits<GlobalAlias>;
friend class SymbolTableListTraits<GlobalIFunc>;
+ friend class SymbolTableListTraits<GlobalVariable>;
+ friend class SymbolTableListTraits<Instruction>;
+ friend class Value;
+
/// @name Types
/// @{
public:
@@ -55,14 +60,14 @@ public:
/// @}
/// @name Constructors
/// @{
-public:
- ValueSymbolTable() : vmap(0), LastUnique(0) {}
+
+ ValueSymbolTable() : vmap(0) {}
~ValueSymbolTable();
/// @}
/// @name Accessors
/// @{
-public:
+
/// This method finds the value with the given \p Name in the
/// the symbol table.
/// @returns the value associated with the \p Name
@@ -84,7 +89,7 @@ public:
/// @}
/// @name Iteration
/// @{
-public:
+
/// @brief Get an iterator that from the beginning of the symbol table.
inline iterator begin() { return vmap.begin(); }
@@ -122,13 +127,13 @@ private:
/// @}
/// @name Internal Data
/// @{
-private:
+
ValueMap vmap; ///< The map that holds the symbol table.
- mutable uint32_t LastUnique; ///< Counter for tracking unique names
+ mutable uint32_t LastUnique = 0; ///< Counter for tracking unique names
/// @}
};
-} // End llvm namespace
+} // end namespace llvm
-#endif
+#endif // LLVM_IR_VALUESYMBOLTABLE_H
diff --git a/include/llvm/InitializePasses.h b/include/llvm/InitializePasses.h
index a34ebaf18a03..15c8ff6d04de 100644
--- a/include/llvm/InitializePasses.h
+++ b/include/llvm/InitializePasses.h
@@ -53,13 +53,13 @@ void initializeCoroutines(PassRegistry&);
void initializeCodeGen(PassRegistry&);
/// Initialize all passes linked into the GlobalISel library.
-void initializeGlobalISel(PassRegistry &Registry);
+void initializeGlobalISel(PassRegistry&);
/// Initialize all passes linked into the CodeGen library.
void initializeTarget(PassRegistry&);
void initializeAAEvalLegacyPassPass(PassRegistry&);
-void initializeAAResultsWrapperPassPass(PassRegistry &);
+void initializeAAResultsWrapperPassPass(PassRegistry&);
void initializeADCELegacyPassPass(PassRegistry&);
void initializeAddDiscriminatorsLegacyPassPass(PassRegistry&);
void initializeAddressSanitizerModulePass(PassRegistry&);
@@ -68,37 +68,39 @@ void initializeAliasSetPrinterPass(PassRegistry&);
void initializeAlignmentFromAssumptionsPass(PassRegistry&);
void initializeAlwaysInlinerLegacyPassPass(PassRegistry&);
void initializeArgPromotionPass(PassRegistry&);
-void initializeAssumptionCacheTrackerPass(PassRegistry &);
+void initializeAssumptionCacheTrackerPass(PassRegistry&);
void initializeAtomicExpandPass(PassRegistry&);
void initializeBBVectorizePass(PassRegistry&);
-void initializeBDCELegacyPassPass(PassRegistry &);
+void initializeBDCELegacyPassPass(PassRegistry&);
void initializeBarrierNoopPass(PassRegistry&);
void initializeBasicAAWrapperPassPass(PassRegistry&);
void initializeBlockExtractorPassPass(PassRegistry&);
void initializeBlockFrequencyInfoWrapperPassPass(PassRegistry&);
void initializeBoundsCheckingPass(PassRegistry&);
+void initializeBranchCoalescingPass(PassRegistry&);
void initializeBranchFolderPassPass(PassRegistry&);
void initializeBranchProbabilityInfoWrapperPassPass(PassRegistry&);
void initializeBranchRelaxationPass(PassRegistry&);
void initializeBreakCriticalEdgesPass(PassRegistry&);
+void initializeCFGOnlyPrinterLegacyPassPass(PassRegistry&);
void initializeCFGOnlyViewerLegacyPassPass(PassRegistry&);
void initializeCFGPrinterLegacyPassPass(PassRegistry&);
-void initializeCFGOnlyPrinterLegacyPassPass(PassRegistry&);
void initializeCFGSimplifyPassPass(PassRegistry&);
+void initializeLateCFGSimplifyPassPass(PassRegistry&);
void initializeCFGViewerLegacyPassPass(PassRegistry&);
void initializeCFLAndersAAWrapperPassPass(PassRegistry&);
void initializeCFLSteensAAWrapperPassPass(PassRegistry&);
void initializeCallGraphDOTPrinterPass(PassRegistry&);
void initializeCallGraphPrinterLegacyPassPass(PassRegistry&);
void initializeCallGraphViewerPass(PassRegistry&);
-void initializeCallGraphWrapperPassPass(PassRegistry &);
+void initializeCallGraphWrapperPassPass(PassRegistry&);
void initializeCodeGenPreparePass(PassRegistry&);
-void initializeCountingFunctionInserterPass(PassRegistry&);
void initializeConstantHoistingLegacyPassPass(PassRegistry&);
-void initializeConstantMergeLegacyPassPass(PassRegistry &);
+void initializeConstantMergeLegacyPassPass(PassRegistry&);
void initializeConstantPropagationPass(PassRegistry&);
void initializeCorrelatedValuePropagationPass(PassRegistry&);
void initializeCostModelAnalysisPass(PassRegistry&);
+void initializeCountingFunctionInserterPass(PassRegistry&);
void initializeCrossDSOCFIPass(PassRegistry&);
void initializeDAEPass(PassRegistry&);
void initializeDAHPass(PassRegistry&);
@@ -107,7 +109,7 @@ void initializeDSELegacyPassPass(PassRegistry&);
void initializeDataFlowSanitizerPass(PassRegistry&);
void initializeDeadInstEliminationPass(PassRegistry&);
void initializeDeadMachineInstructionElimPass(PassRegistry&);
-void initializeDelinearizationPass(PassRegistry &);
+void initializeDelinearizationPass(PassRegistry&);
void initializeDemandedBitsWrapperPassPass(PassRegistry&);
void initializeDependenceAnalysisPass(PassRegistry&);
void initializeDependenceAnalysisWrapperPassPass(PassRegistry&);
@@ -120,27 +122,27 @@ void initializeDomViewerPass(PassRegistry&);
void initializeDominanceFrontierWrapperPassPass(PassRegistry&);
void initializeDominatorTreeWrapperPassPass(PassRegistry&);
void initializeDwarfEHPreparePass(PassRegistry&);
-void initializeEarlyCSELegacyPassPass(PassRegistry &);
-void initializeEarlyCSEMemSSALegacyPassPass(PassRegistry &);
+void initializeEarlyCSELegacyPassPass(PassRegistry&);
+void initializeEarlyCSEMemSSALegacyPassPass(PassRegistry&);
void initializeEarlyIfConverterPass(PassRegistry&);
void initializeEdgeBundlesPass(PassRegistry&);
void initializeEfficiencySanitizerPass(PassRegistry&);
-void initializeEliminateAvailableExternallyLegacyPassPass(PassRegistry &);
-void initializeRAGreedyPass(PassRegistry&);
-void initializeGVNHoistLegacyPassPass(PassRegistry &);
+void initializeEliminateAvailableExternallyLegacyPassPass(PassRegistry&);
void initializeExpandISelPseudosPass(PassRegistry&);
void initializeExpandPostRAPass(PassRegistry&);
void initializeExternalAAWrapperPassPass(PassRegistry&);
+void initializeFEntryInserterPass(PassRegistry&);
void initializeFinalizeMachineBundlesPass(PassRegistry&);
void initializeFlattenCFGPassPass(PassRegistry&);
void initializeFloat2IntLegacyPassPass(PassRegistry&);
void initializeForceFunctionAttrsLegacyPassPass(PassRegistry&);
void initializeForwardControlFlowIntegrityPass(PassRegistry&);
-void initializeFuncletLayoutPass(PassRegistry &);
-void initializeFunctionImportLegacyPassPass(PassRegistry &);
+void initializeFuncletLayoutPass(PassRegistry&);
+void initializeFunctionImportLegacyPassPass(PassRegistry&);
void initializeGCMachineCodeAnalysisPass(PassRegistry&);
void initializeGCModuleInfoPass(PassRegistry&);
void initializeGCOVProfilerLegacyPassPass(PassRegistry&);
+void initializeGVNHoistLegacyPassPass(PassRegistry&);
void initializeGVNLegacyPassPass(PassRegistry&);
void initializeGlobalDCELegacyPassPass(PassRegistry&);
void initializeGlobalMergePass(PassRegistry&);
@@ -149,32 +151,35 @@ void initializeGlobalSplitPass(PassRegistry&);
void initializeGlobalsAAWrapperPassPass(PassRegistry&);
void initializeGuardWideningLegacyPassPass(PassRegistry&);
void initializeIPCPPass(PassRegistry&);
-void initializeIPSCCPLegacyPassPass(PassRegistry &);
-void initializeIRTranslatorPass(PassRegistry &);
+void initializeIPSCCPLegacyPassPass(PassRegistry&);
+void initializeIRTranslatorPass(PassRegistry&);
void initializeIVUsersWrapperPassPass(PassRegistry&);
void initializeIfConverterPass(PassRegistry&);
void initializeImplicitNullChecksPass(PassRegistry&);
void initializeIndVarSimplifyLegacyPassPass(PassRegistry&);
void initializeInductiveRangeCheckEliminationPass(PassRegistry&);
+void initializeInferAddressSpacesPass(PassRegistry&);
void initializeInferFunctionAttrsLegacyPassPass(PassRegistry&);
void initializeInlineCostAnalysisPass(PassRegistry&);
void initializeInstCountPass(PassRegistry&);
void initializeInstNamerPass(PassRegistry&);
void initializeInstSimplifierPass(PassRegistry&);
-void initializeInstrProfilingLegacyPassPass(PassRegistry &);
+void initializeInstrProfilingLegacyPassPass(PassRegistry&);
void initializeInstructionCombiningPassPass(PassRegistry&);
-void initializeInstructionSelectPass(PassRegistry &);
-void initializeInterleavedAccessPass(PassRegistry &);
+void initializeInstructionSelectPass(PassRegistry&);
+void initializeInterleavedAccessPass(PassRegistry&);
void initializeInternalizeLegacyPassPass(PassRegistry&);
void initializeIntervalPartitionPass(PassRegistry&);
void initializeJumpThreadingPass(PassRegistry&);
-void initializeLCSSAWrapperPassPass(PassRegistry&);
void initializeLCSSAVerificationPassPass(PassRegistry&);
-void initializeLegacyLICMPassPass(PassRegistry&);
-void initializeLegacyLoopSinkPassPass(PassRegistry&);
-void initializeLazyBranchProbabilityInfoPassPass(PassRegistry&);
+void initializeLCSSAWrapperPassPass(PassRegistry&);
void initializeLazyBlockFrequencyInfoPassPass(PassRegistry&);
+void initializeLazyBranchProbabilityInfoPassPass(PassRegistry&);
+void initializeLazyMachineBlockFrequencyInfoPassPass(PassRegistry&);
void initializeLazyValueInfoWrapperPassPass(PassRegistry&);
+void initializeLegacyLICMPassPass(PassRegistry&);
+void initializeLegacyLoopSinkPassPass(PassRegistry&);
+void initializeLazyValueInfoPrinterPass(PassRegistry&);
void initializeLegalizerPass(PassRegistry&);
void initializeLibCallsShrinkWrapLegacyPassPass(PassRegistry&);
void initializeLintPass(PassRegistry&);
@@ -185,20 +190,21 @@ void initializeLiveRegMatrixPass(PassRegistry&);
void initializeLiveStacksPass(PassRegistry&);
void initializeLiveVariablesPass(PassRegistry&);
void initializeLoadCombinePass(PassRegistry&);
-void initializeLoaderPassPass(PassRegistry&);
void initializeLoadStoreVectorizerPass(PassRegistry&);
+void initializeLoaderPassPass(PassRegistry&);
void initializeLocalStackSlotPassPass(PassRegistry&);
void initializeLoopAccessLegacyAnalysisPass(PassRegistry&);
-void initializeLoopDataPrefetchLegacyPassPass(PassRegistry &);
+void initializeLoopDataPrefetchLegacyPassPass(PassRegistry&);
void initializeLoopDeletionLegacyPassPass(PassRegistry&);
void initializeLoopDistributeLegacyPass(PassRegistry&);
void initializeLoopExtractorPass(PassRegistry&);
void initializeLoopIdiomRecognizeLegacyPassPass(PassRegistry&);
void initializeLoopInfoWrapperPassPass(PassRegistry&);
void initializeLoopInstSimplifyLegacyPassPass(PassRegistry&);
-void initializeLoopInterchangePass(PassRegistry &);
+void initializeLoopInterchangePass(PassRegistry&);
void initializeLoopLoadEliminationPass(PassRegistry&);
void initializeLoopPassPass(PassRegistry&);
+void initializeLoopPredicationLegacyPassPass(PassRegistry&);
void initializeLoopRerollPass(PassRegistry&);
void initializeLoopRotateLegacyPassPass(PassRegistry&);
void initializeLoopSimplifyCFGLegacyPassPass(PassRegistry&);
@@ -208,8 +214,8 @@ void initializeLoopUnrollPass(PassRegistry&);
void initializeLoopUnswitchPass(PassRegistry&);
void initializeLoopVectorizePass(PassRegistry&);
void initializeLoopVersioningLICMPass(PassRegistry&);
-void initializeLoopVersioningPassPass(PassRegistry &);
-void initializeLowerAtomicLegacyPassPass(PassRegistry &);
+void initializeLoopVersioningPassPass(PassRegistry&);
+void initializeLowerAtomicLegacyPassPass(PassRegistry&);
void initializeLowerEmuTLSPass(PassRegistry&);
void initializeLowerExpectIntrinsicPass(PassRegistry&);
void initializeLowerGuardIntrinsicLegacyPassPass(PassRegistry&);
@@ -223,7 +229,7 @@ void initializeMachineBlockPlacementPass(PassRegistry&);
void initializeMachineBlockPlacementStatsPass(PassRegistry&);
void initializeMachineBranchProbabilityInfoPass(PassRegistry&);
void initializeMachineCSEPass(PassRegistry&);
-void initializeMachineCombinerPass(PassRegistry &);
+void initializeMachineCombinerPass(PassRegistry&);
void initializeMachineCopyPropagationPass(PassRegistry&);
void initializeMachineDominanceFrontierPass(PassRegistry&);
void initializeMachineDominatorTreePass(PassRegistry&);
@@ -231,6 +237,8 @@ void initializeMachineFunctionPrinterPassPass(PassRegistry&);
void initializeMachineLICMPass(PassRegistry&);
void initializeMachineLoopInfoPass(PassRegistry&);
void initializeMachineModuleInfoPass(PassRegistry&);
+void initializeMachineOptimizationRemarkEmitterPassPass(PassRegistry&);
+void initializeMachineOutlinerPass(PassRegistry&);
void initializeMachinePipelinerPass(PassRegistry&);
void initializeMachinePostDominatorTreePass(PassRegistry&);
void initializeMachineRegionInfoPassPass(PassRegistry&);
@@ -242,17 +250,17 @@ void initializeMemCpyOptLegacyPassPass(PassRegistry&);
void initializeMemDepPrinterPass(PassRegistry&);
void initializeMemDerefPrinterPass(PassRegistry&);
void initializeMemoryDependenceWrapperPassPass(PassRegistry&);
+void initializeMemorySSAPrinterLegacyPassPass(PassRegistry&);
void initializeMemorySSAWrapperPassPass(PassRegistry&);
-void initializeMemorySSAPrinterLegacyPassPass(PassRegistry &);
void initializeMemorySanitizerPass(PassRegistry&);
void initializeMergeFunctionsPass(PassRegistry&);
-void initializeMergedLoadStoreMotionLegacyPassPass(PassRegistry &);
+void initializeMergedLoadStoreMotionLegacyPassPass(PassRegistry&);
void initializeMetaRenamerPass(PassRegistry&);
void initializeModuleDebugInfoPrinterPass(PassRegistry&);
-void initializeModuleSummaryIndexWrapperPassPass(PassRegistry &);
-void initializeNameAnonGlobalLegacyPassPass(PassRegistry &);
-void initializeNaryReassociateLegacyPassPass(PassRegistry &);
-void initializeNewGVNPass(PassRegistry&);
+void initializeModuleSummaryIndexWrapperPassPass(PassRegistry&);
+void initializeNameAnonGlobalLegacyPassPass(PassRegistry&);
+void initializeNaryReassociateLegacyPassPass(PassRegistry&);
+void initializeNewGVNLegacyPassPass(PassRegistry&);
void initializeObjCARCAAWrapperPassPass(PassRegistry&);
void initializeObjCARCAPElimPass(PassRegistry&);
void initializeObjCARCContractPass(PassRegistry&);
@@ -260,17 +268,18 @@ void initializeObjCARCExpandPass(PassRegistry&);
void initializeObjCARCOptPass(PassRegistry&);
void initializeOptimizationRemarkEmitterWrapperPassPass(PassRegistry&);
void initializeOptimizePHIsPass(PassRegistry&);
-void initializePAEvalPass(PassRegistry &);
+void initializePAEvalPass(PassRegistry&);
void initializePEIPass(PassRegistry&);
void initializePGOIndirectCallPromotionLegacyPassPass(PassRegistry&);
void initializePGOInstrumentationGenLegacyPassPass(PassRegistry&);
void initializePGOInstrumentationUseLegacyPassPass(PassRegistry&);
+void initializePGOMemOPSizeOptLegacyPassPass(PassRegistry&);
void initializePHIEliminationPass(PassRegistry&);
-void initializePhysicalRegisterUsageInfoPass(PassRegistry &);
-void initializePartialInlinerLegacyPassPass(PassRegistry &);
-void initializePartiallyInlineLibCallsLegacyPassPass(PassRegistry &);
-void initializePatchableFunctionPass(PassRegistry &);
+void initializePartialInlinerLegacyPassPass(PassRegistry&);
+void initializePartiallyInlineLibCallsLegacyPassPass(PassRegistry&);
+void initializePatchableFunctionPass(PassRegistry&);
void initializePeepholeOptimizerPass(PassRegistry&);
+void initializePhysicalRegisterUsageInfoPass(PassRegistry&);
void initializePlaceBackedgeSafepointsImplPass(PassRegistry&);
void initializePlaceSafepointsPass(PassRegistry&);
void initializePostDomOnlyPrinterPass(PassRegistry&);
@@ -283,15 +292,17 @@ void initializePostOrderFunctionAttrsLegacyPassPass(PassRegistry&);
void initializePostRAHazardRecognizerPass(PassRegistry&);
void initializePostRASchedulerPass(PassRegistry&);
void initializePreISelIntrinsicLoweringLegacyPassPass(PassRegistry&);
+void initializePredicateInfoPrinterLegacyPassPass(PassRegistry&);
void initializePrintBasicBlockPassPass(PassRegistry&);
void initializePrintFunctionPassWrapperPass(PassRegistry&);
void initializePrintModulePassWrapperPass(PassRegistry&);
void initializeProcessImplicitDefsPass(PassRegistry&);
-void initializeProfileSummaryInfoWrapperPassPass(PassRegistry &);
-void initializePromoteLegacyPassPass(PassRegistry &);
+void initializeProfileSummaryInfoWrapperPassPass(PassRegistry&);
+void initializePromoteLegacyPassPass(PassRegistry&);
void initializePruneEHPass(PassRegistry&);
+void initializeRAGreedyPass(PassRegistry&);
void initializeReassociateLegacyPassPass(PassRegistry&);
-void initializeRegBankSelectPass(PassRegistry &);
+void initializeRegBankSelectPass(PassRegistry&);
void initializeRegToMemPass(PassRegistry&);
void initializeRegionInfoPassPass(PassRegistry&);
void initializeRegionOnlyPrinterPass(PassRegistry&);
@@ -299,13 +310,12 @@ void initializeRegionOnlyViewerPass(PassRegistry&);
void initializeRegionPrinterPass(PassRegistry&);
void initializeRegionViewerPass(PassRegistry&);
void initializeRegisterCoalescerPass(PassRegistry&);
-void initializeStripGCRelocatesPass(PassRegistry&);
void initializeRenameIndependentSubregsPass(PassRegistry&);
-void initializeResetMachineFunctionPass(PassRegistry &);
+void initializeResetMachineFunctionPass(PassRegistry&);
void initializeReversePostOrderFunctionAttrsLegacyPassPass(PassRegistry&);
void initializeRewriteStatepointsForGCPass(PassRegistry&);
void initializeRewriteSymbolsLegacyPassPass(PassRegistry&);
-void initializeSCCPLegacyPassPass(PassRegistry &);
+void initializeSCCPLegacyPassPass(PassRegistry&);
void initializeSCEVAAWrapperPassPass(PassRegistry&);
void initializeSLPVectorizerPass(PassRegistry&);
void initializeSROALegacyPassPass(PassRegistry&);
@@ -315,9 +325,9 @@ void initializeSanitizerCoverageModulePass(PassRegistry&);
void initializeScalarEvolutionWrapperPassPass(PassRegistry&);
void initializeScalarizerPass(PassRegistry&);
void initializeScopedNoAliasAAWrapperPassPass(PassRegistry&);
-void initializeSeparateConstOffsetFromGEPPass(PassRegistry &);
+void initializeSeparateConstOffsetFromGEPPass(PassRegistry&);
void initializeShadowStackGCLoweringPass(PassRegistry&);
-void initializeShrinkWrapPass(PassRegistry &);
+void initializeShrinkWrapPass(PassRegistry&);
void initializeSimpleInlinerPass(PassRegistry&);
void initializeSingleLoopExtractorPass(PassRegistry&);
void initializeSinkingLegacyPassPass(PassRegistry&);
@@ -329,19 +339,20 @@ void initializeStackColoringPass(PassRegistry&);
void initializeStackMapLivenessPass(PassRegistry&);
void initializeStackProtectorPass(PassRegistry&);
void initializeStackSlotColoringPass(PassRegistry&);
-void initializeStraightLineStrengthReducePass(PassRegistry &);
+void initializeStraightLineStrengthReducePass(PassRegistry&);
void initializeStripDeadDebugInfoPass(PassRegistry&);
void initializeStripDeadPrototypesLegacyPassPass(PassRegistry&);
void initializeStripDebugDeclarePass(PassRegistry&);
+void initializeStripGCRelocatesPass(PassRegistry&);
void initializeStripNonDebugSymbolsPass(PassRegistry&);
void initializeStripNonLineTableDebugInfoPass(PassRegistry&);
void initializeStripSymbolsPass(PassRegistry&);
void initializeStructurizeCFGPass(PassRegistry&);
void initializeTailCallElimPass(PassRegistry&);
void initializeTailDuplicatePassPass(PassRegistry&);
-void initializeTargetLibraryInfoWrapperPassPass(PassRegistry &);
+void initializeTargetLibraryInfoWrapperPassPass(PassRegistry&);
void initializeTargetPassConfigPass(PassRegistry&);
-void initializeTargetTransformInfoWrapperPassPass(PassRegistry &);
+void initializeTargetTransformInfoWrapperPassPass(PassRegistry&);
void initializeThreadSanitizerPass(PassRegistry&);
void initializeTwoAddressInstructionPassPass(PassRegistry&);
void initializeTypeBasedAAWrapperPassPass(PassRegistry&);
@@ -352,11 +363,11 @@ void initializeUnreachableMachineBlockElimPass(PassRegistry&);
void initializeVerifierLegacyPassPass(PassRegistry&);
void initializeVirtRegMapPass(PassRegistry&);
void initializeVirtRegRewriterPass(PassRegistry&);
-void initializeWholeProgramDevirtPass(PassRegistry &);
+void initializeWholeProgramDevirtPass(PassRegistry&);
void initializeWinEHPreparePass(PassRegistry&);
-void initializeWriteBitcodePassPass(PassRegistry &);
-void initializeWriteThinLTOBitcodePass(PassRegistry &);
-void initializeXRayInstrumentationPass(PassRegistry &);
+void initializeWriteBitcodePassPass(PassRegistry&);
+void initializeWriteThinLTOBitcodePass(PassRegistry&);
+void initializeXRayInstrumentationPass(PassRegistry&);
}
#endif
diff --git a/include/llvm/LTO/Caching.h b/include/llvm/LTO/Caching.h
index 3b96bd1dc301..f5ec70e081c1 100644
--- a/include/llvm/LTO/Caching.h
+++ b/include/llvm/LTO/Caching.h
@@ -24,12 +24,19 @@ namespace lto {
/// This type defines the callback to add a pre-existing native object file
/// (e.g. in a cache).
///
-/// File callbacks must be thread safe.
-typedef std::function<void(unsigned Task, StringRef Path)> AddFileFn;
+/// MB->getBufferIdentifier() is a valid path for the file at the time that it
+/// was opened, but clients should prefer to access MB directly in order to
+/// avoid a potential race condition.
+///
+/// Buffer callbacks must be thread safe.
+typedef std::function<void(unsigned Task, std::unique_ptr<MemoryBuffer> MB)>
+ AddBufferFn;
/// Create a local file system cache which uses the given cache directory and
-/// file callback.
-NativeObjectCache localCache(std::string CacheDirectoryPath, AddFileFn AddFile);
+/// file callback. This function also creates the cache directory if it does not
+/// already exist.
+Expected<NativeObjectCache> localCache(StringRef CacheDirectoryPath,
+ AddBufferFn AddBuffer);
} // namespace lto
} // namespace llvm
diff --git a/include/llvm/LTO/Config.h b/include/llvm/LTO/Config.h
index 3aa48c9f7c28..ede6637dfa4d 100644
--- a/include/llvm/LTO/Config.h
+++ b/include/llvm/LTO/Config.h
@@ -17,6 +17,7 @@
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/Support/CodeGen.h"
+#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
#include <functional>
@@ -41,6 +42,7 @@ struct Config {
Reloc::Model RelocModel = Reloc::PIC_;
CodeModel::Model CodeModel = CodeModel::Default;
CodeGenOpt::Level CGOptLevel = CodeGenOpt::Default;
+ TargetMachine::CodeGenFileType CGFileType = TargetMachine::CGFT_ObjectFile;
unsigned OptLevel = 2;
bool DisableVerify = false;
@@ -68,6 +70,12 @@ struct Config {
/// Sample PGO profile path.
std::string SampleProfile;
+ /// Optimization remarks file path.
+ std::string RemarksFilename = "";
+
+ /// Whether to emit optimization remarks with hotness informations.
+ bool RemarksWithHotness = false;
+
bool ShouldDiscardValueNames = true;
DiagnosticHandlerFunction DiagHandler;
diff --git a/include/llvm/LTO/LTO.h b/include/llvm/LTO/LTO.h
index 78ac73a7418c..3772592757be 100644
--- a/include/llvm/LTO/LTO.h
+++ b/include/llvm/LTO/LTO.h
@@ -19,12 +19,14 @@
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringSet.h"
-#include "llvm/CodeGen/Analysis.h"
+#include "llvm/Analysis/ObjectUtils.h"
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/ModuleSummaryIndex.h"
#include "llvm/LTO/Config.h"
#include "llvm/Linker/IRMover.h"
-#include "llvm/Object/IRObjectFile.h"
+#include "llvm/Object/IRSymtab.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/ToolOutputFile.h"
#include "llvm/Support/thread.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Transforms/IPO/FunctionImport.h"
@@ -68,25 +70,35 @@ std::string getThinLTOOutputFile(const std::string &Path,
const std::string &OldPrefix,
const std::string &NewPrefix);
+/// Setup optimization remarks.
+Expected<std::unique_ptr<tool_output_file>>
+setupOptimizationRemarks(LLVMContext &Context, StringRef LTORemarksFilename,
+ bool LTOPassRemarksWithHotness, int Count = -1);
+
class LTO;
struct SymbolResolution;
class ThinBackendProc;
-/// An input file. This is a wrapper for ModuleSymbolTable that exposes only the
+/// An input file. This is a symbol table wrapper that only exposes the
/// information that an LTO client should need in order to do symbol resolution.
class InputFile {
+public:
+ class Symbol;
+
+private:
// FIXME: Remove LTO class friendship once we have bitcode symbol tables.
friend LTO;
InputFile() = default;
- // FIXME: Remove the LLVMContext once we have bitcode symbol tables.
- LLVMContext Ctx;
- struct InputModule;
- std::vector<InputModule> Mods;
- ModuleSymbolTable SymTab;
+ std::vector<BitcodeModule> Mods;
+ SmallVector<char, 0> Strtab;
+ std::vector<Symbol> Symbols;
- std::vector<StringRef> Comdats;
- DenseMap<const Comdat *, unsigned> ComdatMap;
+ // [begin, end) for each module
+ std::vector<std::pair<size_t, size_t>> ModuleSymIndices;
+
+ StringRef TargetTriple, SourceFileName, COFFLinkerOpts;
+ std::vector<StringRef> ComdatTable;
public:
~InputFile();
@@ -94,143 +106,52 @@ public:
/// Create an InputFile.
static Expected<std::unique_ptr<InputFile>> create(MemoryBufferRef Object);
- class symbol_iterator;
-
- /// This is a wrapper for ArrayRef<ModuleSymbolTable::Symbol>::iterator that
- /// exposes only the information that an LTO client should need in order to do
- /// symbol resolution.
- ///
- /// This object is ephemeral; it is only valid as long as an iterator obtained
- /// from symbols() refers to it.
- class Symbol {
- friend symbol_iterator;
+ /// The purpose of this class is to only expose the symbol information that an
+ /// LTO client should need in order to do symbol resolution.
+ class Symbol : irsymtab::Symbol {
friend LTO;
- ArrayRef<ModuleSymbolTable::Symbol>::iterator I;
- const ModuleSymbolTable &SymTab;
- const InputFile *File;
- uint32_t Flags;
- SmallString<64> Name;
-
- bool shouldSkip() {
- return !(Flags & object::BasicSymbolRef::SF_Global) ||
- (Flags & object::BasicSymbolRef::SF_FormatSpecific);
- }
-
- void skip() {
- ArrayRef<ModuleSymbolTable::Symbol>::iterator E = SymTab.symbols().end();
- while (I != E) {
- Flags = SymTab.getSymbolFlags(*I);
- if (!shouldSkip())
- break;
- ++I;
- }
- if (I == E)
- return;
-
- Name.clear();
- {
- raw_svector_ostream OS(Name);
- SymTab.printSymbolName(OS, *I);
- }
- }
-
- bool isGV() const { return I->is<GlobalValue *>(); }
- GlobalValue *getGV() const { return I->get<GlobalValue *>(); }
-
public:
- Symbol(ArrayRef<ModuleSymbolTable::Symbol>::iterator I,
- const ModuleSymbolTable &SymTab, const InputFile *File)
- : I(I), SymTab(SymTab), File(File) {
- skip();
- }
-
- /// Returns the mangled name of the global.
- StringRef getName() const { return Name; }
-
- uint32_t getFlags() const { return Flags; }
- GlobalValue::VisibilityTypes getVisibility() const {
- if (isGV())
- return getGV()->getVisibility();
- return GlobalValue::DefaultVisibility;
- }
- bool canBeOmittedFromSymbolTable() const {
- return isGV() && llvm::canBeOmittedFromSymbolTable(getGV());
- }
- bool isTLS() const {
- // FIXME: Expose a thread-local flag for module asm symbols.
- return isGV() && getGV()->isThreadLocal();
- }
-
- // Returns the index of the comdat this symbol is in or -1 if the symbol
- // is not in a comdat.
- // FIXME: We have to return Expected<int> because aliases point to an
- // arbitrary ConstantExpr and that might not actually be a constant. That
- // means we might not be able to find what an alias is aliased to and
- // so find its comdat.
- Expected<int> getComdatIndex() const;
-
- uint64_t getCommonSize() const {
- assert(Flags & object::BasicSymbolRef::SF_Common);
- if (!isGV())
- return 0;
- return getGV()->getParent()->getDataLayout().getTypeAllocSize(
- getGV()->getType()->getElementType());
- }
- unsigned getCommonAlignment() const {
- assert(Flags & object::BasicSymbolRef::SF_Common);
- if (!isGV())
- return 0;
- return getGV()->getAlignment();
- }
- };
-
- class symbol_iterator {
- Symbol Sym;
-
- public:
- symbol_iterator(ArrayRef<ModuleSymbolTable::Symbol>::iterator I,
- const ModuleSymbolTable &SymTab, const InputFile *File)
- : Sym(I, SymTab, File) {}
-
- symbol_iterator &operator++() {
- ++Sym.I;
- Sym.skip();
- return *this;
- }
-
- symbol_iterator operator++(int) {
- symbol_iterator I = *this;
- ++*this;
- return I;
- }
-
- const Symbol &operator*() const { return Sym; }
- const Symbol *operator->() const { return &Sym; }
-
- bool operator!=(const symbol_iterator &Other) const {
- return Sym.I != Other.Sym.I;
- }
+ Symbol(const irsymtab::Symbol &S) : irsymtab::Symbol(S) {}
+
+ using irsymtab::Symbol::isUndefined;
+ using irsymtab::Symbol::isCommon;
+ using irsymtab::Symbol::isWeak;
+ using irsymtab::Symbol::isIndirect;
+ using irsymtab::Symbol::getName;
+ using irsymtab::Symbol::getVisibility;
+ using irsymtab::Symbol::canBeOmittedFromSymbolTable;
+ using irsymtab::Symbol::isTLS;
+ using irsymtab::Symbol::getComdatIndex;
+ using irsymtab::Symbol::getCommonSize;
+ using irsymtab::Symbol::getCommonAlignment;
+ using irsymtab::Symbol::getCOFFWeakExternalFallback;
+ using irsymtab::Symbol::isExecutable;
};
/// A range over the symbols in this InputFile.
- iterator_range<symbol_iterator> symbols() {
- return llvm::make_range(
- symbol_iterator(SymTab.symbols().begin(), SymTab, this),
- symbol_iterator(SymTab.symbols().end(), SymTab, this));
- }
+ ArrayRef<Symbol> symbols() const { return Symbols; }
+
+ /// Returns linker options specified in the input file.
+ StringRef getCOFFLinkerOpts() const { return COFFLinkerOpts; }
/// Returns the path to the InputFile.
StringRef getName() const;
+ /// Returns the input file's target triple.
+ StringRef getTargetTriple() const { return TargetTriple; }
+
/// Returns the source file path specified at compile time.
- StringRef getSourceFileName() const;
+ StringRef getSourceFileName() const { return SourceFileName; }
// Returns a table with all the comdats used by this file.
- ArrayRef<StringRef> getComdatTable() const { return Comdats; }
+ ArrayRef<StringRef> getComdatTable() const { return ComdatTable; }
private:
- iterator_range<symbol_iterator> module_symbols(InputModule &IM);
+ ArrayRef<Symbol> module_symbols(unsigned I) const {
+ const auto &Indices = ModuleSymIndices[I];
+ return {Symbols.data() + Indices.first, Symbols.data() + Indices.second};
+ }
};
/// This class wraps an output stream for a native object. Most clients should
@@ -418,20 +339,20 @@ private:
// Global mapping from mangled symbol names to resolutions.
StringMap<GlobalResolution> GlobalResolutions;
- void addSymbolToGlobalRes(SmallPtrSet<GlobalValue *, 8> &Used,
- const InputFile::Symbol &Sym, SymbolResolution Res,
+ void addSymbolToGlobalRes(const InputFile::Symbol &Sym, SymbolResolution Res,
unsigned Partition);
// These functions take a range of symbol resolutions [ResI, ResE) and consume
// the resolutions used by a single input module by incrementing ResI. After
// these functions return, [ResI, ResE) will refer to the resolution range for
// the remaining modules in the InputFile.
- Error addModule(InputFile &Input, InputFile::InputModule &IM,
+ Error addModule(InputFile &Input, unsigned ModI,
const SymbolResolution *&ResI, const SymbolResolution *ResE);
- Error addRegularLTO(BitcodeModule BM, const SymbolResolution *&ResI,
+ Error addRegularLTO(BitcodeModule BM,
+ ArrayRef<InputFile::Symbol> Syms,
+ const SymbolResolution *&ResI,
const SymbolResolution *ResE);
- Error addThinLTO(BitcodeModule BM, Module &M,
- iterator_range<InputFile::symbol_iterator> Syms,
+ Error addThinLTO(BitcodeModule BM, ArrayRef<InputFile::Symbol> Syms,
const SymbolResolution *&ResI, const SymbolResolution *ResE);
Error runRegularLTO(AddStreamFn AddStream);
diff --git a/include/llvm/LTO/LTOBackend.h b/include/llvm/LTO/LTOBackend.h
index 933503afddc8..d4743f6940ff 100644
--- a/include/llvm/LTO/LTOBackend.h
+++ b/include/llvm/LTO/LTOBackend.h
@@ -34,14 +34,15 @@ class Target;
namespace lto {
-/// Runs a regular LTO backend.
+/// Runs a regular LTO backend. The regular LTO backend can also act as the
+/// regular LTO phase of ThinLTO, which may need to access the combined index.
Error backend(Config &C, AddStreamFn AddStream,
unsigned ParallelCodeGenParallelismLevel,
- std::unique_ptr<Module> M);
+ std::unique_ptr<Module> M, ModuleSummaryIndex &CombinedIndex);
/// Runs a ThinLTO backend.
Error thinBackend(Config &C, unsigned Task, AddStreamFn AddStream, Module &M,
- ModuleSummaryIndex &CombinedIndex,
+ const ModuleSummaryIndex &CombinedIndex,
const FunctionImporter::ImportMapTy &ImportList,
const GVSummaryMapTy &DefinedGlobals,
MapVector<StringRef, BitcodeModule> &ModuleMap);
diff --git a/include/llvm/LTO/legacy/LTOCodeGenerator.h b/include/llvm/LTO/legacy/LTOCodeGenerator.h
index f14682111280..952875fc854e 100644
--- a/include/llvm/LTO/legacy/LTOCodeGenerator.h
+++ b/include/llvm/LTO/legacy/LTOCodeGenerator.h
@@ -41,6 +41,7 @@
#include "llvm/ADT/StringSet.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/Module.h"
+#include "llvm/Support/Error.h"
#include "llvm/Support/ToolOutputFile.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
@@ -174,6 +175,10 @@ struct LTOCodeGenerator {
/// Calls \a verifyMergedModuleOnce().
bool compileOptimized(ArrayRef<raw_pwrite_stream *> Out);
+ /// Enable the Freestanding mode: indicate that the optimizer should not
+ /// assume builtins are present on the target.
+ void setFreestanding(bool Enabled) { Freestanding = Enabled; }
+
void setDiagnosticHandler(lto_diagnostic_handler_t, void *);
LLVMContext &getContext() { return Context; }
@@ -206,7 +211,6 @@ private:
void emitError(const std::string &ErrMsg);
void emitWarning(const std::string &ErrMsg);
- bool setupOptimizationRemarks();
void finishOptimizationRemarks();
LLVMContext &Context;
@@ -237,6 +241,7 @@ private:
bool ShouldRestoreGlobalsLinkage = false;
TargetMachine::CodeGenFileType FileType = TargetMachine::CGFT_ObjectFile;
std::unique_ptr<tool_output_file> DiagnosticOutputFile;
+ bool Freestanding = false;
};
}
#endif
diff --git a/include/llvm/LTO/legacy/ThinLTOCodeGenerator.h b/include/llvm/LTO/legacy/ThinLTOCodeGenerator.h
index 0cc3b26e9659..f9545333aabd 100644
--- a/include/llvm/LTO/legacy/ThinLTOCodeGenerator.h
+++ b/include/llvm/LTO/legacy/ThinLTOCodeGenerator.h
@@ -20,6 +20,7 @@
#include "llvm/ADT/StringSet.h"
#include "llvm/ADT/Triple.h"
#include "llvm/IR/ModuleSummaryIndex.h"
+#include "llvm/Support/CachePruning.h"
#include "llvm/Support/CodeGen.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Target/TargetOptions.h"
@@ -140,9 +141,7 @@ public:
struct CachingOptions {
std::string Path; // Path to the cache, empty to disable.
- int PruningInterval = 1200; // seconds, -1 to disable pruning.
- unsigned int Expiration = 7 * 24 * 3600; // seconds (1w default).
- unsigned MaxPercentageOfAvailableSpace = 75; // percentage.
+ CachePruningPolicy Policy;
};
/// Provide a path to a directory where to store the cached files for
@@ -153,14 +152,14 @@ public:
/// negative value (default) to disable pruning. A value of 0 will be ignored.
void setCachePruningInterval(int Interval) {
if (Interval)
- CacheOptions.PruningInterval = Interval;
+ CacheOptions.Policy.Interval = std::chrono::seconds(Interval);
}
/// Cache policy: expiration (in seconds) for an entry.
/// A value of 0 will be ignored.
void setCacheEntryExpiration(unsigned Expiration) {
if (Expiration)
- CacheOptions.Expiration = Expiration;
+ CacheOptions.Policy.Expiration = std::chrono::seconds(Expiration);
}
/**
@@ -178,7 +177,7 @@ public:
*/
void setMaxCacheSizeRelativeToAvailableSpace(unsigned Percentage) {
if (Percentage)
- CacheOptions.MaxPercentageOfAvailableSpace = Percentage;
+ CacheOptions.Policy.PercentageOfAvailableSpace = Percentage;
}
/**@}*/
@@ -206,6 +205,10 @@ public:
TMBuilder.Options = std::move(Options);
}
+ /// Enable the Freestanding mode: indicate that the optimizer should not
+ /// assume builtins are present on the target.
+ void setFreestanding(bool Enabled) { Freestanding = Enabled; }
+
/// CodeModel
void setCodePICModel(Optional<Reloc::Model> Model) {
TMBuilder.RelocModel = Model;
@@ -323,6 +326,10 @@ private:
/// importing or optimization.
bool CodeGenOnly = false;
+ /// Flag to indicate that the optimizer should not assume builtins are present
+ /// on the target.
+ bool Freestanding = false;
+
/// IR Optimization Level [0-3].
unsigned OptLevel = 3;
};
diff --git a/include/llvm/LinkAllPasses.h b/include/llvm/LinkAllPasses.h
index e50137f8e02e..39a86e838bde 100644
--- a/include/llvm/LinkAllPasses.h
+++ b/include/llvm/LinkAllPasses.h
@@ -75,6 +75,7 @@ namespace {
(void) llvm::createCallGraphDOTPrinterPass();
(void) llvm::createCallGraphViewerPass();
(void) llvm::createCFGSimplificationPass();
+ (void) llvm::createLateCFGSimplificationPass();
(void) llvm::createCFLAndersAAWrapperPass();
(void) llvm::createCFLSteensAAWrapperPass();
(void) llvm::createStructurizeCFGPass();
@@ -96,6 +97,7 @@ namespace {
(void) llvm::createPGOInstrumentationGenLegacyPass();
(void) llvm::createPGOInstrumentationUseLegacyPass();
(void) llvm::createPGOIndirectCallPromotionLegacyPass();
+ (void) llvm::createPGOMemOPSizeOptLegacyPass();
(void) llvm::createInstrProfilingLegacyPass();
(void) llvm::createFunctionImportPass();
(void) llvm::createFunctionInliningPass();
@@ -116,6 +118,7 @@ namespace {
(void) llvm::createLazyValueInfoPass();
(void) llvm::createLoopExtractorPass();
(void) llvm::createLoopInterchangePass();
+ (void) llvm::createLoopPredicationPass();
(void) llvm::createLoopSimplifyPass();
(void) llvm::createLoopSimplifyCFGPass();
(void) llvm::createLoopStrengthReducePass();
diff --git a/include/llvm/Linker/IRMover.h b/include/llvm/Linker/IRMover.h
index 2a187cbc42f5..235ada47cef4 100644
--- a/include/llvm/Linker/IRMover.h
+++ b/include/llvm/Linker/IRMover.h
@@ -71,15 +71,11 @@ public:
/// not present in ValuesToLink. The GlobalValue and a ValueAdder callback
/// are passed as an argument, and the callback is expected to be called
/// if the GlobalValue needs to be added to the \p ValuesToLink and linked.
- /// - \p LinkModuleInlineAsm is true if the ModuleInlineAsm string in Src
- /// should be linked with (concatenated into) the ModuleInlineAsm string
- /// for the destination module. It should be true for full LTO, but not
- /// when importing for ThinLTO, otherwise we can have duplicate symbols.
/// - \p IsPerformingImport is true when this IR link is to perform ThinLTO
/// function importing from Src.
Error move(std::unique_ptr<Module> Src, ArrayRef<GlobalValue *> ValuesToLink,
std::function<void(GlobalValue &GV, ValueAdder Add)> AddLazyFor,
- bool LinkModuleInlineAsm, bool IsPerformingImport);
+ bool IsPerformingImport);
Module &getModule() { return Composite; }
private:
diff --git a/include/llvm/Linker/Linker.h b/include/llvm/Linker/Linker.h
index b077c373326f..628e0112bd9d 100644
--- a/include/llvm/Linker/Linker.h
+++ b/include/llvm/Linker/Linker.h
@@ -10,6 +10,7 @@
#ifndef LLVM_LINKER_LINKER_H
#define LLVM_LINKER_LINKER_H
+#include "llvm/ADT/StringSet.h"
#include "llvm/Linker/IRMover.h"
namespace llvm {
@@ -29,10 +30,6 @@ public:
None = 0,
OverrideFromSrc = (1 << 0),
LinkOnlyNeeded = (1 << 1),
- InternalizeLinkedSymbols = (1 << 2),
- /// Don't force link referenced linkonce definitions, import declaration.
- DontForceLinkLinkonceODR = (1 << 3)
-
};
Linker(Module &M);
@@ -41,16 +38,20 @@ public:
///
/// Passing OverrideSymbols as true will have symbols from Src
/// shadow those in the Dest.
- /// For ThinLTO function importing/exporting the \p ModuleSummaryIndex
- /// is passed. If \p GlobalsToImport is provided, only the globals that
- /// are part of the set will be imported from the source module.
+ ///
+ /// Passing InternalizeCallback will have the linker call the function with
+ /// the new module and a list of global value names to be internalized by the
+ /// callback.
///
/// Returns true on error.
bool linkInModule(std::unique_ptr<Module> Src, unsigned Flags = Flags::None,
- DenseSet<const GlobalValue *> *GlobalsToImport = nullptr);
+ std::function<void(Module &, const StringSet<> &)>
+ InternalizeCallback = {});
static bool linkModules(Module &Dest, std::unique_ptr<Module> Src,
- unsigned Flags = Flags::None);
+ unsigned Flags = Flags::None,
+ std::function<void(Module &, const StringSet<> &)>
+ InternalizeCallback = {});
};
} // End llvm namespace
diff --git a/include/llvm/MC/ConstantPools.h b/include/llvm/MC/ConstantPools.h
index f0c445dbe59f..643902377dd3 100644
--- a/include/llvm/MC/ConstantPools.h
+++ b/include/llvm/MC/ConstantPools.h
@@ -11,15 +11,17 @@
//
//===----------------------------------------------------------------------===//
-
#ifndef LLVM_MC_CONSTANTPOOLS_H
#define LLVM_MC_CONSTANTPOOLS_H
+#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/SMLoc.h"
+#include <cstdint>
namespace llvm {
+
class MCContext;
class MCExpr;
class MCSection;
@@ -30,6 +32,7 @@ class MCSymbolRefExpr;
struct ConstantPoolEntry {
ConstantPoolEntry(MCSymbol *L, const MCExpr *Val, unsigned Sz, SMLoc Loc_)
: Label(L), Value(Val), Size(Sz), Loc(Loc_) {}
+
MCSymbol *Label;
const MCExpr *Value;
unsigned Size;
@@ -45,7 +48,7 @@ class ConstantPool {
public:
// Initialize a new empty constant pool
- ConstantPool() {}
+ ConstantPool() = default;
// Add a new entry to the constant pool in the next slot.
// \param Value is the new entry to put in the constant pool.
@@ -90,6 +93,7 @@ private:
ConstantPool *getConstantPool(MCSection *Section);
ConstantPool &getOrCreateConstantPool(MCSection *Section);
};
+
} // end namespace llvm
-#endif
+#endif // LLVM_MC_CONSTANTPOOLS_H
diff --git a/include/llvm/MC/MCAsmBackend.h b/include/llvm/MC/MCAsmBackend.h
index d4bdbcd2baa3..fb21e195b1df 100644
--- a/include/llvm/MC/MCAsmBackend.h
+++ b/include/llvm/MC/MCAsmBackend.h
@@ -1,4 +1,4 @@
-//===-- llvm/MC/MCAsmBackend.h - MC Asm Backend -----------------*- C++ -*-===//
+//===- llvm/MC/MCAsmBackend.h - MC Asm Backend ------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -12,35 +12,33 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/MC/MCDirectives.h"
#include "llvm/MC/MCFixup.h"
-#include "llvm/Support/DataTypes.h"
-#include "llvm/Support/ErrorHandling.h"
+#include <cstdint>
namespace llvm {
+
class MCAsmLayout;
class MCAssembler;
class MCCFIInstruction;
-class MCELFObjectTargetWriter;
struct MCFixupKindInfo;
class MCFragment;
class MCInst;
-class MCRelaxableFragment;
class MCObjectWriter;
-class MCSection;
+class MCRelaxableFragment;
class MCSubtargetInfo;
class MCValue;
class raw_pwrite_stream;
/// Generic interface to target specific assembler backends.
class MCAsmBackend {
- MCAsmBackend(const MCAsmBackend &) = delete;
- void operator=(const MCAsmBackend &) = delete;
-
protected: // Can only create subclasses.
MCAsmBackend();
public:
+ MCAsmBackend(const MCAsmBackend &) = delete;
+ MCAsmBackend &operator=(const MCAsmBackend &) = delete;
virtual ~MCAsmBackend();
/// lifetime management
@@ -73,9 +71,11 @@ public:
/// 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.
+ /// appropriate. Errors (such as an out of range fixup value) should be
+ /// reported via \p Ctx.
virtual void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize,
- uint64_t Value, bool IsPCRel) const = 0;
+ uint64_t Value, bool IsPCRel,
+ MCContext &Ctx) const = 0;
/// @}
@@ -136,6 +136,6 @@ public:
}
};
-} // End llvm namespace
+} // end namespace llvm
-#endif
+#endif // LLVM_MC_MCASMBACKEND_H
diff --git a/include/llvm/MC/MCAsmInfo.h b/include/llvm/MC/MCAsmInfo.h
index f898bf5288d6..bd2717de9960 100644
--- a/include/llvm/MC/MCAsmInfo.h
+++ b/include/llvm/MC/MCAsmInfo.h
@@ -16,20 +16,22 @@
#ifndef LLVM_MC_MCASMINFO_H
#define LLVM_MC_MCASMINFO_H
+#include "llvm/ADT/StringRef.h"
#include "llvm/MC/MCDirectives.h"
#include "llvm/MC/MCDwarf.h"
#include "llvm/MC/MCTargetOptions.h"
-#include <cassert>
#include <vector>
namespace llvm {
+
+class MCContext;
class MCExpr;
class MCSection;
class MCStreamer;
class MCSymbol;
-class MCContext;
namespace WinEH {
+
enum class EncodingType {
Invalid, /// Invalid
Alpha, /// Windows Alpha
@@ -40,11 +42,14 @@ enum class EncodingType {
X86, /// Windows x86, uses no CFI, just EH tables
MIPS = Alpha,
};
-}
+
+} // end namespace WinEH
namespace LCOMM {
+
enum LCOMMType { NoAlignment, ByteAlignment, Log2Alignment };
-}
+
+} // end namespace LCOMM
enum class DebugCompressionType {
DCT_None, // no compression
@@ -61,41 +66,41 @@ protected:
//
/// Pointer size in bytes. Default is 4.
- unsigned PointerSize;
+ unsigned PointerSize = 4;
/// Size of the stack slot reserved for callee-saved registers, in bytes.
/// Default is same as pointer size.
- unsigned CalleeSaveStackSlotSize;
+ unsigned CalleeSaveStackSlotSize = 4;
/// True if target is little endian. Default is true.
- bool IsLittleEndian;
+ bool IsLittleEndian = true;
/// True if target stack grow up. Default is false.
- bool StackGrowsUp;
+ bool StackGrowsUp = false;
/// True if this target has the MachO .subsections_via_symbols directive.
/// Default is false.
- bool HasSubsectionsViaSymbols;
+ bool HasSubsectionsViaSymbols = false;
/// True if this is a MachO target that supports the macho-specific .zerofill
/// directive for emitting BSS Symbols. Default is false.
- bool HasMachoZeroFillDirective;
+ bool HasMachoZeroFillDirective = false;
/// True if this is a MachO target that supports the macho-specific .tbss
/// directive for emitting thread local BSS Symbols. Default is false.
- bool HasMachoTBSSDirective;
+ bool HasMachoTBSSDirective = false;
/// This is the maximum possible length of an instruction, which is needed to
/// compute the size of an inline asm. Defaults to 4.
- unsigned MaxInstLength;
+ unsigned MaxInstLength = 4;
/// Every possible instruction length is a multiple of this value. Factored
/// out in .debug_frame and .debug_line. Defaults to 1.
- unsigned MinInstAlignment;
+ unsigned MinInstAlignment = 1;
/// The '$' token, when not referencing an identifier or constant, refers to
/// the current PC. Defaults to false.
- bool DollarIsPC;
+ bool DollarIsPC = false;
/// This string, if specified, is used to separate instructions from each
/// other when on the same line. Defaults to ';'
@@ -109,10 +114,10 @@ protected:
const char *LabelSuffix;
// Print the EH begin symbol with an assignment. Defaults to false.
- bool UseAssignmentForEHBegin;
+ bool UseAssignmentForEHBegin = false;
// Do we need to create a local symbol for .size?
- bool NeedsLocalForSize;
+ bool NeedsLocalForSize = false;
/// 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
@@ -142,20 +147,20 @@ protected:
const char *Code64Directive;
/// Which dialect of an assembler variant to use. Defaults to 0
- unsigned AssemblerDialect;
+ unsigned AssemblerDialect = 0;
/// This is true if the assembler allows @ characters in symbol names.
/// Defaults to false.
- bool AllowAtInName;
+ bool AllowAtInName = false;
/// If this is true, symbol names with invalid characters will be printed in
/// quotes.
- bool SupportsQuotedNames;
+ bool SupportsQuotedNames = true;
/// This is true if data region markers should be printed as
/// ".data_region/.end_data_region" directives. If false, use "$d/$a" labels
/// instead.
- bool UseDataRegionDirectives;
+ bool UseDataRegionDirectives = false;
//===--- Data Emission Directives -------------------------------------===//
@@ -185,13 +190,13 @@ protected:
/// If non-null, a directive that is used to emit a word which should be
/// relocated as a 64-bit GP-relative offset, e.g. .gpdword on Mips. Defaults
- /// to NULL.
- const char *GPRel64Directive;
+ /// to nullptr.
+ const char *GPRel64Directive = nullptr;
/// If non-null, a directive that is used to emit a word which should be
/// relocated as a 32-bit GP-relative offset, e.g. .gpword on Mips or .gprel32
- /// on Alpha. Defaults to NULL.
- const char *GPRel32Directive;
+ /// on Alpha. Defaults to nullptr.
+ const char *GPRel32Directive = nullptr;
/// If non-null, directives that are used to emit a word/dword which should
/// be relocated as a 32/64-bit DTP/TP-relative offset, e.g. .dtprelword/
@@ -204,14 +209,14 @@ protected:
/// This is true if this target uses "Sun Style" syntax for section switching
/// ("#alloc,#write" etc) instead of the normal ELF syntax (,"a,w") in
/// .section directives. Defaults to false.
- bool SunStyleELFSectionSwitchSyntax;
+ bool SunStyleELFSectionSwitchSyntax = false;
/// This is true if this target uses ELF '.section' directive before the
/// '.bss' one. It's used for PPC/Linux which doesn't support the '.bss'
/// directive only. Defaults to false.
- bool UsesELFSectionDirectiveForBSS;
+ bool UsesELFSectionDirectiveForBSS = false;
- bool NeedsDwarfSectionOffsetDirective;
+ bool NeedsDwarfSectionOffsetDirective = false;
//===--- Alignment Information ----------------------------------------===//
@@ -219,11 +224,11 @@ protected:
/// directives, where N is the number of bytes to align to. Otherwise, it
/// emits ".align log2(N)", e.g. 3 to align to an 8 byte boundary. Defaults
/// to true.
- bool AlignmentIsInBytes;
+ bool AlignmentIsInBytes = true;
/// If non-zero, this is used to fill the executable space created as the
/// result of a alignment directive. Defaults to 0
- unsigned TextAlignFillValue;
+ unsigned TextAlignFillValue = 0;
//===--- Global Variable Emission Directives --------------------------===//
@@ -236,7 +241,7 @@ protected:
/// uses a relocation but it can be suppressed by writing
/// a = f - g
/// .long a
- bool SetDirectiveSuppressesReloc;
+ bool SetDirectiveSuppressesReloc = false;
/// False if the assembler requires that we use
/// \code
@@ -251,98 +256,98 @@ protected:
/// \endcode
///
/// Defaults to true.
- bool HasAggressiveSymbolFolding;
+ bool HasAggressiveSymbolFolding = true;
/// True is .comm's and .lcomms optional alignment is to be specified in bytes
/// instead of log2(n). Defaults to true.
- bool COMMDirectiveAlignmentIsInBytes;
+ bool COMMDirectiveAlignmentIsInBytes = true;
/// Describes if the .lcomm directive for the target supports an alignment
/// argument and how it is interpreted. Defaults to NoAlignment.
- LCOMM::LCOMMType LCOMMDirectiveAlignmentType;
+ LCOMM::LCOMMType LCOMMDirectiveAlignmentType = LCOMM::NoAlignment;
// True if the target allows .align directives on functions. This is true for
// most targets, so defaults to true.
- bool HasFunctionAlignment;
+ bool HasFunctionAlignment = true;
/// True if the target has .type and .size directives, this is true for most
/// ELF targets. Defaults to true.
- bool HasDotTypeDotSizeDirective;
+ bool HasDotTypeDotSizeDirective = true;
/// True if the target has a single parameter .file directive, this is true
/// for ELF targets. Defaults to true.
- bool HasSingleParameterDotFile;
+ bool HasSingleParameterDotFile = true;
/// True if the target has a .ident directive, this is true for ELF targets.
/// Defaults to false.
- bool HasIdentDirective;
+ bool HasIdentDirective = false;
/// True if this target supports the MachO .no_dead_strip directive. Defaults
/// to false.
- bool HasNoDeadStrip;
+ bool HasNoDeadStrip = false;
/// True if this target supports the MachO .alt_entry directive. Defaults to
/// false.
- bool HasAltEntry;
+ bool HasAltEntry = false;
/// Used to declare a global as being a weak symbol. Defaults to ".weak".
const char *WeakDirective;
/// This directive, if non-null, is used to declare a global as being a weak
- /// undefined symbol. Defaults to NULL.
- const char *WeakRefDirective;
+ /// undefined symbol. Defaults to nullptr.
+ const char *WeakRefDirective = nullptr;
/// True if we have a directive to declare a global as being a weak defined
/// symbol. Defaults to false.
- bool HasWeakDefDirective;
+ bool HasWeakDefDirective = false;
/// True if we have a directive to declare a global as being a weak defined
/// symbol that can be hidden (unexported). Defaults to false.
- bool HasWeakDefCanBeHiddenDirective;
+ bool HasWeakDefCanBeHiddenDirective = false;
/// True if we have a .linkonce directive. This is used on cygwin/mingw.
/// Defaults to false.
- bool HasLinkOnceDirective;
+ bool HasLinkOnceDirective = false;
/// This attribute, if not MCSA_Invalid, is used to declare a symbol as having
/// hidden visibility. Defaults to MCSA_Hidden.
- MCSymbolAttr HiddenVisibilityAttr;
+ MCSymbolAttr HiddenVisibilityAttr = MCSA_Hidden;
/// This attribute, if not MCSA_Invalid, is used to declare an undefined
/// symbol as having hidden visibility. Defaults to MCSA_Hidden.
- MCSymbolAttr HiddenDeclarationVisibilityAttr;
+ MCSymbolAttr HiddenDeclarationVisibilityAttr = MCSA_Hidden;
/// This attribute, if not MCSA_Invalid, is used to declare a symbol as having
/// protected visibility. Defaults to MCSA_Protected
- MCSymbolAttr ProtectedVisibilityAttr;
+ MCSymbolAttr ProtectedVisibilityAttr = MCSA_Protected;
//===--- Dwarf Emission Directives -----------------------------------===//
/// True if target supports emission of debugging information. Defaults to
/// false.
- bool SupportsDebugInformation;
+ bool SupportsDebugInformation = false;
/// Exception handling format for the target. Defaults to None.
- ExceptionHandling ExceptionsType;
+ ExceptionHandling ExceptionsType = ExceptionHandling::None;
/// Windows exception handling data (.pdata) encoding. Defaults to Invalid.
- WinEH::EncodingType WinEHEncodingType;
+ WinEH::EncodingType WinEHEncodingType = WinEH::EncodingType::Invalid;
/// True if Dwarf2 output generally uses relocations for references to other
/// .debug_* sections.
- bool DwarfUsesRelocationsAcrossSections;
+ bool DwarfUsesRelocationsAcrossSections = true;
/// True if DWARF FDE symbol reference relocations should be replaced by an
/// absolute difference.
- bool DwarfFDESymbolsUseAbsDiff;
+ bool DwarfFDESymbolsUseAbsDiff = false;
/// True if dwarf register numbers are printed instead of symbolic register
/// names in .cfi_* directives. Defaults to false.
- bool DwarfRegNumForCFI;
+ bool DwarfRegNumForCFI = false;
/// True if target uses parens to indicate the symbol variant instead of @.
/// For example, foo(plt) instead of foo@plt. Defaults to false.
- bool UseParensForSymbolVariant;
+ bool UseParensForSymbolVariant = false;
//===--- Prologue State ----------------------------------------------===//
@@ -361,11 +366,11 @@ protected:
bool PreserveAsmComments;
/// Compress DWARF debug sections. Defaults to no compression.
- DebugCompressionType CompressDebugSections;
+ DebugCompressionType CompressDebugSections = DebugCompressionType::DCT_None;
/// True if the integrated assembler should interpret 'a >> b' constant
/// expressions as logical rather than arithmetic.
- bool UseLogicalShr;
+ bool UseLogicalShr = true;
// If true, emit GOTPCRELX/REX_GOTPCRELX instead of GOTPCREL, on
// X86_64 ELF.
@@ -475,14 +480,17 @@ public:
bool needsLocalForSize() const { return NeedsLocalForSize; }
StringRef getPrivateGlobalPrefix() const { return PrivateGlobalPrefix; }
StringRef getPrivateLabelPrefix() const { return PrivateLabelPrefix; }
+
bool hasLinkerPrivateGlobalPrefix() const {
return LinkerPrivateGlobalPrefix[0] != '\0';
}
+
StringRef getLinkerPrivateGlobalPrefix() const {
if (hasLinkerPrivateGlobalPrefix())
return LinkerPrivateGlobalPrefix;
return getPrivateGlobalPrefix();
}
+
const char *getInlineAsmStart() const { return InlineAsmStart; }
const char *getInlineAsmEnd() const { return InlineAsmEnd; }
const char *getCode16Directive() const { return Code16Directive; }
@@ -491,25 +499,32 @@ public:
unsigned getAssemblerDialect() const { return AssemblerDialect; }
bool doesAllowAtInName() const { return AllowAtInName; }
bool supportsNameQuoting() const { return SupportsQuotedNames; }
+
bool doesSupportDataRegionDirectives() const {
return UseDataRegionDirectives;
}
+
const char *getZeroDirective() const { return ZeroDirective; }
const char *getAsciiDirective() const { return AsciiDirective; }
const char *getAscizDirective() const { return AscizDirective; }
bool getAlignmentIsInBytes() const { return AlignmentIsInBytes; }
unsigned getTextAlignFillValue() const { return TextAlignFillValue; }
const char *getGlobalDirective() const { return GlobalDirective; }
+
bool doesSetDirectiveSuppressReloc() const {
return SetDirectiveSuppressesReloc;
}
+
bool hasAggressiveSymbolFolding() const { return HasAggressiveSymbolFolding; }
+
bool getCOMMDirectiveAlignmentIsInBytes() const {
return COMMDirectiveAlignmentIsInBytes;
}
+
LCOMM::LCOMMType getLCOMMDirectiveAlignmentType() const {
return LCOMMDirectiveAlignmentType;
}
+
bool hasFunctionAlignment() const { return HasFunctionAlignment; }
bool hasDotTypeDotSizeDirective() const { return HasDotTypeDotSizeDirective; }
bool hasSingleParameterDotFile() const { return HasSingleParameterDotFile; }
@@ -519,22 +534,29 @@ public:
const char *getWeakDirective() const { return WeakDirective; }
const char *getWeakRefDirective() const { return WeakRefDirective; }
bool hasWeakDefDirective() const { return HasWeakDefDirective; }
+
bool hasWeakDefCanBeHiddenDirective() const {
return HasWeakDefCanBeHiddenDirective;
}
+
bool hasLinkOnceDirective() const { return HasLinkOnceDirective; }
MCSymbolAttr getHiddenVisibilityAttr() const { return HiddenVisibilityAttr; }
+
MCSymbolAttr getHiddenDeclarationVisibilityAttr() const {
return HiddenDeclarationVisibilityAttr;
}
+
MCSymbolAttr getProtectedVisibilityAttr() const {
return ProtectedVisibilityAttr;
}
+
bool doesSupportDebugInformation() const { return SupportsDebugInformation; }
+
bool doesSupportExceptionHandling() const {
return ExceptionsType != ExceptionHandling::None;
}
+
ExceptionHandling getExceptionHandlingType() const { return ExceptionsType; }
WinEH::EncodingType getWinEHEncodingType() const { return WinEHEncodingType; }
@@ -558,6 +580,7 @@ public:
bool doesDwarfUseRelocationsAcrossSections() const {
return DwarfUsesRelocationsAcrossSections;
}
+
bool doDwarfFDESymbolsUseAbsDiff() const { return DwarfFDESymbolsUseAbsDiff; }
bool useDwarfRegNumForCFI() const { return DwarfRegNumForCFI; }
bool useParensForSymbolVariant() const { return UseParensForSymbolVariant; }
@@ -600,6 +623,7 @@ public:
void setRelaxELFRelocations(bool V) { RelaxELFRelocations = V; }
bool hasMipsExpressions() const { return HasMipsExpressions; }
};
-}
-#endif
+} // end namespace llvm
+
+#endif // LLVM_MC_MCASMINFO_H
diff --git a/include/llvm/MC/MCAsmInfoCOFF.h b/include/llvm/MC/MCAsmInfoCOFF.h
index 56444f3c7cf5..01c8ae49a6fc 100644
--- a/include/llvm/MC/MCAsmInfoCOFF.h
+++ b/include/llvm/MC/MCAsmInfoCOFF.h
@@ -1,4 +1,4 @@
-//===-- MCAsmInfoCOFF.h - COFF asm properties -------------------*- C++ -*-===//
+//===- MCAsmInfoCOFF.h - COFF asm properties --------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -13,24 +13,28 @@
#include "llvm/MC/MCAsmInfo.h"
namespace llvm {
- class MCAsmInfoCOFF : public MCAsmInfo {
- virtual void anchor();
- protected:
- explicit MCAsmInfoCOFF();
- };
-
- class MCAsmInfoMicrosoft : public MCAsmInfoCOFF {
- void anchor() override;
- protected:
- explicit MCAsmInfoMicrosoft();
- };
-
- class MCAsmInfoGNUCOFF : public MCAsmInfoCOFF {
- void anchor() override;
- protected:
- explicit MCAsmInfoGNUCOFF();
- };
-}
+class MCAsmInfoCOFF : public MCAsmInfo {
+ virtual void anchor();
+
+protected:
+ explicit MCAsmInfoCOFF();
+};
+
+class MCAsmInfoMicrosoft : public MCAsmInfoCOFF {
+ void anchor() override;
+
+protected:
+ explicit MCAsmInfoMicrosoft();
+};
+
+class MCAsmInfoGNUCOFF : public MCAsmInfoCOFF {
+ void anchor() override;
+
+protected:
+ explicit MCAsmInfoGNUCOFF();
+};
+
+} // end namespace llvm
#endif // LLVM_MC_MCASMINFOCOFF_H
diff --git a/include/llvm/MC/MCAsmInfoDarwin.h b/include/llvm/MC/MCAsmInfoDarwin.h
index d587c3ce9d54..a533d604a89e 100644
--- a/include/llvm/MC/MCAsmInfoDarwin.h
+++ b/include/llvm/MC/MCAsmInfoDarwin.h
@@ -1,4 +1,4 @@
-//===---- MCAsmInfoDarwin.h - Darwin asm properties -------------*- C++ -*-===//
+//===- MCAsmInfoDarwin.h - Darwin asm properties ----------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -18,12 +18,14 @@
#include "llvm/MC/MCAsmInfo.h"
namespace llvm {
- class MCAsmInfoDarwin : public MCAsmInfo {
- public:
- explicit MCAsmInfoDarwin();
- bool isSectionAtomizableBySymbols(const MCSection &Section) const override;
- };
-}
+class MCAsmInfoDarwin : public MCAsmInfo {
+public:
+ explicit MCAsmInfoDarwin();
+
+ bool isSectionAtomizableBySymbols(const MCSection &Section) const override;
+};
+
+} // end namespace llvm
#endif // LLVM_MC_MCASMINFODARWIN_H
diff --git a/include/llvm/MC/MCAsmInfoELF.h b/include/llvm/MC/MCAsmInfoELF.h
index f8bb943aac4e..f113afc9885e 100644
--- a/include/llvm/MC/MCAsmInfoELF.h
+++ b/include/llvm/MC/MCAsmInfoELF.h
@@ -1,4 +1,4 @@
-//===-- llvm/MC/MCAsmInfoELF.h - ELF Asm info -------------------*- C++ -*-===//
+//===- llvm/MC/MCAsmInfoELF.h - ELF Asm info --------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -13,6 +13,7 @@
#include "llvm/MC/MCAsmInfo.h"
namespace llvm {
+
class MCAsmInfoELF : public MCAsmInfo {
virtual void anchor();
MCSection *getNonexecutableStackSection(MCContext &Ctx) const final;
@@ -20,10 +21,11 @@ class MCAsmInfoELF : public MCAsmInfo {
protected:
/// Targets which have non-executable stacks by default can set this to false
/// to disable the special section which requests a non-executable stack.
- bool UsesNonexecutableStackSection;
+ bool UsesNonexecutableStackSection = true;
MCAsmInfoELF();
};
-}
-#endif
+} // end namespace llvm
+
+#endif // LLVM_MC_MCASMINFOELF_H
diff --git a/include/llvm/MC/MCAsmInfoWasm.h b/include/llvm/MC/MCAsmInfoWasm.h
new file mode 100644
index 000000000000..bc46cfdf4c4c
--- /dev/null
+++ b/include/llvm/MC/MCAsmInfoWasm.h
@@ -0,0 +1,24 @@
+//===-- llvm/MC/MCAsmInfoWasm.h - Wasm Asm 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_MC_MCASMINFOWASM_H
+#define LLVM_MC_MCASMINFOWASM_H
+
+#include "llvm/MC/MCAsmInfo.h"
+
+namespace llvm {
+class MCAsmInfoWasm : public MCAsmInfo {
+ virtual void anchor();
+
+protected:
+ MCAsmInfoWasm();
+};
+}
+
+#endif
diff --git a/include/llvm/MC/MCAssembler.h b/include/llvm/MC/MCAssembler.h
index 641e78994768..c29abaa03a6d 100644
--- a/include/llvm/MC/MCAssembler.h
+++ b/include/llvm/MC/MCAssembler.h
@@ -10,33 +10,35 @@
#ifndef LLVM_MC_MCASSEMBLER_H
#define LLVM_MC_MCASSEMBLER_H
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/SmallPtrSet.h"
-#include "llvm/ADT/ilist.h"
-#include "llvm/ADT/ilist_node.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/iterator.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/MC/MCDirectives.h"
#include "llvm/MC/MCDwarf.h"
#include "llvm/MC/MCFixup.h"
#include "llvm/MC/MCFragment.h"
-#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCLinkerOptimizationHint.h"
-#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/MCSymbol.h"
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <string>
+#include <utility>
+#include <vector>
namespace llvm {
-class raw_ostream;
+
+class MCAsmBackend;
class MCAsmLayout;
-class MCAssembler;
class MCContext;
class MCCodeEmitter;
-class MCExpr;
class MCFragment;
class MCObjectWriter;
class MCSection;
-class MCSubtargetInfo;
class MCValue;
-class MCAsmBackend;
// FIXME: This really doesn't belong here. See comments below.
struct IndirectSymbolData {
@@ -90,9 +92,6 @@ public:
} VersionMinInfoType;
private:
- MCAssembler(const MCAssembler &) = delete;
- void operator=(const MCAssembler &) = delete;
-
MCContext &Context;
MCAsmBackend &Backend;
@@ -131,9 +130,9 @@ private:
/// By default it's 0, which means bundling is disabled.
unsigned BundleAlignSize;
- unsigned RelaxAll : 1;
- unsigned SubsectionsViaSymbols : 1;
- unsigned IncrementalLinkerCompatible : 1;
+ bool RelaxAll : 1;
+ bool SubsectionsViaSymbols : 1;
+ bool IncrementalLinkerCompatible : 1;
/// ELF specific e_header flags
// It would be good if there were an MCELFAssembler class to hold this.
@@ -148,7 +147,6 @@ private:
VersionMinInfoType VersionMinInfo;
-private:
/// Evaluate a fixup to a relocatable expression and the value which should be
/// placed into the fixup.
///
@@ -201,6 +199,18 @@ private:
MCFragment &F, const MCFixup &Fixup);
public:
+ /// Construct a new assembler instance.
+ //
+ // FIXME: How are we going to parameterize this? Two obvious options are stay
+ // concrete and require clients to pass in a target like object. The other
+ // option is to make this abstract, and have targets provide concrete
+ // implementations as we do with AsmParser.
+ MCAssembler(MCContext &Context, MCAsmBackend &Backend,
+ MCCodeEmitter &Emitter, MCObjectWriter &Writer);
+ MCAssembler(const MCAssembler &) = delete;
+ MCAssembler &operator=(const MCAssembler &) = delete;
+ ~MCAssembler();
+
/// Compute the effective fragment size assuming it is laid out at the given
/// \p SectionAddress and \p FragmentOffset.
uint64_t computeFragmentSize(const MCAsmLayout &Layout,
@@ -240,17 +250,6 @@ public:
VersionMinInfo.Update = Update;
}
-public:
- /// Construct a new assembler instance.
- //
- // FIXME: How are we going to parameterize this? Two obvious options are stay
- // concrete and require clients to pass in a target like object. The other
- // option is to make this abstract, and have targets provide concrete
- // implementations as we do with AsmParser.
- MCAssembler(MCContext &Context, MCAsmBackend &Backend,
- MCCodeEmitter &Emitter, MCObjectWriter &Writer);
- ~MCAssembler();
-
/// Reuse an assembler instance
///
void reset();
@@ -425,4 +424,4 @@ uint64_t computeBundlePadding(const MCAssembler &Assembler, const MCFragment *F,
} // end namespace llvm
-#endif
+#endif // LLVM_MC_MCASSEMBLER_H
diff --git a/include/llvm/MC/MCCodeEmitter.h b/include/llvm/MC/MCCodeEmitter.h
index b6c19150c12a..f1b0b784a2df 100644
--- a/include/llvm/MC/MCCodeEmitter.h
+++ b/include/llvm/MC/MCCodeEmitter.h
@@ -1,4 +1,4 @@
-//===-- llvm/MC/MCCodeEmitter.h - Instruction Encoding ----------*- C++ -*-===//
+//===- llvm/MC/MCCodeEmitter.h - Instruction Encoding -----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -10,9 +10,8 @@
#ifndef LLVM_MC_MCCODEEMITTER_H
#define LLVM_MC_MCCODEEMITTER_H
-#include "llvm/Support/Compiler.h"
-
namespace llvm {
+
class MCFixup;
class MCInst;
class MCSubtargetInfo;
@@ -21,14 +20,12 @@ template<typename T> class SmallVectorImpl;
/// MCCodeEmitter - Generic instruction encoding interface.
class MCCodeEmitter {
-private:
- MCCodeEmitter(const MCCodeEmitter &) = delete;
- void operator=(const MCCodeEmitter &) = delete;
-
protected: // Can only create subclasses.
MCCodeEmitter();
public:
+ MCCodeEmitter(const MCCodeEmitter &) = delete;
+ MCCodeEmitter &operator=(const MCCodeEmitter &) = delete;
virtual ~MCCodeEmitter();
/// Lifetime management
@@ -41,6 +38,6 @@ public:
const MCSubtargetInfo &STI) const = 0;
};
-} // End llvm namespace
+} // end namespace llvm
-#endif
+#endif // LLVM_MC_MCCODEEMITTER_H
diff --git a/include/llvm/MC/MCContext.h b/include/llvm/MC/MCContext.h
index f846b632f112..b3106936e27f 100644
--- a/include/llvm/MC/MCContext.h
+++ b/include/llvm/MC/MCContext.h
@@ -15,6 +15,7 @@
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include "llvm/MC/MCDwarf.h"
#include "llvm/MC/MCSubtargetInfo.h"
@@ -23,35 +24,37 @@
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Dwarf.h"
#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
#include <map>
-#include <tuple>
-#include <vector> // FIXME: Shouldn't be needed.
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
namespace llvm {
+
+ class CodeViewContext;
class MCAsmInfo;
- class MCExpr;
- class MCSection;
- class MCSymbol;
- class MCSymbolELF;
class MCLabel;
- struct MCDwarfFile;
- class MCDwarfLoc;
class MCObjectFileInfo;
class MCRegisterInfo;
- class MCLineSection;
- class SMLoc;
- class MCSectionMachO;
- class MCSectionELF;
+ class MCSection;
class MCSectionCOFF;
- class CodeViewContext;
+ class MCSectionELF;
+ class MCSectionMachO;
+ class MCSectionWasm;
+ class MCSymbol;
+ class MCSymbolELF;
+ class MCSymbolWasm;
+ class SMLoc;
/// Context object for machine code objects. This class owns all of the
/// sections that it creates.
///
class MCContext {
- MCContext(const MCContext &) = delete;
- MCContext &operator=(const MCContext &) = delete;
-
public:
typedef StringMap<MCSymbol *, BumpPtrAllocator &> SymbolTable;
@@ -59,6 +62,9 @@ namespace llvm {
/// The SourceMgr for this object, if any.
const SourceMgr *SrcMgr;
+ /// The SourceMgr for inline assembly, if any.
+ SourceMgr *InlineSrcMgr;
+
/// The MCAsmInfo for this target.
const MCAsmInfo *MAI;
@@ -79,14 +85,11 @@ namespace llvm {
SpecificBumpPtrAllocator<MCSectionCOFF> COFFAllocator;
SpecificBumpPtrAllocator<MCSectionELF> ELFAllocator;
SpecificBumpPtrAllocator<MCSectionMachO> MachOAllocator;
+ SpecificBumpPtrAllocator<MCSectionWasm> WasmAllocator;
/// Bindings of names to symbols.
SymbolTable Symbols;
- /// Sections can have a corresponding symbol. This maps one to the
- /// other.
- DenseMap<const MCSection *, MCSymbol *> SectionSymbols;
-
/// A mapping from a local label number and an instance count to a symbol.
/// For example, in the assembly
/// 1:
@@ -123,7 +126,7 @@ namespace llvm {
/// Boolean toggled when .secure_log_unique / .secure_log_reset is seen to
/// catch errors if .secure_log_unique appears twice without
/// .secure_log_reset appearing between them.
- bool SecureLogUsed;
+ bool SecureLogUsed = false;
/// The compilation directory to use for DW_AT_comp_dir.
SmallString<128> CompilationDir;
@@ -139,14 +142,14 @@ namespace llvm {
/// The current dwarf line information from the last dwarf .loc directive.
MCDwarfLoc CurrentDwarfLoc;
- bool DwarfLocSeen;
+ bool DwarfLocSeen = false;
/// Generate dwarf debugging info for assembly source files.
- bool GenDwarfForAssembly;
+ bool GenDwarfForAssembly = false;
/// The current dwarf file number when generate dwarf debugging info for
/// assembly source files.
- unsigned GenDwarfFileNumber;
+ unsigned GenDwarfFileNumber = 0;
/// Sections for generating the .debug_ranges and .debug_aranges sections.
SetVector<MCSection *> SectionsForRanges;
@@ -164,25 +167,27 @@ namespace llvm {
StringRef DwarfDebugProducer;
/// The maximum version of dwarf that we should emit.
- uint16_t DwarfVersion;
+ uint16_t DwarfVersion = 4;
/// Honor temporary labels, this is useful for debugging semantic
/// differences between temporary and non-temporary labels (primarily on
/// Darwin).
- bool AllowTemporaryLabels;
+ bool AllowTemporaryLabels = true;
bool UseNamesOnTempLabels = true;
/// The Compile Unit ID that we are currently processing.
- unsigned DwarfCompileUnitID;
+ unsigned DwarfCompileUnitID = 0;
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;
@@ -197,10 +202,12 @@ namespace llvm {
StringRef GroupName;
int SelectionKey;
unsigned UniqueID;
+
COFFSectionKey(StringRef SectionName, StringRef GroupName,
int SelectionKey, unsigned UniqueID)
: SectionName(SectionName), GroupName(GroupName),
SelectionKey(SelectionKey), UniqueID(UniqueID) {}
+
bool operator<(const COFFSectionKey &Other) const {
if (SectionName != Other.SectionName)
return SectionName < Other.SectionName;
@@ -212,17 +219,35 @@ namespace llvm {
}
};
+ struct WasmSectionKey {
+ std::string SectionName;
+ StringRef GroupName;
+ unsigned UniqueID;
+ WasmSectionKey(StringRef SectionName, StringRef GroupName,
+ unsigned UniqueID)
+ : SectionName(SectionName), GroupName(GroupName), UniqueID(UniqueID) {
+ }
+ bool operator<(const WasmSectionKey &Other) const {
+ if (SectionName != Other.SectionName)
+ return SectionName < Other.SectionName;
+ if (GroupName != Other.GroupName)
+ return GroupName < Other.GroupName;
+ return UniqueID < Other.UniqueID;
+ }
+ };
+
StringMap<MCSectionMachO *> MachOUniquingMap;
std::map<ELFSectionKey, MCSectionELF *> ELFUniquingMap;
std::map<COFFSectionKey, MCSectionCOFF *> COFFUniquingMap;
- StringMap<bool> ELFRelSecNames;
+ std::map<WasmSectionKey, MCSectionWasm *> WasmUniquingMap;
+ StringMap<bool> RelSecNames;
SpecificBumpPtrAllocator<MCSubtargetInfo> MCSubtargetAllocator;
/// Do automatic reset in destructor
bool AutoReset;
- bool HadError;
+ bool HadError = false;
MCSymbol *createSymbolImpl(const StringMapEntry<bool> *Name,
bool CanBeUnnamed);
@@ -232,14 +257,25 @@ namespace llvm {
MCSymbol *getOrCreateDirectionalLocalSymbol(unsigned LocalLabelVal,
unsigned Instance);
+ MCSectionELF *createELFSectionImpl(StringRef Section, unsigned Type,
+ unsigned Flags, SectionKind K,
+ unsigned EntrySize,
+ const MCSymbolELF *Group,
+ unsigned UniqueID,
+ const MCSymbolELF *Associated);
+
public:
explicit MCContext(const MCAsmInfo *MAI, const MCRegisterInfo *MRI,
const MCObjectFileInfo *MOFI,
const SourceMgr *Mgr = nullptr, bool DoAutoReset = true);
+ MCContext(const MCContext &) = delete;
+ MCContext &operator=(const MCContext &) = delete;
~MCContext();
const SourceMgr *getSourceManager() const { return SrcMgr; }
+ void setInlineSourceManager(SourceMgr *SM) { InlineSrcMgr = SM; }
+
const MCAsmInfo *getAsmInfo() const { return MAI; }
const MCRegisterInfo *getRegisterInfo() const { return MRI; }
@@ -288,8 +324,6 @@ namespace llvm {
/// \param Name - The symbol name, which must be unique across all symbols.
MCSymbol *getOrCreateSymbol(const Twine &Name);
- MCSymbolELF *getOrCreateSectionSymbol(const MCSectionELF &Section);
-
/// Gets a symbol that will be defined to the final stack offset of a local
/// variable after codegen.
///
@@ -340,25 +374,13 @@ namespace llvm {
MCSectionELF *getELFSection(const Twine &Section, unsigned Type,
unsigned Flags) {
- return getELFSection(Section, Type, Flags, nullptr);
- }
-
- MCSectionELF *getELFSection(const Twine &Section, unsigned Type,
- unsigned Flags, const char *BeginSymName) {
- return getELFSection(Section, Type, Flags, 0, "", BeginSymName);
+ return getELFSection(Section, Type, Flags, 0, "");
}
MCSectionELF *getELFSection(const Twine &Section, unsigned Type,
unsigned Flags, unsigned EntrySize,
const Twine &Group) {
- return getELFSection(Section, Type, Flags, EntrySize, Group, nullptr);
- }
-
- MCSectionELF *getELFSection(const Twine &Section, unsigned Type,
- unsigned Flags, unsigned EntrySize,
- const Twine &Group, const char *BeginSymName) {
- return getELFSection(Section, Type, Flags, EntrySize, Group, ~0,
- BeginSymName);
+ return getELFSection(Section, Type, Flags, EntrySize, Group, ~0);
}
MCSectionELF *getELFSection(const Twine &Section, unsigned Type,
@@ -371,13 +393,12 @@ namespace llvm {
MCSectionELF *getELFSection(const Twine &Section, unsigned Type,
unsigned Flags, unsigned EntrySize,
const Twine &Group, unsigned UniqueID,
- const char *BeginSymName);
+ const MCSymbolELF *Associated);
MCSectionELF *getELFSection(const Twine &Section, unsigned Type,
unsigned Flags, unsigned EntrySize,
const MCSymbolELF *Group, unsigned UniqueID,
- const char *BeginSymName,
- const MCSectionELF *Associated);
+ const MCSymbolELF *Associated);
/// Get a section with the provided group identifier. This section is
/// named by concatenating \p Prefix with '.' then \p Suffix. The \p Type
@@ -390,7 +411,7 @@ namespace llvm {
MCSectionELF *createELFRelSection(const Twine &Name, unsigned Type,
unsigned Flags, unsigned EntrySize,
const MCSymbolELF *Group,
- const MCSectionELF *Associated);
+ const MCSectionELF *RelInfoSection);
void renameELFSection(MCSectionELF *Section, StringRef Name);
@@ -416,6 +437,54 @@ namespace llvm {
getAssociativeCOFFSection(MCSectionCOFF *Sec, const MCSymbol *KeySym,
unsigned UniqueID = GenericSectionID);
+ MCSectionWasm *getWasmSection(const Twine &Section, unsigned Type,
+ unsigned Flags) {
+ return getWasmSection(Section, Type, Flags, nullptr);
+ }
+
+ MCSectionWasm *getWasmSection(const Twine &Section, unsigned Type,
+ unsigned Flags, const char *BeginSymName) {
+ return getWasmSection(Section, Type, Flags, "", BeginSymName);
+ }
+
+ MCSectionWasm *getWasmSection(const Twine &Section, unsigned Type,
+ unsigned Flags, const Twine &Group) {
+ return getWasmSection(Section, Type, Flags, Group, nullptr);
+ }
+
+ MCSectionWasm *getWasmSection(const Twine &Section, unsigned Type,
+ unsigned Flags, const Twine &Group,
+ const char *BeginSymName) {
+ return getWasmSection(Section, Type, Flags, Group, ~0, BeginSymName);
+ }
+
+ MCSectionWasm *getWasmSection(const Twine &Section, unsigned Type,
+ unsigned Flags, const Twine &Group,
+ unsigned UniqueID) {
+ return getWasmSection(Section, Type, Flags, Group, UniqueID, nullptr);
+ }
+
+ MCSectionWasm *getWasmSection(const Twine &Section, unsigned Type,
+ unsigned Flags, const Twine &Group,
+ unsigned UniqueID, const char *BeginSymName);
+
+ MCSectionWasm *getWasmSection(const Twine &Section, unsigned Type,
+ unsigned Flags, const MCSymbolWasm *Group,
+ unsigned UniqueID, const char *BeginSymName);
+
+ /// Get a section with the provided group identifier. This section is
+ /// named by concatenating \p Prefix with '.' then \p Suffix. The \p Type
+ /// describes the type of the section and \p Flags are used to further
+ /// configure this named section.
+ MCSectionWasm *getWasmNamedSection(const Twine &Prefix, const Twine &Suffix,
+ unsigned Type, unsigned Flags);
+
+ MCSectionWasm *createWasmRelSection(const Twine &Name, unsigned Type,
+ unsigned Flags,
+ const MCSymbolWasm *Group);
+
+ void renameWasmSection(MCSectionWasm *Section, StringRef Name);
+
// Create and save a copy of STI and return a reference to the copy.
MCSubtargetInfo &getSubtargetCopy(const MCSubtargetInfo &STI);
@@ -463,6 +532,7 @@ namespace llvm {
const SmallVectorImpl<MCDwarfFile> &getMCDwarfFiles(unsigned CUID = 0) {
return getMCDwarfLineTable(CUID).getMCDwarfFiles();
}
+
const SmallVectorImpl<std::string> &getMCDwarfDirs(unsigned CUID = 0) {
return getMCDwarfLineTable(CUID).getMCDwarfDirs();
}
@@ -473,10 +543,13 @@ namespace llvm {
return true;
return false;
}
+
unsigned getDwarfCompileUnitID() { return DwarfCompileUnitID; }
+
void setDwarfCompileUnitID(unsigned CUIndex) {
DwarfCompileUnitID = CUIndex;
}
+
void setMCLineTableCompilationDir(unsigned CUID, StringRef CompilationDir) {
getMCDwarfLineTable(CUID).setCompilationDir(CompilationDir);
}
@@ -496,6 +569,7 @@ namespace llvm {
CurrentDwarfLoc.setDiscriminator(Discriminator);
DwarfLocSeen = true;
}
+
void clearDwarfLocSeen() { DwarfLocSeen = false; }
bool getDwarfLocSeen() { return DwarfLocSeen; }
@@ -504,20 +578,25 @@ namespace llvm {
bool getGenDwarfForAssembly() { return GenDwarfForAssembly; }
void setGenDwarfForAssembly(bool Value) { GenDwarfForAssembly = Value; }
unsigned getGenDwarfFileNumber() { return GenDwarfFileNumber; }
+
void setGenDwarfFileNumber(unsigned FileNumber) {
GenDwarfFileNumber = FileNumber;
}
+
const SetVector<MCSection *> &getGenDwarfSectionSyms() {
return SectionsForRanges;
}
+
bool addGenDwarfSection(MCSection *Sec) {
return SectionsForRanges.insert(Sec);
}
void finalizeDwarfSections(MCStreamer &MCOS);
+
const std::vector<MCGenDwarfLabelEntry> &getMCGenDwarfLabelEntries() const {
return MCGenDwarfLabelEntries;
}
+
void addMCGenDwarfLabelEntry(const MCGenDwarfLabelEntry &E) {
MCGenDwarfLabelEntries.push_back(E);
}
@@ -527,10 +606,12 @@ namespace llvm {
void setDwarfDebugProducer(StringRef S) { DwarfDebugProducer = S; }
StringRef getDwarfDebugProducer() { return DwarfDebugProducer; }
+
dwarf::DwarfFormat getDwarfFormat() const {
// TODO: Support DWARF64
return dwarf::DWARF32;
}
+
void setDwarfVersion(uint16_t v) { DwarfVersion = v; }
uint16_t getDwarfVersion() const { return DwarfVersion; }
@@ -538,15 +619,18 @@ namespace llvm {
char *getSecureLogFile() { return SecureLogFile; }
raw_fd_ostream *getSecureLog() { return SecureLog.get(); }
- bool getSecureLogUsed() { return SecureLogUsed; }
+
void setSecureLog(std::unique_ptr<raw_fd_ostream> Value) {
SecureLog = std::move(Value);
}
+
+ bool getSecureLogUsed() { return SecureLogUsed; }
void setSecureLogUsed(bool Value) { SecureLogUsed = Value; }
void *allocate(unsigned Size, unsigned Align = 8) {
return Allocator.Allocate(Size, Align);
}
+
void deallocate(void *Ptr) {}
bool hadError() { return HadError; }
@@ -632,4 +716,4 @@ inline void operator delete[](void *Ptr, llvm::MCContext &C) noexcept {
C.deallocate(Ptr);
}
-#endif
+#endif // LLVM_MC_MCCONTEXT_H
diff --git a/include/llvm/MC/MCDisassembler/MCDisassembler.h b/include/llvm/MC/MCDisassembler/MCDisassembler.h
index 9006d87abb43..5e626f186986 100644
--- a/include/llvm/MC/MCDisassembler/MCDisassembler.h
+++ b/include/llvm/MC/MCDisassembler/MCDisassembler.h
@@ -1,4 +1,4 @@
-//===-- llvm/MC/MCDisassembler.h - Disassembler interface -------*- C++ -*-===//
+//===- llvm/MC/MCDisassembler.h - Disassembler interface --------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -6,20 +6,21 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
+
#ifndef LLVM_MC_MCDISASSEMBLER_MCDISASSEMBLER_H
#define LLVM_MC_MCDISASSEMBLER_MCDISASSEMBLER_H
-#include "llvm-c/Disassembler.h"
#include "llvm/MC/MCDisassembler/MCSymbolizer.h"
-#include "llvm/Support/DataTypes.h"
+#include <cstdint>
+#include <memory>
namespace llvm {
template <typename T> class ArrayRef;
+class MCContext;
class MCInst;
class MCSubtargetInfo;
class raw_ostream;
-class MCContext;
/// Superclass for all disassemblers. Consumes a memory region and provides an
/// array of assembly instructions.
@@ -54,7 +55,7 @@ public:
};
MCDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx)
- : Ctx(Ctx), STI(STI), Symbolizer(), CommentStream(nullptr) {}
+ : Ctx(Ctx), STI(STI) {}
virtual ~MCDisassembler();
@@ -105,9 +106,9 @@ public:
// Marked mutable because we cache it inside the disassembler, rather than
// having to pass it around as an argument through all the autogenerated code.
- mutable raw_ostream *CommentStream;
+ mutable raw_ostream *CommentStream = nullptr;
};
-} // namespace llvm
+} // end namespace llvm
-#endif
+#endif // LLVM_MC_MCDISASSEMBLER_MCDISASSEMBLER_H
diff --git a/include/llvm/MC/MCDisassembler/MCRelocationInfo.h b/include/llvm/MC/MCDisassembler/MCRelocationInfo.h
index 25334f755ee6..7836e886c303 100644
--- a/include/llvm/MC/MCDisassembler/MCRelocationInfo.h
+++ b/include/llvm/MC/MCDisassembler/MCRelocationInfo.h
@@ -1,4 +1,4 @@
-//==-- llvm/MC/MCRelocationInfo.h --------------------------------*- C++ -*-==//
+//===- llvm/MC/MCRelocationInfo.h -------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -16,26 +16,20 @@
#ifndef LLVM_MC_MCDISASSEMBLER_MCRELOCATIONINFO_H
#define LLVM_MC_MCDISASSEMBLER_MCRELOCATIONINFO_H
-#include "llvm/Support/Compiler.h"
-
namespace llvm {
-namespace object {
-class RelocationRef;
-}
-class MCExpr;
class MCContext;
+class MCExpr;
/// \brief Create MCExprs from relocations found in an object file.
class MCRelocationInfo {
- MCRelocationInfo(const MCRelocationInfo &) = delete;
- void operator=(const MCRelocationInfo &) = delete;
-
protected:
MCContext &Ctx;
public:
MCRelocationInfo(MCContext &Ctx);
+ MCRelocationInfo(const MCRelocationInfo &) = delete;
+ MCRelocationInfo &operator=(const MCRelocationInfo &) = delete;
virtual ~MCRelocationInfo();
/// \brief Create an MCExpr for the target-specific \p VariantKind.
@@ -46,6 +40,6 @@ public:
unsigned VariantKind);
};
-}
+} // end namespace llvm
-#endif
+#endif // LLVM_MC_MCDISASSEMBLER_MCRELOCATIONINFO_H
diff --git a/include/llvm/MC/MCDisassembler/MCSymbolizer.h b/include/llvm/MC/MCDisassembler/MCSymbolizer.h
index 713467c0a3e7..d85cf5e066f5 100644
--- a/include/llvm/MC/MCDisassembler/MCSymbolizer.h
+++ b/include/llvm/MC/MCDisassembler/MCSymbolizer.h
@@ -1,4 +1,4 @@
-//===-- llvm/MC/MCSymbolizer.h - MCSymbolizer class -------------*- C++ -*-===//
+//===- llvm/MC/MCSymbolizer.h - MCSymbolizer class --------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -17,9 +17,8 @@
#define LLVM_MC_MCDISASSEMBLER_MCSYMBOLIZER_H
#include "llvm/MC/MCDisassembler/MCRelocationInfo.h"
-#include "llvm/Support/Compiler.h"
-#include "llvm/Support/DataTypes.h"
-#include <cassert>
+#include <algorithm>
+#include <cstdint>
#include <memory>
namespace llvm {
@@ -38,9 +37,6 @@ 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 &) = delete;
- void operator=(const MCSymbolizer &) = delete;
-
protected:
MCContext &Ctx;
std::unique_ptr<MCRelocationInfo> RelInfo;
@@ -51,6 +47,8 @@ public:
: Ctx(Ctx), RelInfo(std::move(RelInfo)) {
}
+ MCSymbolizer(const MCSymbolizer &) = delete;
+ MCSymbolizer &operator=(const MCSymbolizer &) = delete;
virtual ~MCSymbolizer();
/// \brief Try to add a symbolic operand instead of \p Value to the MCInst.
@@ -80,6 +78,6 @@ public:
uint64_t Address) = 0;
};
-}
+} // end namespace llvm
-#endif
+#endif // LLVM_MC_MCDISASSEMBLER_MCSYMBOLIZER_H
diff --git a/include/llvm/MC/MCDwarf.h b/include/llvm/MC/MCDwarf.h
index 0c555d377d8b..0d69c2005cb4 100644
--- a/include/llvm/MC/MCDwarf.h
+++ b/include/llvm/MC/MCDwarf.h
@@ -16,24 +16,27 @@
#define LLVM_MC_MCDWARF_H
#include "llvm/ADT/MapVector.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/MC/MCSection.h"
-#include "llvm/Support/Dwarf.h"
+#include <cassert>
+#include <cstdint>
#include <string>
#include <utility>
#include <vector>
namespace llvm {
+
template <typename T> class ArrayRef;
-class raw_ostream;
class MCAsmBackend;
class MCContext;
class MCObjectStreamer;
class MCStreamer;
class MCSymbol;
-class SourceMgr;
+class raw_ostream;
class SMLoc;
+class SourceMgr;
/// \brief Instances of this class represent the name of the dwarf
/// .file directive and its associated dwarf file number in the MC file,
@@ -71,6 +74,7 @@ class MCDwarfLoc {
private: // MCContext manages these
friend class MCContext;
friend class MCDwarfLineEntry;
+
MCDwarfLoc(unsigned fileNum, unsigned line, unsigned column, unsigned flags,
unsigned isa, unsigned discriminator)
: FileNum(fileNum), Line(line), Column(column), Flags(flags), Isa(isa),
@@ -194,13 +198,14 @@ struct MCDwarfLineTableParams {
};
struct MCDwarfLineTableHeader {
- MCSymbol *Label;
+ MCSymbol *Label = nullptr;
SmallVector<std::string, 3> MCDwarfDirs;
SmallVector<MCDwarfFile, 3> MCDwarfFiles;
StringMap<unsigned> SourceIdMap;
StringRef CompilationDir;
- MCDwarfLineTableHeader() : Label(nullptr) {}
+ MCDwarfLineTableHeader() = default;
+
unsigned getFile(StringRef &Directory, StringRef &FileName,
unsigned FileNumber = 0);
std::pair<MCSymbol *, MCSymbol *> Emit(MCStreamer *MCOS,
@@ -212,13 +217,16 @@ struct MCDwarfLineTableHeader {
class MCDwarfDwoLineTable {
MCDwarfLineTableHeader Header;
+
public:
void setCompilationDir(StringRef CompilationDir) {
Header.CompilationDir = CompilationDir;
}
+
unsigned getFile(StringRef Directory, StringRef FileName) {
return Header.getFile(Directory, FileName);
}
+
void Emit(MCStreamer &MCOS, MCDwarfLineTableParams Params) const;
};
@@ -488,22 +496,19 @@ public:
};
struct MCDwarfFrameInfo {
- MCDwarfFrameInfo()
- : Begin(nullptr), End(nullptr), Personality(nullptr), Lsda(nullptr),
- Instructions(), CurrentCfaRegister(0), PersonalityEncoding(),
- LsdaEncoding(0), CompactUnwindEncoding(0), IsSignalFrame(false),
- IsSimple(false) {}
- MCSymbol *Begin;
- MCSymbol *End;
- const MCSymbol *Personality;
- const MCSymbol *Lsda;
+ MCDwarfFrameInfo() = default;
+
+ MCSymbol *Begin = nullptr;
+ MCSymbol *End = nullptr;
+ const MCSymbol *Personality = nullptr;
+ const MCSymbol *Lsda = nullptr;
std::vector<MCCFIInstruction> Instructions;
- unsigned CurrentCfaRegister;
- unsigned PersonalityEncoding;
- unsigned LsdaEncoding;
- uint32_t CompactUnwindEncoding;
- bool IsSignalFrame;
- bool IsSimple;
+ unsigned CurrentCfaRegister = 0;
+ unsigned PersonalityEncoding = 0;
+ unsigned LsdaEncoding = 0;
+ uint32_t CompactUnwindEncoding = 0;
+ bool IsSignalFrame = false;
+ bool IsSimple = false;
};
class MCDwarfFrameEmitter {
@@ -516,6 +521,7 @@ public:
static void EncodeAdvanceLoc(MCContext &Context, uint64_t AddrDelta,
raw_ostream &OS);
};
+
} // end namespace llvm
-#endif
+#endif // LLVM_MC_MCDWARF_H
diff --git a/include/llvm/MC/MCELFObjectWriter.h b/include/llvm/MC/MCELFObjectWriter.h
index 376e21821316..f22fc11f9b07 100644
--- a/include/llvm/MC/MCELFObjectWriter.h
+++ b/include/llvm/MC/MCELFObjectWriter.h
@@ -1,4 +1,4 @@
-//===-- llvm/MC/MCELFObjectWriter.h - ELF Object Writer ---------*- C++ -*-===//
+//===- llvm/MC/MCELFObjectWriter.h - ELF Object Writer ----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -11,22 +11,21 @@
#define LLVM_MC_MCELFOBJECTWRITER_H
#include "llvm/ADT/Triple.h"
-#include "llvm/MC/MCValue.h"
-#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/Casting.h"
#include "llvm/Support/ELF.h"
#include "llvm/Support/raw_ostream.h"
+#include <cstdint>
#include <vector>
namespace llvm {
+
class MCAssembler;
class MCContext;
class MCFixup;
-class MCFragment;
class MCObjectWriter;
class MCSymbol;
class MCSymbolELF;
class MCValue;
-class raw_pwrite_stream;
struct ELFRelocationEntry {
uint64_t Offset; // Where is the relocation.
@@ -47,6 +46,7 @@ struct ELFRelocationEntry {
<< ", Addend=" << Addend << ", OriginalSymbol=" << OriginalSymbol
<< ", OriginalAddend=" << OriginalAddend;
}
+
void dump() const { print(errs()); }
};
@@ -58,12 +58,12 @@ class MCELFObjectTargetWriter {
const unsigned IsN64 : 1;
protected:
-
- MCELFObjectTargetWriter(bool Is64Bit_, uint8_t OSABI_,
- uint16_t EMachine_, bool HasRelocationAddend,
- bool IsN64=false);
+ MCELFObjectTargetWriter(bool Is64Bit_, uint8_t OSABI_, uint16_t EMachine_,
+ bool HasRelocationAddend, bool IsN64 = false);
public:
+ virtual ~MCELFObjectTargetWriter() = default;
+
static uint8_t getOSABI(Triple::OSType OSType) {
switch (OSType) {
case Triple::CloudABI:
@@ -76,8 +76,6 @@ public:
}
}
- virtual ~MCELFObjectTargetWriter() {}
-
virtual unsigned getRelocType(MCContext &Ctx, const MCValue &Target,
const MCFixup &Fixup, bool IsPCRel) const = 0;
@@ -144,6 +142,7 @@ public:
MCObjectWriter *createELFObjectWriter(MCELFObjectTargetWriter *MOTW,
raw_pwrite_stream &OS,
bool IsLittleEndian);
-} // End llvm namespace
-#endif
+} // end namespace llvm
+
+#endif // LLVM_MC_MCELFOBJECTWRITER_H
diff --git a/include/llvm/MC/MCELFStreamer.h b/include/llvm/MC/MCELFStreamer.h
index a5c263844352..90434f34da5f 100644
--- a/include/llvm/MC/MCELFStreamer.h
+++ b/include/llvm/MC/MCELFStreamer.h
@@ -10,27 +10,24 @@
#ifndef LLVM_MC_MCELFSTREAMER_H
#define LLVM_MC_MCELFSTREAMER_H
-#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/MC/MCDirectives.h"
#include "llvm/MC/MCObjectStreamer.h"
-#include "llvm/MC/SectionKind.h"
-#include "llvm/Support/DataTypes.h"
namespace llvm {
+
class MCAsmBackend;
-class MCAssembler;
class MCCodeEmitter;
class MCExpr;
class MCInst;
-class raw_ostream;
class MCELFStreamer : public MCObjectStreamer {
public:
MCELFStreamer(MCContext &Context, MCAsmBackend &TAB, raw_pwrite_stream &OS,
MCCodeEmitter *Emitter)
- : MCObjectStreamer(Context, TAB, OS, Emitter), SeenIdent(false) {}
+ : MCObjectStreamer(Context, TAB, OS, Emitter) {}
- ~MCELFStreamer() override;
+ ~MCELFStreamer() override = default;
/// state management
void reset() override {
@@ -44,7 +41,8 @@ public:
void InitSections(bool NoExecStack) override;
void ChangeSection(MCSection *Section, const MCExpr *Subsection) override;
- void EmitLabel(MCSymbol *Symbol) override;
+ void EmitLabel(MCSymbol *Symbol, SMLoc Loc = SMLoc()) override;
+ void EmitLabel(MCSymbol *Symbol, SMLoc Loc, MCFragment *F) override;
void EmitAssemblerFlag(MCAssemblerFlag Flag) override;
void EmitThumbFunc(MCSymbol *Func) override;
void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) override;
@@ -52,10 +50,6 @@ public:
void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) override;
void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
unsigned ByteAlignment) override;
- void BeginCOFFSymbolDef(const MCSymbol *Symbol) override;
- void EmitCOFFSymbolStorageClass(int StorageClass) override;
- void EmitCOFFSymbolType(int Type) override;
- void EndCOFFSymbolDef() override;
void emitELFSize(MCSymbol *Symbol, const MCExpr *Value) override;
@@ -69,8 +63,6 @@ public:
void EmitValueImpl(const MCExpr *Value, unsigned Size,
SMLoc Loc = SMLoc()) override;
- void EmitFileDirective(StringRef Filename) override;
-
void EmitIdent(StringRef IdentString) override;
void EmitValueToAlignment(unsigned, int64_t, unsigned, unsigned) override;
@@ -91,11 +83,11 @@ private:
/// \brief Merge the content of the fragment \p EF into the fragment \p DF.
void mergeFragment(MCDataFragment *, MCDataFragment *);
- bool SeenIdent;
+ bool SeenIdent = false;
/// BundleGroups - The stack of fragments holding the bundle-locked
/// instructions.
- llvm::SmallVector<MCDataFragment *, 4> BundleGroups;
+ SmallVector<MCDataFragment *, 4> BundleGroups;
};
MCELFStreamer *createARMELFStreamer(MCContext &Context, MCAsmBackend &TAB,
@@ -105,4 +97,4 @@ MCELFStreamer *createARMELFStreamer(MCContext &Context, MCAsmBackend &TAB,
} // end namespace llvm
-#endif
+#endif // LLVM_MC_MCELFSTREAMER_H
diff --git a/include/llvm/MC/MCExpr.h b/include/llvm/MC/MCExpr.h
index 0d1e675da459..c850abf42e2c 100644
--- a/include/llvm/MC/MCExpr.h
+++ b/include/llvm/MC/MCExpr.h
@@ -11,10 +11,11 @@
#define LLVM_MC_MCEXPR_H
#include "llvm/ADT/DenseMap.h"
-#include "llvm/Support/Casting.h"
-#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/SMLoc.h"
+#include <cstdint>
namespace llvm {
+
class MCAsmInfo;
class MCAsmLayout;
class MCAssembler;
@@ -43,9 +44,7 @@ public:
private:
ExprKind Kind;
-
- MCExpr(const MCExpr&) = delete;
- void operator=(const MCExpr&) = delete;
+ SMLoc Loc;
bool evaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm,
const MCAsmLayout *Layout,
@@ -56,7 +55,7 @@ private:
const SectionAddrMap *Addrs, bool InSet) const;
protected:
- explicit MCExpr(ExprKind Kind) : Kind(Kind) {}
+ explicit MCExpr(ExprKind Kind, SMLoc Loc) : Kind(Kind), Loc(Loc) {}
bool evaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm,
const MCAsmLayout *Layout,
@@ -64,10 +63,14 @@ protected:
const SectionAddrMap *Addrs, bool InSet) const;
public:
+ MCExpr(const MCExpr &) = delete;
+ MCExpr &operator=(const MCExpr &) = delete;
+
/// \name Accessors
/// @{
ExprKind getKind() const { return Kind; }
+ SMLoc getLoc() const { return Loc; }
/// @}
/// \name Utility Methods
@@ -132,7 +135,7 @@ class MCConstantExpr : public MCExpr {
int64_t Value;
explicit MCConstantExpr(int64_t Value)
- : MCExpr(MCExpr::Constant), Value(Value) {}
+ : MCExpr(MCExpr::Constant, SMLoc()), Value(Value) {}
public:
/// \name Construction
@@ -191,6 +194,8 @@ public:
VK_SIZE, // symbol@SIZE
VK_WEAKREF, // The link between the symbols in .weakref foo, bar
+ VK_X86_ABS8,
+
VK_ARM_NONE,
VK_ARM_GOT_PREL,
VK_ARM_TARGET1,
@@ -265,6 +270,7 @@ public:
VK_Hexagon_IE_GOT,
VK_WebAssembly_FUNCTION, // Function table index, rather than virtual addr
+ VK_WebAssembly_TYPEINDEX,// Type table index
VK_AMDGPU_GOTPCREL32_LO, // symbol@gotpcrel32@lo
VK_AMDGPU_GOTPCREL32_HI, // symbol@gotpcrel32@hi
@@ -289,7 +295,7 @@ private:
const MCSymbol *Symbol;
explicit MCSymbolRefExpr(const MCSymbol *Symbol, VariantKind Kind,
- const MCAsmInfo *MAI);
+ const MCAsmInfo *MAI, SMLoc Loc = SMLoc());
public:
/// \name Construction
@@ -300,7 +306,7 @@ public:
}
static const MCSymbolRefExpr *create(const MCSymbol *Symbol, VariantKind Kind,
- MCContext &Ctx);
+ MCContext &Ctx, SMLoc Loc = SMLoc());
static const MCSymbolRefExpr *create(StringRef Name, VariantKind Kind,
MCContext &Ctx);
@@ -345,26 +351,30 @@ 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, SMLoc Loc)
+ : MCExpr(MCExpr::Unary, Loc), Op(Op), Expr(Expr) {}
public:
/// \name Construction
/// @{
static const MCUnaryExpr *create(Opcode Op, const MCExpr *Expr,
- MCContext &Ctx);
- static const MCUnaryExpr *createLNot(const MCExpr *Expr, MCContext &Ctx) {
- return create(LNot, Expr, Ctx);
+ MCContext &Ctx, SMLoc Loc = SMLoc());
+
+ static const MCUnaryExpr *createLNot(const MCExpr *Expr, MCContext &Ctx, SMLoc Loc = SMLoc()) {
+ return create(LNot, Expr, Ctx, Loc);
}
- static const MCUnaryExpr *createMinus(const MCExpr *Expr, MCContext &Ctx) {
- return create(Minus, Expr, Ctx);
+
+ static const MCUnaryExpr *createMinus(const MCExpr *Expr, MCContext &Ctx, SMLoc Loc = SMLoc()) {
+ return create(Minus, Expr, Ctx, Loc);
}
- static const MCUnaryExpr *createNot(const MCExpr *Expr, MCContext &Ctx) {
- return create(Not, Expr, Ctx);
+
+ static const MCUnaryExpr *createNot(const MCExpr *Expr, MCContext &Ctx, SMLoc Loc = SMLoc()) {
+ return create(Not, Expr, Ctx, Loc);
}
- static const MCUnaryExpr *createPlus(const MCExpr *Expr, MCContext &Ctx) {
- return create(Plus, Expr, Ctx);
+
+ static const MCUnaryExpr *createPlus(const MCExpr *Expr, MCContext &Ctx, SMLoc Loc = SMLoc()) {
+ return create(Plus, Expr, Ctx, Loc);
}
/// @}
@@ -417,87 +427,108 @@ 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,
+ SMLoc Loc = SMLoc())
+ : MCExpr(MCExpr::Binary, Loc), Op(Op), LHS(LHS), RHS(RHS) {}
public:
/// \name Construction
/// @{
static const MCBinaryExpr *create(Opcode Op, const MCExpr *LHS,
- const MCExpr *RHS, MCContext &Ctx);
+ const MCExpr *RHS, MCContext &Ctx,
+ SMLoc Loc = SMLoc());
+
static const MCBinaryExpr *createAdd(const MCExpr *LHS, const MCExpr *RHS,
MCContext &Ctx) {
return create(Add, LHS, RHS, Ctx);
}
+
static const MCBinaryExpr *createAnd(const MCExpr *LHS, const MCExpr *RHS,
MCContext &Ctx) {
return create(And, LHS, RHS, Ctx);
}
+
static const MCBinaryExpr *createDiv(const MCExpr *LHS, const MCExpr *RHS,
MCContext &Ctx) {
return create(Div, LHS, RHS, Ctx);
}
+
static const MCBinaryExpr *createEQ(const MCExpr *LHS, const MCExpr *RHS,
MCContext &Ctx) {
return create(EQ, LHS, RHS, Ctx);
}
+
static const MCBinaryExpr *createGT(const MCExpr *LHS, const MCExpr *RHS,
MCContext &Ctx) {
return create(GT, LHS, RHS, Ctx);
}
+
static const MCBinaryExpr *createGTE(const MCExpr *LHS, const MCExpr *RHS,
MCContext &Ctx) {
return create(GTE, LHS, RHS, Ctx);
}
+
static const MCBinaryExpr *createLAnd(const MCExpr *LHS, const MCExpr *RHS,
MCContext &Ctx) {
return create(LAnd, LHS, RHS, Ctx);
}
+
static const MCBinaryExpr *createLOr(const MCExpr *LHS, const MCExpr *RHS,
MCContext &Ctx) {
return create(LOr, LHS, RHS, Ctx);
}
+
static const MCBinaryExpr *createLT(const MCExpr *LHS, const MCExpr *RHS,
MCContext &Ctx) {
return create(LT, LHS, RHS, Ctx);
}
+
static const MCBinaryExpr *createLTE(const MCExpr *LHS, const MCExpr *RHS,
MCContext &Ctx) {
return create(LTE, LHS, RHS, Ctx);
}
+
static const MCBinaryExpr *createMod(const MCExpr *LHS, const MCExpr *RHS,
MCContext &Ctx) {
return create(Mod, LHS, RHS, Ctx);
}
+
static const MCBinaryExpr *createMul(const MCExpr *LHS, const MCExpr *RHS,
MCContext &Ctx) {
return create(Mul, LHS, RHS, Ctx);
}
+
static const MCBinaryExpr *createNE(const MCExpr *LHS, const MCExpr *RHS,
MCContext &Ctx) {
return create(NE, LHS, RHS, Ctx);
}
+
static const MCBinaryExpr *createOr(const MCExpr *LHS, const MCExpr *RHS,
MCContext &Ctx) {
return create(Or, LHS, RHS, Ctx);
}
+
static const MCBinaryExpr *createShl(const MCExpr *LHS, const MCExpr *RHS,
MCContext &Ctx) {
return create(Shl, LHS, RHS, Ctx);
}
+
static const MCBinaryExpr *createAShr(const MCExpr *LHS, const MCExpr *RHS,
MCContext &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) {
return create(Sub, LHS, RHS, Ctx);
}
+
static const MCBinaryExpr *createXor(const MCExpr *LHS, const MCExpr *RHS,
MCContext &Ctx) {
return create(Xor, LHS, RHS, Ctx);
@@ -530,9 +561,11 @@ public:
/// MCExprs are bump pointer allocated and not destructed.
class MCTargetExpr : public MCExpr {
virtual void anchor();
+
protected:
- MCTargetExpr() : MCExpr(Target) {}
- virtual ~MCTargetExpr() {}
+ MCTargetExpr() : MCExpr(Target, SMLoc()) {}
+ virtual ~MCTargetExpr() = default;
+
public:
virtual void printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const = 0;
virtual bool evaluateAsRelocatableImpl(MCValue &Res,
@@ -550,4 +583,4 @@ public:
} // end namespace llvm
-#endif
+#endif // LLVM_MC_MCEXPR_H
diff --git a/include/llvm/MC/MCFragment.h b/include/llvm/MC/MCFragment.h
index edb740f36d91..fc8257f90a9f 100644
--- a/include/llvm/MC/MCFragment.h
+++ b/include/llvm/MC/MCFragment.h
@@ -10,25 +10,26 @@
#ifndef LLVM_MC_MCFRAGMENT_H
#define LLVM_MC_MCFRAGMENT_H
-#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/ilist.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/ilist_node.h"
-#include "llvm/ADT/iterator.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/MC/MCFixup.h"
#include "llvm/MC/MCInst.h"
+#include "llvm/Support/SMLoc.h"
+#include <cstdint>
+#include <utility>
namespace llvm {
+
class MCSection;
-class MCSymbol;
class MCSubtargetInfo;
+class MCSymbol;
class MCFragment : public ilist_node_with_parent<MCFragment, MCSection> {
friend class MCAsmLayout;
- MCFragment() = delete;
- MCFragment(const MCFragment &) = delete;
- void operator=(const MCFragment &) = delete;
-
public:
enum FragmentType : uint8_t {
FT_Align,
@@ -86,6 +87,10 @@ protected:
~MCFragment();
public:
+ MCFragment() = delete;
+ MCFragment(const MCFragment &) = delete;
+ MCFragment &operator=(const MCFragment &) = delete;
+
/// Destroys the current fragment.
///
/// This must be used instead of delete as MCFragment is non-virtual.
@@ -131,7 +136,8 @@ public:
class MCDummyFragment : public MCFragment {
public:
explicit MCDummyFragment(MCSection *Sec)
- : MCFragment(FT_Dummy, false, 0, Sec){};
+ : MCFragment(FT_Dummy, false, 0, Sec) {}
+
static bool classof(const MCFragment *F) { return F->getKind() == FT_Dummy; }
};
@@ -271,7 +277,6 @@ public:
};
class MCAlignFragment : public MCFragment {
-
/// Alignment - The alignment to ensure, in bytes.
unsigned Alignment;
@@ -319,7 +324,6 @@ public:
};
class MCFillFragment : public MCFragment {
-
/// Value to use for filling bytes.
uint8_t Value;
@@ -339,7 +343,6 @@ public:
};
class MCOrgFragment : public MCFragment {
-
/// Offset - The offset this fragment should start at.
const MCExpr *Offset;
@@ -371,7 +374,6 @@ public:
};
class MCLEBFragment : public MCFragment {
-
/// Value - The value this fragment should contain.
const MCExpr *Value;
@@ -404,7 +406,6 @@ public:
};
class MCDwarfLineAddrFragment : public MCFragment {
-
/// LineDelta - the value of the difference between the two line numbers
/// between two .loc dwarf directives.
int64_t LineDelta;
@@ -441,7 +442,6 @@ public:
};
class MCDwarfCallFrameFragment : public MCFragment {
-
/// AddrDelta - The expression for the difference of the two symbols that
/// make up the address delta between two .cfi_* dwarf directives.
const MCExpr *AddrDelta;
@@ -561,4 +561,4 @@ public:
} // end namespace llvm
-#endif
+#endif // LLVM_MC_MCFRAGMENT_H
diff --git a/include/llvm/MC/MCInst.h b/include/llvm/MC/MCInst.h
index 4688b5f2b6e9..702279659371 100644
--- a/include/llvm/MC/MCInst.h
+++ b/include/llvm/MC/MCInst.h
@@ -1,4 +1,4 @@
-//===-- llvm/MC/MCInst.h - MCInst class -------------------------*- C++ -*-===//
+//===- llvm/MC/MCInst.h - MCInst class --------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -18,15 +18,17 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/DataTypes.h"
#include "llvm/Support/SMLoc.h"
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
namespace llvm {
-class raw_ostream;
-class MCAsmInfo;
-class MCInstPrinter;
+
class MCExpr;
class MCInst;
+class MCInstPrinter;
+class raw_ostream;
/// \brief Instances of this class represent operands of the MCInst class.
/// This is a simple discriminated union.
@@ -39,7 +41,7 @@ class MCOperand {
kExpr, ///< Relocatable immediate operand.
kInst ///< Sub-instruction operand.
};
- MachineOperandType Kind;
+ MachineOperandType Kind = kInvalid;
union {
unsigned RegVal;
@@ -50,7 +52,7 @@ class MCOperand {
};
public:
- MCOperand() : Kind(kInvalid), FPImmVal(0.0) {}
+ MCOperand() : FPImmVal(0.0) {}
bool isValid() const { return Kind != kInvalid; }
bool isReg() const { return Kind == kRegister; }
@@ -75,6 +77,7 @@ public:
assert(isImm() && "This is not an immediate");
return ImmVal;
}
+
void setImm(int64_t Val) {
assert(isImm() && "This is not an immediate");
ImmVal = Val;
@@ -94,6 +97,7 @@ public:
assert(isExpr() && "This is not an expression");
return ExprVal;
}
+
void setExpr(const MCExpr *Val) {
assert(isExpr() && "This is not an expression");
ExprVal = Val;
@@ -103,6 +107,7 @@ public:
assert(isInst() && "This is not a sub-instruction");
return InstVal;
}
+
void setInst(const MCInst *Val) {
assert(isInst() && "This is not a sub-instruction");
InstVal = Val;
@@ -114,24 +119,28 @@ public:
Op.RegVal = Reg;
return Op;
}
+
static MCOperand createImm(int64_t Val) {
MCOperand Op;
Op.Kind = kImmediate;
Op.ImmVal = Val;
return Op;
}
+
static MCOperand createFPImm(double Val) {
MCOperand Op;
Op.Kind = kFPImmediate;
Op.FPImmVal = Val;
return Op;
}
+
static MCOperand createExpr(const MCExpr *Val) {
MCOperand Op;
Op.Kind = kExpr;
Op.ExprVal = Val;
return Op;
}
+
static MCOperand createInst(const MCInst *Val) {
MCOperand Op;
Op.Kind = kInst;
@@ -148,12 +157,12 @@ template <> struct isPodLike<MCOperand> { static const bool value = true; };
/// \brief Instances of this class represent a single low-level machine
/// instruction.
class MCInst {
- unsigned Opcode;
+ unsigned Opcode = 0;
SMLoc Loc;
SmallVector<MCOperand, 8> Operands;
public:
- MCInst() : Opcode(0) {}
+ MCInst() = default;
void setOpcode(unsigned Op) { Opcode = Op; }
unsigned getOpcode() const { return Opcode; }
@@ -176,6 +185,7 @@ public:
const_iterator begin() const { return Operands.begin(); }
iterator end() { return Operands.end(); }
const_iterator end() const { return Operands.end(); }
+
iterator insert(iterator I, const MCOperand &Op) {
return Operands.insert(I, Op);
}
@@ -202,4 +212,4 @@ inline raw_ostream& operator<<(raw_ostream &OS, const MCInst &MI) {
} // end namespace llvm
-#endif
+#endif // LLVM_MC_MCINST_H
diff --git a/include/llvm/MC/MCInstPrinter.h b/include/llvm/MC/MCInstPrinter.h
index 320b280cc756..069403074b31 100644
--- a/include/llvm/MC/MCInstPrinter.h
+++ b/include/llvm/MC/MCInstPrinter.h
@@ -16,12 +16,12 @@
namespace llvm {
template <typename T> class ArrayRef;
-class MCInst;
-class raw_ostream;
class MCAsmInfo;
+class MCInst;
class MCInstrInfo;
class MCRegisterInfo;
class MCSubtargetInfo;
+class raw_ostream;
class StringRef;
/// Convert `Bytes' to a hex string and output to `OS'
@@ -43,28 +43,26 @@ protected:
/// \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;
+ raw_ostream *CommentStream = nullptr;
const MCAsmInfo &MAI;
const MCInstrInfo &MII;
const MCRegisterInfo &MRI;
/// True if we are printing marked up assembly.
- bool UseMarkup;
+ bool UseMarkup = false;
/// True if we are printing immediates as hex.
- bool PrintImmHex;
+ bool PrintImmHex = false;
/// Which style to use for printing hexadecimal values.
- HexStyle::Style PrintHexStyle;
+ HexStyle::Style PrintHexStyle = HexStyle::C;
/// Utility function for printing annotations.
void printAnnotation(raw_ostream &OS, StringRef Annot);
public:
MCInstPrinter(const MCAsmInfo &mai, const MCInstrInfo &mii,
- const MCRegisterInfo &mri)
- : CommentStream(nullptr), MAI(mai), MII(mii), MRI(mri), UseMarkup(false),
- PrintImmHex(false), PrintHexStyle(HexStyle::C) {}
+ const MCRegisterInfo &mri) : MAI(mai), MII(mii), MRI(mri) {}
virtual ~MCInstPrinter();
diff --git a/include/llvm/MC/MCInstrAnalysis.h b/include/llvm/MC/MCInstrAnalysis.h
index 8f5159e9e1c8..dd3e1df477b4 100644
--- a/include/llvm/MC/MCInstrAnalysis.h
+++ b/include/llvm/MC/MCInstrAnalysis.h
@@ -1,4 +1,4 @@
-//===-- llvm/MC/MCInstrAnalysis.h - InstrDesc target hooks ------*- C++ -*-===//
+//===- llvm/MC/MCInstrAnalysis.h - InstrDesc target hooks -------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -18,18 +18,19 @@
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCInstrDesc.h"
#include "llvm/MC/MCInstrInfo.h"
+#include <cstdint>
namespace llvm {
class MCInstrAnalysis {
protected:
friend class Target;
+
const MCInstrInfo *Info;
public:
MCInstrAnalysis(const MCInstrInfo *Info) : Info(Info) {}
-
- virtual ~MCInstrAnalysis() {}
+ virtual ~MCInstrAnalysis() = default;
virtual bool isBranch(const MCInst &Inst) const {
return Info->get(Inst.getOpcode()).isBranch();
@@ -66,6 +67,6 @@ public:
uint64_t &Target) const;
};
-} // End llvm namespace
+} // end namespace llvm
-#endif
+#endif // LLVM_MC_MCINSTRANALYSIS_H
diff --git a/include/llvm/MC/MCInstrItineraries.h b/include/llvm/MC/MCInstrItineraries.h
index 1fb276a302b9..4443dd113715 100644
--- a/include/llvm/MC/MCInstrItineraries.h
+++ b/include/llvm/MC/MCInstrItineraries.h
@@ -1,4 +1,4 @@
-//===-- llvm/MC/MCInstrItineraries.h - Scheduling ---------------*- C++ -*-===//
+//===- llvm/MC/MCInstrItineraries.h - Scheduling ----------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -88,7 +88,6 @@ struct InstrStage {
}
};
-
//===----------------------------------------------------------------------===//
/// An itinerary represents the scheduling information for an instruction.
/// This includes a set of stages occupied by the instruction and the pipeline
@@ -102,23 +101,20 @@ struct InstrItinerary {
unsigned LastOperandCycle; ///< Index of last + 1 operand rd/wr
};
-
//===----------------------------------------------------------------------===//
/// Itinerary data supplied by a subtarget to be used by a target.
///
class InstrItineraryData {
public:
- MCSchedModel SchedModel; ///< Basic machine properties.
- const InstrStage *Stages; ///< Array of stages selected
- const unsigned *OperandCycles; ///< Array of operand cycles selected
- const unsigned *Forwardings; ///< Array of pipeline forwarding paths
- const InstrItinerary *Itineraries; ///< Array of itineraries selected
-
- /// Ctors.
- InstrItineraryData() : SchedModel(MCSchedModel::GetDefaultSchedModel()),
- Stages(nullptr), OperandCycles(nullptr),
- Forwardings(nullptr), Itineraries(nullptr) {}
-
+ MCSchedModel SchedModel =
+ MCSchedModel::GetDefaultSchedModel(); ///< Basic machine properties.
+ const InstrStage *Stages = nullptr; ///< Array of stages selected
+ const unsigned *OperandCycles = nullptr; ///< Array of operand cycles selected
+ const unsigned *Forwardings = nullptr; ///< Array of pipeline forwarding paths
+ const InstrItinerary *Itineraries =
+ nullptr; ///< Array of itineraries selected
+
+ InstrItineraryData() = default;
InstrItineraryData(const MCSchedModel &SM, const InstrStage *S,
const unsigned *OS, const unsigned *F)
: SchedModel(SM), Stages(S), OperandCycles(OS), Forwardings(F),
@@ -234,6 +230,6 @@ public:
}
};
-} // End llvm namespace
+} // end namespace llvm
-#endif
+#endif // LLVM_MC_MCINSTRITINERARIES_H
diff --git a/include/llvm/MC/MCLabel.h b/include/llvm/MC/MCLabel.h
index a12473fdad02..b6579fd654ab 100644
--- a/include/llvm/MC/MCLabel.h
+++ b/include/llvm/MC/MCLabel.h
@@ -14,10 +14,8 @@
#ifndef LLVM_MC_MCLABEL_H
#define LLVM_MC_MCLABEL_H
-#include "llvm/Support/Compiler.h"
-
namespace llvm {
-class MCContext;
+
class raw_ostream;
/// \brief Instances of this class represent a label name in the MC file,
@@ -29,12 +27,13 @@ class MCLabel {
private: // MCContext creates and uniques these.
friend class MCContext;
+
MCLabel(unsigned instance) : Instance(instance) {}
+public:
MCLabel(const MCLabel &) = delete;
- void operator=(const MCLabel &) = delete;
+ MCLabel &operator=(const MCLabel &) = delete;
-public:
/// \brief Get the current instance of this Directional Local Label.
unsigned getInstance() const { return Instance; }
@@ -52,6 +51,7 @@ inline raw_ostream &operator<<(raw_ostream &OS, const MCLabel &Label) {
Label.print(OS);
return OS;
}
+
} // end namespace llvm
-#endif
+#endif // LLVM_MC_MCLABEL_H
diff --git a/include/llvm/MC/MCLinkerOptimizationHint.h b/include/llvm/MC/MCLinkerOptimizationHint.h
index 200bb93f64c8..0c3525bbeda6 100644
--- a/include/llvm/MC/MCLinkerOptimizationHint.h
+++ b/include/llvm/MC/MCLinkerOptimizationHint.h
@@ -21,13 +21,14 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/raw_ostream.h"
+#include <cassert>
+#include <cstdint>
namespace llvm {
-// Forward declarations.
+class MachObjectWriter;
class MCAsmLayout;
class MCSymbol;
-class MachObjectWriter;
/// Linker Optimization Hint Type.
enum MCLOHType {
@@ -133,7 +134,7 @@ public:
class MCLOHContainer {
/// Keep track of the emit size of all the LOHs.
- mutable uint64_t EmitSize;
+ mutable uint64_t EmitSize = 0;
/// Keep track of all LOH directives.
SmallVector<MCLOHDirective, 32> Directives;
@@ -141,7 +142,7 @@ class MCLOHContainer {
public:
typedef SmallVectorImpl<MCLOHDirective> LOHDirectives;
- MCLOHContainer() : EmitSize(0) {}
+ MCLOHContainer() = default;
/// Const accessor to the directives.
const LOHDirectives &getDirectives() const {
@@ -183,4 +184,4 @@ typedef MCLOHContainer::LOHDirectives MCLOHDirectives;
} // end namespace llvm
-#endif
+#endif // LLVM_MC_MCLINKEROPTIMIZATIONHINT_H
diff --git a/include/llvm/MC/MCMachObjectWriter.h b/include/llvm/MC/MCMachObjectWriter.h
index 1a685dbd608e..b93638f86408 100644
--- a/include/llvm/MC/MCMachObjectWriter.h
+++ b/include/llvm/MC/MCMachObjectWriter.h
@@ -1,4 +1,4 @@
-//===-- llvm/MC/MCMachObjectWriter.h - Mach Object Writer -------*- C++ -*-===//
+//===- llvm/MC/MCMachObjectWriter.h - Mach Object Writer --------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -11,12 +11,15 @@
#define LLVM_MC_MCMACHOBJECTWRITER_H
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCSection.h"
#include "llvm/MC/MCObjectWriter.h"
#include "llvm/MC/StringTableBuilder.h"
-#include "llvm/Support/DataTypes.h"
#include "llvm/Support/MachO.h"
+#include <cstdint>
+#include <memory>
+#include <string>
#include <vector>
namespace llvm {
@@ -95,8 +98,8 @@ class MachObjectWriter : public MCObjectWriter {
: Sym(Sym), MRE(MRE) {}
};
- llvm::DenseMap<const MCSection *, std::vector<RelAndSymbol>> Relocations;
- llvm::DenseMap<const MCSection *, unsigned> IndirectSymBase;
+ DenseMap<const MCSection *, std::vector<RelAndSymbol>> Relocations;
+ DenseMap<const MCSection *, unsigned> IndirectSymBase;
SectionAddrMap SectionAddress;
@@ -271,6 +274,6 @@ MCObjectWriter *createMachObjectWriter(MCMachObjectTargetWriter *MOTW,
raw_pwrite_stream &OS,
bool IsLittleEndian);
-} // End llvm namespace
+} // end namespace llvm
-#endif
+#endif // LLVM_MC_MCMACHOBJECTWRITER_H
diff --git a/include/llvm/MC/MCObjectFileInfo.h b/include/llvm/MC/MCObjectFileInfo.h
index 9aa8812c7bb3..8b2a1261b220 100644
--- a/include/llvm/MC/MCObjectFileInfo.h
+++ b/include/llvm/MC/MCObjectFileInfo.h
@@ -129,7 +129,7 @@ protected:
/// it'll go here.
MCSection *TLSExtraDataSection;
- /// Section directive for Thread Local data. ELF, MachO and COFF.
+ /// Section directive for Thread Local data. ELF, MachO, COFF, and Wasm.
MCSection *TLSDataSection; // Defaults to ".tdata".
/// Section directive for Thread Local uninitialized data.
@@ -338,7 +338,7 @@ public:
return EHFrameSection;
}
- enum Environment { IsMachO, IsELF, IsCOFF };
+ enum Environment { IsMachO, IsELF, IsCOFF, IsWasm };
Environment getObjectFileType() const { return Env; }
bool isPositionIndependent() const { return PositionIndependent; }
@@ -353,6 +353,7 @@ private:
void initMachOMCObjectFileInfo(const Triple &T);
void initELFMCObjectFileInfo(const Triple &T);
void initCOFFMCObjectFileInfo(const Triple &T);
+ void initWasmMCObjectFileInfo(const Triple &T);
public:
const Triple &getTargetTriple() const { return TT; }
diff --git a/include/llvm/MC/MCObjectStreamer.h b/include/llvm/MC/MCObjectStreamer.h
index f9111b7f47ea..7c1189e46ab2 100644
--- a/include/llvm/MC/MCObjectStreamer.h
+++ b/include/llvm/MC/MCObjectStreamer.h
@@ -89,7 +89,8 @@ public:
/// \name MCStreamer Interface
/// @{
- void EmitLabel(MCSymbol *Symbol) override;
+ void EmitLabel(MCSymbol *Symbol, SMLoc Loc = SMLoc()) override;
+ virtual void EmitLabel(MCSymbol *Symbol, SMLoc Loc, MCFragment *F);
void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) override;
void EmitValueImpl(const MCExpr *Value, unsigned Size,
SMLoc Loc = SMLoc()) override;
@@ -97,7 +98,8 @@ public:
void EmitSLEB128Value(const MCExpr *Value) override;
void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) override;
void ChangeSection(MCSection *Section, const MCExpr *Subsection) override;
- void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo& STI) override;
+ void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
+ bool = false) override;
/// \brief Emit an instruction to a special fragment, because this instruction
/// can change its size during relaxation.
@@ -152,6 +154,7 @@ public:
SMLoc Loc = SMLoc()) override;
void emitFill(const MCExpr &NumValues, int64_t Size, int64_t Expr,
SMLoc Loc = SMLoc()) override;
+ void EmitFileDirective(StringRef Filename) override;
void FinishImpl() override;
diff --git a/include/llvm/MC/MCObjectWriter.h b/include/llvm/MC/MCObjectWriter.h
index 0ecebe42a0b9..86bcbb6861d7 100644
--- a/include/llvm/MC/MCObjectWriter.h
+++ b/include/llvm/MC/MCObjectWriter.h
@@ -1,4 +1,4 @@
-//===-- llvm/MC/MCObjectWriter.h - Object File Writer Interface -*- C++ -*-===//
+//===- llvm/MC/MCObjectWriter.h - Object File Writer Interface --*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -11,13 +11,15 @@
#define LLVM_MC_MCOBJECTWRITER_H
#include "llvm/ADT/SmallVector.h"
-#include "llvm/Support/Compiler.h"
-#include "llvm/Support/DataTypes.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Endian.h"
#include "llvm/Support/EndianStream.h"
#include "llvm/Support/raw_ostream.h"
#include <cassert>
+#include <cstdint>
namespace llvm {
+
class MCAsmLayout;
class MCAssembler;
class MCFixup;
@@ -38,15 +40,12 @@ 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 &) = delete;
- void operator=(const MCObjectWriter &) = delete;
-
raw_pwrite_stream *OS;
protected:
unsigned IsLittleEndian : 1;
-protected: // Can only create subclasses.
+ // Can only create subclasses.
MCObjectWriter(raw_pwrite_stream &OS, bool IsLittleEndian)
: OS(&OS), IsLittleEndian(IsLittleEndian) {}
@@ -55,6 +54,8 @@ protected: // Can only create subclasses.
}
public:
+ MCObjectWriter(const MCObjectWriter &) = delete;
+ MCObjectWriter &operator=(const MCObjectWriter &) = delete;
virtual ~MCObjectWriter();
/// lifetime management
@@ -108,11 +109,6 @@ public:
bool InSet,
bool IsPCRel) const;
- /// 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;
-
/// Write the object file.
///
/// This routine is called by the assembler after layout and relaxation is
@@ -199,6 +195,6 @@ public:
/// @}
};
-} // End llvm namespace
+} // end namespace llvm
-#endif
+#endif // LLVM_MC_MCOBJECTWRITER_H
diff --git a/include/llvm/MC/MCParser/AsmCond.h b/include/llvm/MC/MCParser/AsmCond.h
index a918b5600ed5..8e7bfc521556 100644
--- a/include/llvm/MC/MCParser/AsmCond.h
+++ b/include/llvm/MC/MCParser/AsmCond.h
@@ -28,13 +28,13 @@ public:
ElseCond // inside else conditional
};
- ConditionalAssemblyType TheCond;
- bool CondMet;
- bool Ignore;
+ ConditionalAssemblyType TheCond = NoCond;
+ bool CondMet = false;
+ bool Ignore = false;
- AsmCond() : TheCond(NoCond), CondMet(false), Ignore(false) {}
+ AsmCond() = default;
};
} // end namespace llvm
-#endif
+#endif // LLVM_MC_MCPARSER_ASMCOND_H
diff --git a/include/llvm/MC/MCParser/AsmLexer.h b/include/llvm/MC/MCParser/AsmLexer.h
index 029598c013d3..207183a69b0e 100644
--- a/include/llvm/MC/MCParser/AsmLexer.h
+++ b/include/llvm/MC/MCParser/AsmLexer.h
@@ -16,25 +16,22 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/MC/MCParser/MCAsmLexer.h"
-#include "llvm/Support/DataTypes.h"
#include <string>
namespace llvm {
-class MemoryBuffer;
+
class MCAsmInfo;
/// AsmLexer - Lexer class for assembly files.
class AsmLexer : public MCAsmLexer {
const MCAsmInfo &MAI;
- const char *CurPtr;
+ const char *CurPtr = nullptr;
StringRef CurBuf;
- bool IsAtStartOfLine;
- bool IsAtStartOfStatement;
- bool IsParsingMSInlineAsm;
- bool IsPeeking;
- void operator=(const AsmLexer&) = delete;
- AsmLexer(const AsmLexer&) = delete;
+ bool IsAtStartOfLine = true;
+ bool IsAtStartOfStatement = true;
+ bool IsParsingMSInlineAsm = false;
+ bool IsPeeking = false;
protected:
/// LexToken - Read the next token and return its code.
@@ -42,6 +39,8 @@ protected:
public:
AsmLexer(const MCAsmInfo &MAI);
+ AsmLexer(const AsmLexer &) = delete;
+ AsmLexer &operator=(const AsmLexer &) = delete;
~AsmLexer() override;
void setBuffer(StringRef Buf, const char *ptr = nullptr);
@@ -74,4 +73,4 @@ private:
} // end namespace llvm
-#endif
+#endif // LLVM_MC_MCPARSER_ASMLEXER_H
diff --git a/include/llvm/MC/MCParser/MCAsmLexer.h b/include/llvm/MC/MCParser/MCAsmLexer.h
index 56da6f85c199..7ddc7722e512 100644
--- a/include/llvm/MC/MCParser/MCAsmLexer.h
+++ b/include/llvm/MC/MCParser/MCAsmLexer.h
@@ -1,4 +1,4 @@
-//===-- llvm/MC/MCAsmLexer.h - Abstract Asm Lexer Interface -----*- C++ -*-===//
+//===- llvm/MC/MCAsmLexer.h - Abstract Asm Lexer Interface ------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -14,10 +14,12 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/Compiler.h"
-#include "llvm/Support/DataTypes.h"
#include "llvm/Support/SMLoc.h"
-#include <utility>
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <string>
namespace llvm {
@@ -76,7 +78,7 @@ private:
APInt IntVal;
public:
- AsmToken() {}
+ AsmToken() = default;
AsmToken(TokenKind Kind, StringRef Str, APInt IntVal)
: Kind(Kind), Str(Str), IntVal(std::move(IntVal)) {}
AsmToken(TokenKind Kind, StringRef Str, int64_t IntVal = 0)
@@ -132,7 +134,7 @@ public:
/// it is lexed.
class AsmCommentConsumer {
public:
- virtual ~AsmCommentConsumer() {};
+ virtual ~AsmCommentConsumer() = default;
/// Callback function for when a comment is lexed. Loc is the start of the
/// comment text (excluding the comment-start marker). CommentText is the text
@@ -152,14 +154,12 @@ class MCAsmLexer {
SMLoc ErrLoc;
std::string Err;
- MCAsmLexer(const MCAsmLexer &) = delete;
- void operator=(const MCAsmLexer &) = delete;
protected: // Can only create subclasses.
- const char *TokStart;
- bool SkipSpace;
+ const char *TokStart = nullptr;
+ bool SkipSpace = true;
bool AllowAtInIdentifier;
- bool IsAtStartOfStatement;
- AsmCommentConsumer *CommentConsumer;
+ bool IsAtStartOfStatement = true;
+ AsmCommentConsumer *CommentConsumer = nullptr;
MCAsmLexer();
@@ -171,6 +171,8 @@ protected: // Can only create subclasses.
}
public:
+ MCAsmLexer(const MCAsmLexer &) = delete;
+ MCAsmLexer &operator=(const MCAsmLexer &) = delete;
virtual ~MCAsmLexer();
/// Consume the next token from the input stream and return it.
@@ -255,6 +257,6 @@ public:
}
};
-} // End llvm namespace
+} // end namespace llvm
-#endif
+#endif // LLVM_MC_MCPARSER_MCASMLEXER_H
diff --git a/include/llvm/MC/MCParser/MCAsmParser.h b/include/llvm/MC/MCParser/MCAsmParser.h
index eb85a3a30963..6763374185ec 100644
--- a/include/llvm/MC/MCParser/MCAsmParser.h
+++ b/include/llvm/MC/MCParser/MCAsmParser.h
@@ -1,4 +1,4 @@
-//===-- llvm/MC/MCAsmParser.h - Abstract Asm Parser Interface ---*- C++ -*-===//
+//===- llvm/MC/MCAsmParser.h - Abstract Asm Parser Interface ----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -10,16 +10,21 @@
#ifndef LLVM_MC_MCPARSER_MCASMPARSER_H
#define LLVM_MC_MCPARSER_MCASMPARSER_H
-#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/None.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
-#include "llvm/MC/MCParser/AsmLexer.h"
-#include "llvm/Support/DataTypes.h"
+#include "llvm/MC/MCParser/MCAsmLexer.h"
+#include "llvm/Support/SMLoc.h"
+#include <cstdint>
+#include <string>
+#include <utility>
namespace llvm {
+
class MCAsmInfo;
-class MCAsmLexer;
class MCAsmParserExtension;
class MCContext;
class MCExpr;
@@ -27,10 +32,7 @@ class MCInstPrinter;
class MCInstrInfo;
class MCStreamer;
class MCTargetAsmParser;
-class SMLoc;
-class SMRange;
class SourceMgr;
-class Twine;
class InlineAsmIdentifierInfo {
public:
@@ -51,12 +53,12 @@ public:
class MCAsmParserSemaCallback {
public:
virtual ~MCAsmParserSemaCallback();
+
virtual void *LookupInlineAsmIdentifier(StringRef &LineBuf,
InlineAsmIdentifierInfo &Info,
bool IsUnevaluatedContext) = 0;
virtual StringRef LookupInlineAsmLabel(StringRef Identifier, SourceMgr &SM,
SMLoc Location, bool Create) = 0;
-
virtual bool LookupInlineAsmField(StringRef Base, StringRef Member,
unsigned &Offset) = 0;
};
@@ -76,22 +78,21 @@ public:
};
private:
- MCAsmParser(const MCAsmParser &) = delete;
- void operator=(const MCAsmParser &) = delete;
-
- MCTargetAsmParser *TargetParser;
+ MCTargetAsmParser *TargetParser = nullptr;
unsigned ShowParsedOperands : 1;
protected: // Can only create subclasses.
MCAsmParser();
- bool HadError;
+ bool HadError = false;
SmallVector<MCPendingError, 1> PendingErrors;
/// Flag tracking whether any errors have been encountered.
public:
+ MCAsmParser(const MCAsmParser &) = delete;
+ MCAsmParser &operator=(const MCAsmParser &) = delete;
virtual ~MCAsmParser();
virtual void addDirectiveHandler(StringRef Directive,
@@ -186,12 +187,12 @@ public:
bool parseEOL(const Twine &ErrMsg);
- bool parseMany(std::function<bool()> parseOne, bool hasComma = true);
+ bool parseMany(function_ref<bool()> parseOne, bool hasComma = true);
bool parseIntToken(int64_t &V, const Twine &ErrMsg);
- bool check(bool P, const llvm::Twine &Msg);
- bool check(bool P, SMLoc Loc, const llvm::Twine &Msg);
+ bool check(bool P, const Twine &Msg);
+ bool check(bool P, SMLoc Loc, const Twine &Msg);
/// \brief Parse an identifier or string (as a quoted identifier) and set \p
/// Res to the identifier contents.
@@ -258,8 +259,8 @@ public:
/// \brief Create an MCAsmParser instance.
MCAsmParser *createMCAsmParser(SourceMgr &, MCContext &, MCStreamer &,
- const MCAsmInfo &);
+ const MCAsmInfo &, unsigned CB = 0);
-} // End llvm namespace
+} // end namespace llvm
-#endif
+#endif // LLVM_MC_MCPARSER_MCASMPARSER_H
diff --git a/include/llvm/MC/MCParser/MCAsmParserExtension.h b/include/llvm/MC/MCParser/MCAsmParserExtension.h
index dabda0ab9485..ffb8d7a4a26a 100644
--- a/include/llvm/MC/MCParser/MCAsmParserExtension.h
+++ b/include/llvm/MC/MCParser/MCAsmParserExtension.h
@@ -1,4 +1,4 @@
-//===-- llvm/MC/MCAsmParserExtension.h - Asm Parser Hooks -------*- C++ -*-===//
+//===- llvm/MC/MCAsmParserExtension.h - Asm Parser Hooks --------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -10,20 +10,20 @@
#ifndef LLVM_MC_MCPARSER_MCASMPARSEREXTENSION_H
#define LLVM_MC_MCPARSER_MCASMPARSEREXTENSION_H
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/MC/MCParser/MCAsmLexer.h"
#include "llvm/MC/MCParser/MCAsmParser.h"
#include "llvm/Support/SMLoc.h"
namespace llvm {
+
class Twine;
/// \brief Generic interface for extending the MCAsmParser,
/// which is implemented by target and object file assembly parser
/// implementations.
class MCAsmParserExtension {
- MCAsmParserExtension(const MCAsmParserExtension &) = delete;
- void operator=(const MCAsmParserExtension &) = delete;
-
MCAsmParser *Parser;
protected:
@@ -38,9 +38,11 @@ protected:
return (Obj->*Handler)(Directive, DirectiveLoc);
}
- bool BracketExpressionsSupported;
+ bool BracketExpressionsSupported = false;
public:
+ MCAsmParserExtension(const MCAsmParserExtension &) = delete;
+ MCAsmParserExtension &operator=(const MCAsmParserExtension &) = delete;
virtual ~MCAsmParserExtension();
/// \brief Initialize the extension for parsing using the given \p Parser.
@@ -65,15 +67,19 @@ public:
SourceMgr &getSourceManager() { return getParser().getSourceManager(); }
MCStreamer &getStreamer() { return getParser().getStreamer(); }
+
bool Warning(SMLoc L, const Twine &Msg) {
return getParser().Warning(L, Msg);
}
+
bool Error(SMLoc L, const Twine &Msg, SMRange Range = SMRange()) {
return getParser().Error(L, Msg, Range);
}
+
void Note(SMLoc L, const Twine &Msg) {
getParser().Note(L, Msg);
}
+
bool TokError(const Twine &Msg) {
return getParser().TokError(Msg);
}
@@ -85,7 +91,7 @@ public:
return getParser().parseToken(T, Msg);
}
- bool parseMany(std::function<bool()> parseOne, bool hasComma = true) {
+ bool parseMany(function_ref<bool()> parseOne, bool hasComma = true) {
return getParser().parseMany(parseOne, hasComma);
}
@@ -93,11 +99,11 @@ public:
return getParser().parseOptionalToken(T);
}
- bool check(bool P, const llvm::Twine &Msg) {
+ bool check(bool P, const Twine &Msg) {
return getParser().check(P, Msg);
}
- bool check(bool P, SMLoc Loc, const llvm::Twine &Msg) {
+ bool check(bool P, SMLoc Loc, const Twine &Msg) {
return getParser().check(P, Loc, Msg);
}
@@ -110,6 +116,6 @@ public:
/// @}
};
-} // End llvm namespace
+} // end namespace llvm
-#endif
+#endif // LLVM_MC_MCPARSER_MCASMPARSEREXTENSION_H
diff --git a/include/llvm/MC/MCParser/MCAsmParserUtils.h b/include/llvm/MC/MCParser/MCAsmParserUtils.h
index 9834fe96307b..84173bb9cb8e 100644
--- a/include/llvm/MC/MCParser/MCAsmParserUtils.h
+++ b/include/llvm/MC/MCParser/MCAsmParserUtils.h
@@ -1,4 +1,4 @@
-//===------ llvm/MC/MCAsmParserUtils.h - Asm Parser Utilities ---*- C++ -*-===//
+//===- llvm/MC/MCAsmParserUtils.h - Asm Parser Utilities --------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -28,6 +28,7 @@ bool parseAssignmentExpression(StringRef Name, bool allow_redef,
const MCExpr *&Value);
} // namespace MCParserUtils
+
} // namespace llvm
-#endif
+#endif // LLVM_MC_MCPARSER_MCASMPARSERUTILS_H
diff --git a/include/llvm/MC/MCParser/MCParsedAsmOperand.h b/include/llvm/MC/MCParser/MCParsedAsmOperand.h
index a90d280c240c..4af76ac2a858 100644
--- a/include/llvm/MC/MCParser/MCParsedAsmOperand.h
+++ b/include/llvm/MC/MCParser/MCParsedAsmOperand.h
@@ -1,4 +1,4 @@
-//===-- llvm/MC/MCParsedAsmOperand.h - Asm Parser Operand -------*- C++ -*-===//
+//===- llvm/MC/MCParsedAsmOperand.h - Asm Parser Operand --------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -10,11 +10,12 @@
#ifndef LLVM_MC_MCPARSER_MCPARSEDASMOPERAND_H
#define LLVM_MC_MCPARSER_MCPARSEDASMOPERAND_H
-#include <string>
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/SMLoc.h"
+#include <string>
namespace llvm {
+
class raw_ostream;
/// MCParsedAsmOperand - This abstract class represents a source-level assembly
@@ -35,12 +36,12 @@ protected:
// lots of members and MSVC doesn't support defaulted move ops, so to avoid
// that verbosity, just rely on defaulted copy ops. It's only the Constraint
// string member that would benefit from movement anyway.
+ MCParsedAsmOperand() = default;
MCParsedAsmOperand(const MCParsedAsmOperand &RHS) = default;
MCParsedAsmOperand &operator=(const MCParsedAsmOperand &) = default;
- MCParsedAsmOperand() = default;
public:
- virtual ~MCParsedAsmOperand() {}
+ virtual ~MCParsedAsmOperand() = default;
void setConstraint(StringRef C) { Constraint = C.str(); }
StringRef getConstraint() { return Constraint; }
@@ -81,6 +82,7 @@ public:
/// print - Print a debug representation of the operand to the given stream.
virtual void print(raw_ostream &OS) const = 0;
+
/// dump - Print to the debug stream.
virtual void dump() const;
};
@@ -93,6 +95,6 @@ inline raw_ostream& operator<<(raw_ostream &OS, const MCParsedAsmOperand &MO) {
return OS;
}
-} // end namespace llvm.
+} // end namespace llvm
-#endif
+#endif // LLVM_MC_MCPARSER_MCPARSEDASMOPERAND_H
diff --git a/include/llvm/MC/MCParser/MCTargetAsmParser.h b/include/llvm/MC/MCParser/MCTargetAsmParser.h
index 70cd60c9a112..c81a7624011f 100644
--- a/include/llvm/MC/MCParser/MCTargetAsmParser.h
+++ b/include/llvm/MC/MCParser/MCTargetAsmParser.h
@@ -1,4 +1,4 @@
-//===-- llvm/MC/MCTargetAsmParser.h - Target Assembly Parser ----*- C++ -*-===//
+//===- llvm/MC/MCTargetAsmParser.h - Target Assembly Parser -----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -10,19 +10,21 @@
#ifndef LLVM_MC_MCPARSER_MCTARGETASMPARSER_H
#define LLVM_MC_MCPARSER_MCTARGETASMPARSER_H
+#include "llvm/ADT/StringRef.h"
#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCParser/MCAsmLexer.h"
#include "llvm/MC/MCParser/MCAsmParserExtension.h"
#include "llvm/MC/MCTargetOptions.h"
+#include "llvm/Support/SMLoc.h"
+#include <cstdint>
#include <memory>
namespace llvm {
-class AsmToken;
+
class MCInst;
class MCParsedAsmOperand;
class MCStreamer;
class MCSubtargetInfo;
-class SMLoc;
-class StringRef;
template <typename T> class SmallVectorImpl;
typedef SmallVectorImpl<std::unique_ptr<MCParsedAsmOperand>> OperandVector;
@@ -66,6 +68,7 @@ struct AsmRewrite {
unsigned Len;
unsigned Val;
StringRef Label;
+
public:
AsmRewrite(AsmRewriteKind kind, SMLoc loc, unsigned len = 0, unsigned val = 0)
: Kind(kind), Loc(loc), Len(len), Val(val) {}
@@ -74,10 +77,9 @@ public:
};
struct ParseInstructionInfo {
+ SmallVectorImpl<AsmRewrite> *AsmRewrites = nullptr;
- SmallVectorImpl<AsmRewrite> *AsmRewrites;
-
- ParseInstructionInfo() : AsmRewrites(nullptr) {}
+ ParseInstructionInfo() = default;
ParseInstructionInfo(SmallVectorImpl<AsmRewrite> *rewrites)
: AsmRewrites(rewrites) {}
};
@@ -99,9 +101,6 @@ public:
FIRST_TARGET_MATCH_RESULT_TY
};
-private:
- MCTargetAsmParser(const MCTargetAsmParser &) = delete;
- void operator=(const MCTargetAsmParser &) = delete;
protected: // Can only create subclasses.
MCTargetAsmParser(MCTargetOptions const &, const MCSubtargetInfo &STI);
@@ -109,10 +108,10 @@ protected: // Can only create subclasses.
MCSubtargetInfo &copySTI();
/// AvailableFeatures - The current set of available features.
- uint64_t AvailableFeatures;
+ uint64_t AvailableFeatures = 0;
/// ParsingInlineAsm - Are we parsing ms-style inline assembly?
- bool ParsingInlineAsm;
+ bool ParsingInlineAsm = false;
/// SemaCallback - The Sema callback implementation. Must be set when parsing
/// ms-style inline assembly.
@@ -125,6 +124,9 @@ protected: // Can only create subclasses.
const MCSubtargetInfo *STI;
public:
+ MCTargetAsmParser(const MCTargetAsmParser &) = delete;
+ MCTargetAsmParser &operator=(const MCTargetAsmParser &) = delete;
+
~MCTargetAsmParser() override;
const MCSubtargetInfo &getSTI() const;
@@ -229,11 +231,11 @@ public:
return nullptr;
}
- virtual void onLabelParsed(MCSymbol *Symbol) { }
+ virtual void onLabelParsed(MCSymbol *Symbol) {}
/// Ensure that all previously parsed instructions have been emitted to the
/// output streamer, if the target does not emit them immediately.
- virtual void flushPendingInstructions(MCStreamer &Out) { }
+ virtual void flushPendingInstructions(MCStreamer &Out) {}
virtual const MCExpr *createTargetUnaryExpr(const MCExpr *E,
AsmToken::TokenKind OperatorToken,
@@ -242,6 +244,6 @@ public:
}
};
-} // End llvm namespace
+} // end namespace llvm
-#endif
+#endif // LLVM_MC_MCPARSER_MCTARGETASMPARSER_H
diff --git a/include/llvm/MC/MCRegisterInfo.h b/include/llvm/MC/MCRegisterInfo.h
index 3dc88a298ff8..015d0b96d9f2 100644
--- a/include/llvm/MC/MCRegisterInfo.h
+++ b/include/llvm/MC/MCRegisterInfo.h
@@ -1,4 +1,4 @@
-//=== MC/MCRegisterInfo.h - Target Register Description ---------*- C++ -*-===//
+//===- MC/MCRegisterInfo.h - Target Register Description --------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -17,9 +17,11 @@
#define LLVM_MC_MCREGISTERINFO_H
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/iterator_range.h"
#include "llvm/MC/LaneBitmask.h"
-#include "llvm/Support/ErrorHandling.h"
#include <cassert>
+#include <cstdint>
+#include <utility>
namespace llvm {
@@ -39,7 +41,7 @@ public:
const uint16_t RegsSize;
const uint16_t RegSetSize;
const uint16_t ID;
- const uint16_t RegSize, Alignment; // Size & Alignment of register in bytes
+ const uint16_t PhysRegSize;
const int8_t CopyCost;
const bool Allocatable;
@@ -78,13 +80,10 @@ public:
return contains(Reg1) && contains(Reg2);
}
- /// getSize - Return the size of the register in bytes, which is also the size
- /// of a stack slot allocated to hold a spilled copy of this register.
- unsigned getSize() const { return RegSize; }
-
- /// getAlignment - Return the minimum required alignment for a register of
- /// this class.
- unsigned getAlignment() const { return Alignment; }
+ /// Return the size of the physical register in bytes.
+ unsigned getPhysRegSize() const { return PhysRegSize; }
+ /// Temporary function to allow out-of-tree targets to switch.
+ unsigned getSize() const { return getPhysRegSize(); }
/// getCopyCost - Return the cost of copying a value between two registers in
/// this class. A negative number means the register class is very expensive
@@ -152,6 +151,7 @@ public:
uint16_t Offset;
uint16_t Size;
};
+
private:
const MCRegisterDesc *Desc; // Pointer to the descriptor array
unsigned NumRegs; // Number of entries in the array
@@ -191,12 +191,12 @@ public:
/// Don't use this class directly, use one of the specialized sub-classes
/// defined below.
class DiffListIterator {
- uint16_t Val;
- const MCPhysReg *List;
+ uint16_t Val = 0;
+ const MCPhysReg *List = nullptr;
protected:
/// Create an invalid iterator. Call init() to point to something useful.
- DiffListIterator() : Val(0), List(nullptr) {}
+ DiffListIterator() = default;
/// init - Point the iterator to InitVal, decoding subsequent values from
/// DiffList. The iterator will initially point to InitVal, sub-classes are
@@ -217,7 +217,6 @@ public:
}
public:
-
/// isValid - returns true if this iterator is not yet at the end.
bool isValid() const { return List; }
@@ -418,6 +417,9 @@ public:
regclass_iterator regclass_begin() const { return Classes; }
regclass_iterator regclass_end() const { return Classes+NumClasses; }
+ iterator_range<regclass_iterator> regclasses() const {
+ return make_range(regclass_begin(), regclass_end());
+ }
unsigned getNumRegClasses() const {
return (unsigned)(regclass_end()-regclass_begin());
@@ -492,6 +494,7 @@ public:
class MCSubRegIndexIterator {
MCSubRegIterator SRIter;
const uint16_t *SRIndex;
+
public:
/// Constructs an iterator that traverses subregisters and their
/// associated subregister indices.
@@ -504,6 +507,7 @@ public:
unsigned getSubReg() const {
return *SRIter;
}
+
/// Returns sub-register index of the current sub-register.
unsigned getSubRegIndex() const {
return *SRIndex;
@@ -523,7 +527,8 @@ public:
/// If IncludeSelf is set, Reg itself is included in the list.
class MCSuperRegIterator : public MCRegisterInfo::DiffListIterator {
public:
- MCSuperRegIterator() {}
+ MCSuperRegIterator() = default;
+
MCSuperRegIterator(unsigned Reg, const MCRegisterInfo *MCRI,
bool IncludeSelf = false) {
init(Reg, MCRI->DiffLists + MCRI->get(Reg).SuperRegs);
@@ -560,7 +565,8 @@ class MCRegUnitIterator : public MCRegisterInfo::DiffListIterator {
public:
/// MCRegUnitIterator - Create an iterator that traverses the register units
/// in Reg.
- MCRegUnitIterator() {}
+ MCRegUnitIterator() = default;
+
MCRegUnitIterator(unsigned Reg, const MCRegisterInfo *MCRI) {
assert(Reg && "Null register has no regunits");
// Decode the RegUnits MCRegisterDesc field.
@@ -586,8 +592,10 @@ public:
class MCRegUnitMaskIterator {
MCRegUnitIterator RUIter;
const LaneBitmask *MaskListIter;
+
public:
- MCRegUnitMaskIterator() {}
+ MCRegUnitMaskIterator() = default;
+
/// Constructs an iterator that traverses the register units and their
/// associated LaneMasks in Reg.
MCRegUnitMaskIterator(unsigned Reg, const MCRegisterInfo *MCRI)
@@ -622,10 +630,12 @@ public:
/// MCRegUnitRootIterator enumerates the root registers of a register unit.
class MCRegUnitRootIterator {
- uint16_t Reg0;
- uint16_t Reg1;
+ uint16_t Reg0 = 0;
+ uint16_t Reg1 = 0;
+
public:
- MCRegUnitRootIterator() : Reg0(0), Reg1(0) {}
+ MCRegUnitRootIterator() = default;
+
MCRegUnitRootIterator(unsigned RegUnit, const MCRegisterInfo *MCRI) {
assert(RegUnit < MCRI->getNumRegUnits() && "Invalid register unit");
Reg0 = MCRI->RegUnitRoots[RegUnit][0];
@@ -662,11 +672,11 @@ private:
MCRegUnitIterator RI;
MCRegUnitRootIterator RRI;
MCSuperRegIterator SI;
+
public:
MCRegAliasIterator(unsigned Reg, const MCRegisterInfo *MCRI,
bool IncludeSelf)
: Reg(Reg), MCRI(MCRI), IncludeSelf(IncludeSelf) {
-
// Initialize the iterators.
for (RI = MCRegUnitIterator(Reg, MCRI); RI.isValid(); ++RI) {
for (RRI = MCRegUnitRootIterator(*RI, MCRI); RRI.isValid(); ++RRI) {
@@ -681,7 +691,7 @@ public:
bool isValid() const { return RI.isValid(); }
unsigned operator*() const {
- assert (SI.isValid() && "Cannot dereference an invalid iterator.");
+ assert(SI.isValid() && "Cannot dereference an invalid iterator.");
return *SI;
}
@@ -710,6 +720,6 @@ public:
}
};
-} // End llvm namespace
+} // end namespace llvm
-#endif
+#endif // LLVM_MC_MCREGISTERINFO_H
diff --git a/include/llvm/MC/MCSection.h b/include/llvm/MC/MCSection.h
index d4c31696b40f..2974d8f1b80b 100644
--- a/include/llvm/MC/MCSection.h
+++ b/include/llvm/MC/MCSection.h
@@ -14,22 +14,21 @@
#ifndef LLVM_MC_MCSECTION_H
#define LLVM_MC_MCSECTION_H
-#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/ilist.h"
-#include "llvm/ADT/ilist_node.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/MC/MCFragment.h"
#include "llvm/MC/SectionKind.h"
-#include "llvm/Support/Compiler.h"
+#include <cassert>
+#include <utility>
namespace llvm {
+
class MCAsmInfo;
-class MCAssembler;
class MCContext;
class MCExpr;
-class MCFragment;
-class MCSection;
class MCSymbol;
class raw_ostream;
+class Triple;
template <> struct ilist_alloc_traits<MCFragment> {
static void deleteNode(MCFragment *V);
@@ -39,7 +38,7 @@ template <> struct ilist_alloc_traits<MCFragment> {
/// current translation unit. The MCContext class uniques and creates these.
class MCSection {
public:
- enum SectionVariant { SV_COFF = 0, SV_ELF, SV_MachO };
+ enum SectionVariant { SV_COFF = 0, SV_ELF, SV_MachO, SV_Wasm };
/// \brief Express the state of bundle locked groups while emitting code.
enum BundleLockStateType {
@@ -57,9 +56,6 @@ public:
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.
@@ -77,12 +73,12 @@ private:
/// \brief We've seen a bundle_lock directive but not its first instruction
/// yet.
- unsigned BundleGroupBeforeFirstInst : 1;
+ bool BundleGroupBeforeFirstInst : 1;
/// Whether this section has had instructions emitted into it.
- unsigned HasInstructions : 1;
+ bool HasInstructions : 1;
- unsigned IsRegistered : 1;
+ bool IsRegistered : 1;
MCDummyFragment DummyFragment;
@@ -93,12 +89,16 @@ private:
SmallVector<std::pair<unsigned, MCFragment *>, 1> SubsectionFragmentMap;
protected:
- MCSection(SectionVariant V, SectionKind K, MCSymbol *Begin);
SectionVariant Variant;
SectionKind Kind;
+
+ MCSection(SectionVariant V, SectionKind K, MCSymbol *Begin);
~MCSection();
public:
+ MCSection(const MCSection &) = delete;
+ MCSection &operator=(const MCSection &) = delete;
+
SectionKind getKind() const { return Kind; }
SectionVariant getVariant() const { return Variant; }
@@ -169,7 +169,8 @@ public:
void dump();
- virtual void PrintSwitchToSection(const MCAsmInfo &MAI, raw_ostream &OS,
+ virtual void PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T,
+ raw_ostream &OS,
const MCExpr *Subsection) const = 0;
/// Return true if a .align directive should use "optimized nops" to fill
@@ -183,4 +184,4 @@ public:
} // end namespace llvm
-#endif
+#endif // LLVM_MC_MCSECTION_H
diff --git a/include/llvm/MC/MCSectionCOFF.h b/include/llvm/MC/MCSectionCOFF.h
index 7d5f9f7f3cde..24b9f8898ebb 100644
--- a/include/llvm/MC/MCSectionCOFF.h
+++ b/include/llvm/MC/MCSectionCOFF.h
@@ -16,8 +16,11 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/MC/MCSection.h"
+#include "llvm/MC/SectionKind.h"
+#include <cassert>
namespace llvm {
+
class MCSymbol;
/// This represents a section on Windows
@@ -73,7 +76,8 @@ public:
void setSelection(int Selection) const;
- void PrintSwitchToSection(const MCAsmInfo &MAI, raw_ostream &OS,
+ void PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T,
+ raw_ostream &OS,
const MCExpr *Subsection) const override;
bool UseCodeAlign() const override;
bool isVirtualSection() const override;
@@ -93,4 +97,4 @@ public:
} // end namespace llvm
-#endif
+#endif // LLVM_MC_MCSECTIONCOFF_H
diff --git a/include/llvm/MC/MCSectionELF.h b/include/llvm/MC/MCSectionELF.h
index dabd787b0d45..00c289c6bd6e 100644
--- a/include/llvm/MC/MCSectionELF.h
+++ b/include/llvm/MC/MCSectionELF.h
@@ -14,12 +14,10 @@
#ifndef LLVM_MC_MCSECTIONELF_H
#define LLVM_MC_MCSECTIONELF_H
-#include "llvm/ADT/Twine.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/MC/MCSection.h"
#include "llvm/MC/MCSymbolELF.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/ELF.h"
-#include "llvm/Support/raw_ostream.h"
+#include "llvm/MC/SectionKind.h"
namespace llvm {
@@ -47,17 +45,18 @@ class MCSectionELF final : public MCSection {
const MCSymbolELF *Group;
- /// Depending on the type of the section this is sh_link or sh_info.
- const MCSectionELF *Associated;
+ /// sh_info for SHF_LINK_ORDER (can be null).
+ const MCSymbol *AssociatedSymbol;
private:
friend class MCContext;
+
MCSectionELF(StringRef Section, unsigned type, unsigned flags, SectionKind K,
unsigned entrySize, const MCSymbolELF *group, unsigned UniqueID,
- MCSymbol *Begin, const MCSectionELF *Associated)
+ MCSymbol *Begin, const MCSymbolELF *AssociatedSymbol)
: MCSection(SV_ELF, K, Begin), SectionName(Section), Type(type),
Flags(flags), UniqueID(UniqueID), EntrySize(entrySize), Group(group),
- Associated(Associated) {
+ AssociatedSymbol(AssociatedSymbol) {
if (Group)
Group->setIsSignature();
}
@@ -78,7 +77,8 @@ public:
void setFlags(unsigned F) { Flags = F; }
const MCSymbolELF *getGroup() const { return Group; }
- void PrintSwitchToSection(const MCAsmInfo &MAI, raw_ostream &OS,
+ void PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T,
+ raw_ostream &OS,
const MCExpr *Subsection) const override;
bool UseCodeAlign() const override;
bool isVirtualSection() const override;
@@ -86,7 +86,8 @@ public:
bool isUnique() const { return UniqueID != ~0U; }
unsigned getUniqueID() const { return UniqueID; }
- const MCSectionELF *getAssociatedSection() const { return Associated; }
+ const MCSection *getAssociatedSection() const { return &AssociatedSymbol->getSection(); }
+ const MCSymbol *getAssociatedSymbol() const { return AssociatedSymbol; }
static bool classof(const MCSection *S) {
return S->getVariant() == SV_ELF;
@@ -95,4 +96,4 @@ public:
} // end namespace llvm
-#endif
+#endif // LLVM_MC_MCSECTIONELF_H
diff --git a/include/llvm/MC/MCSectionMachO.h b/include/llvm/MC/MCSectionMachO.h
index 658dfcda7268..3bc5408a4f75 100644
--- a/include/llvm/MC/MCSectionMachO.h
+++ b/include/llvm/MC/MCSectionMachO.h
@@ -76,7 +76,8 @@ public:
bool &TAAParsed, // Out.
unsigned &StubSize); // Out.
- void PrintSwitchToSection(const MCAsmInfo &MAI, raw_ostream &OS,
+ void PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T,
+ raw_ostream &OS,
const MCExpr *Subsection) const override;
bool UseCodeAlign() const override;
bool isVirtualSection() const override;
diff --git a/include/llvm/MC/MCSectionWasm.h b/include/llvm/MC/MCSectionWasm.h
new file mode 100644
index 000000000000..4e19196175c0
--- /dev/null
+++ b/include/llvm/MC/MCSectionWasm.h
@@ -0,0 +1,86 @@
+//===- MCSectionWasm.h - Wasm Machine Code Sections -------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares the MCSectionWasm class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_MC_MCSECTIONWASM_H
+#define LLVM_MC_MCSECTIONWASM_H
+
+#include "llvm/ADT/Twine.h"
+#include "llvm/MC/MCSection.h"
+#include "llvm/MC/MCSymbolWasm.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace llvm {
+
+class MCSymbol;
+
+/// This represents a section on wasm.
+class MCSectionWasm final : public MCSection {
+ /// This is the name of the section. The referenced memory is owned by
+ /// TargetLoweringObjectFileWasm's WasmUniqueMap.
+ StringRef SectionName;
+
+ /// This is the sh_type field of a section, drawn from the enums below.
+ unsigned Type;
+
+ /// This is the sh_flags field of a section, drawn from the enums below.
+ unsigned Flags;
+
+ unsigned UniqueID;
+
+ const MCSymbolWasm *Group;
+
+ // The offset of the MC function section in the wasm code section.
+ uint64_t SectionOffset;
+
+private:
+ friend class MCContext;
+ MCSectionWasm(StringRef Section, unsigned type, unsigned flags, SectionKind K,
+ const MCSymbolWasm *group, unsigned UniqueID, MCSymbol *Begin)
+ : MCSection(SV_Wasm, K, Begin), SectionName(Section), Type(type),
+ Flags(flags), UniqueID(UniqueID), Group(group), SectionOffset(0) {
+ }
+
+ void setSectionName(StringRef Name) { SectionName = Name; }
+
+public:
+ ~MCSectionWasm();
+
+ /// Decides whether a '.section' directive should be printed before the
+ /// section name
+ bool ShouldOmitSectionDirective(StringRef Name, const MCAsmInfo &MAI) const;
+
+ StringRef getSectionName() const { return SectionName; }
+ unsigned getType() const { return Type; }
+ unsigned getFlags() const { return Flags; }
+ void setFlags(unsigned F) { Flags = F; }
+ const MCSymbolWasm *getGroup() const { return Group; }
+
+ void PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T,
+ raw_ostream &OS,
+ const MCExpr *Subsection) const override;
+ bool UseCodeAlign() const override;
+ bool isVirtualSection() const override;
+
+ bool isUnique() const { return UniqueID != ~0U; }
+ unsigned getUniqueID() const { return UniqueID; }
+
+ uint64_t getSectionOffset() const { return SectionOffset; }
+ void setSectionOffset(uint64_t Offset) { SectionOffset = Offset; }
+
+ static bool classof(const MCSection *S) { return S->getVariant() == SV_Wasm; }
+};
+
+} // end namespace llvm
+
+#endif
diff --git a/include/llvm/MC/MCStreamer.h b/include/llvm/MC/MCStreamer.h
index 41f00a24dfbf..e466b368ed34 100644
--- a/include/llvm/MC/MCStreamer.h
+++ b/include/llvm/MC/MCStreamer.h
@@ -15,17 +15,26 @@
#define LLVM_MC_MCSTREAMER_H
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/MC/MCDirectives.h"
#include "llvm/MC/MCDwarf.h"
#include "llvm/MC/MCLinkerOptimizationHint.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/MC/MCWinEH.h"
-#include "llvm/Support/DataTypes.h"
#include "llvm/Support/SMLoc.h"
+#include <cassert>
+#include <cstdint>
+#include <memory>
#include <string>
+#include <utility>
+#include <vector>
namespace llvm {
+
+class AssemblerConstantPools;
+class formatted_raw_ostream;
class MCAsmBackend;
class MCCodeEmitter;
class MCContext;
@@ -34,14 +43,11 @@ class MCInst;
class MCInstPrinter;
class MCSection;
class MCStreamer;
-class MCSymbolELF;
class MCSymbolRefExpr;
+class MCSymbolWasm;
class MCSubtargetInfo;
-class StringRef;
-class Twine;
class raw_ostream;
-class formatted_raw_ostream;
-class AssemblerConstantPools;
+class Twine;
typedef std::pair<MCSection *, const MCExpr *> MCSectionSubPair;
@@ -162,9 +168,6 @@ class MCStreamer {
MCContext &Context;
std::unique_ptr<MCTargetStreamer> TargetStreamer;
- MCStreamer(const MCStreamer &) = delete;
- MCStreamer &operator=(const MCStreamer &) = delete;
-
std::vector<MCDwarfFrameInfo> DwarfFrameInfos;
MCDwarfFrameInfo *getCurrentDwarfFrameInfo();
void EnsureValidDwarfFrame();
@@ -205,6 +208,8 @@ protected:
virtual void EmitRawTextImpl(StringRef String);
public:
+ MCStreamer(const MCStreamer &) = delete;
+ MCStreamer &operator=(const MCStreamer &) = delete;
virtual ~MCStreamer();
void visitUsedExpr(const MCExpr &Expr);
@@ -282,6 +287,7 @@ public:
/// \brief Add explicit comment T. T is required to be a valid
/// comment in the output and does not need to be escaped.
virtual void addExplicitComment(const Twine &T);
+
/// \brief Emit added explicit comments.
virtual void emitExplicitComments();
@@ -393,7 +399,7 @@ public:
/// used in an assignment.
// FIXME: These emission are non-const because we mutate the symbol to
// add the section we're emitting it to later.
- virtual void EmitLabel(MCSymbol *Symbol);
+ virtual void EmitLabel(MCSymbol *Symbol, SMLoc Loc = SMLoc());
virtual void EmitEHSymAttributes(const MCSymbol *Symbol, MCSymbol *EHSymbol);
@@ -483,6 +489,14 @@ public:
/// .size symbol, expression
virtual void emitELFSize(MCSymbol *Symbol, const MCExpr *Value);
+ /// \brief Emit an ELF .symver directive.
+ ///
+ /// This corresponds to an assembler statement such as:
+ /// .symver _start, foo@@SOME_VERSION
+ /// \param Alias - The versioned alias (i.e. "foo@@SOME_VERSION")
+ /// \param Aliasee - The aliased symbol (i.e. "_start")
+ virtual void emitELFSymverDirective(MCSymbol *Alias, const MCSymbol *Aliasee);
+
/// \brief Emit a Linker Optimization Hint (LOH) directive.
/// \param Args - Arguments of the LOH.
virtual void EmitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) {}
@@ -822,7 +836,9 @@ public:
}
/// \brief Emit the given \p Instruction into the current section.
- virtual void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI);
+ /// PrintSchedInfo == true then schedul comment should be added to output
+ virtual void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
+ bool PrintSchedInfo = false);
/// \brief Set the bundle alignment mode from now on in the section.
/// The argument is the power of 2 to which the alignment is set. The
@@ -876,6 +892,7 @@ MCStreamer *createAsmStreamer(MCContext &Ctx,
bool isVerboseAsm, bool useDwarfDirectory,
MCInstPrinter *InstPrint, MCCodeEmitter *CE,
MCAsmBackend *TAB, bool ShowInst);
+
} // end namespace llvm
-#endif
+#endif // LLVM_MC_MCSTREAMER_H
diff --git a/include/llvm/MC/MCSubtargetInfo.h b/include/llvm/MC/MCSubtargetInfo.h
index 5ede043fa2ee..6229db3bbcb2 100644
--- a/include/llvm/MC/MCSubtargetInfo.h
+++ b/include/llvm/MC/MCSubtargetInfo.h
@@ -1,4 +1,4 @@
-//==-- llvm/MC/MCSubtargetInfo.h - Subtarget Information ---------*- C++ -*-==//
+//===- llvm/MC/MCSubtargetInfo.h - Subtarget Information --------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -15,13 +15,19 @@
#define LLVM_MC_MCSUBTARGETINFO_H
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Triple.h"
#include "llvm/MC/MCInstrItineraries.h"
+#include "llvm/MC/MCSchedule.h"
#include "llvm/MC/SubtargetFeature.h"
+#include <algorithm>
+#include <cassert>
+#include <cstdint>
#include <string>
namespace llvm {
-
-class StringRef;
+class MachineInstr;
+class MCInst;
//===----------------------------------------------------------------------===//
///
@@ -45,10 +51,6 @@ class MCSubtargetInfo {
const unsigned *ForwardingPaths; // Forwarding paths
FeatureBitset FeatureBits; // Feature bits for current CPU + FS
- MCSubtargetInfo() = delete;
- MCSubtargetInfo &operator=(MCSubtargetInfo &&) = delete;
- MCSubtargetInfo &operator=(const MCSubtargetInfo &) = delete;
-
public:
MCSubtargetInfo(const MCSubtargetInfo &) = default;
MCSubtargetInfo(const Triple &TT, StringRef CPU, StringRef FS,
@@ -58,6 +60,11 @@ public:
const MCWriteProcResEntry *WPR, const MCWriteLatencyEntry *WL,
const MCReadAdvanceEntry *RA, const InstrStage *IS,
const unsigned *OC, const unsigned *FP);
+ MCSubtargetInfo() = delete;
+ MCSubtargetInfo &operator=(const MCSubtargetInfo &) = delete;
+ MCSubtargetInfo &operator=(MCSubtargetInfo &&) = delete;
+
+ virtual ~MCSubtargetInfo() {}
/// getTargetTriple - Return the target triple string.
const Triple &getTargetTriple() const { return TargetTriple; }
@@ -164,8 +171,17 @@ public:
auto Found = std::lower_bound(ProcDesc.begin(), ProcDesc.end(), CPU);
return Found != ProcDesc.end() && StringRef(Found->Key) == CPU;
}
+
+ /// Returns string representation of scheduler comment
+ virtual std::string getSchedInfoStr(const MachineInstr &MI) const {
+ return std::string();
+ }
+
+ virtual std::string getSchedInfoStr(MCInst const &MCI) const {
+ return std::string();
+ }
};
-} // End llvm namespace
+} // end namespace llvm
-#endif
+#endif // LLVM_MC_MCSUBTARGETINFO_H
diff --git a/include/llvm/MC/MCSymbol.h b/include/llvm/MC/MCSymbol.h
index 23e34b7869a5..e8432afd8627 100644
--- a/include/llvm/MC/MCSymbol.h
+++ b/include/llvm/MC/MCSymbol.h
@@ -15,18 +15,21 @@
#define LLVM_MC_MCSYMBOL_H
#include "llvm/ADT/PointerIntPair.h"
-#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/MC/MCFragment.h"
-#include "llvm/Support/Compiler.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/MathExtras.h"
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
namespace llvm {
+
class MCAsmInfo;
+class MCContext;
class MCExpr;
-class MCSymbol;
-class MCFragment;
class MCSection;
-class MCContext;
class raw_ostream;
/// MCSymbol - Instances of this class represent a symbol name in the MC file,
@@ -45,6 +48,7 @@ protected:
SymbolKindCOFF,
SymbolKindELF,
SymbolKindMachO,
+ SymbolKindWasm,
};
/// A symbol can contain an Offset, or Value, or be Common, but never more
@@ -97,7 +101,7 @@ protected:
/// LLVM RTTI discriminator. This is actually a SymbolKind enumerator, but is
/// unsigned to avoid sign extension and achieve better bitpacking with MSVC.
- unsigned Kind : 2;
+ unsigned Kind : 3;
/// True if we have created a relocation that uses this symbol.
mutable unsigned IsUsedInReloc : 1;
@@ -133,7 +137,7 @@ protected:
const MCExpr *Value;
};
-protected: // MCContext creates and uniques these.
+ // MCContext creates and uniques these.
friend class MCExpr;
friend class MCContext;
@@ -163,7 +167,6 @@ protected: // MCContext creates and uniques these.
MCContext &Ctx);
private:
-
void operator delete(void *);
/// \brief Placement delete - required by std, but never called.
void operator delete(void*, unsigned) {
@@ -174,8 +177,6 @@ private:
llvm_unreachable("Constructor throws?");
}
- MCSymbol(const MCSymbol &) = delete;
- void operator=(const MCSymbol &) = delete;
MCSection *getSectionPtr(bool SetUsed = true) const {
if (MCFragment *F = getFragment(SetUsed)) {
assert(F != AbsolutePseudoFragment);
@@ -195,6 +196,9 @@ private:
}
public:
+ MCSymbol(const MCSymbol &) = delete;
+ MCSymbol &operator=(const MCSymbol &) = delete;
+
/// getName - Get the symbol name.
StringRef getName() const {
if (!FragmentAndHasName.getInt())
@@ -281,6 +285,8 @@ public:
bool isMachO() const { return Kind == SymbolKindMachO; }
+ bool isWasm() const { return Kind == SymbolKindWasm; }
+
/// @}
/// \name Variable Symbols
/// @{
@@ -416,6 +422,7 @@ inline raw_ostream &operator<<(raw_ostream &OS, const MCSymbol &Sym) {
Sym.print(OS, nullptr);
return OS;
}
+
} // end namespace llvm
-#endif
+#endif // LLVM_MC_MCSYMBOL_H
diff --git a/include/llvm/MC/MCSymbolCOFF.h b/include/llvm/MC/MCSymbolCOFF.h
index 2172c67981c0..7918c353dc15 100644
--- a/include/llvm/MC/MCSymbolCOFF.h
+++ b/include/llvm/MC/MCSymbolCOFF.h
@@ -6,16 +6,18 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
+
#ifndef LLVM_MC_MCSYMBOLCOFF_H
#define LLVM_MC_MCSYMBOLCOFF_H
#include "llvm/MC/MCSymbol.h"
+#include <cstdint>
namespace llvm {
-class MCSymbolCOFF : public MCSymbol {
+class MCSymbolCOFF : public MCSymbol {
/// This corresponds to the e_type field of the COFF symbol.
- mutable uint16_t Type;
+ mutable uint16_t Type = 0;
enum SymbolFlags : uint16_t {
SF_ClassMask = 0x00FF,
@@ -27,7 +29,7 @@ class MCSymbolCOFF : public MCSymbol {
public:
MCSymbolCOFF(const StringMapEntry<bool> *Name, bool isTemporary)
- : MCSymbol(SymbolKindCOFF, Name, isTemporary), Type(0) {}
+ : MCSymbol(SymbolKindCOFF, Name, isTemporary) {}
uint16_t getType() const {
return Type;
@@ -59,6 +61,7 @@ public:
static bool classof(const MCSymbol *S) { return S->isCOFF(); }
};
-}
-#endif
+} // end namespace llvm
+
+#endif // LLVM_MC_MCSYMBOLCOFF_H
diff --git a/include/llvm/MC/MCSymbolWasm.h b/include/llvm/MC/MCSymbolWasm.h
new file mode 100644
index 000000000000..4445be006eb0
--- /dev/null
+++ b/include/llvm/MC/MCSymbolWasm.h
@@ -0,0 +1,57 @@
+//===- MCSymbolWasm.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_MC_MCSYMBOLWASM_H
+#define LLVM_MC_MCSYMBOLWASM_H
+
+#include "llvm/MC/MCSymbol.h"
+#include "llvm/Support/Wasm.h"
+
+namespace llvm {
+class MCSymbolWasm : public MCSymbol {
+private:
+ bool IsFunction = false;
+ std::string ModuleName;
+ SmallVector<wasm::ValType, 1> Returns;
+ SmallVector<wasm::ValType, 4> Params;
+
+ /// 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;
+
+public:
+ // Use a module name of "env" for now, for compatibility with existing tools.
+ // This is temporary, and may change, as the ABI is not yet stable.
+ MCSymbolWasm(const StringMapEntry<bool> *Name, bool isTemporary)
+ : MCSymbol(SymbolKindWasm, Name, isTemporary),
+ ModuleName("env") {}
+ static bool classof(const MCSymbol *S) { return S->isWasm(); }
+
+ const MCExpr *getSize() const { return SymbolSize; }
+ void setSize(const MCExpr *SS) { SymbolSize = SS; }
+
+ bool isFunction() const { return IsFunction; }
+ void setIsFunction(bool isFunc) { IsFunction = isFunc; }
+
+ const StringRef getModuleName() const { return ModuleName; }
+
+ const SmallVector<wasm::ValType, 1> &getReturns() const { return Returns; }
+
+ void setReturns(SmallVectorImpl<wasm::ValType> &&Rets) {
+ Returns = std::move(Rets);
+ }
+
+ const SmallVector<wasm::ValType, 4> &getParams() const { return Params; }
+
+ void setParams(SmallVectorImpl<wasm::ValType> &&Pars) {
+ Params = std::move(Pars);
+ }
+};
+}
+
+#endif
diff --git a/include/llvm/MC/MCTargetOptions.h b/include/llvm/MC/MCTargetOptions.h
index 25642379ac9f..06f58d498030 100644
--- a/include/llvm/MC/MCTargetOptions.h
+++ b/include/llvm/MC/MCTargetOptions.h
@@ -1,4 +1,4 @@
-//===- MCTargetOptions.h - MC Target Options -------------------*- C++ -*-===//
+//===- MCTargetOptions.h - MC Target Options --------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -51,12 +51,8 @@ public:
/// Preserve Comments in Assembly.
bool PreserveAsmComments : 1;
- int DwarfVersion;
+ int DwarfVersion = 0;
- /// getABIName - If this returns a non-empty string this represents the
- /// textual name of the ABI that we want the backend to use, e.g. o32, or
- /// aapcs-linux.
- StringRef getABIName() const;
std::string ABIName;
/// Additional paths to search for `.include` directives when using the
@@ -64,33 +60,13 @@ public:
std::vector<std::string> IASSearchPaths;
MCTargetOptions();
-};
-inline bool operator==(const MCTargetOptions &LHS, const MCTargetOptions &RHS) {
-#define ARE_EQUAL(X) LHS.X == RHS.X
- return (ARE_EQUAL(SanitizeAddress) &&
- ARE_EQUAL(MCRelaxAll) &&
- ARE_EQUAL(MCNoExecStack) &&
- ARE_EQUAL(MCFatalWarnings) &&
- ARE_EQUAL(MCNoWarn) &&
- ARE_EQUAL(MCNoDeprecatedWarn) &&
- ARE_EQUAL(MCSaveTempLabels) &&
- ARE_EQUAL(MCUseDwarfDirectory) &&
- ARE_EQUAL(MCIncrementalLinkerCompatible) &&
- ARE_EQUAL(MCPIECopyRelocations) &&
- ARE_EQUAL(ShowMCEncoding) &&
- ARE_EQUAL(ShowMCInst) &&
- ARE_EQUAL(AsmVerbose) &&
- ARE_EQUAL(DwarfVersion) &&
- ARE_EQUAL(ABIName) &&
- ARE_EQUAL(IASSearchPaths));
-#undef ARE_EQUAL
-}
-
-inline bool operator!=(const MCTargetOptions &LHS, const MCTargetOptions &RHS) {
- return !(LHS == RHS);
-}
+ /// getABIName - If this returns a non-empty string this represents the
+ /// textual name of the ABI that we want the backend to use, e.g. o32, or
+ /// aapcs-linux.
+ StringRef getABIName() const;
+};
} // end namespace llvm
-#endif
+#endif // LLVM_MC_MCTARGETOPTIONS_H
diff --git a/include/llvm/MC/MCWasmObjectWriter.h b/include/llvm/MC/MCWasmObjectWriter.h
new file mode 100644
index 000000000000..6e458eaac9c8
--- /dev/null
+++ b/include/llvm/MC/MCWasmObjectWriter.h
@@ -0,0 +1,85 @@
+//===-- llvm/MC/MCWasmObjectWriter.h - Wasm Object Writer -------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_MC_MCWASMOBJECTWRITER_H
+#define LLVM_MC_MCWASMOBJECTWRITER_H
+
+#include "llvm/ADT/Triple.h"
+#include "llvm/MC/MCValue.h"
+#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/raw_ostream.h"
+#include <vector>
+
+namespace llvm {
+class MCAssembler;
+class MCContext;
+class MCFixup;
+class MCFragment;
+class MCObjectWriter;
+class MCSectionWasm;
+class MCSymbol;
+class MCSymbolWasm;
+class MCValue;
+class raw_pwrite_stream;
+
+// Information about a single relocation.
+struct WasmRelocationEntry {
+ uint64_t Offset; // Where is the relocation.
+ const MCSymbolWasm *Symbol; // The symbol to relocate with.
+ uint64_t Addend; // A value to add to the symbol.
+ unsigned Type; // The type of the relocation.
+ MCSectionWasm *FixupSection;// The section the relocation is targeting.
+
+ WasmRelocationEntry(uint64_t Offset, const MCSymbolWasm *Symbol,
+ uint64_t Addend, unsigned Type,
+ MCSectionWasm *FixupSection)
+ : Offset(Offset), Symbol(Symbol), Addend(Addend), Type(Type),
+ FixupSection(FixupSection) {}
+
+ void print(raw_ostream &Out) const {
+ Out << "Off=" << Offset << ", Sym=" << Symbol << ", Addend=" << Addend
+ << ", Type=" << Type << ", FixupSection=" << FixupSection;
+ }
+ void dump() const { print(errs()); }
+};
+
+class MCWasmObjectTargetWriter {
+ const unsigned Is64Bit : 1;
+
+protected:
+ explicit MCWasmObjectTargetWriter(bool Is64Bit_);
+
+public:
+ virtual ~MCWasmObjectTargetWriter() {}
+
+ virtual unsigned getRelocType(MCContext &Ctx, const MCValue &Target,
+ const MCFixup &Fixup, bool IsPCRel) const = 0;
+
+ virtual bool needsRelocateWithSymbol(const MCSymbol &Sym,
+ unsigned Type) const;
+
+ virtual void sortRelocs(const MCAssembler &Asm,
+ std::vector<WasmRelocationEntry> &Relocs);
+
+ /// \name Accessors
+ /// @{
+ bool is64Bit() const { return Is64Bit; }
+ /// @}
+};
+
+/// \brief Construct a new Wasm writer instance.
+///
+/// \param MOTW - The target specific Wasm writer subclass.
+/// \param OS - The stream to write to.
+/// \returns The constructed object writer.
+MCObjectWriter *createWasmObjectWriter(MCWasmObjectTargetWriter *MOTW,
+ raw_pwrite_stream &OS);
+} // End llvm namespace
+
+#endif
diff --git a/include/llvm/MC/MCWasmStreamer.h b/include/llvm/MC/MCWasmStreamer.h
new file mode 100644
index 000000000000..bdd6f103cd44
--- /dev/null
+++ b/include/llvm/MC/MCWasmStreamer.h
@@ -0,0 +1,83 @@
+//===- MCWasmStreamer.h - MCStreamer Wasm Object File Interface -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_MC_MCWASMSTREAMER_H
+#define LLVM_MC_MCWASMSTREAMER_H
+
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/MC/MCDirectives.h"
+#include "llvm/MC/MCObjectStreamer.h"
+#include "llvm/MC/SectionKind.h"
+#include "llvm/Support/DataTypes.h"
+
+namespace llvm {
+class MCAsmBackend;
+class MCAssembler;
+class MCCodeEmitter;
+class MCExpr;
+class MCInst;
+class raw_ostream;
+
+class MCWasmStreamer : public MCObjectStreamer {
+public:
+ MCWasmStreamer(MCContext &Context, MCAsmBackend &TAB, raw_pwrite_stream &OS,
+ MCCodeEmitter *Emitter)
+ : MCObjectStreamer(Context, TAB, OS, Emitter), SeenIdent(false) {}
+
+ ~MCWasmStreamer() override;
+
+ /// state management
+ void reset() override {
+ SeenIdent = false;
+ MCObjectStreamer::reset();
+ }
+
+ /// \name MCStreamer Interface
+ /// @{
+
+ void ChangeSection(MCSection *Section, const MCExpr *Subsection) override;
+ void EmitAssemblerFlag(MCAssemblerFlag Flag) override;
+ void EmitThumbFunc(MCSymbol *Func) override;
+ void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) override;
+ bool EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override;
+ void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) override;
+ void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
+ unsigned ByteAlignment) override;
+
+ void emitELFSize(MCSymbol *Symbol, const MCExpr *Value) override;
+
+ void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
+ unsigned ByteAlignment) override;
+
+ void EmitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr,
+ uint64_t Size = 0, unsigned ByteAlignment = 0) override;
+ void EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, uint64_t Size,
+ unsigned ByteAlignment = 0) override;
+ void EmitValueImpl(const MCExpr *Value, unsigned Size,
+ SMLoc Loc = SMLoc()) override;
+
+ void EmitIdent(StringRef IdentString) override;
+
+ void EmitValueToAlignment(unsigned, int64_t, unsigned, unsigned) override;
+
+ void FinishImpl() override;
+
+private:
+ void EmitInstToFragment(const MCInst &Inst, const MCSubtargetInfo &) override;
+ void EmitInstToData(const MCInst &Inst, const MCSubtargetInfo &) override;
+
+ /// \brief Merge the content of the fragment \p EF into the fragment \p DF.
+ void mergeFragment(MCDataFragment *, MCDataFragment *);
+
+ bool SeenIdent;
+};
+
+} // end namespace llvm
+
+#endif
diff --git a/include/llvm/MC/MCWinCOFFObjectWriter.h b/include/llvm/MC/MCWinCOFFObjectWriter.h
index e2e95c7df710..57bed213aad4 100644
--- a/include/llvm/MC/MCWinCOFFObjectWriter.h
+++ b/include/llvm/MC/MCWinCOFFObjectWriter.h
@@ -1,4 +1,4 @@
-//===-- llvm/MC/MCWinCOFFObjectWriter.h - Win COFF Object Writer *- C++ -*-===//
+//===- llvm/MC/MCWinCOFFObjectWriter.h - Win COFF Object Writer -*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -11,22 +11,23 @@
#define LLVM_MC_MCWINCOFFOBJECTWRITER_H
namespace llvm {
+
class MCAsmBackend;
class MCFixup;
class MCObjectWriter;
class MCValue;
-class raw_ostream;
class raw_pwrite_stream;
class MCWinCOFFObjectTargetWriter {
virtual void anchor();
+
const unsigned Machine;
protected:
MCWinCOFFObjectTargetWriter(unsigned Machine_);
public:
- virtual ~MCWinCOFFObjectTargetWriter() {}
+ virtual ~MCWinCOFFObjectTargetWriter() = default;
unsigned getMachine() const { return Machine; }
virtual unsigned getRelocType(const MCValue &Target, const MCFixup &Fixup,
@@ -42,6 +43,6 @@ class raw_pwrite_stream;
/// \returns The constructed object writer.
MCObjectWriter *createWinCOFFObjectWriter(MCWinCOFFObjectTargetWriter *MOTW,
raw_pwrite_stream &OS);
-} // End llvm namespace
+} // end namespace llvm
-#endif
+#endif // LLVM_MC_MCWINCOFFOBJECTWRITER_H
diff --git a/include/llvm/MC/MCWinCOFFStreamer.h b/include/llvm/MC/MCWinCOFFStreamer.h
index 63e44f2e67d6..84e60b85be6a 100644
--- a/include/llvm/MC/MCWinCOFFStreamer.h
+++ b/include/llvm/MC/MCWinCOFFStreamer.h
@@ -14,16 +14,15 @@
#include "llvm/MC/MCObjectStreamer.h"
namespace llvm {
+
class MCAsmBackend;
class MCContext;
class MCCodeEmitter;
-class MCExpr;
class MCInst;
class MCSection;
class MCSubtargetInfo;
class MCSymbol;
class StringRef;
-class raw_ostream;
class raw_pwrite_stream;
class MCWinCOFFStreamer : public MCObjectStreamer {
@@ -41,7 +40,7 @@ public:
/// \{
void InitSections(bool NoExecStack) override;
- void EmitLabel(MCSymbol *Symbol) override;
+ void EmitLabel(MCSymbol *Symbol, SMLoc Loc = SMLoc()) override;
void EmitAssemblerFlag(MCAssemblerFlag Flag) override;
void EmitThumbFunc(MCSymbol *Func) override;
bool EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override;
@@ -61,7 +60,6 @@ public:
unsigned ByteAlignment) override;
void EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, uint64_t Size,
unsigned ByteAlignment) override;
- void EmitFileDirective(StringRef Filename) override;
void EmitIdent(StringRef IdentString) override;
void EmitWinEHHandlerData() override;
void FinishImpl() override;
@@ -70,12 +68,13 @@ public:
protected:
const MCSymbol *CurSymbol;
+
void EmitInstToData(const MCInst &Inst, const MCSubtargetInfo &STI) override;
private:
void Error(const Twine &Msg) const;
};
-}
-#endif
+} // end namespace llvm
+#endif // LLVM_MC_MCWINCOFFSTREAMER_H
diff --git a/include/llvm/MC/MachineLocation.h b/include/llvm/MC/MachineLocation.h
index 4b5cf4357793..f4fc6ee2fd19 100644
--- a/include/llvm/MC/MachineLocation.h
+++ b/include/llvm/MC/MachineLocation.h
@@ -1,4 +1,4 @@
-//===-- llvm/MC/MachineLocation.h -------------------------------*- C++ -*-===//
+//===- llvm/MC/MachineLocation.h --------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -12,35 +12,31 @@
// explicitly passing an offset to the constructor.
//===----------------------------------------------------------------------===//
-
#ifndef LLVM_MC_MACHINELOCATION_H
#define LLVM_MC_MACHINELOCATION_H
-#include "llvm/Support/Compiler.h"
-#include "llvm/Support/DataTypes.h"
+#include <cstdint>
namespace llvm {
- class MCSymbol;
class MachineLocation {
private:
- bool IsRegister; // True if location is a register.
- unsigned Register; // gcc/gdb register number.
- int Offset; // Displacement if not register.
+ bool IsRegister = false; // True if location is a register.
+ unsigned Register = 0; // gcc/gdb register number.
+ int Offset = 0; // Displacement if not register.
+
public:
enum : uint32_t {
// The target register number for an abstract frame pointer. The value is
// an arbitrary value that doesn't collide with any real target register.
VirtualFP = ~0U
};
- MachineLocation()
- : IsRegister(false), Register(0), Offset(0) {}
+
+ MachineLocation() = default;
/// Create a direct register location.
- explicit MachineLocation(unsigned R)
- : IsRegister(true), Register(R), Offset(0) {}
+ explicit MachineLocation(unsigned R) : IsRegister(true), Register(R) {}
/// Create a register-indirect location with an offset.
- MachineLocation(unsigned R, int O)
- : IsRegister(false), Register(R), Offset(O) {}
+ MachineLocation(unsigned R, int O) : Register(R), Offset(O) {}
bool operator==(const MachineLocation &Other) const {
return IsRegister == Other.IsRegister && Register == Other.Register &&
@@ -56,12 +52,14 @@ public:
void setIsRegister(bool Is) { IsRegister = Is; }
void setRegister(unsigned R) { Register = R; }
void setOffset(int O) { Offset = O; }
+
/// Make this location a direct register location.
void set(unsigned R) {
IsRegister = true;
Register = R;
Offset = 0;
}
+
/// Make this location a register-indirect+offset location.
void set(unsigned R, int O) {
IsRegister = false;
@@ -74,6 +72,6 @@ inline bool operator!=(const MachineLocation &LHS, const MachineLocation &RHS) {
return !(LHS == RHS);
}
-} // End llvm namespace
+} // end namespace llvm
-#endif
+#endif // LLVM_MC_MACHINELOCATION_H
diff --git a/include/llvm/MC/StringTableBuilder.h b/include/llvm/MC/StringTableBuilder.h
index 7da444f7bfb1..0df3fcd63723 100644
--- a/include/llvm/MC/StringTableBuilder.h
+++ b/include/llvm/MC/StringTableBuilder.h
@@ -1,4 +1,4 @@
-//===-- StringTableBuilder.h - String table building utility ------*- C++ -*-=//
+//===- StringTableBuilder.h - String table building utility -----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -12,9 +12,12 @@
#include "llvm/ADT/CachedHashString.h"
#include "llvm/ADT/DenseMap.h"
-#include <cassert>
+#include "llvm/ADT/StringRef.h"
+#include <cstddef>
+#include <cstdint>
namespace llvm {
+
class raw_ostream;
/// \brief Utility for building string tables with deduplicated suffixes.
@@ -67,6 +70,6 @@ private:
bool isFinalized() const { return Finalized; }
};
-} // end llvm namespace
+} // end namespace llvm
-#endif
+#endif // LLVM_MC_STRINGTABLEBUILDER_H
diff --git a/include/llvm/MC/SubtargetFeature.h b/include/llvm/MC/SubtargetFeature.h
index ed4abd772821..cb036671b752 100644
--- a/include/llvm/MC/SubtargetFeature.h
+++ b/include/llvm/MC/SubtargetFeature.h
@@ -1,4 +1,4 @@
-//===-- llvm/MC/SubtargetFeature.h - CPU characteristics --------*- C++ -*-===//
+//===- llvm/MC/SubtargetFeature.h - CPU characteristics ---------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,126 +7,124 @@
//
//===----------------------------------------------------------------------===//
//
-// This file defines and manages user or tool specified CPU characteristics.
-// The intent is to be able to package specific features that should or should
-// not be used on a specific target processor. A tool, such as llc, could, as
-// as example, gather chip info from the command line, a long with features
-// that should be used on that chip.
+/// \file Defines and manages user or tool specified CPU characteristics.
+/// The intent is to be able to package specific features that should or should
+/// not be used on a specific target processor. A tool, such as llc, could, as
+/// as example, gather chip info from the command line, a long with features
+/// that should be used on that chip.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_MC_SUBTARGETFEATURE_H
#define LLVM_MC_SUBTARGETFEATURE_H
-#include "llvm/ADT/Triple.h"
-#include "llvm/Support/DataTypes.h"
+#include "llvm/ADT/StringRef.h"
#include <bitset>
+#include <initializer_list>
+#include <string>
#include <vector>
namespace llvm {
+
template <typename T> class ArrayRef;
- class raw_ostream;
- class StringRef;
+class raw_ostream;
+class Triple;
-// 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 = 128;
+const unsigned MAX_SUBTARGET_FEATURES = 192;
+/// Container class for subtarget features.
+/// This is convenient because std::bitset does not have a constructor
+/// with an initializer list of set bits.
class FeatureBitset : public std::bitset<MAX_SUBTARGET_FEATURES> {
public:
// Cannot inherit constructors because it's not supported by VC++..
- FeatureBitset() : bitset() {}
+ FeatureBitset() = default;
FeatureBitset(const bitset<MAX_SUBTARGET_FEATURES>& B) : bitset(B) {}
- FeatureBitset(std::initializer_list<unsigned> Init) : bitset() {
+ FeatureBitset(std::initializer_list<unsigned> Init) {
for (auto I : Init)
set(I);
}
};
//===----------------------------------------------------------------------===//
-///
-/// SubtargetFeatureKV - Used to provide key value pairs for feature and
-/// CPU bit flags.
-//
+
+/// Used to provide key value pairs for feature and CPU bit flags.
struct SubtargetFeatureKV {
- const char *Key; // K-V key string
- const char *Desc; // Help descriptor
- FeatureBitset Value; // K-V integer value
- FeatureBitset Implies; // K-V bit mask
+ const char *Key; ///< K-V key string
+ const char *Desc; ///< Help descriptor
+ FeatureBitset Value; ///< K-V integer value
+ FeatureBitset Implies; ///< K-V bit mask
- // Compare routine for std::lower_bound
+ /// Compare routine for std::lower_bound
bool operator<(StringRef S) const {
return StringRef(Key) < S;
}
- // Compare routine for std::is_sorted.
+ /// Compare routine for std::is_sorted.
bool operator<(const SubtargetFeatureKV &Other) const {
return StringRef(Key) < StringRef(Other.Key);
}
};
//===----------------------------------------------------------------------===//
-///
-/// SubtargetInfoKV - Used to provide key value pairs for CPU and arbitrary
-/// pointers.
-//
+
+/// Used to provide key value pairs for CPU and arbitrary pointers.
struct SubtargetInfoKV {
- const char *Key; // K-V key string
- const void *Value; // K-V pointer value
+ const char *Key; ///< K-V key string
+ const void *Value; ///< K-V pointer value
- // Compare routine for std::lower_bound
+ /// Compare routine for std::lower_bound
bool operator<(StringRef S) const {
return StringRef(Key) < S;
}
};
//===----------------------------------------------------------------------===//
+
+/// Manages the enabling and disabling of subtarget specific features.
///
-/// SubtargetFeatures - Manages the enabling and disabling of subtarget
-/// specific features. Features are encoded as a string of the form
+/// Features are encoded as a string of the form
/// "+attr1,+attr2,-attr3,...,+attrN"
/// A comma separates each feature from the next (all lowercase.)
/// Each of the remaining features is prefixed with + or - indicating whether
/// that feature should be enabled or disabled contrary to the cpu
/// specification.
-///
-
class SubtargetFeatures {
- std::vector<std::string> Features; // Subtarget features as a vector
+ std::vector<std::string> Features; ///< Subtarget features as a vector
+
public:
explicit SubtargetFeatures(StringRef Initial = "");
- /// Features string accessors.
+ /// Returns features as a string.
std::string getString() const;
- /// Adding Features.
+ /// Adds Features.
void AddFeature(StringRef String, bool Enable = true);
- /// ToggleFeature - Toggle a feature and update the feature bits.
+ /// Toggles a feature and update the feature bits.
static void ToggleFeature(FeatureBitset &Bits, StringRef String,
ArrayRef<SubtargetFeatureKV> FeatureTable);
- /// Apply the feature flag and update the feature bits.
+ /// Applies the feature flag and update the feature bits.
static void ApplyFeatureFlag(FeatureBitset &Bits, StringRef Feature,
ArrayRef<SubtargetFeatureKV> FeatureTable);
- /// Get feature bits of a CPU.
+ /// Returns feature bits of a CPU.
FeatureBitset getFeatureBits(StringRef CPU,
- ArrayRef<SubtargetFeatureKV> CPUTable,
- ArrayRef<SubtargetFeatureKV> FeatureTable);
+ ArrayRef<SubtargetFeatureKV> CPUTable,
+ ArrayRef<SubtargetFeatureKV> FeatureTable);
- /// Print feature string.
+ /// Prints feature string.
void print(raw_ostream &OS) const;
- // Dump feature info.
+ // Dumps feature info.
void dump() const;
/// Adds the default features for the specified target triple.
void getDefaultSubtargetFeatures(const Triple& Triple);
};
-} // End namespace llvm
+} // end namespace llvm
-#endif
+#endif // LLVM_MC_SUBTARGETFEATURE_H
diff --git a/include/llvm/Object/Archive.h b/include/llvm/Object/Archive.h
index 08128b0c2515..d423957d9b79 100644
--- a/include/llvm/Object/Archive.h
+++ b/include/llvm/Object/Archive.h
@@ -212,6 +212,7 @@ public:
K_GNU,
K_MIPS64,
K_BSD,
+ K_DARWIN,
K_DARWIN64,
K_COFF
};
diff --git a/include/llvm/Object/Binary.h b/include/llvm/Object/Binary.h
index 00d06e3c7437..bdbe94301dc7 100644
--- a/include/llvm/Object/Binary.h
+++ b/include/llvm/Object/Binary.h
@@ -14,6 +14,7 @@
#ifndef LLVM_OBJECT_BINARY_H
#define LLVM_OBJECT_BINARY_H
+#include "llvm/ADT/Triple.h"
#include "llvm/Object/Error.h"
#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/FileSystem.h"
@@ -133,6 +134,16 @@ public:
return !(TypeID == ID_ELF32B || TypeID == ID_ELF64B ||
TypeID == ID_MachO32B || TypeID == ID_MachO64B);
}
+
+ Triple::ObjectFormatType getTripleObjectFormat() const {
+ if (isCOFF())
+ return Triple::COFF;
+ if (isMachO())
+ return Triple::MachO;
+ if (isELF())
+ return Triple::ELF;
+ return Triple::UnknownObjectFormat;
+ }
};
/// @brief Create a Binary from Source, autodetecting the file type.
diff --git a/include/llvm/Object/ELF.h b/include/llvm/Object/ELF.h
index aaa79ae70f01..7a3155b3953e 100644
--- a/include/llvm/Object/ELF.h
+++ b/include/llvm/Object/ELF.h
@@ -340,7 +340,7 @@ ELFFile<ELFT>::ELFFile(StringRef Object) : Buf(Object) {
}
template <class ELFT>
-static bool compareAddr(uint64_t VAddr, const Elf_Phdr_Impl<ELFT> *Phdr) {
+bool compareAddr(uint64_t VAddr, const Elf_Phdr_Impl<ELFT> *Phdr) {
return VAddr < Phdr->p_vaddr;
}
diff --git a/include/llvm/Object/ELFObjectFile.h b/include/llvm/Object/ELFObjectFile.h
index 69987d433e2d..9e95f2958aa4 100644
--- a/include/llvm/Object/ELFObjectFile.h
+++ b/include/llvm/Object/ELFObjectFile.h
@@ -26,6 +26,7 @@
#include "llvm/Object/Error.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Object/SymbolicFile.h"
+#include "llvm/Support/ARMAttributeParser.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/ELF.h"
#include "llvm/Support/Endian.h"
@@ -72,6 +73,12 @@ public:
static inline bool classof(const Binary *v) { return v->isELF(); }
SubtargetFeatures getFeatures() const override;
+
+ SubtargetFeatures getMIPSFeatures() const;
+
+ SubtargetFeatures getARMFeatures() const;
+
+ void setARMSubArch(Triple &TheTriple) const override;
};
class ELFSectionRef : public SectionRef {
@@ -356,6 +363,28 @@ public:
return std::error_code();
}
+ std::error_code getBuildAttributes(ARMAttributeParser &Attributes) const override {
+ auto SectionsOrErr = EF.sections();
+ if (!SectionsOrErr)
+ return errorToErrorCode(SectionsOrErr.takeError());
+
+ for (const Elf_Shdr &Sec : *SectionsOrErr) {
+ if (Sec.sh_type == ELF::SHT_ARM_ATTRIBUTES) {
+ auto ErrorOrContents = EF.getSectionContents(&Sec);
+ if (!ErrorOrContents)
+ return errorToErrorCode(ErrorOrContents.takeError());
+
+ auto Contents = ErrorOrContents.get();
+ if (Contents[0] != ARMBuildAttrs::Format_Version || Contents.size() == 1)
+ return std::error_code();
+
+ Attributes.Parse(Contents, ELFT::TargetEndianness == support::little);
+ break;
+ }
+ }
+ return std::error_code();
+ }
+
const ELFFile<ELFT> *getELFFile() const { return &EF; }
bool isDyldType() const { return isDyldELFObject; }
@@ -866,6 +895,8 @@ elf_symbol_iterator ELFObjectFile<ELFT>::dynamic_symbol_begin() const {
template <class ELFT>
elf_symbol_iterator ELFObjectFile<ELFT>::dynamic_symbol_end() const {
const Elf_Shdr *SymTab = DotDynSymSec;
+ if (!SymTab)
+ return dynamic_symbol_begin();
DataRefImpl Sym = toDRI(SymTab, SymTab->sh_size / sizeof(Elf_Sym));
return basic_symbol_iterator(SymbolRef(Sym, this));
}
diff --git a/include/llvm/Object/IRSymtab.h b/include/llvm/Object/IRSymtab.h
new file mode 100644
index 000000000000..cde6f3b0f651
--- /dev/null
+++ b/include/llvm/Object/IRSymtab.h
@@ -0,0 +1,302 @@
+//===- IRSymtab.h - data definitions for IR symbol tables -------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains data definitions and a reader and builder for a symbol
+// table for LLVM IR. Its purpose is to allow linkers and other consumers of
+// bitcode files to efficiently read the symbol table for symbol resolution
+// purposes without needing to construct a module in memory.
+//
+// As with most object files the symbol table has two parts: the symbol table
+// itself and a string table which is referenced by the symbol table.
+//
+// A symbol table corresponds to a single bitcode file, which may consist of
+// multiple modules, so symbol tables may likewise contain symbols for multiple
+// modules.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_OBJECT_IRSYMTAB_H
+#define LLVM_OBJECT_IRSYMTAB_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/IR/GlobalValue.h"
+#include "llvm/Object/SymbolicFile.h"
+#include "llvm/Support/Endian.h"
+
+namespace llvm {
+namespace irsymtab {
+namespace storage {
+
+// The data structures in this namespace define the low-level serialization
+// format. Clients that just want to read a symbol table should use the
+// irsymtab::Reader class.
+
+typedef support::ulittle32_t Word;
+
+/// A reference to a string in the string table.
+struct Str {
+ Word Offset;
+ StringRef get(StringRef Strtab) const {
+ return Strtab.data() + Offset;
+ }
+};
+
+/// A reference to a range of objects in the symbol table.
+template <typename T> struct Range {
+ Word Offset, Size;
+ ArrayRef<T> get(StringRef Symtab) const {
+ return {reinterpret_cast<const T *>(Symtab.data() + Offset), Size};
+ }
+};
+
+/// Describes the range of a particular module's symbols within the symbol
+/// table.
+struct Module {
+ Word Begin, End;
+};
+
+/// This is equivalent to an IR comdat.
+struct Comdat {
+ Str Name;
+};
+
+/// Contains the information needed by linkers for symbol resolution, as well as
+/// by the LTO implementation itself.
+struct Symbol {
+ /// The mangled symbol name.
+ Str Name;
+
+ /// The unmangled symbol name, or the empty string if this is not an IR
+ /// symbol.
+ Str IRName;
+
+ /// The index into Header::Comdats, or -1 if not a comdat member.
+ Word ComdatIndex;
+
+ Word Flags;
+ enum FlagBits {
+ FB_visibility, // 2 bits
+ FB_undefined = FB_visibility + 2,
+ FB_weak,
+ FB_common,
+ FB_indirect,
+ FB_used,
+ FB_tls,
+ FB_may_omit,
+ FB_global,
+ FB_format_specific,
+ FB_unnamed_addr,
+ FB_executable,
+ };
+
+ /// The index into the Uncommon table, or -1 if this symbol does not have an
+ /// Uncommon.
+ Word UncommonIndex;
+};
+
+/// This data structure contains rarely used symbol fields and is optionally
+/// referenced by a Symbol.
+struct Uncommon {
+ Word CommonSize, CommonAlign;
+
+ /// COFF-specific: the name of the symbol that a weak external resolves to
+ /// if not defined.
+ Str COFFWeakExternFallbackName;
+};
+
+struct Header {
+ Range<Module> Modules;
+ Range<Comdat> Comdats;
+ Range<Symbol> Symbols;
+ Range<Uncommon> Uncommons;
+
+ Str TargetTriple, SourceFileName;
+
+ /// COFF-specific: linker directives.
+ Str COFFLinkerOpts;
+};
+
+}
+
+/// Fills in Symtab and Strtab with a valid symbol and string table for Mods.
+Error build(ArrayRef<Module *> Mods, SmallVector<char, 0> &Symtab,
+ SmallVector<char, 0> &Strtab);
+
+/// This represents a symbol that has been read from a storage::Symbol and
+/// possibly a storage::Uncommon.
+struct Symbol {
+ // Copied from storage::Symbol.
+ StringRef Name, IRName;
+ int ComdatIndex;
+ uint32_t Flags;
+
+ // Copied from storage::Uncommon.
+ uint32_t CommonSize, CommonAlign;
+ StringRef COFFWeakExternFallbackName;
+
+ /// Returns the mangled symbol name.
+ StringRef getName() const { return Name; }
+
+ /// Returns the unmangled symbol name, or the empty string if this is not an
+ /// IR symbol.
+ StringRef getIRName() const { return IRName; }
+
+ /// Returns the index into the comdat table (see Reader::getComdatTable()), or
+ /// -1 if not a comdat member.
+ int getComdatIndex() const { return ComdatIndex; }
+
+ using S = storage::Symbol;
+ GlobalValue::VisibilityTypes getVisibility() const {
+ return GlobalValue::VisibilityTypes((Flags >> S::FB_visibility) & 3);
+ }
+ bool isUndefined() const { return (Flags >> S::FB_undefined) & 1; }
+ bool isWeak() const { return (Flags >> S::FB_weak) & 1; }
+ bool isCommon() const { return (Flags >> S::FB_common) & 1; }
+ bool isIndirect() const { return (Flags >> S::FB_indirect) & 1; }
+ bool isUsed() const { return (Flags >> S::FB_used) & 1; }
+ bool isTLS() const { return (Flags >> S::FB_tls) & 1; }
+ bool canBeOmittedFromSymbolTable() const {
+ return (Flags >> S::FB_may_omit) & 1;
+ }
+ bool isGlobal() const { return (Flags >> S::FB_global) & 1; }
+ bool isFormatSpecific() const { return (Flags >> S::FB_format_specific) & 1; }
+ bool isUnnamedAddr() const { return (Flags >> S::FB_unnamed_addr) & 1; }
+ bool isExecutable() const { return (Flags >> S::FB_executable) & 1; }
+
+ uint64_t getCommonSize() const {
+ assert(isCommon());
+ return CommonSize;
+ }
+ uint32_t getCommonAlignment() const {
+ assert(isCommon());
+ return CommonAlign;
+ }
+
+ /// COFF-specific: for weak externals, returns the name of the symbol that is
+ /// used as a fallback if the weak external remains undefined.
+ StringRef getCOFFWeakExternalFallback() const {
+ assert(isWeak() && isIndirect());
+ return COFFWeakExternFallbackName;
+ }
+};
+
+/// This class can be used to read a Symtab and Strtab produced by
+/// irsymtab::build.
+class Reader {
+ StringRef Symtab, Strtab;
+
+ ArrayRef<storage::Module> Modules;
+ ArrayRef<storage::Comdat> Comdats;
+ ArrayRef<storage::Symbol> Symbols;
+ ArrayRef<storage::Uncommon> Uncommons;
+
+ StringRef str(storage::Str S) const { return S.get(Strtab); }
+ template <typename T> ArrayRef<T> range(storage::Range<T> R) const {
+ return R.get(Symtab);
+ }
+ const storage::Header &header() const {
+ return *reinterpret_cast<const storage::Header *>(Symtab.data());
+ }
+
+public:
+ class SymbolRef;
+
+ Reader() = default;
+ Reader(StringRef Symtab, StringRef Strtab) : Symtab(Symtab), Strtab(Strtab) {
+ Modules = range(header().Modules);
+ Comdats = range(header().Comdats);
+ Symbols = range(header().Symbols);
+ Uncommons = range(header().Uncommons);
+ }
+
+ typedef iterator_range<object::content_iterator<SymbolRef>> symbol_range;
+
+ /// Returns the symbol table for the entire bitcode file.
+ /// The symbols enumerated by this method are ephemeral, but they can be
+ /// copied into an irsymtab::Symbol object.
+ symbol_range symbols() const;
+
+ /// Returns a slice of the symbol table for the I'th module in the file.
+ /// The symbols enumerated by this method are ephemeral, but they can be
+ /// copied into an irsymtab::Symbol object.
+ symbol_range module_symbols(unsigned I) const;
+
+ StringRef getTargetTriple() const { return str(header().TargetTriple); }
+
+ /// Returns the source file path specified at compile time.
+ StringRef getSourceFileName() const { return str(header().SourceFileName); }
+
+ /// Returns a table with all the comdats used by this file.
+ std::vector<StringRef> getComdatTable() const {
+ std::vector<StringRef> ComdatTable;
+ ComdatTable.reserve(Comdats.size());
+ for (auto C : Comdats)
+ ComdatTable.push_back(str(C.Name));
+ return ComdatTable;
+ }
+
+ /// COFF-specific: returns linker options specified in the input file.
+ StringRef getCOFFLinkerOpts() const { return str(header().COFFLinkerOpts); }
+};
+
+/// Ephemeral symbols produced by Reader::symbols() and
+/// Reader::module_symbols().
+class Reader::SymbolRef : public Symbol {
+ const storage::Symbol *SymI, *SymE;
+ const Reader *R;
+
+public:
+ SymbolRef(const storage::Symbol *SymI, const storage::Symbol *SymE,
+ const Reader *R)
+ : SymI(SymI), SymE(SymE), R(R) {
+ read();
+ }
+
+ void read() {
+ if (SymI == SymE)
+ return;
+
+ Name = R->str(SymI->Name);
+ IRName = R->str(SymI->IRName);
+ ComdatIndex = SymI->ComdatIndex;
+ Flags = SymI->Flags;
+
+ uint32_t UncI = SymI->UncommonIndex;
+ if (UncI != -1u) {
+ const storage::Uncommon &Unc = R->Uncommons[UncI];
+ CommonSize = Unc.CommonSize;
+ CommonAlign = Unc.CommonAlign;
+ COFFWeakExternFallbackName = R->str(Unc.COFFWeakExternFallbackName);
+ }
+ }
+ void moveNext() {
+ ++SymI;
+ read();
+ }
+
+ bool operator==(const SymbolRef &Other) const { return SymI == Other.SymI; }
+};
+
+inline Reader::symbol_range Reader::symbols() const {
+ return {SymbolRef(Symbols.begin(), Symbols.end(), this),
+ SymbolRef(Symbols.end(), Symbols.end(), this)};
+}
+
+inline Reader::symbol_range Reader::module_symbols(unsigned I) const {
+ const storage::Module &M = Modules[I];
+ const storage::Symbol *MBegin = Symbols.begin() + M.Begin,
+ *MEnd = Symbols.begin() + M.End;
+ return {SymbolRef(MBegin, MEnd, this), SymbolRef(MEnd, MEnd, this)};
+}
+
+}
+
+}
+
+#endif
diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h
index 8c33ec8fd603..1ee571cce738 100644
--- a/include/llvm/Object/MachO.h
+++ b/include/llvm/Object/MachO.h
@@ -100,18 +100,58 @@ private:
};
typedef content_iterator<ExportEntry> export_iterator;
+// Segment info so SegIndex/SegOffset pairs in a Mach-O Bind or Rebase entry
+// can be checked and translated. Only the SegIndex/SegOffset pairs from
+// checked entries are to be used with the segmentName(), sectionName() and
+// address() methods below.
+class BindRebaseSegInfo {
+public:
+ BindRebaseSegInfo(const object::MachOObjectFile *Obj);
+
+ // Used to check a Mach-O Bind or Rebase entry for errors when iterating.
+ const char *checkSegAndOffset(int32_t SegIndex, uint64_t SegOffset,
+ bool endInvalid);
+ const char *checkCountAndSkip(uint32_t Count, uint32_t Skip,
+ uint8_t PointerSize, int32_t SegIndex,
+ uint64_t SegOffset);
+ // Used with valid SegIndex/SegOffset values from checked entries.
+ StringRef segmentName(int32_t SegIndex);
+ StringRef sectionName(int32_t SegIndex, uint64_t SegOffset);
+ uint64_t address(uint32_t SegIndex, uint64_t SegOffset);
+
+private:
+ struct SectionInfo {
+ uint64_t Address;
+ uint64_t Size;
+ StringRef SectionName;
+ StringRef SegmentName;
+ uint64_t OffsetInSegment;
+ uint64_t SegmentStartAddress;
+ int32_t SegmentIndex;
+ };
+ const SectionInfo &findSection(int32_t SegIndex, uint64_t SegOffset);
+ SmallVector<SectionInfo, 32> Sections;
+ int32_t MaxSegIndex;
+};
+
/// MachORebaseEntry encapsulates the current state in the decompression of
/// rebasing opcodes. This allows you to iterate through the compressed table of
/// rebasing using:
-/// for (const llvm::object::MachORebaseEntry &Entry : Obj->rebaseTable()) {
+/// Error Err;
+/// for (const llvm::object::MachORebaseEntry &Entry : Obj->rebaseTable(&Err)) {
/// }
+/// if (Err) { report error ...
class MachORebaseEntry {
public:
- MachORebaseEntry(ArrayRef<uint8_t> opcodes, bool is64Bit);
+ MachORebaseEntry(Error *Err, const MachOObjectFile *O,
+ ArrayRef<uint8_t> opcodes, bool is64Bit);
- uint32_t segmentIndex() const;
+ int32_t segmentIndex() const;
uint64_t segmentOffset() const;
StringRef typeName() const;
+ StringRef segmentName() const;
+ StringRef sectionName() const;
+ uint64_t address() const;
bool operator==(const MachORebaseEntry &) const;
@@ -121,17 +161,18 @@ private:
friend class MachOObjectFile;
void moveToFirst();
void moveToEnd();
- uint64_t readULEB128();
+ uint64_t readULEB128(const char **error);
+ Error *E;
+ const MachOObjectFile *O;
ArrayRef<uint8_t> Opcodes;
const uint8_t *Ptr;
uint64_t SegmentOffset;
- uint32_t SegmentIndex;
+ int32_t SegmentIndex;
uint64_t RemainingLoopCount;
uint64_t AdvanceAmount;
uint8_t RebaseType;
uint8_t PointerSize;
- bool Malformed;
bool Done;
};
typedef content_iterator<MachORebaseEntry> rebase_iterator;
@@ -139,15 +180,18 @@ typedef content_iterator<MachORebaseEntry> rebase_iterator;
/// MachOBindEntry encapsulates the current state in the decompression of
/// binding opcodes. This allows you to iterate through the compressed table of
/// bindings using:
-/// for (const llvm::object::MachOBindEntry &Entry : Obj->bindTable()) {
+/// Error Err;
+/// for (const llvm::object::MachOBindEntry &Entry : Obj->bindTable(&Err)) {
/// }
+/// if (Err) { report error ...
class MachOBindEntry {
public:
enum class Kind { Regular, Lazy, Weak };
- MachOBindEntry(ArrayRef<uint8_t> Opcodes, bool is64Bit, MachOBindEntry::Kind);
+ MachOBindEntry(Error *Err, const MachOObjectFile *O,
+ ArrayRef<uint8_t> Opcodes, bool is64Bit, MachOBindEntry::Kind);
- uint32_t segmentIndex() const;
+ int32_t segmentIndex() const;
uint64_t segmentOffset() const;
StringRef typeName() const;
StringRef symbolName() const;
@@ -155,6 +199,10 @@ public:
int64_t addend() const;
int ordinal() const;
+ StringRef segmentName() const;
+ StringRef sectionName() const;
+ uint64_t address() const;
+
bool operator==(const MachOBindEntry &) const;
void moveNext();
@@ -163,14 +211,17 @@ private:
friend class MachOObjectFile;
void moveToFirst();
void moveToEnd();
- uint64_t readULEB128();
- int64_t readSLEB128();
+ uint64_t readULEB128(const char **error);
+ int64_t readSLEB128(const char **error);
+ Error *E;
+ const MachOObjectFile *O;
ArrayRef<uint8_t> Opcodes;
const uint8_t *Ptr;
uint64_t SegmentOffset;
- uint32_t SegmentIndex;
+ int32_t SegmentIndex;
StringRef SymbolName;
+ bool LibraryOrdinalSet;
int Ordinal;
uint32_t Flags;
int64_t Addend;
@@ -179,7 +230,6 @@ private:
uint8_t BindType;
uint8_t PointerSize;
Kind TableKind;
- bool Malformed;
bool Done;
};
typedef content_iterator<MachOBindEntry> bind_iterator;
@@ -245,6 +295,7 @@ public:
// MachO specific.
std::error_code getLibraryShortNameByIndex(unsigned Index, StringRef &) const;
+ uint32_t getLibraryCount() const;
section_iterator getRelocationRelocatedSection(relocation_iterator Rel) const;
@@ -285,26 +336,79 @@ public:
static iterator_range<export_iterator> exports(ArrayRef<uint8_t> Trie);
/// For use iterating over all rebase table entries.
- iterator_range<rebase_iterator> rebaseTable() const;
+ iterator_range<rebase_iterator> rebaseTable(Error &Err);
- /// For use examining rebase opcodes not in a MachOObjectFile.
- static iterator_range<rebase_iterator> rebaseTable(ArrayRef<uint8_t> Opcodes,
+ /// For use examining rebase opcodes in a MachOObjectFile.
+ static iterator_range<rebase_iterator> rebaseTable(Error &Err,
+ MachOObjectFile *O,
+ ArrayRef<uint8_t> Opcodes,
bool is64);
/// For use iterating over all bind table entries.
- iterator_range<bind_iterator> bindTable() const;
+ iterator_range<bind_iterator> bindTable(Error &Err);
/// For use iterating over all lazy bind table entries.
- iterator_range<bind_iterator> lazyBindTable() const;
+ iterator_range<bind_iterator> lazyBindTable(Error &Err);
- /// For use iterating over all lazy bind table entries.
- iterator_range<bind_iterator> weakBindTable() const;
+ /// For use iterating over all weak bind table entries.
+ iterator_range<bind_iterator> weakBindTable(Error &Err);
- /// For use examining bind opcodes not in a MachOObjectFile.
- static iterator_range<bind_iterator> bindTable(ArrayRef<uint8_t> Opcodes,
+ /// For use examining bind opcodes in a MachOObjectFile.
+ static iterator_range<bind_iterator> bindTable(Error &Err,
+ MachOObjectFile *O,
+ ArrayRef<uint8_t> Opcodes,
bool is64,
MachOBindEntry::Kind);
+ /// For use with a SegIndex,SegOffset pair in MachOBindEntry::moveNext() to
+ /// validate a MachOBindEntry.
+ const char *BindEntryCheckSegAndOffset(int32_t SegIndex, uint64_t SegOffset,
+ bool endInvalid) const {
+ return BindRebaseSectionTable->checkSegAndOffset(SegIndex, SegOffset,
+ endInvalid);
+ }
+ /// For use in MachOBindEntry::moveNext() to validate a MachOBindEntry for
+ /// the BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB opcode.
+ const char *BindEntryCheckCountAndSkip(uint32_t Count, uint32_t Skip,
+ uint8_t PointerSize, int32_t SegIndex,
+ uint64_t SegOffset) const {
+ return BindRebaseSectionTable->checkCountAndSkip(Count, Skip, PointerSize,
+ SegIndex, SegOffset);
+ }
+
+ /// For use with a SegIndex,SegOffset pair in MachORebaseEntry::moveNext() to
+ /// validate a MachORebaseEntry.
+ const char *RebaseEntryCheckSegAndOffset(int32_t SegIndex, uint64_t SegOffset,
+ bool endInvalid) const {
+ return BindRebaseSectionTable->checkSegAndOffset(SegIndex, SegOffset,
+ endInvalid);
+ }
+ /// For use in MachORebaseEntry::moveNext() to validate a MachORebaseEntry for
+ /// the REBASE_OPCODE_DO_*_TIMES* opcodes.
+ const char *RebaseEntryCheckCountAndSkip(uint32_t Count, uint32_t Skip,
+ uint8_t PointerSize, int32_t SegIndex,
+ uint64_t SegOffset) const {
+ return BindRebaseSectionTable->checkCountAndSkip(Count, Skip, PointerSize,
+ SegIndex, SegOffset);
+ }
+
+ /// For use with the SegIndex of a checked Mach-O Bind or Rebase entry to
+ /// get the segment name.
+ StringRef BindRebaseSegmentName(int32_t SegIndex) const {
+ return BindRebaseSectionTable->segmentName(SegIndex);
+ }
+
+ /// For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or
+ /// Rebase entry to get the section name.
+ StringRef BindRebaseSectionName(uint32_t SegIndex, uint64_t SegOffset) const {
+ return BindRebaseSectionTable->sectionName(SegIndex, SegOffset);
+ }
+
+ /// For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or
+ /// Rebase entry to get the address.
+ uint64_t BindRebaseAddress(uint32_t SegIndex, uint64_t SegOffset) const {
+ return BindRebaseSectionTable->address(SegIndex, SegOffset);
+ }
// In a MachO file, sections have a segment name. This is used in the .o
// files. They have a single segment, but this field specifies which segment
@@ -351,6 +455,12 @@ public:
getLinkerOptionLoadCommand(const LoadCommandInfo &L) const;
MachO::version_min_command
getVersionMinLoadCommand(const LoadCommandInfo &L) const;
+ MachO::note_command
+ getNoteLoadCommand(const LoadCommandInfo &L) const;
+ MachO::build_version_command
+ getBuildVersionLoadCommand(const LoadCommandInfo &L) const;
+ MachO::build_tool_version
+ getBuildToolVersion(unsigned index) const;
MachO::dylib_command
getDylibIDLoadCommand(const LoadCommandInfo &L) const;
MachO::dyld_info_command
@@ -444,6 +554,46 @@ public:
return VersionOrSDK & 0xff;
}
+ static std::string getBuildPlatform(uint32_t platform) {
+ switch (platform) {
+ case MachO::PLATFORM_MACOS: return "macos";
+ case MachO::PLATFORM_IOS: return "ios";
+ case MachO::PLATFORM_TVOS: return "tvos";
+ case MachO::PLATFORM_WATCHOS: return "watchos";
+ case MachO::PLATFORM_BRIDGEOS: return "bridgeos";
+ default:
+ std::string ret;
+ llvm::raw_string_ostream ss(ret);
+ ss << format_hex(platform, 8, true);
+ return ss.str();
+ }
+ }
+
+ static std::string getBuildTool(uint32_t tools) {
+ switch (tools) {
+ case MachO::TOOL_CLANG: return "clang";
+ case MachO::TOOL_SWIFT: return "swift";
+ case MachO::TOOL_LD: return "ld";
+ default:
+ std::string ret;
+ llvm::raw_string_ostream ss(ret);
+ ss << format_hex(tools, 8, true);
+ return ss.str();
+ }
+ }
+
+ static std::string getVersionString(uint32_t version) {
+ uint32_t major = (version >> 16) & 0xffff;
+ uint32_t minor = (version >> 8) & 0xff;
+ uint32_t update = version & 0xff;
+
+ SmallString<32> Version;
+ Version = utostr(major) + "." + utostr(minor);
+ if (update != 0)
+ Version += "." + utostr(update);
+ return Version.str();
+ }
+
private:
MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian, bool Is64Bits,
@@ -462,7 +612,10 @@ private:
LibraryList Libraries;
LoadCommandList LoadCommands;
typedef SmallVector<StringRef, 1> LibraryShortName;
+ using BuildToolList = SmallVector<const char*, 1>;
+ BuildToolList BuildTools;
mutable LibraryShortName LibrariesShortNames;
+ std::unique_ptr<BindRebaseSegInfo> BindRebaseSectionTable;
const char *SymtabLoadCmd;
const char *DysymtabLoadCmd;
const char *DataInCodeLoadCmd;
diff --git a/include/llvm/Object/ModuleSummaryIndexObjectFile.h b/include/llvm/Object/ModuleSummaryIndexObjectFile.h
index 6205927039dc..713022264ea7 100644
--- a/include/llvm/Object/ModuleSummaryIndexObjectFile.h
+++ b/include/llvm/Object/ModuleSummaryIndexObjectFile.h
@@ -88,9 +88,12 @@ public:
}
/// Parse the module summary index out of an IR file and return the module
-/// summary index object if found, or nullptr if not.
+/// summary index object if found, or nullptr if not. If Identifier is
+/// non-empty, it is used as the module ID (module path) in the resulting
+/// index. This can be used when the index is being read from a file
+/// containing minimized bitcode just for the thin link.
Expected<std::unique_ptr<ModuleSummaryIndex>>
-getModuleSummaryIndexForFile(StringRef Path);
+getModuleSummaryIndexForFile(StringRef Path, StringRef Identifier = "");
}
#endif
diff --git a/include/llvm/Object/ModuleSymbolTable.h b/include/llvm/Object/ModuleSymbolTable.h
index 70775352d977..333301d5b456 100644
--- a/include/llvm/Object/ModuleSymbolTable.h
+++ b/include/llvm/Object/ModuleSymbolTable.h
@@ -26,6 +26,7 @@
namespace llvm {
class GlobalValue;
+class RecordStreamer;
class ModuleSymbolTable {
public:
@@ -52,7 +53,7 @@ public:
/// For each found symbol, call \p AsmSymbol with the name of the symbol found
/// and the associated flags.
static void CollectAsmSymbols(
- const Triple &TheTriple, StringRef InlineAsm,
+ const Module &M,
function_ref<void(StringRef, object::BasicSymbolRef::Flags)> AsmSymbol);
};
diff --git a/include/llvm/Object/ObjectFile.h b/include/llvm/Object/ObjectFile.h
index 13d5845c3a71..b689dc2ac03a 100644
--- a/include/llvm/Object/ObjectFile.h
+++ b/include/llvm/Object/ObjectFile.h
@@ -24,6 +24,8 @@
#include <cstring>
namespace llvm {
+class ARMAttributeParser;
+
namespace object {
class ObjectFile;
@@ -265,6 +267,7 @@ public:
virtual StringRef getFileFormatName() const = 0;
virtual /* Triple::ArchType */ unsigned getArch() const = 0;
virtual SubtargetFeatures getFeatures() const = 0;
+ virtual void setARMSubArch(Triple &TheTriple) const { }
/// Returns platform-specific object flags, if any.
virtual std::error_code getPlatformFlags(unsigned &Result) const {
@@ -272,6 +275,11 @@ public:
return object_error::invalid_file_type;
}
+ virtual std::error_code
+ getBuildAttributes(ARMAttributeParser &Attributes) const {
+ return std::error_code();
+ }
+
/// True if this is a relocatable object (.o/.obj).
virtual bool isRelocatableObject() const = 0;
diff --git a/include/llvm/Object/RelocVisitor.h b/include/llvm/Object/RelocVisitor.h
index 3510d293d73d..3a0a62d9283b 100644
--- a/include/llvm/Object/RelocVisitor.h
+++ b/include/llvm/Object/RelocVisitor.h
@@ -155,6 +155,8 @@ private:
switch (RelocType) {
case llvm::ELF::R_AMDGPU_ABS32:
return visitELF_AMDGPU_ABS32(R, Value);
+ case llvm::ELF::R_AMDGPU_ABS64:
+ return visitELF_AMDGPU_ABS64(R, Value);
default:
HasError = true;
return RelocToApply();
@@ -450,6 +452,11 @@ private:
return RelocToApply(Value + Addend, 4);
}
+ RelocToApply visitELF_AMDGPU_ABS64(RelocationRef R, uint64_t Value) {
+ int64_t Addend = getELFAddend(R);
+ return RelocToApply(Value + Addend, 8);
+ }
+
/// I386 COFF
RelocToApply visitCOFF_I386_SECREL(RelocationRef R, uint64_t Value) {
return RelocToApply(static_cast<uint32_t>(Value), /*Width=*/4);
diff --git a/include/llvm/Object/SymbolicFile.h b/include/llvm/Object/SymbolicFile.h
index af62e62c51d8..ef0f96f7834a 100644
--- a/include/llvm/Object/SymbolicFile.h
+++ b/include/llvm/Object/SymbolicFile.h
@@ -16,6 +16,7 @@
#include "llvm/Object/Binary.h"
#include "llvm/Support/Format.h"
+#include <cinttypes>
#include <utility>
namespace llvm {
@@ -33,7 +34,8 @@ union DataRefImpl {
template <typename OStream>
OStream& operator<<(OStream &OS, const DataRefImpl &D) {
- OS << "(" << format("0x%x8", D.p) << " (" << format("0x%x8", D.d.a) << ", " << format("0x%x8", D.d.b) << "))";
+ OS << "(" << format("0x%08" PRIxPTR, D.p) << " (" << format("0x%08x", D.d.a)
+ << ", " << format("0x%08x", D.d.b) << "))";
return OS;
}
diff --git a/include/llvm/Object/Wasm.h b/include/llvm/Object/Wasm.h
index 2ece6a6c3770..43ad62be68b6 100644
--- a/include/llvm/Object/Wasm.h
+++ b/include/llvm/Object/Wasm.h
@@ -17,24 +17,74 @@
#ifndef LLVM_OBJECT_WASM_H
#define LLVM_OBJECT_WASM_H
+#include "llvm/Object/Binary.h"
#include "llvm/Object/ObjectFile.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Wasm.h"
+#include <cstddef>
+#include <cstdint>
+#include <vector>
namespace llvm {
namespace object {
+class WasmSymbol {
+public:
+ enum class SymbolType {
+ FUNCTION_IMPORT,
+ FUNCTION_EXPORT,
+ GLOBAL_IMPORT,
+ GLOBAL_EXPORT,
+ DEBUG_FUNCTION_NAME,
+ };
+
+ WasmSymbol(StringRef Name, SymbolType Type) : Name(Name), Type(Type) {}
+
+ StringRef Name;
+ SymbolType Type;
+};
+
+class WasmSection {
+public:
+ WasmSection() : Type(0), Offset(0) {}
+
+ uint32_t Type; // Section type (See below)
+ uint32_t Offset; // Offset with in the file
+ StringRef Name; // Section name (User-defined sections only)
+ ArrayRef<uint8_t> Content; // Section content
+ std::vector<wasm::WasmRelocation> Relocations; // Relocations for this section
+};
+
class WasmObjectFile : public ObjectFile {
public:
WasmObjectFile(MemoryBufferRef Object, Error &Err);
+
const wasm::WasmObjectHeader &getHeader() const;
- const wasm::WasmSection *getWasmSection(const SectionRef &Section) const;
+ const WasmSymbol &getWasmSymbol(DataRefImpl Symb) const;
+ const WasmSection &getWasmSection(const SectionRef &Section) const;
+ const wasm::WasmRelocation &getWasmRelocation(const RelocationRef& Ref) const;
+
static bool classof(const Binary *v) { return v->isWasm(); }
-protected:
- void moveSymbolNext(DataRefImpl &Symb) const override;
+ const std::vector<wasm::WasmSignature>& types() const { return Signatures; }
+ const std::vector<uint32_t>& functionTypes() const { return FunctionTypes; }
+ const std::vector<wasm::WasmImport>& imports() const { return Imports; }
+ const std::vector<wasm::WasmTable>& tables() const { return Tables; }
+ const std::vector<wasm::WasmLimits>& memories() const { return Memories; }
+ const std::vector<wasm::WasmGlobal>& globals() const { return Globals; }
+ const std::vector<wasm::WasmExport>& exports() const { return Exports; }
+ const std::vector<wasm::WasmElemSegment>& elements() const {
+ return ElemSegments;
+ }
+ const std::vector<wasm::WasmDataSegment>& dataSegments() const {
+ return DataSegments;
+ }
+ const std::vector<wasm::WasmFunction>& functions() const { return Functions; }
+ const ArrayRef<uint8_t>& code() const { return CodeSection; }
+ uint32_t startFunction() const { return StartFunction; }
- std::error_code printSymbolName(raw_ostream &OS,
- DataRefImpl Symb) const override;
+ void moveSymbolNext(DataRefImpl &Symb) const override;
uint32_t getSymbolFlags(DataRefImpl Symb) const override;
@@ -67,7 +117,6 @@ protected:
bool isSectionBitcode(DataRefImpl Sec) const override;
relocation_iterator section_rel_begin(DataRefImpl Sec) const override;
relocation_iterator section_rel_end(DataRefImpl Sec) const override;
- section_iterator getRelocatedSection(DataRefImpl Sec) const override;
// Overrides from RelocationRef.
void moveRelocationNext(DataRefImpl &Rel) const override;
@@ -86,14 +135,53 @@ protected:
bool isRelocatableObject() const override;
private:
+ const WasmSection &getWasmSection(DataRefImpl Ref) const;
+ const wasm::WasmRelocation &getWasmRelocation(DataRefImpl Ref) const;
+
+ WasmSection* findCustomSectionByName(StringRef Name);
+ WasmSection* findSectionByType(uint32_t Type);
+
const uint8_t *getPtr(size_t Offset) const;
- Error parseUserSection(wasm::WasmSection &Sec, const uint8_t *Ptr,
- size_t Length);
+ Error parseSection(WasmSection &Sec);
+ Error parseCustomSection(WasmSection &Sec, const uint8_t *Ptr,
+ const uint8_t *End);
+
+ // Standard section types
+ Error parseTypeSection(const uint8_t *Ptr, const uint8_t *End);
+ Error parseImportSection(const uint8_t *Ptr, const uint8_t *End);
+ Error parseFunctionSection(const uint8_t *Ptr, const uint8_t *End);
+ Error parseTableSection(const uint8_t *Ptr, const uint8_t *End);
+ Error parseMemorySection(const uint8_t *Ptr, const uint8_t *End);
+ Error parseGlobalSection(const uint8_t *Ptr, const uint8_t *End);
+ Error parseExportSection(const uint8_t *Ptr, const uint8_t *End);
+ Error parseStartSection(const uint8_t *Ptr, const uint8_t *End);
+ Error parseElemSection(const uint8_t *Ptr, const uint8_t *End);
+ Error parseCodeSection(const uint8_t *Ptr, const uint8_t *End);
+ Error parseDataSection(const uint8_t *Ptr, const uint8_t *End);
+
+ // Custom section types
+ Error parseNameSection(const uint8_t *Ptr, const uint8_t *End);
+ Error parseRelocSection(StringRef Name, const uint8_t *Ptr,
+ const uint8_t *End);
wasm::WasmObjectHeader Header;
- std::vector<wasm::WasmSection> Sections;
+ std::vector<WasmSection> Sections;
+ std::vector<wasm::WasmSignature> Signatures;
+ std::vector<uint32_t> FunctionTypes;
+ std::vector<wasm::WasmTable> Tables;
+ std::vector<wasm::WasmLimits> Memories;
+ std::vector<wasm::WasmGlobal> Globals;
+ std::vector<wasm::WasmImport> Imports;
+ std::vector<wasm::WasmExport> Exports;
+ std::vector<wasm::WasmElemSegment> ElemSegments;
+ std::vector<wasm::WasmDataSegment> DataSegments;
+ std::vector<WasmSymbol> Symbols;
+ std::vector<wasm::WasmFunction> Functions;
+ ArrayRef<uint8_t> CodeSection;
+ uint32_t StartFunction;
};
-}
-}
-#endif
+} // end namespace object
+} // end namespace llvm
+
+#endif // LLVM_OBJECT_WASM_H
diff --git a/include/llvm/ObjectYAML/DWARFEmitter.h b/include/llvm/ObjectYAML/DWARFEmitter.h
new file mode 100644
index 000000000000..ce231cc0ce68
--- /dev/null
+++ b/include/llvm/ObjectYAML/DWARFEmitter.h
@@ -0,0 +1,48 @@
+//===--- DWARFEmitter.h - -------------------------------------------*- C++
+//-*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+/// \brief Common declarations for yaml2obj
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_OBJECTYAML_DWARFEMITTER_H
+#define LLVM_OBJECTYAML_DWARFEMITTER_H
+
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/Host.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include <memory>
+#include <vector>
+
+namespace llvm {
+class raw_ostream;
+
+namespace DWARFYAML {
+struct Data;
+struct PubSection;
+
+void EmitDebugAbbrev(llvm::raw_ostream &OS, const llvm::DWARFYAML::Data &DI);
+void EmitDebugStr(llvm::raw_ostream &OS, const llvm::DWARFYAML::Data &DI);
+
+void EmitDebugAranges(llvm::raw_ostream &OS, const llvm::DWARFYAML::Data &DI);
+void EmitPubSection(llvm::raw_ostream &OS,
+ const llvm::DWARFYAML::PubSection &Sect,
+ bool IsLittleEndian);
+void EmitDebugInfo(llvm::raw_ostream &OS, const llvm::DWARFYAML::Data &DI);
+void EmitDebugLine(llvm::raw_ostream &OS, const llvm::DWARFYAML::Data &DI);
+
+Expected<StringMap<std::unique_ptr<MemoryBuffer>>>
+EmitDebugSections(StringRef YAMLString,
+ bool IsLittleEndian = sys::IsLittleEndianHost);
+
+} // namespace DWARFYAML
+} // namespace llvm
+
+#endif
diff --git a/include/llvm/ObjectYAML/DWARFYAML.h b/include/llvm/ObjectYAML/DWARFYAML.h
index d031b5ac404c..ec34de1f0881 100644
--- a/include/llvm/ObjectYAML/DWARFYAML.h
+++ b/include/llvm/ObjectYAML/DWARFYAML.h
@@ -13,7 +13,6 @@
///
//===----------------------------------------------------------------------===//
-
#ifndef LLVM_OBJECTYAML_DWARFYAML_H
#define LLVM_OBJECTYAML_DWARFYAML_H
@@ -23,9 +22,30 @@
namespace llvm {
namespace DWARFYAML {
+struct InitialLength {
+ uint32_t TotalLength;
+ uint64_t TotalLength64;
+
+ bool isDWARF64() const { return TotalLength == UINT32_MAX; }
+
+ uint64_t getLength() const {
+ return isDWARF64() ? TotalLength64 : TotalLength;
+ }
+
+ void setLength(uint64_t Len) {
+ if (Len >= (uint64_t)UINT32_MAX) {
+ TotalLength64 = Len;
+ TotalLength = UINT32_MAX;
+ } else {
+ TotalLength = Len;
+ }
+ }
+};
+
struct AttributeAbbrev {
llvm::dwarf::Attribute Attribute;
llvm::dwarf::Form Form;
+ llvm::yaml::Hex64 Value; // Some DWARF5 attributes have values
};
struct Abbrev {
@@ -41,7 +61,7 @@ struct ARangeDescriptor {
};
struct ARange {
- uint32_t Length;
+ InitialLength Length;
uint16_t Version;
uint32_t CuOffset;
uint8_t AddrSize;
@@ -58,7 +78,7 @@ struct PubEntry {
struct PubSection {
PubSection() : IsGNUStyle(false) {}
- uint32_t Length;
+ InitialLength Length;
uint16_t Version;
uint32_t UnitOffset;
uint32_t UnitSize;
@@ -78,8 +98,9 @@ struct Entry {
};
struct Unit {
- uint32_t Length;
+ InitialLength Length;
uint16_t Version;
+ llvm::dwarf::UnitType Type; // Added in DWARF 5
uint32_t AbbrOffset;
uint8_t AddrSize;
std::vector<Entry> Entries;
@@ -104,8 +125,7 @@ struct LineTableOpcode {
};
struct LineTable {
- uint32_t TotalLength;
- uint64_t TotalLength64;
+ InitialLength Length;
uint16_t Version;
uint64_t PrologueLength;
uint8_t MinInstLength;
@@ -130,7 +150,7 @@ struct Data {
PubSection GNUPubNames;
PubSection GNUPubTypes;
-
+
std::vector<Unit> CompileUnits;
std::vector<LineTable> DebugLines;
@@ -141,7 +161,7 @@ struct Data {
} // namespace llvm::DWARFYAML
} // namespace llvm
-LLVM_YAML_IS_SEQUENCE_VECTOR(uint8_t)
+LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(uint8_t)
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::Hex64)
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::StringRef)
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::Hex8)
@@ -203,7 +223,7 @@ template <> struct MappingTraits<DWARFYAML::FormValue> {
template <> struct MappingTraits<DWARFYAML::File> {
static void mapping(IO &IO, DWARFYAML::File &File);
};
-
+
template <> struct MappingTraits<DWARFYAML::LineTableOpcode> {
static void mapping(IO &IO, DWARFYAML::LineTableOpcode &LineTableOpcode);
};
@@ -212,6 +232,10 @@ template <> struct MappingTraits<DWARFYAML::LineTable> {
static void mapping(IO &IO, DWARFYAML::LineTable &LineTable);
};
+template <> struct MappingTraits<DWARFYAML::InitialLength> {
+ static void mapping(IO &IO, DWARFYAML::InitialLength &DWARF);
+};
+
#define HANDLE_DW_TAG(unused, name) \
io.enumCase(value, "DW_TAG_" #name, dwarf::DW_TAG_##name);
@@ -262,6 +286,16 @@ template <> struct ScalarEnumerationTraits<dwarf::Form> {
}
};
+#define HANDLE_DW_UT(unused, name) \
+ io.enumCase(value, "DW_UT_" #name, dwarf::DW_UT_##name);
+
+template <> struct ScalarEnumerationTraits<dwarf::UnitType> {
+ static void enumeration(IO &io, dwarf::UnitType &value) {
+#include "llvm/Support/Dwarf.def"
+ io.enumFallback<Hex8>(value);
+ }
+};
+
template <> struct ScalarEnumerationTraits<dwarf::Constants> {
static void enumeration(IO &io, dwarf::Constants &value) {
io.enumCase(value, "DW_CHILDREN_no", dwarf::DW_CHILDREN_no);
diff --git a/include/llvm/ObjectYAML/MachOYAML.h b/include/llvm/ObjectYAML/MachOYAML.h
index 9ec32d265bca..ae858c8f4aaf 100644
--- a/include/llvm/ObjectYAML/MachOYAML.h
+++ b/include/llvm/ObjectYAML/MachOYAML.h
@@ -53,6 +53,7 @@ struct LoadCommand {
virtual ~LoadCommand();
llvm::MachO::macho_load_command Data;
std::vector<Section> Sections;
+ std::vector<MachO::build_tool_version> Tools;
std::vector<llvm::yaml::Hex8> PayloadBytes;
std::string PayloadString;
uint64_t ZeroPadBytes;
@@ -139,13 +140,14 @@ struct UniversalBinary {
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MachOYAML::LoadCommand)
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MachOYAML::Section)
-LLVM_YAML_IS_SEQUENCE_VECTOR(int64_t)
+LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(int64_t)
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MachOYAML::RebaseOpcode)
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MachOYAML::BindOpcode)
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MachOYAML::ExportEntry)
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MachOYAML::NListEntry)
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MachOYAML::Object)
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MachOYAML::FatArch)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MachO::build_tool_version)
namespace llvm {
namespace yaml {
@@ -198,6 +200,10 @@ template <> struct MappingTraits<MachOYAML::NListEntry> {
static void mapping(IO &IO, MachOYAML::NListEntry &NListEntry);
};
+template <> struct MappingTraits<MachO::build_tool_version> {
+ static void mapping(IO &IO, MachO::build_tool_version &tool);
+};
+
#define HANDLE_LOAD_COMMAND(LCName, LCValue, LCStruct) \
io.enumCase(value, #LCName, MachO::LCName);
diff --git a/include/llvm/ObjectYAML/ObjectYAML.h b/include/llvm/ObjectYAML/ObjectYAML.h
index 1d6462347770..36d6ed5417cf 100644
--- a/include/llvm/ObjectYAML/ObjectYAML.h
+++ b/include/llvm/ObjectYAML/ObjectYAML.h
@@ -10,10 +10,11 @@
#ifndef LLVM_OBJECTYAML_OBJECTYAML_H
#define LLVM_OBJECTYAML_OBJECTYAML_H
-#include "llvm/Support/YAMLTraits.h"
-#include "llvm/ObjectYAML/ELFYAML.h"
#include "llvm/ObjectYAML/COFFYAML.h"
+#include "llvm/ObjectYAML/ELFYAML.h"
#include "llvm/ObjectYAML/MachOYAML.h"
+#include "llvm/ObjectYAML/WasmYAML.h"
+#include "llvm/Support/YAMLTraits.h"
namespace llvm {
namespace yaml {
@@ -23,6 +24,7 @@ struct YamlObjectFile {
std::unique_ptr<COFFYAML::Object> Coff;
std::unique_ptr<MachOYAML::Object> MachO;
std::unique_ptr<MachOYAML::UniversalBinary> FatMachO;
+ std::unique_ptr<WasmYAML::Object> Wasm;
};
template <> struct MappingTraits<YamlObjectFile> {
diff --git a/include/llvm/ObjectYAML/WasmYAML.h b/include/llvm/ObjectYAML/WasmYAML.h
new file mode 100644
index 000000000000..b1af8bbdfa6e
--- /dev/null
+++ b/include/llvm/ObjectYAML/WasmYAML.h
@@ -0,0 +1,339 @@
+//===- WasmYAML.h - Wasm YAMLIO implementation ------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief This file declares classes for handling the YAML representation
+/// of wasm binaries.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_OBJECTYAML_WASMYAML_H
+#define LLVM_OBJECTYAML_WASMYAML_H
+
+#include "llvm/ObjectYAML/YAML.h"
+#include "llvm/Support/Wasm.h"
+
+namespace llvm {
+namespace WasmYAML {
+
+LLVM_YAML_STRONG_TYPEDEF(uint32_t, SectionType)
+LLVM_YAML_STRONG_TYPEDEF(int32_t, ValueType)
+LLVM_YAML_STRONG_TYPEDEF(int32_t, TableType)
+LLVM_YAML_STRONG_TYPEDEF(int32_t, SignatureForm)
+LLVM_YAML_STRONG_TYPEDEF(uint32_t, ExportKind)
+LLVM_YAML_STRONG_TYPEDEF(uint32_t, Opcode)
+LLVM_YAML_STRONG_TYPEDEF(uint32_t, RelocType)
+
+struct FileHeader {
+ yaml::Hex32 Version;
+};
+
+struct Import {
+ StringRef Module;
+ StringRef Field;
+ ExportKind Kind;
+ union {
+ uint32_t SigIndex;
+ ValueType GlobalType;
+ };
+ bool GlobalMutable;
+};
+
+struct Limits {
+ yaml::Hex32 Flags;
+ yaml::Hex32 Initial;
+ yaml::Hex32 Maximum;
+};
+
+struct Table {
+ TableType ElemType;
+ Limits TableLimits;
+};
+
+struct Export {
+ StringRef Name;
+ ExportKind Kind;
+ uint32_t Index;
+};
+
+struct ElemSegment {
+ uint32_t TableIndex;
+ wasm::WasmInitExpr Offset;
+ std::vector<uint32_t> Functions;
+};
+
+struct Global {
+ ValueType Type;
+ bool Mutable;
+ wasm::WasmInitExpr InitExpr;
+};
+
+struct LocalDecl {
+ ValueType Type;
+ uint32_t Count;
+};
+
+struct Function {
+ std::vector<LocalDecl> Locals;
+ yaml::BinaryRef Body;
+};
+
+struct Relocation {
+ RelocType Type;
+ uint32_t Index;
+ yaml::Hex32 Offset;
+ yaml::Hex32 Addend;
+};
+
+struct DataSegment {
+ uint32_t Index;
+ wasm::WasmInitExpr Offset;
+ yaml::BinaryRef Content;
+};
+
+struct Signature {
+ Signature() : Form(wasm::WASM_TYPE_FUNC) {}
+
+ uint32_t Index;
+ SignatureForm Form;
+ std::vector<ValueType> ParamTypes;
+ ValueType ReturnType;
+};
+
+struct Section {
+ Section(SectionType SecType) : Type(SecType) {}
+ virtual ~Section();
+
+ SectionType Type;
+ std::vector<Relocation> Relocations;
+};
+
+struct CustomSection : Section {
+ CustomSection() : Section(wasm::WASM_SEC_CUSTOM) {}
+ static bool classof(const Section *S) {
+ return S->Type == wasm::WASM_SEC_CUSTOM;
+ }
+
+ StringRef Name;
+ yaml::BinaryRef Payload;
+};
+
+struct TypeSection : Section {
+ TypeSection() : Section(wasm::WASM_SEC_TYPE) {}
+ static bool classof(const Section *S) {
+ return S->Type == wasm::WASM_SEC_TYPE;
+ }
+
+ std::vector<Signature> Signatures;
+};
+
+struct ImportSection : Section {
+ ImportSection() : Section(wasm::WASM_SEC_IMPORT) {}
+ static bool classof(const Section *S) {
+ return S->Type == wasm::WASM_SEC_IMPORT;
+ }
+
+ std::vector<Import> Imports;
+};
+
+struct FunctionSection : Section {
+ FunctionSection() : Section(wasm::WASM_SEC_FUNCTION) {}
+ static bool classof(const Section *S) {
+ return S->Type == wasm::WASM_SEC_FUNCTION;
+ }
+
+ std::vector<uint32_t> FunctionTypes;
+};
+
+struct TableSection : Section {
+ TableSection() : Section(wasm::WASM_SEC_TABLE) {}
+ static bool classof(const Section *S) {
+ return S->Type == wasm::WASM_SEC_TABLE;
+ }
+
+ std::vector<Table> Tables;
+};
+
+struct MemorySection : Section {
+ MemorySection() : Section(wasm::WASM_SEC_MEMORY) {}
+ static bool classof(const Section *S) {
+ return S->Type == wasm::WASM_SEC_MEMORY;
+ }
+
+ std::vector<Limits> Memories;
+};
+
+struct GlobalSection : Section {
+ GlobalSection() : Section(wasm::WASM_SEC_GLOBAL) {}
+ static bool classof(const Section *S) {
+ return S->Type == wasm::WASM_SEC_GLOBAL;
+ }
+
+ std::vector<Global> Globals;
+};
+
+struct ExportSection : Section {
+ ExportSection() : Section(wasm::WASM_SEC_EXPORT) {}
+ static bool classof(const Section *S) {
+ return S->Type == wasm::WASM_SEC_EXPORT;
+ }
+
+ std::vector<Export> Exports;
+};
+
+struct StartSection : Section {
+ StartSection() : Section(wasm::WASM_SEC_START) {}
+ static bool classof(const Section *S) {
+ return S->Type == wasm::WASM_SEC_START;
+ }
+
+ uint32_t StartFunction;
+};
+
+struct ElemSection : Section {
+ ElemSection() : Section(wasm::WASM_SEC_ELEM) {}
+ static bool classof(const Section *S) {
+ return S->Type == wasm::WASM_SEC_ELEM;
+ }
+
+ std::vector<ElemSegment> Segments;
+};
+
+struct CodeSection : Section {
+ CodeSection() : Section(wasm::WASM_SEC_CODE) {}
+ static bool classof(const Section *S) {
+ return S->Type == wasm::WASM_SEC_CODE;
+ }
+
+ std::vector<Function> Functions;
+};
+
+struct DataSection : Section {
+ DataSection() : Section(wasm::WASM_SEC_DATA) {}
+ static bool classof(const Section *S) {
+ return S->Type == wasm::WASM_SEC_DATA;
+ }
+
+ std::vector<DataSegment> Segments;
+};
+
+struct Object {
+ FileHeader Header;
+ std::vector<std::unique_ptr<Section>> Sections;
+};
+
+} // end namespace WasmYAML
+} // end namespace llvm
+
+LLVM_YAML_IS_SEQUENCE_VECTOR(std::unique_ptr<llvm::WasmYAML::Section>)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::Signature)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::ValueType)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::Table)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::Import)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::Export)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::ElemSegment)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::Limits)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::DataSegment)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::Global)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::Function)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::LocalDecl)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::Relocation)
+LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(uint32_t)
+
+namespace llvm {
+namespace yaml {
+
+template <> struct MappingTraits<WasmYAML::FileHeader> {
+ static void mapping(IO &IO, WasmYAML::FileHeader &FileHdr);
+};
+
+template <> struct MappingTraits<std::unique_ptr<WasmYAML::Section>> {
+ static void mapping(IO &IO, std::unique_ptr<WasmYAML::Section> &Section);
+};
+
+template <> struct MappingTraits<WasmYAML::Object> {
+ static void mapping(IO &IO, WasmYAML::Object &Object);
+};
+
+template <> struct MappingTraits<WasmYAML::Import> {
+ static void mapping(IO &IO, WasmYAML::Import &Import);
+};
+
+template <> struct MappingTraits<WasmYAML::Export> {
+ static void mapping(IO &IO, WasmYAML::Export &Export);
+};
+
+template <> struct MappingTraits<WasmYAML::Global> {
+ static void mapping(IO &IO, WasmYAML::Global &Global);
+};
+
+template <> struct ScalarEnumerationTraits<WasmYAML::SectionType> {
+ static void enumeration(IO &IO, WasmYAML::SectionType &Type);
+};
+
+template <> struct MappingTraits<WasmYAML::Signature> {
+ static void mapping(IO &IO, WasmYAML::Signature &Signature);
+};
+
+template <> struct MappingTraits<WasmYAML::Table> {
+ static void mapping(IO &IO, WasmYAML::Table &Table);
+};
+
+template <> struct MappingTraits<WasmYAML::Limits> {
+ static void mapping(IO &IO, WasmYAML::Limits &Limits);
+};
+
+template <> struct MappingTraits<WasmYAML::Function> {
+ static void mapping(IO &IO, WasmYAML::Function &Function);
+};
+
+template <> struct MappingTraits<WasmYAML::Relocation> {
+ static void mapping(IO &IO, WasmYAML::Relocation &Relocation);
+};
+
+template <> struct MappingTraits<WasmYAML::LocalDecl> {
+ static void mapping(IO &IO, WasmYAML::LocalDecl &LocalDecl);
+};
+
+template <> struct MappingTraits<wasm::WasmInitExpr> {
+ static void mapping(IO &IO, wasm::WasmInitExpr &Expr);
+};
+
+template <> struct MappingTraits<WasmYAML::DataSegment> {
+ static void mapping(IO &IO, WasmYAML::DataSegment &Segment);
+};
+
+template <> struct MappingTraits<WasmYAML::ElemSegment> {
+ static void mapping(IO &IO, WasmYAML::ElemSegment &Segment);
+};
+
+template <> struct ScalarEnumerationTraits<WasmYAML::ValueType> {
+ static void enumeration(IO &IO, WasmYAML::ValueType &Type);
+};
+
+template <> struct ScalarEnumerationTraits<WasmYAML::ExportKind> {
+ static void enumeration(IO &IO, WasmYAML::ExportKind &Kind);
+};
+
+template <> struct ScalarEnumerationTraits<WasmYAML::TableType> {
+ static void enumeration(IO &IO, WasmYAML::TableType &Type);
+};
+
+template <> struct ScalarEnumerationTraits<WasmYAML::Opcode> {
+ static void enumeration(IO &IO, WasmYAML::Opcode &Opcode);
+};
+
+template <> struct ScalarEnumerationTraits<WasmYAML::RelocType> {
+ static void enumeration(IO &IO, WasmYAML::RelocType &Kind);
+};
+
+} // end namespace yaml
+} // end namespace llvm
+
+#endif
diff --git a/include/llvm/Option/ArgList.h b/include/llvm/Option/ArgList.h
index 53cb0d8dec4d..4ed28d7a852b 100644
--- a/include/llvm/Option/ArgList.h
+++ b/include/llvm/Option/ArgList.h
@@ -10,6 +10,7 @@
#ifndef LLVM_OPTION_ARGLIST_H
#define LLVM_OPTION_ARGLIST_H
+#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"
@@ -28,40 +29,57 @@ class ArgList;
class Option;
/// arg_iterator - Iterates through arguments stored inside an ArgList.
+template<typename BaseIter, unsigned NumOptSpecifiers = 0>
class arg_iterator {
- /// The current argument.
- SmallVectorImpl<Arg*>::const_iterator Current;
-
- /// The argument list we are iterating over.
- const ArgList &Args;
-
- /// Optional filters on the arguments which will be match. Most clients
- /// should never want to iterate over arguments without filters, so we won't
- /// bother to factor this into two separate iterator implementations.
- //
- // FIXME: Make efficient; the idea is to provide efficient iteration over
- // all arguments which match a particular id and then just provide an
- // iterator combinator which takes multiple iterators which can be
- // efficiently compared and returns them in order.
- OptSpecifier Id0, Id1, Id2;
+ /// The current argument and the end of the sequence we're iterating.
+ BaseIter Current, End;
+
+ /// Optional filters on the arguments which will be match. To avoid a
+ /// zero-sized array, we store one specifier even if we're asked for none.
+ OptSpecifier Ids[NumOptSpecifiers ? NumOptSpecifiers : 1];
+
+ void SkipToNextArg() {
+ for (; Current != End; ++Current) {
+ // Skip erased elements.
+ if (!*Current)
+ continue;
+
+ // Done if there are no filters.
+ if (!NumOptSpecifiers)
+ return;
+
+ // Otherwise require a match.
+ const Option &O = (*Current)->getOption();
+ for (auto Id : Ids) {
+ if (!Id.isValid())
+ break;
+ if (O.matches(Id))
+ return;
+ }
+ }
+ }
- void SkipToNextArg();
+ typedef std::iterator_traits<BaseIter> Traits;
public:
- typedef Arg * const * value_type;
- typedef Arg * const & reference;
- typedef Arg * const * pointer;
- 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) {
+ typedef typename Traits::value_type value_type;
+ typedef typename Traits::reference reference;
+ typedef typename Traits::pointer pointer;
+ typedef std::forward_iterator_tag iterator_category;
+ typedef std::ptrdiff_t difference_type;
+
+ arg_iterator(
+ BaseIter Current, BaseIter End,
+ const OptSpecifier (&Ids)[NumOptSpecifiers ? NumOptSpecifiers : 1] = {})
+ : Current(Current), End(End) {
+ for (unsigned I = 0; I != NumOptSpecifiers; ++I)
+ this->Ids[I] = Ids[I];
SkipToNextArg();
}
+ // FIXME: This conversion function makes no sense.
operator const Arg*() { return *Current; }
+
reference operator*() const { return *Current; }
pointer operator->() const { return Current; }
@@ -94,15 +112,31 @@ public:
class ArgList {
public:
typedef SmallVector<Arg*, 16> arglist_type;
- typedef arglist_type::iterator iterator;
- typedef arglist_type::const_iterator const_iterator;
- typedef arglist_type::reverse_iterator reverse_iterator;
- typedef arglist_type::const_reverse_iterator const_reverse_iterator;
+ typedef arg_iterator<arglist_type::iterator> iterator;
+ typedef arg_iterator<arglist_type::const_iterator> const_iterator;
+ typedef arg_iterator<arglist_type::reverse_iterator> reverse_iterator;
+ typedef arg_iterator<arglist_type::const_reverse_iterator>
+ const_reverse_iterator;
+
+ template<unsigned N> using filtered_iterator =
+ arg_iterator<arglist_type::const_iterator, N>;
+ template<unsigned N> using filtered_reverse_iterator =
+ arg_iterator<arglist_type::const_reverse_iterator, N>;
private:
/// The internal list of arguments.
arglist_type Args;
+ typedef std::pair<unsigned, unsigned> OptRange;
+ static OptRange emptyRange() { return {-1u, 0u}; }
+
+ /// The first and last index of each different OptSpecifier ID.
+ DenseMap<unsigned, OptRange> OptRanges;
+
+ /// Get the range of indexes in which options with the specified IDs might
+ /// reside, or (0, 0) if there are no such options.
+ OptRange getRange(std::initializer_list<OptSpecifier> Ids) const;
+
protected:
// Make the default special members protected so they won't be used to slice
// derived objects, but can still be used by derived objects to implement
@@ -113,24 +147,32 @@ protected:
// InputArgList which deletes the contents of the container. If we could fix
// up the ownership here (delegate storage/ownership to the derived class so
// it can be a container of unique_ptr) this would be simpler.
- ArgList(ArgList &&RHS) : Args(std::move(RHS.Args)) { RHS.Args.clear(); }
+ ArgList(ArgList &&RHS)
+ : Args(std::move(RHS.Args)), OptRanges(std::move(RHS.OptRanges)) {
+ RHS.Args.clear();
+ RHS.OptRanges.clear();
+ }
ArgList &operator=(ArgList &&RHS) {
Args = std::move(RHS.Args);
RHS.Args.clear();
+ OptRanges = std::move(RHS.OptRanges);
+ RHS.OptRanges.clear();
return *this;
}
// Protect the dtor to ensure this type is never destroyed polymorphically.
~ArgList() = default;
-public:
+ // Implicitly convert a value to an OptSpecifier. Used to work around a bug
+ // in MSVC's implementation of narrowing conversion checking.
+ static OptSpecifier toOptSpecifier(OptSpecifier S) { return S; }
+public:
/// @name Arg Access
/// @{
/// append - Append \p A to the arg list.
void append(Arg *A);
- arglist_type &getArgs() { return Args; }
const arglist_type &getArgs() const { return Args; }
unsigned size() const { return Args.size(); }
@@ -139,30 +181,38 @@ public:
/// @name Arg Iteration
/// @{
- iterator begin() { return Args.begin(); }
- iterator end() { return Args.end(); }
+ iterator begin() { return {Args.begin(), Args.end()}; }
+ iterator end() { return {Args.end(), Args.end()}; }
- reverse_iterator rbegin() { return Args.rbegin(); }
- reverse_iterator rend() { return Args.rend(); }
+ reverse_iterator rbegin() { return {Args.rbegin(), Args.rend()}; }
+ reverse_iterator rend() { return {Args.rend(), Args.rend()}; }
- const_iterator begin() const { return Args.begin(); }
- const_iterator end() const { return Args.end(); }
+ const_iterator begin() const { return {Args.begin(), Args.end()}; }
+ const_iterator end() const { return {Args.end(), Args.end()}; }
- const_reverse_iterator rbegin() const { return Args.rbegin(); }
- const_reverse_iterator rend() const { return Args.rend(); }
+ const_reverse_iterator rbegin() const { return {Args.rbegin(), Args.rend()}; }
+ const_reverse_iterator rend() const { return {Args.rend(), Args.rend()}; }
- arg_iterator filtered_begin(OptSpecifier Id0 = 0U, OptSpecifier Id1 = 0U,
- OptSpecifier Id2 = 0U) const {
- return arg_iterator(Args.begin(), *this, Id0, Id1, Id2);
- }
- arg_iterator filtered_end() const {
- return arg_iterator(Args.end(), *this);
+ template<typename ...OptSpecifiers>
+ iterator_range<filtered_iterator<sizeof...(OptSpecifiers)>>
+ filtered(OptSpecifiers ...Ids) const {
+ OptRange Range = getRange({toOptSpecifier(Ids)...});
+ auto B = Args.begin() + Range.first;
+ auto E = Args.begin() + Range.second;
+ using Iterator = filtered_iterator<sizeof...(OptSpecifiers)>;
+ return make_range(Iterator(B, E, {toOptSpecifier(Ids)...}),
+ Iterator(E, E, {toOptSpecifier(Ids)...}));
}
- iterator_range<arg_iterator> filtered(OptSpecifier Id0 = 0U,
- OptSpecifier Id1 = 0U,
- OptSpecifier Id2 = 0U) const {
- return make_range(filtered_begin(Id0, Id1, Id2), filtered_end());
+ template<typename ...OptSpecifiers>
+ iterator_range<filtered_reverse_iterator<sizeof...(OptSpecifiers)>>
+ filtered_reverse(OptSpecifiers ...Ids) const {
+ OptRange Range = getRange({toOptSpecifier(Ids)...});
+ auto B = Args.rend() - Range.second;
+ auto E = Args.rend() - Range.first;
+ using Iterator = filtered_reverse_iterator<sizeof...(OptSpecifiers)>;
+ return make_range(Iterator(B, E, {toOptSpecifier(Ids)...}),
+ Iterator(E, E, {toOptSpecifier(Ids)...}));
}
/// @}
@@ -179,43 +229,34 @@ public:
/// hasArg - Does the arg list contain any option matching \p Id.
///
/// \p Claim Whether the argument should be claimed, if it exists.
- bool hasArgNoClaim(OptSpecifier Id) const {
- return getLastArgNoClaim(Id) != nullptr;
- }
- bool hasArg(OptSpecifier Id) const {
- return getLastArg(Id) != nullptr;
+ template<typename ...OptSpecifiers>
+ bool hasArgNoClaim(OptSpecifiers ...Ids) const {
+ return getLastArgNoClaim(Ids...) != nullptr;
}
- bool hasArg(OptSpecifier Id0, OptSpecifier Id1) const {
- return getLastArg(Id0, Id1) != nullptr;
+ template<typename ...OptSpecifiers>
+ bool hasArg(OptSpecifiers ...Ids) const {
+ return getLastArg(Ids...) != nullptr;
}
- bool hasArg(OptSpecifier Id0, OptSpecifier Id1, OptSpecifier Id2) const {
- return getLastArg(Id0, Id1, Id2) != nullptr;
+
+ /// Return the last argument matching \p Id, or null.
+ template<typename ...OptSpecifiers>
+ Arg *getLastArg(OptSpecifiers ...Ids) const {
+ Arg *Res = nullptr;
+ for (Arg *A : filtered(Ids...)) {
+ Res = A;
+ Res->claim();
+ }
+ return Res;
}
- /// getLastArg - Return the last argument matching \p Id, or null.
- ///
- /// \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;
- Arg *getLastArg(OptSpecifier Id0, OptSpecifier Id1, OptSpecifier Id2,
- OptSpecifier Id3) const;
- Arg *getLastArg(OptSpecifier Id0, OptSpecifier Id1, OptSpecifier Id2,
- OptSpecifier Id3, OptSpecifier Id4) const;
- Arg *getLastArg(OptSpecifier Id0, OptSpecifier Id1, OptSpecifier Id2,
- OptSpecifier Id3, OptSpecifier Id4, OptSpecifier Id5) const;
- Arg *getLastArg(OptSpecifier Id0, OptSpecifier Id1, OptSpecifier Id2,
- OptSpecifier Id3, OptSpecifier Id4, OptSpecifier Id5,
- OptSpecifier Id6) const;
- Arg *getLastArg(OptSpecifier Id0, OptSpecifier Id1, OptSpecifier Id2,
- OptSpecifier Id3, OptSpecifier Id4, OptSpecifier Id5,
- OptSpecifier Id6, OptSpecifier Id7) const;
+ /// Return the last argument matching \p Id, or null. Do not "claim" the
+ /// option (don't mark it as having been used).
+ template<typename ...OptSpecifiers>
+ Arg *getLastArgNoClaim(OptSpecifiers ...Ids) const {
+ for (Arg *A : filtered_reverse(Ids...))
+ return A;
+ return nullptr;
+ }
/// getArgString - Return the input argument string at \p Index.
virtual const char *getArgString(unsigned Index) const = 0;
@@ -230,8 +271,7 @@ public:
/// @{
/// getLastArgValue - Return the value of the last argument, or a default.
- StringRef getLastArgValue(OptSpecifier Id,
- StringRef Default = "") const;
+ StringRef getLastArgValue(OptSpecifier Id, StringRef Default = "") const;
/// getAllArgValues - Get the values of all instances of the given argument
/// as strings.
@@ -273,7 +313,7 @@ public:
/// AddAllArgValues - Render the argument values of all arguments
/// matching the given ids.
void AddAllArgValues(ArgStringList &Output, OptSpecifier Id0,
- OptSpecifier Id1 = 0U, OptSpecifier Id2 = 0U) const;
+ OptSpecifier Id1 = 0U, OptSpecifier Id2 = 0U) const;
/// AddAllArgsTranslated - Render all the arguments matching the
/// given ids, but forced to separate args and using the provided
diff --git a/include/llvm/PassSupport.h b/include/llvm/PassSupport.h
index e77a0b9882b2..852d79fbd443 100644
--- a/include/llvm/PassSupport.h
+++ b/include/llvm/PassSupport.h
@@ -41,7 +41,7 @@ class TargetMachine;
Registry.registerPass(*PI, true); \
return PI; \
} \
- LLVM_DEFINE_ONCE_FLAG(Initialize##passName##PassFlag); \
+ static llvm::once_flag Initialize##passName##PassFlag; \
void llvm::initialize##passName##Pass(PassRegistry &Registry) { \
llvm::call_once(Initialize##passName##PassFlag, \
initialize##passName##PassOnce, std::ref(Registry)); \
@@ -61,7 +61,7 @@ class TargetMachine;
Registry.registerPass(*PI, true); \
return PI; \
} \
- LLVM_DEFINE_ONCE_FLAG(Initialize##passName##PassFlag); \
+ static llvm::once_flag Initialize##passName##PassFlag; \
void llvm::initialize##passName##Pass(PassRegistry &Registry) { \
llvm::call_once(Initialize##passName##PassFlag, \
initialize##passName##PassOnce, std::ref(Registry)); \
@@ -152,7 +152,7 @@ struct RegisterAnalysisGroup : public RegisterAGBase {
Registry.registerAnalysisGroup(&agName::ID, 0, *AI, false, true); \
return AI; \
} \
- LLVM_DEFINE_ONCE_FLAG(Initialize##agName##AnalysisGroupFlag); \
+ static llvm::once_flag Initialize##agName##AnalysisGroupFlag; \
void llvm::initialize##agName##AnalysisGroup(PassRegistry &Registry) { \
llvm::call_once(Initialize##agName##AnalysisGroupFlag, \
initialize##agName##AnalysisGroupOnce, \
@@ -173,7 +173,7 @@ struct RegisterAnalysisGroup : public RegisterAGBase {
true); \
return AI; \
} \
- LLVM_DEFINE_ONCE_FLAG(Initialize##passName##PassFlag); \
+ static llvm::once_flag Initialize##passName##PassFlag; \
void llvm::initialize##passName##Pass(PassRegistry &Registry) { \
llvm::call_once(Initialize##passName##PassFlag, \
initialize##passName##PassOnce, std::ref(Registry)); \
@@ -194,7 +194,7 @@ struct RegisterAnalysisGroup : public RegisterAGBase {
Registry.registerAnalysisGroup(&agName::ID, &passName::ID, *AI, def, true); \
return AI; \
} \
- LLVM_DEFINE_ONCE_FLAG(Initialize##passName##PassFlag); \
+ static llvm::once_flag Initialize##passName##PassFlag; \
void llvm::initialize##passName##Pass(PassRegistry &Registry) { \
llvm::call_once(Initialize##passName##PassFlag, \
initialize##passName##PassOnce, std::ref(Registry)); \
diff --git a/include/llvm/Passes/PassBuilder.h b/include/llvm/Passes/PassBuilder.h
index d76c13984d11..efa36d957fbd 100644
--- a/include/llvm/Passes/PassBuilder.h
+++ b/include/llvm/Passes/PassBuilder.h
@@ -27,6 +27,14 @@ class StringRef;
class AAManager;
class TargetMachine;
+/// A struct capturing PGO tunables.
+struct PGOOptions {
+ std::string ProfileGenFile = "";
+ std::string ProfileUseFile = "";
+ bool RunProfileGen = false;
+ bool SamplePGO = false;
+};
+
/// \brief This class provides access to building LLVM's passes.
///
/// It's members provide the baseline state available to passes during their
@@ -35,6 +43,7 @@ class TargetMachine;
/// construction.
class PassBuilder {
TargetMachine *TM;
+ Optional<PGOOptions> PGOOpt;
public:
/// \brief LLVM-provided high-level optimization levels.
@@ -123,7 +132,9 @@ public:
Oz
};
- explicit PassBuilder(TargetMachine *TM = nullptr) : TM(TM) {}
+ explicit PassBuilder(TargetMachine *TM = nullptr,
+ Optional<PGOOptions> PGOOpt = None)
+ : TM(TM), PGOOpt(PGOOpt) {}
/// \brief Cross register the analysis managers through their proxies.
///
diff --git a/include/llvm/ProfileData/Coverage/CoverageMapping.h b/include/llvm/ProfileData/Coverage/CoverageMapping.h
index d6051ffb3f8d..b9a9f5377698 100644
--- a/include/llvm/ProfileData/Coverage/CoverageMapping.h
+++ b/include/llvm/ProfileData/Coverage/CoverageMapping.h
@@ -1,4 +1,4 @@
-//=-- CoverageMapping.h - Code coverage mapping support ---------*- C++ -*-=//
+//===- CoverageMapping.h - Code coverage mapping support --------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -12,25 +12,42 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_PROFILEDATA_COVERAGEMAPPING_H_
-#define LLVM_PROFILEDATA_COVERAGEMAPPING_H_
+#ifndef LLVM_PROFILEDATA_COVERAGE_COVERAGEMAPPING_H
+#define LLVM_PROFILEDATA_COVERAGE_COVERAGEMAPPING_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/Hashing.h"
-#include "llvm/ADT/StringSet.h"
-#include "llvm/ADT/Triple.h"
#include "llvm/ADT/iterator.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/StringSet.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/ProfileData/InstrProf.h"
+#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Endian.h"
+#include "llvm/Support/Error.h"
#include "llvm/Support/raw_ostream.h"
+#include <cassert>
+#include <cstdint>
+#include <iterator>
+#include <memory>
+#include <string>
#include <system_error>
#include <tuple>
+#include <utility>
+#include <vector>
namespace llvm {
+
+class IndexedInstrProfReader;
+
namespace coverage {
+class CoverageMappingReader;
+struct CoverageMappingRecord;
+
enum class coveragemap_error {
success = 0,
eof,
@@ -68,19 +85,6 @@ private:
coveragemap_error Err;
};
-} // end of coverage namespace.
-} // end of llvm namespace
-
-namespace llvm {
-class IndexedInstrProfReader;
-namespace coverage {
-
-class CoverageMappingReader;
-struct CoverageMappingRecord;
-
-class CoverageMapping;
-struct CounterExpressions;
-
/// \brief A Counter is an abstract value that describes how to compute the
/// execution count for a region of code using the collected profile count data.
struct Counter {
@@ -91,13 +95,13 @@ struct Counter {
EncodingTagBits + 1;
private:
- CounterKind Kind;
- unsigned ID;
+ CounterKind Kind = Zero;
+ unsigned ID = 0;
Counter(CounterKind Kind, unsigned ID) : Kind(Kind), ID(ID) {}
public:
- Counter() : Kind(Zero), ID(0) {}
+ Counter() = default;
CounterKind getKind() const { return Kind; }
@@ -153,8 +157,9 @@ struct CounterExpression {
class CounterExpressionBuilder {
/// \brief A list of all the counter expressions
std::vector<CounterExpression> Expressions;
+
/// \brief A lookup table for the index of a given expression.
- llvm::DenseMap<CounterExpression, unsigned> ExpressionIndices;
+ DenseMap<CounterExpression, unsigned> ExpressionIndices;
/// \brief Return the counter which corresponds to the given expression.
///
@@ -238,7 +243,6 @@ struct CounterMappingRegion {
LineEnd, ColumnEnd, SkippedRegion);
}
-
inline std::pair<unsigned, unsigned> startLoc() const {
return std::pair<unsigned, unsigned>(LineStart, ColumnStart);
}
@@ -269,7 +273,7 @@ public:
void setCounts(ArrayRef<uint64_t> Counts) { CounterValues = Counts; }
- void dump(const Counter &C, llvm::raw_ostream &OS) const;
+ void dump(const Counter &C, raw_ostream &OS) const;
void dump(const Counter &C) const { dump(C, dbgs()); }
/// \brief Return the number of times that a region of code associated with
@@ -390,13 +394,14 @@ struct CoverageSegment {
/// provides a sequence of CoverageSegments to iterate through, as well as the
/// list of expansions that can be further processed.
class CoverageData {
+ friend class CoverageMapping;
+
std::string Filename;
std::vector<CoverageSegment> Segments;
std::vector<ExpansionRecord> Expansions;
- friend class CoverageMapping;
public:
- CoverageData() {}
+ CoverageData() = default;
CoverageData(StringRef Filename) : Filename(Filename) {}
@@ -422,18 +427,17 @@ public:
class CoverageMapping {
StringSet<> FunctionNames;
std::vector<FunctionRecord> Functions;
- unsigned MismatchedFunctionCount;
-
- CoverageMapping() : MismatchedFunctionCount(0) {}
-
- CoverageMapping(const CoverageMapping &) = delete;
- const CoverageMapping &operator=(const CoverageMapping &) = delete;
+ unsigned MismatchedFunctionCount = 0;
+ CoverageMapping() = default;
/// \brief Add a function record corresponding to \p Record.
Error loadFunctionRecord(const CoverageMappingRecord &Record,
IndexedInstrProfReader &ProfileReader);
public:
+ CoverageMapping(const CoverageMapping &) = delete;
+ CoverageMapping &operator=(const CoverageMapping &) = delete;
+
/// \brief Load the coverage mapping using the given readers.
static Expected<std::unique_ptr<CoverageMapping>>
load(CoverageMappingReader &CoverageReader,
@@ -517,14 +521,17 @@ template <class IntPtrT> struct CovMapFunctionRecordV1 {
template <support::endianness Endian> uint64_t getFuncHash() const {
return support::endian::byte_swap<uint64_t, Endian>(FuncHash);
}
+
// Return the coverage map data size for the funciton.
template <support::endianness Endian> uint32_t getDataSize() const {
return support::endian::byte_swap<uint32_t, Endian>(DataSize);
}
+
// Return function lookup key. The value is consider opaque.
template <support::endianness Endian> IntPtrT getFuncNameRef() const {
return support::endian::byte_swap<IntPtrT, Endian>(NamePtr);
}
+
// Return the PGO name of the function */
template <support::endianness Endian>
Error getFuncName(InstrProfSymtab &ProfileNames, StringRef &FuncName) const {
@@ -545,14 +552,17 @@ struct CovMapFunctionRecord {
template <support::endianness Endian> uint64_t getFuncHash() const {
return support::endian::byte_swap<uint64_t, Endian>(FuncHash);
}
+
// Return the coverage map data size for the funciton.
template <support::endianness Endian> uint32_t getDataSize() const {
return support::endian::byte_swap<uint32_t, Endian>(DataSize);
}
+
// Return function lookup key. The value is consider opaque.
template <support::endianness Endian> uint64_t getFuncNameRef() const {
return support::endian::byte_swap<uint64_t, Endian>(NameRef);
}
+
// Return the PGO name of the function */
template <support::endianness Endian>
Error getFuncName(InstrProfSymtab &ProfileNames, StringRef &FuncName) const {
@@ -570,12 +580,15 @@ struct CovMapHeader {
template <support::endianness Endian> uint32_t getNRecords() const {
return support::endian::byte_swap<uint32_t, Endian>(NRecords);
}
+
template <support::endianness Endian> uint32_t getFilenamesSize() const {
return support::endian::byte_swap<uint32_t, Endian>(FilenamesSize);
}
+
template <support::endianness Endian> uint32_t getCoverageSize() const {
return support::endian::byte_swap<uint32_t, Endian>(CoverageSize);
}
+
template <support::endianness Endian> uint32_t getVersion() const {
return support::endian::byte_swap<uint32_t, Endian>(Version);
}
@@ -635,4 +648,4 @@ template<> struct DenseMapInfo<coverage::CounterExpression> {
} // end namespace llvm
-#endif // LLVM_PROFILEDATA_COVERAGEMAPPING_H_
+#endif // LLVM_PROFILEDATA_COVERAGE_COVERAGEMAPPING_H
diff --git a/include/llvm/ProfileData/Coverage/CoverageMappingReader.h b/include/llvm/ProfileData/Coverage/CoverageMappingReader.h
index db907f128d93..5b372252a9ac 100644
--- a/include/llvm/ProfileData/Coverage/CoverageMappingReader.h
+++ b/include/llvm/ProfileData/Coverage/CoverageMappingReader.h
@@ -1,4 +1,4 @@
-//=-- CoverageMappingReader.h - Code coverage mapping reader ------*- C++ -*-=//
+//===- CoverageMappingReader.h - Code coverage mapping reader ---*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -12,18 +12,20 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_PROFILEDATA_COVERAGEMAPPINGREADER_H
-#define LLVM_PROFILEDATA_COVERAGEMAPPINGREADER_H
+#ifndef LLVM_PROFILEDATA_COVERAGE_COVERAGEMAPPINGREADER_H
+#define LLVM_PROFILEDATA_COVERAGE_COVERAGEMAPPINGREADER_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/Triple.h"
-#include "llvm/Object/ObjectFile.h"
#include "llvm/ProfileData/Coverage/CoverageMapping.h"
#include "llvm/ProfileData/InstrProf.h"
-#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Error.h"
#include "llvm/Support/MemoryBuffer.h"
+#include <cstddef>
+#include <cstdint>
#include <iterator>
+#include <memory>
+#include <vector>
namespace llvm {
namespace coverage {
@@ -42,13 +44,14 @@ struct CoverageMappingRecord {
/// \brief A file format agnostic iterator over coverage mapping data.
class CoverageMappingIterator
: public std::iterator<std::input_iterator_tag, CoverageMappingRecord> {
- CoverageMappingReader *Reader;
+ CoverageMappingReader *Reader = nullptr;
CoverageMappingRecord Record;
void increment();
public:
- CoverageMappingIterator() : Reader(nullptr) {}
+ CoverageMappingIterator() = default;
+
CoverageMappingIterator(CoverageMappingReader *Reader) : Reader(Reader) {
increment();
}
@@ -69,10 +72,11 @@ public:
class CoverageMappingReader {
public:
+ virtual ~CoverageMappingReader() = default;
+
virtual Error 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.
@@ -92,13 +96,12 @@ protected:
class RawCoverageFilenamesReader : public RawCoverageReader {
std::vector<StringRef> &Filenames;
- RawCoverageFilenamesReader(const RawCoverageFilenamesReader &) = delete;
- RawCoverageFilenamesReader &
- operator=(const RawCoverageFilenamesReader &) = delete;
-
public:
RawCoverageFilenamesReader(StringRef Data, std::vector<StringRef> &Filenames)
: RawCoverageReader(Data), Filenames(Filenames) {}
+ RawCoverageFilenamesReader(const RawCoverageFilenamesReader &) = delete;
+ RawCoverageFilenamesReader &
+ operator=(const RawCoverageFilenamesReader &) = delete;
Error read();
};
@@ -120,10 +123,6 @@ class RawCoverageMappingReader : public RawCoverageReader {
std::vector<CounterExpression> &Expressions;
std::vector<CounterMappingRegion> &MappingRegions;
- RawCoverageMappingReader(const RawCoverageMappingReader &) = delete;
- RawCoverageMappingReader &
- operator=(const RawCoverageMappingReader &) = delete;
-
public:
RawCoverageMappingReader(StringRef MappingData,
ArrayRef<StringRef> TranslationUnitFilenames,
@@ -134,6 +133,9 @@ public:
TranslationUnitFilenames(TranslationUnitFilenames),
Filenames(Filenames), Expressions(Expressions),
MappingRegions(MappingRegions) {}
+ RawCoverageMappingReader(const RawCoverageMappingReader &) = delete;
+ RawCoverageMappingReader &
+ operator=(const RawCoverageMappingReader &) = delete;
Error read();
@@ -169,17 +171,17 @@ private:
std::vector<StringRef> Filenames;
std::vector<ProfileMappingRecord> MappingRecords;
InstrProfSymtab ProfileNames;
- size_t CurrentRecord;
+ size_t CurrentRecord = 0;
std::vector<StringRef> FunctionsFilenames;
std::vector<CounterExpression> Expressions;
std::vector<CounterMappingRegion> MappingRegions;
+ BinaryCoverageReader() = default;
+
+public:
BinaryCoverageReader(const BinaryCoverageReader &) = delete;
BinaryCoverageReader &operator=(const BinaryCoverageReader &) = delete;
- BinaryCoverageReader() : CurrentRecord(0) {}
-
-public:
static Expected<std::unique_ptr<BinaryCoverageReader>>
create(std::unique_ptr<MemoryBuffer> &ObjectBuffer,
StringRef Arch);
@@ -190,4 +192,4 @@ public:
} // end namespace coverage
} // end namespace llvm
-#endif
+#endif // LLVM_PROFILEDATA_COVERAGE_COVERAGEMAPPINGREADER_H
diff --git a/include/llvm/ProfileData/Coverage/CoverageMappingWriter.h b/include/llvm/ProfileData/Coverage/CoverageMappingWriter.h
index 24fb94647247..b6f864ab3de3 100644
--- a/include/llvm/ProfileData/Coverage/CoverageMappingWriter.h
+++ b/include/llvm/ProfileData/Coverage/CoverageMappingWriter.h
@@ -1,4 +1,4 @@
-//=-- CoverageMappingWriter.h - Code coverage mapping writer ------*- C++ -*-=//
+//===- CoverageMappingWriter.h - Code coverage mapping writer ---*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -12,15 +12,17 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_PROFILEDATA_COVERAGEMAPPINGWRITER_H
-#define LLVM_PROFILEDATA_COVERAGEMAPPINGWRITER_H
+#ifndef LLVM_PROFILEDATA_COVERAGE_COVERAGEMAPPINGWRITER_H
+#define LLVM_PROFILEDATA_COVERAGE_COVERAGEMAPPINGWRITER_H
#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/ProfileData/Coverage/CoverageMapping.h"
-#include "llvm/Support/raw_ostream.h"
namespace llvm {
+
+class raw_ostream;
+
namespace coverage {
/// \brief Writer of the filenames section for the instrumentation
@@ -54,6 +56,7 @@ public:
};
} // end namespace coverage
+
} // end namespace llvm
-#endif
+#endif // LLVM_PROFILEDATA_COVERAGE_COVERAGEMAPPINGWRITER_H
diff --git a/include/llvm/ProfileData/InstrProf.h b/include/llvm/ProfileData/InstrProf.h
index c7e558efa3dc..c9828858cce3 100644
--- a/include/llvm/ProfileData/InstrProf.h
+++ b/include/llvm/ProfileData/InstrProf.h
@@ -1,4 +1,4 @@
-//===-- InstrProf.h - Instrumented profiling format support -----*- C++ -*-===//
+//===- InstrProf.h - Instrumented profiling format support ------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -16,62 +16,57 @@
#ifndef LLVM_PROFILEDATA_INSTRPROF_H
#define LLVM_PROFILEDATA_INSTRPROF_H
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSet.h"
+#include "llvm/ADT/Triple.h"
#include "llvm/IR/GlobalValue.h"
-#include "llvm/IR/Metadata.h"
+#include "llvm/IR/ProfileSummary.h"
#include "llvm/ProfileData/InstrProfData.inc"
-#include "llvm/ProfileData/ProfileCommon.h"
+#include "llvm/Support/Compiler.h"
#include "llvm/Support/Endian.h"
+#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/Host.h"
#include "llvm/Support/MD5.h"
#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
#include <cstdint>
+#include <cstring>
#include <list>
+#include <memory>
+#include <string>
#include <system_error>
+#include <utility>
#include <vector>
namespace llvm {
class Function;
class GlobalVariable;
+struct InstrProfRecord;
+class InstrProfSymtab;
+class Instruction;
+class MDNode;
class Module;
-/// Return the name of data section containing profile counter variables.
-inline StringRef getInstrProfCountersSectionName(bool AddSegment) {
- return AddSegment ? "__DATA," INSTR_PROF_CNTS_SECT_NAME_STR
- : INSTR_PROF_CNTS_SECT_NAME_STR;
-}
-
-/// Return the name of data section containing names of instrumented
-/// functions.
-inline StringRef getInstrProfNameSectionName(bool AddSegment) {
- return AddSegment ? "__DATA," INSTR_PROF_NAME_SECT_NAME_STR
- : INSTR_PROF_NAME_SECT_NAME_STR;
-}
-
-/// Return the name of the data section containing per-function control
-/// data.
-inline StringRef getInstrProfDataSectionName(bool AddSegment) {
- return AddSegment ? "__DATA," INSTR_PROF_DATA_SECT_NAME_STR
- ",regular,live_support"
- : INSTR_PROF_DATA_SECT_NAME_STR;
-}
-
-/// Return the name of data section containing pointers to value profile
-/// counters/nodes.
-inline StringRef getInstrProfValuesSectionName(bool AddSegment) {
- return AddSegment ? "__DATA," INSTR_PROF_VALS_SECT_NAME_STR
- : INSTR_PROF_VALS_SECT_NAME_STR;
-}
+enum InstrProfSectKind {
+#define INSTR_PROF_SECT_ENTRY(Kind, SectNameCommon, SectNameCoff, Prefix) Kind,
+#include "llvm/ProfileData/InstrProfData.inc"
+};
-/// Return the name of data section containing nodes holdling value
-/// profiling data.
-inline StringRef getInstrProfVNodesSectionName(bool AddSegment) {
- return AddSegment ? "__DATA," INSTR_PROF_VNODES_SECT_NAME_STR
- : INSTR_PROF_VNODES_SECT_NAME_STR;
-}
+/// Return the name of the profile section corresponding to \p IPSK.
+///
+/// The name of the section depends on the object format type \p OF. If
+/// \p AddSegmentInfo is true, a segment prefix and additional linker hints may
+/// be added to the section name (this is the default).
+std::string getInstrProfSectionName(InstrProfSectKind IPSK,
+ Triple::ObjectFormatType OF,
+ bool AddSegmentInfo = true);
/// Return the name profile runtime entry point to do value profiling
/// for a given site.
@@ -79,12 +74,18 @@ inline StringRef getInstrProfValueProfFuncName() {
return INSTR_PROF_VALUE_PROF_FUNC_STR;
}
+/// Return the name profile runtime entry point to do value range profiling.
+inline StringRef getInstrProfValueRangeProfFuncName() {
+ return INSTR_PROF_VALUE_RANGE_PROF_FUNC_STR;
+}
+
/// Return the name of the section containing function coverage mapping
/// data.
-inline StringRef getInstrProfCoverageSectionName(bool AddSegment) {
- return AddSegment ? "__LLVM_COV," INSTR_PROF_COVMAP_SECT_NAME_STR
- : INSTR_PROF_COVMAP_SECT_NAME_STR;
-}
+std::string getInstrProfCoverageSectionName(const Module *M = nullptr);
+/// Similar to the above, but used by host tool (e.g, coverage) which has
+/// object format information. The section name returned is not prefixed
+/// with segment name.
+std::string getInstrProfCoverageSectionNameInObject(bool isCoff);
/// Return the name prefix of variables containing instrumented function names.
inline StringRef getInstrProfNameVarPrefix() { return "__profn_"; }
@@ -201,6 +202,7 @@ GlobalVariable *createPGOFuncNameVar(Function &F, StringRef PGOFuncName);
GlobalVariable *createPGOFuncNameVar(Module &M,
GlobalValue::LinkageTypes Linkage,
StringRef PGOFuncName);
+
/// Return the initializer in string of the PGO name var \c NameVar.
StringRef getPGOFuncNameVarInitializer(GlobalVariable *NameVar);
@@ -220,11 +222,12 @@ StringRef getFuncNameWithoutPrefix(StringRef PGOFuncName,
/// second field will have value zero.
Error collectPGOFuncNameStrings(const std::vector<std::string> &NameStrs,
bool doCompression, std::string &Result);
+
/// Produce \c Result string with the same format described above. The input
/// is vector of PGO function name variables that are referenced.
Error collectPGOFuncNameStrings(const std::vector<GlobalVariable *> &NameVars,
std::string &Result, bool doCompression = true);
-class InstrProfSymtab;
+
/// \c NameStrings is a string composed of one of more sub-strings encoded in
/// the format described above. The substrings are separated by 0 or more zero
/// bytes. This method decodes the string and populates the \c Symtab.
@@ -244,8 +247,6 @@ enum InstrProfValueKind : uint32_t {
#include "llvm/ProfileData/InstrProfData.inc"
};
-struct InstrProfRecord;
-
/// Get the value profile data for value site \p SiteIdx from \p InstrProfR
/// and annotate the instruction \p Inst with the value profile meta data.
/// Annotate up to \p MaxMDCount (default 3) number of records per value site.
@@ -253,6 +254,7 @@ void annotateValueSite(Module &M, Instruction &Inst,
const InstrProfRecord &InstrProfR,
InstrProfValueKind ValueKind, uint32_t SiteIndx,
uint32_t MaxMDCount = 3);
+
/// Same as the above interface but using an ArrayRef, as well as \p Sum.
void annotateValueSite(Module &M, Instruction &Inst,
ArrayRef<InstrProfValueData> VDs,
@@ -347,25 +349,22 @@ class SoftInstrProfErrors {
/// the first such error for reporting purposes.
/// The first soft error encountered.
- instrprof_error FirstError;
+ instrprof_error FirstError = instrprof_error::success;
/// The number of hash mismatches.
- unsigned NumHashMismatches;
+ unsigned NumHashMismatches = 0;
/// The number of count mismatches.
- unsigned NumCountMismatches;
+ unsigned NumCountMismatches = 0;
/// The number of counter overflows.
- unsigned NumCounterOverflows;
+ unsigned NumCounterOverflows = 0;
/// The number of value site count mismatches.
- unsigned NumValueSiteCountMismatches;
+ unsigned NumValueSiteCountMismatches = 0;
public:
- SoftInstrProfErrors()
- : FirstError(instrprof_error::success), NumHashMismatches(0),
- NumCountMismatches(0), NumCounterOverflows(0),
- NumValueSiteCountMismatches(0) {}
+ SoftInstrProfErrors() = default;
~SoftInstrProfErrors() {
assert(FirstError == instrprof_error::success &&
@@ -401,12 +400,16 @@ public:
};
namespace object {
+
class SectionRef;
-}
+
+} // end namespace object
namespace IndexedInstrProf {
+
uint64_t ComputeHash(StringRef K);
-}
+
+} // end namespace IndexedInstrProf
/// A symbol table used for function PGO name look-up with keys
/// (such as pointers, md5hash values) to the function. A function's
@@ -419,7 +422,7 @@ public:
private:
StringRef Data;
- uint64_t Address;
+ uint64_t Address = 0;
// Unique name strings.
StringSet<> NameTab;
// A map from MD5 keys to function name strings.
@@ -432,9 +435,7 @@ private:
AddrHashMap AddrToMD5Map;
public:
- InstrProfSymtab()
- : Data(), Address(0), NameTab(), MD5NameMap(), MD5FuncMap(),
- AddrToMD5Map() {}
+ InstrProfSymtab() = default;
/// Create InstrProfSymtab from an object file section which
/// contains function PGO names. When section may contain raw
@@ -443,26 +444,32 @@ public:
/// the section base address. The decompression will be delayed
/// until before it is used. See also \c create(StringRef) method.
Error create(object::SectionRef &Section);
+
/// This interface is used by reader of CoverageMapping test
/// format.
inline Error create(StringRef D, uint64_t BaseAddr);
+
/// \c NameStrings is a string composed of one of more sub-strings
/// encoded in the format described in \c collectPGOFuncNameStrings.
/// This method is a wrapper to \c readPGOFuncNameStrings method.
inline Error create(StringRef NameStrings);
+
/// A wrapper interface to populate the PGO symtab with functions
/// decls from module \c M. This interface is used by transformation
/// passes such as indirect function call promotion. Variable \c InLTO
/// indicates if this is called from LTO optimization passes.
void create(Module &M, bool InLTO = false);
+
/// Create InstrProfSymtab from a set of names iteratable from
/// \p IterRange. This interface is used by IndexedProfReader.
template <typename NameIterRange> void create(const NameIterRange &IterRange);
+
// If the symtab is created by a series of calls to \c addFuncName, \c
// finalizeSymtab needs to be called before looking up function names.
// This is required because the underlying map is a vector (for space
// efficiency) which needs to be sorted.
inline void finalizeSymtab();
+
/// Update the symtab by adding \p FuncName to the table. This interface
/// is used by the raw and text profile readers.
void addFuncName(StringRef FuncName) {
@@ -471,25 +478,32 @@ public:
MD5NameMap.push_back(std::make_pair(
IndexedInstrProf::ComputeHash(FuncName), Ins.first->getKey()));
}
+
/// Map a function address to its name's MD5 hash. This interface
/// is only used by the raw profiler reader.
void mapAddress(uint64_t Addr, uint64_t MD5Val) {
AddrToMD5Map.push_back(std::make_pair(Addr, MD5Val));
}
+
AddrHashMap &getAddrHashMap() { return AddrToMD5Map; }
+
/// Return function's PGO name from the function name's symbol
/// address in the object file. If an error occurs, return
/// an empty string.
StringRef getFuncName(uint64_t FuncNameAddress, size_t NameSize);
+
/// Return function's PGO name from the name's md5 hash value.
/// If not found, return an empty string.
inline StringRef getFuncName(uint64_t FuncMD5Hash);
+
/// Return function from the name's md5 hash. Return nullptr if not found.
inline Function *getFunction(uint64_t FuncMD5Hash);
+
/// Return the function's original assembly name by stripping off
/// the prefix attached (to symbols with priviate linkage). For
/// global functions, it returns the same string as getFuncName.
inline StringRef getOrigFuncName(uint64_t FuncMD5Hash);
+
/// Return the name section data.
inline StringRef getNameData() const { return Data; }
};
@@ -579,40 +593,48 @@ struct InstrProfValueSiteRecord {
/// Profiling information for a single function.
struct InstrProfRecord {
- InstrProfRecord() : SIPE() {}
- InstrProfRecord(StringRef Name, uint64_t Hash, std::vector<uint64_t> Counts)
- : Name(Name), Hash(Hash), Counts(std::move(Counts)), SIPE() {}
StringRef Name;
uint64_t Hash;
std::vector<uint64_t> Counts;
SoftInstrProfErrors SIPE;
+ InstrProfRecord() = default;
+ InstrProfRecord(StringRef Name, uint64_t Hash, std::vector<uint64_t> Counts)
+ : Name(Name), Hash(Hash), Counts(std::move(Counts)) {}
+
typedef std::vector<std::pair<uint64_t, uint64_t>> ValueMapType;
/// Return the number of value profile kinds with non-zero number
/// of profile sites.
inline uint32_t getNumValueKinds() const;
+
/// Return the number of instrumented sites for ValueKind.
inline uint32_t getNumValueSites(uint32_t ValueKind) const;
+
/// Return the total number of ValueData for ValueKind.
inline uint32_t getNumValueData(uint32_t ValueKind) const;
+
/// Return the number of value data collected for ValueKind at profiling
/// site: Site.
inline uint32_t getNumValueDataForSite(uint32_t ValueKind,
uint32_t Site) const;
+
/// Return the array of profiled values at \p Site. If \p TotalC
/// is not null, the total count of all target values at this site
/// will be stored in \c *TotalC.
inline std::unique_ptr<InstrProfValueData[]>
getValueForSite(uint32_t ValueKind, uint32_t Site,
- uint64_t *TotalC = 0) const;
+ uint64_t *TotalC = nullptr) const;
+
/// Get the target value/counts of kind \p ValueKind collected at site
/// \p Site and store the result in array \p Dest. Return the total
/// counts of all target values at this site.
inline uint64_t getValueForSite(InstrProfValueData Dest[], uint32_t ValueKind,
uint32_t Site) const;
+
/// Reserve space for NumValueSites sites.
inline void reserveSites(uint32_t ValueKind, uint32_t NumValueSites);
+
/// Add ValueData for ValueKind at value Site.
void addValueData(uint32_t ValueKind, uint32_t Site,
InstrProfValueData *VData, uint32_t N,
@@ -635,6 +657,13 @@ struct InstrProfRecord {
SR.sortByCount();
}
}
+
+ /// Clear value data entries and edge counters.
+ void Clear() {
+ Counts.clear();
+ clearValueData();
+ }
+
/// Clear value data entries
void clearValueData() {
for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind)
@@ -646,11 +675,15 @@ struct InstrProfRecord {
private:
std::vector<InstrProfValueSiteRecord> IndirectCallSites;
+ std::vector<InstrProfValueSiteRecord> MemOPSizes;
const std::vector<InstrProfValueSiteRecord> &
+
getValueSitesForKind(uint32_t ValueKind) const {
switch (ValueKind) {
case IPVK_IndirectCallTarget:
return IndirectCallSites;
+ case IPVK_MemOPSize:
+ return MemOPSizes;
default:
llvm_unreachable("Unknown value kind!");
}
@@ -672,6 +705,7 @@ private:
// Scale merged value counts by \p Weight.
void mergeValueProfData(uint32_t ValueKind, InstrProfRecord &Src,
uint64_t Weight);
+
// Scale up value profile data count.
void scaleValueProfData(uint32_t ValueKind, uint64_t Weight);
};
@@ -706,7 +740,7 @@ std::unique_ptr<InstrProfValueData[]>
InstrProfRecord::getValueForSite(uint32_t ValueKind, uint32_t Site,
uint64_t *TotalC) const {
uint64_t Dummy;
- uint64_t &TotalCount = (TotalC == 0 ? Dummy : *TotalC);
+ uint64_t &TotalCount = (TotalC == nullptr ? Dummy : *TotalC);
uint32_t N = getNumValueDataForSite(ValueKind, Site);
if (N == 0) {
TotalCount = 0;
@@ -762,7 +796,6 @@ namespace IndexedInstrProf {
enum class HashT : uint32_t {
MD5,
-
Last = MD5
};
@@ -816,7 +849,6 @@ struct Header {
// format. It is introduced in version 4. The summary data follows
// right after the profile file header.
struct Summary {
-
struct Entry {
uint64_t Cutoff; ///< The required percentile of total execution count.
uint64_t
@@ -857,13 +889,16 @@ struct Summary {
const uint64_t *getSummaryDataBase() const {
return reinterpret_cast<const uint64_t *>(this + 1);
}
+
uint64_t *getSummaryDataBase() {
return reinterpret_cast<uint64_t *>(this + 1);
}
+
const Entry *getCutoffEntryBase() const {
return reinterpret_cast<const Entry *>(
&getSummaryDataBase()[NumSummaryFields]);
}
+
Entry *getCutoffEntryBase() {
return reinterpret_cast<Entry *>(&getSummaryDataBase()[NumSummaryFields]);
}
@@ -877,6 +912,7 @@ struct Summary {
}
const Entry &getEntry(uint32_t I) const { return getCutoffEntryBase()[I]; }
+
void setEntry(uint32_t I, const ProfileSummaryEntry &E) {
Entry &ER = getCutoffEntryBase()[I];
ER.Cutoff = E.Cutoff;
@@ -894,6 +930,7 @@ inline std::unique_ptr<Summary> allocSummary(uint32_t TotalSize) {
return std::unique_ptr<Summary>(new (::operator new(TotalSize))
Summary(TotalSize));
}
+
} // end namespace IndexedInstrProf
namespace RawInstrProf {
@@ -937,6 +974,10 @@ struct Header {
} // end namespace RawInstrProf
+// Parse MemOP Size range option.
+void getMemOPSizeRangeFromOption(std::string Str, int64_t &RangeStart,
+ int64_t &RangeLast);
+
} // end namespace llvm
#endif // LLVM_PROFILEDATA_INSTRPROF_H
diff --git a/include/llvm/ProfileData/InstrProfData.inc b/include/llvm/ProfileData/InstrProfData.inc
index f7c22d10763c..be0dd4ad04bf 100644
--- a/include/llvm/ProfileData/InstrProfData.inc
+++ b/include/llvm/ProfileData/InstrProfData.inc
@@ -153,7 +153,17 @@ INSTR_PROF_RAW_HEADER(uint64_t, ValueKindLast, IPVK_Last)
VALUE_PROF_FUNC_PARAM(uint64_t, TargetValue, Type::getInt64Ty(Ctx)) \
INSTR_PROF_COMMA
VALUE_PROF_FUNC_PARAM(void *, Data, Type::getInt8PtrTy(Ctx)) INSTR_PROF_COMMA
+#ifndef VALUE_RANGE_PROF
VALUE_PROF_FUNC_PARAM(uint32_t, CounterIndex, Type::getInt32Ty(Ctx))
+#else /* VALUE_RANGE_PROF */
+VALUE_PROF_FUNC_PARAM(uint32_t, CounterIndex, Type::getInt32Ty(Ctx)) \
+ INSTR_PROF_COMMA
+VALUE_PROF_FUNC_PARAM(uint64_t, PreciseRangeStart, Type::getInt64Ty(Ctx)) \
+ INSTR_PROF_COMMA
+VALUE_PROF_FUNC_PARAM(uint64_t, PreciseRangeLast, Type::getInt64Ty(Ctx)) \
+ INSTR_PROF_COMMA
+VALUE_PROF_FUNC_PARAM(uint64_t, LargeValue, Type::getInt64Ty(Ctx))
+#endif /*VALUE_RANGE_PROF */
#undef VALUE_PROF_FUNC_PARAM
#undef INSTR_PROF_COMMA
/* VALUE_PROF_FUNC_PARAM end */
@@ -174,13 +184,15 @@ VALUE_PROF_FUNC_PARAM(uint32_t, CounterIndex, Type::getInt32Ty(Ctx))
* name hash and the function address.
*/
VALUE_PROF_KIND(IPVK_IndirectCallTarget, 0)
+/* For memory intrinsic functions size profiling. */
+VALUE_PROF_KIND(IPVK_MemOPSize, 1)
/* These two kinds must be the last to be
* declared. This is to make sure the string
* array created with the template can be
* indexed with the kind value.
*/
VALUE_PROF_KIND(IPVK_First, IPVK_IndirectCallTarget)
-VALUE_PROF_KIND(IPVK_Last, IPVK_IndirectCallTarget)
+VALUE_PROF_KIND(IPVK_Last, IPVK_MemOPSize)
#undef VALUE_PROF_KIND
/* VALUE_PROF_KIND end */
@@ -234,6 +246,31 @@ COVMAP_HEADER(uint32_t, Int32Ty, Version, \
/* COVMAP_HEADER end. */
+#ifdef INSTR_PROF_SECT_ENTRY
+#define INSTR_PROF_DATA_DEFINED
+INSTR_PROF_SECT_ENTRY(IPSK_data, \
+ INSTR_PROF_QUOTE(INSTR_PROF_DATA_COMMON), \
+ INSTR_PROF_QUOTE(INSTR_PROF_DATA_COFF), "__DATA,")
+INSTR_PROF_SECT_ENTRY(IPSK_cnts, \
+ INSTR_PROF_QUOTE(INSTR_PROF_CNTS_COMMON), \
+ INSTR_PROF_QUOTE(INSTR_PROF_CNTS_COFF), "__DATA,")
+INSTR_PROF_SECT_ENTRY(IPSK_name, \
+ INSTR_PROF_QUOTE(INSTR_PROF_NAME_COMMON), \
+ INSTR_PROF_QUOTE(INSTR_PROF_NAME_COFF), "__DATA,")
+INSTR_PROF_SECT_ENTRY(IPSK_vals, \
+ INSTR_PROF_QUOTE(INSTR_PROF_VALS_COMMON), \
+ INSTR_PROF_QUOTE(INSTR_PROF_VALS_COFF), "__DATA,")
+INSTR_PROF_SECT_ENTRY(IPSK_vnodes, \
+ INSTR_PROF_QUOTE(INSTR_PROF_VNODES_COMMON), \
+ INSTR_PROF_QUOTE(INSTR_PROF_VNODES_COFF), "__DATA,")
+INSTR_PROF_SECT_ENTRY(IPSK_covmap, \
+ INSTR_PROF_QUOTE(INSTR_PROF_COVMAP_COMMON), \
+ INSTR_PROF_QUOTE(INSTR_PROF_COVMAP_COFF), "__LLVM_COV,")
+
+#undef INSTR_PROF_SECT_ENTRY
+#endif
+
+
#ifdef INSTR_PROF_VALUE_PROF_DATA
#define INSTR_PROF_DATA_DEFINED
@@ -610,17 +647,47 @@ serializeValueProfDataFrom(ValueProfRecordClosure *Closure,
* specified via command line. */
#define INSTR_PROF_PROFILE_NAME_VAR __llvm_profile_filename
+/* section name strings common to all targets other
+ than WIN32 */
+#define INSTR_PROF_DATA_COMMON __llvm_prf_data
+#define INSTR_PROF_NAME_COMMON __llvm_prf_names
+#define INSTR_PROF_CNTS_COMMON __llvm_prf_cnts
+#define INSTR_PROF_VALS_COMMON __llvm_prf_vals
+#define INSTR_PROF_VNODES_COMMON __llvm_prf_vnds
+#define INSTR_PROF_COVMAP_COMMON __llvm_covmap
+/* Win32 */
+#define INSTR_PROF_DATA_COFF .lprfd
+#define INSTR_PROF_NAME_COFF .lprfn
+#define INSTR_PROF_CNTS_COFF .lprfc
+#define INSTR_PROF_VALS_COFF .lprfv
+#define INSTR_PROF_VNODES_COFF .lprfnd
+#define INSTR_PROF_COVMAP_COFF .lcovmap
+
+#ifdef _WIN32
/* Runtime section names and name strings. */
-#define INSTR_PROF_DATA_SECT_NAME __llvm_prf_data
-#define INSTR_PROF_NAME_SECT_NAME __llvm_prf_names
-#define INSTR_PROF_CNTS_SECT_NAME __llvm_prf_cnts
+#define INSTR_PROF_DATA_SECT_NAME INSTR_PROF_DATA_COFF
+#define INSTR_PROF_NAME_SECT_NAME INSTR_PROF_NAME_COFF
+#define INSTR_PROF_CNTS_SECT_NAME INSTR_PROF_CNTS_COFF
/* Array of pointers. Each pointer points to a list
* of value nodes associated with one value site.
*/
-#define INSTR_PROF_VALS_SECT_NAME __llvm_prf_vals
+#define INSTR_PROF_VALS_SECT_NAME INSTR_PROF_VALS_COFF
/* Value profile nodes section. */
-#define INSTR_PROF_VNODES_SECT_NAME __llvm_prf_vnds
-#define INSTR_PROF_COVMAP_SECT_NAME __llvm_covmap
+#define INSTR_PROF_VNODES_SECT_NAME INSTR_PROF_VNODES_COFF
+#define INSTR_PROF_COVMAP_SECT_NAME INSTR_PROF_COVMAP_COFF
+#else
+/* Runtime section names and name strings. */
+#define INSTR_PROF_DATA_SECT_NAME INSTR_PROF_DATA_COMMON
+#define INSTR_PROF_NAME_SECT_NAME INSTR_PROF_NAME_COMMON
+#define INSTR_PROF_CNTS_SECT_NAME INSTR_PROF_CNTS_COMMON
+/* Array of pointers. Each pointer points to a list
+ * of value nodes associated with one value site.
+ */
+#define INSTR_PROF_VALS_SECT_NAME INSTR_PROF_VALS_COMMON
+/* Value profile nodes section. */
+#define INSTR_PROF_VNODES_SECT_NAME INSTR_PROF_VNODES_COMMON
+#define INSTR_PROF_COVMAP_SECT_NAME INSTR_PROF_COVMAP_COMMON
+#endif
#define INSTR_PROF_DATA_SECT_NAME_STR \
INSTR_PROF_QUOTE(INSTR_PROF_DATA_SECT_NAME)
@@ -649,6 +716,9 @@ serializeValueProfDataFrom(ValueProfRecordClosure *Closure,
#define INSTR_PROF_VALUE_PROF_FUNC __llvm_profile_instrument_target
#define INSTR_PROF_VALUE_PROF_FUNC_STR \
INSTR_PROF_QUOTE(INSTR_PROF_VALUE_PROF_FUNC)
+#define INSTR_PROF_VALUE_RANGE_PROF_FUNC __llvm_profile_instrument_range
+#define INSTR_PROF_VALUE_RANGE_PROF_FUNC_STR \
+ INSTR_PROF_QUOTE(INSTR_PROF_VALUE_RANGE_PROF_FUNC)
/* InstrProfile per-function control data alignment. */
#define INSTR_PROF_DATA_ALIGNMENT 8
diff --git a/include/llvm/ProfileData/InstrProfReader.h b/include/llvm/ProfileData/InstrProfReader.h
index 65b11f61d10b..1d85a7149afc 100644
--- a/include/llvm/ProfileData/InstrProfReader.h
+++ b/include/llvm/ProfileData/InstrProfReader.h
@@ -1,4 +1,4 @@
-//=-- InstrProfReader.h - Instrumented profiling readers ----------*- C++ -*-=//
+//===- InstrProfReader.h - Instrumented profiling readers -------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -16,14 +16,23 @@
#define LLVM_PROFILEDATA_INSTRPROFREADER_H
#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/IR/ProfileSummary.h"
#include "llvm/ProfileData/InstrProf.h"
-#include "llvm/Support/EndianStream.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/Error.h"
#include "llvm/Support/LineIterator.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/OnDiskHashTable.h"
-#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/SwapByteOrder.h"
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
#include <iterator>
+#include <memory>
+#include <utility>
+#include <vector>
namespace llvm {
@@ -32,12 +41,13 @@ class InstrProfReader;
/// A file format agnostic iterator over profiling data.
class InstrProfIterator : public std::iterator<std::input_iterator_tag,
InstrProfRecord> {
- InstrProfReader *Reader;
+ InstrProfReader *Reader = nullptr;
InstrProfRecord Record;
void Increment();
+
public:
- InstrProfIterator() : Reader(nullptr) {}
+ InstrProfIterator() = default;
InstrProfIterator(InstrProfReader *Reader) : Reader(Reader) { Increment(); }
InstrProfIterator &operator++() { Increment(); return *this; }
@@ -50,19 +60,22 @@ public:
/// Base class and interface for reading profiling data of any known instrprof
/// format. Provides an iterator over InstrProfRecords.
class InstrProfReader {
- instrprof_error LastError;
+ instrprof_error LastError = instrprof_error::success;
public:
- InstrProfReader() : LastError(instrprof_error::success), Symtab() {}
- virtual ~InstrProfReader() {}
+ InstrProfReader() = default;
+ virtual ~InstrProfReader() = default;
/// Read the header. Required before reading first record.
virtual Error readHeader() = 0;
+
/// Read a single record.
virtual Error readNextRecord(InstrProfRecord &Record) = 0;
+
/// Iterator over profile data.
InstrProfIterator begin() { return InstrProfIterator(this); }
InstrProfIterator end() { return InstrProfIterator(); }
+
virtual bool isIRLevelProfile() const = 0;
/// Return the PGO symtab. There are three different readers:
@@ -86,6 +99,7 @@ protected:
return Error::success();
return make_error<InstrProfError>(Err);
}
+
Error error(Error E) { return error(InstrProfError::take(std::move(E))); }
/// Clear the current error and return a successful one.
@@ -94,8 +108,10 @@ protected:
public:
/// Return true if the reader has finished reading the profile data.
bool isEOF() { return LastError == instrprof_error::eof; }
+
/// Return true if the reader encountered an error reading profiling data.
bool hasError() { return LastError != instrprof_error::success && !isEOF(); }
+
/// Get the current error.
Error getError() {
if (hasError())
@@ -125,16 +141,15 @@ private:
std::unique_ptr<MemoryBuffer> DataBuffer;
/// Iterator over the profile data.
line_iterator Line;
- bool IsIRLevelProfile;
+ bool IsIRLevelProfile = false;
- TextInstrProfReader(const TextInstrProfReader &) = delete;
- TextInstrProfReader &operator=(const TextInstrProfReader &) = delete;
Error readValueProfileData(InstrProfRecord &Record);
public:
TextInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer_)
- : DataBuffer(std::move(DataBuffer_)), Line(*DataBuffer, true, '#'),
- IsIRLevelProfile(false) {}
+ : DataBuffer(std::move(DataBuffer_)), Line(*DataBuffer, true, '#') {}
+ TextInstrProfReader(const TextInstrProfReader &) = delete;
+ TextInstrProfReader &operator=(const TextInstrProfReader &) = delete;
/// Return true if the given buffer is in text instrprof format.
static bool hasFormat(const MemoryBuffer &Buffer);
@@ -143,6 +158,7 @@ public:
/// Read the header.
Error readHeader() override;
+
/// Read a single record.
Error readNextRecord(InstrProfRecord &Record) override;
@@ -184,15 +200,16 @@ private:
InstrProfRecord::ValueMapType FunctionPtrToNameMap;
- RawInstrProfReader(const RawInstrProfReader &) = delete;
- RawInstrProfReader &operator=(const RawInstrProfReader &) = delete;
public:
RawInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer)
: DataBuffer(std::move(DataBuffer)) { }
+ RawInstrProfReader(const RawInstrProfReader &) = delete;
+ RawInstrProfReader &operator=(const RawInstrProfReader &) = delete;
static bool hasFormat(const MemoryBuffer &DataBuffer);
Error readHeader() override;
Error readNextRecord(InstrProfRecord &Record) override;
+
bool isIRLevelProfile() const override {
return (Version & VARIANT_MASK_IR_PROF) != 0;
}
@@ -206,9 +223,11 @@ private:
Error createSymtab(InstrProfSymtab &Symtab);
Error readNextHeader(const char *CurrentPos);
Error readHeader(const RawInstrProf::Header &Header);
+
template <class IntT> IntT swap(IntT Int) const {
return ShouldSwapBytes ? sys::getSwappedBytes(Int) : Int;
}
+
support::endianness getDataEndianness() const {
support::endianness HostEndian = getHostEndianness();
if (!ShouldSwapBytes)
@@ -222,15 +241,18 @@ private:
inline uint8_t getNumPaddingBytes(uint64_t SizeInBytes) {
return 7 & (sizeof(uint64_t) - SizeInBytes % sizeof(uint64_t));
}
+
Error readName(InstrProfRecord &Record);
Error readFuncHash(InstrProfRecord &Record);
Error readRawCounts(InstrProfRecord &Record);
Error readValueProfilingData(InstrProfRecord &Record);
bool atEnd() const { return Data == DataEnd; }
+
void advanceData() {
Data++;
ValueDataStart += CurValueDataSize;
}
+
const char *getNextHeaderPos() const {
assert(atEnd());
return (const char *)ValueDataStart;
@@ -240,6 +262,7 @@ private:
ptrdiff_t Offset = (swap(CounterPtr) - CountersDelta) / sizeof(uint64_t);
return CountersStart + Offset;
}
+
StringRef getName(uint64_t NameRef) const {
return Symtab->getFuncName(swap(NameRef));
}
@@ -249,8 +272,10 @@ typedef RawInstrProfReader<uint32_t> RawInstrProfReader32;
typedef RawInstrProfReader<uint64_t> RawInstrProfReader64;
namespace IndexedInstrProf {
+
enum class HashT : uint32_t;
-}
+
+} // end namespace IndexedInstrProf
/// Trait for lookups into the on-disk hash table for the binary instrprof
/// format.
@@ -261,12 +286,11 @@ class InstrProfLookupTrait {
// Endianness of the input value profile data.
// It should be LE by default, but can be changed
// for testing purpose.
- support::endianness ValueProfDataEndianness;
+ support::endianness ValueProfDataEndianness = support::little;
public:
InstrProfLookupTrait(IndexedInstrProf::HashT HashType, unsigned FormatVersion)
- : HashType(HashType), FormatVersion(FormatVersion),
- ValueProfDataEndianness(support::little) {}
+ : HashType(HashType), FormatVersion(FormatVersion) {}
typedef ArrayRef<InstrProfRecord> data_type;
@@ -284,6 +308,7 @@ public:
static std::pair<offset_type, offset_type>
ReadKeyDataLength(const unsigned char *&D) {
using namespace support;
+
offset_type KeyLen = endian::readNext<offset_type, little, unaligned>(D);
offset_type DataLen = endian::readNext<offset_type, little, unaligned>(D);
return std::make_pair(KeyLen, DataLen);
@@ -304,16 +329,18 @@ public:
};
struct InstrProfReaderIndexBase {
+ virtual ~InstrProfReaderIndexBase() = default;
+
// Read all the profile records with the same key pointed to the current
// iterator.
virtual Error getRecords(ArrayRef<InstrProfRecord> &Data) = 0;
+
// Read all the profile records with the key equal to FuncName
virtual Error getRecords(StringRef FuncName,
ArrayRef<InstrProfRecord> &Data) = 0;
virtual void advanceToNextKey() = 0;
virtual bool atEnd() const = 0;
virtual void setValueProfDataEndianness(support::endianness Endianness) = 0;
- virtual ~InstrProfReaderIndexBase() {}
virtual uint64_t getVersion() const = 0;
virtual bool isIRLevelProfile() const = 0;
virtual void populateSymtab(InstrProfSymtab &) = 0;
@@ -335,22 +362,27 @@ public:
const unsigned char *const Payload,
const unsigned char *const Base,
IndexedInstrProf::HashT HashType, uint64_t Version);
+ ~InstrProfReaderIndex() override = default;
Error getRecords(ArrayRef<InstrProfRecord> &Data) override;
Error getRecords(StringRef FuncName,
ArrayRef<InstrProfRecord> &Data) override;
void advanceToNextKey() override { RecordIterator++; }
+
bool atEnd() const override {
return RecordIterator == HashTable->data_end();
}
+
void setValueProfDataEndianness(support::endianness Endianness) override {
HashTable->getInfoObj().setValueProfDataEndianness(Endianness);
}
- ~InstrProfReaderIndex() override {}
+
uint64_t getVersion() const override { return GET_VERSION(FormatVersion); }
+
bool isIRLevelProfile() const override {
return (FormatVersion & VARIANT_MASK_IR_PROF) != 0;
}
+
void populateSymtab(InstrProfSymtab &Symtab) override {
Symtab.create(HashTable->keys());
}
@@ -366,20 +398,20 @@ private:
/// Profile summary data.
std::unique_ptr<ProfileSummary> Summary;
- IndexedInstrProfReader(const IndexedInstrProfReader &) = delete;
- IndexedInstrProfReader &operator=(const IndexedInstrProfReader &) = delete;
-
// Read the profile summary. Return a pointer pointing to one byte past the
// end of the summary data if it exists or the input \c Cur.
const unsigned char *readSummary(IndexedInstrProf::ProfVersion Version,
const unsigned char *Cur);
public:
+ IndexedInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer)
+ : DataBuffer(std::move(DataBuffer)) {}
+ IndexedInstrProfReader(const IndexedInstrProfReader &) = delete;
+ IndexedInstrProfReader &operator=(const IndexedInstrProfReader &) = delete;
+
/// Return the profile version.
uint64_t getVersion() const { return Index->getVersion(); }
bool isIRLevelProfile() const override { return Index->isIRLevelProfile(); }
- IndexedInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer)
- : DataBuffer(std::move(DataBuffer)), Index(nullptr) {}
/// Return true if the given buffer is in an indexed instrprof format.
static bool hasFormat(const MemoryBuffer &DataBuffer);
@@ -422,4 +454,4 @@ public:
} // end namespace llvm
-#endif
+#endif // LLVM_PROFILEDATA_INSTRPROFREADER_H
diff --git a/include/llvm/ProfileData/InstrProfWriter.h b/include/llvm/ProfileData/InstrProfWriter.h
index f7780fb45004..10742c0228eb 100644
--- a/include/llvm/ProfileData/InstrProfWriter.h
+++ b/include/llvm/ProfileData/InstrProfWriter.h
@@ -1,4 +1,4 @@
-//=-- InstrProfWriter.h - Instrumented profiling writer -----------*- C++ -*-=//
+//===- InstrProfWriter.h - Instrumented profiling writer --------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -16,16 +16,19 @@
#define LLVM_PROFILEDATA_INSTRPROFWRITER_H
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/StringMap.h"
#include "llvm/ProfileData/InstrProf.h"
-#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/Error.h"
#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/raw_ostream.h"
+#include <cstdint>
+#include <memory>
namespace llvm {
/// Writer for instrumentation based profile data.
-class ProfOStream;
class InstrProfRecordWriterTrait;
+class ProfOStream;
class InstrProfWriter {
public:
@@ -35,7 +38,7 @@ public:
private:
bool Sparse;
StringMap<ProfilingData> FunctionData;
- ProfKind ProfileKind;
+ ProfKind ProfileKind = PF_Unknown;
// Use raw pointer here for the incomplete type object.
InstrProfRecordWriterTrait *InfoObj;
@@ -47,15 +50,20 @@ public:
/// for this function and the hash and number of counts match, each counter is
/// summed. Optionally scale counts by \p Weight.
Error addRecord(InstrProfRecord &&I, uint64_t Weight = 1);
+
/// Merge existing function counts from the given writer.
Error mergeRecordsFromWriter(InstrProfWriter &&IPW);
+
/// Write the profile to \c OS
void write(raw_fd_ostream &OS);
+
/// Write the profile in text format to \c OS
void writeText(raw_fd_ostream &OS);
+
/// Write \c Record in text format to \c OS
static void writeRecordInText(const InstrProfRecord &Record,
InstrProfSymtab &Symtab, raw_fd_ostream &OS);
+
/// Write the profile, returning the raw data. For testing.
std::unique_ptr<MemoryBuffer> writeBuffer();
@@ -82,4 +90,4 @@ private:
} // end namespace llvm
-#endif
+#endif // LLVM_PROFILEDATA_INSTRPROFWRITER_H
diff --git a/include/llvm/ProfileData/ProfileCommon.h b/include/llvm/ProfileData/ProfileCommon.h
index e955755e5c9a..987e3160ccae 100644
--- a/include/llvm/ProfileData/ProfileCommon.h
+++ b/include/llvm/ProfileData/ProfileCommon.h
@@ -1,4 +1,4 @@
-//===-- ProfileCommon.h - Common profiling APIs. ----------------*- C++ -*-===//
+//===- ProfileCommon.h - Common profiling APIs. -----------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -12,38 +12,33 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_PROFILEDATA_PROFILE_COMMON_H
-#define LLVM_PROFILEDATA_PROFILE_COMMON_H
+#ifndef LLVM_PROFILEDATA_PROFILECOMMON_H
+#define LLVM_PROFILEDATA_PROFILECOMMON_H
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/IR/ProfileSummary.h"
+#include "llvm/Support/Error.h"
+#include <algorithm>
#include <cstdint>
#include <functional>
#include <map>
-#include <utility>
+#include <memory>
#include <vector>
-#include "llvm/IR/ProfileSummary.h"
-#include "llvm/Support/Error.h"
-#include "llvm/ADT/ArrayRef.h"
-
namespace llvm {
-class Function;
-namespace IndexedInstrProf {
-struct Summary;
-}
+
+struct InstrProfRecord;
+
namespace sampleprof {
+
class FunctionSamples;
-}
-struct InstrProfRecord;
-class LLVMContext;
-class Metadata;
-class MDTuple;
-class MDNode;
+
+} // end namespace sampleprof
inline const char *getHotSectionPrefix() { return ".hot"; }
inline const char *getUnlikelySectionPrefix() { return ".unlikely"; }
class ProfileSummaryBuilder {
-
private:
/// We keep track of the number of times a count (block count or samples)
/// appears in the profile. The map is kept sorted in the descending order of
@@ -53,13 +48,18 @@ private:
protected:
SummaryEntryVector DetailedSummary;
+ uint64_t TotalCount = 0;
+ uint64_t MaxCount = 0;
+ uint64_t MaxFunctionCount = 0;
+ uint32_t NumCounts = 0;
+ uint32_t NumFunctions = 0;
+
ProfileSummaryBuilder(std::vector<uint32_t> Cutoffs)
: DetailedSummaryCutoffs(std::move(Cutoffs)) {}
- inline void addCount(uint64_t Count);
~ProfileSummaryBuilder() = default;
+
+ inline void addCount(uint64_t Count);
void computeDetailedSummary();
- uint64_t TotalCount = 0, MaxCount = 0, MaxFunctionCount = 0;
- uint32_t NumCounts = 0, NumFunctions = 0;
public:
/// \brief A vector of useful cutoff values for detailed summary.
@@ -68,22 +68,24 @@ public:
class InstrProfSummaryBuilder final : public ProfileSummaryBuilder {
uint64_t MaxInternalBlockCount = 0;
+
inline void addEntryCount(uint64_t Count);
inline void addInternalCount(uint64_t Count);
public:
InstrProfSummaryBuilder(std::vector<uint32_t> Cutoffs)
: ProfileSummaryBuilder(std::move(Cutoffs)) {}
+
void addRecord(const InstrProfRecord &);
std::unique_ptr<ProfileSummary> getSummary();
};
class SampleProfileSummaryBuilder final : public ProfileSummaryBuilder {
-
public:
- void addRecord(const sampleprof::FunctionSamples &FS);
SampleProfileSummaryBuilder(std::vector<uint32_t> Cutoffs)
: ProfileSummaryBuilder(std::move(Cutoffs)) {}
+
+ void addRecord(const sampleprof::FunctionSamples &FS);
std::unique_ptr<ProfileSummary> getSummary();
};
@@ -96,6 +98,6 @@ void ProfileSummaryBuilder::addCount(uint64_t Count) {
CountFrequencies[Count]++;
}
-
} // end namespace llvm
-#endif
+
+#endif // LLVM_PROFILEDATA_PROFILECOMMON_H
diff --git a/include/llvm/ProfileData/SampleProf.h b/include/llvm/ProfileData/SampleProf.h
index a96f83620f8b..7a705ca5416d 100644
--- a/include/llvm/ProfileData/SampleProf.h
+++ b/include/llvm/ProfileData/SampleProf.h
@@ -1,4 +1,4 @@
-//=-- SampleProf.h - Sampling profiling format support --------------------===//
+//===- SampleProf.h - Sampling profiling format support ---------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -12,20 +12,30 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_PROFILEDATA_SAMPLEPROF_H_
-#define LLVM_PROFILEDATA_SAMPLEPROF_H_
+#ifndef LLVM_PROFILEDATA_SAMPLEPROF_H
+#define LLVM_PROFILEDATA_SAMPLEPROF_H
+#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/GlobalValue.h"
+#include "llvm/IR/Module.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorOr.h"
-#include "llvm/Support/raw_ostream.h"
-
+#include "llvm/Support/MathExtras.h"
+#include <algorithm>
+#include <cstdint>
#include <map>
+#include <string>
#include <system_error>
+#include <utility>
namespace llvm {
+class raw_ostream;
+
const std::error_category &sampleprof_category();
enum class sampleprof_error {
@@ -59,12 +69,13 @@ inline sampleprof_error MergeResult(sampleprof_error &Accumulator,
} // end namespace llvm
namespace std {
+
template <>
struct is_error_code_enum<llvm::sampleprof_error> : std::true_type {};
-}
-namespace llvm {
+} // end namespace std
+namespace llvm {
namespace sampleprof {
static inline uint64_t SPMagic() {
@@ -87,8 +98,10 @@ static inline uint64_t SPVersion() { return 103; }
/// (e.g., the two post-increment instructions in "if (p) x++; else y++;").
struct LineLocation {
LineLocation(uint32_t L, uint32_t D) : LineOffset(L), Discriminator(D) {}
+
void print(raw_ostream &OS) const;
void dump() const;
+
bool operator<(const LineLocation &O) const {
return LineOffset < O.LineOffset ||
(LineOffset == O.LineOffset && Discriminator < O.Discriminator);
@@ -114,7 +127,7 @@ class SampleRecord {
public:
typedef StringMap<uint64_t> CallTargetMap;
- SampleRecord() : NumSamples(0), CallTargets() {}
+ SampleRecord() = default;
/// Increment the number of samples for this record by \p S.
/// Optionally scale sample count \p S by \p Weight.
@@ -144,7 +157,7 @@ public:
}
/// Return true if this sample record contains function calls.
- bool hasCalls() const { return CallTargets.size() > 0; }
+ bool hasCalls() const { return !CallTargets.empty(); }
uint64_t getSamples() const { return NumSamples; }
const CallTargetMap &getCallTargets() const { return CallTargets; }
@@ -163,7 +176,7 @@ public:
void dump() const;
private:
- uint64_t NumSamples;
+ uint64_t NumSamples = 0;
CallTargetMap CallTargets;
};
@@ -171,7 +184,8 @@ raw_ostream &operator<<(raw_ostream &OS, const SampleRecord &Sample);
typedef std::map<LineLocation, SampleRecord> BodySampleMap;
class FunctionSamples;
-typedef std::map<LineLocation, FunctionSamples> CallsiteSampleMap;
+typedef StringMap<FunctionSamples> FunctionSamplesMap;
+typedef std::map<LineLocation, FunctionSamplesMap> CallsiteSampleMap;
/// Representation of the samples collected for a function.
///
@@ -180,9 +194,11 @@ typedef std::map<LineLocation, FunctionSamples> CallsiteSampleMap;
/// within the body of the function.
class FunctionSamples {
public:
- FunctionSamples() : Name(), TotalSamples(0), TotalHeadSamples(0) {}
+ FunctionSamples() = default;
+
void print(raw_ostream &OS = dbgs(), unsigned Indent = 0) const;
void dump() const;
+
sampleprof_error addTotalSamples(uint64_t Num, uint64_t Weight = 1) {
bool Overflowed;
TotalSamples =
@@ -190,6 +206,7 @@ public:
return Overflowed ? sampleprof_error::counter_overflow
: sampleprof_error::success;
}
+
sampleprof_error addHeadSamples(uint64_t Num, uint64_t Weight = 1) {
bool Overflowed;
TotalHeadSamples =
@@ -197,11 +214,13 @@ public:
return Overflowed ? sampleprof_error::counter_overflow
: sampleprof_error::success;
}
+
sampleprof_error addBodySamples(uint32_t LineOffset, uint32_t Discriminator,
uint64_t Num, uint64_t Weight = 1) {
return BodySamples[LineLocation(LineOffset, Discriminator)].addSamples(
Num, Weight);
}
+
sampleprof_error addCalledTargetSamples(uint32_t LineOffset,
uint32_t Discriminator,
const std::string &FName,
@@ -222,34 +241,53 @@ public:
return ret->second.getSamples();
}
- /// Return the total number of call target samples collected at a given
- /// location. Each location is specified by \p LineOffset and
- /// \p Discriminator. If the location is not found in profile, return error.
- ErrorOr<uint64_t> findCallSamplesAt(uint32_t LineOffset,
- uint32_t Discriminator) const {
+ /// Returns the call target map collected at a given location.
+ /// Each location is specified by \p LineOffset and \p Discriminator.
+ /// If the location is not found in profile, return error.
+ ErrorOr<SampleRecord::CallTargetMap>
+ findCallTargetMapAt(uint32_t LineOffset, uint32_t Discriminator) const {
const auto &ret = BodySamples.find(LineLocation(LineOffset, Discriminator));
if (ret == BodySamples.end())
return std::error_code();
- uint64_t T = 0;
- for (const auto &t_c : ret->second.getCallTargets()) {
- T += t_c.second;
- }
- return T;
+ return ret->second.getCallTargets();
}
/// Return the function samples at the given callsite location.
- FunctionSamples &functionSamplesAt(const LineLocation &Loc) {
+ FunctionSamplesMap &functionSamplesAt(const LineLocation &Loc) {
return CallsiteSamples[Loc];
}
- /// Return a pointer to function samples at the given callsite location.
- const FunctionSamples *findFunctionSamplesAt(const LineLocation &Loc) const {
+ /// Returns the FunctionSamplesMap at the given \p Loc.
+ const FunctionSamplesMap *
+ findFunctionSamplesMapAt(const LineLocation &Loc) const {
auto iter = CallsiteSamples.find(Loc);
- if (iter == CallsiteSamples.end()) {
+ if (iter == CallsiteSamples.end())
return nullptr;
- } else {
- return &iter->second;
- }
+ return &iter->second;
+ }
+
+ /// Returns a pointer to FunctionSamples at the given callsite location \p Loc
+ /// with callee \p CalleeName. If no callsite can be found, relax the
+ /// restriction to return the FunctionSamples at callsite location \p Loc
+ /// with the maximum total sample count.
+ const FunctionSamples *findFunctionSamplesAt(const LineLocation &Loc,
+ StringRef CalleeName) const {
+ auto iter = CallsiteSamples.find(Loc);
+ if (iter == CallsiteSamples.end())
+ return nullptr;
+ auto FS = iter->second.find(CalleeName);
+ if (FS != iter->second.end())
+ return &FS->getValue();
+ // If we cannot find exact match of the callee name, return the FS with
+ // the max total count.
+ uint64_t MaxTotalSamples = 0;
+ const FunctionSamples *R = nullptr;
+ for (const auto &NameFS : iter->second)
+ if (NameFS.second.getTotalSamples() >= MaxTotalSamples) {
+ MaxTotalSamples = NameFS.second.getTotalSamples();
+ R = &NameFS.second;
+ }
+ return R;
}
bool empty() const { return TotalSamples == 0; }
@@ -283,12 +321,28 @@ public:
}
for (const auto &I : Other.getCallsiteSamples()) {
const LineLocation &Loc = I.first;
- const FunctionSamples &Rec = I.second;
- MergeResult(Result, functionSamplesAt(Loc).merge(Rec, Weight));
+ FunctionSamplesMap &FSMap = functionSamplesAt(Loc);
+ for (const auto &Rec : I.second)
+ MergeResult(Result, FSMap[Rec.first()].merge(Rec.second, Weight));
}
return Result;
}
+ /// Recursively traverses all children, if the corresponding function is
+ /// not defined in module \p M, and its total sample is no less than
+ /// \p Threshold, add its corresponding GUID to \p S.
+ void findImportedFunctions(DenseSet<GlobalValue::GUID> &S, const Module *M,
+ uint64_t Threshold) const {
+ if (TotalSamples <= Threshold)
+ return;
+ Function *F = M->getFunction(Name);
+ if (!F || !F->getSubprogram())
+ S.insert(Function::getGUID(Name));
+ for (auto CS : CallsiteSamples)
+ for (const auto &NameFS : CS.second)
+ NameFS.second.findImportedFunctions(S, M, Threshold);
+ }
+
/// Set the name of the function.
void setName(StringRef FunctionName) { Name = FunctionName; }
@@ -303,12 +357,12 @@ private:
///
/// Samples are cumulative, they include all the samples collected
/// inside this function and all its inlined callees.
- uint64_t TotalSamples;
+ uint64_t TotalSamples = 0;
/// 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.
- uint64_t TotalHeadSamples;
+ uint64_t TotalHeadSamples = 0;
/// Map instruction locations to collected samples.
///
@@ -355,6 +409,7 @@ public:
return A->first < B->first;
});
}
+
const SamplesWithLocList &get() const { return V; }
private:
@@ -362,7 +417,6 @@ private:
};
} // end namespace sampleprof
-
} // end namespace llvm
-#endif // LLVM_PROFILEDATA_SAMPLEPROF_H_
+#endif // LLVM_PROFILEDATA_SAMPLEPROF_H
diff --git a/include/llvm/ProfileData/SampleProfReader.h b/include/llvm/ProfileData/SampleProfReader.h
index bf86721709c7..29e3aba3e0e7 100644
--- a/include/llvm/ProfileData/SampleProfReader.h
+++ b/include/llvm/ProfileData/SampleProfReader.h
@@ -1,4 +1,4 @@
-//===- SampleProfReader.h - Read LLVM sample profile data -----------------===//
+//===- SampleProfReader.h - Read LLVM sample profile data -------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -205,26 +205,34 @@
// FUNCTION BODY
// A FUNCTION BODY entry describing the inlined function.
//===----------------------------------------------------------------------===//
+
#ifndef LLVM_PROFILEDATA_SAMPLEPROFREADER_H
#define LLVM_PROFILEDATA_SAMPLEPROFREADER_H
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/LLVMContext.h"
-#include "llvm/ProfileData/ProfileCommon.h"
+#include "llvm/IR/ProfileSummary.h"
#include "llvm/ProfileData/SampleProf.h"
#include "llvm/Support/Debug.h"
-#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/GCOV.h"
#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <cstdint>
+#include <memory>
+#include <string>
+#include <system_error>
+#include <vector>
namespace llvm {
+class raw_ostream;
+
namespace sampleprof {
/// \brief Sample-based profile reader.
@@ -259,7 +267,7 @@ public:
SampleProfileReader(std::unique_ptr<MemoryBuffer> B, LLVMContext &C)
: Profiles(0), Ctx(C), Buffer(std::move(B)) {}
- virtual ~SampleProfileReader() {}
+ virtual ~SampleProfileReader() = default;
/// \brief Read and validate the file header.
virtual std::error_code readHeader() = 0;
@@ -275,7 +283,12 @@ public:
/// \brief Return the samples collected for function \p F.
FunctionSamples *getSamplesFor(const Function &F) {
- return &Profiles[F.getName()];
+ // The function name may have been updated by adding suffix. In sample
+ // profile, the function names are all stripped, so we need to strip
+ // the function name suffix before matching with profile.
+ if (Profiles.count(F.getName().split('.').first))
+ return &Profiles[(F.getName().split('.').first)];
+ return nullptr;
}
/// \brief Return all the profiles.
@@ -442,8 +455,8 @@ protected:
static const uint32_t GCOVTagAFDOFunction = 0xac000000;
};
-} // End namespace sampleprof
+} // end namespace sampleprof
-} // End namespace llvm
+} // end namespace llvm
#endif // LLVM_PROFILEDATA_SAMPLEPROFREADER_H
diff --git a/include/llvm/ProfileData/SampleProfWriter.h b/include/llvm/ProfileData/SampleProfWriter.h
index f6f2e2702e31..9d69af32dd46 100644
--- a/include/llvm/ProfileData/SampleProfWriter.h
+++ b/include/llvm/ProfileData/SampleProfWriter.h
@@ -1,4 +1,4 @@
-//===- SampleProfWriter.h - Write LLVM sample profile data ----------------===//
+//===- SampleProfWriter.h - Write LLVM sample profile data ------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -14,15 +14,18 @@
#define LLVM_PROFILEDATA_SAMPLEPROFWRITER_H
#include "llvm/ADT/MapVector.h"
+#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
-#include "llvm/ProfileData/ProfileCommon.h"
+#include "llvm/IR/ProfileSummary.h"
#include "llvm/ProfileData/SampleProf.h"
#include "llvm/Support/ErrorOr.h"
-#include "llvm/Support/FileSystem.h"
#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <cstdint>
+#include <memory>
+#include <system_error>
namespace llvm {
-
namespace sampleprof {
enum SampleProfileFormat { SPF_None = 0, SPF_Text, SPF_Binary, SPF_GCC };
@@ -30,7 +33,7 @@ enum SampleProfileFormat { SPF_None = 0, SPF_Text, SPF_Binary, SPF_GCC };
/// \brief Sample-based profile writer. Base class.
class SampleProfileWriter {
public:
- virtual ~SampleProfileWriter() {}
+ virtual ~SampleProfileWriter() = default;
/// Write sample profiles in \p S.
///
@@ -114,7 +117,7 @@ public:
protected:
SampleProfileWriterBinary(std::unique_ptr<raw_ostream> &OS)
- : SampleProfileWriter(OS), NameTable() {}
+ : SampleProfileWriter(OS) {}
std::error_code
writeHeader(const StringMap<FunctionSamples> &ProfileMap) override;
@@ -133,8 +136,7 @@ private:
SampleProfileFormat Format);
};
-} // End namespace sampleprof
-
-} // End namespace llvm
+} // end namespace sampleprof
+} // end namespace llvm
#endif // LLVM_PROFILEDATA_SAMPLEPROFWRITER_H
diff --git a/include/llvm/Support/AArch64TargetParser.def b/include/llvm/Support/AArch64TargetParser.def
index c4416f099de1..46d253bf0ec7 100644
--- a/include/llvm/Support/AArch64TargetParser.def
+++ b/include/llvm/Support/AArch64TargetParser.def
@@ -73,8 +73,17 @@ AARCH64_CPU_NAME("falkor", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
(AArch64::AEK_SIMD | AArch64::AEK_CRC | AArch64::AEK_CRYPTO))
AARCH64_CPU_NAME("kryo", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
(AArch64::AEK_SIMD | AArch64::AEK_CRC | AArch64::AEK_CRYPTO))
-AARCH64_CPU_NAME("vulcan", AK_ARMV8_1A, FK_CRYPTO_NEON_FP_ARMV8, false,
- (AArch64::AEK_SIMD | AArch64::AEK_CRC | AArch64::AEK_CRYPTO))
+AARCH64_CPU_NAME("thunderx2t99", AK_ARMV8_1A, FK_CRYPTO_NEON_FP_ARMV8, false,
+ (AArch64::AEK_SIMD | AArch64::AEK_LSE | AArch64::AEK_CRC |
+ AArch64::AEK_CRYPTO))
+AARCH64_CPU_NAME("thunderx", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
+ (AArch64::AEK_SIMD | AArch64::AEK_CRC | AArch64::AEK_CRYPTO | AArch64::AEK_FP | AArch64::AEK_PROFILE))
+AARCH64_CPU_NAME("thunderxt88", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
+ (AArch64::AEK_SIMD | AArch64::AEK_CRC | AArch64::AEK_CRYPTO | AArch64::AEK_FP | AArch64::AEK_PROFILE))
+AARCH64_CPU_NAME("thunderxt81", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
+ (AArch64::AEK_SIMD | AArch64::AEK_CRC | AArch64::AEK_CRYPTO | AArch64::AEK_FP | AArch64::AEK_PROFILE))
+AARCH64_CPU_NAME("thunderxt83", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
+ (AArch64::AEK_SIMD | AArch64::AEK_CRC | AArch64::AEK_CRYPTO | AArch64::AEK_FP | AArch64::AEK_PROFILE))
// Invalid CPU
AARCH64_CPU_NAME("invalid", AK_INVALID, FK_INVALID, true, AArch64::AEK_INVALID)
#undef AARCH64_CPU_NAME
diff --git a/include/llvm/Support/ARMAttributeParser.h b/include/llvm/Support/ARMAttributeParser.h
new file mode 100644
index 000000000000..919f39721f86
--- /dev/null
+++ b/include/llvm/Support/ARMAttributeParser.h
@@ -0,0 +1,140 @@
+//===--- ARMAttributeParser.h - ARM Attribute Information Printer ---------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_ARMATTRIBUTEPARSER_H
+#define LLVM_SUPPORT_ARMATTRIBUTEPARSER_H
+
+#include "ARMBuildAttributes.h"
+#include "ScopedPrinter.h"
+
+#include <map>
+
+namespace llvm {
+class StringRef;
+
+class ARMAttributeParser {
+ ScopedPrinter *SW;
+
+ std::map<unsigned, unsigned> Attributes;
+
+ struct DisplayHandler {
+ ARMBuildAttrs::AttrType Attribute;
+ void (ARMAttributeParser::*Routine)(ARMBuildAttrs::AttrType,
+ const uint8_t *, uint32_t &);
+ };
+ static const DisplayHandler DisplayRoutines[];
+
+ uint64_t ParseInteger(const uint8_t *Data, uint32_t &Offset);
+ StringRef ParseString(const uint8_t *Data, uint32_t &Offset);
+
+ void IntegerAttribute(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void StringAttribute(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+
+ void PrintAttribute(unsigned Tag, unsigned Value, StringRef ValueDesc);
+
+ void CPU_arch(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void CPU_arch_profile(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void ARM_ISA_use(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void THUMB_ISA_use(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void FP_arch(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void WMMX_arch(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void Advanced_SIMD_arch(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void PCS_config(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void ABI_PCS_R9_use(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void ABI_PCS_RW_data(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void ABI_PCS_RO_data(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void ABI_PCS_GOT_use(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void ABI_PCS_wchar_t(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void ABI_FP_rounding(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void ABI_FP_denormal(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void ABI_FP_exceptions(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void ABI_FP_user_exceptions(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void ABI_FP_number_model(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void ABI_align_needed(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void ABI_align_preserved(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void ABI_enum_size(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void ABI_HardFP_use(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void ABI_VFP_args(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void ABI_WMMX_args(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void ABI_optimization_goals(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void ABI_FP_optimization_goals(ARMBuildAttrs::AttrType Tag,
+ const uint8_t *Data, uint32_t &Offset);
+ void compatibility(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void CPU_unaligned_access(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void FP_HP_extension(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void ABI_FP_16bit_format(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void MPextension_use(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void DIV_use(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void DSP_extension(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void T2EE_use(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void Virtualization_use(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+ void nodefaults(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
+ uint32_t &Offset);
+
+ void ParseAttributeList(const uint8_t *Data, uint32_t &Offset,
+ uint32_t Length);
+ void ParseIndexList(const uint8_t *Data, uint32_t &Offset,
+ SmallVectorImpl<uint8_t> &IndexList);
+ void ParseSubsection(const uint8_t *Data, uint32_t Length);
+public:
+ ARMAttributeParser(ScopedPrinter *SW) : SW(SW) {}
+
+ ARMAttributeParser() : SW(nullptr) { }
+
+ void Parse(ArrayRef<uint8_t> Section, bool isLittle);
+
+ bool hasAttribute(unsigned Tag) const {
+ return Attributes.count(Tag);
+ }
+
+ unsigned getAttributeValue(unsigned Tag) const {
+ return Attributes.find(Tag)->second;
+ }
+};
+
+}
+
+#endif
+
diff --git a/include/llvm/Support/ARMBuildAttributes.h b/include/llvm/Support/ARMBuildAttributes.h
index e25445790b0c..6c83e447cb24 100644
--- a/include/llvm/Support/ARMBuildAttributes.h
+++ b/include/llvm/Support/ARMBuildAttributes.h
@@ -176,14 +176,25 @@ enum {
WCharWidth2Bytes = 2, // sizeof(wchar_t) == 2
WCharWidth4Bytes = 4, // sizeof(wchar_t) == 4
+ // Tag_ABI_align_needed, (=24), uleb128
+ Align8Byte = 1,
+ Align4Byte = 2,
+ AlignReserved = 3,
+
+ // Tag_ABI_align_needed, (=25), uleb128
+ AlignNotPreserved = 0,
+ AlignPreserve8Byte = 1,
+ AlignPreserveAll = 2,
+
// Tag_ABI_FP_denormal, (=20), uleb128
PositiveZero = 0,
IEEEDenormals = 1,
PreserveFPSign = 2, // sign when flushed-to-zero is preserved
// Tag_ABI_FP_number_model, (=23), uleb128
+ AllowIEEENormal = 1,
AllowRTABI = 2, // numbers, infinities, and one quiet NaN (see [RTABI])
- AllowIEE754 = 3, // this code to use all the IEEE 754-defined FP encodings
+ AllowIEEE754 = 3, // this code to use all the IEEE 754-defined FP encodings
// Tag_ABI_enum_size, (=26), uleb128
EnumProhibited = 0, // The user prohibited the use of enums when building
@@ -208,6 +219,7 @@ enum {
// Tag_FP_16bit_format, (=38), uleb128
FP16FormatIEEE = 1,
+ FP16VFP3 = 2,
// Tag_MPextension_use, (=42), uleb128
AllowMP = 1, // Allow use of MP extensions
diff --git a/include/llvm/Support/ARMTargetParser.def b/include/llvm/Support/ARMTargetParser.def
index 58cb6381a9ab..18bf9af43226 100644
--- a/include/llvm/Support/ARMTargetParser.def
+++ b/include/llvm/Support/ARMTargetParser.def
@@ -76,6 +76,9 @@ ARM_ARCH("armv6-m", AK_ARMV6M, "6-M", "v6m", ARMBuildAttrs::CPUArch::v6_M,
FK_NONE, ARM::AEK_NONE)
ARM_ARCH("armv7-a", AK_ARMV7A, "7-A", "v7", ARMBuildAttrs::CPUArch::v7,
FK_NEON, ARM::AEK_DSP)
+ARM_ARCH("armv7ve", AK_ARMV7VE, "7VE", "v7ve", ARMBuildAttrs::CPUArch::v7,
+ FK_NEON, (ARM::AEK_SEC | ARM::AEK_MP | ARM::AEK_VIRT |
+ ARM::AEK_HWDIVARM | ARM::AEK_HWDIV | ARM::AEK_DSP))
ARM_ARCH("armv7-r", AK_ARMV7R, "7-R", "v7r", ARMBuildAttrs::CPUArch::v7,
FK_NONE, (ARM::AEK_HWDIV | ARM::AEK_DSP))
ARM_ARCH("armv7-m", AK_ARMV7M, "7-M", "v7m", ARMBuildAttrs::CPUArch::v7,
@@ -229,6 +232,8 @@ ARM_CPU_NAME("sc300", AK_ARMV7M, FK_NONE, false, ARM::AEK_NONE)
ARM_CPU_NAME("cortex-m3", AK_ARMV7M, FK_NONE, true, ARM::AEK_NONE)
ARM_CPU_NAME("cortex-m4", AK_ARMV7EM, FK_FPV4_SP_D16, true, ARM::AEK_NONE)
ARM_CPU_NAME("cortex-m7", AK_ARMV7EM, FK_FPV5_D16, false, ARM::AEK_NONE)
+ARM_CPU_NAME("cortex-m23", AK_ARMV8MBaseline, FK_NONE, false, ARM::AEK_NONE)
+ARM_CPU_NAME("cortex-m33", AK_ARMV8MMainline, FK_FPV5_SP_D16, false, ARM::AEK_DSP)
ARM_CPU_NAME("cortex-a32", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC)
ARM_CPU_NAME("cortex-a35", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC)
ARM_CPU_NAME("cortex-a53", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, true, ARM::AEK_CRC)
@@ -239,6 +244,7 @@ ARM_CPU_NAME("cyclone", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC)
ARM_CPU_NAME("exynos-m1", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC)
ARM_CPU_NAME("exynos-m2", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC)
ARM_CPU_NAME("exynos-m3", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC)
+ARM_CPU_NAME("kryo", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC)
// Non-standard Arch names.
ARM_CPU_NAME("iwmmxt", AK_IWMMXT, FK_NONE, true, ARM::AEK_NONE)
ARM_CPU_NAME("xscale", AK_XSCALE, FK_NONE, true, ARM::AEK_NONE)
diff --git a/include/llvm/Support/Allocator.h b/include/llvm/Support/Allocator.h
index c71759abd7d2..a5e662f4c588 100644
--- a/include/llvm/Support/Allocator.h
+++ b/include/llvm/Support/Allocator.h
@@ -1,4 +1,4 @@
-//===--- Allocator.h - Simple memory allocation abstraction -----*- C++ -*-===//
+//===- Allocator.h - Simple memory allocation abstraction -------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -144,19 +144,18 @@ public:
"that objects larger than a slab go into their own memory "
"allocation.");
- BumpPtrAllocatorImpl()
- : CurPtr(nullptr), End(nullptr), BytesAllocated(0), Allocator() {}
+ BumpPtrAllocatorImpl() = default;
+
template <typename T>
BumpPtrAllocatorImpl(T &&Allocator)
- : CurPtr(nullptr), End(nullptr), BytesAllocated(0),
- Allocator(std::forward<T &&>(Allocator)) {}
+ : Allocator(std::forward<T &&>(Allocator)) {}
// 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)),
CustomSizedSlabs(std::move(Old.CustomSizedSlabs)),
- BytesAllocated(Old.BytesAllocated),
+ BytesAllocated(Old.BytesAllocated), RedZoneSize(Old.RedZoneSize),
Allocator(std::move(Old.Allocator)) {
Old.CurPtr = Old.End = nullptr;
Old.BytesAllocated = 0;
@@ -176,6 +175,7 @@ public:
CurPtr = RHS.CurPtr;
End = RHS.End;
BytesAllocated = RHS.BytesAllocated;
+ RedZoneSize = RHS.RedZoneSize;
Slabs = std::move(RHS.Slabs);
CustomSizedSlabs = std::move(RHS.CustomSizedSlabs);
Allocator = std::move(RHS.Allocator);
@@ -218,10 +218,16 @@ public:
size_t Adjustment = alignmentAdjustment(CurPtr, Alignment);
assert(Adjustment + Size >= Size && "Adjustment + Size must not overflow");
+ size_t SizeToAllocate = Size;
+#if LLVM_ADDRESS_SANITIZER_BUILD
+ // Add trailing bytes as a "red zone" under ASan.
+ SizeToAllocate += RedZoneSize;
+#endif
+
// Check if we have enough space.
- if (Adjustment + Size <= size_t(End - CurPtr)) {
+ if (Adjustment + SizeToAllocate <= size_t(End - CurPtr)) {
char *AlignedPtr = CurPtr + Adjustment;
- CurPtr = AlignedPtr + Size;
+ CurPtr = AlignedPtr + SizeToAllocate;
// Update the allocation point of this memory block in MemorySanitizer.
// Without this, MemorySanitizer messages for values originated from here
// will point to the allocation of the entire slab.
@@ -232,7 +238,7 @@ public:
}
// If Size is really big, allocate a separate slab for it.
- size_t PaddedSize = Size + Alignment - 1;
+ size_t PaddedSize = SizeToAllocate + Alignment - 1;
if (PaddedSize > SizeThreshold) {
void *NewSlab = Allocator.Allocate(PaddedSize, 0);
// We own the new slab and don't want anyone reading anyting other than
@@ -251,10 +257,10 @@ public:
// Otherwise, start a new slab and try again.
StartNewSlab();
uintptr_t AlignedAddr = alignAddr(CurPtr, Alignment);
- assert(AlignedAddr + Size <= (uintptr_t)End &&
+ assert(AlignedAddr + SizeToAllocate <= (uintptr_t)End &&
"Unable to allocate memory!");
char *AlignedPtr = (char*)AlignedAddr;
- CurPtr = AlignedPtr + Size;
+ CurPtr = AlignedPtr + SizeToAllocate;
__msan_allocated_memory(AlignedPtr, Size);
__asan_unpoison_memory_region(AlignedPtr, Size);
return AlignedPtr;
@@ -283,6 +289,10 @@ public:
size_t getBytesAllocated() const { return BytesAllocated; }
+ void setRedZoneSize(size_t NewSize) {
+ RedZoneSize = NewSize;
+ }
+
void PrintStats() const {
detail::printBumpPtrAllocatorStats(Slabs.size(), BytesAllocated,
getTotalMemory());
@@ -292,10 +302,10 @@ private:
/// \brief The current pointer into the current slab.
///
/// This points to the next free byte in the slab.
- char *CurPtr;
+ char *CurPtr = nullptr;
/// \brief The end of the current slab.
- char *End;
+ char *End = nullptr;
/// \brief The slabs allocated so far.
SmallVector<void *, 4> Slabs;
@@ -306,7 +316,11 @@ private:
/// \brief How many bytes we've allocated.
///
/// Used so that we can compute how much space was wasted.
- size_t BytesAllocated;
+ size_t BytesAllocated = 0;
+
+ /// \brief The number of bytes to put between allocations when running under
+ /// a sanitizer.
+ size_t RedZoneSize = 1;
/// \brief The allocator instance we use to get slabs of memory.
AllocatorT Allocator;
@@ -357,7 +371,7 @@ private:
};
/// \brief The standard BumpPtrAllocator which just uses the default template
-/// paramaters.
+/// parameters.
typedef BumpPtrAllocatorImpl<> BumpPtrAllocator;
/// \brief A BumpPtrAllocator that allows only elements of a specific type to be
@@ -369,7 +383,11 @@ template <typename T> class SpecificBumpPtrAllocator {
BumpPtrAllocator Allocator;
public:
- SpecificBumpPtrAllocator() = default;
+ SpecificBumpPtrAllocator() {
+ // Because SpecificBumpPtrAllocator walks the memory to call destructors,
+ // it can't have red zones between allocations.
+ Allocator.setRedZoneSize(0);
+ }
SpecificBumpPtrAllocator(SpecificBumpPtrAllocator &&Old)
: Allocator(std::move(Old.Allocator)) {}
~SpecificBumpPtrAllocator() { DestroyAll(); }
diff --git a/include/llvm/Support/Atomic.h b/include/llvm/Support/Atomic.h
index d03714b009c5..552313f0c241 100644
--- a/include/llvm/Support/Atomic.h
+++ b/include/llvm/Support/Atomic.h
@@ -20,6 +20,11 @@
#include "llvm/Support/DataTypes.h"
+// Windows will at times define MemoryFence.
+#ifdef MemoryFence
+#undef MemoryFence
+#endif
+
namespace llvm {
namespace sys {
void MemoryFence();
diff --git a/include/llvm/Support/BinaryByteStream.h b/include/llvm/Support/BinaryByteStream.h
new file mode 100644
index 000000000000..694be28e07e1
--- /dev/null
+++ b/include/llvm/Support/BinaryByteStream.h
@@ -0,0 +1,192 @@
+//===- BinaryByteStream.h ---------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//===----------------------------------------------------------------------===//
+// A BinaryStream which stores data in a single continguous memory buffer.
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_BINARYBYTESTREAM_H
+#define LLVM_SUPPORT_BINARYBYTESTREAM_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/BinaryStream.h"
+#include "llvm/Support/BinaryStreamError.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/FileOutputBuffer.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include <algorithm>
+#include <cstdint>
+#include <cstring>
+#include <memory>
+
+namespace llvm {
+
+/// \brief An implementation of BinaryStream which holds its entire data set
+/// in a single contiguous buffer. BinaryByteStream guarantees that no read
+/// operation will ever incur a copy. Note that BinaryByteStream does not
+/// own the underlying buffer.
+class BinaryByteStream : public BinaryStream {
+public:
+ BinaryByteStream() = default;
+ BinaryByteStream(ArrayRef<uint8_t> Data, llvm::support::endianness Endian)
+ : Endian(Endian), Data(Data) {}
+ BinaryByteStream(StringRef Data, llvm::support::endianness Endian)
+ : Endian(Endian), Data(Data.bytes_begin(), Data.bytes_end()) {}
+
+ llvm::support::endianness getEndian() const override { return Endian; }
+
+ Error readBytes(uint32_t Offset, uint32_t Size,
+ ArrayRef<uint8_t> &Buffer) override {
+ if (auto EC = checkOffset(Offset, Size))
+ return EC;
+ Buffer = Data.slice(Offset, Size);
+ return Error::success();
+ }
+
+ Error readLongestContiguousChunk(uint32_t Offset,
+ ArrayRef<uint8_t> &Buffer) override {
+ if (auto EC = checkOffset(Offset, 1))
+ return EC;
+ Buffer = Data.slice(Offset);
+ return Error::success();
+ }
+
+ uint32_t getLength() override { return Data.size(); }
+
+ ArrayRef<uint8_t> data() const { return Data; }
+
+ StringRef str() const {
+ const char *CharData = reinterpret_cast<const char *>(Data.data());
+ return StringRef(CharData, Data.size());
+ }
+
+protected:
+ llvm::support::endianness Endian;
+ ArrayRef<uint8_t> Data;
+};
+
+/// \brief An implementation of BinaryStream whose data is backed by an llvm
+/// MemoryBuffer object. MemoryBufferByteStream owns the MemoryBuffer in
+/// question. As with BinaryByteStream, reading from a MemoryBufferByteStream
+/// will never cause a copy.
+class MemoryBufferByteStream : public BinaryByteStream {
+public:
+ MemoryBufferByteStream(std::unique_ptr<MemoryBuffer> Buffer,
+ llvm::support::endianness Endian)
+ : BinaryByteStream(Buffer->getBuffer(), Endian),
+ MemBuffer(std::move(Buffer)) {}
+
+ std::unique_ptr<MemoryBuffer> MemBuffer;
+};
+
+/// \brief An implementation of BinaryStream which holds its entire data set
+/// in a single contiguous buffer. As with BinaryByteStream, the mutable
+/// version also guarantees that no read operation will ever incur a copy,
+/// and similarly it does not own the underlying buffer.
+class MutableBinaryByteStream : public WritableBinaryStream {
+public:
+ MutableBinaryByteStream() = default;
+ MutableBinaryByteStream(MutableArrayRef<uint8_t> Data,
+ llvm::support::endianness Endian)
+ : Data(Data), ImmutableStream(Data, Endian) {}
+
+ llvm::support::endianness getEndian() const override {
+ return ImmutableStream.getEndian();
+ }
+
+ Error readBytes(uint32_t Offset, uint32_t Size,
+ ArrayRef<uint8_t> &Buffer) override {
+ return ImmutableStream.readBytes(Offset, Size, Buffer);
+ }
+
+ Error readLongestContiguousChunk(uint32_t Offset,
+ ArrayRef<uint8_t> &Buffer) override {
+ return ImmutableStream.readLongestContiguousChunk(Offset, Buffer);
+ }
+
+ uint32_t getLength() override { return ImmutableStream.getLength(); }
+
+ Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> Buffer) override {
+ if (Buffer.empty())
+ return Error::success();
+
+ if (auto EC = checkOffset(Offset, Buffer.size()))
+ return EC;
+
+ uint8_t *DataPtr = const_cast<uint8_t *>(Data.data());
+ ::memcpy(DataPtr + Offset, Buffer.data(), Buffer.size());
+ return Error::success();
+ }
+
+ Error commit() override { return Error::success(); }
+
+ MutableArrayRef<uint8_t> data() const { return Data; }
+
+private:
+ MutableArrayRef<uint8_t> Data;
+ BinaryByteStream ImmutableStream;
+};
+
+/// \brief An implementation of WritableBinaryStream backed by an llvm
+/// FileOutputBuffer.
+class FileBufferByteStream : public WritableBinaryStream {
+private:
+ class StreamImpl : public MutableBinaryByteStream {
+ public:
+ StreamImpl(std::unique_ptr<FileOutputBuffer> Buffer,
+ llvm::support::endianness Endian)
+ : MutableBinaryByteStream(
+ MutableArrayRef<uint8_t>(Buffer->getBufferStart(),
+ Buffer->getBufferEnd()),
+ Endian),
+ FileBuffer(std::move(Buffer)) {}
+
+ Error commit() override {
+ if (FileBuffer->commit())
+ return make_error<BinaryStreamError>(
+ stream_error_code::filesystem_error);
+ return Error::success();
+ }
+
+ private:
+ std::unique_ptr<FileOutputBuffer> FileBuffer;
+ };
+
+public:
+ FileBufferByteStream(std::unique_ptr<FileOutputBuffer> Buffer,
+ llvm::support::endianness Endian)
+ : Impl(std::move(Buffer), Endian) {}
+
+ llvm::support::endianness getEndian() const override {
+ return Impl.getEndian();
+ }
+
+ Error readBytes(uint32_t Offset, uint32_t Size,
+ ArrayRef<uint8_t> &Buffer) override {
+ return Impl.readBytes(Offset, Size, Buffer);
+ }
+
+ Error readLongestContiguousChunk(uint32_t Offset,
+ ArrayRef<uint8_t> &Buffer) override {
+ return Impl.readLongestContiguousChunk(Offset, Buffer);
+ }
+
+ uint32_t getLength() override { return Impl.getLength(); }
+
+ Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> Data) override {
+ return Impl.writeBytes(Offset, Data);
+ }
+
+ Error commit() override { return Impl.commit(); }
+
+private:
+ StreamImpl Impl;
+};
+
+} // end namespace llvm
+
+#endif // LLVM_SUPPORT_BYTESTREAM_H
diff --git a/include/llvm/DebugInfo/MSF/SequencedItemStream.h b/include/llvm/Support/BinaryItemStream.h
index 1949beef9fff..f4b319217819 100644
--- a/include/llvm/DebugInfo/MSF/SequencedItemStream.h
+++ b/include/llvm/Support/BinaryItemStream.h
@@ -1,4 +1,4 @@
-//===- SequencedItemStream.h ------------------------------------*- C++ -*-===//
+//===- BinaryItemStream.h ---------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,52 +7,54 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_DEBUGINFO_MSF_SEQUENCEDITEMSTREAM_H
-#define LLVM_DEBUGINFO_MSF_SEQUENCEDITEMSTREAM_H
+#ifndef LLVM_SUPPORT_BINARYITEMSTREAM_H
+#define LLVM_SUPPORT_BINARYITEMSTREAM_H
#include "llvm/ADT/ArrayRef.h"
-#include "llvm/DebugInfo/MSF/MSFError.h"
-#include "llvm/DebugInfo/MSF/StreamInterface.h"
+#include "llvm/Support/BinaryStream.h"
+#include "llvm/Support/BinaryStreamError.h"
#include "llvm/Support/Error.h"
#include <cstddef>
#include <cstdint>
namespace llvm {
-namespace msf {
-template <typename T> struct SequencedItemTraits {
+template <typename T> struct BinaryItemTraits {
static size_t length(const T &Item) = delete;
static ArrayRef<uint8_t> bytes(const T &Item) = delete;
};
-/// SequencedItemStream represents a sequence of objects stored in a
-/// standard container but for which it is useful to view as a stream of
-/// contiguous bytes. An example of this might be if you have a std::vector
-/// of TPI records, where each record contains a byte sequence that
-/// represents that one record serialized, but where each consecutive item
-/// might not be allocated immediately after the previous item. Using a
-/// SequencedItemStream, we can adapt the VarStreamArray class to trivially
-/// extract one item at a time, allowing the data to be used anywhere a
-/// VarStreamArray could be used.
-template <typename T, typename Traits = SequencedItemTraits<T>>
-class SequencedItemStream : public ReadableStream {
+/// BinaryItemStream represents a sequence of objects stored in some kind of
+/// external container but for which it is useful to view as a stream of
+/// contiguous bytes. An example of this might be if you have a collection of
+/// records and you serialize each one into a buffer, and store these serialized
+/// records in a container. The pointers themselves are not laid out
+/// contiguously in memory, but we may wish to read from or write to these
+/// records as if they were.
+template <typename T, typename Traits = BinaryItemTraits<T>>
+class BinaryItemStream : public BinaryStream {
public:
- SequencedItemStream() = default;
+ explicit BinaryItemStream(llvm::support::endianness Endian)
+ : Endian(Endian) {}
+
+ llvm::support::endianness getEndian() const override { return Endian; }
Error readBytes(uint32_t Offset, uint32_t Size,
- ArrayRef<uint8_t> &Buffer) const override {
+ ArrayRef<uint8_t> &Buffer) override {
auto ExpectedIndex = translateOffsetIndex(Offset);
if (!ExpectedIndex)
return ExpectedIndex.takeError();
const auto &Item = Items[*ExpectedIndex];
+ if (auto EC = checkOffset(Offset, Size))
+ return EC;
if (Size > Traits::length(Item))
- return make_error<MSFError>(msf_error_code::insufficient_buffer);
+ return make_error<BinaryStreamError>(stream_error_code::stream_too_short);
Buffer = Traits::bytes(Item).take_front(Size);
return Error::success();
}
Error readLongestContiguousChunk(uint32_t Offset,
- ArrayRef<uint8_t> &Buffer) const override {
+ ArrayRef<uint8_t> &Buffer) override {
auto ExpectedIndex = translateOffsetIndex(Offset);
if (!ExpectedIndex)
return ExpectedIndex.takeError();
@@ -62,7 +64,7 @@ public:
void setItems(ArrayRef<T> ItemArray) { Items = ItemArray; }
- uint32_t getLength() const override {
+ uint32_t getLength() override {
uint32_t Size = 0;
for (const auto &Item : Items)
Size += Traits::length(Item);
@@ -80,14 +82,14 @@ private:
++CurrentIndex;
}
if (CurrentOffset != Offset)
- return make_error<MSFError>(msf_error_code::insufficient_buffer);
+ return make_error<BinaryStreamError>(stream_error_code::stream_too_short);
return CurrentIndex;
}
+ llvm::support::endianness Endian;
ArrayRef<T> Items;
};
-} // end namespace msf
} // end namespace llvm
-#endif // LLVM_DEBUGINFO_MSF_SEQUENCEDITEMSTREAM_H
+#endif // LLVM_SUPPORT_BINARYITEMSTREAM_H
diff --git a/include/llvm/Support/BinaryStream.h b/include/llvm/Support/BinaryStream.h
new file mode 100644
index 000000000000..a227117e063e
--- /dev/null
+++ b/include/llvm/Support/BinaryStream.h
@@ -0,0 +1,78 @@
+//===- BinaryStream.h - Base interface for a stream of data -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_BINARYSTREAM_H
+#define LLVM_SUPPORT_BINARYSTREAM_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/Support/BinaryStreamError.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/Error.h"
+#include <cstdint>
+
+namespace llvm {
+
+/// \brief An interface for accessing data in a stream-like format, but which
+/// discourages copying. Instead of specifying a buffer in which to copy
+/// data on a read, the API returns an ArrayRef to data owned by the stream's
+/// implementation. Since implementations may not necessarily store data in a
+/// single contiguous buffer (or even in memory at all), in such cases a it may
+/// be necessary for an implementation to cache such a buffer so that it can
+/// return it.
+class BinaryStream {
+public:
+ virtual ~BinaryStream() = default;
+
+ virtual llvm::support::endianness getEndian() const = 0;
+
+ /// \brief Given an offset into the stream and a number of bytes, attempt to
+ /// read the bytes and set the output ArrayRef to point to data owned by the
+ /// stream.
+ virtual Error readBytes(uint32_t Offset, uint32_t Size,
+ ArrayRef<uint8_t> &Buffer) = 0;
+
+ /// \brief Given an offset into the stream, read as much as possible without
+ /// copying any data.
+ virtual Error readLongestContiguousChunk(uint32_t Offset,
+ ArrayRef<uint8_t> &Buffer) = 0;
+
+ /// \brief Return the number of bytes of data in this stream.
+ virtual uint32_t getLength() = 0;
+
+protected:
+ Error checkOffset(uint32_t Offset, uint32_t DataSize) {
+ if (Offset > getLength())
+ return make_error<BinaryStreamError>(stream_error_code::invalid_offset);
+ if (getLength() < DataSize + Offset)
+ return make_error<BinaryStreamError>(stream_error_code::stream_too_short);
+ return Error::success();
+ }
+};
+
+/// \brief A BinaryStream which can be read from as well as written to. Note
+/// that writing to a BinaryStream always necessitates copying from the input
+/// buffer to the stream's backing store. Streams are assumed to be buffered
+/// so that to be portable it is necessary to call commit() on the stream when
+/// all data has been written.
+class WritableBinaryStream : public BinaryStream {
+public:
+ ~WritableBinaryStream() override = default;
+
+ /// \brief Attempt to write the given bytes into the stream at the desired
+ /// offset. This will always necessitate a copy. Cannot shrink or grow the
+ /// stream, only writes into existing allocated space.
+ virtual Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> Data) = 0;
+
+ /// \brief For buffered streams, commits changes to the backing store.
+ virtual Error commit() = 0;
+};
+
+} // end namespace llvm
+
+#endif // LLVM_SUPPORT_BINARYSTREAM_H
diff --git a/include/llvm/DebugInfo/MSF/StreamArray.h b/include/llvm/Support/BinaryStreamArray.h
index 5dfeb8c524af..3b1301d3cc0b 100644
--- a/include/llvm/DebugInfo/MSF/StreamArray.h
+++ b/include/llvm/Support/BinaryStreamArray.h
@@ -1,4 +1,4 @@
-//===- StreamArray.h - Array backed by an arbitrary stream ------*- C++ -*-===//
+//===- BinaryStreamArray.h - Array backed by an arbitrary stream *- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,21 +7,30 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_DEBUGINFO_MSF_STREAMARRAY_H
-#define LLVM_DEBUGINFO_MSF_STREAMARRAY_H
+#ifndef LLVM_SUPPORT_BINARYSTREAMARRAY_H
+#define LLVM_SUPPORT_BINARYSTREAMARRAY_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/iterator.h"
-#include "llvm/DebugInfo/MSF/StreamRef.h"
+#include "llvm/Support/BinaryStreamRef.h"
#include "llvm/Support/Error.h"
#include <cassert>
#include <cstdint>
+/// Lightweight arrays that are backed by an arbitrary BinaryStream. This file
+/// provides two different array implementations.
+///
+/// VarStreamArray - Arrays of variable length records. The user specifies
+/// an Extractor type that can extract a record from a given offset and
+/// return the number of bytes consumed by the record.
+///
+/// FixedStreamArray - Arrays of fixed length records. This is similar in
+/// spirit to ArrayRef<T>, but since it is backed by a BinaryStream, the
+/// elements of the array need not be laid out in contiguous memory.
namespace llvm {
-namespace msf {
/// VarStreamArrayExtractor is intended to be specialized to provide customized
-/// extraction logic. On input it receives a StreamRef pointing to the
+/// extraction logic. On input it receives a BinaryStreamRef pointing to the
/// beginning of the next record, but where the length of the record is not yet
/// known. Upon completion, it should return an appropriate Error instance if
/// a record could not be extracted, or if one could be extracted it should
@@ -35,7 +44,7 @@ namespace msf {
template <typename T> struct VarStreamArrayExtractor {
// Method intentionally deleted. You must provide an explicit specialization
// with the following method implemented.
- Error operator()(ReadableStreamRef Stream, uint32_t &Len,
+ Error operator()(BinaryStreamRef Stream, uint32_t &Len,
T &Item) const = delete;
};
@@ -49,10 +58,10 @@ template <typename T> struct VarStreamArrayExtractor {
/// abstracting this out, we need not duplicate this memory, and we can
/// iterate over arrays in arbitrarily formatted streams. Elements are parsed
/// lazily on iteration, so there is no upfront cost associated with building
-/// a VarStreamArray, no matter how large it may be.
+/// or copying a VarStreamArray, no matter how large it may be.
///
/// You create a VarStreamArray by specifying a ValueType and an Extractor type.
-/// If you do not specify an Extractor type, it expects you to specialize
+/// If you do not specify an Extractor type, you are expected to specialize
/// VarStreamArrayExtractor<T> for your ValueType.
///
/// By default an Extractor is default constructed in the class, but in some
@@ -86,8 +95,8 @@ public:
VarStreamArray() = default;
explicit VarStreamArray(const Extractor &E) : E(E) {}
- explicit VarStreamArray(ReadableStreamRef Stream) : Stream(Stream) {}
- VarStreamArray(ReadableStreamRef Stream, const Extractor &E)
+ explicit VarStreamArray(BinaryStreamRef Stream) : Stream(Stream) {}
+ VarStreamArray(BinaryStreamRef Stream, const Extractor &E)
: Stream(Stream), E(E) {}
VarStreamArray(const VarStreamArray<ValueType, Extractor> &Other)
@@ -101,10 +110,10 @@ public:
const Extractor &getExtractor() const { return E; }
- ReadableStreamRef getUnderlyingStream() const { return Stream; }
+ BinaryStreamRef getUnderlyingStream() const { return Stream; }
private:
- ReadableStreamRef Stream;
+ BinaryStreamRef Stream;
Extractor E;
};
@@ -153,23 +162,25 @@ public:
return ThisValue;
}
- IterType &operator++() {
- // We are done with the current record, discard it so that we are
- // positioned at the next record.
- IterRef = IterRef.drop_front(ThisLen);
- if (IterRef.getLength() == 0) {
- // There is nothing after the current record, we must make this an end
- // iterator.
- moveToEnd();
- } else {
- // There is some data after the current record.
- auto EC = Extract(IterRef, ThisLen, ThisValue);
- if (EC) {
- consumeError(std::move(EC));
- markError();
- } else if (ThisLen == 0) {
- // An empty record? Make this an end iterator.
+ IterType &operator+=(unsigned N) {
+ for (unsigned I = 0; I < N; ++I) {
+ // We are done with the current record, discard it so that we are
+ // positioned at the next record.
+ IterRef = IterRef.drop_front(ThisLen);
+ if (IterRef.getLength() == 0) {
+ // There is nothing after the current record, we must make this an end
+ // iterator.
moveToEnd();
+ } else {
+ // There is some data after the current record.
+ auto EC = Extract(IterRef, ThisLen, ThisValue);
+ if (EC) {
+ consumeError(std::move(EC));
+ markError();
+ } else if (ThisLen == 0) {
+ // An empty record? Make this an end iterator.
+ moveToEnd();
+ }
}
}
return *this;
@@ -188,7 +199,7 @@ private:
}
ValueType ThisValue;
- ReadableStreamRef IterRef;
+ BinaryStreamRef IterRef;
const ArrayType *Array{nullptr};
uint32_t ThisLen{0};
bool HasError{false};
@@ -198,12 +209,17 @@ private:
template <typename T> class FixedStreamArrayIterator;
+/// FixedStreamArray is similar to VarStreamArray, except with each record
+/// having a fixed-length. As with VarStreamArray, there is no upfront
+/// cost associated with building or copying a FixedStreamArray, as the
+/// memory for each element is not read from the backing stream until that
+/// element is iterated.
template <typename T> class FixedStreamArray {
friend class FixedStreamArrayIterator<T>;
public:
FixedStreamArray() = default;
- FixedStreamArray(ReadableStreamRef Stream) : Stream(Stream) {
+ explicit FixedStreamArray(BinaryStreamRef Stream) : Stream(Stream) {
assert(Stream.getLength() % sizeof(T) == 0);
}
@@ -227,6 +243,7 @@ public:
// an exact multiple of the element size.
consumeError(std::move(EC));
}
+ assert(llvm::alignmentAdjustment(Data.data(), alignof(T)) == 0);
return *reinterpret_cast<const T *>(Data.data());
}
@@ -242,10 +259,10 @@ public:
return FixedStreamArrayIterator<T>(*this, size());
}
- ReadableStreamRef getUnderlyingStream() const { return Stream; }
+ BinaryStreamRef getUnderlyingStream() const { return Stream; }
private:
- ReadableStreamRef Stream;
+ BinaryStreamRef Stream;
};
template <typename T>
@@ -298,7 +315,6 @@ private:
uint32_t Index;
};
-} // namespace msf
} // namespace llvm
-#endif // LLVM_DEBUGINFO_MSF_STREAMARRAY_H
+#endif // LLVM_SUPPORT_BINARYSTREAMARRAY_H
diff --git a/include/llvm/Support/BinaryStreamError.h b/include/llvm/Support/BinaryStreamError.h
new file mode 100644
index 000000000000..7d9699d53639
--- /dev/null
+++ b/include/llvm/Support/BinaryStreamError.h
@@ -0,0 +1,48 @@
+//===- BinaryStreamError.h - Error extensions for Binary Streams *- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_BINARYSTREAMERROR_H
+#define LLVM_SUPPORT_BINARYSTREAMERROR_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Error.h"
+
+#include <string>
+
+namespace llvm {
+enum class stream_error_code {
+ unspecified,
+ stream_too_short,
+ invalid_array_size,
+ invalid_offset,
+ filesystem_error
+};
+
+/// Base class for errors originating when parsing raw PDB files
+class BinaryStreamError : public ErrorInfo<BinaryStreamError> {
+public:
+ static char ID;
+ explicit BinaryStreamError(stream_error_code C);
+ explicit BinaryStreamError(StringRef Context);
+ BinaryStreamError(stream_error_code C, StringRef Context);
+
+ void log(raw_ostream &OS) const override;
+ std::error_code convertToErrorCode() const override;
+
+ StringRef getErrorMessage() const;
+
+ stream_error_code getErrorCode() const { return Code; }
+
+private:
+ std::string ErrMsg;
+ stream_error_code Code;
+};
+} // namespace llvm
+
+#endif // LLVM_SUPPORT_BINARYSTREAMERROR_H
diff --git a/include/llvm/Support/BinaryStreamReader.h b/include/llvm/Support/BinaryStreamReader.h
new file mode 100644
index 000000000000..d994fa0f49d0
--- /dev/null
+++ b/include/llvm/Support/BinaryStreamReader.h
@@ -0,0 +1,234 @@
+//===- BinaryStreamReader.h - Reads objects from a binary stream *- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_BINARYSTREAMREADER_H
+#define LLVM_SUPPORT_BINARYSTREAMREADER_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/BinaryStreamArray.h"
+#include "llvm/Support/BinaryStreamRef.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/type_traits.h"
+
+#include <string>
+#include <type_traits>
+
+namespace llvm {
+
+/// \brief Provides read only access to a subclass of `BinaryStream`. Provides
+/// bounds checking and helpers for writing certain common data types such as
+/// null-terminated strings, integers in various flavors of endianness, etc.
+/// Can be subclassed to provide reading of custom datatypes, although no
+/// are overridable.
+class BinaryStreamReader {
+public:
+ explicit BinaryStreamReader(BinaryStreamRef Stream);
+ virtual ~BinaryStreamReader() {}
+
+ /// Read as much as possible from the underlying string at the current offset
+ /// without invoking a copy, and set \p Buffer to the resulting data slice.
+ /// Updates the stream's offset to point after the newly read data.
+ ///
+ /// \returns a success error code if the data was successfully read, otherwise
+ /// returns an appropriate error code.
+ Error readLongestContiguousChunk(ArrayRef<uint8_t> &Buffer);
+
+ /// Read \p Size bytes from the underlying stream at the current offset and
+ /// and set \p Buffer to the resulting data slice. Whether a copy occurs
+ /// depends on the implementation of the underlying stream. Updates the
+ /// stream's offset to point after the newly read data.
+ ///
+ /// \returns a success error code if the data was successfully read, otherwise
+ /// returns an appropriate error code.
+ Error readBytes(ArrayRef<uint8_t> &Buffer, uint32_t Size);
+
+ /// Read an integer of the specified endianness into \p Dest and update the
+ /// stream's offset. The data is always copied from the stream's underlying
+ /// buffer into \p Dest. Updates the stream's offset to point after the newly
+ /// read data.
+ ///
+ /// \returns a success error code if the data was successfully read, otherwise
+ /// returns an appropriate error code.
+ template <typename T> Error readInteger(T &Dest) {
+ static_assert(std::is_integral<T>::value,
+ "Cannot call readInteger with non-integral value!");
+
+ ArrayRef<uint8_t> Bytes;
+ if (auto EC = readBytes(Bytes, sizeof(T)))
+ return EC;
+
+ Dest = llvm::support::endian::read<T, llvm::support::unaligned>(
+ Bytes.data(), Stream.getEndian());
+ return Error::success();
+ }
+
+ /// Similar to readInteger.
+ template <typename T> Error readEnum(T &Dest) {
+ static_assert(std::is_enum<T>::value,
+ "Cannot call readEnum with non-enum value!");
+ typename std::underlying_type<T>::type N;
+ if (auto EC = readInteger(N))
+ return EC;
+ Dest = static_cast<T>(N);
+ return Error::success();
+ }
+
+ /// Read a null terminated string from \p Dest. Whether a copy occurs depends
+ /// on the implementation of the underlying stream. Updates the stream's
+ /// offset to point after the newly read data.
+ ///
+ /// \returns a success error code if the data was successfully read, otherwise
+ /// returns an appropriate error code.
+ Error readCString(StringRef &Dest);
+
+ /// Read a \p Length byte string into \p Dest. Whether a copy occurs depends
+ /// on the implementation of the underlying stream. Updates the stream's
+ /// offset to point after the newly read data.
+ ///
+ /// \returns a success error code if the data was successfully read, otherwise
+ /// returns an appropriate error code.
+ Error readFixedString(StringRef &Dest, uint32_t Length);
+
+ /// Read the entire remainder of the underlying stream into \p Ref. This is
+ /// equivalent to calling getUnderlyingStream().slice(Offset). Updates the
+ /// stream's offset to point to the end of the stream. Never causes a copy.
+ ///
+ /// \returns a success error code if the data was successfully read, otherwise
+ /// returns an appropriate error code.
+ Error readStreamRef(BinaryStreamRef &Ref);
+
+ /// Read \p Length bytes from the underlying stream into \p Ref. This is
+ /// equivalent to calling getUnderlyingStream().slice(Offset, Length).
+ /// Updates the stream's offset to point after the newly read object. Never
+ /// causes a copy.
+ ///
+ /// \returns a success error code if the data was successfully read, otherwise
+ /// returns an appropriate error code.
+ Error readStreamRef(BinaryStreamRef &Ref, uint32_t Length);
+
+ /// Get a pointer to an object of type T from the underlying stream, as if by
+ /// memcpy, and store the result into \p Dest. It is up to the caller to
+ /// ensure that objects of type T can be safely treated in this manner.
+ /// Updates the stream's offset to point after the newly read object. Whether
+ /// a copy occurs depends upon the implementation of the underlying
+ /// stream.
+ ///
+ /// \returns a success error code if the data was successfully read, otherwise
+ /// returns an appropriate error code.
+ template <typename T> Error readObject(const T *&Dest) {
+ ArrayRef<uint8_t> Buffer;
+ if (auto EC = readBytes(Buffer, sizeof(T)))
+ return EC;
+ Dest = reinterpret_cast<const T *>(Buffer.data());
+ return Error::success();
+ }
+
+ /// Get a reference to a \p NumElements element array of objects of type T
+ /// from the underlying stream as if by memcpy, and store the resulting array
+ /// slice into \p array. It is up to the caller to ensure that objects of
+ /// type T can be safely treated in this manner. Updates the stream's offset
+ /// to point after the newly read object. Whether a copy occurs depends upon
+ /// the implementation of the underlying stream.
+ ///
+ /// \returns a success error code if the data was successfully read, otherwise
+ /// returns an appropriate error code.
+ template <typename T>
+ Error readArray(ArrayRef<T> &Array, uint32_t NumElements) {
+ ArrayRef<uint8_t> Bytes;
+ if (NumElements == 0) {
+ Array = ArrayRef<T>();
+ return Error::success();
+ }
+
+ if (NumElements > UINT32_MAX / sizeof(T))
+ return make_error<BinaryStreamError>(
+ stream_error_code::invalid_array_size);
+
+ if (auto EC = readBytes(Bytes, NumElements * sizeof(T)))
+ return EC;
+
+ assert(alignmentAdjustment(Bytes.data(), alignof(T)) == 0 &&
+ "Reading at invalid alignment!");
+
+ Array = ArrayRef<T>(reinterpret_cast<const T *>(Bytes.data()), NumElements);
+ return Error::success();
+ }
+
+ /// Read a VarStreamArray of size \p Size bytes and store the result into
+ /// \p Array. Updates the stream's offset to point after the newly read
+ /// array. Never causes a copy (although iterating the elements of the
+ /// VarStreamArray may, depending upon the implementation of the underlying
+ /// stream).
+ ///
+ /// \returns a success error code if the data was successfully read, otherwise
+ /// returns an appropriate error code.
+ template <typename T, typename U>
+ Error readArray(VarStreamArray<T, U> &Array, uint32_t Size) {
+ BinaryStreamRef S;
+ if (auto EC = readStreamRef(S, Size))
+ return EC;
+ Array = VarStreamArray<T, U>(S, Array.getExtractor());
+ return Error::success();
+ }
+
+ /// Read a FixedStreamArray of \p NumItems elements and store the result into
+ /// \p Array. Updates the stream's offset to point after the newly read
+ /// array. Never causes a copy (although iterating the elements of the
+ /// FixedStreamArray may, depending upon the implementation of the underlying
+ /// stream).
+ ///
+ /// \returns a success error code if the data was successfully read, otherwise
+ /// returns an appropriate error code.
+ template <typename T>
+ Error readArray(FixedStreamArray<T> &Array, uint32_t NumItems) {
+ if (NumItems == 0) {
+ Array = FixedStreamArray<T>();
+ return Error::success();
+ }
+
+ if (NumItems > UINT32_MAX / sizeof(T))
+ return make_error<BinaryStreamError>(
+ stream_error_code::invalid_array_size);
+
+ BinaryStreamRef View;
+ if (auto EC = readStreamRef(View, NumItems * sizeof(T)))
+ return EC;
+
+ Array = FixedStreamArray<T>(View);
+ return Error::success();
+ }
+
+ bool empty() const { return bytesRemaining() == 0; }
+ void setOffset(uint32_t Off) { Offset = Off; }
+ uint32_t getOffset() const { return Offset; }
+ uint32_t getLength() const { return Stream.getLength(); }
+ uint32_t bytesRemaining() const { return getLength() - getOffset(); }
+
+ /// Advance the stream's offset by \p Amount bytes.
+ ///
+ /// \returns a success error code if at least \p Amount bytes remain in the
+ /// stream, otherwise returns an appropriate error code.
+ Error skip(uint32_t Amount);
+
+ /// Examine the next byte of the underlying stream without advancing the
+ /// stream's offset. If the stream is empty the behavior is undefined.
+ ///
+ /// \returns the next byte in the stream.
+ uint8_t peek() const;
+
+private:
+ BinaryStreamRef Stream;
+ uint32_t Offset;
+};
+} // namespace llvm
+
+#endif // LLVM_SUPPORT_BINARYSTREAMREADER_H
diff --git a/include/llvm/Support/BinaryStreamRef.h b/include/llvm/Support/BinaryStreamRef.h
new file mode 100644
index 000000000000..23ce02fd7ca4
--- /dev/null
+++ b/include/llvm/Support/BinaryStreamRef.h
@@ -0,0 +1,174 @@
+//===- BinaryStreamRef.h - A copyable reference to a stream -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_BINARYSTREAMREF_H
+#define LLVM_SUPPORT_BINARYSTREAMREF_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/Support/BinaryStream.h"
+#include "llvm/Support/BinaryStreamError.h"
+#include "llvm/Support/Error.h"
+#include <algorithm>
+#include <cstdint>
+
+namespace llvm {
+
+/// Common stuff for mutable and immutable StreamRefs.
+template <class StreamType, class RefType> class BinaryStreamRefBase {
+public:
+ BinaryStreamRefBase() : Stream(nullptr), ViewOffset(0), Length(0) {}
+ BinaryStreamRefBase(StreamType &Stream, uint32_t Offset, uint32_t Length)
+ : Stream(&Stream), ViewOffset(Offset), Length(Length) {}
+
+ llvm::support::endianness getEndian() const { return Stream->getEndian(); }
+
+ uint32_t getLength() const { return Length; }
+ const StreamType *getStream() const { return Stream; }
+
+ /// Return a new BinaryStreamRef with the first \p N elements removed.
+ RefType drop_front(uint32_t N) const {
+ if (!Stream)
+ return RefType();
+
+ N = std::min(N, Length);
+ return RefType(*Stream, ViewOffset + N, Length - N);
+ }
+
+ /// Return a new BinaryStreamRef with only the first \p N elements remaining.
+ RefType keep_front(uint32_t N) const {
+ if (!Stream)
+ return RefType();
+ N = std::min(N, Length);
+ return RefType(*Stream, ViewOffset, N);
+ }
+
+ /// Return a new BinaryStreamRef with the first \p Offset elements removed,
+ /// and retaining exactly \p Len elements.
+ RefType slice(uint32_t Offset, uint32_t Len) const {
+ return drop_front(Offset).keep_front(Len);
+ }
+
+ bool operator==(const RefType &Other) const {
+ if (Stream != Other.Stream)
+ return false;
+ if (ViewOffset != Other.ViewOffset)
+ return false;
+ if (Length != Other.Length)
+ return false;
+ return true;
+ }
+
+protected:
+ Error checkOffset(uint32_t Offset, uint32_t DataSize) const {
+ if (Offset > getLength())
+ return make_error<BinaryStreamError>(stream_error_code::invalid_offset);
+ if (getLength() < DataSize + Offset)
+ return make_error<BinaryStreamError>(stream_error_code::stream_too_short);
+ return Error::success();
+ }
+
+ StreamType *Stream;
+ uint32_t ViewOffset;
+ uint32_t Length;
+};
+
+/// \brief BinaryStreamRef is to BinaryStream what ArrayRef is to an Array. It
+/// provides copy-semantics and read only access to a "window" of the underlying
+/// BinaryStream. Note that BinaryStreamRef is *not* a BinaryStream. That is to
+/// say, it does not inherit and override the methods of BinaryStream. In
+/// general, you should not pass around pointers or references to BinaryStreams
+/// and use inheritance to achieve polymorphism. Instead, you should pass
+/// around BinaryStreamRefs by value and achieve polymorphism that way.
+class BinaryStreamRef
+ : public BinaryStreamRefBase<BinaryStream, BinaryStreamRef> {
+public:
+ BinaryStreamRef() = default;
+ BinaryStreamRef(BinaryStream &Stream)
+ : BinaryStreamRefBase(Stream, 0, Stream.getLength()) {}
+ BinaryStreamRef(BinaryStream &Stream, uint32_t Offset, uint32_t Length)
+ : BinaryStreamRefBase(Stream, Offset, Length) {}
+
+ // Use BinaryStreamRef.slice() instead.
+ BinaryStreamRef(BinaryStreamRef &S, uint32_t Offset,
+ uint32_t Length) = delete;
+
+ /// Given an Offset into this StreamRef and a Size, return a reference to a
+ /// buffer owned by the stream.
+ ///
+ /// \returns a success error code if the entire range of data is within the
+ /// bounds of this BinaryStreamRef's view and the implementation could read
+ /// the data, and an appropriate error code otherwise.
+ Error readBytes(uint32_t Offset, uint32_t Size,
+ ArrayRef<uint8_t> &Buffer) const {
+ if (auto EC = checkOffset(Offset, Size))
+ return EC;
+
+ return Stream->readBytes(ViewOffset + Offset, Size, Buffer);
+ }
+
+ /// Given an Offset into this BinaryStreamRef, return a reference to the
+ /// largest buffer the stream could support without necessitating a copy.
+ ///
+ /// \returns a success error code if implementation could read the data,
+ /// and an appropriate error code otherwise.
+ Error readLongestContiguousChunk(uint32_t Offset,
+ ArrayRef<uint8_t> &Buffer) const {
+ if (auto EC = checkOffset(Offset, 1))
+ return EC;
+
+ if (auto EC =
+ Stream->readLongestContiguousChunk(ViewOffset + Offset, Buffer))
+ return EC;
+ // This StreamRef might refer to a smaller window over a larger stream. In
+ // that case we will have read out more bytes than we should return, because
+ // we should not read past the end of the current view.
+ uint32_t MaxLength = Length - Offset;
+ if (Buffer.size() > MaxLength)
+ Buffer = Buffer.slice(0, MaxLength);
+ return Error::success();
+ }
+};
+
+class WritableBinaryStreamRef
+ : public BinaryStreamRefBase<WritableBinaryStream,
+ WritableBinaryStreamRef> {
+public:
+ WritableBinaryStreamRef() = default;
+ WritableBinaryStreamRef(WritableBinaryStream &Stream)
+ : BinaryStreamRefBase(Stream, 0, Stream.getLength()) {}
+ WritableBinaryStreamRef(WritableBinaryStream &Stream, uint32_t Offset,
+ uint32_t Length)
+ : BinaryStreamRefBase(Stream, Offset, Length) {}
+
+ // Use WritableBinaryStreamRef.slice() instead.
+ WritableBinaryStreamRef(WritableBinaryStreamRef &S, uint32_t Offset,
+ uint32_t Length) = delete;
+
+ /// Given an Offset into this WritableBinaryStreamRef and some input data,
+ /// writes the data to the underlying stream.
+ ///
+ /// \returns a success error code if the data could fit within the underlying
+ /// stream at the specified location and the implementation could write the
+ /// data, and an appropriate error code otherwise.
+ Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> Data) const {
+ if (auto EC = checkOffset(Offset, Data.size()))
+ return EC;
+
+ return Stream->writeBytes(ViewOffset + Offset, Data);
+ }
+
+ operator BinaryStreamRef() { return BinaryStreamRef(*Stream); }
+
+ /// \brief For buffered streams, commits changes to the backing store.
+ Error commit() { return Stream->commit(); }
+};
+
+} // end namespace llvm
+
+#endif // LLVM_SUPPORT_BINARYSTREAMREF_H
diff --git a/include/llvm/Support/BinaryStreamWriter.h b/include/llvm/Support/BinaryStreamWriter.h
new file mode 100644
index 000000000000..64f26b24543d
--- /dev/null
+++ b/include/llvm/Support/BinaryStreamWriter.h
@@ -0,0 +1,166 @@
+//===- BinaryStreamWriter.h - Writes objects to a BinaryStream ---*- C++-*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_BINARYSTREAMWRITER_H
+#define LLVM_SUPPORT_BINARYSTREAMWRITER_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/BinaryStreamArray.h"
+#include "llvm/Support/BinaryStreamError.h"
+#include "llvm/Support/BinaryStreamRef.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/Error.h"
+#include <cstdint>
+#include <type_traits>
+
+namespace llvm {
+
+/// \brief Provides write only access to a subclass of `WritableBinaryStream`.
+/// Provides bounds checking and helpers for writing certain common data types
+/// such as null-terminated strings, integers in various flavors of endianness,
+/// etc. Can be subclassed to provide reading and writing of custom datatypes,
+/// although no methods are overridable.
+class BinaryStreamWriter {
+public:
+ BinaryStreamWriter() = default;
+ explicit BinaryStreamWriter(WritableBinaryStreamRef Stream);
+ virtual ~BinaryStreamWriter() {}
+
+ /// Write the bytes specified in \p Buffer to the underlying stream.
+ /// On success, updates the offset so that subsequent writes will occur
+ /// at the next unwritten position.
+ ///
+ /// \returns a success error code if the data was successfully written,
+ /// otherwise returns an appropriate error code.
+ Error writeBytes(ArrayRef<uint8_t> Buffer);
+
+ /// Write the the integer \p Value to the underlying stream in the
+ /// specified endianness. On success, updates the offset so that
+ /// subsequent writes occur at the next unwritten position.
+ ///
+ /// \returns a success error code if the data was successfully written,
+ /// otherwise returns an appropriate error code.
+ template <typename T> Error writeInteger(T Value) {
+ static_assert(std::is_integral<T>::value,
+ "Cannot call writeInteger with non-integral value!");
+ uint8_t Buffer[sizeof(T)];
+ llvm::support::endian::write<T, llvm::support::unaligned>(
+ Buffer, Value, Stream.getEndian());
+ return writeBytes(Buffer);
+ }
+
+ /// Similar to writeInteger
+ template <typename T> Error writeEnum(T Num) {
+ static_assert(std::is_enum<T>::value,
+ "Cannot call writeEnum with non-Enum type");
+
+ using U = typename std::underlying_type<T>::type;
+ return writeInteger<U>(static_cast<U>(Num));
+ }
+
+ /// Write the the string \p Str to the underlying stream followed by a null
+ /// terminator. On success, updates the offset so that subsequent writes
+ /// occur at the next unwritten position. \p Str need not be null terminated
+ /// on input.
+ ///
+ /// \returns a success error code if the data was successfully written,
+ /// otherwise returns an appropriate error code.
+ Error writeCString(StringRef Str);
+
+ /// Write the the string \p Str to the underlying stream without a null
+ /// terminator. On success, updates the offset so that subsequent writes
+ /// occur at the next unwritten position.
+ ///
+ /// \returns a success error code if the data was successfully written,
+ /// otherwise returns an appropriate error code.
+ Error writeFixedString(StringRef Str);
+
+ /// Efficiently reads all data from \p Ref, and writes it to this stream.
+ /// This operation will not invoke any copies of the source data, regardless
+ /// of the source stream's implementation.
+ ///
+ /// \returns a success error code if the data was successfully written,
+ /// otherwise returns an appropriate error code.
+ Error writeStreamRef(BinaryStreamRef Ref);
+
+ /// Efficiently reads \p Size bytes from \p Ref, and writes it to this stream.
+ /// This operation will not invoke any copies of the source data, regardless
+ /// of the source stream's implementation.
+ ///
+ /// \returns a success error code if the data was successfully written,
+ /// otherwise returns an appropriate error code.
+ Error writeStreamRef(BinaryStreamRef Ref, uint32_t Size);
+
+ /// Writes the object \p Obj to the underlying stream, as if by using memcpy.
+ /// It is up to the caller to ensure that type of \p Obj can be safely copied
+ /// in this fashion, as no checks are made to ensure that this is safe.
+ ///
+ /// \returns a success error code if the data was successfully written,
+ /// otherwise returns an appropriate error code.
+ template <typename T> Error writeObject(const T &Obj) {
+ static_assert(!std::is_pointer<T>::value,
+ "writeObject should not be used with pointers, to write "
+ "the pointed-to value dereference the pointer before calling "
+ "writeObject");
+ return writeBytes(
+ ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(&Obj), sizeof(T)));
+ }
+
+ /// Writes an array of objects of type T to the underlying stream, as if by
+ /// using memcpy. It is up to the caller to ensure that type of \p Obj can
+ /// be safely copied in this fashion, as no checks are made to ensure that
+ /// this is safe.
+ ///
+ /// \returns a success error code if the data was successfully written,
+ /// otherwise returns an appropriate error code.
+ template <typename T> Error writeArray(ArrayRef<T> Array) {
+ if (Array.empty())
+ return Error::success();
+ if (Array.size() > UINT32_MAX / sizeof(T))
+ return make_error<BinaryStreamError>(
+ stream_error_code::invalid_array_size);
+
+ return writeBytes(
+ ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Array.data()),
+ Array.size() * sizeof(T)));
+ }
+
+ /// Writes all data from the array \p Array to the underlying stream.
+ ///
+ /// \returns a success error code if the data was successfully written,
+ /// otherwise returns an appropriate error code.
+ template <typename T, typename U>
+ Error writeArray(VarStreamArray<T, U> Array) {
+ return writeStreamRef(Array.getUnderlyingStream());
+ }
+
+ /// Writes all elements from the array \p Array to the underlying stream.
+ ///
+ /// \returns a success error code if the data was successfully written,
+ /// otherwise returns an appropriate error code.
+ template <typename T> Error writeArray(FixedStreamArray<T> Array) {
+ return writeStreamRef(Array.getUnderlyingStream());
+ }
+
+ void setOffset(uint32_t Off) { Offset = Off; }
+ uint32_t getOffset() const { return Offset; }
+ uint32_t getLength() const { return Stream.getLength(); }
+ uint32_t bytesRemaining() const { return getLength() - getOffset(); }
+ Error padToAlignment(uint32_t Align);
+
+protected:
+ WritableBinaryStreamRef Stream;
+ uint32_t Offset = 0;
+};
+
+} // end namespace llvm
+
+#endif // LLVM_SUPPORT_BINARYSTREAMWRITER_H
diff --git a/include/llvm/Support/CMakeLists.txt b/include/llvm/Support/CMakeLists.txt
new file mode 100644
index 000000000000..b4b993705745
--- /dev/null
+++ b/include/llvm/Support/CMakeLists.txt
@@ -0,0 +1,54 @@
+# Figure out if we can track VC revisions.
+function(find_first_existing_file out_var)
+ foreach(file ${ARGN})
+ if(EXISTS "${file}")
+ set(${out_var} "${file}" PARENT_SCOPE)
+ return()
+ endif()
+ endforeach()
+endfunction()
+
+macro(find_first_existing_vc_file out_var path)
+ find_program(git_executable NAMES git git.exe git.cmd)
+ # Run from a subdirectory to force git to print an absolute path.
+ execute_process(COMMAND ${git_executable} rev-parse --git-dir
+ WORKING_DIRECTORY ${path}/cmake
+ RESULT_VARIABLE git_result
+ OUTPUT_VARIABLE git_dir)
+ if(git_result EQUAL 0)
+ string(STRIP "${git_dir}" git_dir)
+ set(${out_var} "${git_dir}/logs/HEAD")
+ else()
+ find_first_existing_file(${out_var}
+ "${path}/.svn/wc.db" # SVN 1.7
+ "${path}/.svn/entries" # SVN 1.6
+ )
+ endif()
+endmacro()
+
+find_first_existing_vc_file(llvm_vc "${LLVM_MAIN_SRC_DIR}")
+
+# The VC revision include that we want to generate.
+set(version_inc "${CMAKE_CURRENT_BINARY_DIR}/VCSRevision.h")
+
+set(get_svn_script "${LLVM_CMAKE_PATH}/GenerateVersionFromCVS.cmake")
+
+if(DEFINED llvm_vc)
+ # Create custom target to generate the VC revision include.
+ add_custom_command(OUTPUT "${version_inc}"
+ DEPENDS "${llvm_vc}" "${get_svn_script}"
+ COMMAND
+ ${CMAKE_COMMAND} "-DSOURCE_DIR=${LLVM_MAIN_SRC_DIR}"
+ "-DNAME=LLVM_REVISION"
+ "-DHEADER_FILE=${version_inc}"
+ -P "${get_svn_script}")
+
+ # Mark the generated header as being generated.
+ set_source_files_properties("${version_inc}"
+ PROPERTIES GENERATED TRUE
+ HEADER_FILE_ONLY TRUE)
+else()
+ file(WRITE "${version_inc}" "")
+endif()
+
+add_custom_target(llvm_vcsrevision_h DEPENDS "${version_inc}")
diff --git a/include/llvm/Support/CachePruning.h b/include/llvm/Support/CachePruning.h
index 954fd8ae7ffb..e826938878e5 100644
--- a/include/llvm/Support/CachePruning.h
+++ b/include/llvm/Support/CachePruning.h
@@ -20,51 +20,44 @@
namespace llvm {
-/// Handle pruning a directory provided a path and some options to control what
-/// to prune.
-class CachePruning {
-public:
- /// Prepare to prune \p Path.
- CachePruning(StringRef Path) : Path(Path) {}
-
- /// Define the pruning interval. This is intended to be used to avoid scanning
- /// the directory too often. It does not impact the decision of which file to
- /// prune. A value of 0 forces the scan to occurs.
- CachePruning &setPruningInterval(std::chrono::seconds PruningInterval) {
- Interval = PruningInterval;
- return *this;
- }
-
- /// Define the expiration for a file. When a file hasn't been accessed for
- /// \p ExpireAfter seconds, it is removed from the cache. A value of 0 disable
- /// the expiration-based pruning.
- CachePruning &setEntryExpiration(std::chrono::seconds ExpireAfter) {
- Expiration = ExpireAfter;
- return *this;
- }
-
- /// Define the maximum size for the cache directory, in terms of percentage of
- /// the available space on the the disk. Set to 100 to indicate no limit, 50
- /// to indicate that the cache size will not be left over half the
- /// available disk space. A value over 100 will be reduced to 100. A value of
- /// 0 disable the size-based pruning.
- CachePruning &setMaxSize(unsigned Percentage) {
- PercentageOfAvailableSpace = std::min(100u, Percentage);
- return *this;
- }
-
- /// Peform pruning using the supplied options, returns true if pruning
- /// occured, i.e. if PruningInterval was expired.
- bool prune();
-
-private:
- // Options that matches the setters above.
- std::string Path;
- std::chrono::seconds Expiration = std::chrono::seconds::zero();
- std::chrono::seconds Interval = std::chrono::seconds::zero();
- unsigned PercentageOfAvailableSpace = 0;
+template <typename T> class Expected;
+
+/// Policy for the pruneCache() function. A default constructed
+/// CachePruningPolicy provides a reasonable default policy.
+struct CachePruningPolicy {
+ /// The pruning interval. This is intended to be used to avoid scanning the
+ /// directory too often. It does not impact the decision of which file to
+ /// prune. A value of 0 forces the scan to occur.
+ std::chrono::seconds Interval = std::chrono::seconds(1200);
+
+ /// The expiration for a file. When a file hasn't been accessed for Expiration
+ /// seconds, it is removed from the cache. A value of 0 disables the
+ /// expiration-based pruning.
+ std::chrono::seconds Expiration = std::chrono::hours(7 * 24); // 1w
+
+ /// The maximum size for the cache directory, in terms of percentage of the
+ /// available space on the the disk. Set to 100 to indicate no limit, 50 to
+ /// indicate that the cache size will not be left over half the available disk
+ /// space. A value over 100 will be reduced to 100. A value of 0 disables the
+ /// size-based pruning.
+ unsigned PercentageOfAvailableSpace = 75;
};
+/// Parse the given string as a cache pruning policy. Defaults are taken from a
+/// default constructed CachePruningPolicy object.
+/// For example: "prune_interval=30s:prune_after=24h:cache_size=50%"
+/// which means a pruning interval of 30 seconds, expiration time of 24 hours
+/// and maximum cache size of 50% of available disk space.
+Expected<CachePruningPolicy> parseCachePruningPolicy(StringRef PolicyStr);
+
+/// Peform pruning using the supplied policy, returns true if pruning
+/// occured, i.e. if Policy.Interval was expired.
+///
+/// As a safeguard against data loss if the user specifies the wrong directory
+/// as their cache directory, this function will ignore files not matching the
+/// pattern "llvmcache-*".
+bool pruneCache(StringRef Path, CachePruningPolicy Policy);
+
} // namespace llvm
#endif
diff --git a/include/llvm/Support/Casting.h b/include/llvm/Support/Casting.h
index a73047b2b557..89d2af052dc1 100644
--- a/include/llvm/Support/Casting.h
+++ b/include/llvm/Support/Casting.h
@@ -18,6 +18,7 @@
#include "llvm/Support/Compiler.h"
#include "llvm/Support/type_traits.h"
#include <cassert>
+#include <memory>
namespace llvm {
@@ -76,6 +77,14 @@ template <typename To, typename From> struct isa_impl_cl<To, const From> {
}
};
+template <typename To, typename From>
+struct isa_impl_cl<To, const std::unique_ptr<From>> {
+ static inline bool doit(const std::unique_ptr<From> &Val) {
+ assert(Val && "isa<> used on a null pointer");
+ return isa_impl_cl<To, From>::doit(*Val);
+ }
+};
+
template <typename To, typename From> struct isa_impl_cl<To, From*> {
static inline bool doit(const From *Val) {
assert(Val && "isa<> used on a null pointer");
@@ -161,6 +170,15 @@ template<class To, class From> struct cast_retty_impl<To, const From*const> {
typedef const To* ret_type; // Constant pointer arg case, return const Ty*
};
+template <class To, class From>
+struct cast_retty_impl<To, std::unique_ptr<From>> {
+private:
+ typedef typename cast_retty_impl<To, From *>::ret_type PointerType;
+ typedef typename std::remove_pointer<PointerType>::type ResultType;
+
+public:
+ typedef std::unique_ptr<ResultType> ret_type;
+};
template<class To, class From, class SimpleFrom>
struct cast_retty_wrap {
@@ -238,6 +256,16 @@ inline typename cast_retty<X, Y *>::ret_type cast(Y *Val) {
typename simplify_type<Y*>::SimpleType>::doit(Val);
}
+template <class X, class Y>
+inline typename cast_retty<X, std::unique_ptr<Y>>::ret_type
+cast(std::unique_ptr<Y> &&Val) {
+ assert(isa<X>(Val.get()) && "cast<Ty>() argument of incompatible type!");
+ using ret_type = typename cast_retty<X, std::unique_ptr<Y>>::ret_type;
+ return ret_type(
+ cast_convert_val<X, Y *, typename simplify_type<Y *>::SimpleType>::doit(
+ Val.release()));
+}
+
// cast_or_null<X> - Functionally identical to cast, except that a null value is
// accepted.
//
@@ -271,6 +299,13 @@ cast_or_null(Y *Val) {
return cast<X>(Val);
}
+template <class X, class Y>
+inline typename cast_retty<X, std::unique_ptr<Y>>::ret_type
+cast_or_null(std::unique_ptr<Y> &&Val) {
+ if (!Val)
+ return nullptr;
+ return cast<X>(std::move(Val));
+}
// dyn_cast<X> - Return the argument parameter cast to the specified type. This
// casting operator returns null if the argument is of the wrong type, so it can
@@ -323,6 +358,41 @@ dyn_cast_or_null(Y *Val) {
return (Val && isa<X>(Val)) ? cast<X>(Val) : nullptr;
}
+// unique_dyn_cast<X> - Given a unique_ptr<Y>, try to return a unique_ptr<X>,
+// taking ownership of the input pointer iff isa<X>(Val) is true. If the
+// cast is successful, From refers to nullptr on exit and the casted value
+// is returned. If the cast is unsuccessful, the function returns nullptr
+// and From is unchanged.
+template <class X, class Y>
+LLVM_NODISCARD inline auto unique_dyn_cast(std::unique_ptr<Y> &Val)
+ -> decltype(cast<X>(Val)) {
+ if (!isa<X>(Val))
+ return nullptr;
+ return cast<X>(std::move(Val));
+}
+
+template <class X, class Y>
+LLVM_NODISCARD inline auto unique_dyn_cast(std::unique_ptr<Y> &&Val)
+ -> decltype(cast<X>(Val)) {
+ return unique_dyn_cast<X, Y>(Val);
+}
+
+// dyn_cast_or_null<X> - Functionally identical to unique_dyn_cast, except that
+// a null value is accepted.
+template <class X, class Y>
+LLVM_NODISCARD inline auto unique_dyn_cast_or_null(std::unique_ptr<Y> &Val)
+ -> decltype(cast<X>(Val)) {
+ if (!Val)
+ return nullptr;
+ return unique_dyn_cast<X, Y>(Val);
+}
+
+template <class X, class Y>
+LLVM_NODISCARD inline auto unique_dyn_cast_or_null(std::unique_ptr<Y> &&Val)
+ -> decltype(cast<X>(Val)) {
+ return unique_dyn_cast_or_null<X, Y>(Val);
+}
+
} // End llvm namespace
#endif
diff --git a/include/llvm/Support/Chrono.h b/include/llvm/Support/Chrono.h
index 203439cab919..6118ed0476ed 100644
--- a/include/llvm/Support/Chrono.h
+++ b/include/llvm/Support/Chrono.h
@@ -11,6 +11,7 @@
#define LLVM_SUPPORT_CHRONO_H
#include "llvm/Support/Compiler.h"
+#include "llvm/Support/FormatProviders.h"
#include <chrono>
#include <ctime>
@@ -50,6 +51,100 @@ toTimePoint(std::time_t T) {
raw_ostream &operator<<(raw_ostream &OS, sys::TimePoint<> TP);
+/// Implementation of format_provider<T> for duration types.
+///
+/// The options string of a duration type has the grammar:
+///
+/// duration_options ::= [unit][show_unit [number_options]]
+/// unit ::= `h`|`m`|`s`|`ms|`us`|`ns`
+/// show_unit ::= `+` | `-`
+/// number_options ::= options string for a integral or floating point type
+///
+/// Examples
+/// =================================
+/// | options | Input | Output |
+/// =================================
+/// | "" | 1s | 1 s |
+/// | "ms" | 1s | 1000 ms |
+/// | "ms-" | 1s | 1000 |
+/// | "ms-n" | 1s | 1,000 |
+/// | "" | 1.0s | 1.00 s |
+/// =================================
+///
+/// If the unit of the duration type is not one of the units specified above,
+/// it is still possible to format it, provided you explicitly request a
+/// display unit or you request that the unit is not displayed.
+
+namespace detail {
+template <typename Period> struct unit { static const char value[]; };
+template <typename Period> const char unit<Period>::value[] = "";
+
+template <> struct unit<std::ratio<3600>> { static const char value[]; };
+template <> struct unit<std::ratio<60>> { static const char value[]; };
+template <> struct unit<std::ratio<1>> { static const char value[]; };
+template <> struct unit<std::milli> { static const char value[]; };
+template <> struct unit<std::micro> { static const char value[]; };
+template <> struct unit<std::nano> { static const char value[]; };
+} // namespace detail
+
+template <typename Rep, typename Period>
+struct format_provider<std::chrono::duration<Rep, Period>> {
+private:
+ typedef std::chrono::duration<Rep, Period> Dur;
+ typedef typename std::conditional<
+ std::chrono::treat_as_floating_point<Rep>::value, double, intmax_t>::type
+ InternalRep;
+
+ template <typename AsPeriod> static InternalRep getAs(const Dur &D) {
+ using namespace std::chrono;
+ return duration_cast<duration<InternalRep, AsPeriod>>(D).count();
+ }
+
+ static std::pair<InternalRep, StringRef> consumeUnit(StringRef &Style,
+ const Dur &D) {
+ using namespace std::chrono;
+ if (Style.consume_front("ns"))
+ return {getAs<std::nano>(D), "ns"};
+ if (Style.consume_front("us"))
+ return {getAs<std::micro>(D), "us"};
+ if (Style.consume_front("ms"))
+ return {getAs<std::milli>(D), "ms"};
+ if (Style.consume_front("s"))
+ return {getAs<std::ratio<1>>(D), "s"};
+ if (Style.consume_front("m"))
+ return {getAs<std::ratio<60>>(D), "m"};
+ if (Style.consume_front("h"))
+ return {getAs<std::ratio<3600>>(D), "h"};
+ return {D.count(), detail::unit<Period>::value};
+ }
+
+ static bool consumeShowUnit(StringRef &Style) {
+ if (Style.empty())
+ return true;
+ if (Style.consume_front("-"))
+ return false;
+ if (Style.consume_front("+"))
+ return true;
+ assert(0 && "Unrecognised duration format");
+ return true;
+ }
+
+public:
+ static void format(const Dur &D, llvm::raw_ostream &Stream, StringRef Style) {
+ InternalRep count;
+ StringRef unit;
+ std::tie(count, unit) = consumeUnit(Style, D);
+ bool show_unit = consumeShowUnit(Style);
+
+ format_provider<InternalRep>::format(count, Stream, Style);
+
+ if (show_unit) {
+ assert(!unit.empty());
+ Stream << " " << unit;
+ }
+ }
+};
+
} // namespace llvm
#endif // LLVM_SUPPORT_CHRONO_H
diff --git a/include/llvm/Support/CommandLine.h b/include/llvm/Support/CommandLine.h
index 8d4ac81d2942..ae32e20d6dab 100644
--- a/include/llvm/Support/CommandLine.h
+++ b/include/llvm/Support/CommandLine.h
@@ -50,9 +50,12 @@ namespace cl {
//===----------------------------------------------------------------------===//
// ParseCommandLineOptions - Command line option processing entry point.
//
+// Returns true on success. Otherwise, this will print the error message to
+// stderr and exit if \p Errs is not set (nullptr by default), or print the
+// error message to \p Errs and return false if \p Errs is provided.
bool ParseCommandLineOptions(int argc, const char *const *argv,
StringRef Overview = "",
- bool IgnoreErrors = false);
+ raw_ostream *Errs = nullptr);
//===----------------------------------------------------------------------===//
// ParseEnvironmentOptions - Environment variable option processing alternate
@@ -343,6 +346,9 @@ public:
virtual void printOptionValue(size_t GlobalWidth, bool Force) const = 0;
+ static void printHelpStr(StringRef HelpStr, size_t Indent,
+ size_t FirstLineIndentedBy);
+
virtual void getExtraOptionNames(SmallVectorImpl<StringRef> &) {}
// addOccurrence - Wrapper around handleOccurrence that enforces Flags.
diff --git a/include/llvm/Support/Compiler.h b/include/llvm/Support/Compiler.h
index 55148a490c29..a56bc93e111b 100644
--- a/include/llvm/Support/Compiler.h
+++ b/include/llvm/Support/Compiler.h
@@ -343,7 +343,7 @@
/// int k;
/// long long l;
/// };
-/// LLVM_PACKED_END
+/// LLVM_PACKED_END
#ifdef _MSC_VER
# define LLVM_PACKED(d) __pragma(pack(push, 1)) d __pragma(pack(pop))
# define LLVM_PACKED_START __pragma(pack(push, 1))
@@ -445,6 +445,9 @@ void AnnotateIgnoreWritesEnd(const char *file, int line);
/// \brief Mark debug helper function definitions like dump() that should not be
/// stripped from debug builds.
+/// Note that you should also surround dump() functions with
+/// `#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)` so they do always
+/// get stripped in release builds.
// FIXME: Move this to a private config.h as it's not usable in public headers.
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
#define LLVM_DUMP_METHOD LLVM_ATTRIBUTE_NOINLINE LLVM_ATTRIBUTE_USED
@@ -461,7 +464,7 @@ void AnnotateIgnoreWritesEnd(const char *file, int line);
#define LLVM_PRETTY_FUNCTION __FUNCSIG__
#elif defined(__GNUC__) || defined(__clang__)
#define LLVM_PRETTY_FUNCTION __PRETTY_FUNCTION__
-#else
+#else
#define LLVM_PRETTY_FUNCTION __func__
#endif
diff --git a/include/llvm/Support/Compression.h b/include/llvm/Support/Compression.h
index 5bf7031fe9f9..2d191abe4b1a 100644
--- a/include/llvm/Support/Compression.h
+++ b/include/llvm/Support/Compression.h
@@ -18,6 +18,7 @@
namespace llvm {
template <typename T> class SmallVectorImpl;
+class Error;
class StringRef;
namespace zlib {
@@ -29,26 +30,17 @@ enum CompressionLevel {
BestSizeCompression
};
-enum Status {
- StatusOK,
- StatusUnsupported, // zlib is unavailable
- StatusOutOfMemory, // there was not enough memory
- StatusBufferTooShort, // there was not enough room in the output buffer
- StatusInvalidArg, // invalid input parameter
- StatusInvalidData // data was corrupted or incomplete
-};
-
bool isAvailable();
-Status compress(StringRef InputBuffer, SmallVectorImpl<char> &CompressedBuffer,
- CompressionLevel Level = DefaultCompression);
+Error compress(StringRef InputBuffer, SmallVectorImpl<char> &CompressedBuffer,
+ CompressionLevel Level = DefaultCompression);
-Status uncompress(StringRef InputBuffer, char *UncompressedBuffer,
- size_t &UncompressedSize);
+Error uncompress(StringRef InputBuffer, char *UncompressedBuffer,
+ size_t &UncompressedSize);
-Status uncompress(StringRef InputBuffer,
- SmallVectorImpl<char> &UncompressedBuffer,
- size_t UncompressedSize);
+Error uncompress(StringRef InputBuffer,
+ SmallVectorImpl<char> &UncompressedBuffer,
+ size_t UncompressedSize);
uint32_t crc32(StringRef Buffer);
diff --git a/include/llvm/Support/Debug.h b/include/llvm/Support/Debug.h
index 3465c403361f..48e9e1bc167d 100644
--- a/include/llvm/Support/Debug.h
+++ b/include/llvm/Support/Debug.h
@@ -33,11 +33,6 @@ namespace llvm {
class raw_ostream;
#ifndef NDEBUG
-/// DebugFlag - This boolean is set to true if the '-debug' command line option
-/// is specified. This should probably not be referenced directly, instead, use
-/// the DEBUG macro below.
-///
-extern bool DebugFlag;
/// isCurrentDebugType - Return true if the specified string is the debug type
/// specified on the command line, or if none was specified on the command line
@@ -77,6 +72,29 @@ void setCurrentDebugTypes(const char **Types, unsigned Count);
#define DEBUG_WITH_TYPE(TYPE, X) do { } while (false)
#endif
+/// This boolean is set to true if the '-debug' command line option
+/// is specified. This should probably not be referenced directly, instead, use
+/// the DEBUG macro below.
+///
+extern bool DebugFlag;
+
+/// \name Verification flags.
+///
+/// These flags turns on/off that are expensive and are turned off by default,
+/// unless macro EXPENSIVE_CHECKS is defined. The flags allow selectively
+/// turning the checks on without need to recompile.
+/// \{
+
+/// Enables verification of dominator trees.
+///
+extern bool VerifyDomInfo;
+
+/// Enables verification of loop info.
+///
+extern bool VerifyLoopInfo;
+
+///\}
+
/// EnableDebugBuffering - This defaults to false. If true, the debug
/// stream will install signal handlers to dump any buffered debug
/// output. It allows clients to selectively allow the debug stream
diff --git a/include/llvm/Support/DebugCounter.h b/include/llvm/Support/DebugCounter.h
new file mode 100644
index 000000000000..9687cb7b9d95
--- /dev/null
+++ b/include/llvm/Support/DebugCounter.h
@@ -0,0 +1,165 @@
+//===- llvm/Support/DebugCounter.h - Debug counter support ------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+/// \brief This file provides an implementation of debug counters. Debug
+/// counters are a tool that let you narrow down a miscompilation to a specific
+/// thing happening.
+///
+/// To give a use case: Imagine you have a file, very large, and you
+/// are trying to understand the minimal transformation that breaks it. Bugpoint
+/// and bisection is often helpful here in narrowing it down to a specific pass,
+/// but it's still a very large file, and a very complicated pass to try to
+/// debug. That is where debug counting steps in. You can instrument the pass
+/// with a debug counter before it does a certain thing, and depending on the
+/// counts, it will either execute that thing or not. The debug counter itself
+/// consists of a skip and a count. Skip is the number of times shouldExecute
+/// needs to be called before it returns true. Count is the number of times to
+/// return true once Skip is 0. So a skip=47, count=2 ,would skip the first 47
+/// executions by returning false from shouldExecute, then execute twice, and
+/// then return false again.
+/// Note that a counter set to a negative number will always execute.
+/// For a concrete example, during predicateinfo creation, the renaming pass
+/// replaces each use with a renamed use.
+////
+/// If I use DEBUG_COUNTER to create a counter called "predicateinfo", and
+/// variable name RenameCounter, and then instrument this renaming with a debug
+/// counter, like so:
+///
+/// if (!DebugCounter::shouldExecute(RenameCounter)
+/// <continue or return or whatever not executing looks like>
+///
+/// Now I can, from the command line, make it rename or not rename certain uses
+/// by setting the skip and count.
+/// So for example
+/// bin/opt -debug-counter=predicateinfo-skip=47,predicateinfo-count=1
+/// will skip renaming the first 47 uses, then rename one, then skip the rest.
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_DEBUGCOUNTER_H
+#define LLVM_SUPPORT_DEBUGCOUNTER_H
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/UniqueVector.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
+#include <string>
+
+namespace llvm {
+
+class DebugCounter {
+public:
+ /// \brief Returns a reference to the singleton instance.
+ static DebugCounter &instance();
+
+ // Used by the command line option parser to push a new value it parsed.
+ void push_back(const std::string &);
+
+ // Register a counter with the specified name.
+ //
+ // FIXME: Currently, counter registration is required to happen before command
+ // line option parsing. The main reason to register counters is to produce a
+ // nice list of them on the command line, but i'm not sure this is worth it.
+ static unsigned registerCounter(StringRef Name, StringRef Desc) {
+ return instance().addCounter(Name, Desc);
+ }
+ inline static bool shouldExecute(unsigned CounterName) {
+// Compile to nothing when debugging is off
+#ifdef NDEBUG
+ return true;
+#else
+ auto &Us = instance();
+ auto Result = Us.Counters.find(CounterName);
+ if (Result != Us.Counters.end()) {
+ auto &CounterPair = Result->second;
+ // We only execute while the skip (first) is zero and the count (second)
+ // is non-zero.
+ // Negative counters always execute.
+ if (CounterPair.first < 0)
+ return true;
+ if (CounterPair.first != 0) {
+ --CounterPair.first;
+ return false;
+ }
+ if (CounterPair.second < 0)
+ return true;
+ if (CounterPair.second != 0) {
+ --CounterPair.second;
+ return true;
+ }
+ return false;
+ }
+ // Didn't find the counter, should we warn?
+ return true;
+#endif // NDEBUG
+ }
+
+ // Return true if a given counter had values set (either programatically or on
+ // the command line). This will return true even if those values are
+ // currently in a state where the counter will always execute.
+ static bool isCounterSet(unsigned ID) {
+ return instance().Counters.count(ID);
+ }
+
+ // Return the skip and count for a counter. This only works for set counters.
+ static std::pair<int, int> getCounterValue(unsigned ID) {
+ auto &Us = instance();
+ auto Result = Us.Counters.find(ID);
+ assert(Result != Us.Counters.end() && "Asking about a non-set counter");
+ return Result->second;
+ }
+
+ // Set a registered counter to a given value.
+ static void setCounterValue(unsigned ID, const std::pair<int, int> &Val) {
+ auto &Us = instance();
+ Us.Counters[ID] = Val;
+ }
+
+ // Dump or print the current counter set.
+ LLVM_DUMP_METHOD void dump() { print(dbgs()); }
+
+ void print(raw_ostream &OS);
+
+ // Get the counter ID for a given named counter, or return 0 if none is found.
+ unsigned getCounterId(const std::string &Name) const {
+ return RegisteredCounters.idFor(Name);
+ }
+
+ // Return the number of registered counters.
+ unsigned int getNumCounters() const { return RegisteredCounters.size(); }
+
+ // Return the name and description of the counter with the given ID.
+ std::pair<std::string, std::string> getCounterInfo(unsigned ID) const {
+ return std::make_pair(RegisteredCounters[ID], CounterDesc.lookup(ID));
+ }
+
+ // Iterate through the registered counters
+ typedef UniqueVector<std::string> CounterVector;
+ CounterVector::const_iterator begin() const {
+ return RegisteredCounters.begin();
+ }
+ CounterVector::const_iterator end() const { return RegisteredCounters.end(); }
+
+private:
+ unsigned addCounter(const std::string &Name, const std::string &Desc) {
+ unsigned Result = RegisteredCounters.insert(Name);
+ CounterDesc[Result] = Desc;
+ return Result;
+ }
+ DenseMap<unsigned, std::pair<long, long>> Counters;
+ DenseMap<unsigned, std::string> CounterDesc;
+ CounterVector RegisteredCounters;
+};
+
+#define DEBUG_COUNTER(VARNAME, COUNTERNAME, DESC) \
+ static const unsigned VARNAME = \
+ DebugCounter::registerCounter(COUNTERNAME, DESC);
+
+} // namespace llvm
+#endif
diff --git a/include/llvm/Support/Dwarf.def b/include/llvm/Support/Dwarf.def
index 841fc7d4ae22..fdbd8ea70116 100644
--- a/include/llvm/Support/Dwarf.def
+++ b/include/llvm/Support/Dwarf.def
@@ -19,7 +19,8 @@
defined HANDLE_DW_CC || defined HANDLE_DW_LNS || \
defined HANDLE_DW_LNE || defined HANDLE_DW_LNCT || \
defined HANDLE_DW_MACRO || defined HANDLE_DW_RLE || \
- defined HANDLE_DW_CFA || defined HANDLE_DW_APPLE_PROPERTY)
+ defined HANDLE_DW_CFA || defined HANDLE_DW_APPLE_PROPERTY || \
+ defined HANDLE_DW_UT)
#error "Missing macro definition of HANDLE_DW*"
#endif
@@ -87,6 +88,10 @@
#define HANDLE_DW_APPLE_PROPERTY(ID, NAME)
#endif
+#ifndef HANDLE_DW_UT
+#define HANDLE_DW_UT(ID, NAME)
+#endif
+
HANDLE_DW_TAG(0x0000, null)
HANDLE_DW_TAG(0x0001, array_type)
HANDLE_DW_TAG(0x0002, class_type)
@@ -135,6 +140,7 @@ HANDLE_DW_TAG(0x0032, try_block)
HANDLE_DW_TAG(0x0033, variant_part)
HANDLE_DW_TAG(0x0034, variable)
HANDLE_DW_TAG(0x0035, volatile_type)
+// New in DWARF v3:
HANDLE_DW_TAG(0x0036, dwarf_procedure)
HANDLE_DW_TAG(0x0037, restrict_type)
HANDLE_DW_TAG(0x0038, interface_type)
@@ -145,11 +151,11 @@ HANDLE_DW_TAG(0x003c, partial_unit)
HANDLE_DW_TAG(0x003d, imported_unit)
HANDLE_DW_TAG(0x003f, condition)
HANDLE_DW_TAG(0x0040, shared_type)
+// New in DWARF v4:
HANDLE_DW_TAG(0x0041, type_unit)
HANDLE_DW_TAG(0x0042, rvalue_reference_type)
HANDLE_DW_TAG(0x0043, template_alias)
-
-// New in DWARF v5.
+// New in DWARF v5:
HANDLE_DW_TAG(0x0044, coarray_type)
HANDLE_DW_TAG(0x0045, generic_subrange)
HANDLE_DW_TAG(0x0046, dynamic_type)
@@ -158,8 +164,7 @@ HANDLE_DW_TAG(0x0048, call_site)
HANDLE_DW_TAG(0x0049, call_site_parameter)
HANDLE_DW_TAG(0x004a, skeleton_unit)
HANDLE_DW_TAG(0x004b, immutable_type)
-
-// User-defined tags.
+// Vendor extensions:
HANDLE_DW_TAG(0x4081, MIPS_loop)
HANDLE_DW_TAG(0x4101, format_label)
HANDLE_DW_TAG(0x4102, function_template)
@@ -234,6 +239,7 @@ HANDLE_DW_AT(0x4a, use_location)
HANDLE_DW_AT(0x4b, variable_parameter)
HANDLE_DW_AT(0x4c, virtuality)
HANDLE_DW_AT(0x4d, vtable_elem_location)
+// New in DWARF v3:
HANDLE_DW_AT(0x4e, allocated)
HANDLE_DW_AT(0x4f, associated)
HANDLE_DW_AT(0x50, data_location)
@@ -261,14 +267,14 @@ HANDLE_DW_AT(0x65, endianity)
HANDLE_DW_AT(0x66, elemental)
HANDLE_DW_AT(0x67, pure)
HANDLE_DW_AT(0x68, recursive)
+// New in DWARF v4:
HANDLE_DW_AT(0x69, signature)
HANDLE_DW_AT(0x6a, main_subprogram)
HANDLE_DW_AT(0x6b, data_bit_offset)
HANDLE_DW_AT(0x6c, const_expr)
HANDLE_DW_AT(0x6d, enum_class)
HANDLE_DW_AT(0x6e, linkage_name)
-
-// New in DWARF 5:
+// New in DWARF v5:
HANDLE_DW_AT(0x6f, string_length_bit_size)
HANDLE_DW_AT(0x70, string_length_byte_size)
HANDLE_DW_AT(0x71, rank)
@@ -299,7 +305,7 @@ HANDLE_DW_AT(0x89, export_symbols)
HANDLE_DW_AT(0x8a, deleted)
HANDLE_DW_AT(0x8b, defaulted)
HANDLE_DW_AT(0x8c, loclists_base)
-
+// Vendor extensions:
HANDLE_DW_AT(0x2002, MIPS_loop_begin)
HANDLE_DW_AT(0x2003, MIPS_tail_loop_begin)
HANDLE_DW_AT(0x2004, MIPS_epilog_begin)
@@ -315,11 +321,9 @@ HANDLE_DW_AT(0x200d, MIPS_stride_elem)
HANDLE_DW_AT(0x200e, MIPS_ptr_dopetype)
HANDLE_DW_AT(0x200f, MIPS_allocatable_dopetype)
HANDLE_DW_AT(0x2010, MIPS_assumed_shape_dopetype)
-
// This one appears to have only been implemented by Open64 for
// fortran and may conflict with other extensions.
HANDLE_DW_AT(0x2011, MIPS_assumed_size)
-
// GNU extensions
HANDLE_DW_AT(0x2101, sf_names)
HANDLE_DW_AT(0x2102, src_info)
@@ -329,10 +333,8 @@ HANDLE_DW_AT(0x2105, body_begin)
HANDLE_DW_AT(0x2106, body_end)
HANDLE_DW_AT(0x2107, GNU_vector)
HANDLE_DW_AT(0x2110, GNU_template_name)
-
HANDLE_DW_AT(0x210f, GNU_odr_signature)
HANDLE_DW_AT(0x2119, GNU_macros)
-
// Extensions for Fission proposal.
HANDLE_DW_AT(0x2130, GNU_dwo_name)
HANDLE_DW_AT(0x2131, GNU_dwo_id)
@@ -341,7 +343,6 @@ HANDLE_DW_AT(0x2133, GNU_addr_base)
HANDLE_DW_AT(0x2134, GNU_pubnames)
HANDLE_DW_AT(0x2135, GNU_pubtypes)
HANDLE_DW_AT(0x2136, GNU_discriminator)
-
// Borland extensions.
HANDLE_DW_AT(0x3b11, BORLAND_property_read)
HANDLE_DW_AT(0x3b12, BORLAND_property_write)
@@ -360,12 +361,10 @@ HANDLE_DW_AT(0x3b28, BORLAND_Delphi_ABI)
HANDLE_DW_AT(0x3b29, BORLAND_Delphi_return)
HANDLE_DW_AT(0x3b30, BORLAND_Delphi_frameptr)
HANDLE_DW_AT(0x3b31, BORLAND_closure)
-
// LLVM project extensions.
HANDLE_DW_AT(0x3e00, LLVM_include_path)
HANDLE_DW_AT(0x3e01, LLVM_config_macros)
HANDLE_DW_AT(0x3e02, LLVM_isysroot)
-
// Apple extensions.
HANDLE_DW_AT(0x3fe1, APPLE_optimized)
HANDLE_DW_AT(0x3fe2, APPLE_flags)
@@ -403,26 +402,34 @@ HANDLE_DW_FORM(0x13, ref4)
HANDLE_DW_FORM(0x14, ref8)
HANDLE_DW_FORM(0x15, ref_udata)
HANDLE_DW_FORM(0x16, indirect)
+// New in DWARF v4:
HANDLE_DW_FORM(0x17, sec_offset)
HANDLE_DW_FORM(0x18, exprloc)
HANDLE_DW_FORM(0x19, flag_present)
-
-// New in DWARF v5.
+// This was defined out of sequence.
+HANDLE_DW_FORM(0x20, ref_sig8)
+// New in DWARF v5:
HANDLE_DW_FORM(0x1a, strx)
HANDLE_DW_FORM(0x1b, addrx)
-HANDLE_DW_FORM(0x1c, ref_sup)
+HANDLE_DW_FORM(0x1c, ref_sup4)
HANDLE_DW_FORM(0x1d, strp_sup)
HANDLE_DW_FORM(0x1e, data16)
HANDLE_DW_FORM(0x1f, line_strp)
-HANDLE_DW_FORM(0x20, ref_sig8)
HANDLE_DW_FORM(0x21, implicit_const)
HANDLE_DW_FORM(0x22, loclistx)
HANDLE_DW_FORM(0x23, rnglistx)
-
+HANDLE_DW_FORM(0x24, ref_sup8)
+HANDLE_DW_FORM(0x25, strx1)
+HANDLE_DW_FORM(0x26, strx2)
+HANDLE_DW_FORM(0x27, strx3)
+HANDLE_DW_FORM(0x28, strx4)
+HANDLE_DW_FORM(0x29, addrx1)
+HANDLE_DW_FORM(0x2a, addrx2)
+HANDLE_DW_FORM(0x2b, addrx3)
+HANDLE_DW_FORM(0x2c, addrx4)
// Extensions for Fission proposal
HANDLE_DW_FORM(0x1f01, GNU_addr_index)
HANDLE_DW_FORM(0x1f02, GNU_str_index)
-
// Alternate debug sections proposal (output of "dwz" tool).
HANDLE_DW_FORM(0x1f20, GNU_ref_alt)
HANDLE_DW_FORM(0x1f21, GNU_strp_alt)
@@ -462,7 +469,6 @@ 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)
@@ -470,6 +476,7 @@ HANDLE_DW_OP(0x2b, gt)
HANDLE_DW_OP(0x2c, le)
HANDLE_DW_OP(0x2d, lt)
HANDLE_DW_OP(0x2e, ne)
+HANDLE_DW_OP(0x2f, skip)
HANDLE_DW_OP(0x30, lit0)
HANDLE_DW_OP(0x31, lit1)
HANDLE_DW_OP(0x32, lit2)
@@ -573,6 +580,7 @@ HANDLE_DW_OP(0x93, piece)
HANDLE_DW_OP(0x94, deref_size)
HANDLE_DW_OP(0x95, xderef_size)
HANDLE_DW_OP(0x96, nop)
+// New in DWARF v3:
HANDLE_DW_OP(0x97, push_object_address)
HANDLE_DW_OP(0x98, call2)
HANDLE_DW_OP(0x99, call4)
@@ -580,8 +588,10 @@ 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)
+// New in DWARF v4:
HANDLE_DW_OP(0x9e, implicit_value)
HANDLE_DW_OP(0x9f, stack_value)
+// New in DWARF v5:
HANDLE_DW_OP(0xa0, implicit_pointer)
HANDLE_DW_OP(0xa1, addrx)
HANDLE_DW_OP(0xa2, constx)
@@ -592,11 +602,9 @@ HANDLE_DW_OP(0xa6, deref_type)
HANDLE_DW_OP(0xa7, xderef_type)
HANDLE_DW_OP(0xa8, convert)
HANDLE_DW_OP(0xa9, reinterpret)
-
-// Vendor extensions.
+// Vendor extensions:
// 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)
@@ -612,6 +620,7 @@ HANDLE_DW_LANG(0x0007, Fortran77)
HANDLE_DW_LANG(0x0008, Fortran90)
HANDLE_DW_LANG(0x0009, Pascal83)
HANDLE_DW_LANG(0x000a, Modula2)
+// New in DWARF v3:
HANDLE_DW_LANG(0x000b, Java)
HANDLE_DW_LANG(0x000c, C99)
HANDLE_DW_LANG(0x000d, Ada95)
@@ -621,9 +630,9 @@ 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:
+// New in DWARF v4:
HANDLE_DW_LANG(0x0014, Python)
+// New in DWARF v5:
HANDLE_DW_LANG(0x0015, OpenCL)
HANDLE_DW_LANG(0x0016, Go)
HANDLE_DW_LANG(0x0017, Modula3)
@@ -640,8 +649,8 @@ HANDLE_DW_LANG(0x0021, C_plus_plus_14)
HANDLE_DW_LANG(0x0022, Fortran03)
HANDLE_DW_LANG(0x0023, Fortran08)
HANDLE_DW_LANG(0x0024, RenderScript)
-
-// Vendor extensions.
+HANDLE_DW_LANG(0x0025, BLISS)
+// Vendor extensions:
HANDLE_DW_LANG(0x8001, Mips_Assembler)
HANDLE_DW_LANG(0x8e57, GOOGLE_RenderScript)
HANDLE_DW_LANG(0xb000, BORLAND_Delphi)
@@ -655,6 +664,7 @@ HANDLE_DW_ATE(0x05, signed)
HANDLE_DW_ATE(0x06, signed_char)
HANDLE_DW_ATE(0x07, unsigned)
HANDLE_DW_ATE(0x08, unsigned_char)
+// New in DWARF v3:
HANDLE_DW_ATE(0x09, imaginary_float)
HANDLE_DW_ATE(0x0a, packed_decimal)
HANDLE_DW_ATE(0x0b, numeric_string)
@@ -662,7 +672,9 @@ HANDLE_DW_ATE(0x0c, edited)
HANDLE_DW_ATE(0x0d, signed_fixed)
HANDLE_DW_ATE(0x0e, unsigned_fixed)
HANDLE_DW_ATE(0x0f, decimal_float)
+// New in DWARF v4:
HANDLE_DW_ATE(0x10, UTF)
+// New in DWARF v5:
HANDLE_DW_ATE(0x11, UCS)
HANDLE_DW_ATE(0x12, ASCII)
@@ -680,8 +692,10 @@ HANDLE_DW_DEFAULTED(0x02, out_of_class)
HANDLE_DW_CC(0x01, normal)
HANDLE_DW_CC(0x02, program)
HANDLE_DW_CC(0x03, nocall)
+// New in DWARF v5:
HANDLE_DW_CC(0x04, pass_by_reference)
HANDLE_DW_CC(0x05, pass_by_value)
+// Vendor extensions:
HANDLE_DW_CC(0x41, GNU_borland_fastcall_i386)
HANDLE_DW_CC(0xb0, BORLAND_safecall)
HANDLE_DW_CC(0xb1, BORLAND_stdcall)
@@ -696,6 +710,7 @@ HANDLE_DW_CC(0xc0, LLVM_vectorcall)
HANDLE_DW_LNE(0x01, end_sequence)
HANDLE_DW_LNE(0x02, set_address)
HANDLE_DW_LNE(0x03, define_file)
+// New in DWARF v4:
HANDLE_DW_LNE(0x04, set_discriminator)
// Line Number Standard Opcode Encodings.
@@ -709,6 +724,7 @@ HANDLE_DW_LNS(0x06, negate_stmt)
HANDLE_DW_LNS(0x07, set_basic_block)
HANDLE_DW_LNS(0x08, const_add_pc)
HANDLE_DW_LNS(0x09, fixed_advance_pc)
+// New in DWARF v3:
HANDLE_DW_LNS(0x0a, set_prologue_end)
HANDLE_DW_LNS(0x0b, set_epilogue_begin)
HANDLE_DW_LNS(0x0c, set_isa)
@@ -720,6 +736,7 @@ HANDLE_DW_LNCT(0x03, timestamp)
HANDLE_DW_LNCT(0x04, size)
HANDLE_DW_LNCT(0x05, MD5)
+// DWARF v5 Macro information.
HANDLE_DW_MACRO(0x01, define)
HANDLE_DW_MACRO(0x02, undef)
HANDLE_DW_MACRO(0x03, start_file)
@@ -733,7 +750,7 @@ HANDLE_DW_MACRO(0x0a, import_sup)
HANDLE_DW_MACRO(0x0b, define_strx)
HANDLE_DW_MACRO(0x0c, undef_strx)
-// Range list entry encoding values.
+// DWARF v5 Range List Entry encoding values.
HANDLE_DW_RLE(0x00, end_of_list)
HANDLE_DW_RLE(0x01, base_addressx)
HANDLE_DW_RLE(0x02, startx_endx)
@@ -762,6 +779,7 @@ HANDLE_DW_CFA(0x0b, restore_state)
HANDLE_DW_CFA(0x0c, def_cfa)
HANDLE_DW_CFA(0x0d, def_cfa_register)
HANDLE_DW_CFA(0x0e, def_cfa_offset)
+// New in DWARF v3:
HANDLE_DW_CFA(0x0f, def_cfa_expression)
HANDLE_DW_CFA(0x10, expression)
HANDLE_DW_CFA(0x11, offset_extended_sf)
@@ -770,6 +788,7 @@ HANDLE_DW_CFA(0x13, def_cfa_offset_sf)
HANDLE_DW_CFA(0x14, val_offset)
HANDLE_DW_CFA(0x15, val_offset_sf)
HANDLE_DW_CFA(0x16, val_expression)
+// Vendor extensions:
HANDLE_DW_CFA(0x1d, MIPS_advance_loc8)
HANDLE_DW_CFA(0x2d, GNU_window_save)
HANDLE_DW_CFA(0x2e, GNU_args_size)
@@ -792,6 +811,13 @@ HANDLE_DW_APPLE_PROPERTY(0x1000, nullability)
HANDLE_DW_APPLE_PROPERTY(0x2000, null_resettable)
HANDLE_DW_APPLE_PROPERTY(0x4000, class)
+// DWARF v5 Unit Types.
+HANDLE_DW_UT(0x01, compile)
+HANDLE_DW_UT(0x02, type)
+HANDLE_DW_UT(0x03, partial)
+HANDLE_DW_UT(0x04, skeleton)
+HANDLE_DW_UT(0x05, split_compile)
+HANDLE_DW_UT(0x06, split_type)
#undef HANDLE_DW_TAG
#undef HANDLE_DW_AT
@@ -809,3 +835,4 @@ HANDLE_DW_APPLE_PROPERTY(0x4000, class)
#undef HANDLE_DW_RLE
#undef HANDLE_DW_CFA
#undef HANDLE_DW_APPLE_PROPERTY
+#undef HANDLE_DW_UT
diff --git a/include/llvm/Support/Dwarf.h b/include/llvm/Support/Dwarf.h
index 8336b9df9df0..84056682924e 100644
--- a/include/llvm/Support/Dwarf.h
+++ b/include/llvm/Support/Dwarf.h
@@ -29,7 +29,7 @@ class StringRef;
namespace dwarf {
//===----------------------------------------------------------------------===//
-// Dwarf constants as gleaned from the DWARF Debugging Information Format V.4
+// DWARF constants as gleaned from the DWARF Debugging Information Format V.5
// reference manual http://www.dwarfstd.org/.
//
@@ -305,7 +305,15 @@ enum ApplePropertyAttributes {
#include "llvm/Support/Dwarf.def"
};
-// Constants for the DWARF5 Accelerator Table Proposal
+/// Constants for unit types in DWARF v5.
+enum UnitType : unsigned char {
+#define HANDLE_DW_UT(ID, NAME) DW_UT_##NAME = ID,
+#include "llvm/Support/Dwarf.def"
+ DW_UT_lo_user = 0x80,
+ DW_UT_hi_user = 0xff
+};
+
+// Constants for the DWARF v5 Accelerator Table Proposal
enum AcceleratorTable {
// Data layout descriptors.
DW_ATOM_null = 0u, // Marker as the end of a list of atoms.
@@ -373,6 +381,7 @@ StringRef LNExtendedString(unsigned Encoding);
StringRef MacinfoString(unsigned Encoding);
StringRef CallFrameString(unsigned Encoding);
StringRef ApplePropertyString(unsigned);
+StringRef UnitTypeString(unsigned);
StringRef AtomTypeString(unsigned Atom);
StringRef GDBIndexEntryKindString(GDBIndexEntryKind Kind);
StringRef GDBIndexEntryLinkageString(GDBIndexEntryLinkage Linkage);
diff --git a/include/llvm/Support/DynamicLibrary.h b/include/llvm/Support/DynamicLibrary.h
index a7d22212dbdb..aa9bb8938ad3 100644
--- a/include/llvm/Support/DynamicLibrary.h
+++ b/include/llvm/Support/DynamicLibrary.h
@@ -68,6 +68,15 @@ namespace sys {
static DynamicLibrary getPermanentLibrary(const char *filename,
std::string *errMsg = nullptr);
+ /// Registers an externally loaded library. The library will be unloaded
+ /// when the program terminates.
+ ///
+ /// It is safe to call this function multiple times for the same library.
+ ///
+ /// \returns An empty \p DynamicLibrary if the library was already loaded.
+ static DynamicLibrary addPermanentLibrary(void *handle,
+ std::string *errMsg = nullptr);
+
/// This function permanently loads the dynamic library at the given path.
/// Use this instead of getPermanentLibrary() when you won't need to get
/// symbols from the library itself.
diff --git a/include/llvm/Support/ELF.h b/include/llvm/Support/ELF.h
index 3ea4da81ad94..33f20a809d6c 100644
--- a/include/llvm/Support/ELF.h
+++ b/include/llvm/Support/ELF.h
@@ -556,6 +556,7 @@ enum {
EF_HEXAGON_MACH_V5 = 0x00000004, // Hexagon V5
EF_HEXAGON_MACH_V55 = 0x00000005, // Hexagon V55
EF_HEXAGON_MACH_V60 = 0x00000060, // Hexagon V60
+ EF_HEXAGON_MACH_V62 = 0x00000062, // Hexagon V62
// Highest ISA version flags
EF_HEXAGON_ISA_MACH = 0x00000000, // Same as specified in bits[11:0]
@@ -566,6 +567,7 @@ enum {
EF_HEXAGON_ISA_V5 = 0x00000040, // Hexagon V5 ISA
EF_HEXAGON_ISA_V55 = 0x00000050, // Hexagon V55 ISA
EF_HEXAGON_ISA_V60 = 0x00000060, // Hexagon V60 ISA
+ EF_HEXAGON_ISA_V62 = 0x00000062, // Hexagon V62 ISA
};
// Hexagon-specific section indexes for common small data
@@ -703,6 +705,7 @@ enum : unsigned {
SHT_MIPS_REGINFO = 0x70000006, // Register usage information
SHT_MIPS_OPTIONS = 0x7000000d, // General options
+ SHT_MIPS_DWARF = 0x7000001e, // DWARF debugging section.
SHT_MIPS_ABIFLAGS = 0x7000002a, // ABI information.
SHT_HIPROC = 0x7fffffff, // Highest processor arch-specific type.
@@ -751,21 +754,21 @@ enum : unsigned {
// Start of target-specific flags.
- /// XCORE_SHF_CP_SECTION - All sections with the "c" flag are grouped
- /// together by the linker to form the constant pool and the cp register is
- /// set to the start of the constant pool by the boot code.
- XCORE_SHF_CP_SECTION = 0x800U,
-
- /// XCORE_SHF_DP_SECTION - All sections with the "d" flag are grouped
- /// together by the linker to form the data section and the dp register is
- /// set to the start of the section by the boot code.
- XCORE_SHF_DP_SECTION = 0x1000U,
-
SHF_MASKOS = 0x0ff00000,
// Bits indicating processor-specific flags.
SHF_MASKPROC = 0xf0000000,
+ /// All sections with the "d" flag are grouped together by the linker to form
+ /// the data section and the dp register is set to the start of the section by
+ /// the boot code.
+ XCORE_SHF_DP_SECTION = 0x10000000,
+
+ /// All sections with the "c" flag are grouped together by the linker to form
+ /// the constant pool and the cp register is set to the start of the constant
+ /// pool by the boot code.
+ XCORE_SHF_CP_SECTION = 0x20000000,
+
// If an object file section does not have this flag set, then it may not hold
// more than 2GB and can be freely referred to in objects using smaller code
// models. Otherwise, only objects using larger code models can refer to them.
@@ -1312,6 +1315,19 @@ enum { VER_NEED_NONE = 0, VER_NEED_CURRENT = 1 };
// SHT_NOTE section types
enum {
+ NT_FREEBSD_THRMISC = 7,
+ NT_FREEBSD_PROCSTAT_PROC = 8,
+ NT_FREEBSD_PROCSTAT_FILES = 9,
+ NT_FREEBSD_PROCSTAT_VMMAP = 10,
+ NT_FREEBSD_PROCSTAT_GROUPS = 11,
+ NT_FREEBSD_PROCSTAT_UMASK = 12,
+ NT_FREEBSD_PROCSTAT_RLIMIT = 13,
+ NT_FREEBSD_PROCSTAT_OSREL = 14,
+ NT_FREEBSD_PROCSTAT_PSSTRINGS = 15,
+ NT_FREEBSD_PROCSTAT_AUXV = 16,
+};
+
+enum {
NT_GNU_ABI_TAG = 1,
NT_GNU_HWCAP = 2,
NT_GNU_BUILD_ID = 3,
diff --git a/include/llvm/Support/Endian.h b/include/llvm/Support/Endian.h
index cbe3d67b1f9e..06e089ffa166 100644
--- a/include/llvm/Support/Endian.h
+++ b/include/llvm/Support/Endian.h
@@ -17,6 +17,8 @@
#include "llvm/Support/Host.h"
#include "llvm/Support/SwapByteOrder.h"
+#include <stdint.h>
+
namespace llvm {
namespace support {
enum endianness {big, little, native};
@@ -33,48 +35,71 @@ namespace detail {
} // end namespace detail
namespace endian {
+constexpr endianness system_endianness() {
+ return sys::IsBigEndianHost ? big : little;
+}
+
+template <typename value_type>
+inline value_type byte_swap(value_type value, endianness endian) {
+ if ((endian != native) && (endian != system_endianness()))
+ sys::swapByteOrder(value);
+ return value;
+}
+
/// Swap the bytes of value to match the given endianness.
template<typename value_type, endianness endian>
inline value_type byte_swap(value_type value) {
- if (endian != native && sys::IsBigEndianHost != (endian == big))
- sys::swapByteOrder(value);
- return value;
+ return byte_swap(value, endian);
}
/// Read a value of a particular endianness from memory.
-template<typename value_type,
- endianness endian,
- std::size_t alignment>
-inline value_type read(const void *memory) {
+template <typename value_type, std::size_t alignment>
+inline value_type read(const void *memory, endianness endian) {
value_type ret;
memcpy(&ret,
- LLVM_ASSUME_ALIGNED(memory,
- (detail::PickAlignment<value_type, alignment>::value)),
+ LLVM_ASSUME_ALIGNED(
+ memory, (detail::PickAlignment<value_type, alignment>::value)),
sizeof(value_type));
- return byte_swap<value_type, endian>(ret);
+ return byte_swap<value_type>(ret, endian);
+}
+
+template<typename value_type,
+ endianness endian,
+ std::size_t alignment>
+inline value_type read(const void *memory) {
+ return read<value_type, alignment>(memory, endian);
}
/// Read a value of a particular endianness from a buffer, and increment the
/// buffer past that value.
+template <typename value_type, std::size_t alignment, typename CharT>
+inline value_type readNext(const CharT *&memory, endianness endian) {
+ value_type ret = read<value_type, alignment>(memory, endian);
+ memory += sizeof(value_type);
+ return ret;
+}
+
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;
+ return readNext<value_type, alignment, CharT>(memory, endian);
}
/// Write a value to memory with a particular endianness.
+template <typename value_type, std::size_t alignment>
+inline void write(void *memory, value_type value, endianness endian) {
+ value = byte_swap<value_type>(value, endian);
+ memcpy(LLVM_ASSUME_ALIGNED(
+ memory, (detail::PickAlignment<value_type, alignment>::value)),
+ &value, sizeof(value_type));
+}
+
template<typename value_type,
endianness endian,
std::size_t alignment>
inline void write(void *memory, value_type value) {
- value = byte_swap<value_type, endian>(value);
- memcpy(LLVM_ASSUME_ALIGNED(memory,
- (detail::PickAlignment<value_type, alignment>::value)),
- &value,
- sizeof(value_type));
+ write<value_type, alignment>(memory, value, endian);
}
template <typename value_type>
@@ -300,10 +325,24 @@ typedef detail::packed_endian_specific_integral
<int64_t, native, unaligned> unaligned_int64_t;
namespace endian {
+template <typename T> inline T read(const void *P, endianness E) {
+ return read<T, unaligned>(P, E);
+}
+
template <typename T, endianness E> inline T read(const void *P) {
return *(const detail::packed_endian_specific_integral<T, E, unaligned> *)P;
}
+inline uint16_t read16(const void *P, endianness E) {
+ return read<uint16_t>(P, E);
+}
+inline uint32_t read32(const void *P, endianness E) {
+ return read<uint32_t>(P, E);
+}
+inline uint64_t read64(const void *P, endianness E) {
+ return read<uint64_t>(P, E);
+}
+
template <endianness E> inline uint16_t read16(const void *P) {
return read<uint16_t, E>(P);
}
@@ -321,10 +360,24 @@ inline uint16_t read16be(const void *P) { return read16<big>(P); }
inline uint32_t read32be(const void *P) { return read32<big>(P); }
inline uint64_t read64be(const void *P) { return read64<big>(P); }
+template <typename T> inline void write(void *P, T V, endianness E) {
+ write<T, unaligned>(P, V, E);
+}
+
template <typename T, endianness E> inline void write(void *P, T V) {
*(detail::packed_endian_specific_integral<T, E, unaligned> *)P = V;
}
+inline void write16(void *P, uint16_t V, endianness E) {
+ write<uint16_t>(P, V, E);
+}
+inline void write32(void *P, uint32_t V, endianness E) {
+ write<uint32_t>(P, V, E);
+}
+inline void write64(void *P, uint64_t V, endianness E) {
+ write<uint64_t>(P, V, E);
+}
+
template <endianness E> inline void write16(void *P, uint16_t V) {
write<uint16_t, E>(P, V);
}
diff --git a/include/llvm/Support/Error.h b/include/llvm/Support/Error.h
index f13c9484b5fd..a3482f5a58b5 100644
--- a/include/llvm/Support/Error.h
+++ b/include/llvm/Support/Error.h
@@ -64,6 +64,12 @@ public:
/// using std::error_code. It will be removed in the future.
virtual std::error_code convertToErrorCode() const = 0;
+ // Returns the class ID for this type.
+ static const void *classID() { return &ID; }
+
+ // Returns the class ID for the dynamic type of this ErrorInfoBase instance.
+ virtual const void *dynamicClassID() const = 0;
+
// Check whether this instance is a subclass of the class identified by
// ClassID.
virtual bool isA(const void *const ClassID) const {
@@ -75,9 +81,6 @@ public:
return isA(ErrorInfoT::classID());
}
- // Returns the class ID for this type.
- static const void *classID() { return &ID; }
-
private:
virtual void anchor();
@@ -233,6 +236,14 @@ public:
return getPtr() && getPtr()->isA(ErrT::classID());
}
+ /// Returns the dynamic class id of this error, or null if this is a success
+ /// value.
+ const void* dynamicClassID() const {
+ if (!getPtr())
+ return nullptr;
+ return getPtr()->dynamicClassID();
+ }
+
private:
void assertIsChecked() {
#if LLVM_ENABLE_ABI_BREAKING_CHECKS
@@ -316,11 +327,14 @@ template <typename ErrT, typename... ArgTs> Error make_error(ArgTs &&... Args) {
template <typename ThisErrT, typename ParentErrT = ErrorInfoBase>
class ErrorInfo : public ParentErrT {
public:
+
+ static const void *classID() { return &ThisErrT::ID; }
+
+ const void *dynamicClassID() const override { return &ThisErrT::ID; }
+
bool isA(const void *const ClassID) const override {
return ClassID == classID() || ParentErrT::isA(ClassID);
}
-
- static const void *classID() { return &ThisErrT::ID; }
};
/// Special ErrorInfo subclass representing a list of ErrorInfos.
@@ -629,6 +643,7 @@ private:
/// takeError(). It also adds an bool errorIsA<ErrT>() method for testing the
/// error class type.
template <class T> class LLVM_NODISCARD Expected {
+ template <class T1> friend class ExpectedAsOutParameter;
template <class OtherT> friend class Expected;
static const bool isRef = std::is_reference<T>::value;
typedef ReferenceStorage<typename std::remove_reference<T>::type> wrap;
@@ -737,7 +752,7 @@ public:
/// \brief Check that this Expected<T> is an error of type ErrT.
template <typename ErrT> bool errorIsA() const {
- return HasError && getErrorStorage()->template isA<ErrT>();
+ return HasError && (*getErrorStorage())->template isA<ErrT>();
}
/// \brief Take ownership of the stored error.
@@ -832,6 +847,18 @@ private:
return reinterpret_cast<error_type *>(ErrorStorage.buffer);
}
+ const error_type *getErrorStorage() const {
+ assert(HasError && "Cannot get error when a value exists!");
+ return reinterpret_cast<const error_type *>(ErrorStorage.buffer);
+ }
+
+ // Used by ExpectedAsOutParameter to reset the checked flag.
+ void setUnchecked() {
+#if LLVM_ENABLE_ABI_BREAKING_CHECKS
+ Unchecked = true;
+#endif
+ }
+
void assertIsChecked() {
#if LLVM_ENABLE_ABI_BREAKING_CHECKS
if (Unchecked) {
@@ -858,6 +885,28 @@ private:
#endif
};
+/// Helper for Expected<T>s used as out-parameters.
+///
+/// See ErrorAsOutParameter.
+template <typename T>
+class ExpectedAsOutParameter {
+public:
+
+ ExpectedAsOutParameter(Expected<T> *ValOrErr)
+ : ValOrErr(ValOrErr) {
+ if (ValOrErr)
+ (void)!!*ValOrErr;
+ }
+
+ ~ExpectedAsOutParameter() {
+ if (ValOrErr)
+ ValOrErr->setUnchecked();
+ }
+
+private:
+ Expected<T> *ValOrErr;
+};
+
/// This class wraps a std::error_code in a Error.
///
/// This is useful if you're writing an interface that returns a Error
@@ -926,6 +975,8 @@ public:
void log(raw_ostream &OS) const override;
std::error_code convertToErrorCode() const override;
+ const std::string &getMessage() const { return Msg; }
+
private:
std::string Msg;
std::error_code EC;
@@ -985,6 +1036,45 @@ private:
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(Error Err,
bool gen_crash_diag = true);
+/// Report a fatal error if Err is a failure value.
+///
+/// This function can be used to wrap calls to fallible functions ONLY when it
+/// is known that the Error will always be a success value. E.g.
+///
+/// @code{.cpp}
+/// // foo only attempts the fallible operation if DoFallibleOperation is
+/// // true. If DoFallibleOperation is false then foo always returns
+/// // Error::success().
+/// Error foo(bool DoFallibleOperation);
+///
+/// cantFail(foo(false));
+/// @endcode
+inline void cantFail(Error Err) {
+ if (Err)
+ llvm_unreachable("Failure value returned from cantFail wrapped call");
+}
+
+/// Report a fatal error if ValOrErr is a failure value, otherwise unwraps and
+/// returns the contained value.
+///
+/// This function can be used to wrap calls to fallible functions ONLY when it
+/// is known that the Error will always be a success value. E.g.
+///
+/// @code{.cpp}
+/// // foo only attempts the fallible operation if DoFallibleOperation is
+/// // true. If DoFallibleOperation is false then foo always returns an int.
+/// Expected<int> foo(bool DoFallibleOperation);
+///
+/// int X = cantFail(foo(false));
+/// @endcode
+template <typename T>
+T cantFail(Expected<T> ValOrErr) {
+ if (ValOrErr)
+ return std::move(*ValOrErr);
+ else
+ llvm_unreachable("Failure value returned from cantFail wrapped call");
+}
+
} // end namespace llvm
#endif // LLVM_SUPPORT_ERROR_H
diff --git a/include/llvm/Support/FileSystem.h b/include/llvm/Support/FileSystem.h
index ad21d8af66e9..29515c231bc4 100644
--- a/include/llvm/Support/FileSystem.h
+++ b/include/llvm/Support/FileSystem.h
@@ -33,6 +33,7 @@
#include "llvm/Support/Chrono.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ErrorOr.h"
+#include "llvm/Support/MD5.h"
#include <cassert>
#include <cstdint>
#include <ctime>
@@ -93,6 +94,7 @@ enum perms {
set_uid_on_exe = 04000,
set_gid_on_exe = 02000,
sticky_bit = 01000,
+ all_perms = all_all | set_uid_on_exe | set_gid_on_exe | sticky_bit,
perms_not_known = 0xFFFF
};
@@ -141,70 +143,61 @@ public:
/// a platform-specific member to store the result.
class file_status
{
+ friend bool equivalent(file_status A, file_status B);
+
#if defined(LLVM_ON_UNIX)
- dev_t fs_st_dev;
- ino_t fs_st_ino;
- time_t fs_st_atime;
- time_t fs_st_mtime;
- uid_t fs_st_uid;
- gid_t fs_st_gid;
- off_t fs_st_size;
+ dev_t fs_st_dev = 0;
+ nlink_t fs_st_nlinks = 0;
+ ino_t fs_st_ino = 0;
+ time_t fs_st_atime = 0;
+ time_t fs_st_mtime = 0;
+ uid_t fs_st_uid = 0;
+ gid_t fs_st_gid = 0;
+ off_t fs_st_size = 0;
#elif defined (LLVM_ON_WIN32)
- uint32_t LastAccessedTimeHigh;
- uint32_t LastAccessedTimeLow;
- uint32_t LastWriteTimeHigh;
- uint32_t LastWriteTimeLow;
- uint32_t VolumeSerialNumber;
- uint32_t FileSizeHigh;
- uint32_t FileSizeLow;
- uint32_t FileIndexHigh;
- uint32_t FileIndexLow;
+ uint32_t NumLinks = 0;
+ uint32_t LastAccessedTimeHigh = 0;
+ uint32_t LastAccessedTimeLow = 0;
+ uint32_t LastWriteTimeHigh = 0;
+ uint32_t LastWriteTimeLow = 0;
+ uint32_t VolumeSerialNumber = 0;
+ uint32_t FileSizeHigh = 0;
+ uint32_t FileSizeLow = 0;
+ uint32_t FileIndexHigh = 0;
+ uint32_t FileIndexLow = 0;
#endif
- friend bool equivalent(file_status A, file_status B);
- file_type Type;
- perms Perms;
+ file_type Type = file_type::status_error;
+ perms Perms = perms_not_known;
public:
#if defined(LLVM_ON_UNIX)
- file_status()
- : fs_st_dev(0), fs_st_ino(0), fs_st_atime(0), fs_st_mtime(0),
- fs_st_uid(0), fs_st_gid(0), fs_st_size(0),
- Type(file_type::status_error), Perms(perms_not_known) {}
-
- file_status(file_type Type)
- : fs_st_dev(0), fs_st_ino(0), fs_st_atime(0), fs_st_mtime(0),
- fs_st_uid(0), fs_st_gid(0), fs_st_size(0), Type(Type),
- Perms(perms_not_known) {}
-
- file_status(file_type Type, perms Perms, dev_t Dev, ino_t Ino, time_t ATime,
- time_t MTime, uid_t UID, gid_t GID, off_t Size)
- : fs_st_dev(Dev), fs_st_ino(Ino), fs_st_atime(ATime), fs_st_mtime(MTime),
- fs_st_uid(UID), fs_st_gid(GID), fs_st_size(Size), Type(Type),
- Perms(Perms) {}
+ file_status() = default;
+
+ file_status(file_type Type) : Type(Type) {}
+
+ file_status(file_type Type, perms Perms, dev_t Dev, nlink_t Links, ino_t Ino,
+ time_t ATime, time_t MTime, uid_t UID, gid_t GID, off_t Size)
+ : fs_st_dev(Dev), fs_st_nlinks(Links), fs_st_ino(Ino), fs_st_atime(ATime),
+ fs_st_mtime(MTime), fs_st_uid(UID), fs_st_gid(GID), fs_st_size(Size),
+ Type(Type), Perms(Perms) {}
#elif defined(LLVM_ON_WIN32)
- file_status()
- : LastAccessedTimeHigh(0), LastAccessedTimeLow(0), LastWriteTimeHigh(0),
- LastWriteTimeLow(0), VolumeSerialNumber(0), FileSizeHigh(0),
- FileSizeLow(0), FileIndexHigh(0), FileIndexLow(0),
- Type(file_type::status_error), Perms(perms_not_known) {}
-
- file_status(file_type Type)
- : LastAccessedTimeHigh(0), LastAccessedTimeLow(0), LastWriteTimeHigh(0),
- LastWriteTimeLow(0), VolumeSerialNumber(0), FileSizeHigh(0),
- FileSizeLow(0), FileIndexHigh(0), FileIndexLow(0), Type(Type),
- Perms(perms_not_known) {}
-
- file_status(file_type Type, uint32_t LastAccessTimeHigh,
- uint32_t LastAccessTimeLow, uint32_t LastWriteTimeHigh,
- uint32_t LastWriteTimeLow, uint32_t VolumeSerialNumber,
- uint32_t FileSizeHigh, uint32_t FileSizeLow,
- uint32_t FileIndexHigh, uint32_t FileIndexLow)
- : LastAccessedTimeHigh(LastAccessTimeHigh), LastAccessedTimeLow(LastAccessTimeLow),
+ file_status() = default;
+
+ file_status(file_type Type) : Type(Type) {}
+
+ file_status(file_type Type, perms Perms, uint32_t LinkCount,
+ uint32_t LastAccessTimeHigh, uint32_t LastAccessTimeLow,
+ uint32_t LastWriteTimeHigh, uint32_t LastWriteTimeLow,
+ uint32_t VolumeSerialNumber, uint32_t FileSizeHigh,
+ uint32_t FileSizeLow, uint32_t FileIndexHigh,
+ uint32_t FileIndexLow)
+ : NumLinks(LinkCount), LastAccessedTimeHigh(LastAccessTimeHigh),
+ LastAccessedTimeLow(LastAccessTimeLow),
LastWriteTimeHigh(LastWriteTimeHigh),
LastWriteTimeLow(LastWriteTimeLow),
VolumeSerialNumber(VolumeSerialNumber), FileSizeHigh(FileSizeHigh),
FileSizeLow(FileSizeLow), FileIndexHigh(FileIndexHigh),
- FileIndexLow(FileIndexLow), Type(Type), Perms(perms_not_known) {}
+ FileIndexLow(FileIndexLow), Type(Type), Perms(Perms) {}
#endif
// getters
@@ -213,6 +206,7 @@ public:
TimePoint<> getLastAccessedTime() const;
TimePoint<> getLastModificationTime() const;
UniqueID getUniqueID() const;
+ uint32_t getLinkCount() const;
#if defined(LLVM_ON_UNIX)
uint32_t getUser() const { return fs_st_uid; }
@@ -222,9 +216,11 @@ public:
uint32_t getUser() const {
return 9999; // Not applicable to Windows, so...
}
+
uint32_t getGroup() const {
return 9999; // Not applicable to Windows, so...
}
+
uint64_t getSize() const {
return (uint64_t(FileSizeHigh) << 32) + FileSizeLow;
}
@@ -271,12 +267,12 @@ struct file_magic {
return V != unknown;
}
- file_magic() : V(unknown) {}
+ file_magic() = default;
file_magic(Impl V) : V(V) {}
operator Impl() const { return V; }
private:
- Impl V;
+ Impl V = unknown;
};
/// @}
@@ -350,6 +346,16 @@ std::error_code create_link(const Twine &to, const Twine &from);
/// specific error_code.
std::error_code create_hard_link(const Twine &to, const Twine &from);
+/// @brief Collapse all . and .. patterns, resolve all symlinks, and optionally
+/// expand ~ expressions to the user's home directory.
+///
+/// @param path The path to resolve.
+/// @param output The location to store the resolved path.
+/// @param expand_tilde If true, resolves ~ expressions to the user's home
+/// directory.
+std::error_code real_path(const Twine &path, SmallVectorImpl<char> &output,
+ bool expand_tilde = false);
+
/// @brief Get the current path.
///
/// @param result Holds the current path on return.
@@ -357,6 +363,13 @@ std::error_code create_hard_link(const Twine &to, const Twine &from);
/// otherwise a platform-specific error_code.
std::error_code current_path(SmallVectorImpl<char> &result);
+/// @brief Set the current path.
+///
+/// @param path The path to set.
+/// @returns errc::success if the current path was successfully set,
+/// otherwise a platform-specific error_code.
+std::error_code set_current_path(const Twine &path);
+
/// @brief Remove path. Equivalent to POSIX remove().
///
/// @param path Input path.
@@ -365,6 +378,13 @@ std::error_code current_path(SmallVectorImpl<char> &result);
/// returns error if the file didn't exist.
std::error_code remove(const Twine &path, bool IgnoreNonExisting = true);
+/// @brief Recursively delete a directory.
+///
+/// @param path Input path.
+/// @returns errc::success if path has been removed or didn't exist, otherwise a
+/// platform-specific error code.
+std::error_code remove_directories(const Twine &path, bool IgnoreErrors = true);
+
/// @brief Rename \a from to \a to. Files are renamed as if by POSIX rename().
///
/// @param from The path to rename from.
@@ -385,6 +405,16 @@ std::error_code copy_file(const Twine &From, const Twine &To);
/// platform-specific error_code.
std::error_code resize_file(int FD, uint64_t Size);
+/// @brief Compute an MD5 hash of a file's contents.
+///
+/// @param FD Input file descriptor.
+/// @returns An MD5Result with the hash computed, if successful, otherwise a
+/// std::error_code.
+ErrorOr<MD5::MD5Result> md5_contents(int FD);
+
+/// @brief Version of compute_md5 that doesn't require an open file descriptor.
+ErrorOr<MD5::MD5Result> md5_contents(const Twine &Path);
+
/// @}
/// @name Physical Observers
/// @{
@@ -457,6 +487,40 @@ inline bool equivalent(const Twine &A, const Twine &B) {
return !equivalent(A, B, result) && result;
}
+/// @brief Is the file mounted on a local filesystem?
+///
+/// @param path Input path.
+/// @param result Set to true if \a path is on fixed media such as a hard disk,
+/// false if it is not.
+/// @returns errc::success if result has been successfully set, otherwise a
+/// platform specific error_code.
+std::error_code is_local(const Twine &path, bool &result);
+
+/// @brief Version of is_local accepting an open file descriptor.
+std::error_code is_local(int FD, bool &result);
+
+/// @brief Simpler version of is_local for clients that don't need to
+/// differentiate between an error and false.
+inline bool is_local(const Twine &Path) {
+ bool Result;
+ return !is_local(Path, Result) && Result;
+}
+
+/// @brief Simpler version of is_local accepting an open file descriptor for
+/// clients that don't need to differentiate between an error and false.
+inline bool is_local(int FD) {
+ bool Result;
+ return !is_local(FD, Result) && Result;
+}
+
+/// @brief Does status represent a directory?
+///
+/// @param Path The path to get the type of.
+/// @param Follow For symbolic links, indicates whether to return the file type
+/// of the link itself, or of the target.
+/// @returns A value from the file_type enumeration indicating the type of file.
+file_type get_file_type(const Twine &Path, bool Follow = true);
+
/// @brief Does status represent a directory?
///
/// @param status A file_status previously returned from status.
@@ -466,8 +530,8 @@ bool is_directory(file_status status);
/// @brief Is path a directory?
///
/// @param path Input path.
-/// @param result Set to true if \a path is a directory, false if it is not.
-/// Undefined otherwise.
+/// @param result Set to true if \a path is a directory (after following
+/// symlinks, false if it is not. Undefined otherwise.
/// @returns errc::success if result has been successfully set, otherwise a
/// platform-specific error_code.
std::error_code is_directory(const Twine &path, bool &result);
@@ -488,8 +552,8 @@ bool is_regular_file(file_status status);
/// @brief Is path a regular file?
///
/// @param path Input path.
-/// @param result Set to true if \a path is a regular file, false if it is not.
-/// Undefined otherwise.
+/// @param result Set to true if \a path is a regular file (after following
+/// symlinks), false if it is not. Undefined otherwise.
/// @returns errc::success if result has been successfully set, otherwise a
/// platform-specific error_code.
std::error_code is_regular_file(const Twine &path, bool &result);
@@ -503,8 +567,32 @@ inline bool is_regular_file(const Twine &Path) {
return Result;
}
+/// @brief Does status represent a symlink file?
+///
+/// @param status A file_status previously returned from status.
+/// @returns status_known(status) && status.type() == file_type::symlink_file.
+bool is_symlink_file(file_status status);
+
+/// @brief Is path a symlink file?
+///
+/// @param path Input path.
+/// @param result Set to true if \a path is a symlink file, false if it is not.
+/// Undefined otherwise.
+/// @returns errc::success if result has been successfully set, otherwise a
+/// platform-specific error_code.
+std::error_code is_symlink_file(const Twine &path, bool &result);
+
+/// @brief Simpler version of is_symlink_file for clients that don't need to
+/// differentiate between an error and false.
+inline bool is_symlink_file(const Twine &Path) {
+ bool Result;
+ if (is_symlink_file(Path, Result))
+ return false;
+ return Result;
+}
+
/// @brief Does this status represent something that exists but is not a
-/// directory, regular file, or symlink?
+/// directory or regular file?
///
/// @param status A file_status previously returned from status.
/// @returns exists(s) && !is_regular_file(s) && !is_directory(s)
@@ -524,13 +612,37 @@ std::error_code is_other(const Twine &path, bool &result);
///
/// @param path Input path.
/// @param result Set to the file status.
+/// @param follow When true, follows symlinks. Otherwise, the symlink itself is
+/// statted.
/// @returns errc::success if result has been successfully set, otherwise a
/// platform-specific error_code.
-std::error_code status(const Twine &path, file_status &result);
+std::error_code status(const Twine &path, file_status &result,
+ bool follow = true);
/// @brief A version for when a file descriptor is already available.
std::error_code status(int FD, file_status &Result);
+/// @brief Set file permissions.
+///
+/// @param Path File to set permissions on.
+/// @param Permissions New file permissions.
+/// @returns errc::success if the permissions were successfully set, otherwise
+/// a platform-specific error_code.
+/// @note On Windows, all permissions except *_write are ignored. Using any of
+/// owner_write, group_write, or all_write will make the file writable.
+/// Otherwise, the file will be marked as read-only.
+std::error_code setPermissions(const Twine &Path, perms Permissions);
+
+/// @brief Get file permissions.
+///
+/// @param Path File to get permissions from.
+/// @returns the permissions if they were successfully retrieved, otherwise a
+/// platform-specific error_code.
+/// @note On Windows, if the file does not have the FILE_ATTRIBUTE_READONLY
+/// attribute, all_all will be returned. Otherwise, all_read | all_exe
+/// will be returned.
+ErrorOr<perms> getPermissions(const Twine &Path);
+
/// @brief Get file size.
///
/// @param Path Input path.
@@ -735,12 +847,13 @@ std::string getMainExecutable(const char *argv0, void *MainExecAddr);
/// called.
class directory_entry {
std::string Path;
+ bool FollowSymlinks;
mutable file_status Status;
public:
- explicit directory_entry(const Twine &path, file_status st = file_status())
- : Path(path.str())
- , Status(st) {}
+ explicit directory_entry(const Twine &path, bool follow_symlinks = true,
+ file_status st = file_status())
+ : Path(path.str()), FollowSymlinks(follow_symlinks), Status(st) {}
directory_entry() = default;
@@ -763,9 +876,10 @@ public:
};
namespace detail {
+
struct DirIterState;
- std::error_code directory_iterator_construct(DirIterState &, StringRef);
+ std::error_code directory_iterator_construct(DirIterState &, StringRef, bool);
std::error_code directory_iterator_increment(DirIterState &);
std::error_code directory_iterator_destruct(DirIterState &);
@@ -778,6 +892,7 @@ namespace detail {
intptr_t IterationHandle = 0;
directory_entry CurrentEntry;
};
+
} // end namespace detail
/// directory_iterator - Iterates through the entries in path. There is no
@@ -785,18 +900,24 @@ namespace detail {
/// it call report_fatal_error on error.
class directory_iterator {
std::shared_ptr<detail::DirIterState> State;
+ bool FollowSymlinks = true;
public:
- explicit directory_iterator(const Twine &path, std::error_code &ec) {
+ explicit directory_iterator(const Twine &path, std::error_code &ec,
+ bool follow_symlinks = true)
+ : FollowSymlinks(follow_symlinks) {
State = std::make_shared<detail::DirIterState>();
SmallString<128> path_storage;
- ec = detail::directory_iterator_construct(*State,
- path.toStringRef(path_storage));
+ ec = detail::directory_iterator_construct(
+ *State, path.toStringRef(path_storage), FollowSymlinks);
}
- explicit directory_iterator(const directory_entry &de, std::error_code &ec) {
+ explicit directory_iterator(const directory_entry &de, std::error_code &ec,
+ bool follow_symlinks = true)
+ : FollowSymlinks(follow_symlinks) {
State = std::make_shared<detail::DirIterState>();
- ec = detail::directory_iterator_construct(*State, de.path());
+ ec =
+ detail::directory_iterator_construct(*State, de.path(), FollowSymlinks);
}
/// Construct end iterator.
@@ -829,24 +950,29 @@ public:
};
namespace detail {
+
/// Keeps state for the recursive_directory_iterator.
struct RecDirIterState {
std::stack<directory_iterator, std::vector<directory_iterator>> Stack;
uint16_t Level = 0;
bool HasNoPushRequest = false;
};
+
} // end namespace detail
/// recursive_directory_iterator - Same as directory_iterator except for it
/// recurses down into child directories.
class recursive_directory_iterator {
std::shared_ptr<detail::RecDirIterState> State;
+ bool Follow;
public:
recursive_directory_iterator() = default;
- explicit recursive_directory_iterator(const Twine &path, std::error_code &ec)
- : State(std::make_shared<detail::RecDirIterState>()) {
- State->Stack.push(directory_iterator(path, ec));
+ explicit recursive_directory_iterator(const Twine &path, std::error_code &ec,
+ bool follow_symlinks = true)
+ : State(std::make_shared<detail::RecDirIterState>()),
+ Follow(follow_symlinks) {
+ State->Stack.push(directory_iterator(path, ec, Follow));
if (State->Stack.top() == directory_iterator())
State.reset();
}
@@ -861,7 +987,7 @@ public:
file_status st;
if ((ec = State->Stack.top()->status(st))) return *this;
if (is_directory(st)) {
- State->Stack.push(directory_iterator(*State->Stack.top(), ec));
+ State->Stack.push(directory_iterator(*State->Stack.top(), ec, Follow));
if (ec) return *this;
if (State->Stack.top() != end_itr) {
++State->Level;
diff --git a/include/llvm/Support/FormatAdapters.h b/include/llvm/Support/FormatAdapters.h
index 7bacd2e17135..698e134b328d 100644
--- a/include/llvm/Support/FormatAdapters.h
+++ b/include/llvm/Support/FormatAdapters.h
@@ -22,9 +22,6 @@ protected:
explicit FormatAdapter(T &&Item) : Item(Item) {}
T Item;
-
- static_assert(!detail::uses_missing_provider<T>::value,
- "Item does not have a format provider!");
};
namespace detail {
diff --git a/include/llvm/Support/FormatProviders.h b/include/llvm/Support/FormatProviders.h
index 1f0768c3ab08..4e57034ff98e 100644
--- a/include/llvm/Support/FormatProviders.h
+++ b/include/llvm/Support/FormatProviders.h
@@ -18,6 +18,7 @@
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringSwitch.h"
+#include "llvm/ADT/Twine.h"
#include "llvm/Support/FormatVariadicDetails.h"
#include "llvm/Support/NativeFormatting.h"
@@ -45,9 +46,8 @@ struct is_cstring
template <typename T>
struct use_string_formatter
- : public std::integral_constant<
- bool, is_one_of<T, llvm::StringRef, std::string>::value ||
- is_cstring<T>::value> {};
+ : public std::integral_constant<bool,
+ std::is_convertible<T, llvm::StringRef>::value> {};
template <typename T>
struct use_pointer_formatter
@@ -205,11 +205,22 @@ struct format_provider<
if (!Style.empty() && Style.getAsInteger(10, N)) {
assert(false && "Style is not a valid integer");
}
- llvm::StringRef S(V);
+ llvm::StringRef S = V;
Stream << S.substr(0, N);
}
};
+/// Implementation of format_provider<T> for llvm::Twine.
+///
+/// This follows the same rules as the string formatter.
+
+template <> struct format_provider<Twine> {
+ static void format(const Twine &V, llvm::raw_ostream &Stream,
+ StringRef Style) {
+ format_provider<std::string>::format(V.str(), Stream, Style);
+ }
+};
+
/// Implementation of format_provider<T> for characters.
///
/// The options string of a character type has the grammar:
@@ -359,8 +370,7 @@ template <typename IterT> class format_provider<llvm::iterator_range<IterT>> {
return Default;
}
- std::vector<const char *> Delims = {"[]", "<>", "()"};
- for (const char *D : Delims) {
+ for (const char *D : {"[]", "<>", "()"}) {
if (Style.front() != D[0])
continue;
size_t End = Style.find_first_of(D[1]);
diff --git a/include/llvm/Support/FormatVariadic.h b/include/llvm/Support/FormatVariadic.h
index e5f5c9615cb6..3a4668687cc9 100644
--- a/include/llvm/Support/FormatVariadic.h
+++ b/include/llvm/Support/FormatVariadic.h
@@ -196,7 +196,7 @@ public:
// "}}" to print a literal '}'.
//
// ===Parameter Indexing===
-// `index` specifies the index of the paramter in the parameter pack to format
+// `index` specifies the index of the parameter in the parameter pack to format
// into the output. Note that it is possible to refer to the same parameter
// index multiple times in a given format string. This makes it possible to
// output the same value multiple times without passing it multiple times to the
diff --git a/include/llvm/Support/GCOV.h b/include/llvm/Support/GCOV.h
index f297fe609d2a..73fddca8e35b 100644
--- a/include/llvm/Support/GCOV.h
+++ b/include/llvm/Support/GCOV.h
@@ -63,7 +63,7 @@ struct Options {
/// read operations.
class GCOVBuffer {
public:
- GCOVBuffer(MemoryBuffer *B) : Buffer(B), Cursor(0) {}
+ GCOVBuffer(MemoryBuffer *B) : Buffer(B) {}
/// readGCNOFormat - Check GCNO signature is valid at the beginning of buffer.
bool readGCNOFormat() {
@@ -234,39 +234,38 @@ public:
private:
MemoryBuffer *Buffer;
- uint64_t Cursor;
+ uint64_t Cursor = 0;
};
/// GCOVFile - Collects coverage information for one pair of coverage file
/// (.gcno and .gcda).
class GCOVFile {
public:
- GCOVFile()
- : GCNOInitialized(false), Checksum(0), RunCount(0),
- ProgramCount(0) {}
+ GCOVFile() = default;
bool readGCNO(GCOVBuffer &Buffer);
bool readGCDA(GCOVBuffer &Buffer);
uint32_t getChecksum() const { return Checksum; }
+ void print(raw_ostream &OS) const;
void dump() const;
void collectLineCounts(FileInfo &FI);
private:
- bool GCNOInitialized;
+ bool GCNOInitialized = false;
GCOV::GCOVVersion Version;
- uint32_t Checksum;
+ uint32_t Checksum = 0;
SmallVector<std::unique_ptr<GCOVFunction>, 16> Functions;
- uint32_t RunCount;
- uint32_t ProgramCount;
+ uint32_t RunCount = 0;
+ uint32_t ProgramCount = 0;
};
/// GCOVEdge - Collects edge information.
struct GCOVEdge {
- GCOVEdge(GCOVBlock &S, GCOVBlock &D) : Src(S), Dst(D), Count(0) {}
+ GCOVEdge(GCOVBlock &S, GCOVBlock &D) : Src(S), Dst(D) {}
GCOVBlock &Src;
GCOVBlock &Dst;
- uint64_t Count;
+ uint64_t Count = 0;
};
/// GCOVFunction - Collects function information.
@@ -275,7 +274,8 @@ public:
typedef pointee_iterator<SmallVectorImpl<
std::unique_ptr<GCOVBlock>>::const_iterator> BlockIterator;
- GCOVFunction(GCOVFile &P) : Parent(P), Ident(0), LineNumber(0) {}
+ GCOVFunction(GCOVFile &P) : Parent(P) {}
+
bool readGCNO(GCOVBuffer &Buffer, GCOV::GCOVVersion Version);
bool readGCDA(GCOVBuffer &Buffer, GCOV::GCOVVersion Version);
StringRef getName() const { return Name; }
@@ -290,14 +290,15 @@ public:
return make_range(block_begin(), block_end());
}
+ void print(raw_ostream &OS) const;
void dump() const;
void collectLineCounts(FileInfo &FI);
private:
GCOVFile &Parent;
- uint32_t Ident;
+ uint32_t Ident = 0;
uint32_t Checksum;
- uint32_t LineNumber;
+ uint32_t LineNumber = 0;
StringRef Name;
StringRef Filename;
SmallVector<std::unique_ptr<GCOVBlock>, 16> Blocks;
@@ -307,10 +308,10 @@ private:
/// GCOVBlock - Collects block information.
class GCOVBlock {
struct EdgeWeight {
- EdgeWeight(GCOVBlock *D) : Dst(D), Count(0) {}
+ EdgeWeight(GCOVBlock *D) : Dst(D) {}
GCOVBlock *Dst;
- uint64_t Count;
+ uint64_t Count = 0;
};
struct SortDstEdgesFunctor {
@@ -322,8 +323,7 @@ class GCOVBlock {
public:
typedef SmallVectorImpl<GCOVEdge *>::const_iterator EdgeIterator;
- GCOVBlock(GCOVFunction &P, uint32_t N)
- : Parent(P), Number(N), Counter(0), DstEdgesAreSorted(true) {}
+ GCOVBlock(GCOVFunction &P, uint32_t N) : Parent(P), Number(N) {}
~GCOVBlock();
const GCOVFunction &getParent() const { return Parent; }
@@ -361,14 +361,15 @@ public:
return make_range(dst_begin(), dst_end());
}
+ void print(raw_ostream &OS) const;
void dump() const;
void collectLineCounts(FileInfo &FI);
private:
GCOVFunction &Parent;
uint32_t Number;
- uint64_t Counter;
- bool DstEdgesAreSorted;
+ uint64_t Counter = 0;
+ bool DstEdgesAreSorted = true;
SmallVector<GCOVEdge *, 16> SrcEdges;
SmallVector<GCOVEdge *, 16> DstEdges;
SmallVector<uint32_t, 16> Lines;
@@ -386,30 +387,28 @@ class FileInfo {
typedef DenseMap<uint32_t, BlockVector> BlockLines;
struct LineData {
- LineData() : LastLine(0) {}
+ LineData() = default;
+
BlockLines Blocks;
FunctionLines Functions;
- uint32_t LastLine;
+ uint32_t LastLine = 0;
};
struct GCOVCoverage {
- GCOVCoverage(StringRef Name)
- : Name(Name), LogicalLines(0), LinesExec(0), Branches(0),
- BranchesExec(0), BranchesTaken(0) {}
+ GCOVCoverage(StringRef Name) : Name(Name) {}
StringRef Name;
- uint32_t LogicalLines;
- uint32_t LinesExec;
+ uint32_t LogicalLines = 0;
+ uint32_t LinesExec = 0;
- uint32_t Branches;
- uint32_t BranchesExec;
- uint32_t BranchesTaken;
+ uint32_t Branches = 0;
+ uint32_t BranchesExec = 0;
+ uint32_t BranchesTaken = 0;
};
public:
- FileInfo(const GCOV::Options &Options)
- : Options(Options), RunCount(0), ProgramCount(0) {}
+ FileInfo(const GCOV::Options &Options) : Options(Options) {}
void addBlockLine(StringRef Filename, uint32_t Line, const GCOVBlock *Block) {
if (Line > LineInfo[Filename].LastLine)
@@ -446,8 +445,8 @@ private:
const GCOV::Options &Options;
StringMap<LineData> LineInfo;
- uint32_t RunCount;
- uint32_t ProgramCount;
+ uint32_t RunCount = 0;
+ uint32_t ProgramCount = 0;
typedef SmallVector<std::pair<std::string, GCOVCoverage>, 4> FileCoverageList;
typedef MapVector<const GCOVFunction *, GCOVCoverage> FuncCoverageMap;
diff --git a/include/llvm/Support/GenericDomTree.h b/include/llvm/Support/GenericDomTree.h
index 6e6ee4001644..20f3ffdf3aab 100644
--- a/include/llvm/Support/GenericDomTree.h
+++ b/include/llvm/Support/GenericDomTree.h
@@ -13,7 +13,7 @@
/// dominance queries on the CFG, but is fully generic w.r.t. the underlying
/// graph types.
///
-/// Unlike ADT/* graph algorithms, generic dominator tree has more reuiqrement
+/// Unlike ADT/* graph algorithms, generic dominator tree has more requirements
/// on the graph's NodeRef. The NodeRef should be a pointer and, depending on
/// the implementation, e.g. NodeRef->getParent() return the parent node.
///
@@ -25,14 +25,19 @@
#define LLVM_SUPPORT_GENERICDOMTREE_H
#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"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <iterator>
+#include <memory>
+#include <type_traits>
+#include <utility>
+#include <vector>
namespace llvm {
@@ -47,7 +52,7 @@ template <typename GT> struct DominatorTreeBaseTraits {
typename std::remove_pointer<typename GT::NodeRef>::type>;
};
-} // End namespace detail
+} // end namespace detail
template <typename GT>
using DominatorTreeBaseByGraphTraits =
@@ -59,13 +64,16 @@ template <class NodeT> class DominatorBase {
protected:
std::vector<NodeT *> Roots;
bool IsPostDominators;
+
explicit DominatorBase(bool isPostDom)
: Roots(), IsPostDominators(isPostDom) {}
+
DominatorBase(DominatorBase &&Arg)
: Roots(std::move(Arg.Roots)),
IsPostDominators(std::move(Arg.IsPostDominators)) {
Arg.Roots.clear();
}
+
DominatorBase &operator=(DominatorBase &&RHS) {
Roots = std::move(RHS.Roots);
IsPostDominators = std::move(RHS.IsPostDominators);
@@ -85,19 +93,21 @@ public:
bool isPostDominator() const { return IsPostDominators; }
};
-struct PostDominatorTree;
-
/// \brief Base class for the actual dominator tree node.
template <class NodeT> class DomTreeNodeBase {
+ friend struct PostDominatorTree;
+ template <class N> friend class DominatorTreeBase;
+
NodeT *TheBB;
DomTreeNodeBase<NodeT> *IDom;
std::vector<DomTreeNodeBase<NodeT> *> Children;
- mutable int DFSNumIn, DFSNumOut;
-
- template <class N> friend class DominatorTreeBase;
- friend struct PostDominatorTree;
+ mutable int DFSNumIn = -1;
+ mutable int DFSNumOut = -1;
public:
+ DomTreeNodeBase(NodeT *BB, DomTreeNodeBase<NodeT> *iDom)
+ : TheBB(BB), IDom(iDom) {}
+
typedef typename std::vector<DomTreeNodeBase<NodeT> *>::iterator iterator;
typedef typename std::vector<DomTreeNodeBase<NodeT> *>::const_iterator
const_iterator;
@@ -109,13 +119,11 @@ public:
NodeT *getBlock() const { return TheBB; }
DomTreeNodeBase<NodeT> *getIDom() const { return IDom; }
+
const std::vector<DomTreeNodeBase<NodeT> *> &getChildren() const {
return Children;
}
- DomTreeNodeBase(NodeT *BB, DomTreeNodeBase<NodeT> *iDom)
- : TheBB(BB), IDom(iDom), DFSNumIn(-1), DFSNumOut(-1) {}
-
std::unique_ptr<DomTreeNodeBase<NodeT>>
addChild(std::unique_ptr<DomTreeNodeBase<NodeT>> C) {
Children.push_back(C.get());
@@ -206,9 +214,6 @@ void Calculate(DominatorTreeBaseByGraphTraits<GraphTraits<N>> &DT, FuncT &F);
/// This class is a generic template over graph nodes. It is instantiated for
/// various graphs in the LLVM IR or in the code generator.
template <class NodeT> class DominatorTreeBase : public DominatorBase<NodeT> {
- DominatorTreeBase(const DominatorTreeBase &) = delete;
- DominatorTreeBase &operator=(const DominatorTreeBase &) = delete;
-
bool dominatedBySlowTreeWalk(const DomTreeNodeBase<NodeT> *A,
const DomTreeNodeBase<NodeT> *B) const {
assert(A != B);
@@ -239,16 +244,16 @@ protected:
DomTreeNodeMapType DomTreeNodes;
DomTreeNodeBase<NodeT> *RootNode;
- mutable bool DFSInfoValid;
- mutable unsigned int SlowQueries;
+ mutable bool DFSInfoValid = false;
+ mutable unsigned int SlowQueries = 0;
// Information record used during immediate dominators computation.
struct InfoRec {
- unsigned DFSNum;
- unsigned Parent;
- unsigned Semi;
- NodeT *Label;
+ unsigned DFSNum = 0;
+ unsigned Parent = 0;
+ unsigned Semi = 0;
+ NodeT *Label = nullptr;
- InfoRec() : DFSNum(0), Parent(0), Semi(0), Label(nullptr) {}
+ InfoRec() = default;
};
DenseMap<NodeT *, NodeT *> IDoms;
@@ -336,7 +341,7 @@ protected:
public:
explicit DominatorTreeBase(bool isPostDom)
- : DominatorBase<NodeT>(isPostDom), DFSInfoValid(false), SlowQueries(0) {}
+ : DominatorBase<NodeT>(isPostDom) {}
DominatorTreeBase(DominatorTreeBase &&Arg)
: DominatorBase<NodeT>(
@@ -348,6 +353,7 @@ public:
Vertex(std::move(Arg.Vertex)), Info(std::move(Arg.Info)) {
Arg.wipe();
}
+
DominatorTreeBase &operator=(DominatorTreeBase &&RHS) {
DominatorBase<NodeT>::operator=(
std::move(static_cast<DominatorBase<NodeT> &>(RHS)));
@@ -362,6 +368,9 @@ public:
return *this;
}
+ DominatorTreeBase(const DominatorTreeBase &) = delete;
+ DominatorTreeBase &operator=(const DominatorTreeBase &) = delete;
+
/// compare - Return false if the other dominator tree base matches this
/// dominator tree base. Otherwise return true.
bool compare(const DominatorTreeBase &Other) const {
@@ -684,6 +693,10 @@ protected:
unsigned LastLinked);
template <class GraphT>
+ friend unsigned ReverseDFSPass(DominatorTreeBaseByGraphTraits<GraphT> &DT,
+ typename GraphT::NodeRef V, unsigned N);
+
+ template <class GraphT>
friend unsigned DFSPass(DominatorTreeBaseByGraphTraits<GraphT> &DT,
typename GraphT::NodeRef V, unsigned N);
@@ -716,7 +729,6 @@ 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;
@@ -778,11 +790,9 @@ public:
Calculate<FT, NodeT *>(*this, F);
} else {
// Initialize the roots list
- for (typename TraitsTy::nodes_iterator I = TraitsTy::nodes_begin(&F),
- E = TraitsTy::nodes_end(&F);
- I != E; ++I)
- if (TraitsTy::child_begin(*I) == TraitsTy::child_end(*I))
- addRoot(*I);
+ for (auto *Node : nodes(&F))
+ if (TraitsTy::child_begin(Node) == TraitsTy::child_end(Node))
+ addRoot(Node);
Calculate<FT, Inverse<NodeT *>>(*this, F);
}
@@ -815,6 +825,6 @@ bool DominatorTreeBase<NodeT>::properlyDominates(const NodeT *A,
getNode(const_cast<NodeT *>(B)));
}
-}
+} // end namespace llvm
-#endif
+#endif // LLVM_SUPPORT_GENERICDOMTREE_H
diff --git a/include/llvm/Support/GenericDomTreeConstruction.h b/include/llvm/Support/GenericDomTreeConstruction.h
index 54e55cc1a32e..c1d757f3ab6a 100644
--- a/include/llvm/Support/GenericDomTreeConstruction.h
+++ b/include/llvm/Support/GenericDomTreeConstruction.h
@@ -24,82 +24,77 @@
#ifndef LLVM_SUPPORT_GENERICDOMTREECONSTRUCTION_H
#define LLVM_SUPPORT_GENERICDOMTREECONSTRUCTION_H
+#include "llvm/ADT/DepthFirstIterator.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Support/GenericDomTree.h"
namespace llvm {
-template <class GraphT>
-unsigned DFSPass(DominatorTreeBaseByGraphTraits<GraphT> &DT,
- typename GraphT::NodeRef V, unsigned N) {
- // This is more understandable as a recursive algorithm, but we can't use the
- // recursive algorithm due to stack depth issues. Keep it here for
- // documentation purposes.
-#if 0
- InfoRec &VInfo = DT.Info[DT.Roots[i]];
- VInfo.DFSNum = VInfo.Semi = ++N;
- VInfo.Label = V;
-
- Vertex.push_back(V); // Vertex[n] = V;
-
- for (succ_iterator SI = succ_begin(V), E = succ_end(V); SI != E; ++SI) {
- InfoRec &SuccVInfo = DT.Info[*SI];
- if (SuccVInfo.Semi == 0) {
- SuccVInfo.Parent = V;
- N = DTDFSPass(DT, *SI, N);
- }
+// External storage for depth first iterator that reuses the info lookup map
+// domtree already has. We don't have a set, but a map instead, so we are
+// converting the one argument insert calls.
+template <class NodeRef, class InfoType> struct df_iterator_dom_storage {
+public:
+ typedef DenseMap<NodeRef, InfoType> BaseSet;
+ df_iterator_dom_storage(BaseSet &Storage) : Storage(Storage) {}
+
+ typedef typename BaseSet::iterator iterator;
+ std::pair<iterator, bool> insert(NodeRef N) {
+ return Storage.insert({N, InfoType()});
}
-#else
- bool IsChildOfArtificialExit = (N != 0);
+ void completed(NodeRef) {}
- SmallVector<
- std::pair<typename GraphT::NodeRef, typename GraphT::ChildIteratorType>,
- 32>
- Worklist;
- Worklist.push_back(std::make_pair(V, GraphT::child_begin(V)));
- while (!Worklist.empty()) {
- typename GraphT::NodeRef BB = Worklist.back().first;
- typename GraphT::ChildIteratorType NextSucc = Worklist.back().second;
+private:
+ BaseSet &Storage;
+};
+template <class GraphT>
+unsigned ReverseDFSPass(DominatorTreeBaseByGraphTraits<GraphT> &DT,
+ typename GraphT::NodeRef V, unsigned N) {
+ df_iterator_dom_storage<
+ typename GraphT::NodeRef,
+ typename DominatorTreeBaseByGraphTraits<GraphT>::InfoRec>
+ DFStorage(DT.Info);
+ bool IsChildOfArtificialExit = (N != 0);
+ for (auto I = idf_ext_begin(V, DFStorage), E = idf_ext_end(V, DFStorage);
+ I != E; ++I) {
+ typename GraphT::NodeRef BB = *I;
auto &BBInfo = DT.Info[BB];
+ BBInfo.DFSNum = BBInfo.Semi = ++N;
+ BBInfo.Label = BB;
+ // Set the parent to the top of the visited stack. The stack includes us,
+ // and is 1 based, so we subtract to account for both of these.
+ if (I.getPathLength() > 1)
+ BBInfo.Parent = DT.Info[I.getPath(I.getPathLength() - 2)].DFSNum;
+ DT.Vertex.push_back(BB); // Vertex[n] = V;
- // First time we visited this BB?
- if (NextSucc == GraphT::child_begin(BB)) {
- BBInfo.DFSNum = BBInfo.Semi = ++N;
- BBInfo.Label = BB;
-
- DT.Vertex.push_back(BB); // Vertex[n] = V;
-
- if (IsChildOfArtificialExit)
- BBInfo.Parent = 1;
-
- IsChildOfArtificialExit = false;
- }
-
- // store the DFS number of the current BB - the reference to BBInfo might
- // get invalidated when processing the successors.
- unsigned BBDFSNum = BBInfo.DFSNum;
-
- // If we are done with this block, remove it from the worklist.
- if (NextSucc == GraphT::child_end(BB)) {
- Worklist.pop_back();
- continue;
- }
-
- // Increment the successor number for the next time we get to it.
- ++Worklist.back().second;
-
- // Visit the successor next, if it isn't already visited.
- typename GraphT::NodeRef Succ = *NextSucc;
+ if (IsChildOfArtificialExit)
+ BBInfo.Parent = 1;
- auto &SuccVInfo = DT.Info[Succ];
- if (SuccVInfo.Semi == 0) {
- SuccVInfo.Parent = BBDFSNum;
- Worklist.push_back(std::make_pair(Succ, GraphT::child_begin(Succ)));
- }
+ IsChildOfArtificialExit = false;
}
-#endif
- return N;
+ return N;
+}
+template <class GraphT>
+unsigned DFSPass(DominatorTreeBaseByGraphTraits<GraphT> &DT,
+ typename GraphT::NodeRef V, unsigned N) {
+ df_iterator_dom_storage<
+ typename GraphT::NodeRef,
+ typename DominatorTreeBaseByGraphTraits<GraphT>::InfoRec>
+ DFStorage(DT.Info);
+ for (auto I = df_ext_begin(V, DFStorage), E = df_ext_end(V, DFStorage);
+ I != E; ++I) {
+ typename GraphT::NodeRef BB = *I;
+ auto &BBInfo = DT.Info[BB];
+ BBInfo.DFSNum = BBInfo.Semi = ++N;
+ BBInfo.Label = BB;
+ // Set the parent to the top of the visited stack. The stack includes us,
+ // and is 1 based, so we subtract to account for both of these.
+ if (I.getPathLength() > 1)
+ BBInfo.Parent = DT.Info[I.getPath(I.getPathLength() - 2)].DFSNum;
+ DT.Vertex.push_back(BB); // Vertex[n] = V;
+ }
+ return N;
}
template <class GraphT>
@@ -163,9 +158,13 @@ void Calculate(DominatorTreeBaseByGraphTraits<GraphTraits<NodeT>> &DT,
// Step #1: Number blocks in depth-first order and initialize variables used
// in later stages of the algorithm.
- for (unsigned i = 0, e = static_cast<unsigned>(DT.Roots.size());
- i != e; ++i)
- N = DFSPass<GraphT>(DT, DT.Roots[i], N);
+ if (DT.isPostDominator()){
+ for (unsigned i = 0, e = static_cast<unsigned>(DT.Roots.size());
+ i != e; ++i)
+ N = ReverseDFSPass<GraphT>(DT, DT.Roots[i], N);
+ } else {
+ N = DFSPass<GraphT>(DT, DT.Roots[0], N);
+ }
// it might be that some blocks did not get a DFS number (e.g., blocks of
// infinite loops). In these cases an artificial exit node is required.
@@ -201,17 +200,12 @@ void Calculate(DominatorTreeBaseByGraphTraits<GraphTraits<NodeT>> &DT,
// initialize the semi dominator to point to the parent node
WInfo.Semi = WInfo.Parent;
- typedef GraphTraits<Inverse<NodeT> > InvTraits;
- for (typename InvTraits::ChildIteratorType CI =
- InvTraits::child_begin(W),
- E = InvTraits::child_end(W); CI != E; ++CI) {
- typename InvTraits::NodeRef N = *CI;
- if (DT.Info.count(N)) { // Only if this predecessor is reachable!
+ for (const auto &N : inverse_children<NodeT>(W))
+ if (DT.Info.count(N)) { // Only if this predecessor is reachable!
unsigned SemiU = DT.Info[Eval<GraphT>(DT, N, i + 1)].Semi;
if (SemiU < WInfo.Semi)
WInfo.Semi = SemiU;
}
- }
// If V is a non-root vertex and sdom(V) = parent(V), then idom(V) is
// necessarily parent(V). In this case, set idom(V) here and avoid placing
diff --git a/include/llvm/Support/Host.h b/include/llvm/Support/Host.h
index 9df584c68c0d..89986fdae971 100644
--- a/include/llvm/Support/Host.h
+++ b/include/llvm/Support/Host.h
@@ -15,6 +15,7 @@
#define LLVM_SUPPORT_HOST_H
#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/MemoryBuffer.h"
#if defined(__linux__) || defined(__GNU__) || defined(__HAIKU__)
#include <endian.h>
@@ -32,9 +33,9 @@ namespace llvm {
namespace sys {
#if defined(BYTE_ORDER) && defined(BIG_ENDIAN) && BYTE_ORDER == BIG_ENDIAN
- static const bool IsBigEndianHost = true;
+constexpr bool IsBigEndianHost = true;
#else
- static const bool IsBigEndianHost = false;
+constexpr bool IsBigEndianHost = false;
#endif
static const bool IsLittleEndianHost = !IsBigEndianHost;
@@ -75,6 +76,13 @@ namespace sys {
/// from thread::hardware_concurrency(), which includes hyperthreads).
/// Returns -1 if unknown for the current host system.
int getHostNumPhysicalCores();
+
+ namespace detail {
+ /// Helper functions to extract HostCPUName from /proc/cpuinfo on linux.
+ StringRef getHostCPUNameForPowerPC(const StringRef &ProcCpuinfoContent);
+ StringRef getHostCPUNameForARM(const StringRef &ProcCpuinfoContent);
+ StringRef getHostCPUNameForS390x(const StringRef &ProcCpuinfoContent);
+ }
}
}
diff --git a/include/llvm/Support/LEB128.h b/include/llvm/Support/LEB128.h
index 6a95432ca2d9..ff775f3b7b36 100644
--- a/include/llvm/Support/LEB128.h
+++ b/include/llvm/Support/LEB128.h
@@ -20,7 +20,8 @@
namespace llvm {
/// Utility function to encode a SLEB128 value to an output stream.
-inline void encodeSLEB128(int64_t Value, raw_ostream &OS) {
+inline void encodeSLEB128(int64_t Value, raw_ostream &OS,
+ unsigned Padding = 0) {
bool More;
do {
uint8_t Byte = Value & 0x7f;
@@ -28,10 +29,45 @@ inline void encodeSLEB128(int64_t Value, raw_ostream &OS) {
Value >>= 7;
More = !((((Value == 0 ) && ((Byte & 0x40) == 0)) ||
((Value == -1) && ((Byte & 0x40) != 0))));
- if (More)
+ if (More || Padding != 0)
Byte |= 0x80; // Mark this byte to show that more bytes will follow.
OS << char(Byte);
} while (More);
+
+ // Pad with 0x80 and emit a terminating byte at the end.
+ if (Padding != 0) {
+ uint8_t PadValue = Value < 0 ? 0x7f : 0x00;
+ for (; Padding != 1; --Padding)
+ OS << char(PadValue | 0x80);
+ OS << char(PadValue);
+ }
+}
+
+/// Utility function to encode a SLEB128 value to a buffer. Returns
+/// the length in bytes of the encoded value.
+inline unsigned encodeSLEB128(int64_t Value, uint8_t *p,
+ unsigned Padding = 0) {
+ uint8_t *orig_p = p;
+ bool More;
+ do {
+ uint8_t Byte = Value & 0x7f;
+ // NOTE: this assumes that this signed shift is an arithmetic right shift.
+ Value >>= 7;
+ More = !((((Value == 0 ) && ((Byte & 0x40) == 0)) ||
+ ((Value == -1) && ((Byte & 0x40) != 0))));
+ if (More || Padding != 0)
+ Byte |= 0x80; // Mark this byte to show that more bytes will follow.
+ *p++ = Byte;
+ } while (More);
+
+ // Pad with 0x80 and emit a terminating byte at the end.
+ if (Padding != 0) {
+ uint8_t PadValue = Value < 0 ? 0x7f : 0x00;
+ for (; Padding != 1; --Padding)
+ *p++ = (PadValue | 0x80);
+ *p++ = PadValue;
+ }
+ return (unsigned)(p - orig_p);
}
/// Utility function to encode a ULEB128 value to an output stream.
@@ -77,11 +113,30 @@ inline unsigned encodeULEB128(uint64_t Value, uint8_t *p,
/// Utility function to decode a ULEB128 value.
-inline uint64_t decodeULEB128(const uint8_t *p, unsigned *n = nullptr) {
+inline uint64_t decodeULEB128(const uint8_t *p, unsigned *n = nullptr,
+ const uint8_t *end = nullptr,
+ const char **error = nullptr) {
const uint8_t *orig_p = p;
uint64_t Value = 0;
unsigned Shift = 0;
+ if(error)
+ *error = nullptr;
do {
+ if(end && p == end){
+ if(error)
+ *error = "malformed uleb128, extends past end";
+ if (n)
+ *n = (unsigned)(p - orig_p);
+ return 0;
+ }
+ uint64_t Slice = *p & 0x7f;
+ if(Shift >= 64 || Slice << Shift >> Shift != Slice){
+ if(error)
+ *error = "uleb128 too big for uint64";
+ if (n)
+ *n = (unsigned)(p - orig_p);
+ return 0;
+ }
Value += uint64_t(*p & 0x7f) << Shift;
Shift += 7;
} while (*p++ >= 128);
@@ -91,12 +146,21 @@ inline uint64_t decodeULEB128(const uint8_t *p, unsigned *n = nullptr) {
}
/// Utility function to decode a SLEB128 value.
-inline int64_t decodeSLEB128(const uint8_t *p, unsigned *n = nullptr) {
+inline int64_t decodeSLEB128(const uint8_t *p, unsigned *n = nullptr,
+ const uint8_t *end = nullptr,
+ const char **error = nullptr) {
const uint8_t *orig_p = p;
int64_t Value = 0;
unsigned Shift = 0;
uint8_t Byte;
do {
+ if(end && p == end){
+ if(error)
+ *error = "malformed sleb128, extends past end";
+ if (n)
+ *n = (unsigned)(p - orig_p);
+ return 0;
+ }
Byte = *p++;
Value |= ((Byte & 0x7f) << Shift);
Shift += 7;
diff --git a/include/llvm/Support/LowLevelTypeImpl.h b/include/llvm/Support/LowLevelTypeImpl.h
new file mode 100644
index 000000000000..02df4d806f13
--- /dev/null
+++ b/include/llvm/Support/LowLevelTypeImpl.h
@@ -0,0 +1,202 @@
+//== llvm/Support/LowLevelTypeImpl.h --------------------------- -*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+/// Implement a low-level type suitable for MachineInstr level instruction
+/// selection.
+///
+/// For a type attached to a MachineInstr, we only care about 2 details: total
+/// size and the number of vector lanes (if any). Accordingly, there are 4
+/// possible valid type-kinds:
+///
+/// * `sN` for scalars and aggregates
+/// * `<N x sM>` for vectors, which must have at least 2 elements.
+/// * `pN` for pointers
+///
+/// Other information required for correct selection is expected to be carried
+/// by the opcode, or non-type flags. For example the distinction between G_ADD
+/// and G_FADD for int/float or fast-math flags.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_LOWLEVELTYPEIMPL_H
+#define LLVM_SUPPORT_LOWLEVELTYPEIMPL_H
+
+#include <cassert>
+#include "llvm/ADT/DenseMapInfo.h"
+#include "llvm/CodeGen/MachineValueType.h"
+
+namespace llvm {
+
+class DataLayout;
+class Type;
+class raw_ostream;
+
+class LLT {
+public:
+ enum TypeKind : uint16_t {
+ Invalid,
+ Scalar,
+ Pointer,
+ Vector,
+ };
+
+ /// Get a low-level scalar or aggregate "bag of bits".
+ static LLT scalar(unsigned SizeInBits) {
+ assert(SizeInBits > 0 && "invalid scalar size");
+ return LLT{Scalar, 1, SizeInBits};
+ }
+
+ /// Get a low-level pointer in the given address space (defaulting to 0).
+ static LLT pointer(uint16_t AddressSpace, unsigned SizeInBits) {
+ return LLT{Pointer, AddressSpace, SizeInBits};
+ }
+
+ /// Get a low-level vector of some number of elements and element width.
+ /// \p NumElements must be at least 2.
+ static LLT vector(uint16_t NumElements, unsigned ScalarSizeInBits) {
+ assert(NumElements > 1 && "invalid number of vector elements");
+ return LLT{Vector, NumElements, ScalarSizeInBits};
+ }
+
+ /// Get a low-level vector of some number of elements and element type.
+ static LLT vector(uint16_t NumElements, LLT ScalarTy) {
+ assert(NumElements > 1 && "invalid number of vector elements");
+ assert(ScalarTy.isScalar() && "invalid vector element type");
+ return LLT{Vector, NumElements, ScalarTy.getSizeInBits()};
+ }
+
+ explicit LLT(TypeKind Kind, uint16_t NumElements, unsigned SizeInBits)
+ : SizeInBits(SizeInBits), ElementsOrAddrSpace(NumElements), Kind(Kind) {
+ assert((Kind != Vector || ElementsOrAddrSpace > 1) &&
+ "invalid number of vector elements");
+ }
+
+ explicit LLT() : SizeInBits(0), ElementsOrAddrSpace(0), Kind(Invalid) {}
+
+ explicit LLT(MVT VT);
+
+ bool isValid() const { return Kind != Invalid; }
+
+ bool isScalar() const { return Kind == Scalar; }
+
+ bool isPointer() const { return Kind == Pointer; }
+
+ bool isVector() const { return Kind == Vector; }
+
+ /// Returns the number of elements in a vector LLT. Must only be called on
+ /// vector types.
+ uint16_t getNumElements() const {
+ assert(isVector() && "cannot get number of elements on scalar/aggregate");
+ return ElementsOrAddrSpace;
+ }
+
+ /// Returns the total size of the type. Must only be called on sized types.
+ unsigned getSizeInBits() const {
+ if (isPointer() || isScalar())
+ return SizeInBits;
+ return SizeInBits * ElementsOrAddrSpace;
+ }
+
+ unsigned getScalarSizeInBits() const {
+ return SizeInBits;
+ }
+
+ unsigned getAddressSpace() const {
+ assert(isPointer() && "cannot get address space of non-pointer type");
+ return ElementsOrAddrSpace;
+ }
+
+ /// Returns the vector's element type. Only valid for vector types.
+ LLT getElementType() const {
+ assert(isVector() && "cannot get element type of scalar/aggregate");
+ return scalar(SizeInBits);
+ }
+
+ /// Get a low-level type with half the size of the original, by halving the
+ /// size of the scalar type involved. For example `s32` will become `s16`,
+ /// `<2 x s32>` will become `<2 x s16>`.
+ LLT halfScalarSize() const {
+ assert(!isPointer() && getScalarSizeInBits() > 1 &&
+ getScalarSizeInBits() % 2 == 0 && "cannot half size of this type");
+ return LLT{Kind, ElementsOrAddrSpace, SizeInBits / 2};
+ }
+
+ /// Get a low-level type with twice the size of the original, by doubling the
+ /// size of the scalar type involved. For example `s32` will become `s64`,
+ /// `<2 x s32>` will become `<2 x s64>`.
+ LLT doubleScalarSize() const {
+ assert(!isPointer() && "cannot change size of this type");
+ return LLT{Kind, ElementsOrAddrSpace, SizeInBits * 2};
+ }
+
+ /// Get a low-level type with half the size of the original, by halving the
+ /// number of vector elements of the scalar type involved. The source must be
+ /// a vector type with an even number of elements. For example `<4 x s32>`
+ /// will become `<2 x s32>`, `<2 x s32>` will become `s32`.
+ LLT halfElements() const {
+ assert(isVector() && ElementsOrAddrSpace % 2 == 0 &&
+ "cannot half odd vector");
+ if (ElementsOrAddrSpace == 2)
+ return scalar(SizeInBits);
+
+ return LLT{Vector, static_cast<uint16_t>(ElementsOrAddrSpace / 2),
+ SizeInBits};
+ }
+
+ /// Get a low-level type with twice the size of the original, by doubling the
+ /// number of vector elements of the scalar type involved. The source must be
+ /// a vector type. For example `<2 x s32>` will become `<4 x s32>`. Doubling
+ /// the number of elements in sN produces <2 x sN>.
+ LLT doubleElements() const {
+ assert(!isPointer() && "cannot double elements in pointer");
+ return LLT{Vector, static_cast<uint16_t>(ElementsOrAddrSpace * 2),
+ SizeInBits};
+ }
+
+ void print(raw_ostream &OS) const;
+
+ bool operator==(const LLT &RHS) const {
+ return Kind == RHS.Kind && SizeInBits == RHS.SizeInBits &&
+ ElementsOrAddrSpace == RHS.ElementsOrAddrSpace;
+ }
+
+ bool operator!=(const LLT &RHS) const { return !(*this == RHS); }
+
+ friend struct DenseMapInfo<LLT>;
+private:
+ unsigned SizeInBits;
+ uint16_t ElementsOrAddrSpace;
+ TypeKind Kind;
+};
+
+inline raw_ostream& operator<<(raw_ostream &OS, const LLT &Ty) {
+ Ty.print(OS);
+ return OS;
+}
+
+template<> struct DenseMapInfo<LLT> {
+ static inline LLT getEmptyKey() {
+ return LLT{LLT::Invalid, 0, -1u};
+ }
+ static inline LLT getTombstoneKey() {
+ return LLT{LLT::Invalid, 0, -2u};
+ }
+ static inline unsigned getHashValue(const LLT &Ty) {
+ uint64_t Val = ((uint64_t)Ty.SizeInBits << 32) |
+ ((uint64_t)Ty.ElementsOrAddrSpace << 16) | (uint64_t)Ty.Kind;
+ return DenseMapInfo<uint64_t>::getHashValue(Val);
+ }
+ static bool isEqual(const LLT &LHS, const LLT &RHS) {
+ return LHS == RHS;
+ }
+};
+
+}
+
+#endif // LLVM_SUPPORT_LOWLEVELTYPEIMPL_H
diff --git a/include/llvm/Support/MD5.h b/include/llvm/Support/MD5.h
index eb181bfe8a5c..2c0dc76485f8 100644
--- a/include/llvm/Support/MD5.h
+++ b/include/llvm/Support/MD5.h
@@ -1,4 +1,4 @@
-/*
+/* -*- C++ -*-
* This code is derived from (original license follows):
*
* This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
@@ -29,24 +29,55 @@
#define LLVM_SUPPORT_MD5_H
#include "llvm/ADT/SmallString.h"
-#include "llvm/Support/DataTypes.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Endian.h"
#include <array>
+#include <cstdint>
namespace llvm {
+
template <typename T> class ArrayRef;
class MD5 {
// Any 32-bit or wider unsigned integer data type will do.
typedef uint32_t MD5_u32plus;
- MD5_u32plus a, b, c, d;
- MD5_u32plus hi, lo;
+ MD5_u32plus a = 0x67452301;
+ MD5_u32plus b = 0xefcdab89;
+ MD5_u32plus c = 0x98badcfe;
+ MD5_u32plus d = 0x10325476;
+ MD5_u32plus hi = 0;
+ MD5_u32plus lo = 0;
uint8_t buffer[64];
MD5_u32plus block[16];
public:
- typedef uint8_t MD5Result[16];
+ struct MD5Result {
+ std::array<uint8_t, 16> Bytes;
+
+ operator std::array<uint8_t, 16>() const { return Bytes; }
+
+ const uint8_t &operator[](size_t I) const { return Bytes[I]; }
+ uint8_t &operator[](size_t I) { return Bytes[I]; }
+
+ SmallString<32> digest() const;
+
+ uint64_t low() const {
+ // Our MD5 implementation returns the result in little endian, so the low
+ // word is first.
+ using namespace support;
+ return endian::read<uint64_t, little, unaligned>(Bytes.data());
+ }
+
+ uint64_t high() const {
+ using namespace support;
+ return endian::read<uint64_t, little, unaligned>(Bytes.data() + 8);
+ }
+ std::pair<uint64_t, uint64_t> words() const {
+ using namespace support;
+ return std::make_pair(high(), low());
+ }
+ };
MD5();
@@ -70,18 +101,22 @@ private:
const uint8_t *body(ArrayRef<uint8_t> Data);
};
+inline bool operator==(const MD5::MD5Result &LHS, const MD5::MD5Result &RHS) {
+ return LHS.Bytes == RHS.Bytes;
+}
+
/// Helper to compute and return lower 64 bits of the given string's MD5 hash.
inline uint64_t MD5Hash(StringRef Str) {
+ using namespace support;
+
MD5 Hash;
Hash.update(Str);
- llvm::MD5::MD5Result Result;
+ MD5::MD5Result Result;
Hash.final(Result);
- // Return the least significant 8 bytes. Our MD5 implementation returns the
- // result in little endian, so we may need to swap bytes.
- using namespace llvm::support;
- return endian::read<uint64_t, little, unaligned>(Result);
+ // Return the least significant word.
+ return Result.low();
}
-}
+} // end namespace llvm
-#endif
+#endif // LLVM_SUPPORT_MD5_H
diff --git a/include/llvm/Support/MachO.def b/include/llvm/Support/MachO.def
index 57522897d0fc..95de48d2b19e 100644
--- a/include/llvm/Support/MachO.def
+++ b/include/llvm/Support/MachO.def
@@ -73,6 +73,8 @@ HANDLE_LOAD_COMMAND(LC_LINKER_OPTION, 0x0000002Du, linker_option_command)
HANDLE_LOAD_COMMAND(LC_LINKER_OPTIMIZATION_HINT, 0x0000002Eu, linkedit_data_command)
HANDLE_LOAD_COMMAND(LC_VERSION_MIN_TVOS, 0x0000002Fu, version_min_command)
HANDLE_LOAD_COMMAND(LC_VERSION_MIN_WATCHOS, 0x00000030u, version_min_command)
+HANDLE_LOAD_COMMAND(LC_NOTE, 0x00000031u, note_command)
+HANDLE_LOAD_COMMAND(LC_BUILD_VERSION, 0x00000032u, build_version_command)
#endif
@@ -109,6 +111,8 @@ LOAD_COMMAND_STRUCT(thread_command)
LOAD_COMMAND_STRUCT(twolevel_hints_command)
LOAD_COMMAND_STRUCT(uuid_command)
LOAD_COMMAND_STRUCT(version_min_command)
+LOAD_COMMAND_STRUCT(note_command)
+LOAD_COMMAND_STRUCT(build_version_command)
#endif
diff --git a/include/llvm/Support/MachO.h b/include/llvm/Support/MachO.h
index 2b23c0f86448..3d704292c260 100644
--- a/include/llvm/Support/MachO.h
+++ b/include/llvm/Support/MachO.h
@@ -487,6 +487,22 @@ namespace llvm {
VM_PROT_EXECUTE = 0x4
};
+ // Values for platform field in build_version_command.
+ enum {
+ PLATFORM_MACOS = 1,
+ PLATFORM_IOS = 2,
+ PLATFORM_TVOS = 3,
+ PLATFORM_WATCHOS = 4,
+ PLATFORM_BRIDGEOS = 5
+ };
+
+ // Values for tools enum in build_tool_version.
+ enum {
+ TOOL_CLANG = 1,
+ TOOL_SWIFT = 2,
+ TOOL_LD = 3
+ };
+
// Structs from <mach-o/loader.h>
struct mach_header {
@@ -819,6 +835,29 @@ namespace llvm {
uint32_t sdk; // X.Y.Z is encoded in nibbles xxxx.yy.zz
};
+ struct note_command {
+ uint32_t cmd; // LC_NOTE
+ uint32_t cmdsize; // sizeof(struct note_command)
+ char data_owner[16]; // owner name for this LC_NOTE
+ uint64_t offset; // file offset of this data
+ uint64_t size; // length of data region
+ };
+
+ struct build_tool_version {
+ uint32_t tool; // enum for the tool
+ uint32_t version; // version of the tool
+ };
+
+ struct build_version_command {
+ uint32_t cmd; // LC_BUILD_VERSION
+ uint32_t cmdsize; // sizeof(struct build_version_command) +
+ // ntools * sizeof(struct build_tool_version)
+ uint32_t platform; // platform
+ uint32_t minos; // X.Y.Z is encoded in nibbles xxxx.yy.zz
+ uint32_t sdk; // X.Y.Z is encoded in nibbles xxxx.yy.zz
+ uint32_t ntools; // number of tool entries following this
+ };
+
struct dyld_info_command {
uint32_t cmd;
uint32_t cmdsize;
@@ -1266,6 +1305,27 @@ namespace llvm {
sys::swapByteOrder(C.sdk);
}
+ inline void swapStruct(note_command &C) {
+ sys::swapByteOrder(C.cmd);
+ sys::swapByteOrder(C.cmdsize);
+ sys::swapByteOrder(C.offset);
+ sys::swapByteOrder(C.size);
+ }
+
+ inline void swapStruct(build_version_command&C) {
+ sys::swapByteOrder(C.cmd);
+ sys::swapByteOrder(C.cmdsize);
+ sys::swapByteOrder(C.platform);
+ sys::swapByteOrder(C.minos);
+ sys::swapByteOrder(C.sdk);
+ sys::swapByteOrder(C.ntools);
+ }
+
+ inline void swapStruct(build_tool_version&C) {
+ sys::swapByteOrder(C.tool);
+ sys::swapByteOrder(C.version);
+ }
+
inline void swapStruct(data_in_code_entry &C) {
sys::swapByteOrder(C.offset);
sys::swapByteOrder(C.length);
@@ -1470,6 +1530,25 @@ namespace llvm {
CPU_SUBTYPE_MC98601 = CPU_SUBTYPE_POWERPC_601
};
+ struct x86_thread_state32_t {
+ uint32_t eax;
+ uint32_t ebx;
+ uint32_t ecx;
+ uint32_t edx;
+ uint32_t edi;
+ uint32_t esi;
+ uint32_t ebp;
+ uint32_t esp;
+ uint32_t ss;
+ uint32_t eflags;
+ uint32_t eip;
+ uint32_t cs;
+ uint32_t ds;
+ uint32_t es;
+ uint32_t fs;
+ uint32_t gs;
+ };
+
struct x86_thread_state64_t {
uint64_t rax;
uint64_t rbx;
@@ -1599,6 +1678,25 @@ namespace llvm {
uint64_t faultvaddr;
};
+ inline void swapStruct(x86_thread_state32_t &x) {
+ sys::swapByteOrder(x.eax);
+ sys::swapByteOrder(x.ebx);
+ sys::swapByteOrder(x.ecx);
+ sys::swapByteOrder(x.edx);
+ sys::swapByteOrder(x.edi);
+ sys::swapByteOrder(x.esi);
+ sys::swapByteOrder(x.ebp);
+ sys::swapByteOrder(x.esp);
+ sys::swapByteOrder(x.ss);
+ sys::swapByteOrder(x.eflags);
+ sys::swapByteOrder(x.eip);
+ sys::swapByteOrder(x.cs);
+ sys::swapByteOrder(x.ds);
+ sys::swapByteOrder(x.es);
+ sys::swapByteOrder(x.fs);
+ sys::swapByteOrder(x.gs);
+ }
+
inline void swapStruct(x86_thread_state64_t &x) {
sys::swapByteOrder(x.rax);
sys::swapByteOrder(x.rbx);
@@ -1656,6 +1754,7 @@ namespace llvm {
x86_state_hdr_t tsh;
union {
x86_thread_state64_t ts64;
+ x86_thread_state32_t ts32;
} uts;
};
@@ -1711,6 +1810,9 @@ namespace llvm {
swapStruct(x.ues.es64);
}
+ const uint32_t x86_THREAD_STATE32_COUNT =
+ sizeof(x86_thread_state32_t) / sizeof(uint32_t);
+
const uint32_t x86_THREAD_STATE64_COUNT =
sizeof(x86_thread_state64_t) / sizeof(uint32_t);
const uint32_t x86_FLOAT_STATE64_COUNT =
diff --git a/include/llvm/Support/MathExtras.h b/include/llvm/Support/MathExtras.h
index 77970f487112..19380b23d9d2 100644
--- a/include/llvm/Support/MathExtras.h
+++ b/include/llvm/Support/MathExtras.h
@@ -112,7 +112,7 @@ 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);
+ return llvm::detail::TrailingZerosCounter<T, sizeof(T)>::count(Val, ZB);
}
namespace detail {
@@ -181,7 +181,7 @@ 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);
+ return llvm::detail::LeadingZerosCounter<T, sizeof(T)>::count(Val, ZB);
}
/// \brief Get the index of the first set bit starting from the least
diff --git a/include/llvm/Support/MemoryBuffer.h b/include/llvm/Support/MemoryBuffer.h
index f739d19907b0..e8bdc3e89fa7 100644
--- a/include/llvm/Support/MemoryBuffer.h
+++ b/include/llvm/Support/MemoryBuffer.h
@@ -69,12 +69,12 @@ public:
/// means that the client knows that the file exists and that it has the
/// specified size.
///
- /// \param IsVolatileSize Set to true to indicate that the file size may be
- /// changing, e.g. when libclang tries to parse while the user is
- /// editing/updating the file.
+ /// \param IsVolatile Set to true to indicate that the contents of the file
+ /// can change outside the user's control, e.g. when libclang tries to parse
+ /// while the user is editing/updating the file or if the file is on an NFS.
static ErrorOr<std::unique_ptr<MemoryBuffer>>
getFile(const Twine &Filename, int64_t FileSize = -1,
- bool RequiresNullTerminator = true, bool IsVolatileSize = false);
+ bool RequiresNullTerminator = true, bool IsVolatile = false);
/// Read all of the specified file into a MemoryBuffer as a stream
/// (i.e. until EOF reached). This is useful for special files that
@@ -87,17 +87,17 @@ public:
/// Since this is in the middle of a file, the buffer is not null terminated.
static ErrorOr<std::unique_ptr<MemoryBuffer>>
getOpenFileSlice(int FD, const Twine &Filename, uint64_t MapSize,
- int64_t Offset);
+ int64_t Offset, bool IsVolatile = false);
/// Given an already-open file descriptor, read the file and return a
/// MemoryBuffer.
///
- /// \param IsVolatileSize Set to true to indicate that the file size may be
- /// changing, e.g. when libclang tries to parse while the user is
- /// editing/updating the file.
+ /// \param IsVolatile Set to true to indicate that the contents of the file
+ /// can change outside the user's control, e.g. when libclang tries to parse
+ /// while the user is editing/updating the file or if the file is on an NFS.
static ErrorOr<std::unique_ptr<MemoryBuffer>>
getOpenFile(int FD, const Twine &Filename, uint64_t FileSize,
- bool RequiresNullTerminator = true, bool IsVolatileSize = false);
+ bool RequiresNullTerminator = true, bool IsVolatile = false);
/// Open the specified memory range as a MemoryBuffer. Note that InputData
/// must be null terminated if RequiresNullTerminator is true.
@@ -136,7 +136,7 @@ public:
/// Map a subrange of the specified file as a MemoryBuffer.
static ErrorOr<std::unique_ptr<MemoryBuffer>>
- getFileSlice(const Twine &Filename, uint64_t MapSize, uint64_t Offset);
+ getFileSlice(const Twine &Filename, uint64_t MapSize, uint64_t Offset, bool IsVolatile = false);
//===--------------------------------------------------------------------===//
// Provided for performance analysis.
diff --git a/include/llvm/Support/Path.h b/include/llvm/Support/Path.h
index 2bbcef0c293f..6ac51195519e 100644
--- a/include/llvm/Support/Path.h
+++ b/include/llvm/Support/Path.h
@@ -24,6 +24,8 @@ namespace llvm {
namespace sys {
namespace path {
+enum class Style { windows, posix, native };
+
/// @name Lexical Component Iterator
/// @{
@@ -51,9 +53,10 @@ class const_iterator
StringRef Path; ///< The entire path.
StringRef Component; ///< The current component. Not necessarily in Path.
size_t Position; ///< The iterators current position within Path.
+ Style S; ///< The path style to use.
// An end iterator has Position = Path.size() + 1.
- friend const_iterator begin(StringRef path);
+ friend const_iterator begin(StringRef path, Style style);
friend const_iterator end(StringRef path);
public:
@@ -77,8 +80,9 @@ class reverse_iterator
StringRef Path; ///< The entire path.
StringRef Component; ///< The current component. Not necessarily in Path.
size_t Position; ///< The iterators current position within Path.
+ Style S; ///< The path style to use.
- friend reverse_iterator rbegin(StringRef path);
+ friend reverse_iterator rbegin(StringRef path, Style style);
friend reverse_iterator rend(StringRef path);
public:
@@ -95,7 +99,7 @@ public:
/// @brief Get begin iterator over \a path.
/// @param path Input path.
/// @returns Iterator initialized with the first component of \a path.
-const_iterator begin(StringRef path);
+const_iterator begin(StringRef path, Style style = Style::native);
/// @brief Get end iterator over \a path.
/// @param path Input path.
@@ -105,7 +109,7 @@ const_iterator end(StringRef path);
/// @brief Get reverse begin iterator over \a path.
/// @param path Input path.
/// @returns Iterator initialized with the first reverse component of \a path.
-reverse_iterator rbegin(StringRef path);
+reverse_iterator rbegin(StringRef path, Style style = Style::native);
/// @brief Get reverse end iterator over \a path.
/// @param path Input path.
@@ -126,7 +130,7 @@ reverse_iterator rend(StringRef path);
/// @endcode
///
/// @param path A path that is modified to not have a file component.
-void remove_filename(SmallVectorImpl<char> &path);
+void remove_filename(SmallVectorImpl<char> &path, Style style = Style::native);
/// @brief Replace the file extension of \a path with \a extension.
///
@@ -140,7 +144,8 @@ void remove_filename(SmallVectorImpl<char> &path);
/// @param extension The extension to be added. It may be empty. It may also
/// optionally start with a '.', if it does not, one will be
/// prepended.
-void replace_extension(SmallVectorImpl<char> &path, const Twine &extension);
+void replace_extension(SmallVectorImpl<char> &path, const Twine &extension,
+ Style style = Style::native);
/// @brief Replace matching path prefix with another path.
///
@@ -156,8 +161,8 @@ void replace_extension(SmallVectorImpl<char> &path, const Twine &extension);
/// @param OldPrefix The path prefix to strip from \a Path.
/// @param NewPrefix The path prefix to replace \a NewPrefix with.
void replace_path_prefix(SmallVectorImpl<char> &Path,
- const StringRef &OldPrefix,
- const StringRef &NewPrefix);
+ const StringRef &OldPrefix, const StringRef &NewPrefix,
+ Style style = Style::native);
/// @brief Append to path.
///
@@ -174,6 +179,9 @@ void append(SmallVectorImpl<char> &path, const Twine &a,
const Twine &c = "",
const Twine &d = "");
+void append(SmallVectorImpl<char> &path, Style style, const Twine &a,
+ const Twine &b = "", const Twine &c = "", const Twine &d = "");
+
/// @brief Append to path.
///
/// @code
@@ -185,8 +193,8 @@ void append(SmallVectorImpl<char> &path, const Twine &a,
/// @param path Set to \a path + [\a begin, \a end).
/// @param begin Start of components to append.
/// @param end One past the end of components to append.
-void append(SmallVectorImpl<char> &path,
- const_iterator begin, const_iterator end);
+void append(SmallVectorImpl<char> &path, const_iterator begin,
+ const_iterator end, Style style = Style::native);
/// @}
/// @name Transforms (or some other better name)
@@ -198,14 +206,15 @@ void append(SmallVectorImpl<char> &path,
///
/// @param path A path that is transformed to native format.
/// @param result Holds the result of the transformation.
-void native(const Twine &path, SmallVectorImpl<char> &result);
+void native(const Twine &path, SmallVectorImpl<char> &result,
+ Style style = Style::native);
/// Convert path to the native form in place. This is used to give paths to
/// users and operating system calls in the platform's normal way. For example,
/// on Windows all '/' are converted to '\'.
///
/// @param path A path that is transformed to native format.
-void native(SmallVectorImpl<char> &path);
+void native(SmallVectorImpl<char> &path, Style style = Style::native);
/// @brief Replaces backslashes with slashes if Windows.
///
@@ -213,7 +222,7 @@ void native(SmallVectorImpl<char> &path);
/// @result The result of replacing backslashes with forward slashes if Windows.
/// On Unix, this function is a no-op because backslashes are valid path
/// chracters.
-std::string convert_to_slash(StringRef path);
+std::string convert_to_slash(StringRef path, Style style = Style::native);
/// @}
/// @name Lexical Observers
@@ -229,7 +238,7 @@ std::string convert_to_slash(StringRef path);
///
/// @param path Input path.
/// @result The root name of \a path if it has one, otherwise "".
-StringRef root_name(StringRef path);
+StringRef root_name(StringRef path, Style style = Style::native);
/// @brief Get root directory.
///
@@ -242,7 +251,7 @@ StringRef root_name(StringRef path);
/// @param path Input path.
/// @result The root directory of \a path if it has one, otherwise
/// "".
-StringRef root_directory(StringRef path);
+StringRef root_directory(StringRef path, Style style = Style::native);
/// @brief Get root path.
///
@@ -250,7 +259,7 @@ StringRef root_directory(StringRef path);
///
/// @param path Input path.
/// @result The root path of \a path if it has one, otherwise "".
-StringRef root_path(StringRef path);
+StringRef root_path(StringRef path, Style style = Style::native);
/// @brief Get relative path.
///
@@ -262,7 +271,7 @@ StringRef root_path(StringRef path);
///
/// @param path Input path.
/// @result The path starting after root_path if one exists, otherwise "".
-StringRef relative_path(StringRef path);
+StringRef relative_path(StringRef path, Style style = Style::native);
/// @brief Get parent path.
///
@@ -274,7 +283,7 @@ StringRef relative_path(StringRef path);
///
/// @param path Input path.
/// @result The parent path of \a path if one exists, otherwise "".
-StringRef parent_path(StringRef path);
+StringRef parent_path(StringRef path, Style style = Style::native);
/// @brief Get filename.
///
@@ -288,7 +297,7 @@ StringRef parent_path(StringRef path);
/// @param path Input path.
/// @result The filename part of \a path. This is defined as the last component
/// of \a path.
-StringRef filename(StringRef path);
+StringRef filename(StringRef path, Style style = Style::native);
/// @brief Get stem.
///
@@ -306,7 +315,7 @@ StringRef filename(StringRef path);
///
/// @param path Input path.
/// @result The stem of \a path.
-StringRef stem(StringRef path);
+StringRef stem(StringRef path, Style style = Style::native);
/// @brief Get extension.
///
@@ -322,18 +331,18 @@ StringRef stem(StringRef path);
///
/// @param path Input path.
/// @result The extension of \a path.
-StringRef extension(StringRef path);
+StringRef extension(StringRef path, Style style = Style::native);
/// @brief Check whether the given char is a path separator on the host OS.
///
/// @param value a character
/// @result true if \a value is a path separator character on the host OS
-bool is_separator(char value);
+bool is_separator(char value, Style style = Style::native);
/// @brief Return the preferred separator for this platform.
///
/// @result StringRef of the preferred separator, null-terminated.
-StringRef get_separator();
+StringRef get_separator(Style style = Style::native);
/// @brief Get the typical temporary directory for the system, e.g.,
/// "/var/tmp" or "C:/TEMP"
@@ -374,7 +383,7 @@ bool user_cache_directory(SmallVectorImpl<char> &Result, const Twine &Path1,
///
/// @param path Input path.
/// @result True if the path has a root name, false otherwise.
-bool has_root_name(const Twine &path);
+bool has_root_name(const Twine &path, Style style = Style::native);
/// @brief Has root directory?
///
@@ -382,7 +391,7 @@ bool has_root_name(const Twine &path);
///
/// @param path Input path.
/// @result True if the path has a root directory, false otherwise.
-bool has_root_directory(const Twine &path);
+bool has_root_directory(const Twine &path, Style style = Style::native);
/// @brief Has root path?
///
@@ -390,7 +399,7 @@ bool has_root_directory(const Twine &path);
///
/// @param path Input path.
/// @result True if the path has a root path, false otherwise.
-bool has_root_path(const Twine &path);
+bool has_root_path(const Twine &path, Style style = Style::native);
/// @brief Has relative path?
///
@@ -398,7 +407,7 @@ bool has_root_path(const Twine &path);
///
/// @param path Input path.
/// @result True if the path has a relative path, false otherwise.
-bool has_relative_path(const Twine &path);
+bool has_relative_path(const Twine &path, Style style = Style::native);
/// @brief Has parent path?
///
@@ -406,7 +415,7 @@ bool has_relative_path(const Twine &path);
///
/// @param path Input path.
/// @result True if the path has a parent path, false otherwise.
-bool has_parent_path(const Twine &path);
+bool has_parent_path(const Twine &path, Style style = Style::native);
/// @brief Has filename?
///
@@ -414,7 +423,7 @@ bool has_parent_path(const Twine &path);
///
/// @param path Input path.
/// @result True if the path has a filename, false otherwise.
-bool has_filename(const Twine &path);
+bool has_filename(const Twine &path, Style style = Style::native);
/// @brief Has stem?
///
@@ -422,7 +431,7 @@ bool has_filename(const Twine &path);
///
/// @param path Input path.
/// @result True if the path has a stem, false otherwise.
-bool has_stem(const Twine &path);
+bool has_stem(const Twine &path, Style style = Style::native);
/// @brief Has extension?
///
@@ -430,25 +439,25 @@ bool has_stem(const Twine &path);
///
/// @param path Input path.
/// @result True if the path has a extension, false otherwise.
-bool has_extension(const Twine &path);
+bool has_extension(const Twine &path, Style style = Style::native);
/// @brief Is path absolute?
///
/// @param path Input path.
/// @result True if the path is absolute, false if it is not.
-bool is_absolute(const Twine &path);
+bool is_absolute(const Twine &path, Style style = Style::native);
/// @brief Is path relative?
///
/// @param path Input path.
/// @result True if the path is relative, false if it is not.
-bool is_relative(const Twine &path);
+bool is_relative(const Twine &path, Style style = Style::native);
/// @brief Remove redundant leading "./" pieces and consecutive separators.
///
/// @param path Input path.
/// @result The cleaned-up \a path.
-StringRef remove_leading_dotslash(StringRef path);
+StringRef remove_leading_dotslash(StringRef path, Style style = Style::native);
/// @brief In-place remove any './' and optionally '../' components from a path.
///
@@ -456,7 +465,8 @@ StringRef remove_leading_dotslash(StringRef path);
/// @param remove_dot_dot specify if '../' (except for leading "../") should be
/// removed
/// @result True if path was changed
-bool remove_dots(SmallVectorImpl<char> &path, bool remove_dot_dot = false);
+bool remove_dots(SmallVectorImpl<char> &path, bool remove_dot_dot = false,
+ Style style = Style::native);
} // end namespace path
} // end namespace sys
diff --git a/include/llvm/Support/PointerLikeTypeTraits.h b/include/llvm/Support/PointerLikeTypeTraits.h
index 9ff894edbeb0..521a49684e45 100644
--- a/include/llvm/Support/PointerLikeTypeTraits.h
+++ b/include/llvm/Support/PointerLikeTypeTraits.h
@@ -60,6 +60,20 @@ public:
enum { NumLowBitsAvailable = 2 };
};
+// Provide PointerLikeTypeTraits for const things.
+template <typename T> class PointerLikeTypeTraits<const T> {
+ typedef PointerLikeTypeTraits<T> NonConst;
+
+public:
+ static inline const void *getAsVoidPointer(const T P) {
+ return NonConst::getAsVoidPointer(P);
+ }
+ static inline const T getFromVoidPointer(const void *P) {
+ return NonConst::getFromVoidPointer(const_cast<void *>(P));
+ }
+ enum { NumLowBitsAvailable = NonConst::NumLowBitsAvailable };
+};
+
// Provide PointerLikeTypeTraits for const pointers.
template <typename T> class PointerLikeTypeTraits<const T *> {
typedef PointerLikeTypeTraits<T *> NonConst;
diff --git a/include/llvm/Support/RWMutex.h b/include/llvm/Support/RWMutex.h
index e4736b8e24eb..85f4fc09fb87 100644
--- a/include/llvm/Support/RWMutex.h
+++ b/include/llvm/Support/RWMutex.h
@@ -14,7 +14,7 @@
#ifndef LLVM_SUPPORT_RWMUTEX_H
#define LLVM_SUPPORT_RWMUTEX_H
-#include "llvm/Support/Compiler.h"
+#include "llvm/Config/llvm-config.h"
#include "llvm/Support/Threading.h"
#include <cassert>
@@ -32,6 +32,13 @@ namespace sys {
/// @brief Default Constructor.
explicit RWMutexImpl();
+ /// @}
+ /// @name Do Not Implement
+ /// @{
+ RWMutexImpl(const RWMutexImpl & original) = delete;
+ RWMutexImpl &operator=(const RWMutexImpl &) = delete;
+ /// @}
+
/// Releases and removes the lock
/// @brief Destructor
~RWMutexImpl();
@@ -70,16 +77,8 @@ namespace sys {
/// @{
private:
#if defined(LLVM_ENABLE_THREADS) && LLVM_ENABLE_THREADS != 0
- void* data_; ///< We don't know what the data will be
+ void* data_ = nullptr; ///< We don't know what the data will be
#endif
-
- /// @}
- /// @name Do Not Implement
- /// @{
- private:
- RWMutexImpl(const RWMutexImpl & original) = delete;
- void operator=(const RWMutexImpl &) = delete;
- /// @}
};
/// SmartMutex - An R/W mutex with a compile time constant parameter that
@@ -93,6 +92,8 @@ namespace sys {
public:
explicit SmartRWMutex() = default;
+ SmartRWMutex(const SmartRWMutex<mt_only> & original) = delete;
+ SmartRWMutex<mt_only> &operator=(const SmartRWMutex<mt_only> &) = delete;
bool lock_shared() {
if (!mt_only || llvm_is_multithreaded())
@@ -136,10 +137,6 @@ namespace sys {
--writers;
return true;
}
-
- private:
- SmartRWMutex(const SmartRWMutex<mt_only> & original);
- void operator=(const SmartRWMutex<mt_only> &);
};
typedef SmartRWMutex<false> RWMutex;
diff --git a/include/llvm/Support/SMLoc.h b/include/llvm/Support/SMLoc.h
index eb3a1ba7db51..5b8be5505540 100644
--- a/include/llvm/Support/SMLoc.h
+++ b/include/llvm/Support/SMLoc.h
@@ -22,10 +22,10 @@ namespace llvm {
/// Represents a location in source code.
class SMLoc {
- const char *Ptr;
+ const char *Ptr = nullptr;
public:
- SMLoc() : Ptr(nullptr) {}
+ SMLoc() = default;
bool isValid() const { return Ptr != nullptr; }
diff --git a/include/llvm/Support/SourceMgr.h b/include/llvm/Support/SourceMgr.h
index bc7478e0d703..cb90d968c44c 100644
--- a/include/llvm/Support/SourceMgr.h
+++ b/include/llvm/Support/SourceMgr.h
@@ -17,18 +17,24 @@
#define LLVM_SUPPORT_SOURCEMGR_H
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/SMLoc.h"
+#include <algorithm>
+#include <cassert>
+#include <memory>
#include <string>
+#include <utility>
+#include <vector>
namespace llvm {
- class SourceMgr;
- class SMDiagnostic;
- class SMFixIt;
- class Twine;
- class raw_ostream;
+
+class raw_ostream;
+class SMDiagnostic;
+class SMFixIt;
/// This owns the files read by a parser, handles include stacks,
/// and handles diagnostic wrangling.
@@ -44,6 +50,7 @@ public:
/// register a function pointer+context as a diagnostic handler.
/// It gets called each time PrintMessage is invoked.
typedef void (*DiagHandlerTy)(const SMDiagnostic &, void *Context);
+
private:
struct SrcBuffer {
/// The memory buffer for the file.
@@ -61,18 +68,17 @@ private:
/// This is a cache for line number queries, its implementation is really
/// private to SourceMgr.cpp.
- mutable void *LineNoCache;
+ mutable void *LineNoCache = nullptr;
- DiagHandlerTy DiagHandler;
- void *DiagContext;
+ DiagHandlerTy DiagHandler = nullptr;
+ void *DiagContext = nullptr;
bool isValidBufferID(unsigned i) const { return i && i <= Buffers.size(); }
- SourceMgr(const SourceMgr&) = delete;
- void operator=(const SourceMgr&) = delete;
public:
- SourceMgr()
- : LineNoCache(nullptr), DiagHandler(nullptr), DiagContext(nullptr) {}
+ SourceMgr() = default;
+ SourceMgr(const SourceMgr &) = delete;
+ SourceMgr &operator=(const SourceMgr &) = delete;
~SourceMgr();
void setIncludeDirs(const std::vector<std::string> &Dirs) {
@@ -190,7 +196,6 @@ public:
void PrintIncludeStack(SMLoc IncludeLoc, raw_ostream &OS) const;
};
-
/// Represents a single fixit, a replacement of one range of text with another.
class SMFixIt {
SMRange Range;
@@ -222,33 +227,31 @@ public:
}
};
-
/// Instances of this class encapsulate one diagnostic report, allowing
/// printing to a raw_ostream as a caret diagnostic.
class SMDiagnostic {
- const SourceMgr *SM;
+ const SourceMgr *SM = nullptr;
SMLoc Loc;
std::string Filename;
- int LineNo, ColumnNo;
- SourceMgr::DiagKind Kind;
+ int LineNo = 0;
+ int ColumnNo = 0;
+ SourceMgr::DiagKind Kind = SourceMgr::DK_Error;
std::string Message, LineContents;
- std::vector<std::pair<unsigned, unsigned> > Ranges;
+ std::vector<std::pair<unsigned, unsigned>> Ranges;
SmallVector<SMFixIt, 4> FixIts;
public:
// Null diagnostic.
- SMDiagnostic()
- : SM(nullptr), LineNo(0), ColumnNo(0), Kind(SourceMgr::DK_Error) {}
+ SMDiagnostic() = default;
// Diagnostic with no location (e.g. file not found, command line arg error).
SMDiagnostic(StringRef filename, SourceMgr::DiagKind Knd, StringRef Msg)
- : SM(nullptr), Filename(filename), LineNo(-1), ColumnNo(-1), Kind(Knd),
- Message(Msg) {}
+ : Filename(filename), LineNo(-1), ColumnNo(-1), Kind(Knd), Message(Msg) {}
// Diagnostic with a location.
SMDiagnostic(const SourceMgr &sm, SMLoc L, StringRef FN,
int Line, int Col, SourceMgr::DiagKind Kind,
StringRef Msg, StringRef LineStr,
- ArrayRef<std::pair<unsigned,unsigned> > Ranges,
+ ArrayRef<std::pair<unsigned,unsigned>> Ranges,
ArrayRef<SMFixIt> FixIts = None);
const SourceMgr *getSourceMgr() const { return SM; }
@@ -259,9 +262,7 @@ public:
SourceMgr::DiagKind getKind() const { return Kind; }
StringRef getMessage() const { return Message; }
StringRef getLineContents() const { return LineContents; }
- ArrayRef<std::pair<unsigned, unsigned> > getRanges() const {
- return Ranges;
- }
+ ArrayRef<std::pair<unsigned, unsigned>> getRanges() const { return Ranges; }
void addFixIt(const SMFixIt &Hint) {
FixIts.push_back(Hint);
@@ -275,6 +276,6 @@ public:
bool ShowKindLabel = true) const;
};
-} // end llvm namespace
+} // end namespace llvm
-#endif
+#endif // LLVM_SUPPORT_SOURCEMGR_H
diff --git a/include/llvm/Support/TargetParser.h b/include/llvm/Support/TargetParser.h
index 63aeca7f4e1e..68e6b2765810 100644
--- a/include/llvm/Support/TargetParser.h
+++ b/include/llvm/Support/TargetParser.h
@@ -142,7 +142,7 @@ unsigned parseArchVersion(StringRef Arch);
} // namespace ARM
-// FIXME:This should be made into class design,to avoid dupplication.
+// FIXME:This should be made into class design,to avoid dupplication.
namespace AArch64 {
// Arch names.
diff --git a/include/llvm/Support/TargetRegistry.h b/include/llvm/Support/TargetRegistry.h
index 954cdb13abaf..bd68d2414487 100644
--- a/include/llvm/Support/TargetRegistry.h
+++ b/include/llvm/Support/TargetRegistry.h
@@ -1,4 +1,4 @@
-//===-- Support/TargetRegistry.h - Target Registration ----------*- C++ -*-===//
+//===- Support/TargetRegistry.h - Target Registration -----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -20,15 +20,22 @@
#define LLVM_SUPPORT_TARGETREGISTRY_H
#include "llvm-c/Disassembler.h"
+#include "llvm/ADT/iterator_range.h"
#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Support/CodeGen.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FormattedStream.h"
+#include <algorithm>
#include <cassert>
+#include <cstddef>
+#include <iterator>
#include <memory>
#include <string>
namespace llvm {
+
class AsmPrinter;
class MCAsmBackend;
class MCAsmInfo;
@@ -36,22 +43,20 @@ class MCAsmParser;
class MCCodeEmitter;
class MCContext;
class MCDisassembler;
-class MCInstrAnalysis;
class MCInstPrinter;
+class MCInstrAnalysis;
class MCInstrInfo;
class MCRegisterInfo;
+class MCRelocationInfo;
class MCStreamer;
class MCSubtargetInfo;
class MCSymbolizer;
-class MCRelocationInfo;
class MCTargetAsmParser;
class MCTargetOptions;
class MCTargetStreamer;
+class raw_pwrite_stream;
class TargetMachine;
class TargetOptions;
-class raw_ostream;
-class raw_pwrite_stream;
-class formatted_raw_ostream;
MCStreamer *createNullStreamer(MCContext &Ctx);
MCStreamer *createAsmStreamer(MCContext &Ctx,
@@ -68,6 +73,9 @@ MCStreamer *createMachOStreamer(MCContext &Ctx, MCAsmBackend &TAB,
raw_pwrite_stream &OS, MCCodeEmitter *CE,
bool RelaxAll, bool DWARFMustBeAtTheEnd,
bool LabelSections = false);
+MCStreamer *createWasmStreamer(MCContext &Ctx, MCAsmBackend &TAB,
+ raw_pwrite_stream &OS, MCCodeEmitter *CE,
+ bool RelaxAll);
MCRelocationInfo *createMCRelocationInfo(const Triple &TT, MCContext &Ctx);
@@ -143,6 +151,11 @@ public:
MCCodeEmitter *Emitter,
bool RelaxAll,
bool IncrementalLinkerCompatible);
+ typedef MCStreamer *(*WasmStreamerCtorTy)(const Triple &T, 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,
@@ -224,36 +237,33 @@ private:
MCCodeEmitterCtorTy MCCodeEmitterCtorFn;
// Construction functions for the various object formats, if registered.
- COFFStreamerCtorTy COFFStreamerCtorFn;
- MachOStreamerCtorTy MachOStreamerCtorFn;
- ELFStreamerCtorTy ELFStreamerCtorFn;
+ COFFStreamerCtorTy COFFStreamerCtorFn = nullptr;
+ MachOStreamerCtorTy MachOStreamerCtorFn = nullptr;
+ ELFStreamerCtorTy ELFStreamerCtorFn = nullptr;
+ WasmStreamerCtorTy WasmStreamerCtorFn = nullptr;
/// Construction function for this target's null TargetStreamer, if
/// registered (default = nullptr).
- NullTargetStreamerCtorTy NullTargetStreamerCtorFn;
+ NullTargetStreamerCtorTy NullTargetStreamerCtorFn = nullptr;
/// Construction function for this target's asm TargetStreamer, if
/// registered (default = nullptr).
- AsmTargetStreamerCtorTy AsmTargetStreamerCtorFn;
+ AsmTargetStreamerCtorTy AsmTargetStreamerCtorFn = nullptr;
/// Construction function for this target's obj TargetStreamer, if
/// registered (default = nullptr).
- ObjectTargetStreamerCtorTy ObjectTargetStreamerCtorFn;
+ ObjectTargetStreamerCtorTy ObjectTargetStreamerCtorFn = nullptr;
/// MCRelocationInfoCtorFn - Construction function for this target's
/// MCRelocationInfo, if registered (default = llvm::createMCRelocationInfo)
- MCRelocationInfoCtorTy MCRelocationInfoCtorFn;
+ MCRelocationInfoCtorTy MCRelocationInfoCtorFn = nullptr;
/// MCSymbolizerCtorFn - Construction function for this target's
/// MCSymbolizer, if registered (default = llvm::createMCSymbolizer)
- MCSymbolizerCtorTy MCSymbolizerCtorFn;
+ MCSymbolizerCtorTy MCSymbolizerCtorFn = nullptr;
public:
- Target()
- : COFFStreamerCtorFn(nullptr), MachOStreamerCtorFn(nullptr),
- ELFStreamerCtorFn(nullptr), NullTargetStreamerCtorFn(nullptr),
- AsmTargetStreamerCtorFn(nullptr), ObjectTargetStreamerCtorFn(nullptr),
- MCRelocationInfoCtorFn(nullptr), MCSymbolizerCtorFn(nullptr) {}
+ Target() = default;
/// @name Target Information
/// @{
@@ -461,6 +471,12 @@ public:
else
S = createELFStreamer(Ctx, TAB, OS, Emitter, RelaxAll);
break;
+ case Triple::Wasm:
+ if (WasmStreamerCtorFn)
+ S = WasmStreamerCtorFn(T, Ctx, TAB, OS, Emitter, RelaxAll);
+ else
+ S = createWasmStreamer(Ctx, TAB, OS, Emitter, RelaxAll);
+ break;
}
if (ObjectTargetStreamerCtorFn)
ObjectTargetStreamerCtorFn(*S, STI);
@@ -548,12 +564,14 @@ struct TargetRegistry {
class iterator
: public std::iterator<std::forward_iterator_tag, Target, ptrdiff_t> {
- const Target *Current;
- explicit iterator(Target *T) : Current(T) {}
friend struct TargetRegistry;
+ const Target *Current = nullptr;
+
+ explicit iterator(Target *T) : Current(T) {}
+
public:
- iterator() : Current(nullptr) {}
+ iterator() = default;
bool operator==(const iterator &x) const { return Current == x.Current; }
bool operator!=(const iterator &x) const { return !operator==(x); }
@@ -800,6 +818,10 @@ struct TargetRegistry {
T.ELFStreamerCtorFn = Fn;
}
+ static void RegisterWasmStreamer(Target &T, Target::WasmStreamerCtorTy Fn) {
+ T.WasmStreamerCtorFn = Fn;
+ }
+
static void RegisterNullTargetStreamer(Target &T,
Target::NullTargetStreamerCtorTy Fn) {
T.NullTargetStreamerCtorFn = Fn;
@@ -1147,6 +1169,7 @@ private:
return new MCCodeEmitterImpl();
}
};
-}
-#endif
+} // end namespace llvm
+
+#endif // LLVM_SUPPORT_TARGETREGISTRY_H
diff --git a/include/llvm/Support/ThreadPool.h b/include/llvm/Support/ThreadPool.h
index 665cec2465bf..f0e3ffa0999c 100644
--- a/include/llvm/Support/ThreadPool.h
+++ b/include/llvm/Support/ThreadPool.h
@@ -16,23 +16,8 @@
#include "llvm/Support/thread.h"
-#ifdef _MSC_VER
-// concrt.h depends on eh.h for __uncaught_exception declaration
-// even if we disable exceptions.
-#include <eh.h>
-
-// Disable warnings from ppltasks.h transitively included by <future>.
-#pragma warning(push)
-#pragma warning(disable:4530)
-#pragma warning(disable:4062)
-#endif
-
#include <future>
-#ifdef _MSC_VER
-#pragma warning(pop)
-#endif
-
#include <atomic>
#include <condition_variable>
#include <functional>
diff --git a/include/llvm/Support/Threading.h b/include/llvm/Support/Threading.h
index 4bef7ec8dd3f..03963a24c107 100644
--- a/include/llvm/Support/Threading.h
+++ b/include/llvm/Support/Threading.h
@@ -15,16 +15,22 @@
#ifndef LLVM_SUPPORT_THREADING_H
#define LLVM_SUPPORT_THREADING_H
+#include "llvm/ADT/SmallVector.h"
#include "llvm/Config/llvm-config.h" // for LLVM_ON_UNIX
#include "llvm/Support/Compiler.h"
#include <ciso646> // So we can check the C++ standard lib macros.
#include <functional>
+#if defined(_MSC_VER)
+// MSVC's call_once implementation worked since VS 2015, which is the minimum
+// supported version as of this writing.
+#define LLVM_THREADING_USE_STD_CALL_ONCE 1
+#elif defined(LLVM_ON_UNIX) && \
+ (defined(_LIBCPP_VERSION) || \
+ !(defined(__NetBSD__) || defined(__OpenBSD__) || defined(__ppc__)))
// std::call_once from libc++ is used on all Unix platforms. Other
// implementations like libstdc++ are known to have problems on NetBSD,
// OpenBSD and PowerPC.
-#if defined(LLVM_ON_UNIX) && (defined(_LIBCPP_VERSION) || \
- !(defined(__NetBSD__) || defined(__OpenBSD__) || defined(__ppc__)))
#define LLVM_THREADING_USE_STD_CALL_ONCE 1
#else
#define LLVM_THREADING_USE_STD_CALL_ONCE 0
@@ -37,41 +43,43 @@
#endif
namespace llvm {
- /// Returns true if LLVM is compiled with support for multi-threading, and
- /// false otherwise.
- bool llvm_is_multithreaded();
-
- /// llvm_execute_on_thread - Execute the given \p UserFn on a separate
- /// thread, passing it the provided \p UserData and waits for thread
- /// completion.
- ///
- /// This function does not guarantee that the code will actually be executed
- /// on a separate thread or honoring the requested stack size, but tries to do
- /// so where system support is available.
- ///
- /// \param UserFn - The callback to execute.
- /// \param UserData - An argument to pass to the callback function.
- /// \param RequestedStackSize - If non-zero, a requested size (in bytes) for
- /// the thread stack.
- void llvm_execute_on_thread(void (*UserFn)(void*), void *UserData,
- unsigned RequestedStackSize = 0);
+class Twine;
+
+/// Returns true if LLVM is compiled with support for multi-threading, and
+/// false otherwise.
+bool llvm_is_multithreaded();
+
+/// llvm_execute_on_thread - Execute the given \p UserFn on a separate
+/// thread, passing it the provided \p UserData and waits for thread
+/// completion.
+///
+/// This function does not guarantee that the code will actually be executed
+/// on a separate thread or honoring the requested stack size, but tries to do
+/// so where system support is available.
+///
+/// \param UserFn - The callback to execute.
+/// \param UserData - An argument to pass to the callback function.
+/// \param RequestedStackSize - If non-zero, a requested size (in bytes) for
+/// the thread stack.
+void llvm_execute_on_thread(void (*UserFn)(void *), void *UserData,
+ unsigned RequestedStackSize = 0);
#if LLVM_THREADING_USE_STD_CALL_ONCE
typedef std::once_flag once_flag;
- /// This macro is the only way you should define your once flag for LLVM's
- /// call_once.
-#define LLVM_DEFINE_ONCE_FLAG(flag) static once_flag flag
-
#else
enum InitStatus { Uninitialized = 0, Wait = 1, Done = 2 };
- typedef volatile sys::cas_flag once_flag;
- /// This macro is the only way you should define your once flag for LLVM's
- /// call_once.
-#define LLVM_DEFINE_ONCE_FLAG(flag) static once_flag flag = Uninitialized
+ /// \brief The llvm::once_flag structure
+ ///
+ /// This type is modeled after std::once_flag to use with llvm::call_once.
+ /// This structure must be used as an opaque object. It is a struct to force
+ /// autoinitialization and behave like std::once_flag.
+ struct once_flag {
+ volatile sys::cas_flag status = Uninitialized;
+ };
#endif
@@ -81,7 +89,7 @@ namespace llvm {
/// \code
/// void foo() {...};
/// ...
- /// LLVM_DEFINE_ONCE_FLAG(flag);
+ /// static once_flag flag;
/// call_once(flag, foo);
/// \endcode
///
@@ -95,24 +103,24 @@ namespace llvm {
#else
// For other platforms we use a generic (if brittle) version based on our
// atomics.
- sys::cas_flag old_val = sys::CompareAndSwap(&flag, Wait, Uninitialized);
+ sys::cas_flag old_val = sys::CompareAndSwap(&flag.status, Wait, Uninitialized);
if (old_val == Uninitialized) {
std::forward<Function>(F)(std::forward<Args>(ArgList)...);
sys::MemoryFence();
TsanIgnoreWritesBegin();
- TsanHappensBefore(&flag);
- flag = Done;
+ TsanHappensBefore(&flag.status);
+ flag.status = Done;
TsanIgnoreWritesEnd();
} else {
// Wait until any thread doing the call has finished.
- sys::cas_flag tmp = flag;
+ sys::cas_flag tmp = flag.status;
sys::MemoryFence();
while (tmp != Done) {
- tmp = flag;
+ tmp = flag.status;
sys::MemoryFence();
}
}
- TsanHappensAfter(&flag);
+ TsanHappensAfter(&flag.status);
#endif
}
@@ -122,6 +130,32 @@ namespace llvm {
/// thread::hardware_concurrency().
/// Returns 1 when LLVM is configured with LLVM_ENABLE_THREADS=OFF
unsigned heavyweight_hardware_concurrency();
+
+ /// \brief Return the current thread id, as used in various OS system calls.
+ /// Note that not all platforms guarantee that the value returned will be
+ /// unique across the entire system, so portable code should not assume
+ /// this.
+ uint64_t get_threadid();
+
+ /// \brief Get the maximum length of a thread name on this platform.
+ /// A value of 0 means there is no limit.
+ uint32_t get_max_thread_name_length();
+
+ /// \brief Set the name of the current thread. Setting a thread's name can
+ /// be helpful for enabling useful diagnostics under a debugger or when
+ /// logging. The level of support for setting a thread's name varies
+ /// wildly across operating systems, and we only make a best effort to
+ /// perform the operation on supported platforms. No indication of success
+ /// or failure is returned.
+ void set_thread_name(const Twine &Name);
+
+ /// \brief Get the name of the current thread. The level of support for
+ /// getting a thread's name varies wildly across operating systems, and it
+ /// is not even guaranteed that if you can successfully set a thread's name
+ /// that you can later get it back. This function is intended for diagnostic
+ /// purposes, and as with setting a thread's name no indication of whether
+ /// the operation succeeded or failed is returned.
+ void get_thread_name(SmallVectorImpl<char> &Name);
}
#endif
diff --git a/include/llvm/Support/Timer.h b/include/llvm/Support/Timer.h
index 80e8f13dccfe..198855ae0377 100644
--- a/include/llvm/Support/Timer.h
+++ b/include/llvm/Support/Timer.h
@@ -207,6 +207,9 @@ public:
/// This static method prints all timers and clears them all out.
static void printAll(raw_ostream &OS);
+ /// Prints all timers as JSON key/value pairs, and clears them all out.
+ static const char *printAllJSONValues(raw_ostream &OS, const char *delim);
+
/// Ensure global timer group lists are initialized. This function is mostly
/// used by the Statistic code to influence the construction and destruction
/// order of the global timer lists.
@@ -221,7 +224,6 @@ private:
void printJSONValue(raw_ostream &OS, const PrintRecord &R,
const char *suffix, double Value);
const char *printJSONValues(raw_ostream &OS, const char *delim);
- static const char *printAllJSONValues(raw_ostream &OS, const char *delim);
};
} // end namespace llvm
diff --git a/include/llvm/Support/TrailingObjects.h b/include/llvm/Support/TrailingObjects.h
index 4d355724149c..cb5a52b0d861 100644
--- a/include/llvm/Support/TrailingObjects.h
+++ b/include/llvm/Support/TrailingObjects.h
@@ -294,7 +294,14 @@ class TrailingObjects : private trailing_objects_internal::TrailingObjectsImpl<
public:
// Make this (privately inherited) member public.
+#ifndef _MSC_VER
using ParentType::OverloadToken;
+#else
+ // MSVC bug prevents the above from working, at least up through CL
+ // 19.10.24629.
+ template <typename T>
+ using OverloadToken = typename ParentType::template OverloadToken<T>;
+#endif
/// Returns a pointer to the trailing object array of the given type
/// (which must be one of those specified in the class template). The
diff --git a/include/llvm/Support/UniqueLock.h b/include/llvm/Support/UniqueLock.h
index 529284d3868b..b4675f4b43ae 100644
--- a/include/llvm/Support/UniqueLock.h
+++ b/include/llvm/Support/UniqueLock.h
@@ -1,4 +1,4 @@
-//===-- Support/UniqueLock.h - Acquire/Release Mutex In Scope ---*- C++ -*-===//
+//===- Support/UniqueLock.h - Acquire/Release Mutex In Scope ----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -15,9 +15,10 @@
#ifndef LLVM_SUPPORT_UNIQUE_LOCK_H
#define LLVM_SUPPORT_UNIQUE_LOCK_H
-#include "llvm/Support/Mutex.h"
+#include <cassert>
namespace llvm {
+
/// A pared-down imitation of std::unique_lock from C++11. Contrary to the
/// name, it's really more of a wrapper for a lock. It may or may not have
/// an associated mutex, which is guaranteed to be locked upon creation
@@ -26,14 +27,14 @@ namespace llvm {
/// @brief Guard a section of code with a mutex.
template<typename MutexT>
class unique_lock {
- MutexT *M;
- bool locked;
+ MutexT *M = nullptr;
+ bool locked = false;
- unique_lock(const unique_lock &) = delete;
- void operator=(const unique_lock &) = delete;
public:
- unique_lock() : M(nullptr), locked(false) {}
+ unique_lock() = default;
explicit unique_lock(MutexT &m) : M(&m), locked(true) { M->lock(); }
+ unique_lock(const unique_lock &) = delete;
+ unique_lock &operator=(const unique_lock &) = delete;
void operator=(unique_lock &&o) {
if (owns_lock())
@@ -62,6 +63,7 @@ namespace llvm {
bool owns_lock() { return locked; }
};
-}
+
+} // end namespace llvm
#endif // LLVM_SUPPORT_UNIQUE_LOCK_H
diff --git a/include/llvm/Support/Wasm.h b/include/llvm/Support/Wasm.h
index 8ac6b9038e91..8e6c418c8189 100644
--- a/include/llvm/Support/Wasm.h
+++ b/include/llvm/Support/Wasm.h
@@ -23,22 +23,94 @@ namespace wasm {
// Object file magic string.
const char WasmMagic[] = {'\0', 'a', 's', 'm'};
// Wasm binary format version
-const uint32_t WasmVersion = 0xd;
+const uint32_t WasmVersion = 0x1;
struct WasmObjectHeader {
StringRef Magic;
uint32_t Version;
};
-struct WasmSection {
- uint32_t Type; // Section type (See below)
- uint32_t Offset; // Offset with in the file
- StringRef Name; // Section name (User-defined sections only)
- ArrayRef<uint8_t> Content; // Section content
+struct WasmSignature {
+ std::vector<int32_t> ParamTypes;
+ int32_t ReturnType;
+};
+
+struct WasmImport {
+ StringRef Module;
+ StringRef Field;
+ uint32_t Kind;
+ union {
+ uint32_t SigIndex;
+ int32_t GlobalType;
+ };
+ bool GlobalMutable;
+};
+
+struct WasmExport {
+ StringRef Name;
+ uint32_t Kind;
+ uint32_t Index;
+};
+
+struct WasmLimits {
+ uint32_t Flags;
+ uint32_t Initial;
+ uint32_t Maximum;
+};
+
+struct WasmTable {
+ int32_t ElemType;
+ WasmLimits Limits;
+};
+
+struct WasmInitExpr {
+ uint8_t Opcode;
+ union {
+ int32_t Int32;
+ int64_t Int64;
+ int32_t Float32;
+ int64_t Float64;
+ uint32_t Global;
+ } Value;
+};
+
+struct WasmGlobal {
+ int32_t Type;
+ bool Mutable;
+ WasmInitExpr InitExpr;
+};
+
+struct WasmLocalDecl {
+ int32_t Type;
+ uint32_t Count;
+};
+
+struct WasmFunction {
+ std::vector<WasmLocalDecl> Locals;
+ ArrayRef<uint8_t> Body;
+};
+
+struct WasmDataSegment {
+ uint32_t Index;
+ WasmInitExpr Offset;
+ ArrayRef<uint8_t> Content;
+};
+
+struct WasmElemSegment {
+ uint32_t TableIndex;
+ WasmInitExpr Offset;
+ std::vector<uint32_t> Functions;
+};
+
+struct WasmRelocation {
+ uint32_t Type; // The type of the relocation.
+ int32_t Index; // Index into function to global index space.
+ uint64_t Offset; // Offset from the start of the section.
+ uint64_t Addend; // A value to add to the symbol.
};
enum : unsigned {
- WASM_SEC_USER = 0, // User-defined section
+ WASM_SEC_CUSTOM = 0, // Custom / User-defined section
WASM_SEC_TYPE = 1, // Function signature declarations
WASM_SEC_IMPORT = 2, // Import declarations
WASM_SEC_FUNCTION = 3, // Function declarations
@@ -53,14 +125,14 @@ enum : unsigned {
};
// Type immediate encodings used in various contexts.
-enum : unsigned {
- WASM_TYPE_I32 = 0x7f,
- WASM_TYPE_I64 = 0x7e,
- WASM_TYPE_F32 = 0x7d,
- WASM_TYPE_F64 = 0x7c,
- WASM_TYPE_ANYFUNC = 0x70,
- WASM_TYPE_FUNC = 0x60,
- WASM_TYPE_NORESULT = 0x40, // for blocks with no result values
+enum {
+ WASM_TYPE_I32 = -0x01,
+ WASM_TYPE_I64 = -0x02,
+ WASM_TYPE_F32 = -0x03,
+ WASM_TYPE_F64 = -0x04,
+ WASM_TYPE_ANYFUNC = -0x10,
+ WASM_TYPE_FUNC = -0x20,
+ WASM_TYPE_NORESULT = -0x40, // for blocks with no result values
};
// Kinds of externals (for imports and exports).
@@ -81,6 +153,49 @@ enum : unsigned {
WASM_OPCODE_F64_CONST = 0x44,
};
+enum : unsigned {
+ WASM_NAMES_FUNCTION = 0x1,
+ WASM_NAMES_LOCAL = 0x2,
+};
+
+enum : unsigned {
+ WASM_LIMITS_FLAG_HAS_MAX = 0x1,
+};
+
+// Subset of types that a value can have
+enum class ValType {
+ I32 = WASM_TYPE_I32,
+ I64 = WASM_TYPE_I64,
+ F32 = WASM_TYPE_F32,
+ F64 = WASM_TYPE_F64,
+};
+
+// Linking metadata kinds.
+enum : unsigned {
+ WASM_STACK_POINTER = 0x1,
+};
+
+#define WASM_RELOC(name, value) name = value,
+
+enum : unsigned {
+#include "WasmRelocs/WebAssembly.def"
+};
+
+#undef WASM_RELOC
+
+struct Global {
+ ValType Type;
+ bool Mutable;
+
+ // The initial value for this global is either the value of an imported
+ // global, in which case InitialModule and InitialName specify the global
+ // import, or a value, in which case InitialModule is empty and InitialValue
+ // holds the value.
+ StringRef InitialModule;
+ StringRef InitialName;
+ uint64_t InitialValue;
+};
+
} // end namespace wasm
} // end namespace llvm
diff --git a/include/llvm/Support/WasmRelocs/WebAssembly.def b/include/llvm/Support/WasmRelocs/WebAssembly.def
new file mode 100644
index 000000000000..da64e025478d
--- /dev/null
+++ b/include/llvm/Support/WasmRelocs/WebAssembly.def
@@ -0,0 +1,13 @@
+
+#ifndef WASM_RELOC
+#error "WASM_RELOC must be defined"
+#endif
+
+WASM_RELOC(R_WEBASSEMBLY_FUNCTION_INDEX_LEB, 0)
+WASM_RELOC(R_WEBASSEMBLY_TABLE_INDEX_SLEB, 1)
+WASM_RELOC(R_WEBASSEMBLY_TABLE_INDEX_I32, 2)
+WASM_RELOC(R_WEBASSEMBLY_GLOBAL_ADDR_LEB, 3)
+WASM_RELOC(R_WEBASSEMBLY_GLOBAL_ADDR_SLEB, 4)
+WASM_RELOC(R_WEBASSEMBLY_GLOBAL_ADDR_I32, 5)
+WASM_RELOC(R_WEBASSEMBLY_TYPE_INDEX_LEB, 6)
+WASM_RELOC(R_WEBASSEMBLY_GLOBAL_INDEX_LEB, 7)
diff --git a/include/llvm/Support/YAMLTraits.h b/include/llvm/Support/YAMLTraits.h
index cbba9c08275a..6d02e4aba48a 100644
--- a/include/llvm/Support/YAMLTraits.h
+++ b/include/llvm/Support/YAMLTraits.h
@@ -689,11 +689,12 @@ private:
assert(DefaultValue.hasValue() == false &&
"Optional<T> shouldn't have a value!");
void *SaveInfo;
- bool UseDefault;
+ bool UseDefault = true;
const bool sameAsDefault = outputting() && !Val.hasValue();
if (!outputting() && !Val.hasValue())
Val = T();
- if (this->preflightKey(Key, Required, sameAsDefault, UseDefault,
+ if (Val.hasValue() &&
+ this->preflightKey(Key, Required, sameAsDefault, UseDefault,
SaveInfo)) {
yamlize(*this, Val.getValue(), Required, Ctx);
this->postflightKey(SaveInfo);
@@ -731,7 +732,7 @@ private:
}
private:
- void *Ctxt;
+ void *Ctxt;
};
namespace detail {
@@ -1251,6 +1252,13 @@ public:
Output(llvm::raw_ostream &, void *Ctxt = nullptr, int WrapColumn = 70);
~Output() override;
+ /// \brief Set whether or not to output optional values which are equal
+ /// to the default value. By default, when outputting if you attempt
+ /// to write a value that is equal to the default, the value gets ignored.
+ /// Sometimes, it is useful to be able to see these in the resulting YAML
+ /// anyway.
+ void setWriteDefaultValues(bool Write) { WriteDefaultValues = Write; }
+
bool outputting() override;
bool mapTag(StringRef, bool) override;
void beginMapping() override;
@@ -1314,6 +1322,7 @@ private:
bool NeedFlowSequenceComma;
bool EnumerationMatchFound;
bool NeedsNewLine;
+ bool WriteDefaultValues;
};
/// YAML I/O does conversion based on types. But often native data types
diff --git a/include/llvm/Support/thread.h b/include/llvm/Support/thread.h
index 9c45418df55c..787a513d6017 100644
--- a/include/llvm/Support/thread.h
+++ b/include/llvm/Support/thread.h
@@ -21,22 +21,8 @@
#if LLVM_ENABLE_THREADS
-#ifdef _MSC_VER
-// concrt.h depends on eh.h for __uncaught_exception declaration
-// even if we disable exceptions.
-#include <eh.h>
-
-// Suppress 'C++ exception handler used, but unwind semantics are not enabled.'
-#pragma warning(push)
-#pragma warning(disable:4530)
-#endif
-
#include <thread>
-#ifdef _MSC_VER
-#pragma warning(pop)
-#endif
-
namespace llvm {
typedef std::thread thread;
}
diff --git a/include/llvm/Support/type_traits.h b/include/llvm/Support/type_traits.h
index 7706ff527197..ce4bbf8cb2cc 100644
--- a/include/llvm/Support/type_traits.h
+++ b/include/llvm/Support/type_traits.h
@@ -95,6 +95,15 @@ struct add_const_past_pointer<
typedef const typename std::remove_pointer<T>::type *type;
};
+template <typename T, typename Enable = void>
+struct const_pointer_or_const_ref {
+ using type = const T &;
+};
+template <typename T>
+struct const_pointer_or_const_ref<
+ T, typename std::enable_if<std::is_pointer<T>::value>::type> {
+ using type = typename add_const_past_pointer<T>::type;
+};
}
// If the compiler supports detecting whether a class is final, define
diff --git a/include/llvm/TableGen/Record.h b/include/llvm/TableGen/Record.h
index 5a100f0cba76..fef5bf304566 100644
--- a/include/llvm/TableGen/Record.h
+++ b/include/llvm/TableGen/Record.h
@@ -1196,6 +1196,9 @@ public:
inline const_arg_iterator arg_begin() const { return Args.begin(); }
inline const_arg_iterator arg_end () const { return Args.end(); }
+ inline iterator_range<const_arg_iterator> args() const {
+ return llvm::make_range(arg_begin(), arg_end());
+ }
inline size_t arg_size () const { return Args.size(); }
inline bool arg_empty() const { return Args.empty(); }
@@ -1462,6 +1465,7 @@ public:
ResolveFirst = b;
}
+ void print(raw_ostream &OS) const;
void dump() const;
//===--------------------------------------------------------------------===//
diff --git a/include/llvm/TableGen/StringMatcher.h b/include/llvm/TableGen/StringMatcher.h
index b43877910834..11a8ad8183aa 100644
--- a/include/llvm/TableGen/StringMatcher.h
+++ b/include/llvm/TableGen/StringMatcher.h
@@ -38,7 +38,7 @@ private:
raw_ostream &OS;
public:
- StringMatcher(StringRef strVariableName,
+ StringMatcher(StringRef strVariableName,
const std::vector<StringPair> &matches, raw_ostream &os)
: StrVariableName(strVariableName), Matches(matches), OS(os) {}
diff --git a/include/llvm/TableGen/StringToOffsetTable.h b/include/llvm/TableGen/StringToOffsetTable.h
index e5b61ed1195e..aaf2a356ffab 100644
--- a/include/llvm/TableGen/StringToOffsetTable.h
+++ b/include/llvm/TableGen/StringToOffsetTable.h
@@ -60,10 +60,10 @@ public:
if (AggregateString[i] != '\\')
continue;
- assert(i+1 < AggregateString.size() && "Incomplete escape sequence!");
- if (isdigit(AggregateString[i+1])) {
- assert(isdigit(AggregateString[i+2]) &&
- isdigit(AggregateString[i+3]) &&
+ assert(i + 1 < AggregateString.size() && "Incomplete escape sequence!");
+ if (isdigit(AggregateString[i + 1])) {
+ assert(isdigit(AggregateString[i + 2]) &&
+ isdigit(AggregateString[i + 3]) &&
"Expected 3 digit octal escape!");
O << AggregateString[++i];
O << AggregateString[++i];
diff --git a/include/llvm/Target/GenericOpcodes.td b/include/llvm/Target/GenericOpcodes.td
index 8694eb5797d0..de3796cd4ee5 100644
--- a/include/llvm/Target/GenericOpcodes.td
+++ b/include/llvm/Target/GenericOpcodes.td
@@ -91,6 +91,21 @@ def G_FCONSTANT : Instruction {
let hasSideEffects = 0;
}
+def G_VASTART : Instruction {
+ let OutOperandList = (outs);
+ let InOperandList = (ins type0:$list);
+ let hasSideEffects = 0;
+ let mayStore = 1;
+}
+
+def G_VAARG : Instruction {
+ let OutOperandList = (outs type0:$val);
+ let InOperandList = (ins type1:$list, unknown:$align);
+ let hasSideEffects = 0;
+ let mayLoad = 1;
+ let mayStore = 1;
+}
+
//------------------------------------------------------------------------------
// Binary ops.
//------------------------------------------------------------------------------
@@ -103,13 +118,6 @@ def G_ADD : Instruction {
let isCommutable = 1;
}
-// Generic pointer offset.
-def G_GEP : Instruction {
- let OutOperandList = (outs type0:$dst);
- let InOperandList = (ins type0:$src1, type1:$src2);
- let hasSideEffects = 0;
-}
-
// Generic subtraction.
def G_SUB : Instruction {
let OutOperandList = (outs type0:$dst);
@@ -224,6 +232,19 @@ def G_SELECT : Instruction {
let hasSideEffects = 0;
}
+// Generic pointer offset.
+def G_GEP : Instruction {
+ let OutOperandList = (outs type0:$dst);
+ let InOperandList = (ins type0:$src1, type1:$src2);
+ let hasSideEffects = 0;
+}
+
+def G_PTR_MASK : Instruction {
+ let OutOperandList = (outs type0:$dst);
+ let InOperandList = (ins type0:$src, unknown:$bits);
+ let hasSideEffects = 0;
+}
+
//------------------------------------------------------------------------------
// Overflow ops
//------------------------------------------------------------------------------
@@ -273,10 +294,34 @@ def G_SMULO : Instruction {
let isCommutable = 1;
}
+// Multiply two numbers at twice the incoming bit width (unsigned) and return
+// the high half of the result.
+def G_UMULH : Instruction {
+ let OutOperandList = (outs type0:$dst);
+ let InOperandList = (ins type0:$src1, type0:$src2);
+ let hasSideEffects = 0;
+ let isCommutable = 1;
+}
+
+// Multiply two numbers at twice the incoming bit width (signed) and return
+// the high half of the result.
+def G_SMULH : Instruction {
+ let OutOperandList = (outs type0:$dst);
+ let InOperandList = (ins type0:$src1, type0:$src2);
+ let hasSideEffects = 0;
+ let isCommutable = 1;
+}
+
//------------------------------------------------------------------------------
// Floating Point Unary Ops.
//------------------------------------------------------------------------------
+def G_FNEG : Instruction {
+ let OutOperandList = (outs type0:$dst);
+ let InOperandList = (ins type0:$src);
+ let hasSideEffects = 0;
+}
+
def G_FPEXT : Instruction {
let OutOperandList = (outs type0:$dst);
let InOperandList = (ins type1:$src);
@@ -355,6 +400,13 @@ def G_FREM : Instruction {
let hasSideEffects = 0;
}
+// Floating point exponentiation.
+def G_FPOW : Instruction {
+ let OutOperandList = (outs type0:$dst);
+ let InOperandList = (ins type0:$src1, type0:$src2);
+ let hasSideEffects = 0;
+}
+
//------------------------------------------------------------------------------
// Memory ops
//------------------------------------------------------------------------------
@@ -383,17 +435,24 @@ def G_STORE : Instruction {
// indexes. This will almost certainly be mapped to sub-register COPYs after
// register banks have been selected.
def G_EXTRACT : Instruction {
+ let OutOperandList = (outs type0:$res);
+ let InOperandList = (ins type1:$src, unknown:$offset);
+ let hasSideEffects = 0;
+}
+
+// Extract multiple registers specified size, starting from blocks given by
+// indexes. This will almost certainly be mapped to sub-register COPYs after
+// register banks have been selected.
+def G_UNMERGE_VALUES : Instruction {
let OutOperandList = (outs);
let InOperandList = (ins variable_ops);
let hasSideEffects = 0;
}
-// Insert a sequence of smaller registers into a larger one at the specified
-// indices (interleaved with the values in the operand list "op0, bit0, op1,
-// bit1, ...")).
+// Insert a smaller register into a larger one at the specified bit-index.
def G_INSERT : Instruction {
let OutOperandList = (outs type0:$dst);
- let InOperandList = (ins type0:$src, variable_ops);
+ let InOperandList = (ins type0:$src, type1:$op, unknown:$offset);
let hasSideEffects = 0;
}
@@ -406,6 +465,12 @@ def G_SEQUENCE : Instruction {
let hasSideEffects = 0;
}
+def G_MERGE_VALUES : Instruction {
+ let OutOperandList = (outs type0:$dst);
+ let InOperandList = (ins variable_ops);
+ let hasSideEffects = 0;
+}
+
// Intrinsic without side effects.
def G_INTRINSIC : Instruction {
let OutOperandList = (outs);
@@ -445,4 +510,38 @@ def G_BRCOND : Instruction {
let isTerminator = 1;
}
+// Generic indirect branch.
+def G_BRINDIRECT : Instruction {
+ let OutOperandList = (outs);
+ let InOperandList = (ins type0:$src1);
+ let hasSideEffects = 0;
+ let isBranch = 1;
+ let isTerminator = 1;
+}
+
+//------------------------------------------------------------------------------
+// Vector ops
+//------------------------------------------------------------------------------
+
+// Generic insertelement.
+def G_INSERT_VECTOR_ELT : Instruction {
+ let OutOperandList = (outs type0:$dst);
+ let InOperandList = (ins type0:$src, type1:$elt, type2:$idx);
+ let hasSideEffects = 0;
+}
+
+// Generic extractelement.
+def G_EXTRACT_VECTOR_ELT : Instruction {
+ let OutOperandList = (outs type0:$dst);
+ let InOperandList = (ins type1:$src, type2:$idx);
+ let hasSideEffects = 0;
+}
+
+// Generic shufflevector.
+def G_SHUFFLE_VECTOR: Instruction {
+ let OutOperandList = (outs type0:$dst);
+ let InOperandList = (ins type1:$v1, type1:$v2, type2:$mask);
+ let hasSideEffects = 0;
+}
+
// TODO: Add the other generic opcodes.
diff --git a/include/llvm/Target/GlobalISel/RegisterBank.td b/include/llvm/Target/GlobalISel/RegisterBank.td
new file mode 100644
index 000000000000..4dfd139e9fb6
--- /dev/null
+++ b/include/llvm/Target/GlobalISel/RegisterBank.td
@@ -0,0 +1,16 @@
+//===- RegisterBank.td - Register bank definitions ---------*- tablegen -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//
+//===----------------------------------------------------------------------===//
+
+class RegisterBank<string name, list<RegisterClass> classes> {
+ string Name = name;
+ list<RegisterClass> RegisterClasses = classes;
+}
diff --git a/include/llvm/Target/TargetGlobalISel.td b/include/llvm/Target/GlobalISel/SelectionDAGCompat.td
index 0727c9802e5e..9f034220815f 100644
--- a/include/llvm/Target/TargetGlobalISel.td
+++ b/include/llvm/Target/GlobalISel/SelectionDAGCompat.td
@@ -25,5 +25,29 @@ class GINodeEquiv<Instruction i, SDNode node> {
SDNode Node = node;
}
+def : GINodeEquiv<G_ZEXT, zext>;
+def : GINodeEquiv<G_SEXT, sext>;
def : GINodeEquiv<G_ADD, add>;
+def : GINodeEquiv<G_SUB, sub>;
+def : GINodeEquiv<G_MUL, mul>;
+
+def : GINodeEquiv<G_OR, or>;
+def : GINodeEquiv<G_XOR, xor>;
+def : GINodeEquiv<G_AND, and>;
+
+def : GINodeEquiv<G_SHL, shl>;
+def : GINodeEquiv<G_LSHR, srl>;
+def : GINodeEquiv<G_ASHR, sra>;
+
+def : GINodeEquiv<G_SDIV, sdiv>;
+def : GINodeEquiv<G_UDIV, udiv>;
+def : GINodeEquiv<G_SREM, srem>;
+def : GINodeEquiv<G_UREM, urem>;
+
def : GINodeEquiv<G_BR, br>;
+
+// Specifies the GlobalISel equivalents for SelectionDAG's ComplexPattern.
+// Should be used on defs that subclass GIComplexOperandMatcher<>.
+class GIComplexPatternEquiv<ComplexPattern seldag> {
+ ComplexPattern SelDAGEquivalent = seldag;
+}
diff --git a/include/llvm/Target/GlobalISel/Target.td b/include/llvm/Target/GlobalISel/Target.td
new file mode 100644
index 000000000000..fa1a424b5895
--- /dev/null
+++ b/include/llvm/Target/GlobalISel/Target.td
@@ -0,0 +1,56 @@
+//===- Target.td - Define GlobalISel rules -----------------*- 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 the target-independent interfaces used to support
+// SelectionDAG instruction selection patterns (specified in
+// TargetSelectionDAG.td) when generating GlobalISel instruction selectors.
+//
+// This is intended as a compatibility layer, to enable reuse of target
+// descriptions written for SelectionDAG without requiring explicit GlobalISel
+// support. It will eventually supersede SelectionDAG patterns.
+//
+//===----------------------------------------------------------------------===//
+
+// Definitions that inherit from LLT define types that will be used in the
+// GlobalISel matcher.
+class LLT;
+
+def s32 : LLT;
+def s64 : LLT;
+
+// Defines a matcher for complex operands. This is analogous to ComplexPattern
+// from SelectionDAG.
+//
+// Definitions that inherit from this may also inherit from
+// GIComplexPatternEquiv to enable the import of SelectionDAG patterns involving
+// those ComplexPatterns.
+class GIComplexOperandMatcher<LLT type, dag operands, string matcherfn> {
+ // The expected type of the root of the match.
+ //
+ // TODO: We should probably support, any-type, any-scalar, and multiple types
+ // in the future.
+ LLT Type = type;
+
+ // The operands that result from a successful match
+ // Should be of the form '(ops ty1, ty2, ...)' where ty1/ty2 are definitions
+ // that inherit from Operand.
+ //
+ // FIXME: Which definition is used for ty1/ty2 doesn't actually matter at the
+ // moment. Only the number of operands is used.
+ dag Operands = operands;
+
+ // The function that determines whether the operand matches. It should be of
+ // the form:
+ // bool select(const MatchOperand &Root, MatchOperand &Result1)
+ // and should have the same number of ResultX arguments as the number of
+ // result operands. It must return true on successful match and false
+ // otherwise. If it returns true, then all the ResultX arguments must be
+ // overwritten.
+ string MatcherFn = matcherfn;
+}
diff --git a/include/llvm/Target/Target.td b/include/llvm/Target/Target.td
index 729d7669e0fa..b21689e0e134 100644
--- a/include/llvm/Target/Target.td
+++ b/include/llvm/Target/Target.td
@@ -402,11 +402,8 @@ class Instruction {
// If so, make sure to override
// TargetInstrInfo::getInsertSubregLikeInputs.
- // Side effect flags - When set, the flags have these meanings:
- //
- // hasSideEffects - The instruction has side effects that are not
- // captured by any operands of the instruction or other flags.
- //
+ // Does the instruction have side effects that are not captured by any
+ // operands of the instruction or other flags?
bit hasSideEffects = ?;
// Is this instruction a "real" instruction (with a distinct machine
@@ -951,11 +948,12 @@ def LOCAL_ESCAPE : Instruction {
let hasSideEffects = 0;
let hasCtrlDep = 1;
}
-def FAULTING_LOAD_OP : Instruction {
+def FAULTING_OP : Instruction {
let OutOperandList = (outs unknown:$dst);
let InOperandList = (ins variable_ops);
let usesCustomInserter = 1;
let mayLoad = 1;
+ let mayStore = 1;
let isTerminator = 1;
let isBranch = 1;
}
@@ -998,6 +996,15 @@ def PATCHABLE_TAIL_CALL : Instruction {
let hasSideEffects = 1;
let isReturn = 1;
}
+def FENTRY_CALL : Instruction {
+ let OutOperandList = (outs unknown:$dst);
+ let InOperandList = (ins variable_ops);
+ let AsmString = "# FEntry call";
+ let usesCustomInserter = 1;
+ let mayLoad = 1;
+ let mayStore = 1;
+ let hasSideEffects = 1;
+}
// Generic opcodes used in GlobalISel.
include "llvm/Target/GenericOpcodes.td"
@@ -1342,6 +1349,16 @@ include "llvm/Target/TargetCallingConv.td"
include "llvm/Target/TargetSelectionDAG.td"
//===----------------------------------------------------------------------===//
-// Pull in the common support for Global ISel generation.
+// Pull in the common support for Global ISel register bank info generation.
+//
+include "llvm/Target/GlobalISel/RegisterBank.td"
+
+//===----------------------------------------------------------------------===//
+// Pull in the common support for DAG isel generation.
+//
+include "llvm/Target/GlobalISel/Target.td"
+
+//===----------------------------------------------------------------------===//
+// Pull in the common support for the Global ISel DAG-based selector generation.
//
-include "llvm/Target/TargetGlobalISel.td"
+include "llvm/Target/GlobalISel/SelectionDAGCompat.td"
diff --git a/include/llvm/Target/TargetCallingConv.h b/include/llvm/Target/TargetCallingConv.h
index be09236cdab0..4f750b8a289f 100644
--- a/include/llvm/Target/TargetCallingConv.h
+++ b/include/llvm/Target/TargetCallingConv.h
@@ -14,146 +14,120 @@
#ifndef LLVM_TARGET_TARGETCALLINGCONV_H
#define LLVM_TARGET_TARGETCALLINGCONV_H
+#include "llvm/CodeGen/MachineValueType.h"
#include "llvm/CodeGen/ValueTypes.h"
-#include "llvm/Support/DataTypes.h"
#include "llvm/Support/MathExtras.h"
+#include <cassert>
#include <climits>
+#include <cstdint>
namespace llvm {
-
namespace ISD {
+
struct ArgFlagsTy {
private:
- static const uint64_t NoFlagSet = 0ULL;
- static const uint64_t ZExt = 1ULL<<0; ///< Zero extended
- static const uint64_t ZExtOffs = 0;
- static const uint64_t SExt = 1ULL<<1; ///< Sign extended
- static const uint64_t SExtOffs = 1;
- static const uint64_t InReg = 1ULL<<2; ///< Passed in register
- static const uint64_t InRegOffs = 2;
- static const uint64_t SRet = 1ULL<<3; ///< Hidden struct-ret ptr
- static const uint64_t SRetOffs = 3;
- static const uint64_t ByVal = 1ULL<<4; ///< Struct passed by value
- static const uint64_t ByValOffs = 4;
- static const uint64_t Nest = 1ULL<<5; ///< Nested fn static chain
- static const uint64_t NestOffs = 5;
- static const uint64_t Returned = 1ULL<<6; ///< Always returned
- static const uint64_t ReturnedOffs = 6;
- static const uint64_t ByValAlign = 0xFULL<<7; ///< Struct alignment
- static const uint64_t ByValAlignOffs = 7;
- static const uint64_t Split = 1ULL<<11;
- static const uint64_t SplitOffs = 11;
- static const uint64_t InAlloca = 1ULL<<12; ///< Passed with inalloca
- static const uint64_t InAllocaOffs = 12;
- static const uint64_t SplitEnd = 1ULL<<13; ///< Last part of a split
- static const uint64_t SplitEndOffs = 13;
- static const uint64_t SwiftSelf = 1ULL<<14; ///< Swift self parameter
- static const uint64_t SwiftSelfOffs = 14;
- static const uint64_t SwiftError = 1ULL<<15; ///< Swift error parameter
- static const uint64_t SwiftErrorOffs = 15;
- static const uint64_t Hva = 1ULL << 16; ///< HVA field for
- ///< vectorcall
- static const uint64_t HvaOffs = 16;
- static const uint64_t HvaStart = 1ULL << 17; ///< HVA structure start
- ///< for vectorcall
- static const uint64_t HvaStartOffs = 17;
- static const uint64_t SecArgPass = 1ULL << 18; ///< Second argument
- ///< pass for vectorcall
- static const uint64_t SecArgPassOffs = 18;
- static const uint64_t OrigAlign = 0x1FULL<<27;
- static const uint64_t OrigAlignOffs = 27;
- static const uint64_t ByValSize = 0x3fffffffULL<<32; ///< Struct size
- static const uint64_t ByValSizeOffs = 32;
- static const uint64_t InConsecutiveRegsLast = 0x1ULL<<62; ///< Struct size
- static const uint64_t InConsecutiveRegsLastOffs = 62;
- static const uint64_t InConsecutiveRegs = 0x1ULL<<63; ///< Struct size
- static const uint64_t InConsecutiveRegsOffs = 63;
-
- static const uint64_t One = 1ULL; ///< 1 of this type, for shifts
-
- uint64_t Flags;
+ unsigned IsZExt : 1; ///< Zero extended
+ unsigned IsSExt : 1; ///< Sign extended
+ unsigned IsInReg : 1; ///< Passed in register
+ unsigned IsSRet : 1; ///< Hidden struct-ret ptr
+ unsigned IsByVal : 1; ///< Struct passed by value
+ unsigned IsNest : 1; ///< Nested fn static chain
+ unsigned IsReturned : 1; ///< Always returned
+ unsigned IsSplit : 1;
+ unsigned IsInAlloca : 1; ///< Passed with inalloca
+ unsigned IsSplitEnd : 1; ///< Last part of a split
+ unsigned IsSwiftSelf : 1; ///< Swift self parameter
+ unsigned IsSwiftError : 1; ///< Swift error parameter
+ unsigned IsHva : 1; ///< HVA field for
+ unsigned IsHvaStart : 1; ///< HVA structure start
+ unsigned IsSecArgPass : 1; ///< Second argument
+ unsigned ByValAlign : 4; ///< Log 2 of byval alignment
+ unsigned OrigAlign : 5; ///< Log 2 of original alignment
+ unsigned IsInConsecutiveRegsLast : 1;
+ unsigned IsInConsecutiveRegs : 1;
+ unsigned IsCopyElisionCandidate : 1; ///< Argument copy elision candidate
+
+ unsigned ByValSize; ///< Byval struct size
public:
- ArgFlagsTy() : Flags(0) { }
+ ArgFlagsTy()
+ : IsZExt(0), IsSExt(0), IsInReg(0), IsSRet(0), IsByVal(0), IsNest(0),
+ IsReturned(0), IsSplit(0), IsInAlloca(0), IsSplitEnd(0),
+ IsSwiftSelf(0), IsSwiftError(0), IsHva(0), IsHvaStart(0),
+ IsSecArgPass(0), ByValAlign(0), OrigAlign(0),
+ IsInConsecutiveRegsLast(0), IsInConsecutiveRegs(0),
+ IsCopyElisionCandidate(0), ByValSize(0) {
+ static_assert(sizeof(*this) == 2 * sizeof(unsigned), "flags are too big");
+ }
- bool isZExt() const { return Flags & ZExt; }
- void setZExt() { Flags |= One << ZExtOffs; }
+ bool isZExt() const { return IsZExt; }
+ void setZExt() { IsZExt = 1; }
- bool isSExt() const { return Flags & SExt; }
- void setSExt() { Flags |= One << SExtOffs; }
+ bool isSExt() const { return IsSExt; }
+ void setSExt() { IsSExt = 1; }
- bool isInReg() const { return Flags & InReg; }
- void setInReg() { Flags |= One << InRegOffs; }
+ bool isInReg() const { return IsInReg; }
+ void setInReg() { IsInReg = 1; }
- bool isSRet() const { return Flags & SRet; }
- void setSRet() { Flags |= One << SRetOffs; }
+ bool isSRet() const { return IsSRet; }
+ void setSRet() { IsSRet = 1; }
- bool isByVal() const { return Flags & ByVal; }
- void setByVal() { Flags |= One << ByValOffs; }
+ bool isByVal() const { return IsByVal; }
+ void setByVal() { IsByVal = 1; }
- bool isInAlloca() const { return Flags & InAlloca; }
- void setInAlloca() { Flags |= One << InAllocaOffs; }
+ bool isInAlloca() const { return IsInAlloca; }
+ void setInAlloca() { IsInAlloca = 1; }
- bool isSwiftSelf() const { return Flags & SwiftSelf; }
- void setSwiftSelf() { Flags |= One << SwiftSelfOffs; }
+ bool isSwiftSelf() const { return IsSwiftSelf; }
+ void setSwiftSelf() { IsSwiftSelf = 1; }
- bool isSwiftError() const { return Flags & SwiftError; }
- void setSwiftError() { Flags |= One << SwiftErrorOffs; }
+ bool isSwiftError() const { return IsSwiftError; }
+ void setSwiftError() { IsSwiftError = 1; }
- bool isHva() const { return Flags & Hva; }
- void setHva() { Flags |= One << HvaOffs; }
+ bool isHva() const { return IsHva; }
+ void setHva() { IsHva = 1; }
- bool isHvaStart() const { return Flags & HvaStart; }
- void setHvaStart() { Flags |= One << HvaStartOffs; }
+ bool isHvaStart() const { return IsHvaStart; }
+ void setHvaStart() { IsHvaStart = 1; }
- bool isSecArgPass() const { return Flags & SecArgPass; }
- void setSecArgPass() { Flags |= One << SecArgPassOffs; }
+ bool isSecArgPass() const { return IsSecArgPass; }
+ void setSecArgPass() { IsSecArgPass = 1; }
- bool isNest() const { return Flags & Nest; }
- void setNest() { Flags |= One << NestOffs; }
+ bool isNest() const { return IsNest; }
+ void setNest() { IsNest = 1; }
- bool isReturned() const { return Flags & Returned; }
- void setReturned() { Flags |= One << ReturnedOffs; }
+ bool isReturned() const { return IsReturned; }
+ void setReturned() { IsReturned = 1; }
- bool isInConsecutiveRegs() const { return Flags & InConsecutiveRegs; }
- void setInConsecutiveRegs() { Flags |= One << InConsecutiveRegsOffs; }
+ bool isInConsecutiveRegs() const { return IsInConsecutiveRegs; }
+ void setInConsecutiveRegs() { IsInConsecutiveRegs = 1; }
- bool isInConsecutiveRegsLast() const { return Flags & InConsecutiveRegsLast; }
- void setInConsecutiveRegsLast() { Flags |= One << InConsecutiveRegsLastOffs; }
+ bool isInConsecutiveRegsLast() const { return IsInConsecutiveRegsLast; }
+ void setInConsecutiveRegsLast() { IsInConsecutiveRegsLast = 1; }
- unsigned getByValAlign() const {
- return (unsigned)
- ((One << ((Flags & ByValAlign) >> ByValAlignOffs)) / 2);
- }
- void setByValAlign(unsigned A) {
- Flags = (Flags & ~ByValAlign) |
- (uint64_t(Log2_32(A) + 1) << ByValAlignOffs);
- }
+ bool isSplit() const { return IsSplit; }
+ void setSplit() { IsSplit = 1; }
- bool isSplit() const { return Flags & Split; }
- void setSplit() { Flags |= One << SplitOffs; }
+ bool isSplitEnd() const { return IsSplitEnd; }
+ void setSplitEnd() { IsSplitEnd = 1; }
- bool isSplitEnd() const { return Flags & SplitEnd; }
- void setSplitEnd() { Flags |= One << SplitEndOffs; }
+ bool isCopyElisionCandidate() const { return IsCopyElisionCandidate; }
+ void setCopyElisionCandidate() { IsCopyElisionCandidate = 1; }
- unsigned getOrigAlign() const {
- return (unsigned)
- ((One << ((Flags & OrigAlign) >> OrigAlignOffs)) / 2);
- }
- void setOrigAlign(unsigned A) {
- Flags = (Flags & ~OrigAlign) |
- (uint64_t(Log2_32(A) + 1) << OrigAlignOffs);
+ unsigned getByValAlign() const { return (1U << ByValAlign) / 2; }
+ void setByValAlign(unsigned A) {
+ ByValAlign = Log2_32(A) + 1;
+ assert(getByValAlign() == A && "bitfield overflow");
}
- unsigned getByValSize() const {
- return (unsigned)((Flags & ByValSize) >> ByValSizeOffs);
- }
- void setByValSize(unsigned S) {
- Flags = (Flags & ~ByValSize) | (uint64_t(S) << ByValSizeOffs);
+ unsigned getOrigAlign() const { return (1U << OrigAlign) / 2; }
+ void setOrigAlign(unsigned A) {
+ OrigAlign = Log2_32(A) + 1;
+ assert(getOrigAlign() == A && "bitfield overflow");
}
- /// getRawBits - Represent the flags as a bunch of bits.
- uint64_t getRawBits() const { return Flags; }
+ unsigned getByValSize() const { return ByValSize; }
+ void setByValSize(unsigned S) { ByValSize = S; }
};
/// InputArg - This struct carries flags and type information about a
@@ -162,9 +136,9 @@ namespace ISD {
///
struct InputArg {
ArgFlagsTy Flags;
- MVT VT;
+ MVT VT = MVT::Other;
EVT ArgVT;
- bool Used;
+ bool Used = false;
/// Index original Function's argument.
unsigned OrigArgIndex;
@@ -176,7 +150,7 @@ namespace ISD {
/// registers, we got 4 InputArgs with PartOffsets 0, 4, 8 and 12.
unsigned PartOffset;
- InputArg() : VT(MVT::Other), Used(false) {}
+ InputArg() = default;
InputArg(ArgFlagsTy flags, EVT vt, EVT argvt, bool used,
unsigned origIdx, unsigned partOffs)
: Flags(flags), Used(used), OrigArgIndex(origIdx), PartOffset(partOffs) {
@@ -204,7 +178,7 @@ namespace ISD {
EVT ArgVT;
/// IsFixed - Is this a "fixed" value, ie not passed through a vararg "...".
- bool IsFixed;
+ bool IsFixed = false;
/// Index original Function's argument.
unsigned OrigArgIndex;
@@ -214,7 +188,7 @@ namespace ISD {
/// registers, we got 4 OutputArgs with PartOffsets 0, 4, 8 and 12.
unsigned PartOffset;
- OutputArg() : IsFixed(false) {}
+ OutputArg() = default;
OutputArg(ArgFlagsTy flags, EVT vt, EVT argvt, bool isfixed,
unsigned origIdx, unsigned partOffs)
: Flags(flags), IsFixed(isfixed), OrigArgIndex(origIdx),
@@ -223,8 +197,8 @@ namespace ISD {
ArgVT = argvt;
}
};
-} // end namespace ISD
-} // end llvm namespace
+} // end namespace ISD
+} // end namespace llvm
#endif // LLVM_TARGET_TARGETCALLINGCONV_H
diff --git a/include/llvm/Target/TargetInstrInfo.h b/include/llvm/Target/TargetInstrInfo.h
index 247d694f2e47..0dc9cf70d335 100644
--- a/include/llvm/Target/TargetInstrInfo.h
+++ b/include/llvm/Target/TargetInstrInfo.h
@@ -152,6 +152,31 @@ public:
unsigned getCallFrameSetupOpcode() const { return CallFrameSetupOpcode; }
unsigned getCallFrameDestroyOpcode() const { return CallFrameDestroyOpcode; }
+ /// Returns true if the argument is a frame pseudo instruction.
+ bool isFrameInstr(const MachineInstr &I) const {
+ return I.getOpcode() == getCallFrameSetupOpcode() ||
+ I.getOpcode() == getCallFrameDestroyOpcode();
+ }
+
+ /// Returns true if the argument is a frame setup pseudo instruction.
+ bool isFrameSetup(const MachineInstr &I) const {
+ return I.getOpcode() == getCallFrameSetupOpcode();
+ }
+
+ /// Returns size of the frame associated with the given frame instruction.
+ /// For frame setup instruction this is frame that is set up space set up
+ /// after the instruction. For frame destroy instruction this is the frame
+ /// freed by the caller.
+ /// Note, in some cases a call frame (or a part of it) may be prepared prior
+ /// to the frame setup instruction. It occurs in the calls that involve
+ /// inalloca arguments. This function reports only the size of the frame part
+ /// that is set up between the frame setup and destroy pseudo instructions.
+ int64_t getFrameSize(const MachineInstr &I) const {
+ assert(isFrameInstr(I));
+ assert(I.getOperand(0).getImm() >= 0);
+ return I.getOperand(0).getImm();
+ }
+
unsigned getCatchReturnOpcode() const { return CatchRetOpcode; }
unsigned getReturnOpcode() const { return ReturnOpcode; }
@@ -1070,15 +1095,6 @@ public:
llvm_unreachable("target did not implement shouldClusterMemOps()");
}
- /// Can this target fuse the given instructions if they are scheduled
- /// adjacent. Note that you have to add:
- /// DAG.addMutation(createMacroFusionDAGMutation());
- /// to TargetPassConfig::createMachineScheduler() to have an effect.
- virtual bool shouldScheduleAdjacent(const MachineInstr &First,
- const MachineInstr &Second) const {
- llvm_unreachable("target did not implement shouldScheduleAdjacent()");
- }
-
/// Reverses the branch condition of the specified condition list,
/// returning false on success and true if it cannot be reversed.
virtual
@@ -1108,6 +1124,25 @@ public:
/// terminator instruction that has not been predicated.
virtual bool isUnpredicatedTerminator(const MachineInstr &MI) const;
+ /// Returns true if MI is an unconditional tail call.
+ virtual bool isUnconditionalTailCall(const MachineInstr &MI) const {
+ return false;
+ }
+
+ /// Returns true if the tail call can be made conditional on BranchCond.
+ virtual bool
+ canMakeTailCallConditional(SmallVectorImpl<MachineOperand> &Cond,
+ const MachineInstr &TailCall) const {
+ return false;
+ }
+
+ /// Replace the conditional branch in MBB with a conditional tail call.
+ virtual void replaceBranchWithTailCall(MachineBasicBlock &MBB,
+ SmallVectorImpl<MachineOperand> &Cond,
+ const MachineInstr &TailCall) const {
+ llvm_unreachable("Target didn't implement replaceBranchWithTailCall!");
+ }
+
/// Convert the instruction into a predicated instruction.
/// It returns true if the operation was successful.
virtual bool PredicateInstruction(MachineInstr &MI,
@@ -1132,7 +1167,7 @@ public:
/// 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 {
+ virtual bool isPredicable(const MachineInstr &MI) const {
return MI.getDesc().isPredicable();
}
@@ -1427,10 +1462,17 @@ public:
return nullptr;
}
- // 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.
+ /// 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.
+ ///
+ /// Assumes any physical registers used to compute addresses have the same
+ /// value for both instructions. (This is the most useful assumption for
+ /// post-RA scheduling.)
+ ///
+ /// See also MachineInstr::mayAlias, which is implemented on top of this
+ /// function.
virtual bool
areMemAccessesTriviallyDisjoint(MachineInstr &MIa, MachineInstr &MIb,
AliasAnalysis *AA = nullptr) const {
@@ -1486,11 +1528,79 @@ public:
return None;
}
- /// Determines whether |Inst| is a tail call instruction.
+ /// Determines whether \p Inst is a tail call instruction. Override this
+ /// method on targets that do not properly set MCID::Return and MCID::Call on
+ /// tail call instructions."
virtual bool isTailCall(const MachineInstr &Inst) const {
+ return Inst.isReturn() && Inst.isCall();
+ }
+
+ /// True if the instruction is bound to the top of its basic block and no
+ /// other instructions shall be inserted before it. This can be implemented
+ /// to prevent register allocator to insert spills before such instructions.
+ virtual bool isBasicBlockPrologue(const MachineInstr &MI) const {
return false;
}
+ /// \brief Return how many instructions would be saved by outlining a
+ /// sequence containing \p SequenceSize instructions that appears
+ /// \p Occurrences times in a module.
+ virtual unsigned getOutliningBenefit(size_t SequenceSize, size_t Occurrences,
+ bool CanBeTailCall) const {
+ llvm_unreachable(
+ "Target didn't implement TargetInstrInfo::getOutliningBenefit!");
+ }
+
+ /// Represents how an instruction should be mapped by the outliner.
+ /// \p Legal instructions are those which are safe to outline.
+ /// \p Illegal instructions are those which cannot be outlined.
+ /// \p Invisible instructions are instructions which can be outlined, but
+ /// shouldn't actually impact the outlining result.
+ enum MachineOutlinerInstrType {Legal, Illegal, Invisible};
+
+ /// Returns how or if \p MI should be outlined.
+ virtual MachineOutlinerInstrType getOutliningType(MachineInstr &MI) const {
+ llvm_unreachable(
+ "Target didn't implement TargetInstrInfo::getOutliningType!");
+ }
+
+ /// Insert a custom epilogue for outlined functions.
+ /// This may be empty, in which case no epilogue or return statement will be
+ /// emitted.
+ virtual void insertOutlinerEpilogue(MachineBasicBlock &MBB,
+ MachineFunction &MF,
+ bool IsTailCall) const {
+ llvm_unreachable(
+ "Target didn't implement TargetInstrInfo::insertOutlinerEpilogue!");
+ }
+
+ /// Insert a call to an outlined function into the program.
+ /// Returns an iterator to the spot where we inserted the call. This must be
+ /// implemented by the target.
+ virtual MachineBasicBlock::iterator
+ insertOutlinedCall(Module &M, MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator &It, MachineFunction &MF,
+ bool IsTailCall) const {
+ llvm_unreachable(
+ "Target didn't implement TargetInstrInfo::insertOutlinedCall!");
+ }
+
+ /// Insert a custom prologue for outlined functions.
+ /// This may be empty, in which case no prologue will be emitted.
+ virtual void insertOutlinerPrologue(MachineBasicBlock &MBB,
+ MachineFunction &MF,
+ bool IsTailCall) const {
+ llvm_unreachable(
+ "Target didn't implement TargetInstrInfo::insertOutlinerPrologue!");
+ }
+
+ /// Return true if the function can safely be outlined from.
+ /// By default, this means that the function has no red zone.
+ virtual bool isFunctionSafeToOutlineFrom(MachineFunction &MF) const {
+ llvm_unreachable("Target didn't implement "
+ "TargetInstrInfo::isFunctionSafeToOutlineFrom!");
+ }
+
private:
unsigned CallFrameSetupOpcode, CallFrameDestroyOpcode;
unsigned CatchRetOpcode;
diff --git a/include/llvm/Target/TargetLowering.h b/include/llvm/Target/TargetLowering.h
index 3728a7a8cb17..85297ae837c5 100644
--- a/include/llvm/Target/TargetLowering.h
+++ b/include/llvm/Target/TargetLowering.h
@@ -25,13 +25,14 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/CodeGen/DAGCombine.h"
#include "llvm/CodeGen/ISDOpcodes.h"
#include "llvm/CodeGen/MachineValueType.h"
#include "llvm/CodeGen/RuntimeLibcalls.h"
+#include "llvm/CodeGen/SelectionDAG.h"
#include "llvm/CodeGen/SelectionDAGNodes.h"
#include "llvm/CodeGen/ValueTypes.h"
#include "llvm/IR/Attributes.h"
@@ -163,6 +164,35 @@ public:
// or custom.
};
+ class ArgListEntry {
+ public:
+ Value *Val = nullptr;
+ SDValue Node = SDValue();
+ Type *Ty = nullptr;
+ bool IsSExt : 1;
+ bool IsZExt : 1;
+ bool IsInReg : 1;
+ bool IsSRet : 1;
+ bool IsNest : 1;
+ bool IsByVal : 1;
+ bool IsInAlloca : 1;
+ bool IsReturned : 1;
+ bool IsSwiftSelf : 1;
+ bool IsSwiftError : 1;
+ uint16_t Alignment = 0;
+
+ ArgListEntry()
+ : IsSExt(false), IsZExt(false), IsInReg(false), IsSRet(false),
+ IsNest(false), IsByVal(false), IsInAlloca(false), IsReturned(false),
+ IsSwiftSelf(false), IsSwiftError(false) {}
+
+ void setAttributes(ImmutableCallSite *CS, unsigned ArgIdx);
+ };
+ typedef std::vector<ArgListEntry> ArgListTy;
+
+ virtual void markLibCallAttributes(MachineFunction *MF, unsigned CC,
+ ArgListTy &Args) const {};
+
static ISD::NodeType getExtendForContent(BooleanContent Content) {
switch (Content) {
case UndefinedBooleanContent:
@@ -254,9 +284,7 @@ public:
/// several shifts, adds, and multiplies for this target.
/// The definition of "cheaper" may depend on whether we're optimizing
/// for speed or for size.
- virtual bool isIntDivCheap(EVT VT, AttributeSet Attr) const {
- return false;
- }
+ virtual bool isIntDivCheap(EVT VT, AttributeList Attr) const { return false; }
/// Return true if the target can handle a standalone remainder operation.
virtual bool hasStandaloneRem(EVT VT) const {
@@ -363,6 +391,9 @@ public:
return false;
}
+ /// Returns if it's reasonable to merge stores to MemVT size.
+ virtual bool canMergeStoresTo(EVT MemVT) const { return true; }
+
/// \brief Return true if it is cheap to speculate a call to intrinsic cttz.
virtual bool isCheapToSpeculateCttz() const {
return false;
@@ -395,16 +426,33 @@ public:
/// \brief Return if the target supports combining a
/// chain like:
/// \code
- /// %andResult = and %val1, #imm-with-one-bit-set;
+ /// %andResult = and %val1, #mask
/// %icmpResult = icmp %andResult, 0
- /// br i1 %icmpResult, label %dest1, label %dest2
/// \endcode
/// into a single machine instruction of a form like:
/// \code
- /// brOnBitSet %register, #bitNumber, dest
+ /// cc = test %register, #mask
/// \endcode
- bool isMaskAndBranchFoldingLegal() const {
- return MaskAndBranchFoldingIsLegal;
+ virtual bool isMaskAndCmp0FoldingBeneficial(const Instruction &AndI) const {
+ return false;
+ }
+
+ /// Use bitwise logic to make pairs of compares more efficient. For example:
+ /// and (seteq A, B), (seteq C, D) --> seteq (or (xor A, B), (xor C, D)), 0
+ /// This should be true when it takes more than one instruction to lower
+ /// setcc (cmp+set on x86 scalar), when bitwise ops are faster than logic on
+ /// condition bits (crand on PowerPC), and/or when reducing cmp+br is a win.
+ virtual bool convertSetCCLogicToBitwiseLogic(EVT VT) const {
+ return false;
+ }
+
+ /// Return the preferred operand type if the target has a quick way to compare
+ /// integer values of the given size. Assume that any legal integer type can
+ /// be compared efficiently. Targets may override this to allow illegal wide
+ /// types to return a vector type if there is support to compare that type.
+ virtual MVT hasFastEqualityCompare(unsigned NumBits) const {
+ MVT VT = MVT::getIntegerVT(NumBits);
+ return isTypeLegal(VT) ? VT : MVT::INVALID_SIMPLE_VALUE_TYPE;
}
/// Return true if the target should transform:
@@ -987,6 +1035,11 @@ public:
return GatherAllAliasesMaxDepth;
}
+ /// Returns the size of the platform's va_list object.
+ virtual unsigned getVaListSizeInBits(const DataLayout &DL) const {
+ return getPointerTy(DL).getSizeInBits();
+ }
+
/// \brief Get maximum # of store operations permitted for llvm.memset
///
/// This function returns the maximum number of store operations permitted
@@ -1384,6 +1437,13 @@ public:
Action != TypeSplitVector;
}
+ /// Return true if a select of constants (select Cond, C1, C2) should be
+ /// transformed into simple math ops with the condition value. For example:
+ /// select Cond, C1, C1-1 --> add (zext Cond), C1-1
+ virtual bool convertSelectOfConstantsToMath() const {
+ return false;
+ }
+
//===--------------------------------------------------------------------===//
// TargetLowering Configuration Methods - These methods should be invoked by
// the derived class constructor to configure this object for the target.
@@ -1490,7 +1550,8 @@ protected:
void computeRegisterProperties(const TargetRegisterInfo *TRI);
/// Indicate that the specified operation does not work with the specified
- /// type and indicate what to do about it.
+ /// type and indicate what to do about it. Note that VT may refer to either
+ /// the type of a result or that of an operand of Op.
void setOperationAction(unsigned Op, MVT VT,
LegalizeAction Action) {
assert(Op < array_lengthof(OpActions[0]) && "Table isn't big enough!");
@@ -1642,10 +1703,9 @@ public:
/// possible to be done in the address mode for that operand. This hook lets
/// targets also pass back when this should be done on intrinsics which
/// load/store.
- virtual bool GetAddrModeArguments(IntrinsicInst * /*I*/,
+ virtual bool getAddrModeArguments(IntrinsicInst * /*I*/,
SmallVectorImpl<Value*> &/*Ops*/,
- Type *&/*AccessTy*/,
- unsigned AddrSpace = 0) const {
+ Type *&/*AccessTy*/) const {
return false;
}
@@ -2197,10 +2257,6 @@ protected:
/// the branch is usually predicted right.
bool PredictableSelectIsExpensive;
- /// MaskAndBranchFoldingIsLegal - Indicates if the target supports folding
- /// a mask of a single bit, a compare, and a branch into a single instruction.
- bool MaskAndBranchFoldingIsLegal;
-
/// \see enableExtLdPromotion.
bool EnableExtLdPromotion;
@@ -2357,11 +2413,11 @@ public:
/// expression and return a mask of KnownOne and KnownZero bits for the
/// expression (used to simplify the caller). The KnownZero/One bits may only
/// be accurate for those bits in the DemandedMask.
- /// \p AssumeSingleUse When this paramater is true, this function will
+ /// \p AssumeSingleUse When this parameter is true, this function will
/// attempt to simplify \p Op even if there are multiple uses.
/// Callers are responsible for correctly updating the DAG based on the
/// results of this function, because simply replacing replacing TLO.Old
- /// with TLO.New will be incorrect when this paramater is true and TLO.Old
+ /// with TLO.New will be incorrect when this parameter is true and TLO.Old
/// has multiple uses.
bool SimplifyDemandedBits(SDValue Op, const APInt &DemandedMask,
APInt &KnownZero, APInt &KnownOne,
@@ -2369,17 +2425,27 @@ public:
unsigned Depth = 0,
bool AssumeSingleUse = false) const;
+ /// Helper wrapper around SimplifyDemandedBits
+ bool SimplifyDemandedBits(SDValue Op, APInt &DemandedMask,
+ DAGCombinerInfo &DCI) const;
+
/// Determine which of the bits specified in Mask are known to be either zero
- /// or one and return them in the KnownZero/KnownOne bitsets.
+ /// or one and return them in the KnownZero/KnownOne bitsets. The DemandedElts
+ /// argument allows us to only collect the known bits that are shared by the
+ /// requested vector elements.
virtual void computeKnownBitsForTargetNode(const SDValue Op,
APInt &KnownZero,
APInt &KnownOne,
+ const APInt &DemandedElts,
const SelectionDAG &DAG,
unsigned Depth = 0) const;
/// This method can be implemented by targets that want to expose additional
- /// information about sign bits to the DAG Combiner.
+ /// information about sign bits to the DAG Combiner. The DemandedElts
+ /// argument allows us to only collect the minimum sign bits that are shared
+ /// by the requested vector elements.
virtual unsigned ComputeNumSignBitsForTargetNode(SDValue Op,
+ const APInt &DemandedElts,
const SelectionDAG &DAG,
unsigned Depth = 0) const;
@@ -2536,30 +2602,6 @@ public:
llvm_unreachable("Not Implemented");
}
- struct ArgListEntry {
- SDValue Node;
- Type* Ty;
- bool isSExt : 1;
- bool isZExt : 1;
- bool isInReg : 1;
- bool isSRet : 1;
- bool isNest : 1;
- bool isByVal : 1;
- bool isInAlloca : 1;
- bool isReturned : 1;
- bool isSwiftSelf : 1;
- bool isSwiftError : 1;
- uint16_t Alignment;
-
- ArgListEntry() : isSExt(false), isZExt(false), isInReg(false),
- isSRet(false), isNest(false), isByVal(false), isInAlloca(false),
- isReturned(false), isSwiftSelf(false), isSwiftError(false),
- Alignment(0) {}
-
- void setAttributes(ImmutableCallSite *CS, unsigned AttrIdx);
- };
- typedef std::vector<ArgListEntry> ArgListTy;
-
/// This structure contains all information that is necessary for lowering
/// calls. It is passed to TLI::LowerCallTo when the SelectionDAG builder
/// needs to lower a call, and targets will see this struct in their LowerCall
@@ -2609,6 +2651,20 @@ public:
return *this;
}
+ // setCallee with target/module-specific attributes
+ CallLoweringInfo &setLibCallee(CallingConv::ID CC, Type *ResultType,
+ SDValue Target, ArgListTy &&ArgsList) {
+ RetTy = ResultType;
+ Callee = Target;
+ CallConv = CC;
+ NumFixedArgs = Args.size();
+ Args = std::move(ArgsList);
+
+ DAG.getTargetLoweringInfo().markLibCallAttributes(
+ &(DAG.getMachineFunction()), CC, Args);
+ return *this;
+ }
+
CallLoweringInfo &setCallee(CallingConv::ID CC, Type *ResultType,
SDValue Target, ArgListTy &&ArgsList) {
RetTy = ResultType;
@@ -2624,15 +2680,15 @@ public:
ImmutableCallSite &Call) {
RetTy = ResultType;
- IsInReg = Call.paramHasAttr(0, Attribute::InReg);
+ IsInReg = Call.hasRetAttr(Attribute::InReg);
DoesNotReturn =
Call.doesNotReturn() ||
(!Call.isInvoke() &&
isa<UnreachableInst>(Call.getInstruction()->getNextNode()));
IsVarArg = FTy->isVarArg();
IsReturnValueUsed = !Call.getInstruction()->use_empty();
- RetSExt = Call.paramHasAttr(0, Attribute::SExt);
- RetZExt = Call.paramHasAttr(0, Attribute::ZExt);
+ RetSExt = Call.hasRetAttr(Attribute::SExt);
+ RetZExt = Call.hasRetAttr(Attribute::ZExt);
Callee = Target;
@@ -3183,7 +3239,7 @@ private:
/// Given an LLVM IR type and return type attributes, compute the return value
/// EVTs and flags, and optionally also the offsets, if the return value is
/// being lowered to memory.
-void GetReturnInfo(Type *ReturnType, AttributeSet attr,
+void GetReturnInfo(Type *ReturnType, AttributeList attr,
SmallVectorImpl<ISD::OutputArg> &Outs,
const TargetLowering &TLI, const DataLayout &DL);
diff --git a/include/llvm/Target/TargetLoweringObjectFile.h b/include/llvm/Target/TargetLoweringObjectFile.h
index 72bae0a38e65..0ffd4b7f8c78 100644
--- a/include/llvm/Target/TargetLoweringObjectFile.h
+++ b/include/llvm/Target/TargetLoweringObjectFile.h
@@ -16,37 +16,35 @@
#define LLVM_TARGET_TARGETLOWERINGOBJECTFILE_H
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/IR/Module.h"
#include "llvm/MC/MCObjectFileInfo.h"
#include "llvm/MC/SectionKind.h"
+#include <cstdint>
namespace llvm {
- class MachineModuleInfo;
- class Mangler;
- class MCContext;
- class MCExpr;
- class MCSection;
- class MCSymbol;
- class MCSymbolRefExpr;
- class MCStreamer;
- class MCValue;
- class ConstantExpr;
- class GlobalValue;
- class TargetMachine;
+
+class GlobalValue;
+class MachineModuleInfo;
+class Mangler;
+class MCContext;
+class MCExpr;
+class MCSection;
+class MCSymbol;
+class MCSymbolRefExpr;
+class MCStreamer;
+class MCValue;
+class TargetMachine;
class TargetLoweringObjectFile : public MCObjectFileInfo {
- MCContext *Ctx;
+ MCContext *Ctx = nullptr;
/// Name-mangler for global names.
Mangler *Mang = nullptr;
- TargetLoweringObjectFile(
- const TargetLoweringObjectFile&) = delete;
- void operator=(const TargetLoweringObjectFile&) = delete;
-
protected:
- bool SupportIndirectSymViaGOTPCRel;
- bool SupportGOTPCRelWithOffset;
+ bool SupportIndirectSymViaGOTPCRel = false;
+ bool SupportGOTPCRelWithOffset = true;
/// This section contains the static constructor pointer list.
MCSection *StaticCtorSection;
@@ -55,15 +53,15 @@ protected:
MCSection *StaticDtorSection;
public:
+ TargetLoweringObjectFile() = default;
+ TargetLoweringObjectFile(const TargetLoweringObjectFile &) = delete;
+ TargetLoweringObjectFile &
+ operator=(const TargetLoweringObjectFile &) = delete;
+ virtual ~TargetLoweringObjectFile();
+
MCContext &getContext() const { return *Ctx; }
Mangler &getMangler() const { return *Mang; }
- TargetLoweringObjectFile()
- : MCObjectFileInfo(), Ctx(nullptr), Mang(nullptr),
- SupportIndirectSymViaGOTPCRel(false), SupportGOTPCRelWithOffset(true) {}
-
- virtual ~TargetLoweringObjectFile();
-
/// This method must be called before any actual lowering is done. This
/// specifies the current context for codegen, and gives the lowering
/// implementations a chance to set up their default sections.
@@ -194,4 +192,4 @@ protected:
} // end namespace llvm
-#endif
+#endif // LLVM_TARGET_TARGETLOWERINGOBJECTFILE_H
diff --git a/include/llvm/Target/TargetMachine.h b/include/llvm/Target/TargetMachine.h
index b1d8f8f1e917..73ae2ad12988 100644
--- a/include/llvm/Target/TargetMachine.h
+++ b/include/llvm/Target/TargetMachine.h
@@ -34,6 +34,7 @@ class MCRegisterInfo;
class MCSubtargetInfo;
class MCSymbol;
class raw_pwrite_stream;
+class PassManagerBuilder;
class Target;
class TargetIntrinsicInfo;
class TargetIRAnalysis;
@@ -205,10 +206,9 @@ public:
/// uses this to answer queries about the IR.
virtual TargetIRAnalysis getTargetIRAnalysis();
- /// Add target-specific function passes that should be run as early as
- /// possible in the optimization pipeline. Most TargetMachines have no such
- /// passes.
- virtual void addEarlyAsPossiblePasses(PassManagerBase &) {}
+ /// Allow the target to modify the pass manager, e.g. by calling
+ /// PassManagerBuilder::addExtension.
+ virtual void adjustPassManager(PassManagerBuilder &) {}
/// 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
@@ -268,8 +268,8 @@ class LLVMTargetMachine : public TargetMachine {
protected: // Can only create subclasses.
LLVMTargetMachine(const Target &T, StringRef DataLayoutString,
const Triple &TargetTriple, StringRef CPU, StringRef FS,
- TargetOptions Options, Reloc::Model RM, CodeModel::Model CM,
- CodeGenOpt::Level OL);
+ const TargetOptions &Options, Reloc::Model RM,
+ CodeModel::Model CM, CodeGenOpt::Level OL);
void initAsmInfo();
public:
diff --git a/include/llvm/Target/TargetOpcodes.def b/include/llvm/Target/TargetOpcodes.def
index edb9b7350ca7..96db6e0a9769 100644
--- a/include/llvm/Target/TargetOpcodes.def
+++ b/include/llvm/Target/TargetOpcodes.def
@@ -107,6 +107,9 @@ HANDLE_TARGET_OPCODE(LIFETIME_END)
/// that must lie within the function and not contain another stackmap.
HANDLE_TARGET_OPCODE(STACKMAP)
+/// FEntry all - This is a marker instruction which gets translated into a raw fentry call.
+HANDLE_TARGET_OPCODE(FENTRY_CALL)
+
/// Patchable call instruction - this instruction represents a call to a
/// constant address, followed by a series of NOPs. It is intended to
/// support optimizations for dynamic languages (such as javascript) that
@@ -131,11 +134,13 @@ HANDLE_TARGET_OPCODE(STATEPOINT)
/// frame index of the local stack allocation.
HANDLE_TARGET_OPCODE(LOCAL_ESCAPE)
-/// Loading instruction that may page fault, bundled with associated
+/// Wraps a machine instruction which can fault, bundled with associated
+/// information on how to handle such a fault.
+/// For example loading instruction that may page fault, bundled with associated
/// information on how to handle such a page fault. It is intended to support
/// "zero cost" null checks in managed languages by allowing LLVM to fold
/// comparisons into existing memory operations.
-HANDLE_TARGET_OPCODE(FAULTING_LOAD_OP)
+HANDLE_TARGET_OPCODE(FAULTING_OP)
/// Wraps a machine instruction to add patchability constraints. An
/// instruction wrapped in PATCHABLE_OP has to either have a minimum
@@ -224,6 +229,8 @@ HANDLE_TARGET_OPCODE(G_GLOBAL_VALUE)
/// (typically a sub-register COPY after instruction selection).
HANDLE_TARGET_OPCODE(G_EXTRACT)
+HANDLE_TARGET_OPCODE(G_UNMERGE_VALUES)
+
/// Generic instruction to insert blocks of bits from the registers given into
/// the source.
HANDLE_TARGET_OPCODE(G_INSERT)
@@ -232,6 +239,8 @@ HANDLE_TARGET_OPCODE(G_INSERT)
/// larger register.
HANDLE_TARGET_OPCODE(G_SEQUENCE)
+HANDLE_TARGET_OPCODE(G_MERGE_VALUES)
+
/// Generic pointer to int conversion.
HANDLE_TARGET_OPCODE(G_PTRTOINT)
@@ -251,6 +260,9 @@ HANDLE_TARGET_OPCODE(G_STORE)
/// Generic conditional branch instruction.
HANDLE_TARGET_OPCODE(G_BRCOND)
+/// Generic indirect branch instruction.
+HANDLE_TARGET_OPCODE(G_BRINDIRECT)
+
/// Generic intrinsic use (without side effects).
HANDLE_TARGET_OPCODE(G_INTRINSIC)
@@ -272,6 +284,12 @@ HANDLE_TARGET_OPCODE(G_CONSTANT)
/// Generic floating constant.
HANDLE_TARGET_OPCODE(G_FCONSTANT)
+/// Generic va_start instruction. Stores to its one pointer operand.
+HANDLE_TARGET_OPCODE(G_VASTART)
+
+/// Generic va_start instruction. Stores to its one pointer operand.
+HANDLE_TARGET_OPCODE(G_VAARG)
+
// Generic sign extend
HANDLE_TARGET_OPCODE(G_SEXT)
@@ -320,6 +338,14 @@ HANDLE_TARGET_OPCODE(G_UMULO)
/// overflow flag.
HANDLE_TARGET_OPCODE(G_SMULO)
+// Multiply two numbers at twice the incoming bit width (unsigned) and return
+// the high half of the result.
+HANDLE_TARGET_OPCODE(G_UMULH)
+
+// Multiply two numbers at twice the incoming bit width (signed) and return
+// the high half of the result.
+HANDLE_TARGET_OPCODE(G_SMULH)
+
/// Generic FP addition.
HANDLE_TARGET_OPCODE(G_FADD)
@@ -335,7 +361,13 @@ HANDLE_TARGET_OPCODE(G_FDIV)
/// Generic FP remainder.
HANDLE_TARGET_OPCODE(G_FREM)
-/// Generic float to signed-int conversion
+/// Generic FP exponentiation.
+HANDLE_TARGET_OPCODE(G_FPOW)
+
+/// Generic FP negation.
+HANDLE_TARGET_OPCODE(G_FNEG)
+
+/// Generic FP extension.
HANDLE_TARGET_OPCODE(G_FPEXT)
/// Generic float to signed-int conversion
@@ -353,18 +385,31 @@ HANDLE_TARGET_OPCODE(G_SITOFP)
/// Generic unsigned-int to float conversion
HANDLE_TARGET_OPCODE(G_UITOFP)
-/// Generic unsigned-int to float conversion
+/// Generic pointer offset
HANDLE_TARGET_OPCODE(G_GEP)
+/// Clear the specified number of low bits in a pointer. This rounds the value
+/// *down* to the given alignment.
+HANDLE_TARGET_OPCODE(G_PTR_MASK)
+
/// Generic BRANCH instruction. This is an unconditional branch.
HANDLE_TARGET_OPCODE(G_BR)
+/// Generic insertelement.
+HANDLE_TARGET_OPCODE(G_INSERT_VECTOR_ELT)
+
+/// Generic extractelement.
+HANDLE_TARGET_OPCODE(G_EXTRACT_VECTOR_ELT)
+
+/// Generic shufflevector.
+HANDLE_TARGET_OPCODE(G_SHUFFLE_VECTOR)
+
// TODO: Add more generic opcodes as we move along.
/// Marker for the end of the generic opcode.
/// This is used to check if an opcode is in the range of the
/// generic opcodes.
-HANDLE_TARGET_OPCODE_MARKER(PRE_ISEL_GENERIC_OPCODE_END, G_BR)
+HANDLE_TARGET_OPCODE_MARKER(PRE_ISEL_GENERIC_OPCODE_END, G_SHUFFLE_VECTOR)
/// BUILTIN_OP_END - This must be the last enum value in this list.
/// The target-specific post-isel opcode values start here.
diff --git a/include/llvm/Target/TargetOptions.h b/include/llvm/Target/TargetOptions.h
index f5134d99b039..7cc33f2fdccb 100644
--- a/include/llvm/Target/TargetOptions.h
+++ b/include/llvm/Target/TargetOptions.h
@@ -99,22 +99,16 @@ namespace llvm {
class TargetOptions {
public:
TargetOptions()
- : PrintMachineCode(false), LessPreciseFPMADOption(false),
- UnsafeFPMath(false), NoInfsFPMath(false), NoNaNsFPMath(false),
- NoTrappingFPMath(false),
+ : PrintMachineCode(false), UnsafeFPMath(false), NoInfsFPMath(false),
+ NoNaNsFPMath(false), NoTrappingFPMath(false),
+ NoSignedZerosFPMath(false),
HonorSignDependentRoundingFPMathOption(false), NoZerosInBSS(false),
- GuaranteedTailCallOpt(false), StackAlignmentOverride(0),
- StackSymbolOrdering(true), EnableFastISel(false), UseInitArray(false),
+ GuaranteedTailCallOpt(false), StackSymbolOrdering(true),
+ EnableFastISel(false), UseInitArray(false),
DisableIntegratedAS(false), CompressDebugSections(false),
RelaxELFRelocations(false), FunctionSections(false),
DataSections(false), UniqueSectionNames(true), TrapUnreachable(false),
- EmulatedTLS(false), EnableIPRA(false),
- FloatABIType(FloatABI::Default),
- AllowFPOpFusion(FPOpFusion::Standard),
- ThreadModel(ThreadModel::POSIX),
- EABIVersion(EABI::Default), DebuggerTuning(DebuggerKind::Default),
- FPDenormalMode(FPDenormal::IEEE),
- ExceptionModel(ExceptionHandling::None) {}
+ EmulatedTLS(false), EnableIPRA(false) {}
/// PrintMachineCode - This flag is enabled when the -print-machineinstrs
/// option is specified on the command line, and should enable debugging
@@ -125,20 +119,11 @@ namespace llvm {
/// optimization should be disabled for the given machine function.
bool DisableFramePointerElim(const MachineFunction &MF) const;
- /// LessPreciseFPMAD - This flag is enabled when the
- /// -enable-fp-mad is specified on the command line. When this flag is off
- /// (the default), the code generator is not allowed to generate mad
- /// (multiply add) if the result is "less precise" than doing those
- /// operations individually.
- unsigned LessPreciseFPMADOption : 1;
- bool LessPreciseFPMAD() const;
-
/// UnsafeFPMath - This flag is enabled when the
/// -enable-unsafe-fp-math flag is specified on the command line. When
/// this flag is off (the default), the code generator is not allowed to
/// produce results that are "less precise" than IEEE allows. This includes
/// use of X86 instructions like FSIN and FCOS instead of libcalls.
- /// UnsafeFPMath implies LessPreciseFPMAD.
unsigned UnsafeFPMath : 1;
/// NoInfsFPMath - This flag is enabled when the
@@ -153,11 +138,17 @@ namespace llvm {
/// assume the FP arithmetic arguments and results are never NaNs.
unsigned NoNaNsFPMath : 1;
- /// NoTrappingFPMath - This flag is enabled when the
- /// -enable-no-trapping-fp-math is specified on the command line. This
+ /// NoTrappingFPMath - This flag is enabled when the
+ /// -enable-no-trapping-fp-math is specified on the command line. This
/// specifies that there are no trap handlers to handle exceptions.
unsigned NoTrappingFPMath : 1;
+ /// NoSignedZerosFPMath - This flag is enabled when the
+ /// -enable-no-signed-zeros-fp-math is specified on the command line. This
+ /// specifies that optimizations are allowed to treat the sign of a zero
+ /// argument or result as insignificant.
+ unsigned NoSignedZerosFPMath : 1;
+
/// HonorSignDependentRoundingFPMath - This returns true when the
/// -enable-sign-dependent-rounding-fp-math is specified. If this returns
/// false (the default), the code generator is allowed to assume that the
@@ -182,7 +173,7 @@ namespace llvm {
unsigned GuaranteedTailCallOpt : 1;
/// StackAlignmentOverride - Override default stack alignment for target.
- unsigned StackAlignmentOverride;
+ unsigned StackAlignmentOverride = 0;
/// StackSymbolOrdering - When true, this will allow CodeGen to order
/// the local stack symbols (for code size, code locality, or any other
@@ -231,7 +222,7 @@ namespace llvm {
/// 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;
+ FloatABI::ABIType FloatABIType = FloatABI::Default;
/// AllowFPOpFusion - This flag is set by the -fuse-fp-ops=xxx option.
/// This controls the creation of fused FP ops that store intermediate
@@ -249,65 +240,29 @@ namespace llvm {
/// optimizers. Fused operations that are explicitly specified (e.g. FMA
/// via the llvm.fma.* intrinsic) will always be honored, regardless of
/// the value of this option.
- FPOpFusion::FPOpFusionMode AllowFPOpFusion;
+ FPOpFusion::FPOpFusionMode AllowFPOpFusion = FPOpFusion::Standard;
/// ThreadModel - This flag specifies the type of threading model to assume
/// for things like atomics
- ThreadModel::Model ThreadModel;
+ ThreadModel::Model ThreadModel = ThreadModel::POSIX;
/// EABIVersion - This flag specifies the EABI version
- EABI EABIVersion;
+ EABI EABIVersion = EABI::Default;
/// Which debugger to tune for.
- DebuggerKind DebuggerTuning;
+ DebuggerKind DebuggerTuning = DebuggerKind::Default;
/// FPDenormalMode - This flags specificies which denormal numbers the code
/// is permitted to require.
- FPDenormal::DenormalMode FPDenormalMode;
+ FPDenormal::DenormalMode FPDenormalMode = FPDenormal::IEEE;
/// What exception model to use
- ExceptionHandling ExceptionModel;
+ ExceptionHandling ExceptionModel = ExceptionHandling::None;
/// Machine level options.
MCTargetOptions MCOptions;
};
-// Comparison operators:
-
-
-inline bool operator==(const TargetOptions &LHS,
- const TargetOptions &RHS) {
-#define ARE_EQUAL(X) LHS.X == RHS.X
- return
- ARE_EQUAL(UnsafeFPMath) &&
- ARE_EQUAL(NoInfsFPMath) &&
- ARE_EQUAL(NoNaNsFPMath) &&
- ARE_EQUAL(NoTrappingFPMath) &&
- ARE_EQUAL(HonorSignDependentRoundingFPMathOption) &&
- ARE_EQUAL(NoZerosInBSS) &&
- ARE_EQUAL(GuaranteedTailCallOpt) &&
- ARE_EQUAL(StackAlignmentOverride) &&
- ARE_EQUAL(EnableFastISel) &&
- ARE_EQUAL(UseInitArray) &&
- ARE_EQUAL(TrapUnreachable) &&
- ARE_EQUAL(EmulatedTLS) &&
- ARE_EQUAL(FloatABIType) &&
- ARE_EQUAL(AllowFPOpFusion) &&
- ARE_EQUAL(ThreadModel) &&
- ARE_EQUAL(EABIVersion) &&
- ARE_EQUAL(DebuggerTuning) &&
- ARE_EQUAL(FPDenormalMode) &&
- ARE_EQUAL(ExceptionModel) &&
- ARE_EQUAL(MCOptions) &&
- ARE_EQUAL(EnableIPRA);
-#undef ARE_EQUAL
-}
-
-inline bool operator!=(const TargetOptions &LHS,
- const TargetOptions &RHS) {
- return !(LHS == RHS);
-}
-
} // End llvm namespace
#endif
diff --git a/include/llvm/Target/TargetRegisterInfo.h b/include/llvm/Target/TargetRegisterInfo.h
index 3080e9a32c3a..3f5daea63ab5 100644
--- a/include/llvm/Target/TargetRegisterInfo.h
+++ b/include/llvm/Target/TargetRegisterInfo.h
@@ -45,6 +45,7 @@ public:
// Instance variables filled by tablegen, do not use!
const MCRegisterClass *MC;
+ const uint16_t SpillSize, SpillAlignment;
const vt_iterator VTs;
const uint32_t *SubClassMask;
const uint16_t *SuperRegIndices;
@@ -94,10 +95,10 @@ public:
/// Return the size of the register in bytes, which is also the size
/// of a stack slot allocated to hold a spilled copy of this register.
- unsigned getSize() const { return MC->getSize(); }
+ unsigned getSize() const { return SpillSize; }
/// Return the minimum required alignment for a register of this class.
- unsigned getAlignment() const { return MC->getAlignment(); }
+ unsigned getAlignment() const { return SpillAlignment; }
/// Return the cost of copying a value between two registers in this class.
/// A negative number means the register class is very expensive
@@ -426,7 +427,9 @@ public:
/// this target. The register should be in the order of desired callee-save
/// stack frame offset. The first register is closest to the incoming stack
/// pointer if stack grows down, and vice versa.
- ///
+ /// Notice: This function does not take into account disabled CSRs.
+ /// In most cases you will want to use instead the function
+ /// getCalleeSavedRegs that is implemented in MachineRegisterInfo.
virtual const MCPhysReg*
getCalleeSavedRegs(const MachineFunction *MF) const = 0;
@@ -633,6 +636,9 @@ public:
///
regclass_iterator regclass_begin() const { return RegClassBegin; }
regclass_iterator regclass_end() const { return RegClassEnd; }
+ iterator_range<regclass_iterator> regclasses() const {
+ return make_range(regclass_begin(), regclass_end());
+ }
unsigned getNumRegClasses() const {
return (unsigned)(regclass_end()-regclass_begin());
diff --git a/include/llvm/Target/TargetSchedule.td b/include/llvm/Target/TargetSchedule.td
index 74b98ac5f6c5..d342e4fe2613 100644
--- a/include/llvm/Target/TargetSchedule.td
+++ b/include/llvm/Target/TargetSchedule.td
@@ -139,7 +139,7 @@ class ProcResourceKind;
// changes this to an in-order issue/dispatch resource. In this case,
// the scheduler counts down from the cycle that the instruction
// issues in-order, forcing a stall whenever a subsequent instruction
-// requires the same resource until the number of ResourceCyles
+// requires the same resource until the number of ResourceCycles
// specified in WriteRes expire. Setting BufferSize=1 changes this to
// an in-order latency resource. In this case, the scheduler models
// producer/consumer stalls between instructions that use the
@@ -255,6 +255,9 @@ class ProcWriteResources<list<ProcResourceKind> resources> {
// Allow a processor to mark some scheduling classes as unsupported
// for stronger verification.
bit Unsupported = 0;
+ // Allow a processor to mark some scheduling classes as single-issue.
+ // SingleIssue is an alias for Begin/End Group.
+ bit SingleIssue = 0;
SchedMachineModel SchedModel = ?;
}
diff --git a/include/llvm/Target/TargetSelectionDAG.td b/include/llvm/Target/TargetSelectionDAG.td
index 55e2c2bce3db..45a842f77a21 100644
--- a/include/llvm/Target/TargetSelectionDAG.td
+++ b/include/llvm/Target/TargetSelectionDAG.td
@@ -136,30 +136,34 @@ def SDTIntUnaryOp : SDTypeProfile<1, 1, [ // ctlz
SDTCisSameAs<0, 1>, SDTCisInt<0>
]>;
def SDTIntExtendOp : SDTypeProfile<1, 1, [ // sext, zext, anyext
- SDTCisInt<0>, SDTCisInt<1>, SDTCisOpSmallerThanOp<1, 0>
+ SDTCisInt<0>, SDTCisInt<1>, SDTCisOpSmallerThanOp<1, 0>, SDTCisSameNumEltsAs<0, 1>
]>;
def SDTIntTruncOp : SDTypeProfile<1, 1, [ // trunc
- SDTCisInt<0>, SDTCisInt<1>, SDTCisOpSmallerThanOp<0, 1>
+ SDTCisInt<0>, SDTCisInt<1>, SDTCisOpSmallerThanOp<0, 1>, SDTCisSameNumEltsAs<0, 1>
]>;
def SDTFPUnaryOp : SDTypeProfile<1, 1, [ // fneg, fsqrt, etc
SDTCisSameAs<0, 1>, SDTCisFP<0>
]>;
def SDTFPRoundOp : SDTypeProfile<1, 1, [ // fround
- SDTCisFP<0>, SDTCisFP<1>, SDTCisOpSmallerThanOp<0, 1>
+ SDTCisFP<0>, SDTCisFP<1>, SDTCisOpSmallerThanOp<0, 1>, SDTCisSameNumEltsAs<0, 1>
]>;
def SDTFPExtendOp : SDTypeProfile<1, 1, [ // fextend
- SDTCisFP<0>, SDTCisFP<1>, SDTCisOpSmallerThanOp<1, 0>
+ SDTCisFP<0>, SDTCisFP<1>, SDTCisOpSmallerThanOp<1, 0>, SDTCisSameNumEltsAs<0, 1>
]>;
def SDTIntToFPOp : SDTypeProfile<1, 1, [ // [su]int_to_fp
- SDTCisFP<0>, SDTCisInt<1>
+ SDTCisFP<0>, SDTCisInt<1>, SDTCisSameNumEltsAs<0, 1>
]>;
def SDTFPToIntOp : SDTypeProfile<1, 1, [ // fp_to_[su]int
- SDTCisInt<0>, SDTCisFP<1>
+ SDTCisInt<0>, SDTCisFP<1>, SDTCisSameNumEltsAs<0, 1>
]>;
def SDTExtInreg : SDTypeProfile<1, 2, [ // sext_inreg
SDTCisSameAs<0, 1>, SDTCisInt<0>, SDTCisVT<2, OtherVT>,
SDTCisVTSmallerThanOp<2, 1>
]>;
+def SDTExtInvec : SDTypeProfile<1, 1, [ // sext_invec
+ SDTCisInt<0>, SDTCisVec<0>, SDTCisInt<1>, SDTCisVec<1>,
+ SDTCisOpSmallerThanOp<1, 0>, SDTCisSameSizeAs<0,1>
+]>;
def SDTSetCC : SDTypeProfile<1, 3, [ // setcc
SDTCisInt<0>, SDTCisSameAs<1, 2>, SDTCisVT<3, OtherVT>
@@ -170,7 +174,7 @@ def SDTSelect : SDTypeProfile<1, 3, [ // select
]>;
def SDTVSelect : SDTypeProfile<1, 3, [ // vselect
- SDTCisInt<1>, SDTCisSameAs<0, 2>, SDTCisSameAs<2, 3>, SDTCisSameNumEltsAs<0, 1>
+ SDTCisVec<0>, SDTCisInt<1>, SDTCisSameAs<0, 2>, SDTCisSameAs<2, 3>, SDTCisSameNumEltsAs<0, 1>
]>;
def SDTSelectCC : SDTypeProfile<1, 5, [ // select_cc
@@ -406,6 +410,10 @@ def umax : SDNode<"ISD::UMAX" , SDTIntBinOp,
[SDNPCommutative, SDNPAssociative]>;
def sext_inreg : SDNode<"ISD::SIGN_EXTEND_INREG", SDTExtInreg>;
+def sext_invec : SDNode<"ISD::SIGN_EXTEND_VECTOR_INREG", SDTExtInvec>;
+def zext_invec : SDNode<"ISD::ZERO_EXTEND_VECTOR_INREG", SDTExtInvec>;
+
+def abs : SDNode<"ISD::ABS" , SDTIntUnaryOp>;
def bitreverse : SDNode<"ISD::BITREVERSE" , SDTIntUnaryOp>;
def bswap : SDNode<"ISD::BSWAP" , SDTIntUnaryOp>;
def ctlz : SDNode<"ISD::CTLZ" , SDTIntUnaryOp>;
diff --git a/include/llvm/Target/TargetSubtargetInfo.h b/include/llvm/Target/TargetSubtargetInfo.h
index 0b4351596021..83950a9cd027 100644
--- a/include/llvm/Target/TargetSubtargetInfo.h
+++ b/include/llvm/Target/TargetSubtargetInfo.h
@@ -20,6 +20,7 @@
#include "llvm/CodeGen/PBQPRAConstraint.h"
#include "llvm/CodeGen/SchedulerRegistry.h"
#include "llvm/CodeGen/ScheduleDAGMutation.h"
+#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/Support/CodeGen.h"
#include <memory>
@@ -143,6 +144,9 @@ public:
/// TargetLowering preference). It does not yet disable the postRA scheduler.
virtual bool enableMachineScheduler() const;
+ /// \brief Support printing of [latency:throughput] comment in output .S file.
+ virtual bool supportPrintSchedInfo() const { return false; }
+
/// \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; }
@@ -227,6 +231,10 @@ public:
/// Please use MachineRegisterInfo::subRegLivenessEnabled() instead where
/// possible.
virtual bool enableSubRegLiveness() const { return false; }
+
+ /// Returns string representation of scheduler comment
+ std::string getSchedInfoStr(const MachineInstr &MI) const override;
+ std::string getSchedInfoStr(MCInst const &MCI) const override;
};
} // end namespace llvm
diff --git a/include/llvm/Transforms/IPO.h b/include/llvm/Transforms/IPO.h
index dd55062e56f1..39ceb19525b3 100644
--- a/include/llvm/Transforms/IPO.h
+++ b/include/llvm/Transforms/IPO.h
@@ -50,12 +50,12 @@ ModulePass *createStripNonLineTableDebugInfoPass();
//===----------------------------------------------------------------------===//
//
-// These pass removes llvm.dbg.declare intrinsics.
+// This pass removes llvm.dbg.declare intrinsics.
ModulePass *createStripDebugDeclarePass();
//===----------------------------------------------------------------------===//
//
-// These pass removes unused symbols' debug info.
+// This pass removes unused symbols' debug info.
ModulePass *createStripDeadDebugInfoPass();
//===----------------------------------------------------------------------===//
@@ -108,7 +108,8 @@ Pass *createFunctionImportPass();
/// threshold given here.
Pass *createFunctionInliningPass();
Pass *createFunctionInliningPass(int Threshold);
-Pass *createFunctionInliningPass(unsigned OptLevel, unsigned SizeOptLevel);
+Pass *createFunctionInliningPass(unsigned OptLevel, unsigned SizeOptLevel,
+ bool DisableInlineHotCallSite);
Pass *createFunctionInliningPass(InlineParams &Params);
//===----------------------------------------------------------------------===//
@@ -215,27 +216,42 @@ ModulePass *createMetaRenamerPass();
/// manager.
ModulePass *createBarrierNoopPass();
-/// What to do with the summary when running the LowerTypeTests pass.
-enum class LowerTypeTestsSummaryAction {
+/// What to do with the summary when running passes that operate on it.
+enum class PassSummaryAction {
None, ///< Do nothing.
- Import, ///< Import typeid resolutions from summary and globals.
- Export, ///< Export typeid resolutions to summary and globals.
+ Import, ///< Import information from summary.
+ Export, ///< Export information to summary.
};
/// \brief This pass lowers type metadata and the llvm.type.test intrinsic to
/// bitsets.
-/// \param Action What to do with the summary passed as Index.
-/// \param Index The summary to use for importing or exporting, this can be null
-/// when Action is None.
-ModulePass *createLowerTypeTestsPass(LowerTypeTestsSummaryAction Action,
- ModuleSummaryIndex *Index);
+///
+/// The behavior depends on the summary arguments:
+/// - If ExportSummary is non-null, this pass will export type identifiers to
+/// the given summary.
+/// - Otherwise, if ImportSummary is non-null, this pass will import type
+/// identifiers from the given summary.
+/// - Otherwise it does neither.
+/// It is invalid for both ExportSummary and ImportSummary to be non-null.
+ModulePass *createLowerTypeTestsPass(ModuleSummaryIndex *ExportSummary,
+ const ModuleSummaryIndex *ImportSummary);
/// \brief This pass export CFI checks for use by external modules.
ModulePass *createCrossDSOCFIPass();
/// \brief This pass implements whole-program devirtualization using type
/// metadata.
-ModulePass *createWholeProgramDevirtPass();
+///
+/// The behavior depends on the summary arguments:
+/// - If ExportSummary is non-null, this pass will export type identifiers to
+/// the given summary.
+/// - Otherwise, if ImportSummary is non-null, this pass will import type
+/// identifiers from the given summary.
+/// - Otherwise it does neither.
+/// It is invalid for both ExportSummary and ImportSummary to be non-null.
+ModulePass *
+createWholeProgramDevirtPass(ModuleSummaryIndex *ExportSummary,
+ const ModuleSummaryIndex *ImportSummary);
/// This pass splits globals into pieces for the benefit of whole-program
/// devirtualization and control-flow integrity.
@@ -248,7 +264,8 @@ ModulePass *createSampleProfileLoaderPass();
ModulePass *createSampleProfileLoaderPass(StringRef Name);
/// Write ThinLTO-ready bitcode to Str.
-ModulePass *createWriteThinLTOBitcodePass(raw_ostream &Str);
+ModulePass *createWriteThinLTOBitcodePass(raw_ostream &Str,
+ raw_ostream *ThinLinkOS = nullptr);
} // End llvm namespace
diff --git a/include/llvm/Transforms/IPO/ArgumentPromotion.h b/include/llvm/Transforms/IPO/ArgumentPromotion.h
new file mode 100644
index 000000000000..724ff72f3b5a
--- /dev/null
+++ b/include/llvm/Transforms/IPO/ArgumentPromotion.h
@@ -0,0 +1,31 @@
+//===- ArgumentPromotion.h - Promote by-reference arguments -----*- 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_IPO_ARGUMENTPROMOTION_H
+#define LLVM_TRANSFORMS_IPO_ARGUMENTPROMOTION_H
+
+#include "llvm/Analysis/CGSCCPassManager.h"
+#include "llvm/Analysis/LazyCallGraph.h"
+
+namespace llvm {
+
+/// Argument promotion pass.
+///
+/// This pass walks the functions in each SCC and for each one tries to
+/// transform it and all of its callers to replace indirect arguments with
+/// direct (by-value) arguments.
+class ArgumentPromotionPass : public PassInfoMixin<ArgumentPromotionPass> {
+public:
+ PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
+ LazyCallGraph &CG, CGSCCUpdateResult &UR);
+};
+
+}
+
+#endif
diff --git a/include/llvm/Transforms/IPO/FunctionAttrs.h b/include/llvm/Transforms/IPO/FunctionAttrs.h
index ee45f35bf11b..85d6364c8bbc 100644
--- a/include/llvm/Transforms/IPO/FunctionAttrs.h
+++ b/include/llvm/Transforms/IPO/FunctionAttrs.h
@@ -20,6 +20,19 @@
namespace llvm {
+class AAResults;
+
+/// The three kinds of memory access relevant to 'readonly' and
+/// 'readnone' attributes.
+enum MemoryAccessKind {
+ MAK_ReadNone = 0,
+ MAK_ReadOnly = 1,
+ MAK_MayWrite = 2
+};
+
+/// Returns the memory access properties of this copy of the function.
+MemoryAccessKind computeFunctionBodyMemoryAccess(Function &F, AAResults &AAR);
+
/// Computes function attributes in post-order over the call graph.
///
/// By operating in post-order, this pass computes precise attributes for
@@ -43,7 +56,7 @@ Pass *createPostOrderFunctionAttrsLegacyPass();
/// This pass provides a general RPO or "top down" propagation of
/// function attributes. For a few (rare) cases, we can deduce significantly
/// more about function attributes by working in RPO, so this pass
-/// provides the compliment to the post-order pass above where the majority of
+/// provides the complement to the post-order pass above where the majority of
/// deduction is performed.
// FIXME: Currently there is no RPO CGSCC pass structure to slide into and so
// this is a boring module pass, but eventually it should be an RPO CGSCC pass
diff --git a/include/llvm/Transforms/IPO/FunctionImport.h b/include/llvm/Transforms/IPO/FunctionImport.h
index eaea092c9179..ed5742ab8b56 100644
--- a/include/llvm/Transforms/IPO/FunctionImport.h
+++ b/include/llvm/Transforms/IPO/FunctionImport.h
@@ -53,12 +53,8 @@ public:
: Index(Index), ModuleLoader(std::move(ModuleLoader)) {}
/// Import functions in Module \p M based on the supplied import list.
- /// \p ForceImportReferencedDiscardableSymbols will set the ModuleLinker in
- /// a mode where referenced discarable symbols in the source modules will be
- /// imported as well even if they are not present in the ImportList.
Expected<bool>
- importFunctions(Module &M, const ImportMapTy &ImportList,
- bool ForceImportReferencedDiscardableSymbols = false);
+ importFunctions(Module &M, const ImportMapTy &ImportList);
private:
/// The summaries index used to trigger importing.
diff --git a/include/llvm/Transforms/IPO/GlobalDCE.h b/include/llvm/Transforms/IPO/GlobalDCE.h
index 57e174c2a37f..9ca939c15b62 100644
--- a/include/llvm/Transforms/IPO/GlobalDCE.h
+++ b/include/llvm/Transforms/IPO/GlobalDCE.h
@@ -18,6 +18,8 @@
#ifndef LLVM_TRANSFORMS_IPO_GLOBALDCE_H
#define LLVM_TRANSFORMS_IPO_GLOBALDCE_H
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallSet.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/PassManager.h"
#include <unordered_map>
@@ -31,14 +33,23 @@ public:
private:
SmallPtrSet<GlobalValue*, 32> AliveGlobals;
- SmallPtrSet<Constant *, 8> SeenConstants;
+
+ /// Global -> Global that uses this global.
+ std::unordered_multimap<GlobalValue *, GlobalValue *> GVDependencies;
+
+ /// Constant -> Globals that use this global cache.
+ std::unordered_map<Constant *, SmallPtrSet<GlobalValue *, 8>>
+ ConstantDependenciesCache;
+
+ /// Comdat -> Globals in that Comdat section.
std::unordered_multimap<Comdat *, GlobalValue *> ComdatMembers;
- /// Mark the specific global value as needed, and
- /// recursively mark anything that it uses as also needed.
- void GlobalIsNeeded(GlobalValue *GV);
- void MarkUsedGlobalsAsNeeded(Constant *C);
+ void UpdateGVDependencies(GlobalValue &GV);
+ void MarkLive(GlobalValue &GV,
+ SmallVectorImpl<GlobalValue *> *Updates = nullptr);
bool RemoveUnusedGlobalValue(GlobalValue &GV);
+
+ void ComputeDependencies(Value *V, SmallPtrSetImpl<GlobalValue *> &U);
};
}
diff --git a/include/llvm/Transforms/IPO/LowerTypeTests.h b/include/llvm/Transforms/IPO/LowerTypeTests.h
index ca6e1b878dff..a2b888ce9ffa 100644
--- a/include/llvm/Transforms/IPO/LowerTypeTests.h
+++ b/include/llvm/Transforms/IPO/LowerTypeTests.h
@@ -15,11 +15,9 @@
#ifndef LLVM_TRANSFORMS_IPO_LOWERTYPETESTS_H
#define LLVM_TRANSFORMS_IPO_LOWERTYPETESTS_H
-#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/PassManager.h"
-
#include <cstdint>
#include <cstring>
#include <limits>
@@ -28,9 +26,6 @@
namespace llvm {
-class DataLayout;
-class GlobalObject;
-class Value;
class raw_ostream;
namespace lowertypetests {
@@ -65,9 +60,10 @@ struct BitSetInfo {
struct BitSetBuilder {
SmallVector<uint64_t, 16> Offsets;
- uint64_t Min, Max;
+ uint64_t Min = std::numeric_limits<uint64_t>::max();
+ uint64_t Max = 0;
- BitSetBuilder() : Min(std::numeric_limits<uint64_t>::max()), Max(0) {}
+ BitSetBuilder() = default;
void addOffset(uint64_t Offset) {
if (Min > Offset)
diff --git a/include/llvm/Transforms/IPO/PassManagerBuilder.h b/include/llvm/Transforms/IPO/PassManagerBuilder.h
index abfb24f0fe50..247382c35eeb 100644
--- a/include/llvm/Transforms/IPO/PassManagerBuilder.h
+++ b/include/llvm/Transforms/IPO/PassManagerBuilder.h
@@ -21,6 +21,7 @@
#include <vector>
namespace llvm {
+class ModuleSummaryIndex;
class Pass;
class TargetLibraryInfoImpl;
class TargetMachine;
@@ -100,6 +101,14 @@ public:
/// will be inserted after each instance of the instruction combiner pass.
EP_Peephole,
+ /// EP_LateLoopOptimizations - This extension point allows adding late loop
+ /// canonicalization and simplification passes. This is the last point in
+ /// the loop optimization pipeline before loop deletion. Each pass added
+ /// here must be an instance of LoopPass.
+ /// This is the place to add passes that can remove loops, such as target-
+ /// specific loop idiom recognition.
+ EP_LateLoopOptimizations,
+
/// EP_CGSCCOptimizerLate - This extension point allows adding CallGraphSCC
/// passes at the end of the main CallGraphSCC passes and before any
/// function simplification passes run by CGPassManager.
@@ -123,6 +132,16 @@ public:
/// added to the per-module passes.
Pass *Inliner;
+ /// The module summary index to use for exporting information from the
+ /// regular LTO phase, for example for the CFI and devirtualization type
+ /// tests.
+ ModuleSummaryIndex *ExportSummary = nullptr;
+
+ /// The module summary index to use for importing information to the
+ /// thin LTO backends, for example for the CFI and devirtualization type
+ /// tests.
+ const ModuleSummaryIndex *ImportSummary = nullptr;
+
bool DisableTailCalls;
bool DisableUnitAtATime;
bool DisableUnrollLoops;
@@ -139,6 +158,7 @@ public:
bool PrepareForLTO;
bool PrepareForThinLTO;
bool PerformThinLTO;
+ bool DivergentTarget;
/// Enable profile instrumentation pass.
bool EnablePGOInstrGen;
diff --git a/include/llvm/Transforms/InstrProfiling.h b/include/llvm/Transforms/InstrProfiling.h
index b7c2935f4d84..65e69761badd 100644
--- a/include/llvm/Transforms/InstrProfiling.h
+++ b/include/llvm/Transforms/InstrProfiling.h
@@ -1,4 +1,4 @@
-//===- Transforms/InstrProfiling.h - Instrumentation passes ---*- C++ -*-===//
+//===- Transforms/InstrProfiling.h - Instrumentation passes -----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -14,10 +14,16 @@
#ifndef LLVM_TRANSFORMS_INSTRPROFILING_H
#define LLVM_TRANSFORMS_INSTRPROFILING_H
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/PassManager.h"
#include "llvm/ProfileData/InstrProf.h"
#include "llvm/Transforms/Instrumentation.h"
+#include <cstddef>
+#include <cstdint>
+#include <cstring>
+#include <vector>
namespace llvm {
@@ -28,7 +34,7 @@ class TargetLibraryInfo;
/// instrumentation pass.
class InstrProfiling : public PassInfoMixin<InstrProfiling> {
public:
- InstrProfiling() {}
+ InstrProfiling() = default;
InstrProfiling(const InstrProfOptions &Options) : Options(Options) {}
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
@@ -37,12 +43,14 @@ public:
private:
InstrProfOptions Options;
Module *M;
+ Triple TT;
const TargetLibraryInfo *TLI;
struct PerFunctionProfileData {
uint32_t NumValueSites[IPVK_Last + 1];
- GlobalVariable *RegionCounters;
- GlobalVariable *DataVar;
- PerFunctionProfileData() : RegionCounters(nullptr), DataVar(nullptr) {
+ GlobalVariable *RegionCounters = nullptr;
+ GlobalVariable *DataVar = nullptr;
+
+ PerFunctionProfileData() {
memset(NumValueSites, 0, sizeof(uint32_t) * (IPVK_Last + 1));
}
};
@@ -52,19 +60,10 @@ private:
GlobalVariable *NamesVar;
size_t NamesSize;
- bool isMachO() const;
-
- /// Get the section name for the counter variables.
- StringRef getCountersSection() const;
-
- /// Get the section name for the name variables.
- StringRef getNameSection() const;
-
- /// Get the section name for the profile data variables.
- StringRef getDataSection() const;
-
- /// Get the section name for the coverage mapping data.
- StringRef getCoverageSection() const;
+ // The start value of precise value profile range for memory intrinsic sizes.
+ int64_t MemOPSizeRangeStart;
+ // The end value of precise value profile range for memory intrinsic sizes.
+ int64_t MemOPSizeRangeLast;
/// Count the number of instrumented value sites for the function.
void computeNumValueSiteCounts(InstrProfValueProfileInst *Ins);
@@ -104,5 +103,6 @@ private:
void emitInitialization();
};
-} // End llvm namespace
-#endif
+} // end namespace llvm
+
+#endif // LLVM_TRANSFORMS_INSTRPROFILING_H
diff --git a/include/llvm/Transforms/Instrumentation.h b/include/llvm/Transforms/Instrumentation.h
index 7fb9a5442081..01a3975a4f2c 100644
--- a/include/llvm/Transforms/Instrumentation.h
+++ b/include/llvm/Transforms/Instrumentation.h
@@ -16,6 +16,10 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/IR/BasicBlock.h"
+#include <cassert>
+#include <cstdint>
+#include <limits>
+#include <string>
#include <vector>
#if defined(__GNUC__) && defined(__linux__) && !defined(ANDROID)
@@ -34,7 +38,8 @@ inline void *getDFSanRetValTLSPtrForJIT() {
namespace llvm {
-class TargetMachine;
+class FunctionPass;
+class ModulePass;
/// Instrumentation passes often insert conditional checks into entry blocks.
/// Call this function before splitting the entry block to move instructions
@@ -44,9 +49,6 @@ class TargetMachine;
BasicBlock::iterator PrepareToSplitEntryBlock(BasicBlock &BB,
BasicBlock::iterator IP);
-class ModulePass;
-class FunctionPass;
-
// Insert GCOV profiling instrumentation
struct GCOVOptions {
static GCOVOptions getDefault();
@@ -76,6 +78,7 @@ struct GCOVOptions {
// all of the function body's blocks.
bool ExitBlockBeforeBody;
};
+
ModulePass *createGCOVProfilerPass(const GCOVOptions &Options =
GCOVOptions::getDefault());
@@ -83,17 +86,40 @@ ModulePass *createGCOVProfilerPass(const GCOVOptions &Options =
ModulePass *createPGOInstrumentationGenLegacyPass();
ModulePass *
createPGOInstrumentationUseLegacyPass(StringRef Filename = StringRef(""));
-ModulePass *createPGOIndirectCallPromotionLegacyPass(bool InLTO = false);
+ModulePass *createPGOIndirectCallPromotionLegacyPass(bool InLTO = false,
+ bool SamplePGO = false);
+FunctionPass *createPGOMemOPSizeOptLegacyPass();
+
+// Helper function to check if it is legal to promote indirect call \p Inst
+// to a direct call of function \p F. Stores the reason in \p Reason.
+bool isLegalToPromote(Instruction *Inst, Function *F, const char **Reason);
+
+// Helper function that transforms Inst (either an indirect-call instruction, or
+// an invoke instruction , to a conditional call to F. This is like:
+// if (Inst.CalledValue == F)
+// F(...);
+// else
+// Inst(...);
+// end
+// TotalCount is the profile count value that the instruction executes.
+// Count is the profile count value that F is the target function.
+// These two values are used to update the branch weight.
+// If \p AttachProfToDirectCall is true, a prof metadata is attached to the
+// new direct call to contain \p Count.
+// Returns the promoted direct call instruction.
+Instruction *promoteIndirectCall(Instruction *Inst, Function *F, uint64_t Count,
+ uint64_t TotalCount,
+ bool AttachProfToDirectCall);
/// Options for the frontend instrumentation based profiling pass.
struct InstrProfOptions {
- InstrProfOptions() : NoRedZone(false) {}
-
// Add the 'noredzone' attribute to added runtime library calls.
- bool NoRedZone;
+ bool NoRedZone = false;
// Name of the profile file to use as output
std::string InstrProfileOutput;
+
+ InstrProfOptions() = default;
};
/// Insert frontend instrumentation based profiling.
@@ -121,12 +147,13 @@ ModulePass *createDataFlowSanitizerPass(
// Options for EfficiencySanitizer sub-tools.
struct EfficiencySanitizerOptions {
- EfficiencySanitizerOptions() : ToolType(ESAN_None) {}
enum Type {
ESAN_None = 0,
ESAN_CacheFrag,
ESAN_WorkingSet,
- } ToolType;
+ } ToolType = ESAN_None;
+
+ EfficiencySanitizerOptions() = default;
};
// Insert EfficiencySanitizer instrumentation.
@@ -135,25 +162,22 @@ ModulePass *createEfficiencySanitizerPass(
// Options for sanitizer coverage instrumentation.
struct SanitizerCoverageOptions {
- SanitizerCoverageOptions()
- : CoverageType(SCK_None), IndirectCalls(false), TraceBB(false),
- TraceCmp(false), TraceDiv(false), TraceGep(false),
- Use8bitCounters(false), TracePC(false), TracePCGuard(false) {}
-
enum Type {
SCK_None = 0,
SCK_Function,
SCK_BB,
SCK_Edge
- } CoverageType;
- bool IndirectCalls;
- bool TraceBB;
- bool TraceCmp;
- bool TraceDiv;
- bool TraceGep;
- bool Use8bitCounters;
- bool TracePC;
- bool TracePCGuard;
+ } CoverageType = SCK_None;
+ bool IndirectCalls = false;
+ bool TraceBB = false;
+ bool TraceCmp = false;
+ bool TraceDiv = false;
+ bool TraceGep = false;
+ bool Use8bitCounters = false;
+ bool TracePC = false;
+ bool TracePCGuard = false;
+
+ SanitizerCoverageOptions() = default;
};
// Insert SanitizerCoverage instrumentation.
@@ -175,9 +199,11 @@ FunctionPass *createBoundsCheckingPass();
/// \brief Calculate what to divide by to scale counts.
///
/// Given the maximum count, calculate a divisor that will scale all the
-/// weights to strictly less than UINT32_MAX.
+/// weights to strictly less than std::numeric_limits<uint32_t>::max().
static inline uint64_t calculateCountScale(uint64_t MaxCount) {
- return MaxCount < UINT32_MAX ? 1 : MaxCount / UINT32_MAX + 1;
+ return MaxCount < std::numeric_limits<uint32_t>::max()
+ ? 1
+ : MaxCount / std::numeric_limits<uint32_t>::max() + 1;
}
/// \brief Scale an individual branch count.
@@ -186,10 +212,10 @@ static inline uint64_t calculateCountScale(uint64_t MaxCount) {
///
static inline uint32_t scaleBranchCount(uint64_t Count, uint64_t Scale) {
uint64_t Scaled = Count / Scale;
- assert(Scaled <= UINT32_MAX && "overflow 32-bits");
+ assert(Scaled <= std::numeric_limits<uint32_t>::max() && "overflow 32-bits");
return Scaled;
}
-} // End llvm namespace
+} // end namespace llvm
-#endif
+#endif // LLVM_TRANSFORMS_INSTRUMENTATION_H
diff --git a/include/llvm/Transforms/PGOInstrumentation.h b/include/llvm/Transforms/PGOInstrumentation.h
index 1b449c9abdc2..19263f0f8071 100644
--- a/include/llvm/Transforms/PGOInstrumentation.h
+++ b/include/llvm/Transforms/PGOInstrumentation.h
@@ -38,11 +38,24 @@ private:
/// The indirect function call promotion pass.
class PGOIndirectCallPromotion : public PassInfoMixin<PGOIndirectCallPromotion> {
public:
- PGOIndirectCallPromotion(bool IsInLTO = false) : InLTO(IsInLTO) {}
+ PGOIndirectCallPromotion(bool IsInLTO = false, bool SamplePGO = false)
+ : InLTO(IsInLTO), SamplePGO(SamplePGO) {}
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
+
private:
bool InLTO;
+ bool SamplePGO;
};
+/// The profile size based optimization pass for memory intrinsics.
+class PGOMemOPSizeOpt : public PassInfoMixin<PGOMemOPSizeOpt> {
+public:
+ PGOMemOPSizeOpt() {}
+ PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
+};
+
+void setProfMetadata(Module *M, Instruction *TI, ArrayRef<uint64_t> EdgeCounts,
+ uint64_t MaxCount);
+
} // End llvm namespace
#endif
diff --git a/include/llvm/Transforms/Scalar.h b/include/llvm/Transforms/Scalar.h
index 92558937d047..ba0a3ee1287a 100644
--- a/include/llvm/Transforms/Scalar.h
+++ b/include/llvm/Transforms/Scalar.h
@@ -147,6 +147,12 @@ Pass *createLoopSinkPass();
//===----------------------------------------------------------------------===//
//
+// LoopPredication - This pass does loop predication on guards.
+//
+Pass *createLoopPredicationPass();
+
+//===----------------------------------------------------------------------===//
+//
// LoopInterchange - This pass interchanges loops to provide a more
// cache-friendly memory access patterns.
//
@@ -163,7 +169,8 @@ Pass *createLoopStrengthReducePass();
//
// LoopUnswitch - This pass is a simple loop unswitching pass.
//
-Pass *createLoopUnswitchPass(bool OptimizeForSize = false);
+Pass *createLoopUnswitchPass(bool OptimizeForSize = false,
+ bool hasBranchDivergence = false);
//===----------------------------------------------------------------------===//
//
@@ -175,11 +182,11 @@ Pass *createLoopInstSimplifyPass();
//
// LoopUnroll - This pass is a simple loop unrolling pass.
//
-Pass *createLoopUnrollPass(int Threshold = -1, int Count = -1,
+Pass *createLoopUnrollPass(int OptLevel = 2, int Threshold = -1, int Count = -1,
int AllowPartial = -1, int Runtime = -1,
int UpperBound = -1);
// Create an unrolling pass for full unrolling that uses exact trip count only.
-Pass *createSimpleLoopUnrollPass();
+Pass *createSimpleLoopUnrollPass(int OptLevel = 2);
//===----------------------------------------------------------------------===//
//
@@ -255,6 +262,14 @@ FunctionPass *createCFGSimplificationPass(
//===----------------------------------------------------------------------===//
//
+// LateCFGSimplification - Like CFGSimplification, but may also
+// convert switches to lookup tables.
+//
+FunctionPass *createLateCFGSimplificationPass(
+ int Threshold = -1, std::function<bool(const Function &)> Ftor = nullptr);
+
+//===----------------------------------------------------------------------===//
+//
// FlattenCFG - flatten CFG, reduce number of conditional branches by using
// parallel-and and parallel-or mode, etc...
//
@@ -406,6 +421,15 @@ Pass *createCorrelatedValuePropagationPass();
//===----------------------------------------------------------------------===//
//
+// InferAddressSpaces - Modify users of addrspacecast instructions with values
+// in the source address space if using the destination address space is slower
+// on the target.
+//
+FunctionPass *createInferAddressSpacesPass();
+extern char &InferAddressSpacesID;
+
+//===----------------------------------------------------------------------===//
+//
// InstructionSimplifier - Remove redundant instructions.
//
FunctionPass *createInstructionSimplifierPass();
diff --git a/include/llvm/Transforms/Scalar/GVNExpression.h b/include/llvm/Transforms/Scalar/GVNExpression.h
index 3458696e0687..2670a0c1a533 100644
--- a/include/llvm/Transforms/Scalar/GVNExpression.h
+++ b/include/llvm/Transforms/Scalar/GVNExpression.h
@@ -1,4 +1,4 @@
-//======- GVNExpression.h - GVN Expression classes -------*- C++ -*-==-------=//
+//======- GVNExpression.h - GVN Expression classes --------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -17,18 +17,22 @@
#define LLVM_TRANSFORMS_SCALAR_GVNEXPRESSION_H
#include "llvm/ADT/Hashing.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/Analysis/MemorySSA.h"
#include "llvm/IR/Constant.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Value.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/ArrayRecycler.h"
+#include "llvm/Support/Casting.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
-#include "llvm/Transforms/Utils/MemorySSA.h"
#include <algorithm>
+#include <cassert>
+#include <iterator>
+#include <utility>
namespace llvm {
-class MemoryAccess;
namespace GVNExpression {
@@ -39,11 +43,13 @@ enum ExpressionType {
ET_Unknown,
ET_BasicStart,
ET_Basic,
- ET_Call,
ET_AggregateValue,
ET_Phi,
+ ET_MemoryStart,
+ ET_Call,
ET_Load,
ET_Store,
+ ET_MemoryEnd,
ET_BasicEnd
};
@@ -53,23 +59,22 @@ private:
unsigned Opcode;
public:
- Expression(const Expression &) = delete;
Expression(ExpressionType ET = ET_Base, unsigned O = ~2U)
: EType(ET), Opcode(O) {}
- void operator=(const Expression &) = delete;
+ Expression(const Expression &) = delete;
+ Expression &operator=(const Expression &) = delete;
virtual ~Expression();
static unsigned getEmptyKey() { return ~0U; }
static unsigned getTombstoneKey() { return ~1U; }
-
+ bool operator!=(const Expression &Other) const { return !(*this == Other); }
bool operator==(const Expression &Other) const {
if (getOpcode() != Other.getOpcode())
return false;
if (getOpcode() == getEmptyKey() || getOpcode() == getTombstoneKey())
return true;
// Compare the expression type for anything but load and store.
- // For load and store we set the opcode to zero.
- // This is needed for load coercion.
+ // For load and store we set the opcode to zero to make them equal.
if (getExpressionType() != ET_Load && getExpressionType() != ET_Store &&
getExpressionType() != Other.getExpressionType())
return false;
@@ -83,9 +88,8 @@ public:
void setOpcode(unsigned opcode) { Opcode = opcode; }
ExpressionType getExpressionType() const { return EType; }
- virtual hash_code getHashValue() const {
- return hash_combine(getExpressionType(), getOpcode());
- }
+ // We deliberately leave the expression type out of the hash value.
+ virtual hash_code getHashValue() const { return getOpcode(); }
//
// Debugging support
@@ -101,7 +105,11 @@ public:
printInternal(OS, true);
OS << "}";
}
- void dump() const { print(dbgs()); }
+
+ LLVM_DUMP_METHOD void dump() const {
+ print(dbgs());
+ dbgs() << "\n";
+ }
};
inline raw_ostream &operator<<(raw_ostream &OS, const Expression &E) {
@@ -119,20 +127,20 @@ private:
Type *ValueType;
public:
- static bool classof(const Expression *EB) {
- ExpressionType ET = EB->getExpressionType();
- return ET > ET_BasicStart && ET < ET_BasicEnd;
- }
-
BasicExpression(unsigned NumOperands)
: BasicExpression(NumOperands, ET_Basic) {}
BasicExpression(unsigned NumOperands, ExpressionType ET)
: Expression(ET), Operands(nullptr), MaxOperands(NumOperands),
NumOperands(0), ValueType(nullptr) {}
- virtual ~BasicExpression() override;
- void operator=(const BasicExpression &) = delete;
- BasicExpression(const BasicExpression &) = delete;
BasicExpression() = delete;
+ BasicExpression(const BasicExpression &) = delete;
+ BasicExpression &operator=(const BasicExpression &) = delete;
+ ~BasicExpression() override;
+
+ static bool classof(const Expression *EB) {
+ ExpressionType ET = EB->getExpressionType();
+ return ET > ET_BasicStart && ET < ET_BasicEnd;
+ }
/// \brief Swap two operands. Used during GVN to put commutative operands in
/// order.
@@ -185,7 +193,7 @@ public:
void setType(Type *T) { ValueType = T; }
Type *getType() const { return ValueType; }
- virtual bool equals(const Expression &Other) const override {
+ bool equals(const Expression &Other) const override {
if (getOpcode() != Other.getOpcode())
return false;
@@ -194,15 +202,15 @@ public:
std::equal(op_begin(), op_end(), OE.op_begin());
}
- virtual hash_code getHashValue() const override {
- return hash_combine(getExpressionType(), getOpcode(), ValueType,
+ hash_code getHashValue() const override {
+ return hash_combine(this->Expression::getHashValue(), ValueType,
hash_combine_range(op_begin(), op_end()));
}
//
// Debugging support
//
- virtual void printInternal(raw_ostream &OS, bool PrintEType) const override {
+ void printInternal(raw_ostream &OS, bool PrintEType) const override {
if (PrintEType)
OS << "ExpressionTypeBasic, ";
@@ -216,6 +224,7 @@ public:
OS << "} ";
}
};
+
class op_inserter
: public std::iterator<std::output_iterator_tag, void, void, void, void> {
private:
@@ -235,131 +244,143 @@ public:
op_inserter &operator++(int) { return *this; }
};
-class CallExpression final : public BasicExpression {
+class MemoryExpression : public BasicExpression {
private:
- CallInst *Call;
- MemoryAccess *DefiningAccess;
+ const MemoryAccess *MemoryLeader;
public:
+ MemoryExpression(unsigned NumOperands, enum ExpressionType EType,
+ const MemoryAccess *MemoryLeader)
+ : BasicExpression(NumOperands, EType), MemoryLeader(MemoryLeader){};
+
+ MemoryExpression() = delete;
+ MemoryExpression(const MemoryExpression &) = delete;
+ MemoryExpression &operator=(const MemoryExpression &) = delete;
static bool classof(const Expression *EB) {
- return EB->getExpressionType() == ET_Call;
+ return EB->getExpressionType() > ET_MemoryStart &&
+ EB->getExpressionType() < ET_MemoryEnd;
+ }
+ hash_code getHashValue() const override {
+ return hash_combine(this->BasicExpression::getHashValue(), MemoryLeader);
}
- CallExpression(unsigned NumOperands, CallInst *C, MemoryAccess *DA)
- : BasicExpression(NumOperands, ET_Call), Call(C), DefiningAccess(DA) {}
- void operator=(const CallExpression &) = delete;
- CallExpression(const CallExpression &) = delete;
- CallExpression() = delete;
- virtual ~CallExpression() override;
-
- virtual bool equals(const Expression &Other) const override {
+ bool equals(const Expression &Other) const override {
if (!this->BasicExpression::equals(Other))
return false;
- const auto &OE = cast<CallExpression>(Other);
- return DefiningAccess == OE.DefiningAccess;
+ const MemoryExpression &OtherMCE = cast<MemoryExpression>(Other);
+
+ return MemoryLeader == OtherMCE.MemoryLeader;
}
- virtual hash_code getHashValue() const override {
- return hash_combine(this->BasicExpression::getHashValue(), DefiningAccess);
+ const MemoryAccess *getMemoryLeader() const { return MemoryLeader; }
+ void setMemoryLeader(const MemoryAccess *ML) { MemoryLeader = ML; }
+};
+
+class CallExpression final : public MemoryExpression {
+private:
+ CallInst *Call;
+
+public:
+ CallExpression(unsigned NumOperands, CallInst *C,
+ const MemoryAccess *MemoryLeader)
+ : MemoryExpression(NumOperands, ET_Call, MemoryLeader), Call(C) {}
+ CallExpression() = delete;
+ CallExpression(const CallExpression &) = delete;
+ CallExpression &operator=(const CallExpression &) = delete;
+ ~CallExpression() override;
+
+ static bool classof(const Expression *EB) {
+ return EB->getExpressionType() == ET_Call;
}
//
// Debugging support
//
- virtual void printInternal(raw_ostream &OS, bool PrintEType) const override {
+ void printInternal(raw_ostream &OS, bool PrintEType) const override {
if (PrintEType)
OS << "ExpressionTypeCall, ";
this->BasicExpression::printInternal(OS, false);
- OS << " represents call at " << Call;
+ OS << " represents call at ";
+ Call->printAsOperand(OS);
}
};
-class LoadExpression final : public BasicExpression {
+class LoadExpression final : public MemoryExpression {
private:
LoadInst *Load;
- MemoryAccess *DefiningAccess;
unsigned Alignment;
public:
- static bool classof(const Expression *EB) {
- return EB->getExpressionType() == ET_Load;
- }
-
- LoadExpression(unsigned NumOperands, LoadInst *L, MemoryAccess *DA)
- : LoadExpression(ET_Load, NumOperands, L, DA) {}
+ LoadExpression(unsigned NumOperands, LoadInst *L,
+ const MemoryAccess *MemoryLeader)
+ : LoadExpression(ET_Load, NumOperands, L, MemoryLeader) {}
LoadExpression(enum ExpressionType EType, unsigned NumOperands, LoadInst *L,
- MemoryAccess *DA)
- : BasicExpression(NumOperands, EType), Load(L), DefiningAccess(DA) {
+ const MemoryAccess *MemoryLeader)
+ : MemoryExpression(NumOperands, EType, MemoryLeader), Load(L) {
Alignment = L ? L->getAlignment() : 0;
}
- void operator=(const LoadExpression &) = delete;
- LoadExpression(const LoadExpression &) = delete;
LoadExpression() = delete;
- virtual ~LoadExpression() override;
+ LoadExpression(const LoadExpression &) = delete;
+ LoadExpression &operator=(const LoadExpression &) = delete;
+ ~LoadExpression() override;
+
+ static bool classof(const Expression *EB) {
+ return EB->getExpressionType() == ET_Load;
+ }
LoadInst *getLoadInst() const { return Load; }
void setLoadInst(LoadInst *L) { Load = L; }
- MemoryAccess *getDefiningAccess() const { return DefiningAccess; }
- void setDefiningAccess(MemoryAccess *MA) { DefiningAccess = MA; }
unsigned getAlignment() const { return Alignment; }
void setAlignment(unsigned Align) { Alignment = Align; }
- virtual bool equals(const Expression &Other) const override;
-
- virtual hash_code getHashValue() const override {
- return hash_combine(getOpcode(), getType(), DefiningAccess,
- hash_combine_range(op_begin(), op_end()));
- }
+ bool equals(const Expression &Other) const override;
//
// Debugging support
//
- virtual void printInternal(raw_ostream &OS, bool PrintEType) const override {
+ void printInternal(raw_ostream &OS, bool PrintEType) const override {
if (PrintEType)
OS << "ExpressionTypeLoad, ";
this->BasicExpression::printInternal(OS, false);
- OS << " represents Load at " << Load;
- OS << " with DefiningAccess " << *DefiningAccess;
+ OS << " represents Load at ";
+ Load->printAsOperand(OS);
+ OS << " with MemoryLeader " << *getMemoryLeader();
}
};
-class StoreExpression final : public BasicExpression {
+class StoreExpression final : public MemoryExpression {
private:
StoreInst *Store;
- MemoryAccess *DefiningAccess;
+ Value *StoredValue;
public:
+ StoreExpression(unsigned NumOperands, StoreInst *S, Value *StoredValue,
+ const MemoryAccess *MemoryLeader)
+ : MemoryExpression(NumOperands, ET_Store, MemoryLeader), Store(S),
+ StoredValue(StoredValue) {}
+ StoreExpression() = delete;
+ StoreExpression(const StoreExpression &) = delete;
+ StoreExpression &operator=(const StoreExpression &) = delete;
+ ~StoreExpression() override;
+
static bool classof(const Expression *EB) {
return EB->getExpressionType() == ET_Store;
}
- StoreExpression(unsigned NumOperands, StoreInst *S, MemoryAccess *DA)
- : BasicExpression(NumOperands, ET_Store), Store(S), DefiningAccess(DA) {}
- void operator=(const StoreExpression &) = delete;
- StoreExpression(const StoreExpression &) = delete;
- StoreExpression() = delete;
- virtual ~StoreExpression() override;
-
StoreInst *getStoreInst() const { return Store; }
- MemoryAccess *getDefiningAccess() const { return DefiningAccess; }
+ Value *getStoredValue() const { return StoredValue; }
- virtual bool equals(const Expression &Other) const override;
+ bool equals(const Expression &Other) const override;
- virtual hash_code getHashValue() const override {
- return hash_combine(getOpcode(), getType(), DefiningAccess,
- hash_combine_range(op_begin(), op_end()));
- }
-
- //
// Debugging support
//
- virtual void printInternal(raw_ostream &OS, bool PrintEType) const override {
+ void printInternal(raw_ostream &OS, bool PrintEType) const override {
if (PrintEType)
OS << "ExpressionTypeStore, ";
this->BasicExpression::printInternal(OS, false);
- OS << " represents Store at " << Store;
- OS << " with DefiningAccess " << *DefiningAccess;
+ OS << " represents Store " << *Store;
+ OS << " with MemoryLeader " << *getMemoryLeader();
}
};
@@ -370,19 +391,19 @@ private:
unsigned *IntOperands;
public:
- static bool classof(const Expression *EB) {
- return EB->getExpressionType() == ET_AggregateValue;
- }
-
AggregateValueExpression(unsigned NumOperands, unsigned NumIntOperands)
: BasicExpression(NumOperands, ET_AggregateValue),
MaxIntOperands(NumIntOperands), NumIntOperands(0),
IntOperands(nullptr) {}
-
- void operator=(const AggregateValueExpression &) = delete;
- AggregateValueExpression(const AggregateValueExpression &) = delete;
AggregateValueExpression() = delete;
- virtual ~AggregateValueExpression() override;
+ AggregateValueExpression(const AggregateValueExpression &) = delete;
+ AggregateValueExpression &
+ operator=(const AggregateValueExpression &) = delete;
+ ~AggregateValueExpression() override;
+
+ static bool classof(const Expression *EB) {
+ return EB->getExpressionType() == ET_AggregateValue;
+ }
typedef unsigned *int_arg_iterator;
typedef const unsigned *const_int_arg_iterator;
@@ -407,7 +428,7 @@ public:
IntOperands = Allocator.Allocate<unsigned>(MaxIntOperands);
}
- virtual bool equals(const Expression &Other) const override {
+ bool equals(const Expression &Other) const override {
if (!this->BasicExpression::equals(Other))
return false;
const AggregateValueExpression &OE = cast<AggregateValueExpression>(Other);
@@ -415,7 +436,7 @@ public:
std::equal(int_op_begin(), int_op_end(), OE.int_op_begin());
}
- virtual hash_code getHashValue() const override {
+ hash_code getHashValue() const override {
return hash_combine(this->BasicExpression::getHashValue(),
hash_combine_range(int_op_begin(), int_op_end()));
}
@@ -423,7 +444,7 @@ public:
//
// Debugging support
//
- virtual void printInternal(raw_ostream &OS, bool PrintEType) const override {
+ void printInternal(raw_ostream &OS, bool PrintEType) const override {
if (PrintEType)
OS << "ExpressionTypeAggregateValue, ";
this->BasicExpression::printInternal(OS, false);
@@ -434,6 +455,7 @@ public:
OS << "}";
}
};
+
class int_op_inserter
: public std::iterator<std::output_iterator_tag, void, void, void, void> {
private:
@@ -443,6 +465,7 @@ private:
public:
explicit int_op_inserter(AggregateValueExpression &E) : AVE(&E) {}
explicit int_op_inserter(AggregateValueExpression *E) : AVE(E) {}
+
int_op_inserter &operator=(unsigned int val) {
AVE->int_op_push_back(val);
return *this;
@@ -457,32 +480,32 @@ private:
BasicBlock *BB;
public:
- static bool classof(const Expression *EB) {
- return EB->getExpressionType() == ET_Phi;
- }
-
PHIExpression(unsigned NumOperands, BasicBlock *B)
: BasicExpression(NumOperands, ET_Phi), BB(B) {}
- void operator=(const PHIExpression &) = delete;
- PHIExpression(const PHIExpression &) = delete;
PHIExpression() = delete;
- virtual ~PHIExpression() override;
+ PHIExpression(const PHIExpression &) = delete;
+ PHIExpression &operator=(const PHIExpression &) = delete;
+ ~PHIExpression() override;
- virtual bool equals(const Expression &Other) const override {
+ static bool classof(const Expression *EB) {
+ return EB->getExpressionType() == ET_Phi;
+ }
+
+ bool equals(const Expression &Other) const override {
if (!this->BasicExpression::equals(Other))
return false;
const PHIExpression &OE = cast<PHIExpression>(Other);
return BB == OE.BB;
}
- virtual hash_code getHashValue() const override {
+ hash_code getHashValue() const override {
return hash_combine(this->BasicExpression::getHashValue(), BB);
}
//
// Debugging support
//
- virtual void printInternal(raw_ostream &OS, bool PrintEType) const override {
+ void printInternal(raw_ostream &OS, bool PrintEType) const override {
if (PrintEType)
OS << "ExpressionTypePhi, ";
this->BasicExpression::printInternal(OS, false);
@@ -495,31 +518,32 @@ private:
Value *VariableValue;
public:
+ VariableExpression(Value *V) : Expression(ET_Variable), VariableValue(V) {}
+ VariableExpression() = delete;
+ VariableExpression(const VariableExpression &) = delete;
+ VariableExpression &operator=(const VariableExpression &) = delete;
+
static bool classof(const Expression *EB) {
return EB->getExpressionType() == ET_Variable;
}
- VariableExpression(Value *V) : Expression(ET_Variable), VariableValue(V) {}
- void operator=(const VariableExpression &) = delete;
- VariableExpression(const VariableExpression &) = delete;
- VariableExpression() = delete;
-
Value *getVariableValue() const { return VariableValue; }
void setVariableValue(Value *V) { VariableValue = V; }
- virtual bool equals(const Expression &Other) const override {
+
+ bool equals(const Expression &Other) const override {
const VariableExpression &OC = cast<VariableExpression>(Other);
return VariableValue == OC.VariableValue;
}
- virtual hash_code getHashValue() const override {
- return hash_combine(getExpressionType(), VariableValue->getType(),
- VariableValue);
+ hash_code getHashValue() const override {
+ return hash_combine(this->Expression::getHashValue(),
+ VariableValue->getType(), VariableValue);
}
//
// Debugging support
//
- virtual void printInternal(raw_ostream &OS, bool PrintEType) const override {
+ void printInternal(raw_ostream &OS, bool PrintEType) const override {
if (PrintEType)
OS << "ExpressionTypeVariable, ";
this->Expression::printInternal(OS, false);
@@ -529,36 +553,36 @@ public:
class ConstantExpression final : public Expression {
private:
- Constant *ConstantValue;
+ Constant *ConstantValue = nullptr;
public:
- static bool classof(const Expression *EB) {
- return EB->getExpressionType() == ET_Constant;
- }
-
- ConstantExpression() : Expression(ET_Constant), ConstantValue(NULL) {}
+ ConstantExpression() : Expression(ET_Constant) {}
ConstantExpression(Constant *constantValue)
: Expression(ET_Constant), ConstantValue(constantValue) {}
- void operator=(const ConstantExpression &) = delete;
ConstantExpression(const ConstantExpression &) = delete;
+ ConstantExpression &operator=(const ConstantExpression &) = delete;
+
+ static bool classof(const Expression *EB) {
+ return EB->getExpressionType() == ET_Constant;
+ }
Constant *getConstantValue() const { return ConstantValue; }
void setConstantValue(Constant *V) { ConstantValue = V; }
- virtual bool equals(const Expression &Other) const override {
+ bool equals(const Expression &Other) const override {
const ConstantExpression &OC = cast<ConstantExpression>(Other);
return ConstantValue == OC.ConstantValue;
}
- virtual hash_code getHashValue() const override {
- return hash_combine(getExpressionType(), ConstantValue->getType(),
- ConstantValue);
+ hash_code getHashValue() const override {
+ return hash_combine(this->Expression::getHashValue(),
+ ConstantValue->getType(), ConstantValue);
}
//
// Debugging support
//
- virtual void printInternal(raw_ostream &OS, bool PrintEType) const override {
+ void printInternal(raw_ostream &OS, bool PrintEType) const override {
if (PrintEType)
OS << "ExpressionTypeConstant, ";
this->Expression::printInternal(OS, false);
@@ -571,35 +595,40 @@ private:
Instruction *Inst;
public:
+ UnknownExpression(Instruction *I) : Expression(ET_Unknown), Inst(I) {}
+ UnknownExpression() = delete;
+ UnknownExpression(const UnknownExpression &) = delete;
+ UnknownExpression &operator=(const UnknownExpression &) = delete;
+
static bool classof(const Expression *EB) {
return EB->getExpressionType() == ET_Unknown;
}
- UnknownExpression(Instruction *I) : Expression(ET_Unknown), Inst(I) {}
- void operator=(const UnknownExpression &) = delete;
- UnknownExpression(const UnknownExpression &) = delete;
- UnknownExpression() = delete;
-
Instruction *getInstruction() const { return Inst; }
void setInstruction(Instruction *I) { Inst = I; }
- virtual bool equals(const Expression &Other) const override {
+
+ bool equals(const Expression &Other) const override {
const auto &OU = cast<UnknownExpression>(Other);
return Inst == OU.Inst;
}
- virtual hash_code getHashValue() const override {
- return hash_combine(getExpressionType(), Inst);
+
+ hash_code getHashValue() const override {
+ return hash_combine(this->Expression::getHashValue(), Inst);
}
+
//
// Debugging support
//
- virtual void printInternal(raw_ostream &OS, bool PrintEType) const override {
+ void printInternal(raw_ostream &OS, bool PrintEType) const override {
if (PrintEType)
OS << "ExpressionTypeUnknown, ";
this->Expression::printInternal(OS, false);
OS << " inst = " << *Inst;
}
};
-}
-}
-#endif
+} // end namespace GVNExpression
+
+} // end namespace llvm
+
+#endif // LLVM_TRANSFORMS_SCALAR_GVNEXPRESSION_H
diff --git a/include/llvm/Transforms/Scalar/JumpThreading.h b/include/llvm/Transforms/Scalar/JumpThreading.h
index f96741c0127d..1da86132591b 100644
--- a/include/llvm/Transforms/Scalar/JumpThreading.h
+++ b/include/llvm/Transforms/Scalar/JumpThreading.h
@@ -17,12 +17,14 @@
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallSet.h"
+#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/BlockFrequencyInfo.h"
#include "llvm/Analysis/BlockFrequencyInfoImpl.h"
#include "llvm/Analysis/BranchProbabilityInfo.h"
#include "llvm/Analysis/LazyValueInfo.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/IR/Instructions.h"
+#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/ValueHandle.h"
namespace llvm {
@@ -59,9 +61,11 @@ enum ConstantPreference { WantInteger, WantBlockAddress };
class JumpThreadingPass : public PassInfoMixin<JumpThreadingPass> {
TargetLibraryInfo *TLI;
LazyValueInfo *LVI;
+ AliasAnalysis *AA;
std::unique_ptr<BlockFrequencyInfo> BFI;
std::unique_ptr<BranchProbabilityInfo> BPI;
bool HasProfileData = false;
+ bool HasGuards = false;
#ifdef NDEBUG
SmallPtrSet<const BasicBlock *, 16> LoopHeaders;
#else
@@ -88,7 +92,8 @@ public:
// Glue for old PM.
bool runImpl(Function &F, TargetLibraryInfo *TLI_, LazyValueInfo *LVI_,
- bool HasProfileData_, std::unique_ptr<BlockFrequencyInfo> BFI_,
+ AliasAnalysis *AA_, bool HasProfileData_,
+ std::unique_ptr<BlockFrequencyInfo> BFI_,
std::unique_ptr<BranchProbabilityInfo> BPI_);
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
@@ -122,6 +127,9 @@ public:
bool TryToUnfoldSelect(CmpInst *CondCmp, BasicBlock *BB);
bool TryToUnfoldSelectInCurrBB(BasicBlock *BB);
+ bool ProcessGuards(BasicBlock *BB);
+ bool ThreadGuard(BasicBlock *BB, IntrinsicInst *Guard, BranchInst *BI);
+
private:
BasicBlock *SplitBlockPreds(BasicBlock *BB, ArrayRef<BasicBlock *> Preds,
const char *Suffix);
diff --git a/include/llvm/Transforms/Scalar/LoopDataPrefetch.h b/include/llvm/Transforms/Scalar/LoopDataPrefetch.h
index 114d1bad17a5..12c7a030ff8b 100644
--- a/include/llvm/Transforms/Scalar/LoopDataPrefetch.h
+++ b/include/llvm/Transforms/Scalar/LoopDataPrefetch.h
@@ -22,10 +22,12 @@ namespace llvm {
/// An optimization pass inserting data prefetches in loops.
class LoopDataPrefetchPass : public PassInfoMixin<LoopDataPrefetchPass> {
public:
- LoopDataPrefetchPass() {}
+ LoopDataPrefetchPass() = default;
+
/// \brief Run the pass over the function.
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
};
-}
-#endif
+} // end namespace llvm
+
+#endif // LLVM_TRANSFORMS_SCALAR_LOOPDATAPREFETCH_H
diff --git a/include/llvm/Transforms/Scalar/LoopDeletion.h b/include/llvm/Transforms/Scalar/LoopDeletion.h
index b44f823a82ca..7b8cb1e115c9 100644
--- a/include/llvm/Transforms/Scalar/LoopDeletion.h
+++ b/include/llvm/Transforms/Scalar/LoopDeletion.h
@@ -1,4 +1,4 @@
-//===- LoopDeletion.h - Loop Deletion -------------------------------------===//
+//===- LoopDeletion.h - Loop Deletion ---------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -14,6 +14,7 @@
#ifndef LLVM_TRANSFORMS_SCALAR_LOOPDELETION_H
#define LLVM_TRANSFORMS_SCALAR_LOOPDELETION_H
+#include "llvm/Analysis/LoopAnalysisManager.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/ScalarEvolution.h"
#include "llvm/IR/PassManager.h"
@@ -23,18 +24,12 @@ namespace llvm {
class LoopDeletionPass : public PassInfoMixin<LoopDeletionPass> {
public:
- LoopDeletionPass() {}
+ LoopDeletionPass() = default;
+
PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM,
LoopStandardAnalysisResults &AR, LPMUpdater &U);
- bool runImpl(Loop *L, DominatorTree &DT, ScalarEvolution &SE,
- LoopInfo &loopInfo);
-
-private:
- bool isLoopDead(Loop *L, ScalarEvolution &SE,
- SmallVectorImpl<BasicBlock *> &exitingBlocks,
- SmallVectorImpl<BasicBlock *> &exitBlocks, bool &Changed,
- BasicBlock *Preheader);
};
-}
+
+} // end namespace llvm
#endif // LLVM_TRANSFORMS_SCALAR_LOOPDELETION_H
diff --git a/include/llvm/Transforms/Scalar/LoopLoadElimination.h b/include/llvm/Transforms/Scalar/LoopLoadElimination.h
new file mode 100644
index 000000000000..7a007a7e822d
--- /dev/null
+++ b/include/llvm/Transforms/Scalar/LoopLoadElimination.h
@@ -0,0 +1,30 @@
+//===---- LoopLoadElimination.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 header defines the LoopLoadEliminationPass object. This pass forwards
+/// loaded values around loop backedges to allow their use in subsequent
+/// iterations.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_SCALAR_LOOPLOADELIMINATION_H
+#define LLVM_TRANSFORMS_SCALAR_LOOPLOADELIMINATION_H
+
+#include "llvm/IR/PassManager.h"
+
+namespace llvm {
+
+/// Pass to forward loads in a loop around the backedge to subsequent
+/// iterations.
+struct LoopLoadEliminationPass : public PassInfoMixin<LoopLoadEliminationPass> {
+ PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
+};
+}
+
+#endif // LLVM_TRANSFORMS_SCALAR_LOOPLOADELIMINATION_H
diff --git a/include/llvm/Transforms/Scalar/LoopPassManager.h b/include/llvm/Transforms/Scalar/LoopPassManager.h
index b0e6dd6f4c08..715b11d3d974 100644
--- a/include/llvm/Transforms/Scalar/LoopPassManager.h
+++ b/include/llvm/Transforms/Scalar/LoopPassManager.h
@@ -51,6 +51,8 @@
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/PassManager.h"
+#include "llvm/Transforms/Utils/LCSSA.h"
+#include "llvm/Transforms/Utils/LoopSimplify.h"
namespace llvm {
@@ -248,19 +250,25 @@ template <typename LoopPassT>
class FunctionToLoopPassAdaptor
: public PassInfoMixin<FunctionToLoopPassAdaptor<LoopPassT>> {
public:
- explicit FunctionToLoopPassAdaptor(LoopPassT Pass) : Pass(std::move(Pass)) {}
+ explicit FunctionToLoopPassAdaptor(LoopPassT Pass) : Pass(std::move(Pass)) {
+ LoopCanonicalizationFPM.addPass(LoopSimplifyPass());
+ LoopCanonicalizationFPM.addPass(LCSSAPass());
+ }
/// \brief Runs the loop passes across every loop in the function.
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) {
- // Setup the loop analysis manager from its proxy.
- LoopAnalysisManager &LAM =
- AM.getResult<LoopAnalysisManagerFunctionProxy>(F).getManager();
+ // Before we even compute any loop analyses, first run a miniature function
+ // pass pipeline to put loops into their canonical form. Note that we can
+ // directly build up function analyses after this as the function pass
+ // manager handles all the invalidation at that layer.
+ PreservedAnalyses PA = LoopCanonicalizationFPM.run(F, AM);
+
// Get the loop structure for this function
LoopInfo &LI = AM.getResult<LoopAnalysis>(F);
// If there are no loops, there is nothing to do here.
if (LI.empty())
- return PreservedAnalyses::all();
+ return PA;
// Get the analysis results needed by loop passes.
LoopStandardAnalysisResults LAR = {AM.getResult<AAManager>(F),
@@ -271,7 +279,13 @@ public:
AM.getResult<TargetLibraryAnalysis>(F),
AM.getResult<TargetIRAnalysis>(F)};
- PreservedAnalyses PA = PreservedAnalyses::all();
+ // Setup the loop analysis manager from its proxy. It is important that
+ // this is only done when there are loops to process and we have built the
+ // LoopStandardAnalysisResults object. The loop analyses cached in this
+ // manager have access to those analysis results and so it must invalidate
+ // itself when they go away.
+ LoopAnalysisManager &LAM =
+ AM.getResult<LoopAnalysisManagerFunctionProxy>(F).getManager();
// A postorder worklist of loops to process.
SmallPriorityWorklist<Loop *, 4> Worklist;
@@ -294,8 +308,15 @@ public:
// Reset the update structure for this loop.
Updater.CurrentL = L;
Updater.SkipCurrentLoop = false;
+
#ifndef NDEBUG
+ // Save a parent loop pointer for asserts.
Updater.ParentL = L->getParentLoop();
+
+ // Verify the loop structure and LCSSA form before visiting the loop.
+ L->verifyLoop();
+ assert(L->isRecursivelyLCSSAForm(LAR.DT, LI) &&
+ "Loops must remain in LCSSA form!");
#endif
PreservedAnalyses PassPA = Pass.run(*L, LAM, LAR, Updater);
@@ -321,7 +342,6 @@ public:
PA.preserveSet<AllAnalysesOn<Loop>>();
PA.preserve<LoopAnalysisManagerFunctionProxy>();
// We also preserve the set of standard analyses.
- PA.preserve<AssumptionAnalysis>();
PA.preserve<DominatorTreeAnalysis>();
PA.preserve<LoopAnalysis>();
PA.preserve<ScalarEvolutionAnalysis>();
@@ -336,6 +356,8 @@ public:
private:
LoopPassT Pass;
+
+ FunctionPassManager LoopCanonicalizationFPM;
};
/// \brief A function to deduce a loop pass type and wrap it in the templated
diff --git a/include/llvm/Transforms/Scalar/LoopPredication.h b/include/llvm/Transforms/Scalar/LoopPredication.h
new file mode 100644
index 000000000000..57398bdb6bd1
--- /dev/null
+++ b/include/llvm/Transforms/Scalar/LoopPredication.h
@@ -0,0 +1,32 @@
+//===- LoopPredication.h - Guard based loop predication pass ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This pass tries to convert loop variant range checks to loop invariant by
+// widening checks across loop iterations.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_SCALAR_LOOPPREDICATION_H
+#define LLVM_TRANSFORMS_SCALAR_LOOPPREDICATION_H
+
+#include "llvm/Analysis/LoopInfo.h"
+#include "llvm/IR/PassManager.h"
+#include "llvm/Transforms/Scalar/LoopPassManager.h"
+
+namespace llvm {
+
+/// Performs Loop Predication Pass.
+class LoopPredicationPass : public PassInfoMixin<LoopPredicationPass> {
+public:
+ PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM,
+ LoopStandardAnalysisResults &AR, LPMUpdater &U);
+};
+} // end namespace llvm
+
+#endif // LLVM_TRANSFORMS_SCALAR_LOOPPREDICATION_H
diff --git a/include/llvm/Transforms/Scalar/LoopSink.h b/include/llvm/Transforms/Scalar/LoopSink.h
new file mode 100644
index 000000000000..371a7c8d2c44
--- /dev/null
+++ b/include/llvm/Transforms/Scalar/LoopSink.h
@@ -0,0 +1,40 @@
+//===- LoopSink.h - Loop Sink Pass ------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides the interface for the Loop Sink pass.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_SCALAR_LOOPSINK_H
+#define LLVM_TRANSFORMS_SCALAR_LOOPSINK_H
+
+#include "llvm/Analysis/LoopInfo.h"
+#include "llvm/IR/PassManager.h"
+#include "llvm/Transforms/Scalar/LoopPassManager.h"
+
+namespace llvm {
+
+/// A pass that does profile-guided sinking of instructions into loops.
+///
+/// This is a function pass as it shouldn't be composed into any kind of
+/// unified loop pass pipeline. The goal of it is to sink code into loops that
+/// is loop invariant but only required within the loop body when doing so
+/// reduces the global expected dynamic frequency with which it executes.
+/// A classic example is an extremely cold branch within a loop body.
+///
+/// We do this as a separate pass so that during normal optimization all
+/// invariant operations can be held outside the loop body to simplify
+/// fundamental analyses and transforms of the loop.
+class LoopSinkPass : public PassInfoMixin<LoopSinkPass> {
+public:
+ PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM);
+};
+}
+
+#endif // LLVM_TRANSFORMS_SCALAR_LOOPSINK_H
diff --git a/include/llvm/Transforms/Scalar/LoopUnrollPass.h b/include/llvm/Transforms/Scalar/LoopUnrollPass.h
index 9da95ef81fad..7253bd09766e 100644
--- a/include/llvm/Transforms/Scalar/LoopUnrollPass.h
+++ b/include/llvm/Transforms/Scalar/LoopUnrollPass.h
@@ -16,12 +16,30 @@
namespace llvm {
-struct LoopUnrollPass : public PassInfoMixin<LoopUnrollPass> {
- Optional<unsigned> ProvidedCount;
- Optional<unsigned> ProvidedThreshold;
- Optional<bool> ProvidedAllowPartial;
- Optional<bool> ProvidedRuntime;
- Optional<bool> ProvidedUpperBound;
+class LoopUnrollPass : public PassInfoMixin<LoopUnrollPass> {
+ const bool AllowPartialUnrolling;
+ const int OptLevel;
+
+ explicit LoopUnrollPass(bool AllowPartialUnrolling, int OptLevel)
+ : AllowPartialUnrolling(AllowPartialUnrolling), OptLevel(OptLevel) {}
+
+public:
+ /// Create an instance of the loop unroll pass that will support both full
+ /// and partial unrolling.
+ ///
+ /// This uses the target information (or flags) to control the thresholds for
+ /// different unrolling stategies but supports all of them.
+ static LoopUnrollPass create(int OptLevel = 2) {
+ return LoopUnrollPass(/*AllowPartialUnrolling*/ true, OptLevel);
+ }
+
+ /// Create an instance of the loop unroll pass that only does full loop
+ /// unrolling.
+ ///
+ /// This will disable any runtime or partial unrolling.
+ static LoopUnrollPass createFull(int OptLevel = 2) {
+ return LoopUnrollPass(/*AllowPartialUnrolling*/ false, OptLevel);
+ }
PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM,
LoopStandardAnalysisResults &AR, LPMUpdater &U);
diff --git a/include/llvm/Transforms/Scalar/MemCpyOptimizer.h b/include/llvm/Transforms/Scalar/MemCpyOptimizer.h
index 4308e44e7c4b..f52872dd2ea7 100644
--- a/include/llvm/Transforms/Scalar/MemCpyOptimizer.h
+++ b/include/llvm/Transforms/Scalar/MemCpyOptimizer.h
@@ -15,17 +15,18 @@
#ifndef LLVM_TRANSFORMS_SCALAR_MEMCPYOPTIMIZER_H
#define LLVM_TRANSFORMS_SCALAR_MEMCPYOPTIMIZER_H
-#include "llvm/ADT/STLExtras.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/AssumptionCache.h"
-#include "llvm/Analysis/GlobalsModRef.h"
#include "llvm/Analysis/MemoryDependenceAnalysis.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
+#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/PassManager.h"
+#include <cstdint>
+#include <functional>
namespace llvm {
@@ -37,7 +38,8 @@ class MemCpyOptPass : public PassInfoMixin<MemCpyOptPass> {
std::function<DominatorTree &()> LookupDomTree;
public:
- MemCpyOptPass() {}
+ MemCpyOptPass() = default;
+
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
// Glue for the old PM.
bool runImpl(Function &F, MemoryDependenceResults *MD_,
@@ -63,6 +65,7 @@ private:
bool iterateOnFunction(Function &F);
};
-}
+
+} // end namespace llvm
#endif // LLVM_TRANSFORMS_SCALAR_MEMCPYOPTIMIZER_H
diff --git a/include/llvm/Transforms/Scalar/SROA.h b/include/llvm/Transforms/Scalar/SROA.h
index 3e93f46dd4e5..3080b75ba894 100644
--- a/include/llvm/Transforms/Scalar/SROA.h
+++ b/include/llvm/Transforms/Scalar/SROA.h
@@ -21,17 +21,21 @@
#include "llvm/IR/Dominators.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/PassManager.h"
+#include "llvm/Support/Compiler.h"
+#include <vector>
namespace llvm {
/// A private "module" namespace for types and utilities used by SROA. These
/// are implementation details and should not be used by clients.
namespace sroa LLVM_LIBRARY_VISIBILITY {
+
class AllocaSliceRewriter;
class AllocaSlices;
class Partition;
class SROALegacyPass;
-}
+
+} // end namespace sroa
/// \brief An optimization pass providing Scalar Replacement of Aggregates.
///
@@ -52,9 +56,9 @@ class SROALegacyPass;
/// this form. By doing so, it will enable promotion of vector aggregates to
/// SSA vector values.
class SROA : public PassInfoMixin<SROA> {
- LLVMContext *C;
- DominatorTree *DT;
- AssumptionCache *AC;
+ LLVMContext *C = nullptr;
+ DominatorTree *DT = nullptr;
+ AssumptionCache *AC = nullptr;
/// \brief Worklist of alloca instructions to simplify.
///
@@ -99,7 +103,7 @@ class SROA : public PassInfoMixin<SROA> {
SetVector<SelectInst *, SmallVector<SelectInst *, 2>> SpeculatableSelects;
public:
- SROA() : C(nullptr), DT(nullptr), AC(nullptr) {}
+ SROA() = default;
/// \brief Run the pass over the function.
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
@@ -122,6 +126,6 @@ private:
bool promoteAllocas(Function &F);
};
-}
+} // end namespace llvm
-#endif
+#endif // LLVM_TRANSFORMS_SCALAR_SROA_H
diff --git a/include/llvm/Transforms/Scalar/SimplifyCFG.h b/include/llvm/Transforms/Scalar/SimplifyCFG.h
index 96e1658c00b0..54b51c405ad4 100644
--- a/include/llvm/Transforms/Scalar/SimplifyCFG.h
+++ b/include/llvm/Transforms/Scalar/SimplifyCFG.h
@@ -27,13 +27,16 @@ namespace llvm {
/// by the rest of the mid-level optimizer.
class SimplifyCFGPass : public PassInfoMixin<SimplifyCFGPass> {
int BonusInstThreshold;
+ bool LateSimplifyCFG;
public:
- /// \brief Construct a pass with the default thresholds.
+ /// \brief Construct a pass with the default thresholds
+ /// and switch optimizations.
SimplifyCFGPass();
- /// \brief Construct a pass with a specific bonus threshold.
- SimplifyCFGPass(int BonusInstThreshold);
+ /// \brief Construct a pass with a specific bonus threshold
+ /// and optional switch optimizations.
+ SimplifyCFGPass(int BonusInstThreshold, bool LateSimplifyCFG);
/// \brief Run the pass over the function.
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
diff --git a/include/llvm/Transforms/Utils/BasicBlockUtils.h b/include/llvm/Transforms/Utils/BasicBlockUtils.h
index 3d41dbe2b954..85bb053135a6 100644
--- a/include/llvm/Transforms/Utils/BasicBlockUtils.h
+++ b/include/llvm/Transforms/Utils/BasicBlockUtils.h
@@ -78,14 +78,13 @@ void ReplaceInstWithInst(Instruction *From, Instruction *To);
struct CriticalEdgeSplittingOptions {
DominatorTree *DT;
LoopInfo *LI;
- bool MergeIdenticalEdges;
- bool DontDeleteUselessPHIs;
- bool PreserveLCSSA;
+ bool MergeIdenticalEdges = false;
+ bool DontDeleteUselessPHIs = false;
+ bool PreserveLCSSA = false;
CriticalEdgeSplittingOptions(DominatorTree *DT = nullptr,
LoopInfo *LI = nullptr)
- : DT(DT), LI(LI), MergeIdenticalEdges(false),
- DontDeleteUselessPHIs(false), PreserveLCSSA(false) {}
+ : DT(DT), LI(LI) {}
CriticalEdgeSplittingOptions &setMergeIdenticalEdges() {
MergeIdenticalEdges = true;
diff --git a/include/llvm/Transforms/Utils/BuildLibCalls.h b/include/llvm/Transforms/Utils/BuildLibCalls.h
index 2d2a85905d0e..a067a685b837 100644
--- a/include/llvm/Transforms/Utils/BuildLibCalls.h
+++ b/include/llvm/Transforms/Utils/BuildLibCalls.h
@@ -84,14 +84,14 @@ namespace llvm {
/// value with the same type. If 'Op' is a long double, 'l' is added as the
/// suffix of name, if 'Op' is a float, we add a 'f' suffix.
Value *emitUnaryFloatFnCall(Value *Op, StringRef Name, IRBuilder<> &B,
- const AttributeSet &Attrs);
+ const AttributeList &Attrs);
/// Emit a call to the binary function named 'Name' (e.g. 'fmin'). This
/// function is known to take type matching 'Op1' and 'Op2' and return one
/// value with the same type. If 'Op1/Op2' are long double, 'l' is added as
/// the suffix of name, if 'Op1/Op2' are float, we add a 'f' suffix.
Value *emitBinaryFloatFnCall(Value *Op1, Value *Op2, StringRef Name,
- IRBuilder<> &B, const AttributeSet &Attrs);
+ IRBuilder<> &B, const AttributeList &Attrs);
/// Emit a call to the putchar function. This assumes that Char is an integer.
Value *emitPutChar(Value *Char, IRBuilder<> &B, const TargetLibraryInfo *TLI);
diff --git a/include/llvm/Transforms/Utils/Cloning.h b/include/llvm/Transforms/Utils/Cloning.h
index 5eeb8cf30695..337305a0a82c 100644
--- a/include/llvm/Transforms/Utils/Cloning.h
+++ b/include/llvm/Transforms/Utils/Cloning.h
@@ -22,32 +22,28 @@
#include "llvm/ADT/Twine.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/AssumptionCache.h"
+#include "llvm/IR/CallSite.h"
#include "llvm/IR/ValueHandle.h"
-#include "llvm/IR/ValueMap.h"
#include "llvm/Transforms/Utils/ValueMapper.h"
#include <functional>
+#include <memory>
+#include <vector>
namespace llvm {
-class Module;
-class Function;
-class Instruction;
-class Pass;
-class LPPassManager;
+class AllocaInst;
class BasicBlock;
-class Value;
+class BlockFrequencyInfo;
class CallInst;
-class InvokeInst;
-class ReturnInst;
-class CallSite;
-class Trace;
class CallGraph;
-class DataLayout;
+class DominatorTree;
+class Function;
+class Instruction;
+class InvokeInst;
class Loop;
class LoopInfo;
-class AllocaInst;
-class AssumptionCacheTracker;
-class DominatorTree;
+class Module;
+class ReturnInst;
/// Return an exact copy of the specified module
///
@@ -67,20 +63,20 @@ CloneModule(const Module *M, ValueToValueMapTy &VMap,
struct ClonedCodeInfo {
/// ContainsCalls - This is set to true if the cloned code contains a normal
/// call instruction.
- bool ContainsCalls;
+ bool ContainsCalls = false;
/// ContainsDynamicAllocas - This is set to true if the cloned code contains
/// a 'dynamic' alloca. Dynamic allocas are allocas that are either not in
/// the entry block or they are in the entry block but are not a constant
/// size.
- bool ContainsDynamicAllocas;
+ bool ContainsDynamicAllocas = false;
/// All cloned call sites that have operand bundles attached are appended to
/// this vector. This vector may contain nulls or undefs if some of the
/// originally inserted callsites were DCE'ed after they were cloned.
std::vector<WeakVH> OperandBundleCallSites;
- ClonedCodeInfo() : ContainsCalls(false), ContainsDynamicAllocas(false) {}
+ ClonedCodeInfo() = default;
};
/// CloneBasicBlock - Return a copy of the specified basic block, but without
@@ -178,13 +174,17 @@ class InlineFunctionInfo {
public:
explicit InlineFunctionInfo(CallGraph *cg = nullptr,
std::function<AssumptionCache &(Function &)>
- *GetAssumptionCache = nullptr)
- : CG(cg), GetAssumptionCache(GetAssumptionCache) {}
+ *GetAssumptionCache = nullptr,
+ BlockFrequencyInfo *CallerBFI = nullptr,
+ BlockFrequencyInfo *CalleeBFI = nullptr)
+ : CG(cg), GetAssumptionCache(GetAssumptionCache), CallerBFI(CallerBFI),
+ CalleeBFI(CalleeBFI) {}
/// CG - If non-null, InlineFunction will update the callgraph to reflect the
/// changes it makes.
CallGraph *CG;
std::function<AssumptionCache &(Function &)> *GetAssumptionCache;
+ BlockFrequencyInfo *CallerBFI, *CalleeBFI;
/// StaticAllocas - InlineFunction fills this in with all static allocas that
/// get copied into the caller.
@@ -245,6 +245,16 @@ Loop *cloneLoopWithPreheader(BasicBlock *Before, BasicBlock *LoopDomBB,
void remapInstructionsInBlocks(const SmallVectorImpl<BasicBlock *> &Blocks,
ValueToValueMapTy &VMap);
-} // End llvm namespace
+/// Split edge between BB and PredBB and duplicate all non-Phi instructions
+/// from BB between its beginning and the StopAt instruction into the split
+/// block. Phi nodes are not duplicated, but their uses are handled correctly:
+/// we replace them with the uses of corresponding Phi inputs. ValueMapping
+/// is used to map the original instructions from BB to their newly-created
+/// copies. Returns the split block.
+BasicBlock *
+DuplicateInstructionsInSplitBetween(BasicBlock *BB, BasicBlock *PredBB,
+ Instruction *StopAt,
+ ValueToValueMapTy &ValueMapping);
+} // end namespace llvm
-#endif
+#endif // LLVM_TRANSFORMS_UTILS_CLONING_H
diff --git a/include/llvm/Transforms/Utils/FunctionComparator.h b/include/llvm/Transforms/Utils/FunctionComparator.h
index a613fc31a5e3..ee58d1d138f7 100644
--- a/include/llvm/Transforms/Utils/FunctionComparator.h
+++ b/include/llvm/Transforms/Utils/FunctionComparator.h
@@ -314,7 +314,7 @@ protected:
private:
int cmpOrderings(AtomicOrdering L, AtomicOrdering R) const;
int cmpInlineAsm(const InlineAsm *L, const InlineAsm *R) const;
- int cmpAttrs(const AttributeSet L, const AttributeSet R) const;
+ int cmpAttrs(const AttributeList L, const AttributeList R) const;
int cmpRangeMetadata(const MDNode *L, const MDNode *R) const;
int cmpOperandBundlesSchema(const Instruction *L, const Instruction *R) const;
diff --git a/include/llvm/Transforms/Utils/FunctionImportUtils.h b/include/llvm/Transforms/Utils/FunctionImportUtils.h
index f18cd92310b4..b9fbef04cdc3 100644
--- a/include/llvm/Transforms/Utils/FunctionImportUtils.h
+++ b/include/llvm/Transforms/Utils/FunctionImportUtils.h
@@ -32,7 +32,7 @@ class FunctionImportGlobalProcessing {
/// Globals to import from this module, all other functions will be
/// imported as declarations instead of definitions.
- DenseSet<const GlobalValue *> *GlobalsToImport;
+ SetVector<GlobalValue *> *GlobalsToImport;
/// Set to true if the given ModuleSummaryIndex contains any functions
/// from this source module, in which case we must conservatively assume
@@ -85,7 +85,7 @@ class FunctionImportGlobalProcessing {
public:
FunctionImportGlobalProcessing(
Module &M, const ModuleSummaryIndex &Index,
- DenseSet<const GlobalValue *> *GlobalsToImport = nullptr)
+ SetVector<GlobalValue *> *GlobalsToImport = nullptr)
: M(M), ImportIndex(Index), GlobalsToImport(GlobalsToImport) {
// If we have a ModuleSummaryIndex but no function to import,
// then this is the primary module being compiled in a ThinLTO
@@ -104,16 +104,15 @@ public:
bool run();
- static bool
- doImportAsDefinition(const GlobalValue *SGV,
- DenseSet<const GlobalValue *> *GlobalsToImport);
+ static bool doImportAsDefinition(const GlobalValue *SGV,
+ SetVector<GlobalValue *> *GlobalsToImport);
};
/// Perform in-place global value handling on the given Module for
/// exported local functions renamed and promoted for ThinLTO.
bool renameModuleForThinLTO(
Module &M, const ModuleSummaryIndex &Index,
- DenseSet<const GlobalValue *> *GlobalsToImport = nullptr);
+ SetVector<GlobalValue *> *GlobalsToImport = nullptr);
} // End llvm namespace
diff --git a/include/llvm/Transforms/Utils/GlobalStatus.h b/include/llvm/Transforms/Utils/GlobalStatus.h
index c36609508808..8cc265bdf81d 100644
--- a/include/llvm/Transforms/Utils/GlobalStatus.h
+++ b/include/llvm/Transforms/Utils/GlobalStatus.h
@@ -10,11 +10,13 @@
#ifndef LLVM_TRANSFORMS_UTILS_GLOBALSTATUS_H
#define LLVM_TRANSFORMS_UTILS_GLOBALSTATUS_H
-#include "llvm/IR/Instructions.h"
+#include "llvm/Support/AtomicOrdering.h"
namespace llvm {
-class Value;
+
+class Constant;
class Function;
+class Value;
/// It is safe to destroy a constant iff it is only used by constants itself.
/// Note that constants cannot be cyclic, so this test is pretty easy to
@@ -27,11 +29,11 @@ bool isSafeToDestroyConstant(const Constant *C);
/// accurate.
struct GlobalStatus {
/// True if the global's address is used in a comparison.
- bool IsCompared;
+ bool IsCompared = false;
/// True if the global is ever loaded. If the global isn't ever loaded it
/// can be deleted.
- bool IsLoaded;
+ bool IsLoaded = false;
/// Keep track of what stores to the global look like.
enum StoredType {
@@ -51,32 +53,33 @@ struct GlobalStatus {
/// This global is stored to by multiple values or something else that we
/// cannot track.
Stored
- } StoredType;
+ } StoredType = NotStored;
/// If only one value (besides the initializer constant) is ever stored to
/// this global, keep track of what value it is.
- Value *StoredOnceValue;
+ Value *StoredOnceValue = nullptr;
/// These start out null/false. When the first accessing function is noticed,
/// it is recorded. When a second different accessing function is noticed,
/// HasMultipleAccessingFunctions is set to true.
- const Function *AccessingFunction;
- bool HasMultipleAccessingFunctions;
+ const Function *AccessingFunction = nullptr;
+ bool HasMultipleAccessingFunctions = false;
/// Set to true if this global has a user that is not an instruction (e.g. a
/// constant expr or GV initializer).
- bool HasNonInstructionUser;
+ bool HasNonInstructionUser = false;
/// Set to the strongest atomic ordering requirement.
- AtomicOrdering Ordering;
+ AtomicOrdering Ordering = AtomicOrdering::NotAtomic;
+
+ GlobalStatus();
/// Look at all uses of the global and fill in the GlobalStatus structure. If
/// the global has its address taken, return true to indicate we can't do
/// anything with it.
static bool analyzeGlobal(const Value *V, GlobalStatus &GS);
-
- GlobalStatus();
};
-}
-#endif
+} // end namespace llvm
+
+#endif // LLVM_TRANSFORMS_UTILS_GLOBALSTATUS_H
diff --git a/include/llvm/Transforms/Utils/Local.h b/include/llvm/Transforms/Utils/Local.h
index 490a765c3fab..4933712fb8ad 100644
--- a/include/llvm/Transforms/Utils/Local.h
+++ b/include/llvm/Transforms/Utils/Local.h
@@ -49,8 +49,6 @@ class LazyValueInfo;
template<typename T> class SmallVectorImpl;
-typedef SmallVector<DbgValueInst *, 1> DbgValueList;
-
//===----------------------------------------------------------------------===//
// Local constant propagation.
//
@@ -74,6 +72,12 @@ bool ConstantFoldTerminator(BasicBlock *BB, bool DeleteDeadConditions = false,
bool isInstructionTriviallyDead(Instruction *I,
const TargetLibraryInfo *TLI = nullptr);
+/// Return true if the result produced by the instruction would have no side
+/// effects if it was not used. This is equivalent to checking whether
+/// isInstructionTriviallyDead would be true if the use count was 0.
+bool wouldInstructionBeTriviallyDead(Instruction *I,
+ const TargetLibraryInfo *TLI = nullptr);
+
/// If the specified value is a trivially dead instruction, delete it.
/// If that makes any of its operands trivially dead, delete them too,
/// recursively. Return true if any instructions were deleted.
@@ -138,7 +142,8 @@ bool EliminateDuplicatePHINodes(BasicBlock *BB);
/// eliminate.
bool SimplifyCFG(BasicBlock *BB, const TargetTransformInfo &TTI,
unsigned BonusInstThreshold, AssumptionCache *AC = nullptr,
- SmallPtrSetImpl<BasicBlock *> *LoopHeaders = nullptr);
+ SmallPtrSetImpl<BasicBlock *> *LoopHeaders = nullptr,
+ bool LateSimplifyCFG = false);
/// This function is used to flatten a CFG. For example, it uses parallel-and
/// and parallel-or mode to collapse if-conditions and merge if-regions with
@@ -278,8 +283,11 @@ bool LowerDbgDeclare(Function &F);
/// Finds the llvm.dbg.declare intrinsic corresponding to an alloca, if any.
DbgDeclareInst *FindAllocaDbgDeclare(Value *V);
-/// Finds the llvm.dbg.value intrinsics corresponding to an alloca, if any.
-void FindAllocaDbgValues(DbgValueList &DbgValues, Value *V);
+/// Finds the llvm.dbg.value intrinsics describing a value.
+void findDbgValues(SmallVectorImpl<DbgValueInst *> &DbgValues, Value *V);
+
+/// Constants for \p replaceDbgDeclare and friends.
+enum { NoDeref = false, WithDeref = true };
/// Replaces llvm.dbg.declare instruction when the address it describes
/// is replaced with a new value. If Deref is true, an additional DW_OP_deref is
@@ -306,6 +314,11 @@ bool replaceDbgDeclareForAlloca(AllocaInst *AI, Value *NewAllocaAddress,
void replaceDbgValueForAlloca(AllocaInst *AI, Value *NewAllocaAddress,
DIBuilder &Builder, int Offset = 0);
+/// Assuming the instruction \p I is going to be deleted, attempt to salvage any
+/// dbg.value intrinsics referring to \p I by rewriting its effect into a
+/// DIExpression.
+void salvageDebugInfo(Instruction &I);
+
/// Remove all instructions from a basic block other than it's terminator
/// and any present EH pad instructions.
unsigned removeAllNonTerminatorAndEHPadInstructions(BasicBlock *BB);
diff --git a/include/llvm/Transforms/Utils/LoopUtils.h b/include/llvm/Transforms/Utils/LoopUtils.h
index 27b45c4fa941..a1cf41d6f931 100644
--- a/include/llvm/Transforms/Utils/LoopUtils.h
+++ b/include/llvm/Transforms/Utils/LoopUtils.h
@@ -1,4 +1,4 @@
-//===- llvm/Transforms/Utils/LoopUtils.h - Loop utilities -*- C++ -*-=========//
+//===- llvm/Transforms/Utils/LoopUtils.h - Loop utilities -------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -14,23 +14,29 @@
#ifndef LLVM_TRANSFORMS_UTILS_LOOPUTILS_H
#define LLVM_TRANSFORMS_UTILS_LOOPUTILS_H
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/EHPersonalities.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/InstrTypes.h"
+#include "llvm/IR/Operator.h"
+#include "llvm/IR/ValueHandle.h"
+#include "llvm/Support/Casting.h"
namespace llvm {
+
class AliasSet;
class AliasSetTracker;
-class AssumptionCache;
class BasicBlock;
class DataLayout;
-class DominatorTree;
class Loop;
class LoopInfo;
class OptimizationRemarkEmitter;
-class Pass;
class PredicatedScalarEvolution;
class PredIteratorCache;
class ScalarEvolution;
@@ -40,12 +46,13 @@ class TargetLibraryInfo;
/// \brief Captures loop safety information.
/// It keep information for loop & its header may throw exception.
struct LoopSafetyInfo {
- bool MayThrow; // The current loop contains an instruction which
- // may throw.
- bool HeaderMayThrow; // Same as previous, but specific to loop header
+ bool MayThrow = false; // The current loop contains an instruction which
+ // may throw.
+ bool HeaderMayThrow = false; // Same as previous, but specific to loop header
// Used to update funclet bundle operands.
DenseMap<BasicBlock *, ColorVector> BlockColors;
- LoopSafetyInfo() : MayThrow(false), HeaderMayThrow(false) {}
+
+ LoopSafetyInfo() = default;
};
/// The RecurrenceDescriptor is used to identify recurrences variables in a
@@ -61,7 +68,6 @@ struct LoopSafetyInfo {
/// This struct holds information about recurrence variables.
class RecurrenceDescriptor {
-
public:
/// This enum represents the kinds of recurrences that we support.
enum RecurrenceKind {
@@ -88,10 +94,7 @@ public:
MRK_FloatMax
};
- RecurrenceDescriptor()
- : StartValue(nullptr), LoopExitInstr(nullptr), Kind(RK_NoRecurrence),
- MinMaxKind(MRK_Invalid), UnsafeAlgebraInst(nullptr),
- RecurrenceType(nullptr), IsSigned(false) {}
+ RecurrenceDescriptor() = default;
RecurrenceDescriptor(Value *Start, Instruction *Exit, RecurrenceKind K,
MinMaxRecurrenceKind MK, Instruction *UAI, Type *RT,
@@ -103,7 +106,6 @@ public:
/// This POD struct holds information about a potential recurrence operation.
class InstDesc {
-
public:
InstDesc(bool IsRecur, Instruction *I, Instruction *UAI = nullptr)
: IsRecurrence(IsRecur), PatternLastInst(I), MinMaxKind(MRK_Invalid),
@@ -242,17 +244,17 @@ private:
// It does not have to be zero!
TrackingVH<Value> StartValue;
// The instruction who's value is used outside the loop.
- Instruction *LoopExitInstr;
+ Instruction *LoopExitInstr = nullptr;
// The kind of the recurrence.
- RecurrenceKind Kind;
+ RecurrenceKind Kind = RK_NoRecurrence;
// If this a min/max recurrence the kind of recurrence.
- MinMaxRecurrenceKind MinMaxKind;
+ MinMaxRecurrenceKind MinMaxKind = MRK_Invalid;
// First occurrence of unasfe algebra in the PHI's use-chain.
- Instruction *UnsafeAlgebraInst;
+ Instruction *UnsafeAlgebraInst = nullptr;
// The type of the recurrence.
- Type *RecurrenceType;
+ Type *RecurrenceType = nullptr;
// True if all source operands of the recurrence are SExtInsts.
- bool IsSigned;
+ bool IsSigned = false;
// Instructions used for type-promoting the recurrence.
SmallPtrSet<Instruction *, 8> CastInsts;
};
@@ -270,9 +272,7 @@ public:
public:
/// Default constructor - creates an invalid induction.
- InductionDescriptor()
- : StartValue(nullptr), IK(IK_NoInduction), Step(nullptr),
- InductionBinOp(nullptr) {}
+ InductionDescriptor() = default;
/// Get the consecutive direction. Returns:
/// 0 - unknown or non-consecutive.
@@ -350,11 +350,11 @@ private:
/// Start value.
TrackingVH<Value> StartValue;
/// Induction kind.
- InductionKind IK;
+ InductionKind IK = IK_NoInduction;
/// Step value.
- const SCEV *Step;
+ const SCEV *Step = nullptr;
// Instruction that advances induction variable.
- BinaryOperator *InductionBinOp;
+ BinaryOperator *InductionBinOp = nullptr;
};
BasicBlock *InsertPreheaderForLoop(Loop *L, DominatorTree *DT, LoopInfo *LI,
@@ -488,6 +488,7 @@ bool canSinkOrHoistInst(Instruction &I, AAResults *AA, DominatorTree *DT,
Loop *CurLoop, AliasSetTracker *CurAST,
LoopSafetyInfo *SafetyInfo,
OptimizationRemarkEmitter *ORE = nullptr);
-}
-#endif
+} // end namespace llvm
+
+#endif // LLVM_TRANSFORMS_UTILS_LOOPUTILS_H
diff --git a/include/llvm/Transforms/Utils/LowerMemIntrinsics.h b/include/llvm/Transforms/Utils/LowerMemIntrinsics.h
new file mode 100644
index 000000000000..e4906b709e4b
--- /dev/null
+++ b/include/llvm/Transforms/Utils/LowerMemIntrinsics.h
@@ -0,0 +1,44 @@
+//===- llvm/Transforms/Utils/LowerMemintrinsics.h ---------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Lower memset, memcpy, memmov intrinsics to loops (e.g. for targets without
+// library support).
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_UTILS_LOWERMEMINTRINSICS_H
+#define LLVM_TRANSFORMS_UTILS_LOWERMEMINTRINSICS_H
+
+namespace llvm {
+
+class Instruction;
+class MemCpyInst;
+class MemMoveInst;
+class MemSetInst;
+class Value;
+
+/// Emit a loop implementing the semantics of llvm.memcpy with the equivalent
+/// arguments at \p InsertBefore.
+void createMemCpyLoop(Instruction *InsertBefore,
+ Value *SrcAddr, Value *DstAddr, Value *CopyLen,
+ unsigned SrcAlign, unsigned DestAlign,
+ bool SrcIsVolatile, bool DstIsVolatile);
+
+/// Expand \p MemCpy as a loop. \p MemCpy is not deleted.
+void expandMemCpyAsLoop(MemCpyInst *MemCpy);
+
+/// Expand \p MemMove as a loop. \p MemMove is not deleted.
+void expandMemMoveAsLoop(MemMoveInst *MemMove);
+
+/// Expand \p MemSet as a loop. \p MemSet is not deleted.
+void expandMemSetAsLoop(MemSetInst *MemSet);
+
+} // End llvm namespace
+
+#endif
diff --git a/include/llvm/Transforms/Utils/ModuleUtils.h b/include/llvm/Transforms/Utils/ModuleUtils.h
index 27508799f8e0..f5e843e2e8b5 100644
--- a/include/llvm/Transforms/Utils/ModuleUtils.h
+++ b/include/llvm/Transforms/Utils/ModuleUtils.h
@@ -46,6 +46,9 @@ void appendToGlobalDtors(Module &M, Function *F, int Priority,
// getOrInsertFunction returns a bitcast.
Function *checkSanitizerInterfaceFunction(Constant *FuncOrBitcast);
+Function *declareSanitizerInitFunction(Module &M, StringRef InitName,
+ ArrayRef<Type *> InitArgTypes);
+
/// \brief Creates sanitizer constructor function, and calls sanitizer's init
/// function from it.
/// \return Returns pair of pointers to constructor, and init functions
diff --git a/include/llvm/Transforms/Utils/NameAnonGlobals.h b/include/llvm/Transforms/Utils/NameAnonGlobals.h
index 4bec361674bb..17fc902eebf8 100644
--- a/include/llvm/Transforms/Utils/NameAnonGlobals.h
+++ b/include/llvm/Transforms/Utils/NameAnonGlobals.h
@@ -1,4 +1,4 @@
-//===-- NameAnonGlobals.h - Anonymous Global Naming Pass ----*- C++ -*-=======//
+//===-- NameAnonGlobals.h - Anonymous Global Naming Pass --------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -23,9 +23,11 @@ namespace llvm {
/// Simple pass that provides a name to every anonymous globals.
class NameAnonGlobalPass : public PassInfoMixin<NameAnonGlobalPass> {
public:
- NameAnonGlobalPass() {}
+ NameAnonGlobalPass() = default;
+
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
};
-}
+
+} // end namespace llvm
#endif // LLVM_TRANSFORMS_UTILS_NAMEANONGLOBALS_H
diff --git a/include/llvm/Transforms/Utils/PredicateInfo.h b/include/llvm/Transforms/Utils/PredicateInfo.h
new file mode 100644
index 000000000000..1322c686eb90
--- /dev/null
+++ b/include/llvm/Transforms/Utils/PredicateInfo.h
@@ -0,0 +1,295 @@
+//===- PredicateInfo.h - Build PredicateInfo ----------------------*-C++-*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief This file implements the PredicateInfo analysis, which creates an Extended
+/// SSA form for operations used in branch comparisons and llvm.assume
+/// comparisons.
+///
+/// Copies of these operations are inserted into the true/false edge (and after
+/// assumes), and information attached to the copies. All uses of the original
+/// operation in blocks dominated by the true/false edge (and assume), are
+/// replaced with uses of the copies. This enables passes to easily and sparsely
+/// propagate condition based info into the operations that may be affected.
+///
+/// Example:
+/// %cmp = icmp eq i32 %x, 50
+/// br i1 %cmp, label %true, label %false
+/// true:
+/// ret i32 %x
+/// false:
+/// ret i32 1
+///
+/// will become
+///
+/// %cmp = icmp eq i32, %x, 50
+/// br i1 %cmp, label %true, label %false
+/// true:
+/// %x.0 = call @llvm.ssa_copy.i32(i32 %x)
+/// ret i32 %x.0
+/// false:
+/// ret i32 1
+///
+/// Using getPredicateInfoFor on x.0 will give you the comparison it is
+/// dominated by (the icmp), and that you are located in the true edge of that
+/// comparison, which tells you x.0 is 50.
+///
+/// In order to reduce the number of copies inserted, predicateinfo is only
+/// inserted where it would actually be live. This means if there are no uses of
+/// an operation dominated by the branch edges, or by an assume, the associated
+/// predicate info is never inserted.
+///
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_UTILS_PREDICATEINFO_H
+#define LLVM_TRANSFORMS_UTILS_PREDICATEINFO_H
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/ilist.h"
+#include "llvm/ADT/ilist_node.h"
+#include "llvm/ADT/iterator.h"
+#include "llvm/Analysis/AssumptionCache.h"
+#include "llvm/IR/BasicBlock.h"
+#include "llvm/IR/Dominators.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/IntrinsicInst.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/OperandTraits.h"
+#include "llvm/IR/Type.h"
+#include "llvm/IR/Use.h"
+#include "llvm/IR/User.h"
+#include "llvm/IR/Value.h"
+#include "llvm/Pass.h"
+#include "llvm/PassAnalysisSupport.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/ErrorHandling.h"
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <iterator>
+#include <memory>
+#include <utility>
+
+namespace llvm {
+
+class DominatorTree;
+class Function;
+class Instruction;
+class MemoryAccess;
+class LLVMContext;
+class raw_ostream;
+class OrderedBasicBlock;
+
+enum PredicateType { PT_Branch, PT_Assume, PT_Switch };
+
+// Base class for all predicate information we provide.
+// All of our predicate information has at least a comparison.
+class PredicateBase : public ilist_node<PredicateBase> {
+public:
+ PredicateType Type;
+ // The original operand before we renamed it.
+ // This can be use by passes, when destroying predicateinfo, to know
+ // whether they can just drop the intrinsic, or have to merge metadata.
+ Value *OriginalOp;
+ PredicateBase(const PredicateBase &) = delete;
+ PredicateBase &operator=(const PredicateBase &) = delete;
+ PredicateBase() = delete;
+ virtual ~PredicateBase() = default;
+
+protected:
+ PredicateBase(PredicateType PT, Value *Op) : Type(PT), OriginalOp(Op) {}
+};
+
+class PredicateWithCondition : public PredicateBase {
+public:
+ Value *Condition;
+ static inline bool classof(const PredicateBase *PB) {
+ return PB->Type == PT_Assume || PB->Type == PT_Branch || PB->Type == PT_Switch;
+ }
+
+protected:
+ PredicateWithCondition(PredicateType PT, Value *Op, Value *Condition)
+ : PredicateBase(PT, Op), Condition(Condition) {}
+};
+
+// Provides predicate information for assumes. Since assumes are always true,
+// we simply provide the assume instruction, so you can tell your relative
+// position to it.
+class PredicateAssume : public PredicateWithCondition {
+public:
+ IntrinsicInst *AssumeInst;
+ PredicateAssume(Value *Op, IntrinsicInst *AssumeInst, Value *Condition)
+ : PredicateWithCondition(PT_Assume, Op, Condition),
+ AssumeInst(AssumeInst) {}
+ PredicateAssume() = delete;
+ static inline bool classof(const PredicateBase *PB) {
+ return PB->Type == PT_Assume;
+ }
+};
+
+// Mixin class for edge predicates. The FROM block is the block where the
+// predicate originates, and the TO block is the block where the predicate is
+// valid.
+class PredicateWithEdge : public PredicateWithCondition {
+public:
+ BasicBlock *From;
+ BasicBlock *To;
+ PredicateWithEdge() = delete;
+ static inline bool classof(const PredicateBase *PB) {
+ return PB->Type == PT_Branch || PB->Type == PT_Switch;
+ }
+
+protected:
+ PredicateWithEdge(PredicateType PType, Value *Op, BasicBlock *From,
+ BasicBlock *To, Value *Cond)
+ : PredicateWithCondition(PType, Op, Cond), From(From), To(To) {}
+};
+
+// Provides predicate information for branches.
+class PredicateBranch : public PredicateWithEdge {
+public:
+ // If true, SplitBB is the true successor, otherwise it's the false successor.
+ bool TrueEdge;
+ PredicateBranch(Value *Op, BasicBlock *BranchBB, BasicBlock *SplitBB,
+ Value *Condition, bool TakenEdge)
+ : PredicateWithEdge(PT_Branch, Op, BranchBB, SplitBB, Condition),
+ TrueEdge(TakenEdge) {}
+ PredicateBranch() = delete;
+ static inline bool classof(const PredicateBase *PB) {
+ return PB->Type == PT_Branch;
+ }
+};
+
+class PredicateSwitch : public PredicateWithEdge {
+public:
+ Value *CaseValue;
+ // This is the switch instruction.
+ SwitchInst *Switch;
+ PredicateSwitch(Value *Op, BasicBlock *SwitchBB, BasicBlock *TargetBB,
+ Value *CaseValue, SwitchInst *SI)
+ : PredicateWithEdge(PT_Switch, Op, SwitchBB, TargetBB,
+ SI->getCondition()),
+ CaseValue(CaseValue), Switch(SI) {}
+ PredicateSwitch() = delete;
+ static inline bool classof(const PredicateBase *PB) {
+ return PB->Type == PT_Switch;
+ }
+};
+
+// This name is used in a few places, so kick it into their own namespace
+namespace PredicateInfoClasses {
+struct ValueDFS;
+}
+
+/// \brief Encapsulates PredicateInfo, including all data associated with memory
+/// accesses.
+class PredicateInfo {
+private:
+ // Used to store information about each value we might rename.
+ struct ValueInfo {
+ // Information about each possible copy. During processing, this is each
+ // inserted info. After processing, we move the uninserted ones to the
+ // uninserted vector.
+ SmallVector<PredicateBase *, 4> Infos;
+ SmallVector<PredicateBase *, 4> UninsertedInfos;
+ };
+ // This owns the all the predicate infos in the function, placed or not.
+ iplist<PredicateBase> AllInfos;
+
+public:
+ PredicateInfo(Function &, DominatorTree &, AssumptionCache &);
+ ~PredicateInfo();
+
+ void verifyPredicateInfo() const;
+
+ void dump() const;
+ void print(raw_ostream &) const;
+
+ const PredicateBase *getPredicateInfoFor(const Value *V) const {
+ return PredicateMap.lookup(V);
+ }
+
+protected:
+ // Used by PredicateInfo annotater, dumpers, and wrapper pass.
+ friend class PredicateInfoAnnotatedWriter;
+ friend class PredicateInfoPrinterLegacyPass;
+
+private:
+ void buildPredicateInfo();
+ void processAssume(IntrinsicInst *, BasicBlock *, SmallPtrSetImpl<Value *> &);
+ void processBranch(BranchInst *, BasicBlock *, SmallPtrSetImpl<Value *> &);
+ void processSwitch(SwitchInst *, BasicBlock *, SmallPtrSetImpl<Value *> &);
+ void renameUses(SmallPtrSetImpl<Value *> &);
+ using ValueDFS = PredicateInfoClasses::ValueDFS;
+ typedef SmallVectorImpl<ValueDFS> ValueDFSStack;
+ void convertUsesToDFSOrdered(Value *, SmallVectorImpl<ValueDFS> &);
+ Value *materializeStack(unsigned int &, ValueDFSStack &, Value *);
+ bool stackIsInScope(const ValueDFSStack &, const ValueDFS &) const;
+ void popStackUntilDFSScope(ValueDFSStack &, const ValueDFS &);
+ ValueInfo &getOrCreateValueInfo(Value *);
+ void addInfoFor(SmallPtrSetImpl<Value *> &OpsToRename, Value *Op,
+ PredicateBase *PB);
+ const ValueInfo &getValueInfo(Value *) const;
+ Function &F;
+ DominatorTree &DT;
+ AssumptionCache &AC;
+ // This maps from copy operands to Predicate Info. Note that it does not own
+ // the Predicate Info, they belong to the ValueInfo structs in the ValueInfos
+ // vector.
+ DenseMap<const Value *, const PredicateBase *> PredicateMap;
+ // This stores info about each operand or comparison result we make copies
+ // of. The real ValueInfos start at index 1, index 0 is unused so that we can
+ // more easily detect invalid indexing.
+ SmallVector<ValueInfo, 32> ValueInfos;
+ // This gives the index into the ValueInfos array for a given Value. Because
+ // 0 is not a valid Value Info index, you can use DenseMap::lookup and tell
+ // whether it returned a valid result.
+ DenseMap<Value *, unsigned int> ValueInfoNums;
+ // OrderedBasicBlocks used during sorting uses
+ DenseMap<const BasicBlock *, std::unique_ptr<OrderedBasicBlock>> OBBMap;
+ // The set of edges along which we can only handle phi uses, due to critical
+ // edges.
+ DenseSet<std::pair<BasicBlock *, BasicBlock *>> EdgeUsesOnly;
+};
+
+// This pass does eager building and then printing of PredicateInfo. It is used
+// by
+// the tests to be able to build, dump, and verify PredicateInfo.
+class PredicateInfoPrinterLegacyPass : public FunctionPass {
+public:
+ PredicateInfoPrinterLegacyPass();
+
+ static char ID;
+ bool runOnFunction(Function &) override;
+ void getAnalysisUsage(AnalysisUsage &AU) const override;
+};
+
+/// \brief Printer pass for \c PredicateInfo.
+class PredicateInfoPrinterPass
+ : public PassInfoMixin<PredicateInfoPrinterPass> {
+ raw_ostream &OS;
+
+public:
+ explicit PredicateInfoPrinterPass(raw_ostream &OS) : OS(OS) {}
+ PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
+};
+
+/// \brief Verifier pass for \c PredicateInfo.
+struct PredicateInfoVerifierPass : PassInfoMixin<PredicateInfoVerifierPass> {
+ PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
+};
+
+} // end namespace llvm
+
+#endif // LLVM_TRANSFORMS_UTILS_PREDICATEINFO_H
diff --git a/include/llvm/Transforms/Utils/PromoteMemToReg.h b/include/llvm/Transforms/Utils/PromoteMemToReg.h
index b548072c413e..bb8a61a474f2 100644
--- a/include/llvm/Transforms/Utils/PromoteMemToReg.h
+++ b/include/llvm/Transforms/Utils/PromoteMemToReg.h
@@ -38,10 +38,7 @@ bool isAllocaPromotable(const AllocaInst *AI);
/// does not modify the CFG of the function at all. All allocas must be from
/// the same function.
///
-/// If AST is specified, the specified tracker is updated to reflect changes
-/// made to the IR.
void PromoteMemToReg(ArrayRef<AllocaInst *> Allocas, DominatorTree &DT,
- AliasSetTracker *AST = nullptr,
AssumptionCache *AC = nullptr);
} // End llvm namespace
diff --git a/include/llvm/Transforms/Utils/SSAUpdater.h b/include/llvm/Transforms/Utils/SSAUpdater.h
index 9f98bac22dc9..8cbcdf47156e 100644
--- a/include/llvm/Transforms/Utils/SSAUpdater.h
+++ b/include/llvm/Transforms/Utils/SSAUpdater.h
@@ -15,19 +15,20 @@
#define LLVM_TRANSFORMS_UTILS_SSAUPDATER_H
#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/Compiler.h"
+#include <string>
namespace llvm {
- class BasicBlock;
- class Instruction;
- class LoadInst;
- template <typename T> class ArrayRef;
- template <typename T> class SmallVectorImpl;
- template <typename T> class SSAUpdaterTraits;
- class PHINode;
- class Type;
- class Use;
- class Value;
+
+class BasicBlock;
+class Instruction;
+class LoadInst;
+template <typename T> class ArrayRef;
+template <typename T> class SmallVectorImpl;
+template <typename T> class SSAUpdaterTraits;
+class PHINode;
+class Type;
+class Use;
+class Value;
/// \brief Helper class for SSA formation on a set of values defined in
/// multiple blocks.
@@ -42,10 +43,10 @@ private:
/// This keeps track of which value to use on a per-block basis. When we
/// insert PHI nodes, we keep track of them here.
//typedef DenseMap<BasicBlock*, Value*> AvailableValsTy;
- void *AV;
+ void *AV = nullptr;
/// ProtoType holds the type of the values being rewritten.
- Type *ProtoType;
+ Type *ProtoType = nullptr;
/// PHI nodes are given a name based on ProtoName.
std::string ProtoName;
@@ -58,6 +59,8 @@ public:
/// If InsertedPHIs is specified, it will be filled
/// in with all PHI Nodes created by rewriting.
explicit SSAUpdater(SmallVectorImpl<PHINode*> *InsertedPHIs = nullptr);
+ SSAUpdater(const SSAUpdater &) = delete;
+ SSAUpdater &operator=(const SSAUpdater &) = delete;
~SSAUpdater();
/// \brief Reset this object to get ready for a new set of SSA updates with
@@ -118,9 +121,6 @@ public:
private:
Value *GetValueAtEndOfBlockInternal(BasicBlock *BB);
-
- void operator=(const SSAUpdater&) = delete;
- SSAUpdater(const SSAUpdater&) = delete;
};
/// \brief Helper class for promoting a collection of loads and stores into SSA
@@ -138,7 +138,7 @@ protected:
public:
LoadAndStorePromoter(ArrayRef<const Instruction*> Insts,
SSAUpdater &S, StringRef Name = StringRef());
- virtual ~LoadAndStorePromoter() {}
+ virtual ~LoadAndStorePromoter() = default;
/// \brief This does the promotion.
///
@@ -173,6 +173,6 @@ public:
}
};
-} // End llvm namespace
+} // end namespace llvm
-#endif
+#endif // LLVM_TRANSFORMS_UTILS_SSAUPDATER_H
diff --git a/include/llvm/Transforms/Utils/SimplifyIndVar.h b/include/llvm/Transforms/Utils/SimplifyIndVar.h
index 90438ee699fe..6cdeeeb60a65 100644
--- a/include/llvm/Transforms/Utils/SimplifyIndVar.h
+++ b/include/llvm/Transforms/Utils/SimplifyIndVar.h
@@ -22,7 +22,6 @@ namespace llvm {
class CastInst;
class DominatorTree;
-class IVUsers;
class Loop;
class LoopInfo;
class PHINode;
@@ -32,13 +31,13 @@ class ScalarEvolution;
/// simplified by this utility.
class IVVisitor {
protected:
- const DominatorTree *DT;
+ const DominatorTree *DT = nullptr;
virtual void anchor();
public:
- IVVisitor() : DT(nullptr) {}
- virtual ~IVVisitor() {}
+ IVVisitor() = default;
+ virtual ~IVVisitor() = default;
const DominatorTree *getDomTree() const { return DT; }
virtual void visitCast(CastInst *Cast) = 0;
@@ -55,6 +54,6 @@ bool simplifyUsersOfIV(PHINode *CurrIV, ScalarEvolution *SE, DominatorTree *DT,
bool simplifyLoopIVs(Loop *L, ScalarEvolution *SE, DominatorTree *DT,
LoopInfo *LI, SmallVectorImpl<WeakVH> &Dead);
-} // namespace llvm
+} // end namespace llvm
-#endif
+#endif // LLVM_TRANSFORMS_UTILS_SIMPLIFYINDVAR_H
diff --git a/include/llvm/Transforms/Utils/SimplifyLibCalls.h b/include/llvm/Transforms/Utils/SimplifyLibCalls.h
index 5e217adf1987..665dd6f4b257 100644
--- a/include/llvm/Transforms/Utils/SimplifyLibCalls.h
+++ b/include/llvm/Transforms/Utils/SimplifyLibCalls.h
@@ -56,8 +56,8 @@ private:
Value *optimizeMemSetChk(CallInst *CI, IRBuilder<> &B);
// Str/Stp cpy are similar enough to be handled in the same functions.
- Value *optimizeStrpCpyChk(CallInst *CI, IRBuilder<> &B, LibFunc::Func Func);
- Value *optimizeStrpNCpyChk(CallInst *CI, IRBuilder<> &B, LibFunc::Func Func);
+ Value *optimizeStrpCpyChk(CallInst *CI, IRBuilder<> &B, LibFunc Func);
+ Value *optimizeStrpNCpyChk(CallInst *CI, IRBuilder<> &B, LibFunc Func);
/// \brief Checks whether the call \p CI to a fortified libcall is foldable
/// to the non-fortified version.
@@ -128,7 +128,6 @@ private:
Value *optimizeCos(CallInst *CI, IRBuilder<> &B);
Value *optimizePow(CallInst *CI, IRBuilder<> &B);
Value *optimizeExp2(CallInst *CI, IRBuilder<> &B);
- Value *optimizeFabs(CallInst *CI, IRBuilder<> &B);
Value *optimizeFMinFMax(CallInst *CI, IRBuilder<> &B);
Value *optimizeLog(CallInst *CI, IRBuilder<> &B);
Value *optimizeSqrt(CallInst *CI, IRBuilder<> &B);
diff --git a/include/llvm/Transforms/Utils/SymbolRewriter.h b/include/llvm/Transforms/Utils/SymbolRewriter.h
index ff995173e126..93658989fba5 100644
--- a/include/llvm/Transforms/Utils/SymbolRewriter.h
+++ b/include/llvm/Transforms/Utils/SymbolRewriter.h
@@ -36,18 +36,24 @@
#include "llvm/IR/Module.h"
#include "llvm/IR/PassManager.h"
#include <list>
+#include <memory>
+#include <string>
namespace llvm {
+
class MemoryBuffer;
namespace yaml {
+
class KeyValueNode;
class MappingNode;
class ScalarNode;
class Stream;
-}
+
+} // end namespace yaml
namespace SymbolRewriter {
+
/// The basic entity representing a rewrite operation. It serves as the base
/// class for any rewrite descriptor. It has a certain set of specializations
/// which describe a particular rewrite.
@@ -60,11 +66,6 @@ namespace SymbolRewriter {
/// select the symbols to rewrite. This descriptor list is passed to the
/// SymbolRewriter pass.
class RewriteDescriptor {
- RewriteDescriptor(const RewriteDescriptor &) = delete;
-
- const RewriteDescriptor &
- operator=(const RewriteDescriptor &) = delete;
-
public:
enum class Type {
Invalid, /// invalid
@@ -73,7 +74,9 @@ public:
NamedAlias, /// named alias - descriptor rewrites a global alias
};
- virtual ~RewriteDescriptor() {}
+ RewriteDescriptor(const RewriteDescriptor &) = delete;
+ RewriteDescriptor &operator=(const RewriteDescriptor &) = delete;
+ virtual ~RewriteDescriptor() = default;
Type getType() const { return Kind; }
@@ -108,7 +111,8 @@ private:
yaml::MappingNode *V,
RewriteDescriptorList *DL);
};
-}
+
+} // end namespace SymbolRewriter
ModulePass *createRewriteSymbolsPass();
ModulePass *createRewriteSymbolsPass(SymbolRewriter::RewriteDescriptorList &);
@@ -130,6 +134,7 @@ private:
SymbolRewriter::RewriteDescriptorList Descriptors;
};
-}
+
+} // end namespace llvm
#endif //LLVM_TRANSFORMS_UTILS_SYMBOLREWRITER_H
diff --git a/include/llvm/Transforms/Utils/UnifyFunctionExitNodes.h b/include/llvm/Transforms/Utils/UnifyFunctionExitNodes.h
index 550292f6b7a3..222c601ad608 100644
--- a/include/llvm/Transforms/Utils/UnifyFunctionExitNodes.h
+++ b/include/llvm/Transforms/Utils/UnifyFunctionExitNodes.h
@@ -19,16 +19,18 @@
#define LLVM_TRANSFORMS_UTILS_UNIFYFUNCTIONEXITNODES_H
#include "llvm/Pass.h"
+#include "llvm/PassRegistry.h"
namespace llvm {
struct UnifyFunctionExitNodes : public FunctionPass {
- BasicBlock *ReturnBlock, *UnwindBlock, *UnreachableBlock;
+ BasicBlock *ReturnBlock = nullptr;
+ BasicBlock *UnwindBlock = nullptr;
+ BasicBlock *UnreachableBlock;
public:
static char ID; // Pass identification, replacement for typeid
- UnifyFunctionExitNodes() : FunctionPass(ID),
- ReturnBlock(nullptr), UnwindBlock(nullptr) {
+ UnifyFunctionExitNodes() : FunctionPass(ID) {
initializeUnifyFunctionExitNodesPass(*PassRegistry::getPassRegistry());
}
@@ -47,6 +49,6 @@ public:
Pass *createUnifyFunctionExitNodesPass();
-} // End llvm namespace
+} // end namespace llvm
-#endif
+#endif // LLVM_TRANSFORMS_UTILS_UNIFYFUNCTIONEXITNODES_H
diff --git a/include/llvm/Transforms/Utils/UnrollLoop.h b/include/llvm/Transforms/Utils/UnrollLoop.h
index f322bea7aa2e..a3115ad16914 100644
--- a/include/llvm/Transforms/Utils/UnrollLoop.h
+++ b/include/llvm/Transforms/Utils/UnrollLoop.h
@@ -53,10 +53,11 @@ bool UnrollRuntimeLoopRemainder(Loop *L, unsigned Count,
bool PreserveLCSSA);
void computePeelCount(Loop *L, unsigned LoopSize,
- TargetTransformInfo::UnrollingPreferences &UP);
+ TargetTransformInfo::UnrollingPreferences &UP,
+ unsigned &TripCount);
bool peelLoop(Loop *L, unsigned PeelCount, LoopInfo *LI, ScalarEvolution *SE,
- DominatorTree *DT, bool PreserveLCSSA);
+ DominatorTree *DT, AssumptionCache *AC, bool PreserveLCSSA);
MDNode *GetUnrollMetadata(MDNode *LoopID, StringRef Name);
}
diff --git a/include/llvm/Transforms/Utils/VNCoercion.h b/include/llvm/Transforms/Utils/VNCoercion.h
new file mode 100644
index 000000000000..1baa9b66e491
--- /dev/null
+++ b/include/llvm/Transforms/Utils/VNCoercion.h
@@ -0,0 +1,108 @@
+//===- VNCoercion.h - Value Numbering Coercion Utilities --------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file / This file provides routines used by LLVM's value numbering passes to
+/// perform various forms of value extraction from memory when the types are not
+/// identical. For example, given
+///
+/// store i32 8, i32 *%foo
+/// %a = bitcast i32 *%foo to i16
+/// %val = load i16, i16 *%a
+///
+/// It possible to extract the value of the load of %a from the store to %foo.
+/// These routines know how to tell whether they can do that (the analyze*
+/// routines), and can also insert the necessary IR to do it (the get*
+/// routines).
+
+#ifndef LLVM_TRANSFORMS_UTILS_VNCOERCION_H
+#define LLVM_TRANSFORMS_UTILS_VNCOERCION_H
+#include "llvm/IR/IRBuilder.h"
+
+namespace llvm {
+class Function;
+class StoreInst;
+class LoadInst;
+class MemIntrinsic;
+class Instruction;
+class Value;
+class Type;
+class DataLayout;
+namespace VNCoercion {
+/// Return true if CoerceAvailableValueToLoadType would succeed if it was
+/// called.
+bool canCoerceMustAliasedValueToLoad(Value *StoredVal, Type *LoadTy,
+ const DataLayout &DL);
+
+/// If we saw a store of a value to memory, and then a load from a must-aliased
+/// pointer of a different type, try to coerce the stored value to the loaded
+/// type. LoadedTy is the type of the load we want to replace. IRB is
+/// IRBuilder used to insert new instructions.
+///
+/// If we can't do it, return null.
+Value *coerceAvailableValueToLoadType(Value *StoredVal, Type *LoadedTy,
+ IRBuilder<> &IRB, const DataLayout &DL);
+
+/// This function determines whether a value for the pointer LoadPtr can be
+/// extracted from the store at DepSI.
+///
+/// On success, it returns the offset into DepSI that extraction would start.
+/// On failure, it returns -1.
+int analyzeLoadFromClobberingStore(Type *LoadTy, Value *LoadPtr,
+ StoreInst *DepSI, const DataLayout &DL);
+
+/// This function determines whether a value for the pointer LoadPtr can be
+/// extracted from the load at DepLI.
+///
+/// On success, it returns the offset into DepLI that extraction would start.
+/// On failure, it returns -1.
+int analyzeLoadFromClobberingLoad(Type *LoadTy, Value *LoadPtr, LoadInst *DepLI,
+ const DataLayout &DL);
+
+/// This function determines whether a value for the pointer LoadPtr can be
+/// extracted from the memory intrinsic at DepMI.
+///
+/// On success, it returns the offset into DepMI that extraction would start.
+/// On failure, it returns -1.
+int analyzeLoadFromClobberingMemInst(Type *LoadTy, Value *LoadPtr,
+ MemIntrinsic *DepMI, const DataLayout &DL);
+
+/// If analyzeLoadFromClobberingStore returned an offset, this function can be
+/// used to actually perform the extraction of the bits from the store. It
+/// inserts instructions to do so at InsertPt, and returns the extracted value.
+Value *getStoreValueForLoad(Value *SrcVal, unsigned Offset, Type *LoadTy,
+ Instruction *InsertPt, const DataLayout &DL);
+// This is the same as getStoreValueForLoad, except it performs no insertion
+// It only allows constant inputs.
+Constant *getConstantStoreValueForLoad(Constant *SrcVal, unsigned Offset,
+ Type *LoadTy, const DataLayout &DL);
+
+/// If analyzeLoadFromClobberingLoad returned an offset, this function can be
+/// used to actually perform the extraction of the bits from the load, including
+/// any necessary load widening. It inserts instructions to do so at InsertPt,
+/// and returns the extracted value.
+Value *getLoadValueForLoad(LoadInst *SrcVal, unsigned Offset, Type *LoadTy,
+ Instruction *InsertPt, const DataLayout &DL);
+// This is the same as getLoadValueForLoad, except it is given the load value as
+// a constant. It returns nullptr if it would require widening the load.
+Constant *getConstantLoadValueForLoad(Constant *SrcVal, unsigned Offset,
+ Type *LoadTy, const DataLayout &DL);
+
+/// If analyzeLoadFromClobberingMemInst returned an offset, this function can be
+/// used to actually perform the extraction of the bits from the memory
+/// intrinsic. It inserts instructions to do so at InsertPt, and returns the
+/// extracted value.
+Value *getMemInstValueForLoad(MemIntrinsic *SrcInst, unsigned Offset,
+ Type *LoadTy, Instruction *InsertPt,
+ const DataLayout &DL);
+// This is the same as getStoreValueForLoad, except it performs no insertion.
+// It returns nullptr if it cannot produce a constant.
+Constant *getConstantMemInstValueForLoad(MemIntrinsic *SrcInst, unsigned Offset,
+ Type *LoadTy, const DataLayout &DL);
+}
+}
+#endif
diff --git a/include/llvm/Transforms/Utils/ValueMapper.h b/include/llvm/Transforms/Utils/ValueMapper.h
index de649009612c..950ad92afcd7 100644
--- a/include/llvm/Transforms/Utils/ValueMapper.h
+++ b/include/llvm/Transforms/Utils/ValueMapper.h
@@ -15,7 +15,9 @@
#ifndef LLVM_TRANSFORMS_UTILS_VALUEMAPPER_H
#define LLVM_TRANSFORMS_UTILS_VALUEMAPPER_H
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/IR/ValueMap.h"
+#include "llvm/IR/ValueHandle.h"
namespace llvm {
@@ -27,8 +29,9 @@ typedef ValueMap<const Value *, WeakVH> ValueToValueMapTy;
/// cloning constants and instructions.
class ValueMapTypeRemapper {
virtual void anchor(); // Out of line method.
+
public:
- virtual ~ValueMapTypeRemapper() {}
+ virtual ~ValueMapTypeRemapper() = default;
/// The client should implement this method if they want to remap types while
/// mapping values.
@@ -92,8 +95,6 @@ static inline RemapFlags operator|(RemapFlags LHS, RemapFlags RHS) {
return RemapFlags(unsigned(LHS) | unsigned(RHS));
}
-class ValueMapperImpl;
-
/// Context for (re-)mapping values (and metadata).
///
/// A shared context used for mapping and remapping of Value and Metadata
@@ -133,15 +134,14 @@ class ValueMapperImpl;
class ValueMapper {
void *pImpl;
- ValueMapper(ValueMapper &&) = delete;
- ValueMapper(const ValueMapper &) = delete;
- ValueMapper &operator=(ValueMapper &&) = delete;
- ValueMapper &operator=(const ValueMapper &) = delete;
-
public:
ValueMapper(ValueToValueMapTy &VM, RemapFlags Flags = RF_None,
ValueMapTypeRemapper *TypeMapper = nullptr,
ValueMaterializer *Materializer = nullptr);
+ ValueMapper(ValueMapper &&) = delete;
+ ValueMapper(const ValueMapper &) = delete;
+ ValueMapper &operator=(ValueMapper &&) = delete;
+ ValueMapper &operator=(const ValueMapper &) = delete;
~ValueMapper();
/// Register an alternate mapping context.
@@ -268,6 +268,6 @@ inline Constant *MapValue(const Constant *V, ValueToValueMapTy &VM,
return ValueMapper(VM, Flags, TypeMapper, Materializer).mapConstant(*V);
}
-} // End llvm namespace
+} // end namespace llvm
-#endif
+#endif // LLVM_TRANSFORMS_UTILS_VALUEMAPPER_H
diff --git a/include/llvm/Transforms/Vectorize/SLPVectorizer.h b/include/llvm/Transforms/Vectorize/SLPVectorizer.h
index 4886700774ca..d669a8e5b615 100644
--- a/include/llvm/Transforms/Vectorize/SLPVectorizer.h
+++ b/include/llvm/Transforms/Vectorize/SLPVectorizer.h
@@ -92,6 +92,12 @@ private:
/// collected in GEPs.
bool vectorizeGEPIndices(BasicBlock *BB, slpvectorizer::BoUpSLP &R);
+ /// Try to find horizontal reduction or otherwise vectorize a chain of binary
+ /// operators.
+ bool vectorizeRootInstruction(PHINode *P, Value *V, BasicBlock *BB,
+ slpvectorizer::BoUpSLP &R,
+ TargetTransformInfo *TTI);
+
/// \brief Scan the basic block and look for patterns that are likely to start
/// a vectorization chain.
bool vectorizeChainsInBlock(BasicBlock *BB, slpvectorizer::BoUpSLP &R);
diff --git a/include/llvm/XRay/Graph.h b/include/llvm/XRay/Graph.h
new file mode 100644
index 000000000000..a4d34a8a4be3
--- /dev/null
+++ b/include/llvm/XRay/Graph.h
@@ -0,0 +1,494 @@
+//===-- Graph.h - XRay Graph Class ------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// A Graph Datatype for XRay.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_XRAY_GRAPH_T_H
+#define LLVM_XRAY_GRAPH_T_H
+
+#include <initializer_list>
+#include <stdint.h>
+#include <type_traits>
+#include <utility>
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/iterator.h"
+#include "llvm/Support/Error.h"
+
+namespace llvm {
+namespace xray {
+
+/// A Graph object represents a Directed Graph and is used in XRay to compute
+/// and store function call graphs and associated statistical information.
+///
+/// The graph takes in four template parameters, these are:
+/// - VertexAttribute, this is a structure which is stored for each vertex.
+/// Must be DefaultConstructible, CopyConstructible, CopyAssignable and
+/// Destructible.
+/// - EdgeAttribute, this is a structure which is stored for each edge
+/// Must be DefaultConstructible, CopyConstructible, CopyAssignable and
+/// Destructible.
+/// - EdgeAttribute, this is a structure which is stored for each variable
+/// - VI, this is a type over which DenseMapInfo is defined and is the type
+/// used look up strings, available as VertexIdentifier.
+/// - If the built in DenseMapInfo is not defined, provide a specialization
+/// class type here.
+///
+/// Graph is CopyConstructible, CopyAssignable, MoveConstructible and
+/// MoveAssignable but is not EqualityComparible or LessThanComparible.
+///
+/// Usage Example Graph with weighted edges and vertices:
+/// Graph<int, int, int> G;
+///
+/// G[1] = 0;
+/// G[2] = 2;
+/// G[{1,2}] = 1;
+/// G[{2,1}] = -1;
+/// for(const auto &v : G.vertices()){
+/// // Do something with the vertices in the graph;
+/// }
+/// for(const auto &e : G.edges()){
+/// // Do something with the edges in the graph;
+/// }
+///
+/// Usage Example with StrRef keys.
+/// Graph<int, double, StrRef> StrG;
+/// char va[] = "Vertex A";
+/// char vaa[] = "Vertex A";
+/// char vb[] = "Vertex B"; // Vertices are referenced by String Refs.
+/// G[va] = 0;
+/// G[vb] = 1;
+/// G[{va, vb}] = 1.0;
+/// cout() << G[vaa] << " " << G[{vaa, vb}]; //prints "0 1.0".
+///
+template <typename VertexAttribute, typename EdgeAttribute,
+ typename VI = int32_t>
+class Graph {
+public:
+ /// These objects are used to name edges and vertices in the graph.
+ typedef VI VertexIdentifier;
+ typedef std::pair<VI, VI> EdgeIdentifier;
+
+ /// This type is the value_type of all iterators which range over vertices,
+ /// Determined by the Vertices DenseMap
+ using VertexValueType =
+ detail::DenseMapPair<VertexIdentifier, VertexAttribute>;
+
+ /// This type is the value_type of all iterators which range over edges,
+ /// Determined by the Edges DenseMap.
+ using EdgeValueType = detail::DenseMapPair<EdgeIdentifier, EdgeAttribute>;
+
+ using size_type = std::size_t;
+
+private:
+ /// The type used for storing the EdgeAttribute for each edge in the graph
+ using EdgeMapT = DenseMap<EdgeIdentifier, EdgeAttribute>;
+
+ /// The type used for storing the VertexAttribute for each vertex in
+ /// the graph.
+ using VertexMapT = DenseMap<VertexIdentifier, VertexAttribute>;
+
+ /// The type used for storing the edges entering a vertex. Indexed by
+ /// the VertexIdentifier of the start of the edge. Only used to determine
+ /// where the incoming edges are, the EdgeIdentifiers are stored in an
+ /// InnerEdgeMapT.
+ using NeighborSetT = DenseSet<VertexIdentifier>;
+
+ /// The type storing the InnerInvGraphT corresponding to each vertex in
+ /// the graph (When a vertex has an incoming edge incident to it)
+ using NeighborLookupT = DenseMap<VertexIdentifier, NeighborSetT>;
+
+private:
+ /// Stores the map from the start and end vertex of an edge to it's
+ /// EdgeAttribute
+ EdgeMapT Edges;
+
+ /// Stores the map from VertexIdentifier to VertexAttribute
+ VertexMapT Vertices;
+
+ /// Allows fast lookup for the incoming edge set of any given vertex.
+ NeighborLookupT InNeighbors;
+
+ /// Allows fast lookup for the outgoing edge set of any given vertex.
+ NeighborLookupT OutNeighbors;
+
+ /// An Iterator adapter using an InnerInvGraphT::iterator as a base iterator,
+ /// and storing the VertexIdentifier the iterator range comes from. The
+ /// dereference operator is then performed using a pointer to the graph's edge
+ /// set.
+ template <bool IsConst, bool IsOut,
+ typename BaseIt = typename NeighborSetT::const_iterator,
+ typename T = typename std::conditional<IsConst, const EdgeValueType,
+ EdgeValueType>::type>
+ class NeighborEdgeIteratorT
+ : public iterator_adaptor_base<
+ NeighborEdgeIteratorT<IsConst, IsOut>, BaseIt,
+ typename std::iterator_traits<BaseIt>::iterator_category, T> {
+ using InternalEdgeMapT =
+ typename std::conditional<IsConst, const EdgeMapT, EdgeMapT>::type;
+
+ friend class NeighborEdgeIteratorT<false, IsOut, BaseIt, EdgeValueType>;
+ friend class NeighborEdgeIteratorT<true, IsOut, BaseIt,
+ const EdgeValueType>;
+
+ InternalEdgeMapT *MP;
+ VertexIdentifier SI;
+
+ public:
+ template <bool IsConstDest,
+ typename = typename std::enable_if<IsConstDest && !IsConst>::type>
+ operator NeighborEdgeIteratorT<IsConstDest, IsOut, BaseIt,
+ const EdgeValueType>() const {
+ return NeighborEdgeIteratorT<IsConstDest, IsOut, BaseIt,
+ const EdgeValueType>(this->I, MP, SI);
+ }
+
+ NeighborEdgeIteratorT() = default;
+ NeighborEdgeIteratorT(BaseIt _I, InternalEdgeMapT *_MP,
+ VertexIdentifier _SI)
+ : iterator_adaptor_base<
+ NeighborEdgeIteratorT<IsConst, IsOut>, BaseIt,
+ typename std::iterator_traits<BaseIt>::iterator_category, T>(_I),
+ MP(_MP), SI(_SI) {}
+
+ T &operator*() const {
+ if (!IsOut)
+ return *(MP->find({*(this->I), SI}));
+ else
+ return *(MP->find({SI, *(this->I)}));
+ }
+ };
+
+public:
+ /// A const iterator type for iterating through the set of edges entering a
+ /// vertex.
+ ///
+ /// Has a const EdgeValueType as its value_type
+ using ConstInEdgeIterator = NeighborEdgeIteratorT<true, false>;
+
+ /// An iterator type for iterating through the set of edges leaving a vertex.
+ ///
+ /// Has an EdgeValueType as its value_type
+ using InEdgeIterator = NeighborEdgeIteratorT<false, false>;
+
+ /// A const iterator type for iterating through the set of edges entering a
+ /// vertex.
+ ///
+ /// Has a const EdgeValueType as its value_type
+ using ConstOutEdgeIterator = NeighborEdgeIteratorT<true, true>;
+
+ /// An iterator type for iterating through the set of edges leaving a vertex.
+ ///
+ /// Has an EdgeValueType as its value_type
+ using OutEdgeIterator = NeighborEdgeIteratorT<false, true>;
+
+ /// A class for ranging over the incoming edges incident to a vertex.
+ ///
+ /// Like all views in this class it provides methods to get the beginning and
+ /// past the range iterators for the range, as well as methods to determine
+ /// the number of elements in the range and whether the range is empty.
+ template <bool isConst, bool isOut> class InOutEdgeView {
+ public:
+ using iterator = NeighborEdgeIteratorT<isConst, isOut>;
+ using const_iterator = NeighborEdgeIteratorT<true, isOut>;
+ using GraphT = typename std::conditional<isConst, const Graph, Graph>::type;
+ using InternalEdgeMapT =
+ typename std::conditional<isConst, const EdgeMapT, EdgeMapT>::type;
+
+ private:
+ InternalEdgeMapT &M;
+ const VertexIdentifier A;
+ const NeighborLookupT &NL;
+
+ public:
+ iterator begin() {
+ auto It = NL.find(A);
+ if (It == NL.end())
+ return iterator();
+ return iterator(It->second.begin(), &M, A);
+ }
+
+ const_iterator cbegin() const {
+ auto It = NL.find(A);
+ if (It == NL.end())
+ return const_iterator();
+ return const_iterator(It->second.begin(), &M, A);
+ }
+
+ const_iterator begin() const { return cbegin(); }
+
+ iterator end() {
+ auto It = NL.find(A);
+ if (It == NL.end())
+ return iterator();
+ return iterator(It->second.end(), &M, A);
+ }
+ const_iterator cend() const {
+ auto It = NL.find(A);
+ if (It == NL.end())
+ return const_iterator();
+ return const_iterator(It->second.end(), &M, A);
+ }
+
+ const_iterator end() const { return cend(); }
+
+ size_type size() const {
+ auto I = NL.find(A);
+ if (I == NL.end())
+ return 0;
+ else
+ return I->second.size();
+ }
+
+ bool empty() const { return NL.count(A) == 0; };
+
+ InOutEdgeView(GraphT &G, VertexIdentifier A)
+ : M(G.Edges), A(A), NL(isOut ? G.OutNeighbors : G.InNeighbors) {}
+ };
+
+ /// A const iterator type for iterating through the whole vertex set of the
+ /// graph.
+ ///
+ /// Has a const VertexValueType as its value_type
+ using ConstVertexIterator = typename VertexMapT::const_iterator;
+
+ /// An iterator type for iterating through the whole vertex set of the graph.
+ ///
+ /// Has a VertexValueType as its value_type
+ using VertexIterator = typename VertexMapT::iterator;
+
+ /// A class for ranging over the vertices in the graph.
+ ///
+ /// Like all views in this class it provides methods to get the beginning and
+ /// past the range iterators for the range, as well as methods to determine
+ /// the number of elements in the range and whether the range is empty.
+ template <bool isConst> class VertexView {
+ public:
+ using iterator = typename std::conditional<isConst, ConstVertexIterator,
+ VertexIterator>::type;
+ using const_iterator = ConstVertexIterator;
+ using GraphT = typename std::conditional<isConst, const Graph, Graph>::type;
+
+ private:
+ GraphT &G;
+
+ public:
+ iterator begin() { return G.Vertices.begin(); }
+ iterator end() { return G.Vertices.end(); }
+ const_iterator cbegin() const { return G.Vertices.cbegin(); }
+ const_iterator cend() const { return G.Vertices.cend(); }
+ const_iterator begin() const { return G.Vertices.begin(); }
+ const_iterator end() const { return G.Vertices.end(); }
+ size_type size() const { return G.Vertices.size(); }
+ bool empty() const { return G.Vertices.empty(); }
+ VertexView(GraphT &_G) : G(_G) {}
+ };
+
+ /// A const iterator for iterating through the entire edge set of the graph.
+ ///
+ /// Has a const EdgeValueType as its value_type
+ using ConstEdgeIterator = typename EdgeMapT::const_iterator;
+
+ /// An iterator for iterating through the entire edge set of the graph.
+ ///
+ /// Has an EdgeValueType as its value_type
+ using EdgeIterator = typename EdgeMapT::iterator;
+
+ /// A class for ranging over all the edges in the graph.
+ ///
+ /// Like all views in this class it provides methods to get the beginning and
+ /// past the range iterators for the range, as well as methods to determine
+ /// the number of elements in the range and whether the range is empty.
+ template <bool isConst> class EdgeView {
+ public:
+ using iterator = typename std::conditional<isConst, ConstEdgeIterator,
+ EdgeIterator>::type;
+ using const_iterator = ConstEdgeIterator;
+ using GraphT = typename std::conditional<isConst, const Graph, Graph>::type;
+
+ private:
+ GraphT &G;
+
+ public:
+ iterator begin() { return G.Edges.begin(); }
+ iterator end() { return G.Edges.end(); }
+ const_iterator cbegin() const { return G.Edges.cbegin(); }
+ const_iterator cend() const { return G.Edges.cend(); }
+ const_iterator begin() const { return G.Edges.begin(); }
+ const_iterator end() const { return G.Edges.end(); }
+ size_type size() const { return G.Edges.size(); }
+ bool empty() const { return G.Edges.empty(); }
+ EdgeView(GraphT &_G) : G(_G) {}
+ };
+
+public:
+ // TODO: implement constructor to enable Graph Initialisation.\
+ // Something like:
+ // Graph<int, int, int> G(
+ // {1, 2, 3, 4, 5},
+ // {{1, 2}, {2, 3}, {3, 4}});
+
+ /// Empty the Graph
+ void clear() {
+ Edges.clear();
+ Vertices.clear();
+ InNeighbors.clear();
+ OutNeighbors.clear();
+ }
+
+ /// Returns a view object allowing iteration over the vertices of the graph.
+ /// also allows access to the size of the vertex set.
+ VertexView<false> vertices() { return VertexView<false>(*this); }
+
+ VertexView<true> vertices() const { return VertexView<true>(*this); }
+
+ /// Returns a view object allowing iteration over the edges of the graph.
+ /// also allows access to the size of the edge set.
+ EdgeView<false> edges() { return EdgeView<false>(*this); }
+
+ EdgeView<true> edges() const { return EdgeView<true>(*this); }
+
+ /// Returns a view object allowing iteration over the edges which start at
+ /// a vertex I.
+ InOutEdgeView<false, true> outEdges(const VertexIdentifier I) {
+ return InOutEdgeView<false, true>(*this, I);
+ }
+
+ InOutEdgeView<true, true> outEdges(const VertexIdentifier I) const {
+ return InOutEdgeView<true, true>(*this, I);
+ }
+
+ /// Returns a view object allowing iteration over the edges which point to
+ /// a vertex I.
+ InOutEdgeView<false, false> inEdges(const VertexIdentifier I) {
+ return InOutEdgeView<false, false>(*this, I);
+ }
+
+ InOutEdgeView<true, false> inEdges(const VertexIdentifier I) const {
+ return InOutEdgeView<true, false>(*this, I);
+ }
+
+ /// Looks up the vertex with identifier I, if it does not exist it default
+ /// constructs it.
+ VertexAttribute &operator[](const VertexIdentifier &I) {
+ return Vertices.FindAndConstruct(I).second;
+ }
+
+ /// Looks up the edge with identifier I, if it does not exist it default
+ /// constructs it, if it's endpoints do not exist it also default constructs
+ /// them.
+ EdgeAttribute &operator[](const EdgeIdentifier &I) {
+ auto &P = Edges.FindAndConstruct(I);
+ Vertices.FindAndConstruct(I.first);
+ Vertices.FindAndConstruct(I.second);
+ InNeighbors[I.second].insert(I.first);
+ OutNeighbors[I.first].insert(I.second);
+ return P.second;
+ }
+
+ /// Looks up a vertex with Identifier I, or an error if it does not exist.
+ Expected<VertexAttribute &> at(const VertexIdentifier &I) {
+ auto It = Vertices.find(I);
+ if (It == Vertices.end())
+ return make_error<StringError>(
+ "Vertex Identifier Does Not Exist",
+ std::make_error_code(std::errc::invalid_argument));
+ return It->second;
+ }
+
+ Expected<const VertexAttribute &> at(const VertexIdentifier &I) const {
+ auto It = Vertices.find(I);
+ if (It == Vertices.end())
+ return make_error<StringError>(
+ "Vertex Identifier Does Not Exist",
+ std::make_error_code(std::errc::invalid_argument));
+ return It->second;
+ }
+
+ /// Looks up an edge with Identifier I, or an error if it does not exist.
+ Expected<EdgeAttribute &> at(const EdgeIdentifier &I) {
+ auto It = Edges.find(I);
+ if (It == Edges.end())
+ return make_error<StringError>(
+ "Edge Identifier Does Not Exist",
+ std::make_error_code(std::errc::invalid_argument));
+ return It->second;
+ }
+
+ Expected<const EdgeAttribute &> at(const EdgeIdentifier &I) const {
+ auto It = Edges.find(I);
+ if (It == Edges.end())
+ return make_error<StringError>(
+ "Edge Identifier Does Not Exist",
+ std::make_error_code(std::errc::invalid_argument));
+ return It->second;
+ }
+
+ /// Looks for a vertex with identifier I, returns 1 if one exists, and
+ /// 0 otherwise
+ size_type count(const VertexIdentifier &I) const {
+ return Vertices.count(I);
+ }
+
+ /// Looks for an edge with Identifier I, returns 1 if one exists and 0
+ /// otherwise
+ size_type count(const EdgeIdentifier &I) const { return Edges.count(I); }
+
+ /// Inserts a vertex into the graph with Identifier Val.first, and
+ /// Attribute Val.second.
+ std::pair<VertexIterator, bool>
+ insert(const std::pair<VertexIdentifier, VertexAttribute> &Val) {
+ return Vertices.insert(Val);
+ }
+
+ std::pair<VertexIterator, bool>
+ insert(std::pair<VertexIdentifier, VertexAttribute> &&Val) {
+ return Vertices.insert(std::move(Val));
+ }
+
+ /// Inserts an edge into the graph with Identifier Val.first, and
+ /// Attribute Val.second. If the key is already in the map, it returns false
+ /// and doesn't update the value.
+ std::pair<EdgeIterator, bool>
+ insert(const std::pair<EdgeIdentifier, EdgeAttribute> &Val) {
+ const auto &p = Edges.insert(Val);
+ if (p.second) {
+ const auto &EI = Val.first;
+ Vertices.FindAndConstruct(EI.first);
+ Vertices.FindAndConstruct(EI.second);
+ InNeighbors[EI.second].insert(EI.first);
+ OutNeighbors[EI.first].insert(EI.second);
+ };
+
+ return p;
+ }
+
+ /// Inserts an edge into the graph with Identifier Val.first, and
+ /// Attribute Val.second. If the key is already in the map, it returns false
+ /// and doesn't update the value.
+ std::pair<EdgeIterator, bool>
+ insert(std::pair<EdgeIdentifier, EdgeAttribute> &&Val) {
+ auto EI = Val.first;
+ const auto &p = Edges.insert(std::move(Val));
+ if (p.second) {
+ Vertices.FindAndConstruct(EI.first);
+ Vertices.FindAndConstruct(EI.second);
+ InNeighbors[EI.second].insert(EI.first);
+ OutNeighbors[EI.first].insert(EI.second);
+ };
+
+ return p;
+ }
+};
+}
+}
+#endif
diff --git a/include/llvm/XRay/InstrumentationMap.h b/include/llvm/XRay/InstrumentationMap.h
new file mode 100644
index 000000000000..f7286c52ff42
--- /dev/null
+++ b/include/llvm/XRay/InstrumentationMap.h
@@ -0,0 +1,129 @@
+//===- InstrumentationMap.h - XRay Instrumentation Map ----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Defines the interface for extracting the instrumentation map from an
+// XRay-instrumented binary.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_XRAY_INSTRUMENTATION_MAP_H
+#define LLVM_XRAY_INSTRUMENTATION_MAP_H
+
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/YAMLTraits.h"
+#include <cstdint>
+#include <unordered_map>
+#include <vector>
+
+namespace llvm {
+
+namespace xray {
+
+// Forward declare to make a friend.
+class InstrumentationMap;
+
+/// Loads the instrumentation map from |Filename|. This auto-deduces the type of
+/// the instrumentation map.
+Expected<InstrumentationMap> loadInstrumentationMap(StringRef Filename);
+
+/// Represents an XRay instrumentation sled entry from an object file.
+struct SledEntry {
+ /// Each entry here represents the kinds of supported instrumentation map
+ /// entries.
+ enum class FunctionKinds { ENTRY, EXIT, TAIL };
+
+ /// The address of the sled.
+ uint64_t Address;
+
+ /// The address of the function.
+ uint64_t Function;
+
+ /// The kind of sled.
+ FunctionKinds Kind;
+
+ /// Whether the sled was annotated to always be instrumented.
+ bool AlwaysInstrument;
+};
+
+struct YAMLXRaySledEntry {
+ int32_t FuncId;
+ yaml::Hex64 Address;
+ yaml::Hex64 Function;
+ SledEntry::FunctionKinds Kind;
+ bool AlwaysInstrument;
+};
+
+/// The InstrumentationMap represents the computed function id's and indicated
+/// function addresses from an object file (or a YAML file). This provides an
+/// interface to just the mapping between the function id, and the function
+/// address.
+///
+/// We also provide raw access to the actual instrumentation map entries we find
+/// associated with a particular object file.
+///
+class InstrumentationMap {
+public:
+ using FunctionAddressMap = std::unordered_map<int32_t, uint64_t>;
+ using FunctionAddressReverseMap = std::unordered_map<uint64_t, int32_t>;
+ using SledContainer = std::vector<SledEntry>;
+
+private:
+ SledContainer Sleds;
+ FunctionAddressMap FunctionAddresses;
+ FunctionAddressReverseMap FunctionIds;
+
+ friend Expected<InstrumentationMap> loadInstrumentationMap(StringRef);
+
+public:
+ /// Provides a raw accessor to the unordered map of function addresses.
+ const FunctionAddressMap &getFunctionAddresses() { return FunctionAddresses; }
+
+ /// Returns an XRay computed function id, provided a function address.
+ Optional<int32_t> getFunctionId(uint64_t Addr) const;
+
+ /// Returns the function address for a function id.
+ Optional<uint64_t> getFunctionAddr(int32_t FuncId) const;
+
+ /// Provide read-only access to the entries of the instrumentation map.
+ const SledContainer &sleds() const { return Sleds; };
+};
+
+} // end namespace xray
+
+namespace yaml {
+
+template <> struct ScalarEnumerationTraits<xray::SledEntry::FunctionKinds> {
+ static void enumeration(IO &IO, xray::SledEntry::FunctionKinds &Kind) {
+ IO.enumCase(Kind, "function-enter", xray::SledEntry::FunctionKinds::ENTRY);
+ IO.enumCase(Kind, "function-exit", xray::SledEntry::FunctionKinds::EXIT);
+ IO.enumCase(Kind, "tail-exit", xray::SledEntry::FunctionKinds::TAIL);
+ }
+};
+
+template <> struct MappingTraits<xray::YAMLXRaySledEntry> {
+ static void mapping(IO &IO, xray::YAMLXRaySledEntry &Entry) {
+ IO.mapRequired("id", Entry.FuncId);
+ IO.mapRequired("address", Entry.Address);
+ IO.mapRequired("function", Entry.Function);
+ IO.mapRequired("kind", Entry.Kind);
+ IO.mapRequired("always-instrument", Entry.AlwaysInstrument);
+ }
+
+ static constexpr bool flow = true;
+};
+
+} // end namespace yaml
+
+} // end namespace llvm
+
+LLVM_YAML_IS_SEQUENCE_VECTOR(xray::YAMLXRaySledEntry)
+
+#endif // LLVM_XRAY_INSTRUMENTATION_MAP_H
diff --git a/include/llvm/XRay/XRayRecord.h b/include/llvm/XRay/XRayRecord.h
index a96846136ec3..68c91a40fed1 100644
--- a/include/llvm/XRay/XRayRecord.h
+++ b/include/llvm/XRay/XRayRecord.h
@@ -42,6 +42,11 @@ struct XRayFileHeader {
/// counter (TSC) values. Useful for estimating the amount of time that
/// elapsed between two TSCs on some platforms.
uint64_t CycleFrequency = 0;
+
+ // This is different depending on the type of xray record. The naive format
+ // stores a Wallclock timespec. FDR logging stores the size of a thread
+ // buffer.
+ char FreeFormData[16];
};
/// Determines the supported types of records that could be seen in XRay traces.
@@ -54,8 +59,8 @@ struct XRayRecord {
/// The type of record.
uint16_t RecordType;
- /// The CPU where the thread is running. We assume number of CPUs <= 256.
- uint8_t CPU;
+ /// The CPU where the thread is running. We assume number of CPUs <= 65536.
+ uint16_t CPU;
/// Identifies the type of record.
RecordTypes Type;
diff --git a/include/llvm/XRay/YAMLXRayRecord.h b/include/llvm/XRay/YAMLXRayRecord.h
index f5836b392242..7e1a4112818e 100644
--- a/include/llvm/XRay/YAMLXRayRecord.h
+++ b/include/llvm/XRay/YAMLXRayRecord.h
@@ -31,7 +31,7 @@ struct YAMLXRayFileHeader {
struct YAMLXRayRecord {
uint16_t RecordType;
- uint8_t CPU;
+ uint16_t CPU;
RecordTypes Type;
int32_t FuncId;
std::string Function;
diff --git a/include/llvm/module.modulemap b/include/llvm/module.modulemap
index 29e6d66b27ff..59b1f1621039 100644
--- a/include/llvm/module.modulemap
+++ b/include/llvm/module.modulemap
@@ -276,6 +276,7 @@ module LLVM_Utils {
textual header "Support/ELFRelocs/SystemZ.def"
textual header "Support/ELFRelocs/x86_64.def"
textual header "Support/ELFRelocs/WebAssembly.def"
+ textual header "Support/WasmRelocs/WebAssembly.def"
}
// This part of the module is usable from both C and C++ code.
@@ -283,12 +284,12 @@ module LLVM_Utils {
header "Support/ConvertUTF.h"
export *
}
-}
-module LLVM_CodeGen_MachineValueType {
- requires cplusplus
- header "CodeGen/MachineValueType.h"
- export *
+ module LLVM_CodeGen_MachineValueType {
+ requires cplusplus
+ header "CodeGen/MachineValueType.h"
+ export *
+ }
}
// This is used for a $src == $build compilation. Otherwise we use