From ebe69fe11e48d322045d5949c83283927a0d790b Mon Sep 17 00:00:00 2001 From: Stephen Hines Date: Mon, 23 Mar 2015 12:10:34 -0700 Subject: Update aosp/master LLVM for rebase to r230699. Change-Id: I2b5be30509658cb8266be782de0ab24f9099f9b9 --- include/llvm-c/Core.h | 5 +- include/llvm-c/ExecutionEngine.h | 4 + include/llvm-c/Linker.h | 9 +- include/llvm-c/Transforms/Scalar.h | 3 + include/llvm-c/lto.h | 48 +- include/llvm/ADT/APFloat.h | 2 +- include/llvm/ADT/APInt.h | 15 +- include/llvm/ADT/APSInt.h | 73 +- include/llvm/ADT/ArrayRef.h | 2 - include/llvm/ADT/BitVector.h | 42 +- include/llvm/ADT/DenseMap.h | 207 +-- include/llvm/ADT/DenseSet.h | 35 +- include/llvm/ADT/DepthFirstIterator.h | 2 +- include/llvm/ADT/EquivalenceClasses.h | 3 +- include/llvm/ADT/FoldingSet.h | 74 +- include/llvm/ADT/Hashing.h | 104 -- include/llvm/ADT/ImmutableList.h | 4 +- include/llvm/ADT/ImmutableMap.h | 4 +- include/llvm/ADT/ImmutableSet.h | 4 +- include/llvm/ADT/IntervalMap.h | 2 +- include/llvm/ADT/IntrusiveRefCntPtr.h | 6 +- include/llvm/ADT/MapVector.h | 9 + include/llvm/ADT/None.h | 5 +- include/llvm/ADT/Optional.h | 49 +- include/llvm/ADT/PointerUnion.h | 80 +- include/llvm/ADT/STLExtras.h | 280 +--- include/llvm/ADT/ScopedHashTable.h | 4 +- include/llvm/ADT/SmallBitVector.h | 28 +- include/llvm/ADT/SmallPtrSet.h | 10 +- include/llvm/ADT/SmallVector.h | 53 +- include/llvm/ADT/SparseBitVector.h | 34 +- include/llvm/ADT/SparseMultiSet.h | 4 +- include/llvm/ADT/SparseSet.h | 4 +- include/llvm/ADT/StringMap.h | 15 +- include/llvm/ADT/StringRef.h | 7 + include/llvm/ADT/TinyPtrVector.h | 22 +- include/llvm/ADT/Triple.h | 55 +- include/llvm/ADT/Twine.h | 14 +- include/llvm/ADT/ilist.h | 12 +- include/llvm/ADT/iterator.h | 2 +- include/llvm/ADT/iterator_range.h | 1 - include/llvm/Analysis/AliasAnalysis.h | 27 +- include/llvm/Analysis/AliasSetTracker.h | 4 +- include/llvm/Analysis/AssumptionCache.h | 183 +++ include/llvm/Analysis/AssumptionTracker.h | 128 -- include/llvm/Analysis/BranchProbabilityInfo.h | 4 + include/llvm/Analysis/CGSCCPassManager.h | 192 +-- include/llvm/Analysis/CallGraph.h | 4 +- include/llvm/Analysis/CodeMetrics.h | 10 +- include/llvm/Analysis/DependenceAnalysis.h | 4 +- include/llvm/Analysis/FindUsedTypes.h | 66 - .../llvm/Analysis/FunctionTargetTransformInfo.h | 49 - include/llvm/Analysis/InlineCost.h | 10 +- include/llvm/Analysis/InstructionSimplify.h | 99 +- include/llvm/Analysis/JumpInstrTableInfo.h | 1 - include/llvm/Analysis/LazyCallGraph.h | 14 +- include/llvm/Analysis/LazyValueInfo.h | 29 +- include/llvm/Analysis/LibCallSemantics.h | 23 + include/llvm/Analysis/LoopAccessAnalysis.h | 290 ++++ include/llvm/Analysis/LoopInfo.h | 202 +-- include/llvm/Analysis/LoopInfoImpl.h | 19 + include/llvm/Analysis/MemoryDependenceAnalysis.h | 24 +- include/llvm/Analysis/PHITransAddr.h | 10 +- include/llvm/Analysis/Passes.h | 8 + include/llvm/Analysis/RegionInfo.h | 12 +- include/llvm/Analysis/RegionInfoImpl.h | 2 +- include/llvm/Analysis/ScalarEvolution.h | 30 +- include/llvm/Analysis/ScalarEvolutionExpressions.h | 2 +- include/llvm/Analysis/SparsePropagation.h | 4 +- include/llvm/Analysis/TargetLibraryInfo.h | 935 +++++++++++ include/llvm/Analysis/TargetTransformInfo.h | 637 ++++++-- include/llvm/Analysis/TargetTransformInfoImpl.h | 433 +++++ include/llvm/Analysis/ValueTracking.h | 36 +- include/llvm/Bitcode/BitCodes.h | 2 +- include/llvm/Bitcode/BitcodeWriterPass.h | 2 +- include/llvm/Bitcode/BitstreamReader.h | 24 +- include/llvm/Bitcode/LLVMBitCodes.h | 41 +- include/llvm/Bitcode/ReaderWriter.h | 70 +- include/llvm/CodeGen/Analysis.h | 17 +- include/llvm/CodeGen/AsmPrinter.h | 54 +- include/llvm/CodeGen/BasicTTIImpl.h | 723 +++++++++ include/llvm/CodeGen/CallingConvLower.h | 63 +- include/llvm/CodeGen/CommandFlags.h | 5 + include/llvm/CodeGen/DIE.h | 587 +++++++ include/llvm/CodeGen/FastISel.h | 11 +- include/llvm/CodeGen/ForwardControlFlowIntegrity.h | 1 - include/llvm/CodeGen/FunctionLoweringInfo.h | 16 +- include/llvm/CodeGen/GCMetadata.h | 295 ++-- include/llvm/CodeGen/GCMetadataPrinter.h | 76 +- include/llvm/CodeGen/GCStrategy.h | 254 +-- include/llvm/CodeGen/GCs.h | 32 +- include/llvm/CodeGen/ISDOpcodes.h | 23 +- include/llvm/CodeGen/LexicalScopes.h | 18 +- include/llvm/CodeGen/LinkAllCodegenComponents.h | 1 + include/llvm/CodeGen/LiveInterval.h | 226 ++- include/llvm/CodeGen/LiveIntervalAnalysis.h | 57 +- include/llvm/CodeGen/LiveIntervalUnion.h | 14 +- include/llvm/CodeGen/LivePhysRegs.h | 4 +- include/llvm/CodeGen/MachineDominanceFrontier.h | 4 +- include/llvm/CodeGen/MachineFrameInfo.h | 4 + include/llvm/CodeGen/MachineFunction.h | 22 +- include/llvm/CodeGen/MachineInstr.h | 25 +- include/llvm/CodeGen/MachineLoopInfo.h | 4 +- include/llvm/CodeGen/MachineModuleInfo.h | 37 +- include/llvm/CodeGen/MachinePassRegistry.h | 7 +- include/llvm/CodeGen/MachineRegisterInfo.h | 19 +- include/llvm/CodeGen/MachineSSAUpdater.h | 4 +- include/llvm/CodeGen/MachineScheduler.h | 1 - include/llvm/CodeGen/MachineValueType.h | 64 +- include/llvm/CodeGen/PBQP/Graph.h | 73 +- include/llvm/CodeGen/PBQP/ReductionRules.h | 32 +- include/llvm/CodeGen/Passes.h | 86 +- include/llvm/CodeGen/RegAllocPBQP.h | 132 +- include/llvm/CodeGen/ScheduleDAG.h | 6 + include/llvm/CodeGen/SelectionDAG.h | 14 +- include/llvm/CodeGen/SelectionDAGISel.h | 2 +- include/llvm/CodeGen/SelectionDAGNodes.h | 127 +- include/llvm/CodeGen/SlotIndexes.h | 2 +- include/llvm/CodeGen/StackMaps.h | 50 +- .../llvm/CodeGen/TargetLoweringObjectFileImpl.h | 11 +- include/llvm/CodeGen/ValueTypes.td | 3 + include/llvm/CodeGen/VirtRegMap.h | 4 +- include/llvm/Config/config.h.cmake | 24 +- include/llvm/Config/config.h.in | 15 + include/llvm/Config/llvm-config.h.cmake | 7 +- include/llvm/Config/llvm-config.h.in | 3 + include/llvm/DebugInfo/DIContext.h | 151 -- include/llvm/DebugInfo/DWARF/DIContext.h | 150 ++ .../DebugInfo/DWARF/DWARFAbbreviationDeclaration.h | 60 + .../llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h | 49 + include/llvm/DebugInfo/DWARF/DWARFCompileUnit.h | 31 + include/llvm/DebugInfo/DWARF/DWARFContext.h | 292 ++++ include/llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h | 63 + include/llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h | 70 + include/llvm/DebugInfo/DWARF/DWARFDebugAranges.h | 87 + include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h | 43 + include/llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h | 160 ++ include/llvm/DebugInfo/DWARF/DWARFDebugLine.h | 238 +++ include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h | 81 + include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h | 77 + include/llvm/DebugInfo/DWARF/DWARFFormValue.h | 93 ++ include/llvm/DebugInfo/DWARF/DWARFRelocMap.h | 22 + include/llvm/DebugInfo/DWARF/DWARFSection.h | 24 + include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h | 38 + include/llvm/DebugInfo/DWARF/DWARFUnit.h | 285 ++++ include/llvm/DebugInfo/DWARFFormValue.h | 93 -- .../llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h | 59 + include/llvm/DebugInfo/PDB/DIA/DIADataStream.h | 33 + .../llvm/DebugInfo/PDB/DIA/DIAEnumDebugStreams.h | 35 + .../llvm/DebugInfo/PDB/DIA/DIAEnumLineNumbers.h | 35 + .../llvm/DebugInfo/PDB/DIA/DIAEnumSourceFiles.h | 37 + include/llvm/DebugInfo/PDB/DIA/DIAEnumSymbols.h | 37 + include/llvm/DebugInfo/PDB/DIA/DIALineNumber.h | 39 + include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h | 206 +++ include/llvm/DebugInfo/PDB/DIA/DIASession.h | 42 + include/llvm/DebugInfo/PDB/DIA/DIASourceFile.h | 36 + include/llvm/DebugInfo/PDB/DIA/DIASupport.h | 33 + include/llvm/DebugInfo/PDB/IPDBDataStream.h | 37 + include/llvm/DebugInfo/PDB/IPDBEnumChildren.h | 33 + include/llvm/DebugInfo/PDB/IPDBLineNumber.h | 36 + include/llvm/DebugInfo/PDB/IPDBRawSymbol.h | 211 +++ include/llvm/DebugInfo/PDB/IPDBSession.h | 56 + include/llvm/DebugInfo/PDB/IPDBSourceFile.h | 37 + include/llvm/DebugInfo/PDB/PDB.h | 23 + include/llvm/DebugInfo/PDB/PDBExtras.h | 37 + include/llvm/DebugInfo/PDB/PDBSymDumper.h | 85 + include/llvm/DebugInfo/PDB/PDBSymbol.h | 98 ++ include/llvm/DebugInfo/PDB/PDBSymbolAnnotation.h | 39 + include/llvm/DebugInfo/PDB/PDBSymbolBlock.h | 41 + include/llvm/DebugInfo/PDB/PDBSymbolCompiland.h | 38 + .../llvm/DebugInfo/PDB/PDBSymbolCompilandDetails.h | 55 + include/llvm/DebugInfo/PDB/PDBSymbolCompilandEnv.h | 37 + include/llvm/DebugInfo/PDB/PDBSymbolCustom.h | 39 + include/llvm/DebugInfo/PDB/PDBSymbolData.h | 61 + include/llvm/DebugInfo/PDB/PDBSymbolExe.h | 46 + include/llvm/DebugInfo/PDB/PDBSymbolFunc.h | 80 + include/llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h | 49 + .../llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h | 49 + include/llvm/DebugInfo/PDB/PDBSymbolLabel.h | 49 + include/llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h | 47 + include/llvm/DebugInfo/PDB/PDBSymbolThunk.h | 57 + include/llvm/DebugInfo/PDB/PDBSymbolTypeArray.h | 45 + .../llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h | 60 + include/llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h | 40 + include/llvm/DebugInfo/PDB/PDBSymbolTypeCustom.h | 36 + .../llvm/DebugInfo/PDB/PDBSymbolTypeDimension.h | 36 + include/llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h | 52 + include/llvm/DebugInfo/PDB/PDBSymbolTypeFriend.h | 37 + .../llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h | 37 + .../llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h | 50 + include/llvm/DebugInfo/PDB/PDBSymbolTypeManaged.h | 35 + include/llvm/DebugInfo/PDB/PDBSymbolTypePointer.h | 43 + include/llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h | 54 + include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h | 52 + include/llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h | 40 + .../llvm/DebugInfo/PDB/PDBSymbolTypeVTableShape.h | 39 + include/llvm/DebugInfo/PDB/PDBSymbolUnknown.h | 34 + .../llvm/DebugInfo/PDB/PDBSymbolUsingNamespace.h | 36 + include/llvm/DebugInfo/PDB/PDBTypes.h | 479 ++++++ include/llvm/ExecutionEngine/ExecutionEngine.h | 39 +- include/llvm/ExecutionEngine/JITEventListener.h | 19 +- include/llvm/ExecutionEngine/ObjectBuffer.h | 76 - include/llvm/ExecutionEngine/ObjectImage.h | 76 - include/llvm/ExecutionEngine/ObjectMemoryBuffer.h | 63 + include/llvm/ExecutionEngine/Orc/CloneSubModule.h | 60 + .../ExecutionEngine/Orc/CompileOnDemandLayer.h | 355 +++++ include/llvm/ExecutionEngine/Orc/CompileUtils.h | 62 + include/llvm/ExecutionEngine/Orc/IRCompileLayer.h | 146 ++ .../llvm/ExecutionEngine/Orc/IndirectionUtils.h | 246 +++ include/llvm/ExecutionEngine/Orc/JITSymbol.h | 74 + .../llvm/ExecutionEngine/Orc/LazyEmittingLayer.h | 283 ++++ .../llvm/ExecutionEngine/Orc/LookasideRTDyldMM.h | 92 ++ .../llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h | 267 ++++ .../llvm/ExecutionEngine/Orc/OrcTargetSupport.h | 56 + include/llvm/ExecutionEngine/OrcMCJITReplacement.h | 38 + include/llvm/ExecutionEngine/RTDyldMemoryManager.h | 32 +- include/llvm/ExecutionEngine/RuntimeDyld.h | 55 +- include/llvm/ExecutionEngine/RuntimeDyldChecker.h | 1 + .../llvm/ExecutionEngine/SectionMemoryManager.h | 4 +- include/llvm/IR/Attributes.h | 5 + include/llvm/IR/BasicBlock.h | 12 +- include/llvm/IR/CFG.h | 26 +- include/llvm/IR/CallSite.h | 2 +- include/llvm/IR/Comdat.h | 2 +- include/llvm/IR/Constant.h | 4 +- include/llvm/IR/ConstantRange.h | 95 +- include/llvm/IR/Constants.h | 64 +- include/llvm/IR/DIBuilder.h | 118 +- include/llvm/IR/DataLayout.h | 7 + include/llvm/IR/DebugInfo.h | 293 ++-- include/llvm/IR/DebugInfoFlags.def | 36 + include/llvm/IR/DebugInfoMetadata.h | 1669 ++++++++++++++++++++ include/llvm/IR/DebugLoc.h | 98 +- include/llvm/IR/DerivedTypes.h | 30 +- include/llvm/IR/DiagnosticInfo.h | 3 + include/llvm/IR/Dominators.h | 49 + include/llvm/IR/Function.h | 42 +- include/llvm/IR/GVMaterializer.h | 4 + include/llvm/IR/GlobalAlias.h | 4 +- include/llvm/IR/GlobalObject.h | 2 +- include/llvm/IR/GlobalValue.h | 3 +- include/llvm/IR/GlobalVariable.h | 6 +- include/llvm/IR/IRBuilder.h | 71 +- include/llvm/IR/IRPrintingPasses.h | 4 +- include/llvm/IR/InlineAsm.h | 4 +- include/llvm/IR/InstIterator.h | 12 + include/llvm/IR/InstrTypes.h | 32 +- include/llvm/IR/Instruction.h | 6 +- include/llvm/IR/Instructions.h | 37 +- include/llvm/IR/IntrinsicInst.h | 54 +- include/llvm/IR/Intrinsics.h | 30 +- include/llvm/IR/Intrinsics.td | 69 + include/llvm/IR/IntrinsicsBPF.td | 22 + include/llvm/IR/IntrinsicsHexagon.td | 319 ++-- include/llvm/IR/IntrinsicsPowerPC.td | 177 +++ include/llvm/IR/IntrinsicsR600.td | 3 + include/llvm/IR/IntrinsicsX86.td | 581 ++++++- include/llvm/IR/LLVMContext.h | 4 +- include/llvm/IR/LeakDetector.h | 92 -- include/llvm/IR/LegacyPassManager.h | 12 +- include/llvm/IR/LegacyPassManagers.h | 9 + include/llvm/IR/LegacyPassNameParser.h | 10 +- include/llvm/IR/MDBuilder.h | 8 + include/llvm/IR/Metadata.def | 99 ++ include/llvm/IR/Metadata.h | 947 +++++++++-- include/llvm/IR/MetadataTracking.h | 99 ++ include/llvm/IR/Module.h | 55 +- include/llvm/IR/Operator.h | 22 +- include/llvm/IR/PassManager.h | 808 ++++------ include/llvm/IR/PassManagerInternal.h | 349 ++++ include/llvm/IR/PatternMatch.h | 751 +++++---- include/llvm/IR/Statepoint.h | 298 ++++ include/llvm/IR/TrackingMDRef.h | 170 ++ include/llvm/IR/Type.h | 3 + include/llvm/IR/TypeFinder.h | 1 + include/llvm/IR/Use.h | 2 +- include/llvm/IR/UseListOrder.h | 4 +- include/llvm/IR/User.h | 4 +- include/llvm/IR/Value.h | 64 +- include/llvm/IR/ValueHandle.h | 98 +- include/llvm/IR/ValueMap.h | 36 +- include/llvm/IR/Verifier.h | 4 +- include/llvm/InitializePasses.h | 32 +- include/llvm/LTO/LTOCodeGenerator.h | 22 +- include/llvm/LinkAllPasses.h | 9 +- include/llvm/Linker/Linker.h | 82 +- include/llvm/MC/MCAsmBackend.h | 18 +- include/llvm/MC/MCAsmInfo.h | 41 +- include/llvm/MC/MCAsmInfoDarwin.h | 2 +- include/llvm/MC/MCAssembler.h | 18 +- include/llvm/MC/MCCodeEmitter.h | 4 +- include/llvm/MC/MCContext.h | 16 +- include/llvm/MC/MCDwarf.h | 6 +- include/llvm/MC/MCELFObjectWriter.h | 1 + include/llvm/MC/MCExpr.h | 5 +- include/llvm/MC/MCInst.h | 22 +- include/llvm/MC/MCInstPrinter.h | 10 +- include/llvm/MC/MCInstrDesc.h | 11 +- include/llvm/MC/MCLabel.h | 4 +- include/llvm/MC/MCLinkerOptimizationHint.h | 2 +- include/llvm/MC/MCMachObjectWriter.h | 28 +- include/llvm/MC/MCObjectWriter.h | 10 +- include/llvm/MC/MCParser/AsmLexer.h | 4 +- include/llvm/MC/MCParser/MCAsmLexer.h | 4 +- include/llvm/MC/MCParser/MCAsmParser.h | 4 +- include/llvm/MC/MCParser/MCAsmParserExtension.h | 4 +- include/llvm/MC/MCRegisterInfo.h | 72 + include/llvm/MC/MCRelocationInfo.h | 4 +- include/llvm/MC/MCSection.h | 4 +- include/llvm/MC/MCSectionELF.h | 14 +- include/llvm/MC/MCStreamer.h | 14 +- include/llvm/MC/MCSubtargetInfo.h | 15 + include/llvm/MC/MCSymbol.h | 22 +- include/llvm/MC/MCSymbolizer.h | 4 +- include/llvm/MC/MCTargetAsmParser.h | 5 +- include/llvm/MC/MCTargetOptions.h | 12 +- include/llvm/MC/MCTargetOptionsCommandFlags.h | 8 +- include/llvm/MC/MCValue.h | 2 +- include/llvm/MC/MCWinCOFFObjectWriter.h | 15 +- include/llvm/MC/SectionKind.h | 6 +- include/llvm/Object/Archive.h | 22 +- include/llvm/Object/Binary.h | 4 +- include/llvm/Object/COFF.h | 14 +- include/llvm/Object/ELFObjectFile.h | 66 +- include/llvm/Object/ELFTypes.h | 52 +- include/llvm/Object/ELFYAML.h | 33 +- include/llvm/Object/IRObjectFile.h | 10 +- include/llvm/Object/MachO.h | 30 +- include/llvm/Object/MachOUniversal.h | 8 +- include/llvm/Object/ObjectFile.h | 27 +- include/llvm/Object/SymbolicFile.h | 5 +- include/llvm/Option/Arg.h | 4 +- include/llvm/Option/ArgList.h | 4 +- include/llvm/Option/OptSpecifier.h | 2 +- include/llvm/Pass.h | 4 +- include/llvm/PassAnalysisSupport.h | 2 +- include/llvm/PassInfo.h | 4 +- include/llvm/PassManager.h | 39 - include/llvm/ProfileData/CoverageMapping.h | 85 +- include/llvm/ProfileData/CoverageMappingReader.h | 81 +- include/llvm/ProfileData/CoverageMappingWriter.h | 2 +- include/llvm/ProfileData/InstrProfReader.h | 28 +- include/llvm/ProfileData/InstrProfWriter.h | 9 +- include/llvm/ProfileData/SampleProf.h | 1 - include/llvm/ProfileData/SampleProfReader.h | 6 +- include/llvm/Support/ARMBuildAttributes.h | 5 + include/llvm/Support/COFF.h | 12 +- include/llvm/Support/Casting.h | 34 + include/llvm/Support/CommandLine.h | 854 ++++------ include/llvm/Support/Compiler.h | 91 +- include/llvm/Support/Compression.h | 2 +- include/llvm/Support/ConvertUTF.h | 8 + include/llvm/Support/CrashRecoveryContext.h | 3 +- include/llvm/Support/Dwarf.def | 351 ++++ include/llvm/Support/Dwarf.h | 333 +--- include/llvm/Support/ELF.h | 806 +--------- include/llvm/Support/ELFRelocs/AArch64.def | 147 ++ include/llvm/Support/ELFRelocs/ARM.def | 138 ++ include/llvm/Support/ELFRelocs/Hexagon.def | 92 ++ include/llvm/Support/ELFRelocs/Mips.def | 112 ++ include/llvm/Support/ELFRelocs/PowerPC.def | 61 + include/llvm/Support/ELFRelocs/PowerPC64.def | 88 ++ include/llvm/Support/ELFRelocs/Sparc.def | 89 ++ include/llvm/Support/ELFRelocs/SystemZ.def | 67 + include/llvm/Support/ELFRelocs/i386.def | 47 + include/llvm/Support/ELFRelocs/x86_64.def | 44 + include/llvm/Support/EndianStream.h | 25 + include/llvm/Support/ErrorOr.h | 2 +- include/llvm/Support/FileOutputBuffer.h | 6 +- include/llvm/Support/FileSystem.h | 48 +- include/llvm/Support/Format.h | 190 +-- include/llvm/Support/GCOV.h | 147 +- include/llvm/Support/GenericDomTree.h | 322 ++-- include/llvm/Support/GenericDomTreeConstruction.h | 20 +- include/llvm/Support/LockFileManager.h | 8 +- include/llvm/Support/MachO.h | 351 +++- include/llvm/Support/MathExtras.h | 332 ++-- include/llvm/Support/MemoryBuffer.h | 4 +- include/llvm/Support/Mutex.h | 4 +- include/llvm/Support/MutexGuard.h | 4 +- include/llvm/Support/OnDiskHashTable.h | 2 +- include/llvm/Support/PrettyStackTrace.h | 4 +- include/llvm/Support/Process.h | 102 +- include/llvm/Support/RWMutex.h | 4 +- include/llvm/Support/RandomNumberGenerator.h | 41 +- include/llvm/Support/Regex.h | 2 +- include/llvm/Support/Registry.h | 9 +- include/llvm/Support/ScaledNumber.h | 1 - include/llvm/Support/Signals.h | 3 + include/llvm/Support/SourceMgr.h | 4 +- include/llvm/Support/SpecialCaseList.h | 30 +- include/llvm/Support/StreamingMemoryObject.h | 13 +- include/llvm/Support/StringPool.h | 4 +- include/llvm/Support/SwapByteOrder.h | 20 + include/llvm/Support/TargetRegistry.h | 71 +- include/llvm/Support/ThreadLocal.h | 2 +- include/llvm/Support/Threading.h | 3 +- include/llvm/Support/Timer.h | 6 +- include/llvm/Support/UniqueLock.h | 4 +- include/llvm/Support/Watchdog.h | 4 +- include/llvm/Support/YAMLTraits.h | 17 +- include/llvm/Support/raw_ostream.h | 4 +- include/llvm/Support/type_traits.h | 10 +- include/llvm/TableGen/Record.h | 80 +- include/llvm/Target/Target.td | 55 +- include/llvm/Target/TargetCallingConv.h | 11 + include/llvm/Target/TargetFrameLowering.h | 19 + include/llvm/Target/TargetInstrInfo.h | 17 +- include/llvm/Target/TargetIntrinsicInfo.h | 4 +- include/llvm/Target/TargetLibraryInfo.h | 813 ---------- include/llvm/Target/TargetLowering.h | 312 ++-- include/llvm/Target/TargetLoweringObjectFile.h | 33 +- include/llvm/Target/TargetMachine.h | 64 +- include/llvm/Target/TargetOpcodes.h | 13 +- include/llvm/Target/TargetOptions.h | 12 +- include/llvm/Target/TargetRegisterInfo.h | 32 +- include/llvm/Target/TargetSelectionDAG.td | 27 + include/llvm/Target/TargetSelectionDAGInfo.h | 5 +- include/llvm/Target/TargetSubtargetInfo.h | 10 +- include/llvm/Transforms/IPO.h | 4 + include/llvm/Transforms/IPO/LowerBitSets.h | 153 ++ include/llvm/Transforms/IPO/PassManagerBuilder.h | 21 +- include/llvm/Transforms/InstCombine/InstCombine.h | 46 + .../Transforms/InstCombine/InstCombineWorklist.h | 116 ++ include/llvm/Transforms/Instrumentation.h | 56 +- include/llvm/Transforms/Scalar.h | 37 +- include/llvm/Transforms/Scalar/EarlyCSE.h | 39 + .../llvm/Transforms/Scalar/LowerExpectIntrinsic.h | 40 + include/llvm/Transforms/Scalar/SimplifyCFG.h | 46 + include/llvm/Transforms/Utils/BasicBlockUtils.h | 158 +- include/llvm/Transforms/Utils/BuildLibCalls.h | 14 - include/llvm/Transforms/Utils/Cloning.h | 67 +- include/llvm/Transforms/Utils/Local.h | 23 +- include/llvm/Transforms/Utils/LoopUtils.h | 69 +- include/llvm/Transforms/Utils/PromoteMemToReg.h | 4 +- include/llvm/Transforms/Utils/SSAUpdater.h | 4 +- include/llvm/Transforms/Utils/SimplifyLibCalls.h | 70 +- include/llvm/Transforms/Utils/SymbolRewriter.h | 4 +- include/llvm/Transforms/Utils/UnrollLoop.h | 9 +- include/llvm/Transforms/Utils/ValueMapper.h | 21 +- include/llvm/Transforms/Utils/VectorUtils.h | 6 +- include/llvm/module.modulemap | 76 +- 442 files changed, 23721 insertions(+), 8631 deletions(-) create mode 100644 include/llvm/Analysis/AssumptionCache.h delete mode 100644 include/llvm/Analysis/AssumptionTracker.h delete mode 100644 include/llvm/Analysis/FindUsedTypes.h delete mode 100644 include/llvm/Analysis/FunctionTargetTransformInfo.h create mode 100644 include/llvm/Analysis/LoopAccessAnalysis.h create mode 100644 include/llvm/Analysis/TargetLibraryInfo.h create mode 100644 include/llvm/Analysis/TargetTransformInfoImpl.h create mode 100644 include/llvm/CodeGen/BasicTTIImpl.h create mode 100644 include/llvm/CodeGen/DIE.h delete mode 100644 include/llvm/DebugInfo/DIContext.h create mode 100644 include/llvm/DebugInfo/DWARF/DIContext.h create mode 100644 include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h create mode 100644 include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h create mode 100644 include/llvm/DebugInfo/DWARF/DWARFCompileUnit.h create mode 100644 include/llvm/DebugInfo/DWARF/DWARFContext.h create mode 100644 include/llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h create mode 100644 include/llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h create mode 100644 include/llvm/DebugInfo/DWARF/DWARFDebugAranges.h create mode 100644 include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h create mode 100644 include/llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h create mode 100644 include/llvm/DebugInfo/DWARF/DWARFDebugLine.h create mode 100644 include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h create mode 100644 include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h create mode 100644 include/llvm/DebugInfo/DWARF/DWARFFormValue.h create mode 100644 include/llvm/DebugInfo/DWARF/DWARFRelocMap.h create mode 100644 include/llvm/DebugInfo/DWARF/DWARFSection.h create mode 100644 include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h create mode 100644 include/llvm/DebugInfo/DWARF/DWARFUnit.h delete mode 100644 include/llvm/DebugInfo/DWARFFormValue.h create mode 100644 include/llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h create mode 100644 include/llvm/DebugInfo/PDB/DIA/DIADataStream.h create mode 100644 include/llvm/DebugInfo/PDB/DIA/DIAEnumDebugStreams.h create mode 100644 include/llvm/DebugInfo/PDB/DIA/DIAEnumLineNumbers.h create mode 100644 include/llvm/DebugInfo/PDB/DIA/DIAEnumSourceFiles.h create mode 100644 include/llvm/DebugInfo/PDB/DIA/DIAEnumSymbols.h create mode 100644 include/llvm/DebugInfo/PDB/DIA/DIALineNumber.h create mode 100644 include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h create mode 100644 include/llvm/DebugInfo/PDB/DIA/DIASession.h create mode 100644 include/llvm/DebugInfo/PDB/DIA/DIASourceFile.h create mode 100644 include/llvm/DebugInfo/PDB/DIA/DIASupport.h create mode 100644 include/llvm/DebugInfo/PDB/IPDBDataStream.h create mode 100644 include/llvm/DebugInfo/PDB/IPDBEnumChildren.h create mode 100644 include/llvm/DebugInfo/PDB/IPDBLineNumber.h create mode 100644 include/llvm/DebugInfo/PDB/IPDBRawSymbol.h create mode 100644 include/llvm/DebugInfo/PDB/IPDBSession.h create mode 100644 include/llvm/DebugInfo/PDB/IPDBSourceFile.h create mode 100644 include/llvm/DebugInfo/PDB/PDB.h create mode 100644 include/llvm/DebugInfo/PDB/PDBExtras.h create mode 100644 include/llvm/DebugInfo/PDB/PDBSymDumper.h create mode 100644 include/llvm/DebugInfo/PDB/PDBSymbol.h create mode 100644 include/llvm/DebugInfo/PDB/PDBSymbolAnnotation.h create mode 100644 include/llvm/DebugInfo/PDB/PDBSymbolBlock.h create mode 100644 include/llvm/DebugInfo/PDB/PDBSymbolCompiland.h create mode 100644 include/llvm/DebugInfo/PDB/PDBSymbolCompilandDetails.h create mode 100644 include/llvm/DebugInfo/PDB/PDBSymbolCompilandEnv.h create mode 100644 include/llvm/DebugInfo/PDB/PDBSymbolCustom.h create mode 100644 include/llvm/DebugInfo/PDB/PDBSymbolData.h create mode 100644 include/llvm/DebugInfo/PDB/PDBSymbolExe.h create mode 100644 include/llvm/DebugInfo/PDB/PDBSymbolFunc.h create mode 100644 include/llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h create mode 100644 include/llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h create mode 100644 include/llvm/DebugInfo/PDB/PDBSymbolLabel.h create mode 100644 include/llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h create mode 100644 include/llvm/DebugInfo/PDB/PDBSymbolThunk.h create mode 100644 include/llvm/DebugInfo/PDB/PDBSymbolTypeArray.h create mode 100644 include/llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h create mode 100644 include/llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h create mode 100644 include/llvm/DebugInfo/PDB/PDBSymbolTypeCustom.h create mode 100644 include/llvm/DebugInfo/PDB/PDBSymbolTypeDimension.h create mode 100644 include/llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h create mode 100644 include/llvm/DebugInfo/PDB/PDBSymbolTypeFriend.h create mode 100644 include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h create mode 100644 include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h create mode 100644 include/llvm/DebugInfo/PDB/PDBSymbolTypeManaged.h create mode 100644 include/llvm/DebugInfo/PDB/PDBSymbolTypePointer.h create mode 100644 include/llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h create mode 100644 include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h create mode 100644 include/llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h create mode 100644 include/llvm/DebugInfo/PDB/PDBSymbolTypeVTableShape.h create mode 100644 include/llvm/DebugInfo/PDB/PDBSymbolUnknown.h create mode 100644 include/llvm/DebugInfo/PDB/PDBSymbolUsingNamespace.h create mode 100644 include/llvm/DebugInfo/PDB/PDBTypes.h delete mode 100644 include/llvm/ExecutionEngine/ObjectBuffer.h delete mode 100644 include/llvm/ExecutionEngine/ObjectImage.h create mode 100644 include/llvm/ExecutionEngine/ObjectMemoryBuffer.h create mode 100644 include/llvm/ExecutionEngine/Orc/CloneSubModule.h create mode 100644 include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h create mode 100644 include/llvm/ExecutionEngine/Orc/CompileUtils.h create mode 100644 include/llvm/ExecutionEngine/Orc/IRCompileLayer.h create mode 100644 include/llvm/ExecutionEngine/Orc/IndirectionUtils.h create mode 100644 include/llvm/ExecutionEngine/Orc/JITSymbol.h create mode 100644 include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h create mode 100644 include/llvm/ExecutionEngine/Orc/LookasideRTDyldMM.h create mode 100644 include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h create mode 100644 include/llvm/ExecutionEngine/Orc/OrcTargetSupport.h create mode 100644 include/llvm/ExecutionEngine/OrcMCJITReplacement.h create mode 100644 include/llvm/IR/DebugInfoFlags.def create mode 100644 include/llvm/IR/DebugInfoMetadata.h create mode 100644 include/llvm/IR/IntrinsicsBPF.td delete mode 100644 include/llvm/IR/LeakDetector.h create mode 100644 include/llvm/IR/Metadata.def create mode 100644 include/llvm/IR/MetadataTracking.h create mode 100644 include/llvm/IR/PassManagerInternal.h create mode 100644 include/llvm/IR/Statepoint.h create mode 100644 include/llvm/IR/TrackingMDRef.h delete mode 100644 include/llvm/PassManager.h create mode 100644 include/llvm/Support/Dwarf.def create mode 100644 include/llvm/Support/ELFRelocs/AArch64.def create mode 100644 include/llvm/Support/ELFRelocs/ARM.def create mode 100644 include/llvm/Support/ELFRelocs/Hexagon.def create mode 100644 include/llvm/Support/ELFRelocs/Mips.def create mode 100644 include/llvm/Support/ELFRelocs/PowerPC.def create mode 100644 include/llvm/Support/ELFRelocs/PowerPC64.def create mode 100644 include/llvm/Support/ELFRelocs/Sparc.def create mode 100644 include/llvm/Support/ELFRelocs/SystemZ.def create mode 100644 include/llvm/Support/ELFRelocs/i386.def create mode 100644 include/llvm/Support/ELFRelocs/x86_64.def delete mode 100644 include/llvm/Target/TargetLibraryInfo.h create mode 100644 include/llvm/Transforms/IPO/LowerBitSets.h create mode 100644 include/llvm/Transforms/InstCombine/InstCombine.h create mode 100644 include/llvm/Transforms/InstCombine/InstCombineWorklist.h create mode 100644 include/llvm/Transforms/Scalar/EarlyCSE.h create mode 100644 include/llvm/Transforms/Scalar/LowerExpectIntrinsic.h create mode 100644 include/llvm/Transforms/Scalar/SimplifyCFG.h (limited to 'include') diff --git a/include/llvm-c/Core.h b/include/llvm-c/Core.h index 30c7595..8873fdb 100644 --- a/include/llvm-c/Core.h +++ b/include/llvm-c/Core.h @@ -1157,8 +1157,6 @@ LLVMTypeRef LLVMX86MMXType(void); macro(Argument) \ macro(BasicBlock) \ macro(InlineAsm) \ - macro(MDNode) \ - macro(MDString) \ macro(User) \ macro(Constant) \ macro(BlockAddress) \ @@ -1307,6 +1305,9 @@ LLVMBool LLVMIsUndef(LLVMValueRef Val); LLVMValueRef LLVMIsA##name(LLVMValueRef Val); LLVM_FOR_EACH_VALUE_SUBCLASS(LLVM_DECLARE_VALUE_CAST) +LLVMValueRef LLVMIsAMDNode(LLVMValueRef Val); +LLVMValueRef LLVMIsAMDString(LLVMValueRef Val); + /** * @} */ diff --git a/include/llvm-c/ExecutionEngine.h b/include/llvm-c/ExecutionEngine.h index f1f4cad..eb3ecab 100644 --- a/include/llvm-c/ExecutionEngine.h +++ b/include/llvm-c/ExecutionEngine.h @@ -170,6 +170,10 @@ void LLVMAddGlobalMapping(LLVMExecutionEngineRef EE, LLVMValueRef Global, void *LLVMGetPointerToGlobal(LLVMExecutionEngineRef EE, LLVMValueRef Global); +uint64_t LLVMGetGlobalValueAddress(LLVMExecutionEngineRef EE, const char *Name); + +uint64_t LLVMGetFunctionAddress(LLVMExecutionEngineRef EE, const char *Name); + /*===-- Operations on memory managers -------------------------------------===*/ typedef uint8_t *(*LLVMMemoryManagerAllocateCodeSectionCallback)( diff --git a/include/llvm-c/Linker.h b/include/llvm-c/Linker.h index 9f337cf..cedde5e 100644 --- a/include/llvm-c/Linker.h +++ b/include/llvm-c/Linker.h @@ -20,20 +20,13 @@ extern "C" { #endif - -typedef enum { - LLVMLinkerDestroySource = 0, /* Allow source module to be destroyed. */ - LLVMLinkerPreserveSource = 1 /* Preserve the source module. */ -} LLVMLinkerMode; - - /* Links the source module into the destination module, taking ownership * of the source module away from the caller. Optionally returns a * human-readable description of any errors that occurred in linking. * OutMessage must be disposed with LLVMDisposeMessage. The return value * is true if an error occurred, false otherwise. */ LLVMBool LLVMLinkModules(LLVMModuleRef Dest, LLVMModuleRef Src, - LLVMLinkerMode Mode, char **OutMessage); + unsigned Unused, char **OutMessage); #ifdef __cplusplus } diff --git a/include/llvm-c/Transforms/Scalar.h b/include/llvm-c/Transforms/Scalar.h index 7ad1ad1..48c19a6 100644 --- a/include/llvm-c/Transforms/Scalar.h +++ b/include/llvm-c/Transforms/Scalar.h @@ -35,6 +35,9 @@ extern "C" { /** See llvm::createAggressiveDCEPass function. */ void LLVMAddAggressiveDCEPass(LLVMPassManagerRef PM); +/** See llvm::createBitTrackingDCEPass function. */ +void LLVMAddBitTrackingDCEPass(LLVMPassManagerRef PM); + /** See llvm::createAlignmentFromAssumptionsPass function. */ void LLVMAddAlignmentFromAssumptionsPass(LLVMPassManagerRef PM); diff --git a/include/llvm-c/lto.h b/include/llvm-c/lto.h index 3f30d6d..c6acdad 100644 --- a/include/llvm-c/lto.h +++ b/include/llvm-c/lto.h @@ -40,7 +40,7 @@ typedef bool lto_bool_t; * @{ */ -#define LTO_API_VERSION 11 +#define LTO_API_VERSION 13 /** * \since prior to LTO_API_VERSION=3 @@ -396,6 +396,17 @@ extern lto_bool_t lto_codegen_add_module(lto_code_gen_t cg, lto_module_t mod); /** + * Sets the object module for code generation. This will transfer the ownship of + * the module to code generator. + * + * \c cg and \c mod must both be in the same context. + * + * \since prior to LTO_API_VERSION=13 + */ +extern void +lto_codegen_set_module(lto_code_gen_t cg, lto_module_t mod); + +/** * Sets if debug info should be generated. * Returns true on error (check lto_get_error_message() for details). * @@ -464,6 +475,8 @@ lto_codegen_write_merged_modules(lto_code_gen_t cg, const char* path); /** * Generates code for all added modules into one native object file. + * This calls lto_codegen_optimize then lto_codegen_compile_optimized. + * * On success returns a pointer to a generated mach-o/ELF buffer and * length set to the buffer size. The buffer is owned by the * lto_code_gen_t and will be freed when lto_codegen_dispose() @@ -477,6 +490,9 @@ lto_codegen_compile(lto_code_gen_t cg, size_t* length); /** * Generates code for all added modules into one native object file. + * This calls lto_codegen_optimize then lto_codegen_compile_optimized (instead + * of returning a generated mach-o/ELF buffer, it writes to a file). + * * The name of the file is written to name. Returns true on error. * * \since LTO_API_VERSION=5 @@ -484,6 +500,36 @@ lto_codegen_compile(lto_code_gen_t cg, size_t* length); extern lto_bool_t lto_codegen_compile_to_file(lto_code_gen_t cg, const char** name); +/** + * Runs optimization for the merged module. Returns true on error. + * + * \since LTO_API_VERSION=12 + */ +extern lto_bool_t +lto_codegen_optimize(lto_code_gen_t cg); + +/** + * Generates code for the optimized merged module into one native object file. + * It will not run any IR optimizations on the merged module. + * + * On success returns a pointer to a generated mach-o/ELF buffer and length set + * to the buffer size. The buffer is owned by the lto_code_gen_t and will be + * freed when lto_codegen_dispose() is called, or + * lto_codegen_compile_optimized() is called again. On failure, returns NULL + * (check lto_get_error_message() for details). + * + * \since LTO_API_VERSION=12 + */ +extern const void* +lto_codegen_compile_optimized(lto_code_gen_t cg, size_t* length); + +/** + * Returns the runtime API version. + * + * \since LTO_API_VERSION=12 + */ +extern unsigned int +lto_api_version(void); /** * Sets options to help debug codegen bugs. diff --git a/include/llvm/ADT/APFloat.h b/include/llvm/ADT/APFloat.h index 26aae77..bf814e0 100644 --- a/include/llvm/ADT/APFloat.h +++ b/include/llvm/ADT/APFloat.h @@ -376,7 +376,7 @@ public: /// The definition of equality is not straightforward for floating point, so /// we won't use operator==. Use one of the following, or write whatever it /// is you really mean. - bool operator==(const APFloat &) const LLVM_DELETED_FUNCTION; + bool operator==(const APFloat &) const = delete; /// IEEE comparison with another floating point number (NaNs compare /// unordered, 0==-0). diff --git a/include/llvm/ADT/APInt.h b/include/llvm/ADT/APInt.h index f4e7e3c..c2fe094 100644 --- a/include/llvm/ADT/APInt.h +++ b/include/llvm/ADT/APInt.h @@ -91,6 +91,8 @@ class APInt { APINT_WORD_SIZE = static_cast(sizeof(uint64_t)) }; + friend struct DenseMapAPIntKeyInfo; + /// \brief Fast internal constructor /// /// This constructor is used only internally for speed of construction of @@ -277,7 +279,6 @@ public: /// Simply makes *this a copy of that. /// @brief Copy Constructor. APInt(const APInt &that) : BitWidth(that.BitWidth), VAL(0) { - assert(BitWidth && "bitwidth too small"); if (isSingleWord()) VAL = that.VAL; else @@ -1355,7 +1356,7 @@ public: /// \brief Count the number of leading one bits. /// - /// This function is an APInt version of the countLeadingOnes_{32,64} + /// This function is an APInt version of the countLeadingOnes /// functions in MathExtras.h. It counts the number of ones from the most /// significant bit to the first zero bit. /// @@ -1371,7 +1372,7 @@ public: /// \brief Count the number of trailing zero bits. /// - /// This function is an APInt version of the countTrailingZeros_{32,64} + /// This function is an APInt version of the countTrailingZeros /// functions in MathExtras.h. It counts the number of zeros from the least /// significant bit to the first set bit. /// @@ -1381,7 +1382,7 @@ public: /// \brief Count the number of trailing one bits. /// - /// This function is an APInt version of the countTrailingOnes_{32,64} + /// This function is an APInt version of the countTrailingOnes /// functions in MathExtras.h. It counts the number of ones from the least /// significant bit to the first zero bit. /// @@ -1389,19 +1390,19 @@ public: /// of ones from the least significant bit to the first zero bit. unsigned countTrailingOnes() const { if (isSingleWord()) - return CountTrailingOnes_64(VAL); + return llvm::countTrailingOnes(VAL); return countTrailingOnesSlowCase(); } /// \brief Count the number of bits set. /// - /// This function is an APInt version of the countPopulation_{32,64} functions + /// This function is an APInt version of the countPopulation functions /// in MathExtras.h. It counts the number of 1 bits in the APInt value. /// /// \returns 0 if the value is zero, otherwise returns the number of set bits. unsigned countPopulation() const { if (isSingleWord()) - return CountPopulation_64(VAL); + return llvm::countPopulation(VAL); return countPopulationSlowCase(); } diff --git a/include/llvm/ADT/APSInt.h b/include/llvm/ADT/APSInt.h index a6693f7..91ccda2 100644 --- a/include/llvm/ADT/APSInt.h +++ b/include/llvm/ADT/APSInt.h @@ -62,6 +62,12 @@ public: } using APInt::toString; + /// \brief Get the correctly-extended \c int64_t value. + int64_t getExtValue() const { + assert(getMinSignedBits() <= 64 && "Too many bits for int64_t"); + return isSigned() ? getSExtValue() : getZExtValue(); + } + APSInt LLVM_ATTRIBUTE_UNUSED_RESULT trunc(uint32_t width) const { return APSInt(APInt::trunc(width), IsUnsigned); } @@ -133,14 +139,27 @@ public: assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); return eq(RHS); } - inline bool operator==(int64_t RHS) const { - return isSameValue(*this, APSInt(APInt(64, RHS), true)); - } inline bool operator!=(const APSInt& RHS) const { return !((*this) == RHS); } - inline bool operator!=(int64_t RHS) const { - return !((*this) == RHS); + + bool operator==(int64_t RHS) const { + return compareValues(*this, get(RHS)) == 0; + } + bool operator!=(int64_t RHS) const { + return compareValues(*this, get(RHS)) != 0; + } + bool operator<=(int64_t RHS) const { + return compareValues(*this, get(RHS)) <= 0; + } + bool operator>=(int64_t RHS) const { + return compareValues(*this, get(RHS)) >= 0; + } + bool operator<(int64_t RHS) const { + return compareValues(*this, get(RHS)) < 0; + } + bool operator>(int64_t RHS) const { + return compareValues(*this, get(RHS)) > 0; } // The remaining operators just wrap the logic of APInt, but retain the @@ -260,37 +279,49 @@ public: /// \brief Determine if two APSInts have the same value, zero- or /// sign-extending as needed. static bool isSameValue(const APSInt &I1, const APSInt &I2) { + return !compareValues(I1, I2); + } + + /// \brief Compare underlying values of two numbers. + static int compareValues(const APSInt &I1, const APSInt &I2) { if (I1.getBitWidth() == I2.getBitWidth() && I1.isSigned() == I2.isSigned()) - return I1 == I2; + return I1 == I2 ? 0 : I1 > I2 ? 1 : -1; // Check for a bit-width mismatch. if (I1.getBitWidth() > I2.getBitWidth()) - return isSameValue(I1, I2.extend(I1.getBitWidth())); + return compareValues(I1, I2.extend(I1.getBitWidth())); else if (I2.getBitWidth() > I1.getBitWidth()) - return isSameValue(I1.extend(I2.getBitWidth()), I2); - - assert(I1.isSigned() != I2.isSigned()); + return compareValues(I1.extend(I2.getBitWidth()), I2); // We have a signedness mismatch. Check for negative values and do an - // unsigned compare if signs match. - if ((I1.isSigned() && I1.isNegative()) || - (!I1.isSigned() && I2.isNegative())) - return false; + // unsigned compare if both are positive. + if (I1.isSigned()) { + assert(!I2.isSigned() && "Expected signed mismatch"); + if (I1.isNegative()) + return -1; + } else { + assert(I2.isSigned() && "Expected signed mismatch"); + if (I2.isNegative()) + return 1; + } - return I1.eq(I2); + return I1.eq(I2) ? 0 : I1.ugt(I2) ? 1 : -1; } + static APSInt get(int64_t X) { return APSInt(APInt(64, X), false); } + static APSInt getUnsigned(uint64_t X) { return APSInt(APInt(64, X), true); } + /// Profile - Used to insert APSInt objects, or objects that contain APSInt /// objects, into FoldingSets. void Profile(FoldingSetNodeID& ID) const; }; -inline bool operator==(int64_t V1, const APSInt& V2) { - return V2 == V1; -} -inline bool operator!=(int64_t V1, const APSInt& V2) { - return V2 != V1; -} +inline bool operator==(int64_t V1, const APSInt &V2) { return V2 == V1; } +inline bool operator!=(int64_t V1, const APSInt &V2) { return V2 != V1; } +inline bool operator<=(int64_t V1, const APSInt &V2) { return V2 >= V1; } +inline bool operator>=(int64_t V1, const APSInt &V2) { return V2 <= V1; } +inline bool operator<(int64_t V1, const APSInt &V2) { return V2 > V1; } +inline bool operator>(int64_t V1, const APSInt &V2) { return V2 < V1; } inline raw_ostream &operator<<(raw_ostream &OS, const APSInt &I) { I.print(OS, I.isSigned()); diff --git a/include/llvm/ADT/ArrayRef.h b/include/llvm/ADT/ArrayRef.h index 8c14a42..5b7ed9c 100644 --- a/include/llvm/ADT/ArrayRef.h +++ b/include/llvm/ADT/ArrayRef.h @@ -97,12 +97,10 @@ namespace llvm { /*implicit*/ LLVM_CONSTEXPR ArrayRef(const T (&Arr)[N]) : Data(Arr), Length(N) {} -#if LLVM_HAS_INITIALIZER_LISTS /// Construct an ArrayRef from a std::initializer_list. /*implicit*/ ArrayRef(const std::initializer_list &Vec) : Data(Vec.begin() == Vec.end() ? (T*)0 : Vec.begin()), Length(Vec.size()) {} -#endif /// Construct an ArrayRef from ArrayRef. This uses SFINAE to /// ensure that only ArrayRefs of pointers can be converted. diff --git a/include/llvm/ADT/BitVector.h b/include/llvm/ADT/BitVector.h index 34e2284..0dbe810 100644 --- a/include/llvm/ADT/BitVector.h +++ b/include/llvm/ADT/BitVector.h @@ -29,6 +29,9 @@ class BitVector { enum { BITWORD_SIZE = (unsigned)sizeof(BitWord) * CHAR_BIT }; + static_assert(BITWORD_SIZE == 64 || BITWORD_SIZE == 32, + "Unsupported word size"); + BitWord *Bits; // Actual bits. unsigned Size; // Size of bitvector in bits. unsigned Capacity; // Size of allocated memory in BitWord. @@ -118,12 +121,7 @@ public: size_type count() const { unsigned NumBits = 0; for (unsigned i = 0; i < NumBitWords(size()); ++i) - if (sizeof(BitWord) == 4) - NumBits += CountPopulation_32((uint32_t)Bits[i]); - else if (sizeof(BitWord) == 8) - NumBits += CountPopulation_64(Bits[i]); - else - llvm_unreachable("Unsupported!"); + NumBits += countPopulation(Bits[i]); return NumBits; } @@ -157,13 +155,8 @@ public: /// of the bits are set. int find_first() const { for (unsigned i = 0; i < NumBitWords(size()); ++i) - if (Bits[i] != 0) { - if (sizeof(BitWord) == 4) - return i * BITWORD_SIZE + countTrailingZeros((uint32_t)Bits[i]); - if (sizeof(BitWord) == 8) - return i * BITWORD_SIZE + countTrailingZeros(Bits[i]); - llvm_unreachable("Unsupported!"); - } + if (Bits[i] != 0) + return i * BITWORD_SIZE + countTrailingZeros(Bits[i]); return -1; } @@ -180,23 +173,13 @@ public: // Mask off previous bits. Copy &= ~0UL << BitPos; - if (Copy != 0) { - if (sizeof(BitWord) == 4) - return WordPos * BITWORD_SIZE + countTrailingZeros((uint32_t)Copy); - if (sizeof(BitWord) == 8) - return WordPos * BITWORD_SIZE + countTrailingZeros(Copy); - llvm_unreachable("Unsupported!"); - } + if (Copy != 0) + return WordPos * BITWORD_SIZE + countTrailingZeros(Copy); // Check subsequent words. for (unsigned i = WordPos+1; i < NumBitWords(size()); ++i) - if (Bits[i] != 0) { - if (sizeof(BitWord) == 4) - return i * BITWORD_SIZE + countTrailingZeros((uint32_t)Bits[i]); - if (sizeof(BitWord) == 8) - return i * BITWORD_SIZE + countTrailingZeros(Bits[i]); - llvm_unreachable("Unsupported!"); - } + if (Bits[i] != 0) + return i * BITWORD_SIZE + countTrailingZeros(Bits[i]); return -1; } @@ -239,6 +222,7 @@ public: } BitVector &set(unsigned Idx) { + assert(Bits && "Bits never allocated"); Bits[Idx / BITWORD_SIZE] |= BitWord(1) << (Idx % BITWORD_SIZE); return *this; } @@ -450,6 +434,7 @@ public: // Grow the bitvector to have enough elements. Capacity = RHSWords; + assert(Capacity > 0 && "negative capacity?"); BitWord *NewBits = (BitWord *)std::malloc(Capacity * sizeof(BitWord)); std::memcpy(NewBits, RHS.Bits, Capacity * sizeof(BitWord)); @@ -545,6 +530,7 @@ private: void grow(unsigned NewSize) { Capacity = std::max(NumBitWords(NewSize), Capacity * 2); + assert(Capacity > 0 && "realloc-ing zero space"); Bits = (BitWord *)std::realloc(Bits, Capacity * sizeof(BitWord)); clear_unused_bits(); @@ -556,7 +542,7 @@ private: template void applyMask(const uint32_t *Mask, unsigned MaskWords) { - assert(BITWORD_SIZE % 32 == 0 && "Unsupported BitWord size."); + static_assert(BITWORD_SIZE % 32 == 0, "Unsupported BitWord size."); MaskWords = std::min(MaskWords, (size() + 31) / 32); const unsigned Scale = BITWORD_SIZE / 32; unsigned i; diff --git a/include/llvm/ADT/DenseMap.h b/include/llvm/ADT/DenseMap.h index c44b67a..1699ea3 100644 --- a/include/llvm/ADT/DenseMap.h +++ b/include/llvm/ADT/DenseMap.h @@ -31,26 +31,35 @@ namespace llvm { -template, - bool IsConst = false> +namespace detail { +// We extend a pair to allow users to override the bucket type with their own +// implementation without requiring two members. +template +struct DenseMapPair : public std::pair { + KeyT &getFirst() { return std::pair::first; } + const KeyT &getFirst() const { return std::pair::first; } + ValueT &getSecond() { return std::pair::second; } + const ValueT &getSecond() const { return std::pair::second; } +}; +} + +template < + typename KeyT, typename ValueT, typename KeyInfoT = DenseMapInfo, + typename Bucket = detail::DenseMapPair, bool IsConst = false> class DenseMapIterator; -template +template class DenseMapBase { -protected: - typedef std::pair BucketT; - public: typedef unsigned size_type; typedef KeyT key_type; typedef ValueT mapped_type; typedef BucketT value_type; - typedef DenseMapIterator iterator; - typedef DenseMapIterator const_iterator; + typedef DenseMapIterator iterator; + typedef DenseMapIterator + const_iterator; inline iterator begin() { // When the map is empty, avoid the overhead of AdvancePastEmptyBuckets(). return empty() ? end() : iterator(getBuckets(), getBucketsEnd()); @@ -88,12 +97,12 @@ public: const KeyT EmptyKey = getEmptyKey(), TombstoneKey = getTombstoneKey(); for (BucketT *P = getBuckets(), *E = getBucketsEnd(); P != E; ++P) { - if (!KeyInfoT::isEqual(P->first, EmptyKey)) { - if (!KeyInfoT::isEqual(P->first, TombstoneKey)) { - P->second.~ValueT(); + if (!KeyInfoT::isEqual(P->getFirst(), EmptyKey)) { + if (!KeyInfoT::isEqual(P->getFirst(), TombstoneKey)) { + P->getSecond().~ValueT(); decrementNumEntries(); } - P->first = EmptyKey; + P->getFirst() = EmptyKey; } } assert(getNumEntries() == 0 && "Node count imbalance!"); @@ -144,7 +153,7 @@ public: ValueT lookup(const KeyT &Val) const { const BucketT *TheBucket; if (LookupBucketFor(Val, TheBucket)) - return TheBucket->second; + return TheBucket->getSecond(); return ValueT(); } @@ -191,16 +200,16 @@ public: if (!LookupBucketFor(Val, TheBucket)) return false; // not in map. - TheBucket->second.~ValueT(); - TheBucket->first = getTombstoneKey(); + TheBucket->getSecond().~ValueT(); + TheBucket->getFirst() = getTombstoneKey(); decrementNumEntries(); incrementNumTombstones(); return true; } void erase(iterator I) { BucketT *TheBucket = &*I; - TheBucket->second.~ValueT(); - TheBucket->first = getTombstoneKey(); + TheBucket->getSecond().~ValueT(); + TheBucket->getFirst() = getTombstoneKey(); decrementNumEntries(); incrementNumTombstones(); } @@ -250,10 +259,10 @@ protected: const KeyT EmptyKey = getEmptyKey(), TombstoneKey = getTombstoneKey(); for (BucketT *P = getBuckets(), *E = getBucketsEnd(); P != E; ++P) { - if (!KeyInfoT::isEqual(P->first, EmptyKey) && - !KeyInfoT::isEqual(P->first, TombstoneKey)) - P->second.~ValueT(); - P->first.~KeyT(); + if (!KeyInfoT::isEqual(P->getFirst(), EmptyKey) && + !KeyInfoT::isEqual(P->getFirst(), TombstoneKey)) + P->getSecond().~ValueT(); + P->getFirst().~KeyT(); } #ifndef NDEBUG @@ -269,7 +278,7 @@ protected: "# initial buckets must be a power of two!"); const KeyT EmptyKey = getEmptyKey(); for (BucketT *B = getBuckets(), *E = getBucketsEnd(); B != E; ++B) - new (&B->first) KeyT(EmptyKey); + new (&B->getFirst()) KeyT(EmptyKey); } void moveFromOldBuckets(BucketT *OldBucketsBegin, BucketT *OldBucketsEnd) { @@ -279,21 +288,21 @@ protected: const KeyT EmptyKey = getEmptyKey(); const KeyT TombstoneKey = getTombstoneKey(); for (BucketT *B = OldBucketsBegin, *E = OldBucketsEnd; B != E; ++B) { - if (!KeyInfoT::isEqual(B->first, EmptyKey) && - !KeyInfoT::isEqual(B->first, TombstoneKey)) { + if (!KeyInfoT::isEqual(B->getFirst(), EmptyKey) && + !KeyInfoT::isEqual(B->getFirst(), TombstoneKey)) { // Insert the key/value into the new table. BucketT *DestBucket; - bool FoundVal = LookupBucketFor(B->first, DestBucket); + bool FoundVal = LookupBucketFor(B->getFirst(), DestBucket); (void)FoundVal; // silence warning. assert(!FoundVal && "Key already in new map?"); - DestBucket->first = std::move(B->first); - new (&DestBucket->second) ValueT(std::move(B->second)); + DestBucket->getFirst() = std::move(B->getFirst()); + new (&DestBucket->getSecond()) ValueT(std::move(B->getSecond())); incrementNumEntries(); // Free the value. - B->second.~ValueT(); + B->getSecond().~ValueT(); } - B->first.~KeyT(); + B->getFirst().~KeyT(); } #ifndef NDEBUG @@ -304,7 +313,8 @@ protected: } template - void copyFrom(const DenseMapBase& other) { + void copyFrom( + const DenseMapBase &other) { assert(&other != this); assert(getNumBuckets() == other.getNumBuckets()); @@ -316,10 +326,12 @@ protected: getNumBuckets() * sizeof(BucketT)); else for (size_t i = 0; i < getNumBuckets(); ++i) { - new (&getBuckets()[i].first) KeyT(other.getBuckets()[i].first); - if (!KeyInfoT::isEqual(getBuckets()[i].first, getEmptyKey()) && - !KeyInfoT::isEqual(getBuckets()[i].first, getTombstoneKey())) - new (&getBuckets()[i].second) ValueT(other.getBuckets()[i].second); + new (&getBuckets()[i].getFirst()) + KeyT(other.getBuckets()[i].getFirst()); + if (!KeyInfoT::isEqual(getBuckets()[i].getFirst(), getEmptyKey()) && + !KeyInfoT::isEqual(getBuckets()[i].getFirst(), getTombstoneKey())) + new (&getBuckets()[i].getSecond()) + ValueT(other.getBuckets()[i].getSecond()); } } @@ -396,8 +408,8 @@ private: BucketT *TheBucket) { TheBucket = InsertIntoBucketImpl(Key, TheBucket); - TheBucket->first = Key; - new (&TheBucket->second) ValueT(Value); + TheBucket->getFirst() = Key; + new (&TheBucket->getSecond()) ValueT(Value); return TheBucket; } @@ -405,16 +417,16 @@ private: BucketT *TheBucket) { TheBucket = InsertIntoBucketImpl(Key, TheBucket); - TheBucket->first = Key; - new (&TheBucket->second) ValueT(std::move(Value)); + TheBucket->getFirst() = Key; + new (&TheBucket->getSecond()) ValueT(std::move(Value)); return TheBucket; } BucketT *InsertIntoBucket(KeyT &&Key, ValueT &&Value, BucketT *TheBucket) { TheBucket = InsertIntoBucketImpl(Key, TheBucket); - TheBucket->first = std::move(Key); - new (&TheBucket->second) ValueT(std::move(Value)); + TheBucket->getFirst() = std::move(Key); + new (&TheBucket->getSecond()) ValueT(std::move(Value)); return TheBucket; } @@ -430,11 +442,12 @@ private: // causing infinite loops in lookup. unsigned NewNumEntries = getNumEntries() + 1; unsigned NumBuckets = getNumBuckets(); - if (NewNumEntries*4 >= NumBuckets*3) { + if (LLVM_UNLIKELY(NewNumEntries * 4 >= NumBuckets * 3)) { this->grow(NumBuckets * 2); LookupBucketFor(Key, TheBucket); NumBuckets = getNumBuckets(); - } else if (NumBuckets-(NewNumEntries+getNumTombstones()) <= NumBuckets/8) { + } else if (LLVM_UNLIKELY(NumBuckets-(NewNumEntries+getNumTombstones()) <= + NumBuckets/8)) { this->grow(NumBuckets); LookupBucketFor(Key, TheBucket); } @@ -446,7 +459,7 @@ private: // If we are writing over a tombstone, remember this. const KeyT EmptyKey = getEmptyKey(); - if (!KeyInfoT::isEqual(TheBucket->first, EmptyKey)) + if (!KeyInfoT::isEqual(TheBucket->getFirst(), EmptyKey)) decrementNumTombstones(); return TheBucket; @@ -480,14 +493,14 @@ private: while (1) { const BucketT *ThisBucket = BucketsPtr + BucketNo; // Found Val's bucket? If so, return it. - if (KeyInfoT::isEqual(Val, ThisBucket->first)) { + if (LLVM_LIKELY(KeyInfoT::isEqual(Val, ThisBucket->getFirst()))) { FoundBucket = ThisBucket; return true; } // If we found an empty bucket, the key doesn't exist in the set. // Insert it and return the default value. - if (KeyInfoT::isEqual(ThisBucket->first, EmptyKey)) { + if (LLVM_LIKELY(KeyInfoT::isEqual(ThisBucket->getFirst(), EmptyKey))) { // If we've already seen a tombstone while probing, fill it in instead // of the empty bucket we eventually probed to. FoundBucket = FoundTombstone ? FoundTombstone : ThisBucket; @@ -496,7 +509,8 @@ private: // If this is a tombstone, remember it. If Val ends up not in the map, we // prefer to return it than something that would require more probing. - if (KeyInfoT::isEqual(ThisBucket->first, TombstoneKey) && !FoundTombstone) + if (KeyInfoT::isEqual(ThisBucket->getFirst(), TombstoneKey) && + !FoundTombstone) FoundTombstone = ThisBucket; // Remember the first tombstone found. // Otherwise, it's a hash collision or a tombstone, continue quadratic @@ -525,16 +539,15 @@ public: } }; -template > -class DenseMap - : public DenseMapBase, - KeyT, ValueT, KeyInfoT> { +template , + typename BucketT = detail::DenseMapPair> +class DenseMap : public DenseMapBase, + KeyT, ValueT, KeyInfoT, BucketT> { // Lift some types from the dependent base class into this class for // simplicity of referring to them. - typedef DenseMapBase BaseT; - typedef typename BaseT::BucketT BucketT; - friend class DenseMapBase; + typedef DenseMapBase BaseT; + friend class DenseMapBase; BucketT *Buckets; unsigned NumEntries; @@ -677,17 +690,17 @@ private: } }; -template > +template , + typename BucketT = detail::DenseMapPair> class SmallDenseMap - : public DenseMapBase, - KeyT, ValueT, KeyInfoT> { + : public DenseMapBase< + SmallDenseMap, KeyT, + ValueT, KeyInfoT, BucketT> { // Lift some types from the dependent base class into this class for // simplicity of referring to them. - typedef DenseMapBase BaseT; - typedef typename BaseT::BucketT BucketT; - friend class DenseMapBase; + typedef DenseMapBase BaseT; + friend class DenseMapBase; unsigned Small : 1; unsigned NumEntries : 31; @@ -744,23 +757,23 @@ public: for (unsigned i = 0, e = InlineBuckets; i != e; ++i) { BucketT *LHSB = &getInlineBuckets()[i], *RHSB = &RHS.getInlineBuckets()[i]; - bool hasLHSValue = (!KeyInfoT::isEqual(LHSB->first, EmptyKey) && - !KeyInfoT::isEqual(LHSB->first, TombstoneKey)); - bool hasRHSValue = (!KeyInfoT::isEqual(RHSB->first, EmptyKey) && - !KeyInfoT::isEqual(RHSB->first, TombstoneKey)); + bool hasLHSValue = (!KeyInfoT::isEqual(LHSB->getFirst(), EmptyKey) && + !KeyInfoT::isEqual(LHSB->getFirst(), TombstoneKey)); + bool hasRHSValue = (!KeyInfoT::isEqual(RHSB->getFirst(), EmptyKey) && + !KeyInfoT::isEqual(RHSB->getFirst(), TombstoneKey)); if (hasLHSValue && hasRHSValue) { // Swap together if we can... std::swap(*LHSB, *RHSB); continue; } // Swap separately and handle any assymetry. - std::swap(LHSB->first, RHSB->first); + std::swap(LHSB->getFirst(), RHSB->getFirst()); if (hasLHSValue) { - new (&RHSB->second) ValueT(std::move(LHSB->second)); - LHSB->second.~ValueT(); + new (&RHSB->getSecond()) ValueT(std::move(LHSB->getSecond())); + LHSB->getSecond().~ValueT(); } else if (hasRHSValue) { - new (&LHSB->second) ValueT(std::move(RHSB->second)); - RHSB->second.~ValueT(); + new (&LHSB->getSecond()) ValueT(std::move(RHSB->getSecond())); + RHSB->getSecond().~ValueT(); } } return; @@ -785,12 +798,12 @@ public: for (unsigned i = 0, e = InlineBuckets; i != e; ++i) { BucketT *NewB = &LargeSide.getInlineBuckets()[i], *OldB = &SmallSide.getInlineBuckets()[i]; - new (&NewB->first) KeyT(std::move(OldB->first)); - OldB->first.~KeyT(); - if (!KeyInfoT::isEqual(NewB->first, EmptyKey) && - !KeyInfoT::isEqual(NewB->first, TombstoneKey)) { - new (&NewB->second) ValueT(std::move(OldB->second)); - OldB->second.~ValueT(); + new (&NewB->getFirst()) KeyT(std::move(OldB->getFirst())); + OldB->getFirst().~KeyT(); + if (!KeyInfoT::isEqual(NewB->getFirst(), EmptyKey) && + !KeyInfoT::isEqual(NewB->getFirst(), TombstoneKey)) { + new (&NewB->getSecond()) ValueT(std::move(OldB->getSecond())); + OldB->getSecond().~ValueT(); } } @@ -852,16 +865,16 @@ public: const KeyT EmptyKey = this->getEmptyKey(); const KeyT TombstoneKey = this->getTombstoneKey(); for (BucketT *P = getBuckets(), *E = P + InlineBuckets; P != E; ++P) { - if (!KeyInfoT::isEqual(P->first, EmptyKey) && - !KeyInfoT::isEqual(P->first, TombstoneKey)) { + if (!KeyInfoT::isEqual(P->getFirst(), EmptyKey) && + !KeyInfoT::isEqual(P->getFirst(), TombstoneKey)) { assert(size_t(TmpEnd - TmpBegin) < InlineBuckets && "Too many inline buckets!"); - new (&TmpEnd->first) KeyT(std::move(P->first)); - new (&TmpEnd->second) ValueT(std::move(P->second)); + new (&TmpEnd->getFirst()) KeyT(std::move(P->getFirst())); + new (&TmpEnd->getSecond()) ValueT(std::move(P->getSecond())); ++TmpEnd; - P->second.~ValueT(); + P->getSecond().~ValueT(); } - P->first.~KeyT(); + P->getFirst().~KeyT(); } // Now make this map use the large rep, and move all the entries back @@ -972,13 +985,12 @@ private: } }; -template +template class DenseMapIterator { - typedef std::pair Bucket; - typedef DenseMapIterator ConstIterator; - friend class DenseMapIterator; + typedef DenseMapIterator ConstIterator; + friend class DenseMapIterator; + public: typedef ptrdiff_t difference_type; typedef typename std::conditional::type @@ -999,9 +1011,9 @@ public: // If IsConst is true this is a converting constructor from iterator to // const_iterator and the default copy constructor is used. // Otherwise this is a copy constructor for iterator. - DenseMapIterator(const DenseMapIterator& I) - : Ptr(I.Ptr), End(I.End) {} + DenseMapIterator( + const DenseMapIterator &I) + : Ptr(I.Ptr), End(I.End) {} reference operator*() const { return *Ptr; @@ -1031,9 +1043,8 @@ private: const KeyT Empty = KeyInfoT::getEmptyKey(); const KeyT Tombstone = KeyInfoT::getTombstoneKey(); - while (Ptr != End && - (KeyInfoT::isEqual(Ptr->first, Empty) || - KeyInfoT::isEqual(Ptr->first, Tombstone))) + while (Ptr != End && (KeyInfoT::isEqual(Ptr->getFirst(), Empty) || + KeyInfoT::isEqual(Ptr->getFirst(), Tombstone))) ++Ptr; } }; diff --git a/include/llvm/ADT/DenseSet.h b/include/llvm/ADT/DenseSet.h index 9ab1be2..d340240 100644 --- a/include/llvm/ADT/DenseSet.h +++ b/include/llvm/ADT/DenseSet.h @@ -18,13 +18,29 @@ namespace llvm { +namespace detail { +struct DenseSetEmpty {}; + +// Use the empty base class trick so we can create a DenseMap where the buckets +// contain only a single item. +template class DenseSetPair : public DenseSetEmpty { + KeyT key; + +public: + KeyT &getFirst() { return key; } + const KeyT &getFirst() const { return key; } + DenseSetEmpty &getSecond() { return *this; } + const DenseSetEmpty &getSecond() const { return *this; } +}; +} + /// DenseSet - This implements a dense probed hash-table based set. -/// -/// FIXME: This is currently implemented directly in terms of DenseMap, this -/// should be optimized later if there is a need. template > class DenseSet { - typedef DenseMap MapTy; + typedef DenseMap> MapTy; + static_assert(sizeof(typename MapTy::value_type) == sizeof(ValueT), + "DenseMap buckets unexpectedly large!"); MapTy TheMap; public: typedef ValueT key_type; @@ -72,8 +88,8 @@ public: Iterator(const typename MapTy::iterator &i) : I(i) {} - ValueT& operator*() { return I->first; } - ValueT* operator->() { return &I->first; } + ValueT &operator*() { return I->getFirst(); } + ValueT *operator->() { return &I->getFirst(); } Iterator& operator++() { ++I; return *this; } bool operator==(const Iterator& X) const { return I == X.I; } @@ -92,8 +108,8 @@ public: ConstIterator(const typename MapTy::const_iterator &i) : I(i) {} - const ValueT& operator*() { return I->first; } - const ValueT* operator->() { return &I->first; } + const ValueT &operator*() { return I->getFirst(); } + const ValueT *operator->() { return &I->getFirst(); } ConstIterator& operator++() { ++I; return *this; } bool operator==(const ConstIterator& X) const { return I == X.I; } @@ -129,7 +145,8 @@ public: void erase(ConstIterator CI) { return TheMap.erase(CI.I); } std::pair insert(const ValueT &V) { - return TheMap.insert(std::make_pair(V, 0)); + detail::DenseSetEmpty Empty; + return TheMap.insert(std::make_pair(V, Empty)); } // Range insertion of values. diff --git a/include/llvm/ADT/DepthFirstIterator.h b/include/llvm/ADT/DepthFirstIterator.h index 0f69146..6cd9e68 100644 --- a/include/llvm/ADT/DepthFirstIterator.h +++ b/include/llvm/ADT/DepthFirstIterator.h @@ -33,10 +33,10 @@ #ifndef LLVM_ADT_DEPTHFIRSTITERATOR_H #define LLVM_ADT_DEPTHFIRSTITERATOR_H -#include "llvm/ADT/iterator_range.h" #include "llvm/ADT/GraphTraits.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/iterator_range.h" #include #include diff --git a/include/llvm/ADT/EquivalenceClasses.h b/include/llvm/ADT/EquivalenceClasses.h index e0396c7..d6a26f8 100644 --- a/include/llvm/ADT/EquivalenceClasses.h +++ b/include/llvm/ADT/EquivalenceClasses.h @@ -17,6 +17,7 @@ #include "llvm/Support/DataTypes.h" #include +#include #include namespace llvm { @@ -254,7 +255,7 @@ public: assert(Node != nullptr && "Dereferencing end()!"); return Node->getData(); } - reference operator->() const { return operator*(); } + pointer operator->() const { return &operator*(); } member_iterator &operator++() { assert(Node != nullptr && "++'d off the end of the list!"); diff --git a/include/llvm/ADT/FoldingSet.h b/include/llvm/ADT/FoldingSet.h index 14c5933..7ade167 100644 --- a/include/llvm/ADT/FoldingSet.h +++ b/include/llvm/ADT/FoldingSet.h @@ -18,6 +18,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/iterator.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/DataTypes.h" @@ -532,46 +533,6 @@ public: }; //===----------------------------------------------------------------------===// -/// FoldingSetVectorIterator - This implements an iterator for -/// FoldingSetVector. It is only necessary because FoldingSetIterator provides -/// a value_type of T, while the vector in FoldingSetVector exposes -/// a value_type of T*. Fortunately, FoldingSetIterator doesn't expose very -/// much besides operator* and operator->, so we just wrap the inner vector -/// iterator and perform the extra dereference. -template -class FoldingSetVectorIterator { - // Provide a typedef to workaround the lack of correct injected class name - // support in older GCCs. - typedef FoldingSetVectorIterator SelfT; - - VectorIteratorT Iterator; - -public: - FoldingSetVectorIterator(VectorIteratorT I) : Iterator(I) {} - - bool operator==(const SelfT &RHS) const { - return Iterator == RHS.Iterator; - } - bool operator!=(const SelfT &RHS) const { - return Iterator != RHS.Iterator; - } - - T &operator*() const { return **Iterator; } - - T *operator->() const { return *Iterator; } - - inline SelfT &operator++() { - ++Iterator; - return *this; - } - SelfT operator++(int) { - SelfT tmp = *this; - ++*this; - return tmp; - } -}; - -//===----------------------------------------------------------------------===// /// FoldingSetVector - This template class combines a FoldingSet and a vector /// to provide the interface of FoldingSet but with deterministic iteration /// order based on the insertion order. T must be a subclass of FoldingSetNode @@ -586,12 +547,11 @@ public: : Set(Log2InitSize) { } - typedef FoldingSetVectorIterator iterator; + typedef pointee_iterator iterator; iterator begin() { return Vector.begin(); } iterator end() { return Vector.end(); } - typedef FoldingSetVectorIterator - const_iterator; + typedef pointee_iterator const_iterator; const_iterator begin() const { return Vector.begin(); } const_iterator end() const { return Vector.end(); } @@ -735,31 +695,9 @@ template class FoldingSetNodeWrapper : public FoldingSetNode { T data; public: - explicit FoldingSetNodeWrapper(const T &x) : data(x) {} - virtual ~FoldingSetNodeWrapper() {} - - template - explicit FoldingSetNodeWrapper(const A1 &a1) - : data(a1) {} - - template - explicit FoldingSetNodeWrapper(const A1 &a1, const A2 &a2) - : data(a1,a2) {} - - template - explicit FoldingSetNodeWrapper(const A1 &a1, const A2 &a2, const A3 &a3) - : data(a1,a2,a3) {} - - template - explicit FoldingSetNodeWrapper(const A1 &a1, const A2 &a2, const A3 &a3, - const A4 &a4) - : data(a1,a2,a3,a4) {} - - template - explicit FoldingSetNodeWrapper(const A1 &a1, const A2 &a2, const A3 &a3, - const A4 &a4, const A5 &a5) - : data(a1,a2,a3,a4,a5) {} - + template + explicit FoldingSetNodeWrapper(Ts &&... Args) + : data(std::forward(Args)...) {} void Profile(FoldingSetNodeID &ID) { FoldingSetTrait::Profile(data, ID); } diff --git a/include/llvm/ADT/Hashing.h b/include/llvm/ADT/Hashing.h index abf02b8..a1e7864 100644 --- a/include/llvm/ADT/Hashing.h +++ b/include/llvm/ADT/Hashing.h @@ -55,12 +55,6 @@ #include #include -// Allow detecting C++11 feature availability when building with Clang without -// breaking other compilers. -#ifndef __has_feature -# define __has_feature(x) 0 -#endif - namespace llvm { /// \brief An opaque object representing a hash code. @@ -553,8 +547,6 @@ public: return buffer_ptr; } -#if defined(__has_feature) && __has_feature(__cxx_variadic_templates__) - /// \brief Recursive, variadic combining method. /// /// This function recurses through each argument, combining that argument @@ -568,53 +560,6 @@ public: return combine(length, buffer_ptr, buffer_end, args...); } -#else - // Manually expanded recursive combining methods. See variadic above for - // documentation. - - template - hash_code combine(size_t length, char *buffer_ptr, char *buffer_end, - const T1 &arg1, const T2 &arg2, const T3 &arg3, - const T4 &arg4, const T5 &arg5, const T6 &arg6) { - buffer_ptr = combine_data(length, buffer_ptr, buffer_end, get_hashable_data(arg1)); - return combine(length, buffer_ptr, buffer_end, arg2, arg3, arg4, arg5, arg6); - } - template - hash_code combine(size_t length, char *buffer_ptr, char *buffer_end, - const T1 &arg1, const T2 &arg2, const T3 &arg3, - const T4 &arg4, const T5 &arg5) { - buffer_ptr = combine_data(length, buffer_ptr, buffer_end, get_hashable_data(arg1)); - return combine(length, buffer_ptr, buffer_end, arg2, arg3, arg4, arg5); - } - template - hash_code combine(size_t length, char *buffer_ptr, char *buffer_end, - const T1 &arg1, const T2 &arg2, const T3 &arg3, - const T4 &arg4) { - buffer_ptr = combine_data(length, buffer_ptr, buffer_end, get_hashable_data(arg1)); - return combine(length, buffer_ptr, buffer_end, arg2, arg3, arg4); - } - template - hash_code combine(size_t length, char *buffer_ptr, char *buffer_end, - const T1 &arg1, const T2 &arg2, const T3 &arg3) { - buffer_ptr = combine_data(length, buffer_ptr, buffer_end, get_hashable_data(arg1)); - return combine(length, buffer_ptr, buffer_end, arg2, arg3); - } - template - hash_code combine(size_t length, char *buffer_ptr, char *buffer_end, - const T1 &arg1, const T2 &arg2) { - buffer_ptr = combine_data(length, buffer_ptr, buffer_end, get_hashable_data(arg1)); - return combine(length, buffer_ptr, buffer_end, arg2); - } - template - hash_code combine(size_t length, char *buffer_ptr, char *buffer_end, - const T1 &arg1) { - buffer_ptr = combine_data(length, buffer_ptr, buffer_end, get_hashable_data(arg1)); - return combine(length, buffer_ptr, buffer_end); - } - -#endif - /// \brief Base case for recursive, variadic combining. /// /// The base case when combining arguments recursively is reached when all @@ -643,9 +588,6 @@ public: } // namespace detail } // namespace hashing - -#if __has_feature(__cxx_variadic_templates__) - /// \brief Combine values into a single hash_code. /// /// This routine accepts a varying number of arguments of any type. It will @@ -663,52 +605,6 @@ template hash_code hash_combine(const Ts &...args) { return helper.combine(0, helper.buffer, helper.buffer + 64, args...); } -#else - -// What follows are manually exploded overloads for each argument width. See -// the above variadic definition for documentation and specification. - -template -hash_code hash_combine(const T1 &arg1, const T2 &arg2, const T3 &arg3, - const T4 &arg4, const T5 &arg5, const T6 &arg6) { - ::llvm::hashing::detail::hash_combine_recursive_helper helper; - return helper.combine(0, helper.buffer, helper.buffer + 64, - arg1, arg2, arg3, arg4, arg5, arg6); -} -template -hash_code hash_combine(const T1 &arg1, const T2 &arg2, const T3 &arg3, - const T4 &arg4, const T5 &arg5) { - ::llvm::hashing::detail::hash_combine_recursive_helper helper; - return helper.combine(0, helper.buffer, helper.buffer + 64, - arg1, arg2, arg3, arg4, arg5); -} -template -hash_code hash_combine(const T1 &arg1, const T2 &arg2, const T3 &arg3, - const T4 &arg4) { - ::llvm::hashing::detail::hash_combine_recursive_helper helper; - return helper.combine(0, helper.buffer, helper.buffer + 64, - arg1, arg2, arg3, arg4); -} -template -hash_code hash_combine(const T1 &arg1, const T2 &arg2, const T3 &arg3) { - ::llvm::hashing::detail::hash_combine_recursive_helper helper; - return helper.combine(0, helper.buffer, helper.buffer + 64, arg1, arg2, arg3); -} -template -hash_code hash_combine(const T1 &arg1, const T2 &arg2) { - ::llvm::hashing::detail::hash_combine_recursive_helper helper; - return helper.combine(0, helper.buffer, helper.buffer + 64, arg1, arg2); -} -template -hash_code hash_combine(const T1 &arg1) { - ::llvm::hashing::detail::hash_combine_recursive_helper helper; - return helper.combine(0, helper.buffer, helper.buffer + 64, arg1); -} - -#endif - - // Implementation details for implementations of hash_value overloads provided // here. namespace hashing { diff --git a/include/llvm/ADT/ImmutableList.h b/include/llvm/ADT/ImmutableList.h index 7f0c239..748d3e4 100644 --- a/include/llvm/ADT/ImmutableList.h +++ b/include/llvm/ADT/ImmutableList.h @@ -33,8 +33,8 @@ class ImmutableListImpl : public FoldingSetNode { friend class ImmutableListFactory; - void operator=(const ImmutableListImpl&) LLVM_DELETED_FUNCTION; - ImmutableListImpl(const ImmutableListImpl&) LLVM_DELETED_FUNCTION; + void operator=(const ImmutableListImpl&) = delete; + ImmutableListImpl(const ImmutableListImpl&) = delete; public: const T& getHead() const { return Head; } diff --git a/include/llvm/ADT/ImmutableMap.h b/include/llvm/ADT/ImmutableMap.h index 11f281b..75fee90 100644 --- a/include/llvm/ADT/ImmutableMap.h +++ b/include/llvm/ADT/ImmutableMap.h @@ -122,8 +122,8 @@ public: } private: - Factory(const Factory& RHS) LLVM_DELETED_FUNCTION; - void operator=(const Factory& RHS) LLVM_DELETED_FUNCTION; + Factory(const Factory& RHS) = delete; + void operator=(const Factory& RHS) = delete; }; bool contains(key_type_ref K) const { diff --git a/include/llvm/ADT/ImmutableSet.h b/include/llvm/ADT/ImmutableSet.h index 5a3d8ad..3c6f58c 100644 --- a/include/llvm/ADT/ImmutableSet.h +++ b/include/llvm/ADT/ImmutableSet.h @@ -1014,8 +1014,8 @@ public: } private: - Factory(const Factory& RHS) LLVM_DELETED_FUNCTION; - void operator=(const Factory& RHS) LLVM_DELETED_FUNCTION; + Factory(const Factory& RHS) = delete; + void operator=(const Factory& RHS) = delete; }; friend class Factory; diff --git a/include/llvm/ADT/IntervalMap.h b/include/llvm/ADT/IntervalMap.h index 46549ee..99be38f 100644 --- a/include/llvm/ADT/IntervalMap.h +++ b/include/llvm/ADT/IntervalMap.h @@ -496,7 +496,7 @@ public: NodeRef() {} /// operator bool - Detect a null ref. - LLVM_EXPLICIT operator bool() const { return pip.getOpaqueValue(); } + explicit operator bool() const { return pip.getOpaqueValue(); } /// NodeRef - Create a reference to the node p with n elements. template diff --git a/include/llvm/ADT/IntrusiveRefCntPtr.h b/include/llvm/ADT/IntrusiveRefCntPtr.h index c859c98..9b12d04 100644 --- a/include/llvm/ADT/IntrusiveRefCntPtr.h +++ b/include/llvm/ADT/IntrusiveRefCntPtr.h @@ -84,7 +84,7 @@ namespace llvm { friend struct IntrusiveRefCntPtrInfo; }; - + template struct IntrusiveRefCntPtrInfo { static void retain(T *obj) { obj->Retain(); } static void release(T *obj) { obj->Release(); } @@ -114,7 +114,7 @@ public: delete static_cast(this); } }; - + //===----------------------------------------------------------------------===// /// IntrusiveRefCntPtr - A template class that implements a "smart pointer" /// that assumes the wrapped object has a reference count associated @@ -177,7 +177,7 @@ public: T* get() const { return Obj; } - LLVM_EXPLICIT operator bool() const { return Obj; } + explicit operator bool() const { return Obj; } void swap(IntrusiveRefCntPtr& other) { T* tmp = other.Obj; diff --git a/include/llvm/ADT/MapVector.h b/include/llvm/ADT/MapVector.h index 14c49c5..1331b15 100644 --- a/include/llvm/ADT/MapVector.h +++ b/include/llvm/ADT/MapVector.h @@ -18,6 +18,7 @@ #define LLVM_ADT_MAPVECTOR_H #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallVector.h" #include namespace llvm { @@ -181,6 +182,14 @@ void MapVector::remove_if(Function Pred) { Vector.erase(O, Vector.end()); } +/// \brief A MapVector that performs no allocations if smaller than a certain +/// size. +template +struct SmallMapVector + : MapVector, + SmallVector, N>> { +}; + } // end namespace llvm #endif diff --git a/include/llvm/ADT/None.h b/include/llvm/ADT/None.h index 5793bd2..d69ec17 100644 --- a/include/llvm/ADT/None.h +++ b/include/llvm/ADT/None.h @@ -19,9 +19,8 @@ namespace llvm { /// \brief A simple null object to allow implicit construction of Optional /// and similar types without having to spell out the specialization's name. -enum NoneType { - None -}; +enum class NoneType { None }; +const NoneType None = None; } #endif diff --git a/include/llvm/ADT/Optional.h b/include/llvm/ADT/Optional.h index 591872e..855ab89 100644 --- a/include/llvm/ADT/Optional.h +++ b/include/llvm/ADT/Optional.h @@ -70,8 +70,6 @@ public: return *this; } -#if LLVM_HAS_VARIADIC_TEMPLATES - /// Create a new object by constructing it in place with the given arguments. template void emplace(ArgTypes &&...Args) { @@ -80,51 +78,6 @@ public: new (storage.buffer) T(std::forward(Args)...); } -#else - - /// Create a new object by default-constructing it in place. - void emplace() { - reset(); - hasVal = true; - new (storage.buffer) T(); - } - - /// Create a new object by constructing it in place with the given arguments. - template - void emplace(T1 &&A1) { - reset(); - hasVal = true; - new (storage.buffer) T(std::forward(A1)); - } - - /// Create a new object by constructing it in place with the given arguments. - template - void emplace(T1 &&A1, T2 &&A2) { - reset(); - hasVal = true; - new (storage.buffer) T(std::forward(A1), std::forward(A2)); - } - - /// Create a new object by constructing it in place with the given arguments. - template - void emplace(T1 &&A1, T2 &&A2, T3 &&A3) { - reset(); - hasVal = true; - new (storage.buffer) T(std::forward(A1), std::forward(A2), - std::forward(A3)); - } - - /// Create a new object by constructing it in place with the given arguments. - template - void emplace(T1 &&A1, T2 &&A2, T3 &&A3, T4 &&A4) { - reset(); - hasVal = true; - new (storage.buffer) T(std::forward(A1), std::forward(A2), - std::forward(A3), std::forward(A4)); - } - -#endif // LLVM_HAS_VARIADIC_TEMPLATES - static inline Optional create(const T* y) { return y ? Optional(*y) : Optional(); } @@ -168,7 +121,7 @@ public: const T& getValue() const LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); } T& getValue() LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); } - LLVM_EXPLICIT operator bool() const { return hasVal; } + explicit operator bool() const { return hasVal; } bool hasValue() const { return hasVal; } const T* operator->() const { return getPointer(); } T* operator->() { return getPointer(); } diff --git a/include/llvm/ADT/PointerUnion.h b/include/llvm/ADT/PointerUnion.h index a6dddd2..f27b811 100644 --- a/include/llvm/ADT/PointerUnion.h +++ b/include/llvm/ADT/PointerUnion.h @@ -61,7 +61,7 @@ namespace llvm { NumLowBitsAvailable = PT1BitsAv < PT2BitsAv ? PT1BitsAv : PT2BitsAv }; }; - + /// PointerUnion - This implements a discriminated union of two pointer types, /// and keeps the discriminator bit-mangled into the low bits of the pointer. /// This allows the implementation to be extremely efficient in space, but @@ -80,7 +80,7 @@ namespace llvm { template class PointerUnion { public: - typedef PointerIntPair > ValTy; private: ValTy Val; @@ -96,14 +96,14 @@ namespace llvm { public: PointerUnion() {} - + PointerUnion(PT1 V) : Val( const_cast(PointerLikeTypeTraits::getAsVoidPointer(V))) { } PointerUnion(PT2 V) : Val( const_cast(PointerLikeTypeTraits::getAsVoidPointer(V)), 1) { } - + /// isNull - Return true if the pointer held in the union is null, /// regardless of which type it is. bool isNull() const { @@ -111,7 +111,7 @@ namespace llvm { // we recursively strip off low bits if we have a nested PointerUnion. return !PointerLikeTypeTraits::getFromVoidPointer(Val.getPointer()); } - LLVM_EXPLICIT operator bool() const { return !isNull(); } + explicit operator bool() const { return !isNull(); } /// is() return true if the Union currently holds the type matching T. template @@ -123,7 +123,7 @@ namespace llvm { int TyNo = Ty::Num; return static_cast(Val.getInt()) == TyNo; } - + /// get() - Return the value of the specified pointer type. If the /// specified pointer type is incorrect, assert. template @@ -131,7 +131,7 @@ namespace llvm { assert(is() && "Invalid accessor called"); return PointerLikeTypeTraits::getFromVoidPointer(Val.getPointer()); } - + /// dyn_cast() - If the current value is of the specified pointer type, /// return it, otherwise return null. template @@ -160,7 +160,7 @@ namespace llvm { Val.initWithPointer(nullptr); return *this; } - + /// Assignment operators - Allow assigning into this union from either /// pointer type, setting the discriminator to remember what it came from. const PointerUnion &operator=(const PT1 &RHS) { @@ -174,7 +174,7 @@ namespace llvm { 1); return *this; } - + void *getOpaqueValue() const { return Val.getOpaqueValue(); } static inline PointerUnion getFromOpaqueValue(void *VP) { PointerUnion V; @@ -195,6 +195,12 @@ namespace llvm { return lhs.getOpaqueValue() != rhs.getOpaqueValue(); } + template + static bool operator<(PointerUnion lhs, + PointerUnion rhs) { + return lhs.getOpaqueValue() < rhs.getOpaqueValue(); + } + // Teach SmallPtrSet that PointerUnion is "basically a pointer", that has // # low bits available = min(PT1bits,PT2bits)-1. template @@ -208,16 +214,16 @@ namespace llvm { getFromVoidPointer(void *P) { return PointerUnion::getFromOpaqueValue(P); } - + // The number of bits available are the min of the two pointer types. enum { - NumLowBitsAvailable = + NumLowBitsAvailable = PointerLikeTypeTraits::ValTy> ::NumLowBitsAvailable }; }; - - + + /// PointerUnion3 - This is a pointer union of three pointer types. See /// documentation for PointerUnion for usage. template @@ -233,7 +239,7 @@ namespace llvm { IsInnerUnion(ValTy val) : Val(val) { } template int is() const { - return Val.template is() && + return Val.template is() && Val.template get().template is(); } template @@ -257,7 +263,7 @@ namespace llvm { public: PointerUnion3() {} - + PointerUnion3(PT1 V) { Val = InnerUnion(V); } @@ -267,12 +273,12 @@ namespace llvm { PointerUnion3(PT3 V) { Val = V; } - + /// isNull - Return true if the pointer held in the union is null, /// regardless of which type it is. bool isNull() const { return Val.isNull(); } - LLVM_EXPLICIT operator bool() const { return !isNull(); } - + explicit operator bool() const { return !isNull(); } + /// is() return true if the Union currently holds the type matching T. template int is() const { @@ -283,7 +289,7 @@ namespace llvm { >::Return Ty; return Ty(Val).template is(); } - + /// get() - Return the value of the specified pointer type. If the /// specified pointer type is incorrect, assert. template @@ -296,7 +302,7 @@ namespace llvm { >::Return Ty; return Ty(Val).template get(); } - + /// dyn_cast() - If the current value is of the specified pointer type, /// return it, otherwise return null. template @@ -310,7 +316,7 @@ namespace llvm { Val = nullptr; return *this; } - + /// Assignment operators - Allow assigning into this union from either /// pointer type, setting the discriminator to remember what it came from. const PointerUnion3 &operator=(const PT1 &RHS) { @@ -325,7 +331,7 @@ namespace llvm { Val = RHS; return *this; } - + void *getOpaqueValue() const { return Val.getOpaqueValue(); } static inline PointerUnion3 getFromOpaqueValue(void *VP) { PointerUnion3 V; @@ -333,7 +339,7 @@ namespace llvm { return V; } }; - + // Teach SmallPtrSet that PointerUnion3 is "basically a pointer", that has // # low bits available = min(PT1bits,PT2bits,PT2bits)-2. template @@ -347,10 +353,10 @@ namespace llvm { getFromVoidPointer(void *P) { return PointerUnion3::getFromOpaqueValue(P); } - + // The number of bits available are the min of the two pointer types. enum { - NumLowBitsAvailable = + NumLowBitsAvailable = PointerLikeTypeTraits::ValTy> ::NumLowBitsAvailable }; @@ -368,7 +374,7 @@ namespace llvm { ValTy Val; public: PointerUnion4() {} - + PointerUnion4(PT1 V) { Val = InnerUnion1(V); } @@ -381,12 +387,12 @@ namespace llvm { PointerUnion4(PT4 V) { Val = InnerUnion2(V); } - + /// isNull - Return true if the pointer held in the union is null, /// regardless of which type it is. bool isNull() const { return Val.isNull(); } - LLVM_EXPLICIT operator bool() const { return !isNull(); } - + explicit operator bool() const { return !isNull(); } + /// is() return true if the Union currently holds the type matching T. template int is() const { @@ -395,10 +401,10 @@ namespace llvm { ::llvm::PointerUnionTypeSelector >::Return Ty; - return Val.template is() && + return Val.template is() && Val.template get().template is(); } - + /// get() - Return the value of the specified pointer type. If the /// specified pointer type is incorrect, assert. template @@ -411,7 +417,7 @@ namespace llvm { >::Return Ty; return Val.template get().template get(); } - + /// dyn_cast() - If the current value is of the specified pointer type, /// return it, otherwise return null. template @@ -425,7 +431,7 @@ namespace llvm { Val = nullptr; return *this; } - + /// Assignment operators - Allow assigning into this union from either /// pointer type, setting the discriminator to remember what it came from. const PointerUnion4 &operator=(const PT1 &RHS) { @@ -444,7 +450,7 @@ namespace llvm { Val = InnerUnion2(RHS); return *this; } - + void *getOpaqueValue() const { return Val.getOpaqueValue(); } static inline PointerUnion4 getFromOpaqueValue(void *VP) { PointerUnion4 V; @@ -452,7 +458,7 @@ namespace llvm { return V; } }; - + // Teach SmallPtrSet that PointerUnion4 is "basically a pointer", that has // # low bits available = min(PT1bits,PT2bits,PT2bits)-2. template @@ -466,10 +472,10 @@ namespace llvm { getFromVoidPointer(void *P) { return PointerUnion4::getFromOpaqueValue(P); } - + // The number of bits available are the min of the two pointer types. enum { - NumLowBitsAvailable = + NumLowBitsAvailable = PointerLikeTypeTraits::ValTy> ::NumLowBitsAvailable }; diff --git a/include/llvm/ADT/STLExtras.h b/include/llvm/ADT/STLExtras.h index 4e56e4d..57af18e 100644 --- a/include/llvm/ADT/STLExtras.h +++ b/include/llvm/ADT/STLExtras.h @@ -18,6 +18,7 @@ #define LLVM_ADT_STLEXTRAS_H #include "llvm/Support/Compiler.h" +#include #include // for std::size_t #include // for qsort #include @@ -63,8 +64,6 @@ struct greater_ptr : public std::binary_function { /// a function_ref. template class function_ref; -#if LLVM_HAS_VARIADIC_TEMPLATES - template class function_ref { Ret (*callback)(intptr_t callable, Params ...params); @@ -89,112 +88,6 @@ public: } }; -#else - -template -class function_ref { - Ret (*callback)(intptr_t callable); - intptr_t callable; - - template - static Ret callback_fn(intptr_t callable) { - return (*reinterpret_cast(callable))(); - } - -public: - template - function_ref(Callable &&callable, - typename std::enable_if< - !std::is_same::type, - function_ref>::value>::type * = nullptr) - : callback(callback_fn::type>), - callable(reinterpret_cast(&callable)) {} - Ret operator()() const { return callback(callable); } -}; - -template -class function_ref { - Ret (*callback)(intptr_t callable, Param1 param1); - intptr_t callable; - - template - static Ret callback_fn(intptr_t callable, Param1 param1) { - return (*reinterpret_cast(callable))( - std::forward(param1)); - } - -public: - template - function_ref(Callable &&callable, - typename std::enable_if< - !std::is_same::type, - function_ref>::value>::type * = nullptr) - : callback(callback_fn::type>), - callable(reinterpret_cast(&callable)) {} - Ret operator()(Param1 param1) { - return callback(callable, std::forward(param1)); - } -}; - -template -class function_ref { - Ret (*callback)(intptr_t callable, Param1 param1, Param2 param2); - intptr_t callable; - - template - static Ret callback_fn(intptr_t callable, Param1 param1, Param2 param2) { - return (*reinterpret_cast(callable))( - std::forward(param1), - std::forward(param2)); - } - -public: - template - function_ref(Callable &&callable, - typename std::enable_if< - !std::is_same::type, - function_ref>::value>::type * = nullptr) - : callback(callback_fn::type>), - callable(reinterpret_cast(&callable)) {} - Ret operator()(Param1 param1, Param2 param2) { - return callback(callable, - std::forward(param1), - std::forward(param2)); - } -}; - -template -class function_ref { - Ret (*callback)(intptr_t callable, Param1 param1, Param2 param2, Param3 param3); - intptr_t callable; - - template - static Ret callback_fn(intptr_t callable, Param1 param1, Param2 param2, - Param3 param3) { - return (*reinterpret_cast(callable))( - std::forward(param1), - std::forward(param2), - std::forward(param3)); - } - -public: - template - function_ref(Callable &&callable, - typename std::enable_if< - !std::is_same::type, - function_ref>::value>::type * = nullptr) - : callback(callback_fn::type>), - callable(reinterpret_cast(&callable)) {} - Ret operator()(Param1 param1, Param2 param2, Param3 param3) { - return callback(callable, - std::forward(param1), - std::forward(param2), - std::forward(param3)); - } -}; - -#endif - // deleter - Very very very simple method that is used to invoke operator // delete on something. It is used like this: // @@ -301,6 +194,28 @@ struct less_second { } }; +// A subset of N3658. More stuff can be added as-needed. + +/// \brief Represents a compile-time sequence of integers. +template struct integer_sequence { + typedef T value_type; + + static LLVM_CONSTEXPR size_t size() { return sizeof...(I); } +}; + +/// \brief Alias for the common case of a sequence of size_ts. +template +struct index_sequence : integer_sequence {}; + +template +struct build_index_impl : build_index_impl {}; +template +struct build_index_impl<0, I...> : index_sequence {}; + +/// \brief Creates a compile-time integer sequence for a parameter pack. +template +struct index_sequence_for : build_index_impl {}; + //===----------------------------------------------------------------------===// // Extra additions for arrays //===----------------------------------------------------------------------===// @@ -392,8 +307,6 @@ void DeleteContainerSeconds(Container &C) { // Extra additions to //===----------------------------------------------------------------------===// -#if LLVM_HAS_VARIADIC_TEMPLATES - // Implement make_unique according to N3656. /// \brief Constructs a `new T()` with the given args and returns a @@ -427,123 +340,7 @@ make_unique(size_t n) { /// This function isn't used and is only here to provide better compile errors. template typename std::enable_if::value != 0>::type -make_unique(Args &&...) LLVM_DELETED_FUNCTION; - -#else - -template -typename std::enable_if::value, std::unique_ptr>::type -make_unique() { - return std::unique_ptr(new T()); -} - -template -typename std::enable_if::value, std::unique_ptr>::type -make_unique(Arg1 &&arg1) { - return std::unique_ptr(new T(std::forward(arg1))); -} - -template -typename std::enable_if::value, std::unique_ptr>::type -make_unique(Arg1 &&arg1, Arg2 &&arg2) { - return std::unique_ptr( - new T(std::forward(arg1), std::forward(arg2))); -} - -template -typename std::enable_if::value, std::unique_ptr>::type -make_unique(Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3) { - return std::unique_ptr(new T(std::forward(arg1), - std::forward(arg2), - std::forward(arg3))); -} - -template -typename std::enable_if::value, std::unique_ptr>::type -make_unique(Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3, Arg4 &&arg4) { - return std::unique_ptr( - new T(std::forward(arg1), std::forward(arg2), - std::forward(arg3), std::forward(arg4))); -} - -template -typename std::enable_if::value, std::unique_ptr>::type -make_unique(Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3, Arg4 &&arg4, Arg5 &&arg5) { - return std::unique_ptr( - new T(std::forward(arg1), std::forward(arg2), - std::forward(arg3), std::forward(arg4), - std::forward(arg5))); -} - -template -typename std::enable_if::value, std::unique_ptr>::type -make_unique(Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3, Arg4 &&arg4, Arg5 &&arg5, - Arg6 &&arg6) { - return std::unique_ptr( - new T(std::forward(arg1), std::forward(arg2), - std::forward(arg3), std::forward(arg4), - std::forward(arg5), std::forward(arg6))); -} - -template -typename std::enable_if::value, std::unique_ptr>::type -make_unique(Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3, Arg4 &&arg4, Arg5 &&arg5, - Arg6 &&arg6, Arg7 &&arg7) { - return std::unique_ptr( - new T(std::forward(arg1), std::forward(arg2), - std::forward(arg3), std::forward(arg4), - std::forward(arg5), std::forward(arg6), - std::forward(arg7))); -} - -template -typename std::enable_if::value, std::unique_ptr>::type -make_unique(Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3, Arg4 &&arg4, Arg5 &&arg5, - Arg6 &&arg6, Arg7 &&arg7, Arg8 &&arg8) { - return std::unique_ptr( - new T(std::forward(arg1), std::forward(arg2), - std::forward(arg3), std::forward(arg4), - std::forward(arg5), std::forward(arg6), - std::forward(arg7), std::forward(arg8))); -} - -template -typename std::enable_if::value, std::unique_ptr>::type -make_unique(Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3, Arg4 &&arg4, Arg5 &&arg5, - Arg6 &&arg6, Arg7 &&arg7, Arg8 &&arg8, Arg9 &&arg9) { - return std::unique_ptr( - new T(std::forward(arg1), std::forward(arg2), - std::forward(arg3), std::forward(arg4), - std::forward(arg5), std::forward(arg6), - std::forward(arg7), std::forward(arg8), - std::forward(arg9))); -} - -template -typename std::enable_if::value, std::unique_ptr>::type -make_unique(Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3, Arg4 &&arg4, Arg5 &&arg5, - Arg6 &&arg6, Arg7 &&arg7, Arg8 &&arg8, Arg9 &&arg9, Arg10 &&arg10) { - return std::unique_ptr( - new T(std::forward(arg1), std::forward(arg2), - std::forward(arg3), std::forward(arg4), - std::forward(arg5), std::forward(arg6), - std::forward(arg7), std::forward(arg8), - std::forward(arg9), std::forward(arg10))); -} - -template -typename std::enable_if::value &&std::extent::value == 0, - std::unique_ptr>::type -make_unique(size_t n) { - return std::unique_ptr(new typename std::remove_extent::type[n]()); -} - -#endif +make_unique(Args &&...) = delete; struct FreeDeleter { void operator()(void* v) { @@ -558,6 +355,35 @@ struct pair_hash { } }; +/// A functor like C++14's std::less in its absence. +struct less { + template bool operator()(A &&a, B &&b) const { + return std::forward(a) < std::forward(b); + } +}; + +/// A functor like C++14's std::equal in its absence. +struct equal { + template bool operator()(A &&a, B &&b) const { + return std::forward(a) == std::forward(b); + } +}; + +/// Binary functor that adapts to any other binary functor after dereferencing +/// operands. +template struct deref { + T func; + // Could be further improved to cope with non-derivable functors and + // non-binary functors (should be a variadic template member function + // operator()). + template + auto operator()(A &lhs, B &rhs) const -> decltype(func(*lhs, *rhs)) { + assert(lhs); + assert(rhs); + return func(*lhs, *rhs); + } +}; + } // End llvm namespace #endif diff --git a/include/llvm/ADT/ScopedHashTable.h b/include/llvm/ADT/ScopedHashTable.h index 2f60ecc..5abe76c 100644 --- a/include/llvm/ADT/ScopedHashTable.h +++ b/include/llvm/ADT/ScopedHashTable.h @@ -90,8 +90,8 @@ class ScopedHashTableScope { /// LastValInScope - This is the last value that was inserted for this scope /// or null if none have been inserted yet. ScopedHashTableVal *LastValInScope; - void operator=(ScopedHashTableScope&) LLVM_DELETED_FUNCTION; - ScopedHashTableScope(ScopedHashTableScope&) LLVM_DELETED_FUNCTION; + void operator=(ScopedHashTableScope&) = delete; + ScopedHashTableScope(ScopedHashTableScope&) = delete; public: ScopedHashTableScope(ScopedHashTable &HT); ~ScopedHashTableScope(); diff --git a/include/llvm/ADT/SmallBitVector.h b/include/llvm/ADT/SmallBitVector.h index ababf0f..22e8ccd 100644 --- a/include/llvm/ADT/SmallBitVector.h +++ b/include/llvm/ADT/SmallBitVector.h @@ -53,6 +53,9 @@ class SmallBitVector { SmallNumDataBits = SmallNumRawBits - SmallNumSizeBits }; + static_assert(NumBaseBits == 64 || NumBaseBits == 32, + "Unsupported word size"); + public: typedef unsigned size_type; // Encapsulation of a single bit. @@ -177,11 +180,7 @@ public: size_type count() const { if (isSmall()) { uintptr_t Bits = getSmallBits(); - if (NumBaseBits == 32) - return CountPopulation_32(Bits); - if (NumBaseBits == 64) - return CountPopulation_64(Bits); - llvm_unreachable("Unsupported!"); + return countPopulation(Bits); } return getPointer()->count(); } @@ -214,11 +213,7 @@ public: uintptr_t Bits = getSmallBits(); if (Bits == 0) return -1; - if (NumBaseBits == 32) - return countTrailingZeros(Bits); - if (NumBaseBits == 64) - return countTrailingZeros(Bits); - llvm_unreachable("Unsupported!"); + return countTrailingZeros(Bits); } return getPointer()->find_first(); } @@ -232,11 +227,7 @@ public: Bits &= ~uintptr_t(0) << (Prev + 1); if (Bits == 0 || Prev + 1 >= getSmallSize()) return -1; - if (NumBaseBits == 32) - return countTrailingZeros(Bits); - if (NumBaseBits == 64) - return countTrailingZeros(Bits); - llvm_unreachable("Unsupported!"); + return countTrailingZeros(Bits); } return getPointer()->find_next(Prev); } @@ -292,8 +283,12 @@ public: } SmallBitVector &set(unsigned Idx) { - if (isSmall()) + if (isSmall()) { + assert(Idx <= static_cast( + std::numeric_limits::digits) && + "undefined behavior"); setSmallBits(getSmallBits() | (uintptr_t(1) << Idx)); + } else getPointer()->set(Idx); return *this; @@ -556,7 +551,6 @@ public: private: template void applyMask(const uint32_t *Mask, unsigned MaskWords) { - assert((NumBaseBits == 64 || NumBaseBits == 32) && "Unsupported word size"); if (NumBaseBits == 64 && MaskWords >= 2) { uint64_t M = Mask[0] | (uint64_t(Mask[1]) << 32); if (InvertMask) M = ~M; diff --git a/include/llvm/ADT/SmallPtrSet.h b/include/llvm/ADT/SmallPtrSet.h index b8977fa..3e3c9c1 100644 --- a/include/llvm/ADT/SmallPtrSet.h +++ b/include/llvm/ADT/SmallPtrSet.h @@ -132,7 +132,7 @@ private: /// Grow - Allocate a larger backing store for the buckets and move it over. void Grow(unsigned NewSize); - void operator=(const SmallPtrSetImplBase &RHS) LLVM_DELETED_FUNCTION; + void operator=(const SmallPtrSetImplBase &RHS) = delete; protected: /// swap - Swaps the elements of two sets. /// Note: This method assumes that both sets have the same small size. @@ -242,7 +242,7 @@ template class SmallPtrSetImpl : public SmallPtrSetImplBase { typedef PointerLikeTypeTraits PtrTraits; - SmallPtrSetImpl(const SmallPtrSetImpl&) LLVM_DELETED_FUNCTION; + SmallPtrSetImpl(const SmallPtrSetImpl&) = delete; protected: // Constructors that forward to the base. SmallPtrSetImpl(const void **SmallStorage, const SmallPtrSetImpl &that) @@ -257,8 +257,10 @@ public: typedef SmallPtrSetIterator iterator; typedef SmallPtrSetIterator const_iterator; - /// insert - This returns true if the pointer was new to the set, false if it - /// was already in the set. + /// Inserts Ptr if and only if there is no element in the container equal to + /// Ptr. The bool component of the returned pair is true if and only if the + /// insertion takes place, and the iterator component of the pair points to + /// the element equal to Ptr. std::pair insert(PtrType Ptr) { auto p = insert_imp(PtrTraits::getAsVoidPointer(Ptr)); return std::make_pair(iterator(p.first, CurArray + CurArraySize), p.second); diff --git a/include/llvm/ADT/SmallVector.h b/include/llvm/ADT/SmallVector.h index 2117541..14e2c7b 100644 --- a/include/llvm/ADT/SmallVector.h +++ b/include/llvm/ADT/SmallVector.h @@ -135,11 +135,11 @@ public: const_pointer data() const { return const_pointer(begin()); } reference operator[](size_type idx) { - assert(begin() + idx < end()); + assert(idx < size()); return begin()[idx]; } const_reference operator[](size_type idx) const { - assert(begin() + idx < end()); + assert(idx < size()); return begin()[idx]; } @@ -307,8 +307,11 @@ protected: /// Copy the range [I, E) onto the uninitialized memory /// starting with "Dest", constructing elements into it as needed. - template - static void uninitialized_copy(T1 *I, T1 *E, T2 *Dest) { + template + static void uninitialized_copy( + T1 *I, T1 *E, T2 *Dest, + typename std::enable_if::type, + T2>::value>::type * = nullptr) { // Use memcpy for PODs iterated by pointers (which includes SmallVector // iterators): std::uninitialized_copy optimizes to memmove, but we can // use memcpy here. @@ -340,7 +343,7 @@ template class SmallVectorImpl : public SmallVectorTemplateBase::value> { typedef SmallVectorTemplateBase::value > SuperClass; - SmallVectorImpl(const SmallVectorImpl&) LLVM_DELETED_FUNCTION; + SmallVectorImpl(const SmallVectorImpl&) = delete; public: typedef typename SuperClass::iterator iterator; typedef typename SuperClass::size_type size_type; @@ -367,7 +370,7 @@ public: this->EndX = this->BeginX; } - void resize(unsigned N) { + void resize(size_type N) { if (N < this->size()) { this->destroy_range(this->begin()+N, this->end()); this->setEnd(this->begin()+N); @@ -380,7 +383,7 @@ public: } } - void resize(unsigned N, const T &NV) { + void resize(size_type N, const T &NV) { if (N < this->size()) { this->destroy_range(this->begin()+N, this->end()); this->setEnd(this->begin()+N); @@ -392,7 +395,7 @@ public: } } - void reserve(unsigned N) { + void reserve(size_type N) { if (this->capacity() < N) this->grow(N); } @@ -414,9 +417,7 @@ public: this->grow(this->size()+NumInputs); // Copy the new elements over. - // TODO: NEED To compile time dispatch on whether in_iter is a random access - // iterator to use the fast uninitialized_copy. - std::uninitialized_copy(in_start, in_end, this->end()); + this->uninitialized_copy(in_start, in_end, this->end()); this->setEnd(this->end() + NumInputs); } @@ -431,7 +432,7 @@ public: this->setEnd(this->end() + NumInputs); } - void assign(unsigned NumElts, const T &Elt) { + void assign(size_type NumElts, const T &Elt) { clear(); if (this->capacity() < NumElts) this->grow(NumElts); @@ -537,7 +538,7 @@ public: assert(I <= this->end() && "Inserting past the end of the vector."); // Ensure there is enough space. - reserve(static_cast(this->size() + NumToInsert)); + reserve(this->size() + NumToInsert); // Uninvalidate the iterator. I = this->begin()+InsertElt; @@ -591,7 +592,7 @@ public: size_t NumToInsert = std::distance(From, To); // Ensure there is enough space. - reserve(static_cast(this->size() + NumToInsert)); + reserve(this->size() + NumToInsert); // Uninvalidate the iterator. I = this->begin()+InsertElt; @@ -632,6 +633,13 @@ public: return I; } + template void emplace_back(ArgTypes &&... Args) { + if (LLVM_UNLIKELY(this->EndX >= this->CapacityX)) + this->grow(); + ::new ((void *)this->end()) T(std::forward(Args)...); + this->setEnd(this->end() + 1); + } + SmallVectorImpl &operator=(const SmallVectorImpl &RHS); SmallVectorImpl &operator=(SmallVectorImpl &&RHS); @@ -658,7 +666,7 @@ public: /// of the buffer when they know that more elements are available, and only /// update the size later. This avoids the cost of value initializing elements /// which will only be overwritten. - void set_size(unsigned N) { + void set_size(size_type N) { assert(N <= this->capacity()); this->setEnd(this->begin() + N); } @@ -684,7 +692,7 @@ void SmallVectorImpl::swap(SmallVectorImpl &RHS) { // Swap the shared elements. size_t NumShared = this->size(); if (NumShared > RHS.size()) NumShared = RHS.size(); - for (unsigned i = 0; i != static_cast(NumShared); ++i) + for (size_type i = 0; i != NumShared; ++i) std::swap((*this)[i], RHS[i]); // Copy over the extra elts. @@ -841,7 +849,7 @@ public: SmallVector() : SmallVectorImpl(N) { } - explicit SmallVector(unsigned Size, const T &Value = T()) + explicit SmallVector(size_t Size, const T &Value = T()) : SmallVectorImpl(N) { this->assign(Size, Value); } @@ -876,6 +884,17 @@ public: SmallVectorImpl::operator=(::std::move(RHS)); return *this; } + + SmallVector(SmallVectorImpl &&RHS) : SmallVectorImpl(N) { + if (!RHS.empty()) + SmallVectorImpl::operator=(::std::move(RHS)); + } + + const SmallVector &operator=(SmallVectorImpl &&RHS) { + SmallVectorImpl::operator=(::std::move(RHS)); + return *this; + } + }; template diff --git a/include/llvm/ADT/SparseBitVector.h b/include/llvm/ADT/SparseBitVector.h index d5bde29..20cbe2c 100644 --- a/include/llvm/ADT/SparseBitVector.h +++ b/include/llvm/ADT/SparseBitVector.h @@ -124,25 +124,15 @@ public: size_type count() const { unsigned NumBits = 0; for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i) - if (sizeof(BitWord) == 4) - NumBits += CountPopulation_32(Bits[i]); - else if (sizeof(BitWord) == 8) - NumBits += CountPopulation_64(Bits[i]); - else - llvm_unreachable("Unsupported!"); + NumBits += countPopulation(Bits[i]); return NumBits; } /// find_first - Returns the index of the first set bit. int find_first() const { for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i) - if (Bits[i] != 0) { - if (sizeof(BitWord) == 4) - return i * BITWORD_SIZE + countTrailingZeros(Bits[i]); - if (sizeof(BitWord) == 8) - return i * BITWORD_SIZE + countTrailingZeros(Bits[i]); - llvm_unreachable("Unsupported!"); - } + if (Bits[i] != 0) + return i * BITWORD_SIZE + countTrailingZeros(Bits[i]); llvm_unreachable("Illegal empty element"); } @@ -161,23 +151,13 @@ public: // Mask off previous bits. Copy &= ~0UL << BitPos; - if (Copy != 0) { - if (sizeof(BitWord) == 4) - return WordPos * BITWORD_SIZE + countTrailingZeros(Copy); - if (sizeof(BitWord) == 8) - return WordPos * BITWORD_SIZE + countTrailingZeros(Copy); - llvm_unreachable("Unsupported!"); - } + if (Copy != 0) + return WordPos * BITWORD_SIZE + countTrailingZeros(Copy); // Check subsequent words. for (unsigned i = WordPos+1; i < BITWORDS_PER_ELEMENT; ++i) - if (Bits[i] != 0) { - if (sizeof(BitWord) == 4) - return i * BITWORD_SIZE + countTrailingZeros(Bits[i]); - if (sizeof(BitWord) == 8) - return i * BITWORD_SIZE + countTrailingZeros(Bits[i]); - llvm_unreachable("Unsupported!"); - } + if (Bits[i] != 0) + return i * BITWORD_SIZE + countTrailingZeros(Bits[i]); return -1; } diff --git a/include/llvm/ADT/SparseMultiSet.h b/include/llvm/ADT/SparseMultiSet.h index f858536..e3aa258 100644 --- a/include/llvm/ADT/SparseMultiSet.h +++ b/include/llvm/ADT/SparseMultiSet.h @@ -133,8 +133,8 @@ class SparseMultiSet { // Disable copy construction and assignment. // This data structure is not meant to be used that way. - SparseMultiSet(const SparseMultiSet&) LLVM_DELETED_FUNCTION; - SparseMultiSet &operator=(const SparseMultiSet&) LLVM_DELETED_FUNCTION; + SparseMultiSet(const SparseMultiSet&) = delete; + SparseMultiSet &operator=(const SparseMultiSet&) = delete; /// Whether the given entry is the head of the list. List heads's previous /// pointers are to the tail of the list, allowing for efficient access to the diff --git a/include/llvm/ADT/SparseSet.h b/include/llvm/ADT/SparseSet.h index 9a13440..a45d1c8 100644 --- a/include/llvm/ADT/SparseSet.h +++ b/include/llvm/ADT/SparseSet.h @@ -133,8 +133,8 @@ class SparseSet { // Disable copy construction and assignment. // This data structure is not meant to be used that way. - SparseSet(const SparseSet&) LLVM_DELETED_FUNCTION; - SparseSet &operator=(const SparseSet&) LLVM_DELETED_FUNCTION; + SparseSet(const SparseSet&) = delete; + SparseSet &operator=(const SparseSet&) = delete; public: typedef ValueT value_type; diff --git a/include/llvm/ADT/StringMap.h b/include/llvm/ADT/StringMap.h index 2feb2ab..8721c73 100644 --- a/include/llvm/ADT/StringMap.h +++ b/include/llvm/ADT/StringMap.h @@ -111,7 +111,7 @@ public: /// and data. template class StringMapEntry : public StringMapEntryBase { - StringMapEntry(StringMapEntry &E) LLVM_DELETED_FUNCTION; + StringMapEntry(StringMapEntry &E) = delete; public: ValueTy second; @@ -179,19 +179,6 @@ public: return Create(Key, ValueTy()); } - /// GetStringMapEntryFromValue - Given a value that is known to be embedded - /// into a StringMapEntry, return the StringMapEntry itself. - static StringMapEntry &GetStringMapEntryFromValue(ValueTy &V) { - StringMapEntry *EPtr = 0; - char *Ptr = reinterpret_cast(&V) - - (reinterpret_cast(&EPtr->second) - - reinterpret_cast(EPtr)); - return *reinterpret_cast(Ptr); - } - static const StringMapEntry &GetStringMapEntryFromValue(const ValueTy &V) { - return GetStringMapEntryFromValue(const_cast(V)); - } - /// GetStringMapEntryFromKeyData - Given key data that is known to be embedded /// into a StringMapEntry, return the StringMapEntry itself. static StringMapEntry &GetStringMapEntryFromKeyData(const char *KeyData) { diff --git a/include/llvm/ADT/StringRef.h b/include/llvm/ADT/StringRef.h index 778fa10..6111c42 100644 --- a/include/llvm/ADT/StringRef.h +++ b/include/llvm/ADT/StringRef.h @@ -91,6 +91,13 @@ namespace llvm { iterator end() const { return Data + Length; } + const unsigned char *bytes_begin() const { + return reinterpret_cast(begin()); + } + const unsigned char *bytes_end() const { + return reinterpret_cast(end()); + } + /// @} /// @name String Operations /// @{ diff --git a/include/llvm/ADT/TinyPtrVector.h b/include/llvm/ADT/TinyPtrVector.h index e158f9d..f29608f 100644 --- a/include/llvm/ADT/TinyPtrVector.h +++ b/include/llvm/ADT/TinyPtrVector.h @@ -27,9 +27,12 @@ class TinyPtrVector { public: typedef llvm::SmallVector VecTy; typedef typename VecTy::value_type value_type; + typedef llvm::PointerUnion PtrUnion; - llvm::PointerUnion Val; +private: + PtrUnion Val; +public: TinyPtrVector() {} ~TinyPtrVector() { if (VecTy *V = Val.template dyn_cast()) @@ -96,6 +99,14 @@ public: return *this; } + /// Constructor from an ArrayRef. + /// + /// This also is a constructor for individual array elements due to the single + /// element constructor for ArrayRef. + explicit TinyPtrVector(ArrayRef Elts) + : Val(Elts.size() == 1 ? PtrUnion(Elts[0]) + : PtrUnion(new VecTy(Elts.begin(), Elts.end()))) {} + // implicit conversion operator to ArrayRef. operator ArrayRef() const { if (Val.isNull()) @@ -105,6 +116,15 @@ public: return *Val.template get(); } + // implicit conversion operator to MutableArrayRef. + operator MutableArrayRef() { + if (Val.isNull()) + return None; + if (Val.template is()) + return *Val.getAddrOfPtr1(); + return *Val.template get(); + } + bool empty() const { // This vector can be empty if it contains no element, or if it // contains a pointer to an empty vector. diff --git a/include/llvm/ADT/Triple.h b/include/llvm/ADT/Triple.h index fbc19f8..886f6fb 100644 --- a/include/llvm/ADT/Triple.h +++ b/include/llvm/ADT/Triple.h @@ -50,6 +50,7 @@ public: armeb, // ARM (big endian): armeb aarch64, // AArch64 (little endian): aarch64 aarch64_be, // AArch64 (big endian): aarch64_be + bpf, // eBPF or extended BPF or 64-bit BPF (little endian) hexagon, // Hexagon: hexagon mips, // MIPS: mips, mipsallegrex mipsel, // MIPSEL: mipsel, mipsallegrexel @@ -60,6 +61,7 @@ public: ppc64, // PPC64: powerpc64, ppu ppc64le, // PPC64LE: powerpc64le r600, // R600: AMD GPUs HD2XXX - HD6XXX + amdgcn, // AMDGCN: AMD GCN GPUs sparc, // Sparc: sparc sparcv9, // Sparcv9: Sparcv9 systemz, // SystemZ: s390x @@ -138,7 +140,9 @@ public: Bitrig, AIX, CUDA, // NVIDIA CUDA - NVCL // NVIDIA OpenCL + NVCL, // NVIDIA OpenCL + AMDHSA, // AMD HSA Runtime + PS4 }; enum EnvironmentType { UnknownEnvironment, @@ -198,6 +202,13 @@ public: Triple(const Twine &ArchStr, const Twine &VendorStr, const Twine &OSStr, const Twine &EnvironmentStr); + bool operator==(const Triple &Other) const { + return Arch == Other.Arch && SubArch == Other.SubArch && + Vendor == Other.Vendor && OS == Other.OS && + Environment == Other.Environment && + ObjectFormat == Other.ObjectFormat; + } + /// @} /// @name Normalization /// @{ @@ -208,6 +219,9 @@ public: /// common case in which otherwise valid components are in the wrong order. static std::string normalize(StringRef Str); + /// \brief Return the normalized form of this triple's string. + std::string normalize() const { return normalize(Data); } + /// @} /// @name Typed Component Access /// @{ @@ -332,6 +346,12 @@ public: return false; } + bool isOSVersionLT(const Triple &Other) const { + unsigned RHS[3]; + Other.getOSVersion(RHS[0], RHS[1], RHS[2]); + return isOSVersionLT(RHS[0], RHS[1], RHS[2]); + } + /// isMacOSXVersionLT - Comparison function for checking OS X version /// compatibility, which handles supporting skewed version numbering schemes /// used by the "darwin" triples. @@ -364,10 +384,28 @@ public: return isMacOSX() || isiOS(); } + bool isOSNetBSD() const { + return getOS() == Triple::NetBSD; + } + + bool isOSOpenBSD() const { + return getOS() == Triple::OpenBSD; + } + bool isOSFreeBSD() const { return getOS() == Triple::FreeBSD; } + bool isOSDragonFly() const { return getOS() == Triple::DragonFly; } + + bool isOSSolaris() const { + return getOS() == Triple::Solaris; + } + + bool isOSBitrig() const { + return getOS() == Triple::Bitrig; + } + bool isWindowsMSVCEnvironment() const { return getOS() == Triple::Win32 && (getEnvironment() == Triple::UnknownEnvironment || @@ -403,7 +441,7 @@ public: /// \brief Tests whether the OS is Windows. bool isOSWindows() const { - return getOS() == Triple::Win32 || isOSCygMing(); + return getOS() == Triple::Win32; } /// \brief Tests whether the OS is NaCl (Native Client) @@ -431,6 +469,19 @@ public: return getObjectFormat() == Triple::MachO; } + /// \brief Tests whether the target is the PS4 CPU + bool isPS4CPU() const { + return getArch() == Triple::x86_64 && + getVendor() == Triple::SCEI && + getOS() == Triple::PS4; + } + + /// \brief Tests whether the target is the PS4 platform + bool isPS4() const { + return getVendor() == Triple::SCEI && + getOS() == Triple::PS4; + } + /// @} /// @name Mutators /// @{ diff --git a/include/llvm/ADT/Twine.h b/include/llvm/ADT/Twine.h index 77d92b4..9e9a4e1 100644 --- a/include/llvm/ADT/Twine.h +++ b/include/llvm/ADT/Twine.h @@ -80,7 +80,7 @@ namespace llvm { /// StringRef) codegen as desired. class Twine { /// NodeKind - Represent the type of an argument. - enum NodeKind { + enum NodeKind : unsigned char { /// An empty string; the result of concatenating anything with it is also /// empty. NullKind, @@ -153,12 +153,10 @@ namespace llvm { /// RHS - The suffix in the concatenation, which may be uninitialized for /// Null or Empty kinds. Child RHS; - // enums stored as unsigned chars to save on space while some compilers - // don't support specifying the backing type for an enum /// LHSKind - The NodeKind of the left hand side, \see getLHSKind(). - unsigned char LHSKind; + NodeKind LHSKind; /// RHSKind - The NodeKind of the right hand side, \see getRHSKind(). - unsigned char RHSKind; + NodeKind RHSKind; private: /// Construct a nullary twine; the kind must be NullKind or EmptyKind. @@ -184,7 +182,7 @@ namespace llvm { /// Since the intended use of twines is as temporary objects, assignments /// when concatenating might cause undefined behavior or stack corruptions - Twine &operator=(const Twine &Other) LLVM_DELETED_FUNCTION; + Twine &operator=(const Twine &Other) = delete; /// isNull - Check for the null twine. bool isNull() const { @@ -238,10 +236,10 @@ namespace llvm { } /// getLHSKind - Get the NodeKind of the left-hand side. - NodeKind getLHSKind() const { return (NodeKind) LHSKind; } + NodeKind getLHSKind() const { return LHSKind; } /// getRHSKind - Get the NodeKind of the right-hand side. - NodeKind getRHSKind() const { return (NodeKind) RHSKind; } + NodeKind getRHSKind() const { return RHSKind; } /// printOneChild - Print one child from a twine. void printOneChild(raw_ostream &OS, Child Ptr, NodeKind Kind) const; diff --git a/include/llvm/ADT/ilist.h b/include/llvm/ADT/ilist.h index 8c19a6f..a7b9306 100644 --- a/include/llvm/ADT/ilist.h +++ b/include/llvm/ADT/ilist.h @@ -237,14 +237,14 @@ public: // These are to catch errors when people try to use them as random access // iterators. template -void operator-(int, ilist_iterator) LLVM_DELETED_FUNCTION; +void operator-(int, ilist_iterator) = delete; template -void operator-(ilist_iterator,int) LLVM_DELETED_FUNCTION; +void operator-(ilist_iterator,int) = delete; template -void operator+(int, ilist_iterator) LLVM_DELETED_FUNCTION; +void operator+(int, ilist_iterator) = delete; template -void operator+(ilist_iterator,int) LLVM_DELETED_FUNCTION; +void operator+(ilist_iterator,int) = delete; // operator!=/operator== - Allow mixed comparisons without dereferencing // the iterator, which could very likely be pointing to end(). @@ -332,8 +332,8 @@ class iplist : public Traits { // No fundamental reason why iplist can't be copyable, but the default // copy/copy-assign won't do. - iplist(const iplist &) LLVM_DELETED_FUNCTION; - void operator=(const iplist &) LLVM_DELETED_FUNCTION; + iplist(const iplist &) = delete; + void operator=(const iplist &) = delete; public: typedef NodeTy *pointer; diff --git a/include/llvm/ADT/iterator.h b/include/llvm/ADT/iterator.h index 56041db..e2c9e5e 100644 --- a/include/llvm/ADT/iterator.h +++ b/include/llvm/ADT/iterator.h @@ -10,8 +10,8 @@ #ifndef LLVM_ADT_ITERATOR_H #define LLVM_ADT_ITERATOR_H -#include #include +#include namespace llvm { diff --git a/include/llvm/ADT/iterator_range.h b/include/llvm/ADT/iterator_range.h index ecaf4a2..523a86f 100644 --- a/include/llvm/ADT/iterator_range.h +++ b/include/llvm/ADT/iterator_range.h @@ -32,7 +32,6 @@ class iterator_range { IteratorT begin_iterator, end_iterator; public: - iterator_range() {} iterator_range(IteratorT begin_iterator, IteratorT end_iterator) : begin_iterator(std::move(begin_iterator)), end_iterator(std::move(end_iterator)) {} diff --git a/include/llvm/Analysis/AliasAnalysis.h b/include/llvm/Analysis/AliasAnalysis.h index 9bfa045..763f372 100644 --- a/include/llvm/Analysis/AliasAnalysis.h +++ b/include/llvm/Analysis/AliasAnalysis.h @@ -502,7 +502,7 @@ public: /// /// canBasicBlockModify - Return true if it is possible for execution of the - /// specified basic block to modify the value pointed to by Ptr. + /// specified basic block to modify the location Loc. bool canBasicBlockModify(const BasicBlock &BB, const Location &Loc); /// canBasicBlockModify - A convenience wrapper. @@ -510,17 +510,20 @@ public: return canBasicBlockModify(BB, Location(P, Size)); } - /// canInstructionRangeModify - Return true if it is possible for the - /// execution of the specified instructions to modify the value pointed to by - /// Ptr. The instructions to consider are all of the instructions in the - /// range of [I1,I2] INCLUSIVE. I1 and I2 must be in the same basic block. - bool canInstructionRangeModify(const Instruction &I1, const Instruction &I2, - const Location &Loc); - - /// canInstructionRangeModify - A convenience wrapper. - bool canInstructionRangeModify(const Instruction &I1, const Instruction &I2, - const Value *Ptr, uint64_t Size) { - return canInstructionRangeModify(I1, I2, Location(Ptr, Size)); + /// canInstructionRangeModRef - Return true if it is possible for the + /// execution of the specified instructions to mod\ref (according to the + /// mode) the location Loc. The instructions to consider are all + /// of the instructions in the range of [I1,I2] INCLUSIVE. + /// I1 and I2 must be in the same basic block. + bool canInstructionRangeModRef(const Instruction &I1, + const Instruction &I2, const Location &Loc, + const ModRefResult Mode); + + /// canInstructionRangeModRef - A convenience wrapper. + bool canInstructionRangeModRef(const Instruction &I1, + const Instruction &I2, const Value *Ptr, + uint64_t Size, const ModRefResult Mode) { + return canInstructionRangeModRef(I1, I2, Location(Ptr, Size), Mode); } //===--------------------------------------------------------------------===// diff --git a/include/llvm/Analysis/AliasSetTracker.h b/include/llvm/Analysis/AliasSetTracker.h index 036d58d..afa7e6f 100644 --- a/include/llvm/Analysis/AliasSetTracker.h +++ b/include/llvm/Analysis/AliasSetTracker.h @@ -226,8 +226,8 @@ private: AccessTy(NoModRef), AliasTy(MustAlias), Volatile(false) { } - AliasSet(const AliasSet &AS) LLVM_DELETED_FUNCTION; - void operator=(const AliasSet &AS) LLVM_DELETED_FUNCTION; + AliasSet(const AliasSet &AS) = delete; + void operator=(const AliasSet &AS) = delete; PointerRec *getSomePointer() const { return PtrList; diff --git a/include/llvm/Analysis/AssumptionCache.h b/include/llvm/Analysis/AssumptionCache.h new file mode 100644 index 0000000..fc1393f --- /dev/null +++ b/include/llvm/Analysis/AssumptionCache.h @@ -0,0 +1,183 @@ +//===- llvm/Analysis/AssumptionCache.h - Track @llvm.assume ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains a pass that keeps track of @llvm.assume intrinsics in +// the functions of a module (allowing assumptions within any function to be +// found cheaply by other parts of the optimizer). +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_ASSUMPTIONCACHE_H +#define LLVM_ANALYSIS_ASSUMPTIONCACHE_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/ValueHandle.h" +#include "llvm/Pass.h" +#include + +namespace llvm { + +// FIXME: Replace this brittle forward declaration with the include of the new +// PassManager.h when doing so doesn't break the PassManagerBuilder. +template class AnalysisManager; +class PreservedAnalyses; + +/// \brief A cache of @llvm.assume calls within a function. +/// +/// This cache provides fast lookup of assumptions within a function by caching +/// them and amortizing the cost of scanning for them across all queries. The +/// cache is also conservatively self-updating so that it will never return +/// incorrect results about a function even as the function is being mutated. +/// However, flushing the cache and rebuilding it (or explicitly updating it) +/// may allow it to discover new assumptions. +class AssumptionCache { + /// \brief The function for which this cache is handling assumptions. + /// + /// We track this to lazily populate our assumptions. + Function &F; + + /// \brief Vector of weak value handles to calls of the @llvm.assume + /// intrinsic. + SmallVector AssumeHandles; + + /// \brief Flag tracking whether we have scanned the function yet. + /// + /// We want to be as lazy about this as possible, and so we scan the function + /// at the last moment. + bool Scanned; + + /// \brief Scan the function for assumptions and add them to the cache. + void scanFunction(); + +public: + /// \brief Construct an AssumptionCache from a function by scanning all of + /// its instructions. + AssumptionCache(Function &F) : F(F), Scanned(false) {} + + /// \brief Add an @llvm.assume intrinsic to this function's cache. + /// + /// The call passed in must be an instruction within this fuction and must + /// not already be in the cache. + void registerAssumption(CallInst *CI); + + /// \brief Clear the cache of @llvm.assume intrinsics for a function. + /// + /// It will be re-scanned the next time it is requested. + void clear() { + AssumeHandles.clear(); + Scanned = false; + } + + /// \brief Access the list of assumption handles currently tracked for this + /// fuction. + /// + /// Note that these produce weak handles that may be null. The caller must + /// handle that case. + /// FIXME: We should replace this with pointee_iterator> + /// when we can write that to filter out the null values. Then caller code + /// will become simpler. + MutableArrayRef assumptions() { + if (!Scanned) + scanFunction(); + return AssumeHandles; + } +}; + +/// \brief A function analysis which provides an \c AssumptionCache. +/// +/// This analysis is intended for use with the new pass manager and will vend +/// assumption caches for a given function. +class AssumptionAnalysis { + static char PassID; + +public: + typedef AssumptionCache Result; + + /// \brief Opaque, unique identifier for this analysis pass. + static void *ID() { return (void *)&PassID; } + + /// \brief Provide a name for the analysis for debugging and logging. + static StringRef name() { return "AssumptionAnalysis"; } + + AssumptionAnalysis() {} + AssumptionAnalysis(const AssumptionAnalysis &Arg) {} + AssumptionAnalysis(AssumptionAnalysis &&Arg) {} + AssumptionAnalysis &operator=(const AssumptionAnalysis &RHS) { return *this; } + AssumptionAnalysis &operator=(AssumptionAnalysis &&RHS) { return *this; } + + AssumptionCache run(Function &F) { return AssumptionCache(F); } +}; + +/// \brief Printer pass for the \c AssumptionAnalysis results. +class AssumptionPrinterPass { + raw_ostream &OS; + +public: + explicit AssumptionPrinterPass(raw_ostream &OS) : OS(OS) {} + PreservedAnalyses run(Function &F, AnalysisManager *AM); + + static StringRef name() { return "AssumptionPrinterPass"; } +}; + +/// \brief An immutable pass that tracks lazily created \c AssumptionCache +/// objects. +/// +/// This is essentially a workaround for the legacy pass manager's weaknesses +/// which associates each assumption cache with Function and clears it if the +/// function is deleted. The nature of the AssumptionCache is that it is not +/// invalidated by any changes to the function body and so this is sufficient +/// to be conservatively correct. +class AssumptionCacheTracker : public ImmutablePass { + /// A callback value handle applied to function objects, which we use to + /// delete our cache of intrinsics for a function when it is deleted. + class FunctionCallbackVH : public CallbackVH { + AssumptionCacheTracker *ACT; + void deleted() override; + + public: + typedef DenseMapInfo DMI; + + FunctionCallbackVH(Value *V, AssumptionCacheTracker *ACT = nullptr) + : CallbackVH(V), ACT(ACT) {} + }; + + friend FunctionCallbackVH; + + typedef DenseMap, + FunctionCallbackVH::DMI> FunctionCallsMap; + FunctionCallsMap AssumptionCaches; + +public: + /// \brief Get the cached assumptions for a function. + /// + /// If no assumptions are cached, this will scan the function. Otherwise, the + /// existing cache will be returned. + AssumptionCache &getAssumptionCache(Function &F); + + AssumptionCacheTracker(); + ~AssumptionCacheTracker(); + + void releaseMemory() override { AssumptionCaches.shrink_and_clear(); } + + void verifyAnalysis() const override; + bool doFinalization(Module &) override { + verifyAnalysis(); + return false; + } + + static char ID; // Pass identification, replacement for typeid +}; + +} // end namespace llvm + +#endif diff --git a/include/llvm/Analysis/AssumptionTracker.h b/include/llvm/Analysis/AssumptionTracker.h deleted file mode 100644 index 5a050a8..0000000 --- a/include/llvm/Analysis/AssumptionTracker.h +++ /dev/null @@ -1,128 +0,0 @@ -//===- llvm/Analysis/AssumptionTracker.h - Track @llvm.assume ---*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file contains a pass that keeps track of @llvm.assume intrinsics in -// the functions of a module (allowing assumptions within any function to be -// found cheaply by other parts of the optimizer). -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_ANALYSIS_ASSUMPTIONTRACKER_H -#define LLVM_ANALYSIS_ASSUMPTIONTRACKER_H - -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/DenseSet.h" -#include "llvm/ADT/SmallSet.h" -#include "llvm/IR/Function.h" -#include "llvm/IR/Instructions.h" -#include "llvm/IR/ValueHandle.h" -#include "llvm/Pass.h" -#include - -namespace llvm { - -/// An immutable pass that tracks @llvm.assume intrinsics in a module. -class AssumptionTracker : public ImmutablePass { - /// A callback value handle applied to function objects, which we use to - /// delete our cache of intrinsics for a function when it is deleted. - class FunctionCallbackVH : public CallbackVH { - AssumptionTracker *AT; - void deleted() override; - - public: - typedef DenseMapInfo DMI; - - FunctionCallbackVH(Value *V, AssumptionTracker *AT = nullptr) - : CallbackVH(V), AT(AT) {} - }; - - /// A callback value handle applied to call instructions, which keeps - /// track of the call's parent function so that we can remove a - /// assumption intrinsic call from our cache when the instruction is - /// deleted. - class CallCallbackVH : public CallbackVH { - AssumptionTracker *AT; - void deleted() override; - - // We store the function here because we need it to lookup the set - // containing this handle when the underlying CallInst is being deleted. - Function *F; - - public: - typedef DenseMapInfo DMI; - - CallCallbackVH(Instruction *I, AssumptionTracker *AT = nullptr) - : CallbackVH(I), AT(AT), F(nullptr) { - if (I != DMI::getEmptyKey() && I != DMI::getTombstoneKey()) - F = I->getParent()->getParent(); - } - - operator CallInst*() const { - Value *V = getValPtr(); - if (V == DMI::getEmptyKey() || V == DMI::getTombstoneKey()) - return reinterpret_cast(V); - - return cast(V); - } - - CallInst *operator->() const { return cast(getValPtr()); } - CallInst &operator*() const { return *cast(getValPtr()); } - }; - - friend FunctionCallbackVH; - friend CallCallbackVH; - - // FIXME: SmallSet might be better here, but it currently has no iterators. - typedef DenseSet CallHandleSet; - typedef DenseMap, - FunctionCallbackVH::DMI> FunctionCallsMap; - FunctionCallsMap CachedAssumeCalls; - - /// Scan the provided function for @llvm.assume intrinsic calls. Returns an - /// iterator to the set for this function in the CachedAssumeCalls map. - FunctionCallsMap::iterator scanFunction(Function *F); - -public: - /// Remove the cache of @llvm.assume intrinsics for the given function. - void forgetCachedAssumptions(Function *F); - - /// Add an @llvm.assume intrinsic to the cache for its parent function. - void registerAssumption(CallInst *CI); - - typedef CallHandleSet::iterator assumption_iterator; - typedef iterator_range assumption_range; - - inline assumption_range assumptions(Function *F) { - FunctionCallsMap::iterator I = CachedAssumeCalls.find_as(F); - if (I == CachedAssumeCalls.end()) { - I = scanFunction(F); - } - - return assumption_range(I->second->begin(), I->second->end()); - } - - AssumptionTracker(); - ~AssumptionTracker(); - - void releaseMemory() override { - CachedAssumeCalls.shrink_and_clear(); - } - - void verifyAnalysis() const override; - bool doFinalization(Module &) override { - verifyAnalysis(); - return false; - } - - static char ID; // Pass identification, replacement for typeid -}; - -} // end namespace llvm - -#endif diff --git a/include/llvm/Analysis/BranchProbabilityInfo.h b/include/llvm/Analysis/BranchProbabilityInfo.h index 4414c84..89eef68 100644 --- a/include/llvm/Analysis/BranchProbabilityInfo.h +++ b/include/llvm/Analysis/BranchProbabilityInfo.h @@ -111,6 +111,10 @@ public: void setEdgeWeight(const BasicBlock *Src, unsigned IndexInSuccessors, uint32_t Weight); + static uint32_t getBranchWeightStackProtector(bool IsLikely) { + return IsLikely ? (1u << 20) - 1 : 1; + } + private: // Since we allow duplicate edges from one basic block to another, we use // a pair (PredBlock and an index in the successors) to specify an edge. diff --git a/include/llvm/Analysis/CGSCCPassManager.h b/include/llvm/Analysis/CGSCCPassManager.h index 1533b36..0d4fe93 100644 --- a/include/llvm/Analysis/CGSCCPassManager.h +++ b/include/llvm/Analysis/CGSCCPassManager.h @@ -21,135 +21,25 @@ #ifndef LLVM_ANALYSIS_CGSCCPASSMANAGER_H #define LLVM_ANALYSIS_CGSCCPASSMANAGER_H -#include "llvm/IR/PassManager.h" #include "llvm/Analysis/LazyCallGraph.h" +#include "llvm/IR/PassManager.h" namespace llvm { -class CGSCCAnalysisManager; - -class CGSCCPassManager { -public: - // We have to explicitly define all the special member functions because MSVC - // refuses to generate them. - CGSCCPassManager() {} - CGSCCPassManager(CGSCCPassManager &&Arg) : Passes(std::move(Arg.Passes)) {} - CGSCCPassManager &operator=(CGSCCPassManager &&RHS) { - Passes = std::move(RHS.Passes); - return *this; - } - - /// \brief Run all of the CGSCC passes in this pass manager over a SCC. - PreservedAnalyses run(LazyCallGraph::SCC *C, - CGSCCAnalysisManager *AM = nullptr); - - template void addPass(CGSCCPassT Pass) { - Passes.emplace_back(new CGSCCPassModel(std::move(Pass))); - } - - static StringRef name() { return "CGSCCPassManager"; } - -private: - // Pull in the concept type and model template specialized for SCCs. - typedef detail::PassConcept - CGSCCPassConcept; - template - struct CGSCCPassModel - : detail::PassModel { - CGSCCPassModel(PassT Pass) - : detail::PassModel( - std::move(Pass)) {} - }; - - CGSCCPassManager(const CGSCCPassManager &) LLVM_DELETED_FUNCTION; - CGSCCPassManager &operator=(const CGSCCPassManager &) LLVM_DELETED_FUNCTION; - - std::vector> Passes; -}; - -/// \brief A function analysis manager to coordinate and cache analyses run over -/// a module. -class CGSCCAnalysisManager : public detail::AnalysisManagerBase< - CGSCCAnalysisManager, LazyCallGraph::SCC *> { - friend class detail::AnalysisManagerBase; - typedef detail::AnalysisManagerBase BaseT; - typedef BaseT::ResultConceptT ResultConceptT; - typedef BaseT::PassConceptT PassConceptT; - -public: - // Most public APIs are inherited from the CRTP base class. - - // We have to explicitly define all the special member functions because MSVC - // refuses to generate them. - CGSCCAnalysisManager() {} - CGSCCAnalysisManager(CGSCCAnalysisManager &&Arg) - : BaseT(std::move(static_cast(Arg))), - CGSCCAnalysisResults(std::move(Arg.CGSCCAnalysisResults)) {} - CGSCCAnalysisManager &operator=(CGSCCAnalysisManager &&RHS) { - BaseT::operator=(std::move(static_cast(RHS))); - CGSCCAnalysisResults = std::move(RHS.CGSCCAnalysisResults); - return *this; - } - - /// \brief Returns true if the analysis manager has an empty results cache. - bool empty() const; - - /// \brief Clear the function analysis result cache. - /// - /// This routine allows cleaning up when the set of functions itself has - /// potentially changed, and thus we can't even look up a a result and - /// invalidate it directly. Notably, this does *not* call invalidate - /// functions as there is nothing to be done for them. - void clear(); - -private: - CGSCCAnalysisManager(const CGSCCAnalysisManager &) LLVM_DELETED_FUNCTION; - CGSCCAnalysisManager & - operator=(const CGSCCAnalysisManager &) LLVM_DELETED_FUNCTION; - - /// \brief Get a function pass result, running the pass if necessary. - ResultConceptT &getResultImpl(void *PassID, LazyCallGraph::SCC *C); - - /// \brief Get a cached function pass result or return null. - ResultConceptT *getCachedResultImpl(void *PassID, - LazyCallGraph::SCC *C) const; - - /// \brief Invalidate a function pass result. - void invalidateImpl(void *PassID, LazyCallGraph::SCC *C); - - /// \brief Invalidate the results for a function.. - void invalidateImpl(LazyCallGraph::SCC *C, const PreservedAnalyses &PA); +/// \brief The CGSCC pass manager. +/// +/// See the documentation for the PassManager template for details. It runs +/// a sequency of SCC passes over each SCC that the manager is run over. This +/// typedef serves as a convenient way to refer to this construct. +typedef PassManager CGSCCPassManager; - /// \brief List of function analysis pass IDs and associated concept pointers. - /// - /// Requires iterators to be valid across appending new entries and arbitrary - /// erases. Provides both the pass ID and concept pointer such that it is - /// half of a bijection and provides storage for the actual result concept. - typedef std::list< - std::pair>>> CGSCCAnalysisResultListT; - - /// \brief Map type from function pointer to our custom list type. - typedef DenseMap - CGSCCAnalysisResultListMapT; - - /// \brief Map from function to a list of function analysis results. - /// - /// Provides linear time removal of all analysis results for a function and - /// the ultimate storage for a particular cached analysis result. - CGSCCAnalysisResultListMapT CGSCCAnalysisResultLists; - - /// \brief Map type from a pair of analysis ID and function pointer to an - /// iterator into a particular result list. - typedef DenseMap, - CGSCCAnalysisResultListT::iterator> CGSCCAnalysisResultMapT; - - /// \brief Map from an analysis ID and function to a particular cached - /// analysis result. - CGSCCAnalysisResultMapT CGSCCAnalysisResults; -}; +/// \brief The CGSCC analysis manager. +/// +/// See the documentation for the AnalysisManager template for detail +/// documentation. This typedef serves as a convenient way to refer to this +/// construct in the adaptors and proxies used to integrate this into the larger +/// pass manager infrastructure. +typedef AnalysisManager CGSCCAnalysisManager; /// \brief A module analysis which acts as a proxy for a CGSCC analysis /// manager. @@ -187,7 +77,7 @@ public: /// Regardless of whether this analysis is marked as preserved, all of the /// analyses in the \c CGSCCAnalysisManager are potentially invalidated /// based on the set of preserved analyses. - bool invalidate(Module *M, const PreservedAnalyses &PA); + bool invalidate(Module &M, const PreservedAnalyses &PA); private: CGSCCAnalysisManager *CGAM; @@ -195,12 +85,13 @@ public: static void *ID() { return (void *)&PassID; } + static StringRef name() { return "CGSCCAnalysisManagerModuleProxy"; } + explicit CGSCCAnalysisManagerModuleProxy(CGSCCAnalysisManager &CGAM) : CGAM(&CGAM) {} // We have to explicitly define all the special member functions because MSVC // refuses to generate them. - CGSCCAnalysisManagerModuleProxy( - const CGSCCAnalysisManagerModuleProxy &Arg) + CGSCCAnalysisManagerModuleProxy(const CGSCCAnalysisManagerModuleProxy &Arg) : CGAM(Arg.CGAM) {} CGSCCAnalysisManagerModuleProxy(CGSCCAnalysisManagerModuleProxy &&Arg) : CGAM(std::move(Arg.CGAM)) {} @@ -219,7 +110,7 @@ public: /// In debug builds, it will also assert that the analysis manager is empty /// as no queries should arrive at the CGSCC analysis manager prior to /// this analysis being requested. - Result run(Module *M); + Result run(Module &M); private: static char PassID; @@ -257,7 +148,7 @@ public: const ModuleAnalysisManager &getManager() const { return *MAM; } /// \brief Handle invalidation by ignoring it, this pass is immutable. - bool invalidate(LazyCallGraph::SCC *) { return false; } + bool invalidate(LazyCallGraph::SCC &) { return false; } private: const ModuleAnalysisManager *MAM; @@ -265,12 +156,13 @@ public: static void *ID() { return (void *)&PassID; } + static StringRef name() { return "ModuleAnalysisManagerCGSCCProxy"; } + ModuleAnalysisManagerCGSCCProxy(const ModuleAnalysisManager &MAM) : MAM(&MAM) {} // We have to explicitly define all the special member functions because MSVC // refuses to generate them. - ModuleAnalysisManagerCGSCCProxy( - const ModuleAnalysisManagerCGSCCProxy &Arg) + ModuleAnalysisManagerCGSCCProxy(const ModuleAnalysisManagerCGSCCProxy &Arg) : MAM(Arg.MAM) {} ModuleAnalysisManagerCGSCCProxy(ModuleAnalysisManagerCGSCCProxy &&Arg) : MAM(std::move(Arg.MAM)) {} @@ -283,7 +175,7 @@ public: /// \brief Run the analysis pass and create our proxy result object. /// Nothing to see here, it just forwards the \c MAM reference into the /// result. - Result run(LazyCallGraph::SCC *) { return Result(*MAM); } + Result run(LazyCallGraph::SCC &) { return Result(*MAM); } private: static char PassID; @@ -323,7 +215,7 @@ public: } /// \brief Runs the CGSCC pass across every SCC in the module. - PreservedAnalyses run(Module *M, ModuleAnalysisManager *AM) { + PreservedAnalyses run(Module &M, ModuleAnalysisManager *AM) { assert(AM && "We need analyses to compute the call graph!"); // Setup the CGSCC analysis manager from its proxy. @@ -335,15 +227,17 @@ public: PreservedAnalyses PA = PreservedAnalyses::all(); for (LazyCallGraph::SCC &C : CG.postorder_sccs()) { - PreservedAnalyses PassPA = Pass.run(&C, &CGAM); + PreservedAnalyses PassPA = Pass.run(C, &CGAM); // We know that the CGSCC pass couldn't have invalidated any other // SCC's analyses (that's the contract of a CGSCC pass), so - // directly handle the CGSCC analysis manager's invalidation here. + // directly handle the CGSCC analysis manager's invalidation here. We + // also update the preserved set of analyses to reflect that invalidated + // analyses are now safe to preserve. // FIXME: This isn't quite correct. We need to handle the case where the // pass updated the CG, particularly some child of the current SCC, and // invalidate its analyses. - CGAM.invalidate(&C, PassPA); + PassPA = CGAM.invalidate(C, std::move(PassPA)); // Then intersect the preserved set so that invalidation of module // analyses will eventually occur when the module pass completes. @@ -409,7 +303,7 @@ public: /// Regardless of whether this analysis is marked as preserved, all of the /// analyses in the \c FunctionAnalysisManager are potentially invalidated /// based on the set of preserved analyses. - bool invalidate(LazyCallGraph::SCC *C, const PreservedAnalyses &PA); + bool invalidate(LazyCallGraph::SCC &C, const PreservedAnalyses &PA); private: FunctionAnalysisManager *FAM; @@ -417,6 +311,8 @@ public: static void *ID() { return (void *)&PassID; } + static StringRef name() { return "FunctionAnalysisManagerCGSCCProxy"; } + explicit FunctionAnalysisManagerCGSCCProxy(FunctionAnalysisManager &FAM) : FAM(&FAM) {} // We have to explicitly define all the special member functions because MSVC @@ -441,7 +337,7 @@ public: /// In debug builds, it will also assert that the analysis manager is empty /// as no queries should arrive at the function analysis manager prior to /// this analysis being requested. - Result run(LazyCallGraph::SCC *C); + Result run(LazyCallGraph::SCC &C); private: static char PassID; @@ -479,7 +375,7 @@ public: const CGSCCAnalysisManager &getManager() const { return *CGAM; } /// \brief Handle invalidation by ignoring it, this pass is immutable. - bool invalidate(Function *) { return false; } + bool invalidate(Function &) { return false; } private: const CGSCCAnalysisManager *CGAM; @@ -487,6 +383,8 @@ public: static void *ID() { return (void *)&PassID; } + static StringRef name() { return "CGSCCAnalysisManagerFunctionProxy"; } + CGSCCAnalysisManagerFunctionProxy(const CGSCCAnalysisManager &CGAM) : CGAM(&CGAM) {} // We have to explicitly define all the special member functions because MSVC @@ -505,7 +403,7 @@ public: /// \brief Run the analysis pass and create our proxy result object. /// Nothing to see here, it just forwards the \c CGAM reference into the /// result. - Result run(Function *) { return Result(*CGAM); } + Result run(Function &) { return Result(*CGAM); } private: static char PassID; @@ -531,7 +429,8 @@ public: : Pass(Arg.Pass) {} CGSCCToFunctionPassAdaptor(CGSCCToFunctionPassAdaptor &&Arg) : Pass(std::move(Arg.Pass)) {} - friend void swap(CGSCCToFunctionPassAdaptor &LHS, CGSCCToFunctionPassAdaptor &RHS) { + friend void swap(CGSCCToFunctionPassAdaptor &LHS, + CGSCCToFunctionPassAdaptor &RHS) { using std::swap; swap(LHS.Pass, RHS.Pass); } @@ -541,21 +440,23 @@ public: } /// \brief Runs the function pass across every function in the module. - PreservedAnalyses run(LazyCallGraph::SCC *C, CGSCCAnalysisManager *AM) { + PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager *AM) { FunctionAnalysisManager *FAM = nullptr; if (AM) // Setup the function analysis manager from its proxy. FAM = &AM->getResult(C).getManager(); PreservedAnalyses PA = PreservedAnalyses::all(); - for (LazyCallGraph::Node *N : *C) { - PreservedAnalyses PassPA = Pass.run(&N->getFunction(), FAM); + for (LazyCallGraph::Node *N : C) { + PreservedAnalyses PassPA = Pass.run(N->getFunction(), FAM); // We know that the function pass couldn't have invalidated any other // function's analyses (that's the contract of a function pass), so // directly handle the function analysis manager's invalidation here. + // Also, update the preserved analyses to reflect that once invalidated + // these can again be preserved. if (FAM) - FAM->invalidate(&N->getFunction(), PassPA); + PassPA = FAM->invalidate(N->getFunction(), std::move(PassPA)); // Then intersect the preserved set so that invalidation of module // analyses will eventually occur when the module pass completes. @@ -585,7 +486,6 @@ CGSCCToFunctionPassAdaptor createCGSCCToFunctionPassAdaptor(FunctionPassT Pass) { return std::move(CGSCCToFunctionPassAdaptor(std::move(Pass))); } - } #endif diff --git a/include/llvm/Analysis/CallGraph.h b/include/llvm/Analysis/CallGraph.h index 76d9073..64d288a 100644 --- a/include/llvm/Analysis/CallGraph.h +++ b/include/llvm/Analysis/CallGraph.h @@ -273,8 +273,8 @@ private: /// CalledFunctions array of this or other CallGraphNodes. unsigned NumReferences; - CallGraphNode(const CallGraphNode &) LLVM_DELETED_FUNCTION; - void operator=(const CallGraphNode &) LLVM_DELETED_FUNCTION; + CallGraphNode(const CallGraphNode &) = delete; + void operator=(const CallGraphNode &) = delete; void DropRef() { --NumReferences; } void AddRef() { ++NumReferences; } diff --git a/include/llvm/Analysis/CodeMetrics.h b/include/llvm/Analysis/CodeMetrics.h index 59502df..2f59691 100644 --- a/include/llvm/Analysis/CodeMetrics.h +++ b/include/llvm/Analysis/CodeMetrics.h @@ -20,7 +20,7 @@ #include "llvm/IR/CallSite.h" namespace llvm { -class AssumptionTracker; +class AssumptionCache; class BasicBlock; class Loop; class Function; @@ -93,13 +93,13 @@ struct CodeMetrics { /// \brief Collect a loop's ephemeral values (those used only by an assume /// or similar intrinsics in the loop). - static void collectEphemeralValues(const Loop *L, AssumptionTracker *AT, - SmallPtrSetImpl &EphValues); + static void collectEphemeralValues(const Loop *L, AssumptionCache *AC, + SmallPtrSetImpl &EphValues); /// \brief Collect a functions's ephemeral values (those used only by an /// assume or similar intrinsics in the function). - static void collectEphemeralValues(const Function *L, AssumptionTracker *AT, - SmallPtrSetImpl &EphValues); + static void collectEphemeralValues(const Function *L, AssumptionCache *AC, + SmallPtrSetImpl &EphValues); }; } diff --git a/include/llvm/Analysis/DependenceAnalysis.h b/include/llvm/Analysis/DependenceAnalysis.h index 1041e3f..e01aa54 100644 --- a/include/llvm/Analysis/DependenceAnalysis.h +++ b/include/llvm/Analysis/DependenceAnalysis.h @@ -278,8 +278,8 @@ namespace llvm { /// DependenceAnalysis - This class is the main dependence-analysis driver. /// class DependenceAnalysis : public FunctionPass { - void operator=(const DependenceAnalysis &) LLVM_DELETED_FUNCTION; - DependenceAnalysis(const DependenceAnalysis &) LLVM_DELETED_FUNCTION; + void operator=(const DependenceAnalysis &) = delete; + DependenceAnalysis(const DependenceAnalysis &) = delete; public: /// depends - Tests for a dependence between the Src and Dst instructions. /// Returns NULL if no dependence; otherwise, returns a Dependence (or a diff --git a/include/llvm/Analysis/FindUsedTypes.h b/include/llvm/Analysis/FindUsedTypes.h deleted file mode 100644 index 574c947..0000000 --- a/include/llvm/Analysis/FindUsedTypes.h +++ /dev/null @@ -1,66 +0,0 @@ -//===- llvm/Analysis/FindUsedTypes.h - Find all Types in use ----*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This pass is used to seek out all of the types in use by the program. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_ANALYSIS_FINDUSEDTYPES_H -#define LLVM_ANALYSIS_FINDUSEDTYPES_H - -#include "llvm/ADT/SetVector.h" -#include "llvm/Pass.h" - -namespace llvm { - -class Type; -class Value; - -class FindUsedTypes : public ModulePass { - SetVector UsedTypes; -public: - static char ID; // Pass identification, replacement for typeid - FindUsedTypes() : ModulePass(ID) { - initializeFindUsedTypesPass(*PassRegistry::getPassRegistry()); - } - - /// getTypes - After the pass has been run, return the set containing all of - /// the types used in the module. - /// - const SetVector &getTypes() const { return UsedTypes; } - - /// Print the types found in the module. If the optional Module parameter is - /// passed in, then the types are printed symbolically if possible, using the - /// symbol table from the module. - /// - void print(raw_ostream &o, const Module *M) const override; - -private: - /// IncorporateType - Incorporate one type and all of its subtypes into the - /// collection of used types. - /// - void IncorporateType(Type *Ty); - - /// IncorporateValue - Incorporate all of the types used by this value. - /// - void IncorporateValue(const Value *V); - -public: - /// run - This incorporates all types used by the specified module - bool runOnModule(Module &M) override; - - /// getAnalysisUsage - We do not modify anything. - void getAnalysisUsage(AnalysisUsage &AU) const override { - AU.setPreservesAll(); - } -}; - -} // End llvm namespace - -#endif diff --git a/include/llvm/Analysis/FunctionTargetTransformInfo.h b/include/llvm/Analysis/FunctionTargetTransformInfo.h deleted file mode 100644 index c1654cc..0000000 --- a/include/llvm/Analysis/FunctionTargetTransformInfo.h +++ /dev/null @@ -1,49 +0,0 @@ -//===- llvm/Analysis/FunctionTargetTransformInfo.h --------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This pass wraps a TargetTransformInfo in a FunctionPass so that it can -// forward along the current Function so that we can make target specific -// decisions based on the particular subtarget specified for each Function. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_ANALYSIS_FUNCTIONTARGETTRANSFORMINFO_H -#define LLVM_ANALYSIS_FUNCTIONTARGETTRANSFORMINFO_H - -#include "llvm/Pass.h" -#include "TargetTransformInfo.h" - -namespace llvm { -class FunctionTargetTransformInfo final : public FunctionPass { -private: - const Function *Fn; - const TargetTransformInfo *TTI; - - FunctionTargetTransformInfo(const FunctionTargetTransformInfo &) - LLVM_DELETED_FUNCTION; - void operator=(const FunctionTargetTransformInfo &) LLVM_DELETED_FUNCTION; - -public: - static char ID; - FunctionTargetTransformInfo(); - - // Implementation boilerplate. - void getAnalysisUsage(AnalysisUsage &AU) const override; - void releaseMemory() override; - bool runOnFunction(Function &F) override; - - // Shimmed functions from TargetTransformInfo. - void - getUnrollingPreferences(Loop *L, - TargetTransformInfo::UnrollingPreferences &UP) const { - TTI->getUnrollingPreferences(Fn, L, UP); - } -}; -} -#endif diff --git a/include/llvm/Analysis/InlineCost.h b/include/llvm/Analysis/InlineCost.h index 81795ba..fdee9f8 100644 --- a/include/llvm/Analysis/InlineCost.h +++ b/include/llvm/Analysis/InlineCost.h @@ -19,11 +19,11 @@ #include namespace llvm { -class AssumptionTracker; +class AssumptionCacheTracker; class CallSite; class DataLayout; class Function; -class TargetTransformInfo; +class TargetTransformInfoWrapperPass; namespace InlineConstants { // Various magic constants used to adjust heuristics. @@ -77,7 +77,7 @@ public: } /// \brief Test whether the inline cost is low enough for inlining. - LLVM_EXPLICIT operator bool() const { + explicit operator bool() const { return Cost < Threshold; } @@ -100,8 +100,8 @@ public: /// \brief Cost analyzer used by inliner. class InlineCostAnalysis : public CallGraphSCCPass { - const TargetTransformInfo *TTI; - AssumptionTracker *AT; + TargetTransformInfoWrapperPass *TTIWP; + AssumptionCacheTracker *ACT; public: static char ID; diff --git a/include/llvm/Analysis/InstructionSimplify.h b/include/llvm/Analysis/InstructionSimplify.h index 51f6e85..1ebf981 100644 --- a/include/llvm/Analysis/InstructionSimplify.h +++ b/include/llvm/Analysis/InstructionSimplify.h @@ -37,7 +37,7 @@ namespace llvm { template class ArrayRef; - class AssumptionTracker; + class AssumptionCache; class DominatorTree; class Instruction; class DataLayout; @@ -52,7 +52,7 @@ namespace llvm { const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, - AssumptionTracker *AT = nullptr, + AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr); /// SimplifySubInst - Given operands for a Sub, see if we can @@ -61,35 +61,34 @@ namespace llvm { const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, - AssumptionTracker *AT = nullptr, + AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr); /// Given operands for an FAdd, see if we can fold the result. If not, this /// returns null. Value *SimplifyFAddInst(Value *LHS, Value *RHS, FastMathFlags FMF, - const DataLayout *TD = nullptr, - const TargetLibraryInfo *TLI = nullptr, - const DominatorTree *DT = nullptr, - AssumptionTracker *AT = nullptr, - const Instruction *CxtI = nullptr); + const DataLayout *TD = nullptr, + const TargetLibraryInfo *TLI = nullptr, + const DominatorTree *DT = nullptr, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr); /// Given operands for an FSub, see if we can fold the result. If not, this /// returns null. Value *SimplifyFSubInst(Value *LHS, Value *RHS, FastMathFlags FMF, - const DataLayout *TD = nullptr, - const TargetLibraryInfo *TLI = nullptr, - const DominatorTree *DT = nullptr, - AssumptionTracker *AT = nullptr, - const Instruction *CxtI = nullptr); + const DataLayout *TD = nullptr, + const TargetLibraryInfo *TLI = nullptr, + const DominatorTree *DT = nullptr, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr); /// Given operands for an FMul, see if we can fold the result. If not, this /// returns null. - Value *SimplifyFMulInst(Value *LHS, Value *RHS, - FastMathFlags FMF, + Value *SimplifyFMulInst(Value *LHS, Value *RHS, FastMathFlags FMF, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, - AssumptionTracker *AT = nullptr, + AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr); /// SimplifyMulInst - Given operands for a Mul, see if we can @@ -97,7 +96,7 @@ namespace llvm { Value *SimplifyMulInst(Value *LHS, Value *RHS, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, - AssumptionTracker *AT = nullptr, + AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr); /// SimplifySDivInst - Given operands for an SDiv, see if we can @@ -106,7 +105,7 @@ namespace llvm { const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, - AssumptionTracker *AT = nullptr, + AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr); /// SimplifyUDivInst - Given operands for a UDiv, see if we can @@ -115,16 +114,16 @@ namespace llvm { const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, - AssumptionTracker *AT = nullptr, + AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr); /// SimplifyFDivInst - Given operands for an FDiv, see if we can /// fold the result. If not, this returns null. - Value *SimplifyFDivInst(Value *LHS, Value *RHS, + Value *SimplifyFDivInst(Value *LHS, Value *RHS, FastMathFlags FMF, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, - AssumptionTracker *AT = nullptr, + AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr); /// SimplifySRemInst - Given operands for an SRem, see if we can @@ -133,7 +132,7 @@ namespace llvm { const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, - AssumptionTracker *AT = nullptr, + AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr); /// SimplifyURemInst - Given operands for a URem, see if we can @@ -142,16 +141,16 @@ namespace llvm { const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, - AssumptionTracker *AT = nullptr, + AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr); /// SimplifyFRemInst - Given operands for an FRem, see if we can /// fold the result. If not, this returns null. - Value *SimplifyFRemInst(Value *LHS, Value *RHS, + Value *SimplifyFRemInst(Value *LHS, Value *RHS, FastMathFlags FMF, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, - AssumptionTracker *AT = nullptr, + AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr); /// SimplifyShlInst - Given operands for a Shl, see if we can @@ -160,7 +159,7 @@ namespace llvm { const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, - AssumptionTracker *AT = nullptr, + AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr); /// SimplifyLShrInst - Given operands for a LShr, see if we can @@ -169,7 +168,7 @@ namespace llvm { const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, - AssumptionTracker *AT = nullptr, + AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr); /// SimplifyAShrInst - Given operands for a AShr, see if we can @@ -178,7 +177,7 @@ namespace llvm { const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, - AssumptionTracker *AT = nullptr, + AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr); /// SimplifyAndInst - Given operands for an And, see if we can @@ -186,7 +185,7 @@ namespace llvm { Value *SimplifyAndInst(Value *LHS, Value *RHS, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, - AssumptionTracker *AT = nullptr, + AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr); /// SimplifyOrInst - Given operands for an Or, see if we can @@ -194,7 +193,7 @@ namespace llvm { Value *SimplifyOrInst(Value *LHS, Value *RHS, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, - AssumptionTracker *AT = nullptr, + AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr); /// SimplifyXorInst - Given operands for a Xor, see if we can @@ -202,7 +201,7 @@ namespace llvm { Value *SimplifyXorInst(Value *LHS, Value *RHS, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, - AssumptionTracker *AT = nullptr, + AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr); /// SimplifyICmpInst - Given operands for an ICmpInst, see if we can @@ -211,7 +210,7 @@ namespace llvm { const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, - AssumptionTracker *AT = nullptr, + AssumptionCache *AC = nullptr, Instruction *CxtI = nullptr); /// SimplifyFCmpInst - Given operands for an FCmpInst, see if we can @@ -220,7 +219,7 @@ namespace llvm { const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, - AssumptionTracker *AT = nullptr, + AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr); /// SimplifySelectInst - Given operands for a SelectInst, see if we can fold @@ -229,7 +228,7 @@ namespace llvm { const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, - AssumptionTracker *AT = nullptr, + AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr); /// SimplifyGEPInst - Given operands for an GetElementPtrInst, see if we can @@ -237,7 +236,7 @@ namespace llvm { Value *SimplifyGEPInst(ArrayRef Ops, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, - AssumptionTracker *AT = nullptr, + AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr); /// SimplifyInsertValueInst - Given operands for an InsertValueInst, see if we @@ -247,7 +246,7 @@ namespace llvm { const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, - AssumptionTracker *AT = nullptr, + AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr); /// SimplifyTruncInst - Given operands for an TruncInst, see if we can fold @@ -255,7 +254,7 @@ namespace llvm { Value *SimplifyTruncInst(Value *Op, Type *Ty, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, - AssumptionTracker *AT = nullptr, + AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr); //=== Helper functions for higher up the class hierarchy. @@ -267,7 +266,7 @@ namespace llvm { const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, - AssumptionTracker *AT = nullptr, + AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr); /// SimplifyBinOp - Given operands for a BinaryOperator, see if we can @@ -276,8 +275,19 @@ namespace llvm { const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, - AssumptionTracker *AT = nullptr, + AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr); + /// SimplifyFPBinOp - Given operands for a BinaryOperator, see if we can + /// fold the result. If not, this returns null. + /// In contrast to SimplifyBinOp, try to use FastMathFlag when folding the + /// result. In case we don't need FastMathFlags, simply fall to SimplifyBinOp. + Value *SimplifyFPBinOp(unsigned Opcode, Value *LHS, Value *RHS, + const FastMathFlags &FMF, + const DataLayout *TD = nullptr, + const TargetLibraryInfo *TLI = nullptr, + const DominatorTree *DT = nullptr, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr); /// \brief Given a function and iterators over arguments, see if we can fold /// the result. @@ -287,7 +297,7 @@ namespace llvm { User::op_iterator ArgEnd, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, - AssumptionTracker *AT = nullptr, + AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr); /// \brief Given a function and set of arguments, see if we can fold the @@ -298,7 +308,7 @@ namespace llvm { const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, - AssumptionTracker *AT = nullptr, + AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr); /// SimplifyInstruction - See if we can compute a simplified version of this @@ -306,8 +316,7 @@ namespace llvm { Value *SimplifyInstruction(Instruction *I, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, - AssumptionTracker *AT = nullptr); - + AssumptionCache *AC = nullptr); /// \brief Replace all uses of 'I' with 'SimpleV' and simplify the uses /// recursively. @@ -321,7 +330,7 @@ namespace llvm { const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, - AssumptionTracker *AT = nullptr); + AssumptionCache *AC = nullptr); /// \brief Recursively attempt to simplify an instruction. /// @@ -333,7 +342,7 @@ namespace llvm { const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, - AssumptionTracker *AT = nullptr); + AssumptionCache *AC = nullptr); } // end namespace llvm #endif diff --git a/include/llvm/Analysis/JumpInstrTableInfo.h b/include/llvm/Analysis/JumpInstrTableInfo.h index 5b0176c..591e794 100644 --- a/include/llvm/Analysis/JumpInstrTableInfo.h +++ b/include/llvm/Analysis/JumpInstrTableInfo.h @@ -16,7 +16,6 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/Pass.h" - #include namespace llvm { diff --git a/include/llvm/Analysis/LazyCallGraph.h b/include/llvm/Analysis/LazyCallGraph.h index 9a59844..b0b9068 100644 --- a/include/llvm/Analysis/LazyCallGraph.h +++ b/include/llvm/Analysis/LazyCallGraph.h @@ -46,11 +46,11 @@ #include "llvm/IR/BasicBlock.h" #include "llvm/IR/Function.h" #include "llvm/IR/Module.h" +#include "llvm/IR/PassManager.h" #include "llvm/Support/Allocator.h" #include namespace llvm { -class ModuleAnalysisManager; class PreservedAnalyses; class raw_ostream; @@ -252,6 +252,12 @@ public: /// \brief Test if this SCC is a descendant of \a C. bool isDescendantOf(const SCC &C) const; + /// \brief Short name useful for debugging or logging. + /// + /// We use the name of the first function in the SCC to name the SCC for + /// the purposes of debugging and logging. + StringRef getName() const { return (*begin())->getFunction().getName(); } + ///@{ /// \name Mutation API /// @@ -537,11 +543,13 @@ public: static void *ID() { return (void *)&PassID; } + static StringRef name() { return "Lazy CallGraph Analysis"; } + /// \brief Compute the \c LazyCallGraph for the module \c M. /// /// This just builds the set of entry points to the call graph. The rest is /// built lazily as it is walked. - LazyCallGraph run(Module *M) { return LazyCallGraph(*M); } + LazyCallGraph run(Module &M) { return LazyCallGraph(M); } private: static char PassID; @@ -556,7 +564,7 @@ class LazyCallGraphPrinterPass { public: explicit LazyCallGraphPrinterPass(raw_ostream &OS); - PreservedAnalyses run(Module *M, ModuleAnalysisManager *AM); + PreservedAnalyses run(Module &M, ModuleAnalysisManager *AM); static StringRef name() { return "LazyCallGraphPrinterPass"; } }; diff --git a/include/llvm/Analysis/LazyValueInfo.h b/include/llvm/Analysis/LazyValueInfo.h index 52cc0d1..51f6b0c 100644 --- a/include/llvm/Analysis/LazyValueInfo.h +++ b/include/llvm/Analysis/LazyValueInfo.h @@ -18,7 +18,7 @@ #include "llvm/Pass.h" namespace llvm { - class AssumptionTracker; + class AssumptionCache; class Constant; class DataLayout; class DominatorTree; @@ -26,16 +26,15 @@ namespace llvm { class TargetLibraryInfo; class Value; -/// LazyValueInfo - This pass computes, caches, and vends lazy value constraint -/// information. +/// This pass computes, caches, and vends lazy value constraint information. class LazyValueInfo : public FunctionPass { - AssumptionTracker *AT; + AssumptionCache *AC; const DataLayout *DL; class TargetLibraryInfo *TLI; DominatorTree *DT; void *PImpl; - LazyValueInfo(const LazyValueInfo&) LLVM_DELETED_FUNCTION; - void operator=(const LazyValueInfo&) LLVM_DELETED_FUNCTION; + LazyValueInfo(const LazyValueInfo&) = delete; + void operator=(const LazyValueInfo&) = delete; public: static char ID; LazyValueInfo() : FunctionPass(ID), PImpl(nullptr) { @@ -43,7 +42,7 @@ public: } ~LazyValueInfo() { assert(!PImpl && "releaseMemory not called"); } - /// Tristate - This is used to return true/false/dunno results. + /// This is used to return true/false/dunno results. enum Tristate { Unknown = -1, False = 0, True = 1 }; @@ -51,33 +50,33 @@ public: // Public query interface. - /// getPredicateOnEdge - Determine whether the specified value comparison - /// with a constant is known to be true or false on the specified CFG edge. + /// Determine whether the specified value comparison with a constant is known + /// to be true or false on the specified CFG edge. /// Pred is a CmpInst predicate. Tristate getPredicateOnEdge(unsigned Pred, Value *V, Constant *C, BasicBlock *FromBB, BasicBlock *ToBB, Instruction *CxtI = nullptr); - /// getPredicateAt - Determine whether the specified value comparison - /// with a constant is known to be true or false at the specified instruction + /// Determine whether the specified value comparison with a constant is known + /// to be true or false at the specified instruction /// (from an assume intrinsic). Pred is a CmpInst predicate. Tristate getPredicateAt(unsigned Pred, Value *V, Constant *C, Instruction *CxtI); - /// getConstant - Determine whether the specified value is known to be a + /// Determine whether the specified value is known to be a /// constant at the end of the specified block. Return null if not. Constant *getConstant(Value *V, BasicBlock *BB, Instruction *CxtI = nullptr); - /// getConstantOnEdge - Determine whether the specified value is known to be a + /// Determine whether the specified value is known to be a /// constant on the specified edge. Return null if not. Constant *getConstantOnEdge(Value *V, BasicBlock *FromBB, BasicBlock *ToBB, Instruction *CxtI = nullptr); - /// threadEdge - Inform the analysis cache that we have threaded an edge from + /// Inform the analysis cache that we have threaded an edge from /// PredBB to OldSucc to be from PredBB to NewSucc instead. void threadEdge(BasicBlock *PredBB, BasicBlock *OldSucc, BasicBlock *NewSucc); - /// eraseBlock - Inform the analysis cache that we have erased a block. + /// Inform the analysis cache that we have erased a block. void eraseBlock(BasicBlock *BB); // Implementation boilerplate. diff --git a/include/llvm/Analysis/LibCallSemantics.h b/include/llvm/Analysis/LibCallSemantics.h index 8bd747f..e6427a4 100644 --- a/include/llvm/Analysis/LibCallSemantics.h +++ b/include/llvm/Analysis/LibCallSemantics.h @@ -18,6 +18,7 @@ #include "llvm/Analysis/AliasAnalysis.h" namespace llvm { +class InvokeInst; /// LibCallLocationInfo - This struct describes a set of memory locations that /// are accessed by libcalls. Identification of a location is doing with a @@ -162,6 +163,28 @@ namespace llvm { virtual const LibCallFunctionInfo *getFunctionInfoArray() const = 0; }; + enum class EHPersonality { + Unknown, + GNU_Ada, + GNU_C, + GNU_CXX, + GNU_ObjC, + MSVC_X86SEH, + MSVC_Win64SEH, + MSVC_CXX, + }; + + /// \brief See if the given exception handling personality function is one + /// that we understand. If so, return a description of it; otherwise return + /// Unknown. + EHPersonality classifyEHPersonality(const Value *Pers); + + /// \brief Returns true if this personality function catches asynchronous + /// exceptions. + bool isAsynchronousEHPersonality(EHPersonality Pers); + + bool canSimplifyInvokeNoUnwind(const InvokeInst *II); + } // end namespace llvm #endif diff --git a/include/llvm/Analysis/LoopAccessAnalysis.h b/include/llvm/Analysis/LoopAccessAnalysis.h new file mode 100644 index 0000000..323af98 --- /dev/null +++ b/include/llvm/Analysis/LoopAccessAnalysis.h @@ -0,0 +1,290 @@ +//===- llvm/Analysis/LoopAccessAnalysis.h -----------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the interface for the loop memory dependence framework that +// was originally developed for the Loop Vectorizer. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_LOOPACCESSANALYSIS_H +#define LLVM_ANALYSIS_LOOPACCESSANALYSIS_H + +#include "llvm/ADT/EquivalenceClasses.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/SetVector.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Analysis/AliasSetTracker.h" +#include "llvm/Analysis/ScalarEvolutionExpressions.h" +#include "llvm/IR/ValueHandle.h" +#include "llvm/Pass.h" +#include "llvm/Support/raw_ostream.h" + +namespace llvm { + +class Value; +class DataLayout; +class AliasAnalysis; +class ScalarEvolution; +class Loop; +class SCEV; + +/// Optimization analysis message produced during vectorization. Messages inform +/// the user why vectorization did not occur. +class LoopAccessReport { + std::string Message; + const Instruction *Instr; + +protected: + LoopAccessReport(const Twine &Message, const Instruction *I) + : Message(Message.str()), Instr(I) {} + +public: + LoopAccessReport(const Instruction *I = nullptr) : Instr(I) {} + + template LoopAccessReport &operator<<(const A &Value) { + raw_string_ostream Out(Message); + Out << Value; + return *this; + } + + const Instruction *getInstr() const { return Instr; } + + std::string &str() { return Message; } + const std::string &str() const { return Message; } + operator Twine() { return Message; } + + /// \brief Emit an analysis note for \p PassName with the debug location from + /// the instruction in \p Message if available. Otherwise use the location of + /// \p TheLoop. + static void emitAnalysis(const LoopAccessReport &Message, + const Function *TheFunction, + const Loop *TheLoop, + const char *PassName); +}; + +/// \brief Collection of parameters shared beetween the Loop Vectorizer and the +/// Loop Access Analysis. +struct VectorizerParams { + /// \brief Maximum SIMD width. + static const unsigned MaxVectorWidth; + + /// \brief VF as overridden by the user. + static unsigned VectorizationFactor; + /// \brief Interleave factor as overridden by the user. + static unsigned VectorizationInterleave; + /// \brief True if force-vector-interleave was specified by the user. + static bool isInterleaveForced(); + + /// \\brief When performing memory disambiguation checks at runtime do not + /// make more than this number of comparisons. + static unsigned RuntimeMemoryCheckThreshold; +}; + +/// \brief Drive the analysis of memory accesses in the loop +/// +/// This class is responsible for analyzing the memory accesses of a loop. It +/// collects the accesses and then its main helper the AccessAnalysis class +/// finds and categorizes the dependences in buildDependenceSets. +/// +/// For memory dependences that can be analyzed at compile time, it determines +/// whether the dependence is part of cycle inhibiting vectorization. This work +/// is delegated to the MemoryDepChecker class. +/// +/// For memory dependences that cannot be determined at compile time, it +/// generates run-time checks to prove independence. This is done by +/// AccessAnalysis::canCheckPtrAtRT and the checks are maintained by the +/// RuntimePointerCheck class. +class LoopAccessInfo { +public: + /// This struct holds information about the memory runtime legality check that + /// a group of pointers do not overlap. + struct RuntimePointerCheck { + RuntimePointerCheck() : Need(false) {} + + /// Reset the state of the pointer runtime information. + void reset() { + Need = false; + Pointers.clear(); + Starts.clear(); + Ends.clear(); + IsWritePtr.clear(); + DependencySetId.clear(); + AliasSetId.clear(); + } + + /// Insert a pointer and calculate the start and end SCEVs. + void insert(ScalarEvolution *SE, Loop *Lp, Value *Ptr, bool WritePtr, + unsigned DepSetId, unsigned ASId, + const ValueToValueMap &Strides); + + /// \brief No run-time memory checking is necessary. + bool empty() const { return Pointers.empty(); } + + /// \brief Decide whether we need to issue a run-time check for pointer at + /// index \p I and \p J to prove their independence. + bool needsChecking(unsigned I, unsigned J) const; + + /// \brief Print the list run-time memory checks necessary. + void print(raw_ostream &OS, unsigned Depth = 0) const; + + /// This flag indicates if we need to add the runtime check. + bool Need; + /// Holds the pointers that we need to check. + SmallVector, 2> Pointers; + /// Holds the pointer value at the beginning of the loop. + SmallVector Starts; + /// Holds the pointer value at the end of the loop. + SmallVector Ends; + /// Holds the information if this pointer is used for writing to memory. + SmallVector IsWritePtr; + /// Holds the id of the set of pointers that could be dependent because of a + /// shared underlying object. + SmallVector DependencySetId; + /// Holds the id of the disjoint alias set to which this pointer belongs. + SmallVector AliasSetId; + }; + + LoopAccessInfo(Loop *L, ScalarEvolution *SE, const DataLayout *DL, + const TargetLibraryInfo *TLI, AliasAnalysis *AA, + DominatorTree *DT, const ValueToValueMap &Strides); + + /// Return true we can analyze the memory accesses in the loop and there are + /// no memory dependence cycles. + bool canVectorizeMemory() const { return CanVecMem; } + + const RuntimePointerCheck *getRuntimePointerCheck() const { + return &PtrRtCheck; + } + + /// Return true if the block BB needs to be predicated in order for the loop + /// to be vectorized. + static bool blockNeedsPredication(BasicBlock *BB, Loop *TheLoop, + DominatorTree *DT); + + /// Returns true if the value V is uniform within the loop. + bool isUniform(Value *V) const; + + unsigned getMaxSafeDepDistBytes() const { return MaxSafeDepDistBytes; } + unsigned getNumStores() const { return NumStores; } + unsigned getNumLoads() const { return NumLoads;} + + /// \brief Add code that checks at runtime if the accessed arrays overlap. + /// + /// Returns a pair of instructions where the first element is the first + /// instruction generated in possibly a sequence of instructions and the + /// second value is the final comparator value or NULL if no check is needed. + std::pair + addRuntimeCheck(Instruction *Loc) const; + + /// \brief The diagnostics report generated for the analysis. E.g. why we + /// couldn't analyze the loop. + const Optional &getReport() const { return Report; } + + /// \brief Print the information about the memory accesses in the loop. + void print(raw_ostream &OS, unsigned Depth = 0) const; + + /// \brief Used to ensure that if the analysis was run with speculating the + /// value of symbolic strides, the client queries it with the same assumption. + /// Only used in DEBUG build but we don't want NDEBUG-dependent ABI. + unsigned NumSymbolicStrides; + +private: + /// \brief Analyze the loop. Substitute symbolic strides using Strides. + void analyzeLoop(const ValueToValueMap &Strides); + + /// \brief Check if the structure of the loop allows it to be analyzed by this + /// pass. + bool canAnalyzeLoop(); + + void emitAnalysis(LoopAccessReport &Message); + + /// We need to check that all of the pointers in this list are disjoint + /// at runtime. + RuntimePointerCheck PtrRtCheck; + Loop *TheLoop; + ScalarEvolution *SE; + const DataLayout *DL; + const TargetLibraryInfo *TLI; + AliasAnalysis *AA; + DominatorTree *DT; + + unsigned NumLoads; + unsigned NumStores; + + unsigned MaxSafeDepDistBytes; + + /// \brief Cache the result of analyzeLoop. + bool CanVecMem; + + /// \brief The diagnostics report generated for the analysis. E.g. why we + /// couldn't analyze the loop. + Optional Report; +}; + +Value *stripIntegerCast(Value *V); + +///\brief Return the SCEV corresponding to a pointer with the symbolic stride +///replaced with constant one. +/// +/// If \p OrigPtr is not null, use it to look up the stride value instead of \p +/// Ptr. \p PtrToStride provides the mapping between the pointer value and its +/// stride as collected by LoopVectorizationLegality::collectStridedAccess. +const SCEV *replaceSymbolicStrideSCEV(ScalarEvolution *SE, + const ValueToValueMap &PtrToStride, + Value *Ptr, Value *OrigPtr = nullptr); + +/// \brief This analysis provides dependence information for the memory accesses +/// of a loop. +/// +/// It runs the analysis for a loop on demand. This can be initiated by +/// querying the loop access info via LAA::getInfo. getInfo return a +/// LoopAccessInfo object. See this class for the specifics of what information +/// is provided. +class LoopAccessAnalysis : public FunctionPass { +public: + static char ID; + + LoopAccessAnalysis() : FunctionPass(ID) { + initializeLoopAccessAnalysisPass(*PassRegistry::getPassRegistry()); + } + + bool runOnFunction(Function &F) override; + + void getAnalysisUsage(AnalysisUsage &AU) const override; + + /// \brief Query the result of the loop access information for the loop \p L. + /// + /// If the client speculates (and then issues run-time checks) for the values + /// of symbolic strides, \p Strides provides the mapping (see + /// replaceSymbolicStrideSCEV). If there is no cached result available run + /// the analysis. + const LoopAccessInfo &getInfo(Loop *L, const ValueToValueMap &Strides); + + void releaseMemory() override { + // Invalidate the cache when the pass is freed. + LoopAccessInfoMap.clear(); + } + + /// \brief Print the result of the analysis when invoked with -analyze. + void print(raw_ostream &OS, const Module *M = nullptr) const override; + +private: + /// \brief The cache. + DenseMap> LoopAccessInfoMap; + + // The used analysis passes. + ScalarEvolution *SE; + const DataLayout *DL; + const TargetLibraryInfo *TLI; + AliasAnalysis *AA; + DominatorTree *DT; +}; +} // End llvm namespace + +#endif diff --git a/include/llvm/Analysis/LoopInfo.h b/include/llvm/Analysis/LoopInfo.h index bef03e9..85c2da7 100644 --- a/include/llvm/Analysis/LoopInfo.h +++ b/include/llvm/Analysis/LoopInfo.h @@ -42,6 +42,11 @@ namespace llvm { +// FIXME: Replace this brittle forward declaration with the include of the new +// PassManager.h when doing so doesn't break the PassManagerBuilder. +template class AnalysisManager; +class PreservedAnalyses; + template inline void RemoveFromVector(std::vector &V, T *N) { typename std::vector::iterator I = std::find(V.begin(), V.end(), N); @@ -74,9 +79,9 @@ class LoopBase { SmallPtrSet DenseBlockSet; - LoopBase(const LoopBase &) LLVM_DELETED_FUNCTION; + LoopBase(const LoopBase &) = delete; const LoopBase& - operator=(const LoopBase &) LLVM_DELETED_FUNCTION; + operator=(const LoopBase &) = delete; public: /// Loop ctor - This creates an empty loop. LoopBase() : ParentLoop(nullptr) {} @@ -496,18 +501,33 @@ class LoopInfoBase { friend class LoopBase; friend class LoopInfo; - void operator=(const LoopInfoBase &) LLVM_DELETED_FUNCTION; - LoopInfoBase(const LoopInfo &) LLVM_DELETED_FUNCTION; + void operator=(const LoopInfoBase &) = delete; + LoopInfoBase(const LoopInfoBase &) = delete; public: LoopInfoBase() { } ~LoopInfoBase() { releaseMemory(); } + LoopInfoBase(LoopInfoBase &&Arg) + : BBMap(std::move(Arg.BBMap)), + TopLevelLoops(std::move(Arg.TopLevelLoops)) { + // We have to clear the arguments top level loops as we've taken ownership. + Arg.TopLevelLoops.clear(); + } + LoopInfoBase &operator=(LoopInfoBase &&RHS) { + BBMap = std::move(RHS.BBMap); + + for (auto *L : TopLevelLoops) + delete L; + TopLevelLoops = std::move(RHS.TopLevelLoops); + RHS.TopLevelLoops.clear(); + return *this; + } + void releaseMemory() { - for (typename std::vector::iterator I = - TopLevelLoops.begin(), E = TopLevelLoops.end(); I != E; ++I) - delete *I; // Delete all of the loops... + BBMap.clear(); - BBMap.clear(); // Reset internal state of analysis + for (auto *L : TopLevelLoops) + delete L; TopLevelLoops.clear(); } @@ -576,8 +596,7 @@ public: /// list with the indicated loop. void changeTopLevelLoop(LoopT *OldLoop, LoopT *NewLoop) { - typename std::vector::iterator I = - std::find(TopLevelLoops.begin(), TopLevelLoops.end(), OldLoop); + auto I = std::find(TopLevelLoops.begin(), TopLevelLoops.end(), OldLoop); assert(I != TopLevelLoops.end() && "Old loop not at top level!"); *I = NewLoop; assert(!NewLoop->ParentLoop && !OldLoop->ParentLoop && @@ -595,7 +614,7 @@ public: /// including all of the Loop objects it is nested in and our mapping from /// BasicBlocks to loops. void removeBlock(BlockT *BB) { - typename DenseMap::iterator I = BBMap.find(BB); + auto I = BBMap.find(BB); if (I != BBMap.end()) { for (LoopT *L = I->second; L; L = L->getParentLoop()) L->removeBlockFromLoop(BB); @@ -617,8 +636,9 @@ public: void Analyze(DominatorTreeBase &DomTree); // Debugging - void print(raw_ostream &OS) const; + + void verify() const; }; // Implementation in LoopInfoImpl.h @@ -626,99 +646,23 @@ public: __extension__ extern template class LoopInfoBase; #endif -class LoopInfo : public FunctionPass { - LoopInfoBase LI; +class LoopInfo : public LoopInfoBase { + typedef LoopInfoBase BaseT; + friend class LoopBase; - void operator=(const LoopInfo &) LLVM_DELETED_FUNCTION; - LoopInfo(const LoopInfo &) LLVM_DELETED_FUNCTION; + void operator=(const LoopInfo &) = delete; + LoopInfo(const LoopInfo &) = delete; public: - static char ID; // Pass identification, replacement for typeid - - LoopInfo() : FunctionPass(ID) { - initializeLoopInfoPass(*PassRegistry::getPassRegistry()); - } - - LoopInfoBase& getBase() { return LI; } + LoopInfo() {} - /// iterator/begin/end - The interface to the top-level loops in the current - /// function. - /// - typedef LoopInfoBase::iterator iterator; - typedef LoopInfoBase::reverse_iterator reverse_iterator; - inline iterator begin() const { return LI.begin(); } - inline iterator end() const { return LI.end(); } - inline reverse_iterator rbegin() const { return LI.rbegin(); } - inline reverse_iterator rend() const { return LI.rend(); } - bool empty() const { return LI.empty(); } - - /// getLoopFor - Return the inner most loop that BB lives in. If a basic - /// block is in no loop (for example the entry node), null is returned. - /// - inline Loop *getLoopFor(const BasicBlock *BB) const { - return LI.getLoopFor(BB); + LoopInfo(LoopInfo &&Arg) : BaseT(std::move(static_cast(Arg))) {} + LoopInfo &operator=(LoopInfo &&RHS) { + BaseT::operator=(std::move(static_cast(RHS))); + return *this; } - /// operator[] - same as getLoopFor... - /// - inline const Loop *operator[](const BasicBlock *BB) const { - return LI.getLoopFor(BB); - } - - /// getLoopDepth - Return the loop nesting level of the specified block. A - /// depth of 0 means the block is not inside any loop. - /// - inline unsigned getLoopDepth(const BasicBlock *BB) const { - return LI.getLoopDepth(BB); - } - - // isLoopHeader - True if the block is a loop header node - inline bool isLoopHeader(BasicBlock *BB) const { - return LI.isLoopHeader(BB); - } - - /// runOnFunction - Calculate the natural loop information. - /// - bool runOnFunction(Function &F) override; - - void verifyAnalysis() const override; - - void releaseMemory() override { LI.releaseMemory(); } - - void print(raw_ostream &O, const Module* M = nullptr) const override; - - void getAnalysisUsage(AnalysisUsage &AU) const override; - - /// removeLoop - This removes the specified top-level loop from this loop info - /// object. The loop is not deleted, as it will presumably be inserted into - /// another loop. - inline Loop *removeLoop(iterator I) { return LI.removeLoop(I); } - - /// changeLoopFor - Change the top-level loop that contains BB to the - /// specified loop. This should be used by transformations that restructure - /// the loop hierarchy tree. - inline void changeLoopFor(BasicBlock *BB, Loop *L) { - LI.changeLoopFor(BB, L); - } - - /// changeTopLevelLoop - Replace the specified loop in the top-level loops - /// list with the indicated loop. - inline void changeTopLevelLoop(Loop *OldLoop, Loop *NewLoop) { - LI.changeTopLevelLoop(OldLoop, NewLoop); - } - - /// addTopLevelLoop - This adds the specified loop to the collection of - /// top-level loops. - inline void addTopLevelLoop(Loop *New) { - LI.addTopLevelLoop(New); - } - - /// removeBlock - This method completely removes BB from all data structures, - /// including all of the Loop objects it is nested in and our mapping from - /// BasicBlocks to loops. - void removeBlock(BasicBlock *BB) { - LI.removeBlock(BB); - } + // Most of the public interface is provided via LoopInfoBase. /// updateUnloop - Update LoopInfo after removing the last backedge from a /// loop--now the "unloop". This updates the loop forest and parent loops for @@ -748,7 +692,6 @@ public: } }; - // Allow clients to walk the list of nested loops... template <> struct GraphTraits { typedef const Loop NodeType; @@ -776,6 +719,65 @@ template <> struct GraphTraits { } }; +/// \brief Analysis pass that exposes the \c LoopInfo for a function. +class LoopAnalysis { + static char PassID; + +public: + typedef LoopInfo Result; + + /// \brief Opaque, unique identifier for this analysis pass. + static void *ID() { return (void *)&PassID; } + + /// \brief Provide a name for the analysis for debugging and logging. + static StringRef name() { return "LoopAnalysis"; } + + LoopAnalysis() {} + LoopAnalysis(const LoopAnalysis &Arg) {} + LoopAnalysis(LoopAnalysis &&Arg) {} + LoopAnalysis &operator=(const LoopAnalysis &RHS) { return *this; } + LoopAnalysis &operator=(LoopAnalysis &&RHS) { return *this; } + + LoopInfo run(Function &F, AnalysisManager *AM); +}; + +/// \brief Printer pass for the \c LoopAnalysis results. +class LoopPrinterPass { + raw_ostream &OS; + +public: + explicit LoopPrinterPass(raw_ostream &OS) : OS(OS) {} + PreservedAnalyses run(Function &F, AnalysisManager *AM); + + static StringRef name() { return "LoopPrinterPass"; } +}; + +/// \brief The legacy pass manager's analysis pass to compute loop information. +class LoopInfoWrapperPass : public FunctionPass { + LoopInfo LI; + +public: + static char ID; // Pass identification, replacement for typeid + + LoopInfoWrapperPass() : FunctionPass(ID) { + initializeLoopInfoWrapperPassPass(*PassRegistry::getPassRegistry()); + } + + LoopInfo &getLoopInfo() { return LI; } + const LoopInfo &getLoopInfo() const { return LI; } + + /// \brief Calculate the natural loop information for a given function. + bool runOnFunction(Function &F) override; + + void verifyAnalysis() const override; + + void releaseMemory() override { LI.releaseMemory(); } + + void print(raw_ostream &O, const Module *M = nullptr) const override; + + void getAnalysisUsage(AnalysisUsage &AU) const override; +}; + } // End llvm namespace #endif diff --git a/include/llvm/Analysis/LoopInfoImpl.h b/include/llvm/Analysis/LoopInfoImpl.h index 948be0f..3321f39 100644 --- a/include/llvm/Analysis/LoopInfoImpl.h +++ b/include/llvm/Analysis/LoopInfoImpl.h @@ -545,6 +545,25 @@ void LoopInfoBase::print(raw_ostream &OS) const { #endif } +template +void LoopInfoBase::verify() const { + DenseSet Loops; + for (iterator I = begin(), E = end(); I != E; ++I) { + assert(!(*I)->getParentLoop() && "Top-level loop has a parent!"); + (*I)->verifyLoopNest(&Loops); + } + + // Verify that blocks are mapped to valid loops. +#ifndef NDEBUG + for (auto &Entry : BBMap) { + BlockT *BB = Entry.first; + LoopT *L = Entry.second; + assert(Loops.count(L) && "orphaned loop"); + assert(L->contains(BB) && "orphaned block"); + } +#endif +} + } // End llvm namespace #endif diff --git a/include/llvm/Analysis/MemoryDependenceAnalysis.h b/include/llvm/Analysis/MemoryDependenceAnalysis.h index 4d315d1..77610b3 100644 --- a/include/llvm/Analysis/MemoryDependenceAnalysis.h +++ b/include/llvm/Analysis/MemoryDependenceAnalysis.h @@ -28,7 +28,7 @@ namespace llvm { class Instruction; class CallSite; class AliasAnalysis; - class AssumptionTracker; + class AssumptionCache; class DataLayout; class MemoryDependenceAnalysis; class PredIteratorCache; @@ -326,7 +326,7 @@ namespace llvm { AliasAnalysis *AA; const DataLayout *DL; DominatorTree *DT; - AssumptionTracker *AT; + AssumptionCache *AC; std::unique_ptr PredCache; public: @@ -366,12 +366,16 @@ namespace llvm { /// getNonLocalPointerDependency - Perform a full dependency query for an - /// access to the specified (non-volatile) memory location, returning the - /// set of instructions that either define or clobber the value. + /// access to the QueryInst's specified memory location, returning the set + /// of instructions that either define or clobber the value. /// - /// This method assumes the pointer has a "NonLocal" dependency within BB. - void getNonLocalPointerDependency(const AliasAnalysis::Location &Loc, - bool isLoad, BasicBlock *BB, + /// Warning: For a volatile query instruction, the dependencies will be + /// accurate, and thus usable for reordering, but it is never legal to + /// remove the query instruction. + /// + /// This method assumes the pointer has a "NonLocal" dependency within + /// QueryInst's parent basic block. + void getNonLocalPointerDependency(Instruction *QueryInst, SmallVectorImpl &Result); /// removeInstruction - Remove an instruction from the dependence analysis, @@ -424,13 +428,15 @@ namespace llvm { MemDepResult getCallSiteDependencyFrom(CallSite C, bool isReadOnlyCall, BasicBlock::iterator ScanIt, BasicBlock *BB); - bool getNonLocalPointerDepFromBB(const PHITransAddr &Pointer, + bool getNonLocalPointerDepFromBB(Instruction *QueryInst, + const PHITransAddr &Pointer, const AliasAnalysis::Location &Loc, bool isLoad, BasicBlock *BB, SmallVectorImpl &Result, DenseMap &Visited, bool SkipFirstBlock = false); - MemDepResult GetNonLocalInfoForBlock(const AliasAnalysis::Location &Loc, + MemDepResult GetNonLocalInfoForBlock(Instruction *QueryInst, + const AliasAnalysis::Location &Loc, bool isLoad, BasicBlock *BB, NonLocalDepInfo *Cache, unsigned NumSortedEntries); diff --git a/include/llvm/Analysis/PHITransAddr.h b/include/llvm/Analysis/PHITransAddr.h index 0790e97..38730d8 100644 --- a/include/llvm/Analysis/PHITransAddr.h +++ b/include/llvm/Analysis/PHITransAddr.h @@ -18,7 +18,7 @@ #include "llvm/IR/Instruction.h" namespace llvm { - class AssumptionTracker; + class AssumptionCache; class DominatorTree; class DataLayout; class TargetLibraryInfo; @@ -44,13 +44,13 @@ class PHITransAddr { const TargetLibraryInfo *TLI; /// A cache of @llvm.assume calls used by SimplifyInstruction. - AssumptionTracker *AT; - + AssumptionCache *AC; + /// InstInputs - The inputs for our symbolic address. SmallVector InstInputs; public: - PHITransAddr(Value *addr, const DataLayout *DL, AssumptionTracker *AT) - : Addr(addr), DL(DL), TLI(nullptr), AT(AT) { + PHITransAddr(Value *addr, const DataLayout *DL, AssumptionCache *AC) + : Addr(addr), DL(DL), TLI(nullptr), AC(AC) { // If the address is an instruction, the whole thing is considered an input. if (Instruction *I = dyn_cast(Addr)) InstInputs.push_back(I); diff --git a/include/llvm/Analysis/Passes.h b/include/llvm/Analysis/Passes.h index 10a5605..530faa7 100644 --- a/include/llvm/Analysis/Passes.h +++ b/include/llvm/Analysis/Passes.h @@ -162,6 +162,14 @@ namespace llvm { // createJumpInstrTableInfoPass - This creates a pass that stores information // about the jump tables created by JumpInstrTables ImmutablePass *createJumpInstrTableInfoPass(); + + //===--------------------------------------------------------------------===// + // + // createMemDerefPrinter - This pass collects memory dereferenceability + // information and prints it with -analyze. + // + FunctionPass *createMemDerefPrinter(); + } #endif diff --git a/include/llvm/Analysis/RegionInfo.h b/include/llvm/Analysis/RegionInfo.h index 6ff7f97..1c7f4d3 100644 --- a/include/llvm/Analysis/RegionInfo.h +++ b/include/llvm/Analysis/RegionInfo.h @@ -115,8 +115,8 @@ public: typedef typename Tr::RegionT RegionT; private: - RegionNodeBase(const RegionNodeBase &) LLVM_DELETED_FUNCTION; - const RegionNodeBase &operator=(const RegionNodeBase &) LLVM_DELETED_FUNCTION; + RegionNodeBase(const RegionNodeBase &) = delete; + const RegionNodeBase &operator=(const RegionNodeBase &) = delete; /// This is the entry basic block that starts this region node. If this is a /// BasicBlock RegionNode, then entry is just the basic block, that this @@ -261,8 +261,8 @@ class RegionBase : public RegionNodeBase { typedef typename InvBlockTraits::ChildIteratorType PredIterTy; friend class RegionInfoBase; - RegionBase(const RegionBase &) LLVM_DELETED_FUNCTION; - const RegionBase &operator=(const RegionBase &) LLVM_DELETED_FUNCTION; + RegionBase(const RegionBase &) = delete; + const RegionBase &operator=(const RegionBase &) = delete; // Information necessary to manage this Region. RegionInfoT *RI; @@ -674,8 +674,8 @@ class RegionInfoBase { RegionInfoBase(); virtual ~RegionInfoBase(); - RegionInfoBase(const RegionInfoBase &) LLVM_DELETED_FUNCTION; - const RegionInfoBase &operator=(const RegionInfoBase &) LLVM_DELETED_FUNCTION; + RegionInfoBase(const RegionInfoBase &) = delete; + const RegionInfoBase &operator=(const RegionInfoBase &) = delete; DomTreeT *DT; PostDomTreeT *PDT; diff --git a/include/llvm/Analysis/RegionInfoImpl.h b/include/llvm/Analysis/RegionInfoImpl.h index b5d0bb3..b0dc263 100644 --- a/include/llvm/Analysis/RegionInfoImpl.h +++ b/include/llvm/Analysis/RegionInfoImpl.h @@ -12,11 +12,11 @@ #ifndef LLVM_ANALYSIS_REGIONINFOIMPL_H #define LLVM_ANALYSIS_REGIONINFOIMPL_H -#include "llvm/Analysis/RegionInfo.h" #include "llvm/ADT/PostOrderIterator.h" #include "llvm/Analysis/DominanceFrontier.h" #include "llvm/Analysis/LoopInfo.h" #include "llvm/Analysis/PostDominators.h" +#include "llvm/Analysis/RegionInfo.h" #include "llvm/Analysis/RegionIterator.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" diff --git a/include/llvm/Analysis/ScalarEvolution.h b/include/llvm/Analysis/ScalarEvolution.h index 893402e..c60cea9 100644 --- a/include/llvm/Analysis/ScalarEvolution.h +++ b/include/llvm/Analysis/ScalarEvolution.h @@ -35,7 +35,7 @@ namespace llvm { class APInt; - class AssumptionTracker; + class AssumptionCache; class Constant; class ConstantInt; class DominatorTree; @@ -71,8 +71,8 @@ namespace llvm { unsigned short SubclassData; private: - SCEV(const SCEV &) LLVM_DELETED_FUNCTION; - void operator=(const SCEV &) LLVM_DELETED_FUNCTION; + SCEV(const SCEV &) = delete; + void operator=(const SCEV &) = delete; public: /// NoWrapFlags are bitfield indices into SubclassData. @@ -82,12 +82,13 @@ namespace llvm { /// operator. NSW is a misnomer that we use to mean no signed overflow or /// underflow. /// - /// AddRec expression may have a no-self-wraparound property if the - /// result can never reach the start value. This property is independent of - /// the actual start value and step direction. Self-wraparound is defined - /// purely in terms of the recurrence's loop, step size, and - /// bitwidth. Formally, a recurrence with no self-wraparound satisfies: - /// abs(step) * max-iteration(loop) <= unsigned-max(bitwidth). + /// AddRec expressions may have a no-self-wraparound property if, in + /// the integer domain, abs(step) * max-iteration(loop) <= + /// unsigned-max(bitwidth). This means that the recurrence will never reach + /// its start value if the step is non-zero. Computing the same value on + /// each iteration is not considered wrapping, and recurrences with step = 0 + /// are trivially . is independent of the sign of step and the + /// value the add recurrence starts with. /// /// Note that NUW and NSW are also valid properties of a recurrence, and /// either implies NW. For convenience, NW will be set for a recurrence @@ -225,7 +226,7 @@ namespace llvm { Function *F; /// The tracker for @llvm.assume intrinsics in this function. - AssumptionTracker *AT; + AssumptionCache *AC; /// LI - The loop information for the function we are currently analyzing. /// @@ -372,14 +373,17 @@ namespace llvm { /// LoopDispositions - Memoized computeLoopDisposition results. DenseMap, 2> > LoopDispositions; + SmallVector, 2>> + LoopDispositions; /// computeLoopDisposition - Compute a LoopDisposition value. LoopDisposition computeLoopDisposition(const SCEV *S, const Loop *L); /// BlockDispositions - Memoized computeBlockDisposition results. - DenseMap, 2> > BlockDispositions; + DenseMap< + const SCEV *, + SmallVector, 2>> + BlockDispositions; /// computeBlockDisposition - Compute a BlockDisposition value. BlockDisposition computeBlockDisposition(const SCEV *S, const BasicBlock *BB); diff --git a/include/llvm/Analysis/ScalarEvolutionExpressions.h b/include/llvm/Analysis/ScalarEvolutionExpressions.h index 94e665f..ff82db1 100644 --- a/include/llvm/Analysis/ScalarEvolutionExpressions.h +++ b/include/llvm/Analysis/ScalarEvolutionExpressions.h @@ -14,8 +14,8 @@ #ifndef LLVM_ANALYSIS_SCALAREVOLUTIONEXPRESSIONS_H #define LLVM_ANALYSIS_SCALAREVOLUTIONEXPRESSIONS_H -#include "llvm/ADT/iterator_range.h" #include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/iterator_range.h" #include "llvm/Analysis/ScalarEvolution.h" #include "llvm/Support/ErrorHandling.h" diff --git a/include/llvm/Analysis/SparsePropagation.h b/include/llvm/Analysis/SparsePropagation.h index 65ff2f6..9ccae5f 100644 --- a/include/llvm/Analysis/SparsePropagation.h +++ b/include/llvm/Analysis/SparsePropagation.h @@ -131,8 +131,8 @@ class SparseSolver { typedef std::pair Edge; std::set KnownFeasibleEdges; - SparseSolver(const SparseSolver&) LLVM_DELETED_FUNCTION; - void operator=(const SparseSolver&) LLVM_DELETED_FUNCTION; + SparseSolver(const SparseSolver&) = delete; + void operator=(const SparseSolver&) = delete; public: explicit SparseSolver(AbstractLatticeFunction *Lattice) : LatticeFunc(Lattice) {} diff --git a/include/llvm/Analysis/TargetLibraryInfo.h b/include/llvm/Analysis/TargetLibraryInfo.h new file mode 100644 index 0000000..5c6f364 --- /dev/null +++ b/include/llvm/Analysis/TargetLibraryInfo.h @@ -0,0 +1,935 @@ +//===-- TargetLibraryInfo.h - Library information ---------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_TARGETLIBRARYINFO_H +#define LLVM_ANALYSIS_TARGETLIBRARYINFO_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/Triple.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Module.h" +#include "llvm/Pass.h" + +// BEGIN ANDROID-SPECIFIC +#ifdef WIN32 +#ifdef fseeko +#undef fseeko +#endif +#ifdef ftello +#undef ftello +#endif +#endif // WIN32 +// END ANDROID-SPECIFIC + +namespace llvm { +class PreservedAnalyses; + + namespace LibFunc { + enum Func { + /// int _IO_getc(_IO_FILE * __fp); + under_IO_getc, + /// int _IO_putc(int __c, _IO_FILE * __fp); + under_IO_putc, + /// void operator delete[](void*); + ZdaPv, + /// void operator delete[](void*, nothrow); + ZdaPvRKSt9nothrow_t, + /// void operator delete[](void*, unsigned int); + ZdaPvj, + /// void operator delete[](void*, unsigned long); + ZdaPvm, + /// void operator delete(void*); + ZdlPv, + /// void operator delete(void*, nothrow); + ZdlPvRKSt9nothrow_t, + /// void operator delete(void*, unsigned int); + ZdlPvj, + /// void operator delete(void*, unsigned long); + ZdlPvm, + /// void *new[](unsigned int); + Znaj, + /// void *new[](unsigned int, nothrow); + ZnajRKSt9nothrow_t, + /// void *new[](unsigned long); + Znam, + /// void *new[](unsigned long, nothrow); + ZnamRKSt9nothrow_t, + /// void *new(unsigned int); + Znwj, + /// void *new(unsigned int, nothrow); + ZnwjRKSt9nothrow_t, + /// void *new(unsigned long); + Znwm, + /// void *new(unsigned long, nothrow); + ZnwmRKSt9nothrow_t, + /// double __cospi(double x); + cospi, + /// float __cospif(float x); + cospif, + /// int __cxa_atexit(void (*f)(void *), void *p, void *d); + cxa_atexit, + /// void __cxa_guard_abort(guard_t *guard); + /// guard_t is int64_t in Itanium ABI or int32_t on ARM eabi. + cxa_guard_abort, + /// int __cxa_guard_acquire(guard_t *guard); + cxa_guard_acquire, + /// void __cxa_guard_release(guard_t *guard); + cxa_guard_release, + /// int __isoc99_scanf (const char *format, ...) + dunder_isoc99_scanf, + /// int __isoc99_sscanf(const char *s, const char *format, ...) + dunder_isoc99_sscanf, + /// void *__memcpy_chk(void *s1, const void *s2, size_t n, size_t s1size); + memcpy_chk, + /// void *__memmove_chk(void *s1, const void *s2, size_t n, + /// size_t s1size); + memmove_chk, + /// void *__memset_chk(void *s, char v, size_t n, size_t s1size); + memset_chk, + /// double __sincospi_stret(double x); + sincospi_stret, + /// float __sincospif_stret(float x); + sincospif_stret, + /// double __sinpi(double x); + sinpi, + /// float __sinpif(float x); + sinpif, + /// double __sqrt_finite(double x); + sqrt_finite, + /// float __sqrt_finite(float x); + sqrtf_finite, + /// long double __sqrt_finite(long double x); + sqrtl_finite, + /// char *__stpcpy_chk(char *s1, const char *s2, size_t s1size); + stpcpy_chk, + /// char *__stpncpy_chk(char *s1, const char *s2, size_t n, + /// size_t s1size); + stpncpy_chk, + /// char *__strcpy_chk(char *s1, const char *s2, size_t s1size); + strcpy_chk, + /// char * __strdup(const char *s); + dunder_strdup, + /// char *__strncpy_chk(char *s1, const char *s2, size_t n, + /// size_t s1size); + strncpy_chk, + /// char *__strndup(const char *s, size_t n); + dunder_strndup, + /// char * __strtok_r(char *s, const char *delim, char **save_ptr); + dunder_strtok_r, + /// int abs(int j); + abs, + /// int access(const char *path, int amode); + access, + /// double acos(double x); + acos, + /// float acosf(float x); + acosf, + /// double acosh(double x); + acosh, + /// float acoshf(float x); + acoshf, + /// long double acoshl(long double x); + acoshl, + /// long double acosl(long double x); + acosl, + /// double asin(double x); + asin, + /// float asinf(float x); + asinf, + /// double asinh(double x); + asinh, + /// float asinhf(float x); + asinhf, + /// long double asinhl(long double x); + asinhl, + /// long double asinl(long double x); + asinl, + /// double atan(double x); + atan, + /// double atan2(double y, double x); + atan2, + /// float atan2f(float y, float x); + atan2f, + /// long double atan2l(long double y, long double x); + atan2l, + /// float atanf(float x); + atanf, + /// double atanh(double x); + atanh, + /// float atanhf(float x); + atanhf, + /// long double atanhl(long double x); + atanhl, + /// long double atanl(long double x); + atanl, + /// double atof(const char *str); + atof, + /// int atoi(const char *str); + atoi, + /// long atol(const char *str); + atol, + /// long long atoll(const char *nptr); + atoll, + /// int bcmp(const void *s1, const void *s2, size_t n); + bcmp, + /// void bcopy(const void *s1, void *s2, size_t n); + bcopy, + /// void bzero(void *s, size_t n); + bzero, + /// void *calloc(size_t count, size_t size); + calloc, + /// double cbrt(double x); + cbrt, + /// float cbrtf(float x); + cbrtf, + /// long double cbrtl(long double x); + cbrtl, + /// double ceil(double x); + ceil, + /// float ceilf(float x); + ceilf, + /// long double ceill(long double x); + ceill, + /// int chmod(const char *path, mode_t mode); + chmod, + /// int chown(const char *path, uid_t owner, gid_t group); + chown, + /// void clearerr(FILE *stream); + clearerr, + /// int closedir(DIR *dirp); + closedir, + /// double copysign(double x, double y); + copysign, + /// float copysignf(float x, float y); + copysignf, + /// long double copysignl(long double x, long double y); + copysignl, + /// double cos(double x); + cos, + /// float cosf(float x); + cosf, + /// double cosh(double x); + cosh, + /// float coshf(float x); + coshf, + /// long double coshl(long double x); + coshl, + /// long double cosl(long double x); + cosl, + /// char *ctermid(char *s); + ctermid, + /// double exp(double x); + exp, + /// double exp10(double x); + exp10, + /// float exp10f(float x); + exp10f, + /// long double exp10l(long double x); + exp10l, + /// double exp2(double x); + exp2, + /// float exp2f(float x); + exp2f, + /// long double exp2l(long double x); + exp2l, + /// float expf(float x); + expf, + /// long double expl(long double x); + expl, + /// double expm1(double x); + expm1, + /// float expm1f(float x); + expm1f, + /// long double expm1l(long double x); + expm1l, + /// double fabs(double x); + fabs, + /// float fabsf(float x); + fabsf, + /// long double fabsl(long double x); + fabsl, + /// int fclose(FILE *stream); + fclose, + /// FILE *fdopen(int fildes, const char *mode); + fdopen, + /// int feof(FILE *stream); + feof, + /// int ferror(FILE *stream); + ferror, + /// int fflush(FILE *stream); + fflush, + /// int ffs(int i); + ffs, + /// int ffsl(long int i); + ffsl, + /// int ffsll(long long int i); + ffsll, + /// int fgetc(FILE *stream); + fgetc, + /// int fgetpos(FILE *stream, fpos_t *pos); + fgetpos, + /// char *fgets(char *s, int n, FILE *stream); + fgets, + /// int fileno(FILE *stream); + fileno, + /// int fiprintf(FILE *stream, const char *format, ...); + fiprintf, + /// void flockfile(FILE *file); + flockfile, + /// double floor(double x); + floor, + /// float floorf(float x); + floorf, + /// long double floorl(long double x); + floorl, + /// double fmax(double x, double y); + fmax, + /// float fmaxf(float x, float y); + fmaxf, + /// long double fmaxl(long double x, long double y); + fmaxl, + /// double fmin(double x, double y); + fmin, + /// float fminf(float x, float y); + fminf, + /// long double fminl(long double x, long double y); + fminl, + /// double fmod(double x, double y); + fmod, + /// float fmodf(float x, float y); + fmodf, + /// long double fmodl(long double x, long double y); + fmodl, + /// FILE *fopen(const char *filename, const char *mode); + fopen, + /// FILE *fopen64(const char *filename, const char *opentype) + fopen64, + /// int fprintf(FILE *stream, const char *format, ...); + fprintf, + /// int fputc(int c, FILE *stream); + fputc, + /// int fputs(const char *s, FILE *stream); + fputs, + /// size_t fread(void *ptr, size_t size, size_t nitems, FILE *stream); + fread, + /// void free(void *ptr); + free, + /// double frexp(double num, int *exp); + frexp, + /// float frexpf(float num, int *exp); + frexpf, + /// long double frexpl(long double num, int *exp); + frexpl, + /// int fscanf(FILE *stream, const char *format, ... ); + fscanf, + /// int fseek(FILE *stream, long offset, int whence); + fseek, + /// int fseeko(FILE *stream, off_t offset, int whence); + fseeko, + /// int fseeko64(FILE *stream, off64_t offset, int whence) + fseeko64, + /// int fsetpos(FILE *stream, const fpos_t *pos); + fsetpos, + /// int fstat(int fildes, struct stat *buf); + fstat, + /// int fstat64(int filedes, struct stat64 *buf) + fstat64, + /// int fstatvfs(int fildes, struct statvfs *buf); + fstatvfs, + /// int fstatvfs64(int fildes, struct statvfs64 *buf); + fstatvfs64, + /// long ftell(FILE *stream); + ftell, + /// off_t ftello(FILE *stream); + ftello, + /// off64_t ftello64(FILE *stream) + ftello64, + /// int ftrylockfile(FILE *file); + ftrylockfile, + /// void funlockfile(FILE *file); + funlockfile, + /// size_t fwrite(const void *ptr, size_t size, size_t nitems, + /// FILE *stream); + fwrite, + /// int getc(FILE *stream); + getc, + /// int getc_unlocked(FILE *stream); + getc_unlocked, + /// int getchar(void); + getchar, + /// char *getenv(const char *name); + getenv, + /// int getitimer(int which, struct itimerval *value); + getitimer, + /// int getlogin_r(char *name, size_t namesize); + getlogin_r, + /// struct passwd *getpwnam(const char *name); + getpwnam, + /// char *gets(char *s); + gets, + /// int gettimeofday(struct timeval *tp, void *tzp); + gettimeofday, + /// uint32_t htonl(uint32_t hostlong); + htonl, + /// uint16_t htons(uint16_t hostshort); + htons, + /// int iprintf(const char *format, ...); + iprintf, + /// int isascii(int c); + isascii, + /// int isdigit(int c); + isdigit, + /// long int labs(long int j); + labs, + /// int lchown(const char *path, uid_t owner, gid_t group); + lchown, + /// double ldexp(double x, int n); + ldexp, + /// float ldexpf(float x, int n); + ldexpf, + /// long double ldexpl(long double x, int n); + ldexpl, + /// long long int llabs(long long int j); + llabs, + /// double log(double x); + log, + /// double log10(double x); + log10, + /// float log10f(float x); + log10f, + /// long double log10l(long double x); + log10l, + /// double log1p(double x); + log1p, + /// float log1pf(float x); + log1pf, + /// long double log1pl(long double x); + log1pl, + /// double log2(double x); + log2, + /// float log2f(float x); + log2f, + /// double long double log2l(long double x); + log2l, + /// double logb(double x); + logb, + /// float logbf(float x); + logbf, + /// long double logbl(long double x); + logbl, + /// float logf(float x); + logf, + /// long double logl(long double x); + logl, + /// int lstat(const char *path, struct stat *buf); + lstat, + /// int lstat64(const char *path, struct stat64 *buf); + lstat64, + /// void *malloc(size_t size); + malloc, + /// void *memalign(size_t boundary, size_t size); + memalign, + /// void *memccpy(void *s1, const void *s2, int c, size_t n); + memccpy, + /// void *memchr(const void *s, int c, size_t n); + memchr, + /// int memcmp(const void *s1, const void *s2, size_t n); + memcmp, + /// void *memcpy(void *s1, const void *s2, size_t n); + memcpy, + /// void *memmove(void *s1, const void *s2, size_t n); + memmove, + // void *memrchr(const void *s, int c, size_t n); + memrchr, + /// void *memset(void *b, int c, size_t len); + memset, + /// void memset_pattern16(void *b, const void *pattern16, size_t len); + memset_pattern16, + /// int mkdir(const char *path, mode_t mode); + mkdir, + /// time_t mktime(struct tm *timeptr); + mktime, + /// double modf(double x, double *iptr); + modf, + /// float modff(float, float *iptr); + modff, + /// long double modfl(long double value, long double *iptr); + modfl, + /// double nearbyint(double x); + nearbyint, + /// float nearbyintf(float x); + nearbyintf, + /// long double nearbyintl(long double x); + nearbyintl, + /// uint32_t ntohl(uint32_t netlong); + ntohl, + /// uint16_t ntohs(uint16_t netshort); + ntohs, + /// int open(const char *path, int oflag, ... ); + open, + /// int open64(const char *filename, int flags[, mode_t mode]) + open64, + /// DIR *opendir(const char *dirname); + opendir, + /// int pclose(FILE *stream); + pclose, + /// void perror(const char *s); + perror, + /// FILE *popen(const char *command, const char *mode); + popen, + /// int posix_memalign(void **memptr, size_t alignment, size_t size); + posix_memalign, + /// double pow(double x, double y); + pow, + /// float powf(float x, float y); + powf, + /// long double powl(long double x, long double y); + powl, + /// ssize_t pread(int fildes, void *buf, size_t nbyte, off_t offset); + pread, + /// int printf(const char *format, ...); + printf, + /// int putc(int c, FILE *stream); + putc, + /// int putchar(int c); + putchar, + /// int puts(const char *s); + puts, + /// ssize_t pwrite(int fildes, const void *buf, size_t nbyte, + /// off_t offset); + pwrite, + /// void qsort(void *base, size_t nel, size_t width, + /// int (*compar)(const void *, const void *)); + qsort, + /// ssize_t read(int fildes, void *buf, size_t nbyte); + read, + /// ssize_t readlink(const char *path, char *buf, size_t bufsize); + readlink, + /// void *realloc(void *ptr, size_t size); + realloc, + /// void *reallocf(void *ptr, size_t size); + reallocf, + /// char *realpath(const char *file_name, char *resolved_name); + realpath, + /// int remove(const char *path); + remove, + /// int rename(const char *old, const char *new); + rename, + /// void rewind(FILE *stream); + rewind, + /// double rint(double x); + rint, + /// float rintf(float x); + rintf, + /// long double rintl(long double x); + rintl, + /// int rmdir(const char *path); + rmdir, + /// double round(double x); + round, + /// float roundf(float x); + roundf, + /// long double roundl(long double x); + roundl, + /// int scanf(const char *restrict format, ... ); + scanf, + /// void setbuf(FILE *stream, char *buf); + setbuf, + /// int setitimer(int which, const struct itimerval *value, + /// struct itimerval *ovalue); + setitimer, + /// int setvbuf(FILE *stream, char *buf, int type, size_t size); + setvbuf, + /// double sin(double x); + sin, + /// float sinf(float x); + sinf, + /// double sinh(double x); + sinh, + /// float sinhf(float x); + sinhf, + /// long double sinhl(long double x); + sinhl, + /// long double sinl(long double x); + sinl, + /// int siprintf(char *str, const char *format, ...); + siprintf, + /// int snprintf(char *s, size_t n, const char *format, ...); + snprintf, + /// int sprintf(char *str, const char *format, ...); + sprintf, + /// double sqrt(double x); + sqrt, + /// float sqrtf(float x); + sqrtf, + /// long double sqrtl(long double x); + sqrtl, + /// int sscanf(const char *s, const char *format, ... ); + sscanf, + /// int stat(const char *path, struct stat *buf); + stat, + /// int stat64(const char *path, struct stat64 *buf); + stat64, + /// int statvfs(const char *path, struct statvfs *buf); + statvfs, + /// int statvfs64(const char *path, struct statvfs64 *buf) + statvfs64, + /// char *stpcpy(char *s1, const char *s2); + stpcpy, + /// char *stpncpy(char *s1, const char *s2, size_t n); + stpncpy, + /// int strcasecmp(const char *s1, const char *s2); + strcasecmp, + /// char *strcat(char *s1, const char *s2); + strcat, + /// char *strchr(const char *s, int c); + strchr, + /// int strcmp(const char *s1, const char *s2); + strcmp, + /// int strcoll(const char *s1, const char *s2); + strcoll, + /// char *strcpy(char *s1, const char *s2); + strcpy, + /// size_t strcspn(const char *s1, const char *s2); + strcspn, + /// char *strdup(const char *s1); + strdup, + /// size_t strlen(const char *s); + strlen, + /// int strncasecmp(const char *s1, const char *s2, size_t n); + strncasecmp, + /// char *strncat(char *s1, const char *s2, size_t n); + strncat, + /// int strncmp(const char *s1, const char *s2, size_t n); + strncmp, + /// char *strncpy(char *s1, const char *s2, size_t n); + strncpy, + /// char *strndup(const char *s1, size_t n); + strndup, + /// size_t strnlen(const char *s, size_t maxlen); + strnlen, + /// char *strpbrk(const char *s1, const char *s2); + strpbrk, + /// char *strrchr(const char *s, int c); + strrchr, + /// size_t strspn(const char *s1, const char *s2); + strspn, + /// char *strstr(const char *s1, const char *s2); + strstr, + /// double strtod(const char *nptr, char **endptr); + strtod, + /// float strtof(const char *nptr, char **endptr); + strtof, + // char *strtok(char *s1, const char *s2); + strtok, + // char *strtok_r(char *s, const char *sep, char **lasts); + strtok_r, + /// long int strtol(const char *nptr, char **endptr, int base); + strtol, + /// long double strtold(const char *nptr, char **endptr); + strtold, + /// long long int strtoll(const char *nptr, char **endptr, int base); + strtoll, + /// unsigned long int strtoul(const char *nptr, char **endptr, int base); + strtoul, + /// unsigned long long int strtoull(const char *nptr, char **endptr, + /// int base); + strtoull, + /// size_t strxfrm(char *s1, const char *s2, size_t n); + strxfrm, + /// int system(const char *command); + system, + /// double tan(double x); + tan, + /// float tanf(float x); + tanf, + /// double tanh(double x); + tanh, + /// float tanhf(float x); + tanhf, + /// long double tanhl(long double x); + tanhl, + /// long double tanl(long double x); + tanl, + /// clock_t times(struct tms *buffer); + times, + /// FILE *tmpfile(void); + tmpfile, + /// FILE *tmpfile64(void) + tmpfile64, + /// int toascii(int c); + toascii, + /// double trunc(double x); + trunc, + /// float truncf(float x); + truncf, + /// long double truncl(long double x); + truncl, + /// int uname(struct utsname *name); + uname, + /// int ungetc(int c, FILE *stream); + ungetc, + /// int unlink(const char *path); + unlink, + /// int unsetenv(const char *name); + unsetenv, + /// int utime(const char *path, const struct utimbuf *times); + utime, + /// int utimes(const char *path, const struct timeval times[2]); + utimes, + /// void *valloc(size_t size); + valloc, + /// int vfprintf(FILE *stream, const char *format, va_list ap); + vfprintf, + /// int vfscanf(FILE *stream, const char *format, va_list arg); + vfscanf, + /// int vprintf(const char *restrict format, va_list ap); + vprintf, + /// int vscanf(const char *format, va_list arg); + vscanf, + /// int vsnprintf(char *s, size_t n, const char *format, va_list ap); + vsnprintf, + /// int vsprintf(char *s, const char *format, va_list ap); + vsprintf, + /// int vsscanf(const char *s, const char *format, va_list arg); + vsscanf, + /// ssize_t write(int fildes, const void *buf, size_t nbyte); + write, + + NumLibFuncs + }; + } + +/// \brief Implementation of the target library information. +/// +/// This class constructs tables that hold the target library information and +/// make it available. However, it is somewhat expensive to compute and only +/// depends on the triple. So users typicaly interact with the \c +/// TargetLibraryInfo wrapper below. +class TargetLibraryInfoImpl { + friend class TargetLibraryInfo; + + unsigned char AvailableArray[(LibFunc::NumLibFuncs+3)/4]; + llvm::DenseMap CustomNames; + static const char* StandardNames[LibFunc::NumLibFuncs]; + + enum AvailabilityState { + StandardName = 3, // (memset to all ones) + CustomName = 1, + Unavailable = 0 // (memset to all zeros) + }; + void setState(LibFunc::Func F, AvailabilityState State) { + AvailableArray[F/4] &= ~(3 << 2*(F&3)); + AvailableArray[F/4] |= State << 2*(F&3); + } + AvailabilityState getState(LibFunc::Func F) const { + return static_cast((AvailableArray[F/4] >> 2*(F&3)) & 3); + } + +public: + TargetLibraryInfoImpl(); + explicit TargetLibraryInfoImpl(const Triple &T); + + // Provide value semantics. + TargetLibraryInfoImpl(const TargetLibraryInfoImpl &TLI); + TargetLibraryInfoImpl(TargetLibraryInfoImpl &&TLI); + TargetLibraryInfoImpl &operator=(const TargetLibraryInfoImpl &TLI); + TargetLibraryInfoImpl &operator=(TargetLibraryInfoImpl &&TLI); + + /// \brief Searches for a particular function name. + /// + /// If it is one of the known library functions, return true and set F to the + /// corresponding value. + bool getLibFunc(StringRef funcName, LibFunc::Func &F) const; + + /// \brief Forces a function to be marked as unavailable. + void setUnavailable(LibFunc::Func F) { + setState(F, Unavailable); + } + + /// \brief Forces a function to be marked as available. + void setAvailable(LibFunc::Func F) { + setState(F, StandardName); + } + + /// \brief Forces a function to be marked as available and provide an + /// alternate name that must be used. + void setAvailableWithName(LibFunc::Func F, StringRef Name) { + if (StandardNames[F] != Name) { + setState(F, CustomName); + CustomNames[F] = Name; + assert(CustomNames.find(F) != CustomNames.end()); + } else { + setState(F, StandardName); + } + } + + /// \brief Disables all builtins. + /// + /// This can be used for options like -fno-builtin. + void disableAllFunctions(); +}; + +/// \brief Provides information about what library functions are available for +/// the current target. +/// +/// This both allows optimizations to handle them specially and frontends to +/// disable such optimizations through -fno-builtin etc. +class TargetLibraryInfo { + friend class TargetLibraryAnalysis; + friend class TargetLibraryInfoWrapperPass; + + const TargetLibraryInfoImpl *Impl; + +public: + explicit TargetLibraryInfo(const TargetLibraryInfoImpl &Impl) : Impl(&Impl) {} + + // Provide value semantics. + TargetLibraryInfo(const TargetLibraryInfo &TLI) : Impl(TLI.Impl) {} + TargetLibraryInfo(TargetLibraryInfo &&TLI) : Impl(TLI.Impl) {} + TargetLibraryInfo &operator=(const TargetLibraryInfo &TLI) { + Impl = TLI.Impl; + return *this; + } + TargetLibraryInfo &operator=(TargetLibraryInfo &&TLI) { + Impl = TLI.Impl; + return *this; + } + + /// \brief Searches for a particular function name. + /// + /// If it is one of the known library functions, return true and set F to the + /// corresponding value. + bool getLibFunc(StringRef funcName, LibFunc::Func &F) const { + return Impl->getLibFunc(funcName, F); + } + + /// \brief Tests wether a library function is available. + bool has(LibFunc::Func F) const { + return Impl->getState(F) != TargetLibraryInfoImpl::Unavailable; + } + + /// \brief Tests if the function is both available and a candidate for + /// optimized code generation. + bool hasOptimizedCodeGen(LibFunc::Func F) const { + if (Impl->getState(F) == TargetLibraryInfoImpl::Unavailable) + return false; + switch (F) { + default: break; + case LibFunc::copysign: case LibFunc::copysignf: case LibFunc::copysignl: + case LibFunc::fabs: case LibFunc::fabsf: case LibFunc::fabsl: + case LibFunc::sin: case LibFunc::sinf: case LibFunc::sinl: + case LibFunc::cos: case LibFunc::cosf: case LibFunc::cosl: + case LibFunc::sqrt: case LibFunc::sqrtf: case LibFunc::sqrtl: + case LibFunc::sqrt_finite: case LibFunc::sqrtf_finite: + case LibFunc::sqrtl_finite: + case LibFunc::fmax: case LibFunc::fmaxf: case LibFunc::fmaxl: + case LibFunc::fmin: case LibFunc::fminf: case LibFunc::fminl: + case LibFunc::floor: case LibFunc::floorf: case LibFunc::floorl: + case LibFunc::nearbyint: case LibFunc::nearbyintf: case LibFunc::nearbyintl: + case LibFunc::ceil: case LibFunc::ceilf: case LibFunc::ceill: + case LibFunc::rint: case LibFunc::rintf: case LibFunc::rintl: + case LibFunc::round: case LibFunc::roundf: case LibFunc::roundl: + case LibFunc::trunc: case LibFunc::truncf: case LibFunc::truncl: + case LibFunc::log2: case LibFunc::log2f: case LibFunc::log2l: + case LibFunc::exp2: case LibFunc::exp2f: case LibFunc::exp2l: + case LibFunc::memcmp: case LibFunc::strcmp: case LibFunc::strcpy: + case LibFunc::stpcpy: case LibFunc::strlen: case LibFunc::strnlen: + case LibFunc::memchr: + return true; + } + return false; + } + + StringRef getName(LibFunc::Func F) const { + auto State = Impl->getState(F); + if (State == TargetLibraryInfoImpl::Unavailable) + return StringRef(); + if (State == TargetLibraryInfoImpl::StandardName) + return Impl->StandardNames[F]; + assert(State == TargetLibraryInfoImpl::CustomName); + return Impl->CustomNames.find(F)->second; + } + + /// \brief Handle invalidation from the pass manager. + /// + /// If we try to invalidate this info, just return false. It cannot become + /// invalid even if the module changes. + bool invalidate(Module &, const PreservedAnalyses &) { return false; } +}; + +/// \brief Analysis pass providing the \c TargetLibraryInfo. +/// +/// Note that this pass's result cannot be invalidated, it is immutable for the +/// life of the module. +class TargetLibraryAnalysis { +public: + typedef TargetLibraryInfo Result; + + /// \brief Opaque, unique identifier for this analysis pass. + static void *ID() { return (void *)&PassID; } + + /// \brief Default construct the library analysis. + /// + /// This will use the module's triple to construct the library info for that + /// module. + TargetLibraryAnalysis() {} + + /// \brief Construct a library analysis with preset info. + /// + /// This will directly copy the preset info into the result without + /// consulting the module's triple. + TargetLibraryAnalysis(TargetLibraryInfoImpl PresetInfoImpl) + : PresetInfoImpl(std::move(PresetInfoImpl)) {} + + // Move semantics. We spell out the constructors for MSVC. + TargetLibraryAnalysis(TargetLibraryAnalysis &&Arg) + : PresetInfoImpl(std::move(Arg.PresetInfoImpl)), Impls(std::move(Arg.Impls)) {} + TargetLibraryAnalysis &operator=(TargetLibraryAnalysis &&RHS) { + PresetInfoImpl = std::move(RHS.PresetInfoImpl); + Impls = std::move(RHS.Impls); + return *this; + } + + TargetLibraryInfo run(Module &M); + TargetLibraryInfo run(Function &F); + + /// \brief Provide access to a name for this pass for debugging purposes. + static StringRef name() { return "TargetLibraryAnalysis"; } + +private: + static char PassID; + + Optional PresetInfoImpl; + + StringMap> Impls; + + TargetLibraryInfoImpl &lookupInfoImpl(Triple T); +}; + +class TargetLibraryInfoWrapperPass : public ImmutablePass { + TargetLibraryInfoImpl TLIImpl; + TargetLibraryInfo TLI; + + virtual void anchor(); + +public: + static char ID; + TargetLibraryInfoWrapperPass(); + explicit TargetLibraryInfoWrapperPass(const Triple &T); + explicit TargetLibraryInfoWrapperPass(const TargetLibraryInfoImpl &TLI); + + TargetLibraryInfo &getTLI() { return TLI; } + const TargetLibraryInfo &getTLI() const { return TLI; } +}; + +} // end namespace llvm + +#endif diff --git a/include/llvm/Analysis/TargetTransformInfo.h b/include/llvm/Analysis/TargetTransformInfo.h index 9acaaa6..4998141 100644 --- a/include/llvm/Analysis/TargetTransformInfo.h +++ b/include/llvm/Analysis/TargetTransformInfo.h @@ -1,4 +1,4 @@ -//===- llvm/Analysis/TargetTransformInfo.h ----------------------*- C++ -*-===// +//===- TargetTransformInfo.h ------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -6,22 +6,24 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// This pass exposes codegen information to IR-level passes. Every -// transformation that uses codegen information is broken into three parts: -// 1. The IR-level analysis pass. -// 2. The IR-level transformation interface which provides the needed -// information. -// 3. Codegen-level implementation which uses target-specific hooks. -// -// This file defines #2, which is the interface that IR-level transformations -// use for querying the codegen. -// +/// \file +/// This pass exposes codegen information to IR-level passes. Every +/// transformation that uses codegen information is broken into three parts: +/// 1. The IR-level analysis pass. +/// 2. The IR-level transformation interface which provides the needed +/// information. +/// 3. Codegen-level implementation which uses target-specific hooks. +/// +/// This file defines #2, which is the interface that IR-level transformations +/// use for querying the codegen. +/// //===----------------------------------------------------------------------===// #ifndef LLVM_ANALYSIS_TARGETTRANSFORMINFO_H #define LLVM_ANALYSIS_TARGETTRANSFORMINFO_H +#include "llvm/ADT/Optional.h" +#include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/Intrinsics.h" #include "llvm/Pass.h" #include "llvm/Support/DataTypes.h" @@ -31,41 +33,61 @@ namespace llvm { class Function; class GlobalValue; class Loop; +class PreservedAnalyses; class Type; class User; class Value; -/// TargetTransformInfo - This pass provides access to the codegen -/// interfaces that are needed for IR-level transformations. +/// \brief Information about a load/store intrinsic defined by the target. +struct MemIntrinsicInfo { + MemIntrinsicInfo() + : ReadMem(false), WriteMem(false), Vol(false), MatchingId(0), + NumMemRefs(0), PtrVal(nullptr) {} + bool ReadMem; + bool WriteMem; + bool Vol; + // Same Id is set by the target for corresponding load/store intrinsics. + unsigned short MatchingId; + int NumMemRefs; + Value *PtrVal; +}; + +/// \brief This pass provides access to the codegen interfaces that are needed +/// for IR-level transformations. class TargetTransformInfo { -protected: - /// \brief The TTI instance one level down the stack. +public: + /// \brief Construct a TTI object using a type implementing the \c Concept + /// API below. /// - /// This is used to implement the default behavior all of the methods which - /// is to delegate up through the stack of TTIs until one can answer the - /// query. - TargetTransformInfo *PrevTTI; + /// This is used by targets to construct a TTI wrapping their target-specific + /// implementaion that encodes appropriate costs for their target. + template TargetTransformInfo(T Impl); - /// \brief The top of the stack of TTI analyses available. + /// \brief Construct a baseline TTI object using a minimal implementation of + /// the \c Concept API below. /// - /// This is a convenience routine maintained as TTI analyses become available - /// that complements the PrevTTI delegation chain. When one part of an - /// analysis pass wants to query another part of the analysis pass it can use - /// this to start back at the top of the stack. - TargetTransformInfo *TopTTI; + /// The TTI implementation will reflect the information in the DataLayout + /// provided if non-null. + explicit TargetTransformInfo(const DataLayout *DL); - /// All pass subclasses must in their initializePass routine call - /// pushTTIStack with themselves to update the pointers tracking the previous - /// TTI instance in the analysis group's stack, and the top of the analysis - /// group's stack. - void pushTTIStack(Pass *P); + // Provide move semantics. + TargetTransformInfo(TargetTransformInfo &&Arg); + TargetTransformInfo &operator=(TargetTransformInfo &&RHS); - /// All pass subclasses must call TargetTransformInfo::getAnalysisUsage. - virtual void getAnalysisUsage(AnalysisUsage &AU) const; + // We need to define the destructor out-of-line to define our sub-classes + // out-of-line. + ~TargetTransformInfo(); -public: - /// This class is intended to be subclassed by real implementations. - virtual ~TargetTransformInfo() = 0; + /// \brief Handle the invalidation of this information. + /// + /// When used as a result of \c TargetIRAnalysis this method will be called + /// when the function this was computed for changes. When it returns false, + /// the information is preserved across those changes. + bool invalidate(Function &, const PreservedAnalyses &) { + // FIXME: We should probably in some way ensure that the subtarget + // information for a function hasn't changed. + return false; + } /// \name Generic Target Information /// @{ @@ -86,9 +108,9 @@ public: /// skipped by renaming the registers in the CPU, but they still are encoded /// and thus wouldn't be considered 'free' here. enum TargetCostConstants { - TCC_Free = 0, ///< Expected to fold away in lowering. - TCC_Basic = 1, ///< The cost of a typical 'add' instruction. - TCC_Expensive = 4 ///< The cost of a 'div' instruction on x86. + TCC_Free = 0, ///< Expected to fold away in lowering. + TCC_Basic = 1, ///< The cost of a typical 'add' instruction. + TCC_Expensive = 4 ///< The cost of a 'div' instruction on x86. }; /// \brief Estimate the cost of a specific operation when lowered. @@ -105,16 +127,15 @@ public: /// /// The returned cost is defined in terms of \c TargetCostConstants, see its /// comments for a detailed explanation of the cost values. - virtual unsigned getOperationCost(unsigned Opcode, Type *Ty, - Type *OpTy = nullptr) const; + unsigned getOperationCost(unsigned Opcode, Type *Ty, + Type *OpTy = nullptr) const; /// \brief Estimate the cost of a GEP operation when lowered. /// /// The contract for this function is the same as \c getOperationCost except /// that it supports an interface that provides extra information specific to /// the GEP operation. - virtual unsigned getGEPCost(const Value *Ptr, - ArrayRef Operands) const; + unsigned getGEPCost(const Value *Ptr, ArrayRef Operands) const; /// \brief Estimate the cost of a function call when lowered. /// @@ -125,31 +146,31 @@ public: /// This is the most basic query for estimating call cost: it only knows the /// function type and (potentially) the number of arguments at the call site. /// The latter is only interesting for varargs function types. - virtual unsigned getCallCost(FunctionType *FTy, int NumArgs = -1) const; + unsigned getCallCost(FunctionType *FTy, int NumArgs = -1) const; /// \brief Estimate the cost of calling a specific function when lowered. /// /// This overload adds the ability to reason about the particular function /// being called in the event it is a library call with special lowering. - virtual unsigned getCallCost(const Function *F, int NumArgs = -1) const; + unsigned getCallCost(const Function *F, int NumArgs = -1) const; /// \brief Estimate the cost of calling a specific function when lowered. /// /// This overload allows specifying a set of candidate argument values. - virtual unsigned getCallCost(const Function *F, - ArrayRef Arguments) const; + unsigned getCallCost(const Function *F, + ArrayRef Arguments) const; /// \brief Estimate the cost of an intrinsic when lowered. /// /// Mirrors the \c getCallCost method but uses an intrinsic identifier. - virtual unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy, - ArrayRef ParamTys) const; + unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy, + ArrayRef ParamTys) const; /// \brief Estimate the cost of an intrinsic when lowered. /// /// Mirrors the \c getCallCost method but uses an intrinsic identifier. - virtual unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy, - ArrayRef Arguments) const; + unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy, + ArrayRef Arguments) const; /// \brief Estimate the cost of a given IR user when lowered. /// @@ -166,13 +187,13 @@ public: /// /// The returned cost is defined in terms of \c TargetCostConstants, see its /// comments for a detailed explanation of the cost values. - virtual unsigned getUserCost(const User *U) const; + unsigned getUserCost(const User *U) const; /// \brief hasBranchDivergence - Return true if branch divergence exists. /// Branch divergence has a significantly negative impact on GPU performance /// when threads in the same wavefront take different paths due to conditional /// branches. - virtual bool hasBranchDivergence() const; + bool hasBranchDivergence() const; /// \brief Test whether calls to a function lower to actual program function /// calls. @@ -186,7 +207,7 @@ public: /// and execution-speed costs. This would allow modelling the core of this /// query more accurately as a call is a single small instruction, but /// incurs significant execution cost. - virtual bool isLoweredToCall(const Function *F) const; + bool isLoweredToCall(const Function *F) const; /// Parameters that control the generic loop unrolling transformation. struct UnrollingPreferences { @@ -196,6 +217,13 @@ public: /// exceed this cost. Set this to UINT_MAX to disable the loop body cost /// restriction. unsigned Threshold; + /// If complete unrolling could help other optimizations (e.g. InstSimplify) + /// to remove N% of instructions, then we can go beyond unroll threshold. + /// This value set the minimal percent for allowing that. + unsigned MinPercentOfOptimized; + /// The absolute cost threshold. We won't go beyond this even if complete + /// unrolling could result in optimizing out 90% of instructions. + unsigned AbsoluteThreshold; /// The cost threshold for the unrolled loop when optimizing for size (set /// to UINT_MAX to disable). unsigned OptSizeThreshold; @@ -203,8 +231,8 @@ public: /// for partial/runtime unrolling (set to UINT_MAX to disable). unsigned PartialThreshold; /// The cost threshold for the unrolled loop when optimizing for size, like - /// OptSizeThreshold, but used for partial/runtime unrolling (set to UINT_MAX - /// to disable). + /// OptSizeThreshold, but used for partial/runtime unrolling (set to + /// UINT_MAX to disable). unsigned PartialOptSizeThreshold; /// A forced unrolling factor (the number of concatenated bodies of the /// original loop in the unrolled loop body). When set to 0, the unrolling @@ -218,18 +246,17 @@ public: unsigned MaxCount; /// Allow partial unrolling (unrolling of loops to expand the size of the /// loop body, not only to eliminate small constant-trip-count loops). - bool Partial; + bool Partial; /// Allow runtime unrolling (unrolling of loops to expand the size of the - /// loop body even when the number of loop iterations is not known at compile - /// time). - bool Runtime; + /// loop body even when the number of loop iterations is not known at + /// compile time). + bool Runtime; }; /// \brief Get target-customized preferences for the generic loop unrolling /// transformation. The caller will initialize UP with the current /// target-independent defaults. - virtual void getUnrollingPreferences(const Function *F, Loop *L, - UnrollingPreferences &UP) const; + void getUnrollingPreferences(Loop *L, UnrollingPreferences &UP) const; /// @} @@ -244,31 +271,33 @@ public: /// support is considered as "Fast" if it can outperform, or is on a par /// with, SW implementation when the population is sparse; otherwise, it is /// considered as "Slow". - enum PopcntSupportKind { - PSK_Software, - PSK_SlowHardware, - PSK_FastHardware - }; + enum PopcntSupportKind { PSK_Software, PSK_SlowHardware, PSK_FastHardware }; /// \brief Return true if the specified immediate is legal add immediate, that /// is the target has add instructions which can add a register with the /// immediate without having to materialize the immediate into a register. - virtual bool isLegalAddImmediate(int64_t Imm) const; + bool isLegalAddImmediate(int64_t Imm) const; /// \brief Return true if the specified immediate is legal icmp immediate, /// that is the target has icmp instructions which can compare a register /// against the immediate without having to materialize the immediate into a /// register. - virtual bool isLegalICmpImmediate(int64_t Imm) const; + bool isLegalICmpImmediate(int64_t Imm) const; /// \brief Return true if the addressing mode represented by AM is legal for /// this target, for a load/store of the specified type. /// The type may be VoidTy, in which case only return true if the addressing /// mode is legal for a load/store of any legal type. /// TODO: Handle pre/postinc as well. - virtual bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV, - int64_t BaseOffset, bool HasBaseReg, - int64_t Scale) const; + bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset, + bool HasBaseReg, int64_t Scale) const; + + /// \brief Return true if the target works with masked instruction + /// AVX2 allows masks for consecutive load and store for i32 and i64 elements. + /// AVX-512 architecture will also allow masks for non-consecutive memory + /// accesses. + bool isLegalMaskedStore(Type *DataType, int Consecutive) const; + bool isLegalMaskedLoad(Type *DataType, int Consecutive) const; /// \brief Return the cost of the scaling factor used in the addressing /// mode represented by AM for this target, for a load/store @@ -276,45 +305,52 @@ public: /// If the AM is supported, the return value must be >= 0. /// If the AM is not supported, it returns a negative value. /// TODO: Handle pre/postinc as well. - virtual int getScalingFactorCost(Type *Ty, GlobalValue *BaseGV, - int64_t BaseOffset, bool HasBaseReg, - int64_t Scale) const; + int getScalingFactorCost(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset, + bool HasBaseReg, int64_t Scale) const; /// \brief Return true if it's free to truncate a value of type Ty1 to type /// Ty2. e.g. On x86 it's free to truncate a i32 value in register EAX to i16 /// by referencing its sub-register AX. - virtual bool isTruncateFree(Type *Ty1, Type *Ty2) const; + bool isTruncateFree(Type *Ty1, Type *Ty2) const; + + /// \brief Return true if it is profitable to hoist instruction in the + /// then/else to before if. + bool isProfitableToHoist(Instruction *I) const; /// \brief Return true if this type is legal. - virtual bool isTypeLegal(Type *Ty) const; + bool isTypeLegal(Type *Ty) const; /// \brief Returns the target's jmp_buf alignment in bytes. - virtual unsigned getJumpBufAlignment() const; + unsigned getJumpBufAlignment() const; /// \brief Returns the target's jmp_buf size in bytes. - virtual unsigned getJumpBufSize() const; + unsigned getJumpBufSize() const; /// \brief Return true if switches should be turned into lookup tables for the /// target. - virtual bool shouldBuildLookupTables() const; + bool shouldBuildLookupTables() const; /// \brief Return hardware support for population count. - virtual PopcntSupportKind getPopcntSupport(unsigned IntTyWidthInBit) const; + PopcntSupportKind getPopcntSupport(unsigned IntTyWidthInBit) const; /// \brief Return true if the hardware has a fast square-root instruction. - virtual bool haveFastSqrt(Type *Ty) const; + bool haveFastSqrt(Type *Ty) const; + + /// \brief Return the expected cost of supporting the floating point operation + /// of the specified type. + unsigned getFPOpCost(Type *Ty) const; /// \brief Return the expected cost of materializing for the given integer /// immediate of the specified type. - virtual unsigned getIntImmCost(const APInt &Imm, Type *Ty) const; + unsigned getIntImmCost(const APInt &Imm, Type *Ty) const; /// \brief Return the expected cost of materialization for the given integer /// immediate of the specified type for a given instruction. The cost can be /// zero if the immediate can be folded into the specified instruction. - virtual unsigned getIntImmCost(unsigned Opc, unsigned Idx, const APInt &Imm, - Type *Ty) const; - virtual unsigned getIntImmCost(Intrinsic::ID IID, unsigned Idx, - const APInt &Imm, Type *Ty) const; + unsigned getIntImmCost(unsigned Opc, unsigned Idx, const APInt &Imm, + Type *Ty) const; + unsigned getIntImmCost(Intrinsic::ID IID, unsigned Idx, const APInt &Imm, + Type *Ty) const; /// @} /// \name Vector Target Information @@ -331,10 +367,10 @@ public: /// \brief Additional information about an operand's possible values. enum OperandValueKind { - OK_AnyValue, // Operand can have any value. - OK_UniformValue, // Operand is uniform (splat of a value). - OK_UniformConstantValue, // Operand is uniform constant. - OK_NonUniformConstantValue // Operand is a non uniform constant value. + OK_AnyValue, // Operand can have any value. + OK_UniformValue, // Operand is uniform (splat of a value). + OK_UniformConstantValue, // Operand is uniform constant. + OK_NonUniformConstantValue // Operand is a non uniform constant value. }; /// \brief Additional properties of an operand's values. @@ -343,18 +379,18 @@ public: /// \return The number of scalar or vector registers that the target has. /// If 'Vectors' is true, it returns the number of vector registers. If it is /// set to false, it returns the number of scalar registers. - virtual unsigned getNumberOfRegisters(bool Vector) const; + unsigned getNumberOfRegisters(bool Vector) const; /// \return The width of the largest scalar or vector register type. - virtual unsigned getRegisterBitWidth(bool Vector) const; + unsigned getRegisterBitWidth(bool Vector) const; /// \return The maximum interleave factor that any transform should try to /// perform for this target. This number depends on the level of parallelism /// and the number of execution units in the CPU. - virtual unsigned getMaxInterleaveFactor() const; + unsigned getMaxInterleaveFactor() const; /// \return The expected cost of arithmetic ops, such as mul, xor, fsub, etc. - virtual unsigned + unsigned getArithmeticInstrCost(unsigned Opcode, Type *Ty, OperandValueKind Opd1Info = OK_AnyValue, OperandValueKind Opd2Info = OK_AnyValue, @@ -364,31 +400,33 @@ public: /// \return The cost of a shuffle instruction of kind Kind and of type Tp. /// The index and subtype parameters are used by the subvector insertion and /// extraction shuffle kinds. - virtual unsigned getShuffleCost(ShuffleKind Kind, Type *Tp, int Index = 0, - Type *SubTp = nullptr) const; + unsigned getShuffleCost(ShuffleKind Kind, Type *Tp, int Index = 0, + Type *SubTp = nullptr) const; /// \return The expected cost of cast instructions, such as bitcast, trunc, /// zext, etc. - virtual unsigned getCastInstrCost(unsigned Opcode, Type *Dst, - Type *Src) const; + unsigned getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src) const; /// \return The expected cost of control-flow related instructions such as /// Phi, Ret, Br. - virtual unsigned getCFInstrCost(unsigned Opcode) const; + unsigned getCFInstrCost(unsigned Opcode) const; /// \returns The expected cost of compare and select instructions. - virtual unsigned getCmpSelInstrCost(unsigned Opcode, Type *ValTy, - Type *CondTy = nullptr) const; + unsigned getCmpSelInstrCost(unsigned Opcode, Type *ValTy, + Type *CondTy = nullptr) const; /// \return The expected cost of vector Insert and Extract. /// Use -1 to indicate that there is no information on the index value. - virtual unsigned getVectorInstrCost(unsigned Opcode, Type *Val, - unsigned Index = -1) const; + unsigned getVectorInstrCost(unsigned Opcode, Type *Val, + unsigned Index = -1) const; /// \return The cost of Load and Store instructions. - virtual unsigned getMemoryOpCost(unsigned Opcode, Type *Src, - unsigned Alignment, - unsigned AddressSpace) const; + unsigned getMemoryOpCost(unsigned Opcode, Type *Src, unsigned Alignment, + unsigned AddressSpace) const; + + /// \return The cost of masked Load and Store instructions. + unsigned getMaskedMemoryOpCost(unsigned Opcode, Type *Src, unsigned Alignment, + unsigned AddressSpace) const; /// \brief Calculate the cost of performing a vector reduction. /// @@ -403,16 +441,16 @@ public: /// Split: /// (v0, v1, v2, v3) /// ((v0+v2), (v1+v3), undef, undef) - virtual unsigned getReductionCost(unsigned Opcode, Type *Ty, - bool IsPairwiseForm) const; + unsigned getReductionCost(unsigned Opcode, Type *Ty, + bool IsPairwiseForm) const; /// \returns The cost of Intrinsic instructions. - virtual unsigned getIntrinsicInstrCost(Intrinsic::ID ID, Type *RetTy, - ArrayRef Tys) const; + unsigned getIntrinsicInstrCost(Intrinsic::ID ID, Type *RetTy, + ArrayRef Tys) const; /// \returns The number of pieces into which the provided type must be /// split during legalization. Zero is returned when the answer is unknown. - virtual unsigned getNumberOfParts(Type *Tp) const; + unsigned getNumberOfParts(Type *Tp) const; /// \returns The cost of the address computation. For most targets this can be /// merged into the instruction indexing mode. Some targets might want to @@ -421,28 +459,385 @@ public: /// The 'IsComplex' parameter is a hint that the address computation is likely /// to involve multiple instructions and as such unlikely to be merged into /// the address indexing mode. - virtual unsigned getAddressComputationCost(Type *Ty, - bool IsComplex = false) const; + unsigned getAddressComputationCost(Type *Ty, bool IsComplex = false) const; /// \returns The cost, if any, of keeping values of the given types alive /// over a callsite. /// /// Some types may require the use of register classes that do not have /// any callee-saved registers, so would require a spill and fill. - virtual unsigned getCostOfKeepingLiveOverCall(ArrayRef Tys) const; + unsigned getCostOfKeepingLiveOverCall(ArrayRef Tys) const; + + /// \returns True if the intrinsic is a supported memory intrinsic. Info + /// will contain additional information - whether the intrinsic may write + /// or read to memory, volatility and the pointer. Info is undefined + /// if false is returned. + bool getTgtMemIntrinsic(IntrinsicInst *Inst, MemIntrinsicInfo &Info) const; + + /// \returns A value which is the result of the given memory intrinsic. New + /// instructions may be created to extract the result from the given intrinsic + /// memory operation. Returns nullptr if the target cannot create a result + /// from the given intrinsic. + Value *getOrCreateResultFromMemIntrinsic(IntrinsicInst *Inst, + Type *ExpectedType) const; /// @} - /// Analysis group identification. +private: + /// \brief The abstract base class used to type erase specific TTI + /// implementations. + class Concept; + + /// \brief The template model for the base class which wraps a concrete + /// implementation in a type erased interface. + template class Model; + + std::unique_ptr TTIImpl; +}; + +class TargetTransformInfo::Concept { +public: + virtual ~Concept() = 0; + + virtual unsigned getOperationCost(unsigned Opcode, Type *Ty, Type *OpTy) = 0; + virtual unsigned getGEPCost(const Value *Ptr, + ArrayRef Operands) = 0; + virtual unsigned getCallCost(FunctionType *FTy, int NumArgs) = 0; + virtual unsigned getCallCost(const Function *F, int NumArgs) = 0; + virtual unsigned getCallCost(const Function *F, + ArrayRef Arguments) = 0; + virtual unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy, + ArrayRef ParamTys) = 0; + virtual unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy, + ArrayRef Arguments) = 0; + virtual unsigned getUserCost(const User *U) = 0; + virtual bool hasBranchDivergence() = 0; + virtual bool isLoweredToCall(const Function *F) = 0; + virtual void getUnrollingPreferences(Loop *L, UnrollingPreferences &UP) = 0; + virtual bool isLegalAddImmediate(int64_t Imm) = 0; + virtual bool isLegalICmpImmediate(int64_t Imm) = 0; + virtual bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV, + int64_t BaseOffset, bool HasBaseReg, + int64_t Scale) = 0; + virtual bool isLegalMaskedStore(Type *DataType, int Consecutive) = 0; + virtual bool isLegalMaskedLoad(Type *DataType, int Consecutive) = 0; + virtual int getScalingFactorCost(Type *Ty, GlobalValue *BaseGV, + int64_t BaseOffset, bool HasBaseReg, + int64_t Scale) = 0; + virtual bool isTruncateFree(Type *Ty1, Type *Ty2) = 0; + virtual bool isProfitableToHoist(Instruction *I) = 0; + virtual bool isTypeLegal(Type *Ty) = 0; + virtual unsigned getJumpBufAlignment() = 0; + virtual unsigned getJumpBufSize() = 0; + virtual bool shouldBuildLookupTables() = 0; + virtual PopcntSupportKind getPopcntSupport(unsigned IntTyWidthInBit) = 0; + virtual bool haveFastSqrt(Type *Ty) = 0; + virtual unsigned getFPOpCost(Type *Ty) = 0; + virtual unsigned getIntImmCost(const APInt &Imm, Type *Ty) = 0; + virtual unsigned getIntImmCost(unsigned Opc, unsigned Idx, const APInt &Imm, + Type *Ty) = 0; + virtual unsigned getIntImmCost(Intrinsic::ID IID, unsigned Idx, + const APInt &Imm, Type *Ty) = 0; + virtual unsigned getNumberOfRegisters(bool Vector) = 0; + virtual unsigned getRegisterBitWidth(bool Vector) = 0; + virtual unsigned getMaxInterleaveFactor() = 0; + virtual unsigned + getArithmeticInstrCost(unsigned Opcode, Type *Ty, OperandValueKind Opd1Info, + OperandValueKind Opd2Info, + OperandValueProperties Opd1PropInfo, + OperandValueProperties Opd2PropInfo) = 0; + virtual unsigned getShuffleCost(ShuffleKind Kind, Type *Tp, int Index, + Type *SubTp) = 0; + virtual unsigned getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src) = 0; + virtual unsigned getCFInstrCost(unsigned Opcode) = 0; + virtual unsigned getCmpSelInstrCost(unsigned Opcode, Type *ValTy, + Type *CondTy) = 0; + virtual unsigned getVectorInstrCost(unsigned Opcode, Type *Val, + unsigned Index) = 0; + virtual unsigned getMemoryOpCost(unsigned Opcode, Type *Src, + unsigned Alignment, + unsigned AddressSpace) = 0; + virtual unsigned getMaskedMemoryOpCost(unsigned Opcode, Type *Src, + unsigned Alignment, + unsigned AddressSpace) = 0; + virtual unsigned getReductionCost(unsigned Opcode, Type *Ty, + bool IsPairwiseForm) = 0; + virtual unsigned getIntrinsicInstrCost(Intrinsic::ID ID, Type *RetTy, + ArrayRef Tys) = 0; + virtual unsigned getNumberOfParts(Type *Tp) = 0; + virtual unsigned getAddressComputationCost(Type *Ty, bool IsComplex) = 0; + virtual unsigned getCostOfKeepingLiveOverCall(ArrayRef Tys) = 0; + virtual bool getTgtMemIntrinsic(IntrinsicInst *Inst, + MemIntrinsicInfo &Info) = 0; + virtual Value *getOrCreateResultFromMemIntrinsic(IntrinsicInst *Inst, + Type *ExpectedType) = 0; +}; + +template +class TargetTransformInfo::Model final : public TargetTransformInfo::Concept { + T Impl; + +public: + Model(T Impl) : Impl(std::move(Impl)) {} + ~Model() override {} + + unsigned getOperationCost(unsigned Opcode, Type *Ty, Type *OpTy) override { + return Impl.getOperationCost(Opcode, Ty, OpTy); + } + unsigned getGEPCost(const Value *Ptr, + ArrayRef Operands) override { + return Impl.getGEPCost(Ptr, Operands); + } + unsigned getCallCost(FunctionType *FTy, int NumArgs) override { + return Impl.getCallCost(FTy, NumArgs); + } + unsigned getCallCost(const Function *F, int NumArgs) override { + return Impl.getCallCost(F, NumArgs); + } + unsigned getCallCost(const Function *F, + ArrayRef Arguments) override { + return Impl.getCallCost(F, Arguments); + } + unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy, + ArrayRef ParamTys) override { + return Impl.getIntrinsicCost(IID, RetTy, ParamTys); + } + unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy, + ArrayRef Arguments) override { + return Impl.getIntrinsicCost(IID, RetTy, Arguments); + } + unsigned getUserCost(const User *U) override { return Impl.getUserCost(U); } + bool hasBranchDivergence() override { return Impl.hasBranchDivergence(); } + bool isLoweredToCall(const Function *F) override { + return Impl.isLoweredToCall(F); + } + void getUnrollingPreferences(Loop *L, UnrollingPreferences &UP) override { + return Impl.getUnrollingPreferences(L, UP); + } + bool isLegalAddImmediate(int64_t Imm) override { + return Impl.isLegalAddImmediate(Imm); + } + bool isLegalICmpImmediate(int64_t Imm) override { + return Impl.isLegalICmpImmediate(Imm); + } + bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset, + bool HasBaseReg, int64_t Scale) override { + return Impl.isLegalAddressingMode(Ty, BaseGV, BaseOffset, HasBaseReg, + Scale); + } + bool isLegalMaskedStore(Type *DataType, int Consecutive) override { + return Impl.isLegalMaskedStore(DataType, Consecutive); + } + bool isLegalMaskedLoad(Type *DataType, int Consecutive) override { + return Impl.isLegalMaskedLoad(DataType, Consecutive); + } + int getScalingFactorCost(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset, + bool HasBaseReg, int64_t Scale) override { + return Impl.getScalingFactorCost(Ty, BaseGV, BaseOffset, HasBaseReg, Scale); + } + bool isTruncateFree(Type *Ty1, Type *Ty2) override { + return Impl.isTruncateFree(Ty1, Ty2); + } + bool isProfitableToHoist(Instruction *I) override { + return Impl.isProfitableToHoist(I); + } + bool isTypeLegal(Type *Ty) override { return Impl.isTypeLegal(Ty); } + unsigned getJumpBufAlignment() override { return Impl.getJumpBufAlignment(); } + unsigned getJumpBufSize() override { return Impl.getJumpBufSize(); } + bool shouldBuildLookupTables() override { + return Impl.shouldBuildLookupTables(); + } + PopcntSupportKind getPopcntSupport(unsigned IntTyWidthInBit) override { + return Impl.getPopcntSupport(IntTyWidthInBit); + } + bool haveFastSqrt(Type *Ty) override { return Impl.haveFastSqrt(Ty); } + + unsigned getFPOpCost(Type *Ty) override { + return Impl.getFPOpCost(Ty); + } + + unsigned getIntImmCost(const APInt &Imm, Type *Ty) override { + return Impl.getIntImmCost(Imm, Ty); + } + unsigned getIntImmCost(unsigned Opc, unsigned Idx, const APInt &Imm, + Type *Ty) override { + return Impl.getIntImmCost(Opc, Idx, Imm, Ty); + } + unsigned getIntImmCost(Intrinsic::ID IID, unsigned Idx, const APInt &Imm, + Type *Ty) override { + return Impl.getIntImmCost(IID, Idx, Imm, Ty); + } + unsigned getNumberOfRegisters(bool Vector) override { + return Impl.getNumberOfRegisters(Vector); + } + unsigned getRegisterBitWidth(bool Vector) override { + return Impl.getRegisterBitWidth(Vector); + } + unsigned getMaxInterleaveFactor() override { + return Impl.getMaxInterleaveFactor(); + } + unsigned + getArithmeticInstrCost(unsigned Opcode, Type *Ty, OperandValueKind Opd1Info, + OperandValueKind Opd2Info, + OperandValueProperties Opd1PropInfo, + OperandValueProperties Opd2PropInfo) override { + return Impl.getArithmeticInstrCost(Opcode, Ty, Opd1Info, Opd2Info, + Opd1PropInfo, Opd2PropInfo); + } + unsigned getShuffleCost(ShuffleKind Kind, Type *Tp, int Index, + Type *SubTp) override { + return Impl.getShuffleCost(Kind, Tp, Index, SubTp); + } + unsigned getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src) override { + return Impl.getCastInstrCost(Opcode, Dst, Src); + } + unsigned getCFInstrCost(unsigned Opcode) override { + return Impl.getCFInstrCost(Opcode); + } + unsigned getCmpSelInstrCost(unsigned Opcode, Type *ValTy, + Type *CondTy) override { + return Impl.getCmpSelInstrCost(Opcode, ValTy, CondTy); + } + unsigned getVectorInstrCost(unsigned Opcode, Type *Val, + unsigned Index) override { + return Impl.getVectorInstrCost(Opcode, Val, Index); + } + unsigned getMemoryOpCost(unsigned Opcode, Type *Src, unsigned Alignment, + unsigned AddressSpace) override { + return Impl.getMemoryOpCost(Opcode, Src, Alignment, AddressSpace); + } + unsigned getMaskedMemoryOpCost(unsigned Opcode, Type *Src, unsigned Alignment, + unsigned AddressSpace) override { + return Impl.getMaskedMemoryOpCost(Opcode, Src, Alignment, AddressSpace); + } + unsigned getReductionCost(unsigned Opcode, Type *Ty, + bool IsPairwiseForm) override { + return Impl.getReductionCost(Opcode, Ty, IsPairwiseForm); + } + unsigned getIntrinsicInstrCost(Intrinsic::ID ID, Type *RetTy, + ArrayRef Tys) override { + return Impl.getIntrinsicInstrCost(ID, RetTy, Tys); + } + unsigned getNumberOfParts(Type *Tp) override { + return Impl.getNumberOfParts(Tp); + } + unsigned getAddressComputationCost(Type *Ty, bool IsComplex) override { + return Impl.getAddressComputationCost(Ty, IsComplex); + } + unsigned getCostOfKeepingLiveOverCall(ArrayRef Tys) override { + return Impl.getCostOfKeepingLiveOverCall(Tys); + } + bool getTgtMemIntrinsic(IntrinsicInst *Inst, + MemIntrinsicInfo &Info) override { + return Impl.getTgtMemIntrinsic(Inst, Info); + } + Value *getOrCreateResultFromMemIntrinsic(IntrinsicInst *Inst, + Type *ExpectedType) override { + return Impl.getOrCreateResultFromMemIntrinsic(Inst, ExpectedType); + } +}; + +template +TargetTransformInfo::TargetTransformInfo(T Impl) + : TTIImpl(new Model(Impl)) {} + +/// \brief Analysis pass providing the \c TargetTransformInfo. +/// +/// The core idea of the TargetIRAnalysis is to expose an interface through +/// which LLVM targets can analyze and provide information about the middle +/// end's target-independent IR. This supports use cases such as target-aware +/// cost modeling of IR constructs. +/// +/// This is a function analysis because much of the cost modeling for targets +/// is done in a subtarget specific way and LLVM supports compiling different +/// functions targeting different subtargets in order to support runtime +/// dispatch according to the observed subtarget. +class TargetIRAnalysis { +public: + typedef TargetTransformInfo Result; + + /// \brief Opaque, unique identifier for this analysis pass. + static void *ID() { return (void *)&PassID; } + + /// \brief Provide access to a name for this pass for debugging purposes. + static StringRef name() { return "TargetIRAnalysis"; } + + /// \brief Default construct a target IR analysis. + /// + /// This will use the module's datalayout to construct a baseline + /// conservative TTI result. + TargetIRAnalysis(); + + /// \brief Construct an IR analysis pass around a target-provide callback. + /// + /// The callback will be called with a particular function for which the TTI + /// is needed and must return a TTI object for that function. + TargetIRAnalysis(std::function TTICallback); + + // Value semantics. We spell out the constructors for MSVC. + TargetIRAnalysis(const TargetIRAnalysis &Arg) + : TTICallback(Arg.TTICallback) {} + TargetIRAnalysis(TargetIRAnalysis &&Arg) + : TTICallback(std::move(Arg.TTICallback)) {} + TargetIRAnalysis &operator=(const TargetIRAnalysis &RHS) { + TTICallback = RHS.TTICallback; + return *this; + } + TargetIRAnalysis &operator=(TargetIRAnalysis &&RHS) { + TTICallback = std::move(RHS.TTICallback); + return *this; + } + + Result run(Function &F); + +private: + static char PassID; + + /// \brief The callback used to produce a result. + /// + /// We use a completely opaque callback so that targets can provide whatever + /// mechanism they desire for constructing the TTI for a given function. + /// + /// FIXME: Should we really use std::function? It's relatively inefficient. + /// It might be possible to arrange for even stateful callbacks to outlive + /// the analysis and thus use a function_ref which would be lighter weight. + /// This may also be less error prone as the callback is likely to reference + /// the external TargetMachine, and that reference needs to never dangle. + std::function TTICallback; + + /// \brief Helper function used as the callback in the default constructor. + static Result getDefaultTTI(Function &F); +}; + +/// \brief Wrapper pass for TargetTransformInfo. +/// +/// This pass can be constructed from a TTI object which it stores internally +/// and is queried by passes. +class TargetTransformInfoWrapperPass : public ImmutablePass { + TargetIRAnalysis TIRA; + Optional TTI; + + virtual void anchor(); + +public: static char ID; + + /// \brief We must provide a default constructor for the pass but it should + /// never be used. + /// + /// Use the constructor below or call one of the creation routines. + TargetTransformInfoWrapperPass(); + + explicit TargetTransformInfoWrapperPass(TargetIRAnalysis TIRA); + + TargetTransformInfo &getTTI(Function &F); }; -/// \brief Create the base case instance of a pass in the TTI analysis group. +/// \brief Create an analysis pass wrapper around a TTI object. /// -/// This class provides the base case for the stack of TTI analyzes. It doesn't -/// delegate to anything and uses the STTI and VTTI objects passed in to -/// satisfy the queries. -ImmutablePass *createNoTargetTransformInfoPass(); +/// This analysis pass just holds the TTI instance and makes it available to +/// clients. +ImmutablePass *createTargetTransformInfoWrapperPass(TargetIRAnalysis TIRA); } // End llvm namespace diff --git a/include/llvm/Analysis/TargetTransformInfoImpl.h b/include/llvm/Analysis/TargetTransformInfoImpl.h new file mode 100644 index 0000000..3e02c0c --- /dev/null +++ b/include/llvm/Analysis/TargetTransformInfoImpl.h @@ -0,0 +1,433 @@ +//===- TargetTransformInfoImpl.h --------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// This file provides helpers for the implementation of +/// a TargetTransformInfo-conforming class. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_TARGETTRANSFORMINFOIMPL_H +#define LLVM_ANALYSIS_TARGETTRANSFORMINFOIMPL_H + +#include "llvm/Analysis/TargetTransformInfo.h" +#include "llvm/IR/CallSite.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Operator.h" +#include "llvm/IR/Type.h" + +namespace llvm { + +/// \brief Base class for use as a mix-in that aids implementing +/// a TargetTransformInfo-compatible class. +class TargetTransformInfoImplBase { +protected: + typedef TargetTransformInfo TTI; + + const DataLayout *DL; + + explicit TargetTransformInfoImplBase(const DataLayout *DL) + : DL(DL) {} + +public: + // Provide value semantics. MSVC requires that we spell all of these out. + TargetTransformInfoImplBase(const TargetTransformInfoImplBase &Arg) + : DL(Arg.DL) {} + TargetTransformInfoImplBase(TargetTransformInfoImplBase &&Arg) + : DL(std::move(Arg.DL)) {} + TargetTransformInfoImplBase & + operator=(const TargetTransformInfoImplBase &RHS) { + DL = RHS.DL; + return *this; + } + TargetTransformInfoImplBase &operator=(TargetTransformInfoImplBase &&RHS) { + DL = std::move(RHS.DL); + return *this; + } + + unsigned getOperationCost(unsigned Opcode, Type *Ty, Type *OpTy) { + switch (Opcode) { + default: + // By default, just classify everything as 'basic'. + return TTI::TCC_Basic; + + case Instruction::GetElementPtr: + llvm_unreachable("Use getGEPCost for GEP operations!"); + + case Instruction::BitCast: + assert(OpTy && "Cast instructions must provide the operand type"); + if (Ty == OpTy || (Ty->isPointerTy() && OpTy->isPointerTy())) + // Identity and pointer-to-pointer casts are free. + return TTI::TCC_Free; + + // Otherwise, the default basic cost is used. + return TTI::TCC_Basic; + + case Instruction::IntToPtr: { + if (!DL) + return TTI::TCC_Basic; + + // An inttoptr cast is free so long as the input is a legal integer type + // which doesn't contain values outside the range of a pointer. + unsigned OpSize = OpTy->getScalarSizeInBits(); + if (DL->isLegalInteger(OpSize) && + OpSize <= DL->getPointerTypeSizeInBits(Ty)) + return TTI::TCC_Free; + + // Otherwise it's not a no-op. + return TTI::TCC_Basic; + } + case Instruction::PtrToInt: { + if (!DL) + return TTI::TCC_Basic; + + // A ptrtoint cast is free so long as the result is large enough to store + // the pointer, and a legal integer type. + unsigned DestSize = Ty->getScalarSizeInBits(); + if (DL->isLegalInteger(DestSize) && + DestSize >= DL->getPointerTypeSizeInBits(OpTy)) + return TTI::TCC_Free; + + // Otherwise it's not a no-op. + return TTI::TCC_Basic; + } + case Instruction::Trunc: + // trunc to a native type is free (assuming the target has compare and + // shift-right of the same width). + if (DL && DL->isLegalInteger(DL->getTypeSizeInBits(Ty))) + return TTI::TCC_Free; + + return TTI::TCC_Basic; + } + } + + unsigned getGEPCost(const Value *Ptr, ArrayRef Operands) { + // In the basic model, we just assume that all-constant GEPs will be folded + // into their uses via addressing modes. + for (unsigned Idx = 0, Size = Operands.size(); Idx != Size; ++Idx) + if (!isa(Operands[Idx])) + return TTI::TCC_Basic; + + return TTI::TCC_Free; + } + + unsigned getCallCost(FunctionType *FTy, int NumArgs) { + assert(FTy && "FunctionType must be provided to this routine."); + + // The target-independent implementation just measures the size of the + // function by approximating that each argument will take on average one + // instruction to prepare. + + if (NumArgs < 0) + // Set the argument number to the number of explicit arguments in the + // function. + NumArgs = FTy->getNumParams(); + + return TTI::TCC_Basic * (NumArgs + 1); + } + + unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy, + ArrayRef ParamTys) { + switch (IID) { + default: + // Intrinsics rarely (if ever) have normal argument setup constraints. + // Model them as having a basic instruction cost. + // FIXME: This is wrong for libc intrinsics. + return TTI::TCC_Basic; + + case Intrinsic::annotation: + case Intrinsic::assume: + case Intrinsic::dbg_declare: + case Intrinsic::dbg_value: + case Intrinsic::invariant_start: + case Intrinsic::invariant_end: + case Intrinsic::lifetime_start: + case Intrinsic::lifetime_end: + case Intrinsic::objectsize: + case Intrinsic::ptr_annotation: + case Intrinsic::var_annotation: + case Intrinsic::experimental_gc_result_int: + case Intrinsic::experimental_gc_result_float: + case Intrinsic::experimental_gc_result_ptr: + case Intrinsic::experimental_gc_result: + case Intrinsic::experimental_gc_relocate: + // These intrinsics don't actually represent code after lowering. + return TTI::TCC_Free; + } + } + + bool hasBranchDivergence() { return false; } + + bool isLoweredToCall(const Function *F) { + // FIXME: These should almost certainly not be handled here, and instead + // handled with the help of TLI or the target itself. This was largely + // ported from existing analysis heuristics here so that such refactorings + // can take place in the future. + + if (F->isIntrinsic()) + return false; + + if (F->hasLocalLinkage() || !F->hasName()) + return true; + + StringRef Name = F->getName(); + + // These will all likely lower to a single selection DAG node. + if (Name == "copysign" || Name == "copysignf" || Name == "copysignl" || + Name == "fabs" || Name == "fabsf" || Name == "fabsl" || Name == "sin" || + Name == "fmin" || Name == "fminf" || Name == "fminl" || + Name == "fmax" || Name == "fmaxf" || Name == "fmaxl" || + Name == "sinf" || Name == "sinl" || Name == "cos" || Name == "cosf" || + Name == "cosl" || Name == "sqrt" || Name == "sqrtf" || Name == "sqrtl") + return false; + + // These are all likely to be optimized into something smaller. + if (Name == "pow" || Name == "powf" || Name == "powl" || Name == "exp2" || + Name == "exp2l" || Name == "exp2f" || Name == "floor" || + Name == "floorf" || Name == "ceil" || Name == "round" || + Name == "ffs" || Name == "ffsl" || Name == "abs" || Name == "labs" || + Name == "llabs") + return false; + + return true; + } + + void getUnrollingPreferences(Loop *, TTI::UnrollingPreferences &) {} + + bool isLegalAddImmediate(int64_t Imm) { return false; } + + bool isLegalICmpImmediate(int64_t Imm) { return false; } + + bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset, + bool HasBaseReg, int64_t Scale) { + // Guess that reg+reg addressing is allowed. This heuristic is taken from + // the implementation of LSR. + return !BaseGV && BaseOffset == 0 && Scale <= 1; + } + + bool isLegalMaskedStore(Type *DataType, int Consecutive) { return false; } + + bool isLegalMaskedLoad(Type *DataType, int Consecutive) { return false; } + + int getScalingFactorCost(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset, + bool HasBaseReg, int64_t Scale) { + // Guess that all legal addressing mode are free. + if (isLegalAddressingMode(Ty, BaseGV, BaseOffset, HasBaseReg, Scale)) + return 0; + return -1; + } + + bool isTruncateFree(Type *Ty1, Type *Ty2) { return false; } + + bool isProfitableToHoist(Instruction *I) { return true; } + + bool isTypeLegal(Type *Ty) { return false; } + + unsigned getJumpBufAlignment() { return 0; } + + unsigned getJumpBufSize() { return 0; } + + bool shouldBuildLookupTables() { return true; } + + TTI::PopcntSupportKind getPopcntSupport(unsigned IntTyWidthInBit) { + return TTI::PSK_Software; + } + + bool haveFastSqrt(Type *Ty) { return false; } + + unsigned getFPOpCost(Type *Ty) { return TargetTransformInfo::TCC_Basic; } + + unsigned getIntImmCost(const APInt &Imm, Type *Ty) { return TTI::TCC_Basic; } + + unsigned getIntImmCost(unsigned Opcode, unsigned Idx, const APInt &Imm, + Type *Ty) { + return TTI::TCC_Free; + } + + unsigned getIntImmCost(Intrinsic::ID IID, unsigned Idx, const APInt &Imm, + Type *Ty) { + return TTI::TCC_Free; + } + + unsigned getNumberOfRegisters(bool Vector) { return 8; } + + unsigned getRegisterBitWidth(bool Vector) { return 32; } + + unsigned getMaxInterleaveFactor() { return 1; } + + unsigned getArithmeticInstrCost(unsigned Opcode, Type *Ty, + TTI::OperandValueKind Opd1Info, + TTI::OperandValueKind Opd2Info, + TTI::OperandValueProperties Opd1PropInfo, + TTI::OperandValueProperties Opd2PropInfo) { + return 1; + } + + unsigned getShuffleCost(TTI::ShuffleKind Kind, Type *Ty, int Index, + Type *SubTp) { + return 1; + } + + unsigned getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src) { return 1; } + + unsigned getCFInstrCost(unsigned Opcode) { return 1; } + + unsigned getCmpSelInstrCost(unsigned Opcode, Type *ValTy, Type *CondTy) { + return 1; + } + + unsigned getVectorInstrCost(unsigned Opcode, Type *Val, unsigned Index) { + return 1; + } + + unsigned getMemoryOpCost(unsigned Opcode, Type *Src, unsigned Alignment, + unsigned AddressSpace) { + return 1; + } + + unsigned getMaskedMemoryOpCost(unsigned Opcode, Type *Src, unsigned Alignment, + unsigned AddressSpace) { + return 1; + } + + unsigned getIntrinsicInstrCost(Intrinsic::ID ID, Type *RetTy, + ArrayRef Tys) { + return 1; + } + + unsigned getNumberOfParts(Type *Tp) { return 0; } + + unsigned getAddressComputationCost(Type *Tp, bool) { return 0; } + + unsigned getReductionCost(unsigned, Type *, bool) { return 1; } + + unsigned getCostOfKeepingLiveOverCall(ArrayRef Tys) { return 0; } + + bool getTgtMemIntrinsic(IntrinsicInst *Inst, MemIntrinsicInfo &Info) { + return false; + } + + Value *getOrCreateResultFromMemIntrinsic(IntrinsicInst *Inst, + Type *ExpectedType) { + return nullptr; + } +}; + +/// \brief CRTP base class for use as a mix-in that aids implementing +/// a TargetTransformInfo-compatible class. +template +class TargetTransformInfoImplCRTPBase : public TargetTransformInfoImplBase { +private: + typedef TargetTransformInfoImplBase BaseT; + +protected: + explicit TargetTransformInfoImplCRTPBase(const DataLayout *DL) + : BaseT(DL) {} + +public: + // Provide value semantics. MSVC requires that we spell all of these out. + TargetTransformInfoImplCRTPBase(const TargetTransformInfoImplCRTPBase &Arg) + : BaseT(static_cast(Arg)) {} + TargetTransformInfoImplCRTPBase(TargetTransformInfoImplCRTPBase &&Arg) + : BaseT(std::move(static_cast(Arg))) {} + TargetTransformInfoImplCRTPBase & + operator=(const TargetTransformInfoImplCRTPBase &RHS) { + BaseT::operator=(static_cast(RHS)); + return *this; + } + TargetTransformInfoImplCRTPBase & + operator=(TargetTransformInfoImplCRTPBase &&RHS) { + BaseT::operator=(std::move(static_cast(RHS))); + return *this; + } + + using BaseT::getCallCost; + + unsigned getCallCost(const Function *F, int NumArgs) { + assert(F && "A concrete function must be provided to this routine."); + + if (NumArgs < 0) + // Set the argument number to the number of explicit arguments in the + // function. + NumArgs = F->arg_size(); + + if (Intrinsic::ID IID = (Intrinsic::ID)F->getIntrinsicID()) { + FunctionType *FTy = F->getFunctionType(); + SmallVector ParamTys(FTy->param_begin(), FTy->param_end()); + return static_cast(this) + ->getIntrinsicCost(IID, FTy->getReturnType(), ParamTys); + } + + if (!static_cast(this)->isLoweredToCall(F)) + return TTI::TCC_Basic; // Give a basic cost if it will be lowered + // directly. + + return static_cast(this)->getCallCost(F->getFunctionType(), NumArgs); + } + + unsigned getCallCost(const Function *F, ArrayRef Arguments) { + // Simply delegate to generic handling of the call. + // FIXME: We should use instsimplify or something else to catch calls which + // will constant fold with these arguments. + return static_cast(this)->getCallCost(F, Arguments.size()); + } + + using BaseT::getIntrinsicCost; + + unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy, + ArrayRef Arguments) { + // Delegate to the generic intrinsic handling code. This mostly provides an + // opportunity for targets to (for example) special case the cost of + // certain intrinsics based on constants used as arguments. + SmallVector ParamTys; + ParamTys.reserve(Arguments.size()); + for (unsigned Idx = 0, Size = Arguments.size(); Idx != Size; ++Idx) + ParamTys.push_back(Arguments[Idx]->getType()); + return static_cast(this)->getIntrinsicCost(IID, RetTy, ParamTys); + } + + unsigned getUserCost(const User *U) { + if (isa(U)) + return TTI::TCC_Free; // Model all PHI nodes as free. + + if (const GEPOperator *GEP = dyn_cast(U)) { + SmallVector Indices(GEP->idx_begin(), GEP->idx_end()); + return static_cast(this) + ->getGEPCost(GEP->getPointerOperand(), Indices); + } + + if (ImmutableCallSite CS = U) { + const Function *F = CS.getCalledFunction(); + if (!F) { + // Just use the called value type. + Type *FTy = CS.getCalledValue()->getType()->getPointerElementType(); + return static_cast(this) + ->getCallCost(cast(FTy), CS.arg_size()); + } + + SmallVector Arguments(CS.arg_begin(), CS.arg_end()); + return static_cast(this)->getCallCost(F, Arguments); + } + + if (const CastInst *CI = dyn_cast(U)) { + // Result of a cmp instruction is often extended (to be used by other + // cmp instructions, logical or return instructions). These are usually + // nop on most sane targets. + if (isa(CI->getOperand(0))) + return TTI::TCC_Free; + } + + return static_cast(this)->getOperationCost( + Operator::getOpcode(U), U->getType(), + U->getNumOperands() == 1 ? U->getOperand(0)->getType() : nullptr); + } +}; +} + +#endif diff --git a/include/llvm/Analysis/ValueTracking.h b/include/llvm/Analysis/ValueTracking.h index 6bbf4f4..ac8c3b7 100644 --- a/include/llvm/Analysis/ValueTracking.h +++ b/include/llvm/Analysis/ValueTracking.h @@ -25,7 +25,7 @@ namespace llvm { class DataLayout; class StringRef; class MDNode; - class AssumptionTracker; + class AssumptionCache; class DominatorTree; class TargetLibraryInfo; @@ -37,9 +37,9 @@ namespace llvm { /// where V is a vector, the known zero and known one values are the /// same width as the vector element, and the bit is set only if it is true /// for all of the elements in the vector. - void computeKnownBits(Value *V, APInt &KnownZero, APInt &KnownOne, + void computeKnownBits(Value *V, APInt &KnownZero, APInt &KnownOne, const DataLayout *TD = nullptr, unsigned Depth = 0, - AssumptionTracker *AT = nullptr, + AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr, const DominatorTree *DT = nullptr); /// Compute known bits from the range metadata. @@ -51,7 +51,7 @@ namespace llvm { /// one. Convenience wrapper around computeKnownBits. void ComputeSignBit(Value *V, bool &KnownZero, bool &KnownOne, const DataLayout *TD = nullptr, unsigned Depth = 0, - AssumptionTracker *AT = nullptr, + AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr, const DominatorTree *DT = nullptr); @@ -61,7 +61,7 @@ namespace llvm { /// integer or pointer type and vectors of integers. If 'OrZero' is set then /// returns true if the given value is either a power of two or zero. bool isKnownToBeAPowerOfTwo(Value *V, bool OrZero = false, unsigned Depth = 0, - AssumptionTracker *AT = nullptr, + AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr, const DominatorTree *DT = nullptr); @@ -70,7 +70,7 @@ namespace llvm { /// non-zero when defined. Supports values with integer or pointer type and /// vectors of integers. bool isKnownNonZero(Value *V, const DataLayout *TD = nullptr, - unsigned Depth = 0, AssumptionTracker *AT = nullptr, + unsigned Depth = 0, AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr, const DominatorTree *DT = nullptr); @@ -83,13 +83,12 @@ namespace llvm { /// where V is a vector, the mask, known zero, and known one values are the /// same width as the vector element, and the bit is set only if it is true /// for all of the elements in the vector. - bool MaskedValueIsZero(Value *V, const APInt &Mask, + bool MaskedValueIsZero(Value *V, const APInt &Mask, const DataLayout *TD = nullptr, unsigned Depth = 0, - AssumptionTracker *AT = nullptr, + AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr, const DominatorTree *DT = nullptr); - /// ComputeNumSignBits - Return the number of times the sign bit of the /// register is replicated into the other bits. We know that at least 1 bit /// is always equal to the sign bit (itself), but other cases can give us @@ -99,8 +98,7 @@ namespace llvm { /// 'Op' must have a scalar integer type. /// unsigned ComputeNumSignBits(Value *Op, const DataLayout *TD = nullptr, - unsigned Depth = 0, - AssumptionTracker *AT = nullptr, + unsigned Depth = 0, AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr, const DominatorTree *DT = nullptr); @@ -118,6 +116,11 @@ namespace llvm { /// bool CannotBeNegativeZero(const Value *V, unsigned Depth = 0); + /// CannotBeOrderedLessThanZero - Return true if we can prove that the + /// specified FP value is either a NaN or never less than 0.0. + /// + bool CannotBeOrderedLessThanZero(const Value *V, unsigned Depth = 0); + /// isBytewiseValue - If the specified value can be set by repeating the same /// byte in memory, return the i8 value that it is represented with. This is /// true for all i8 values obviously, but is also true for i32 0, i32 -1, @@ -217,6 +220,17 @@ namespace llvm { const DataLayout *DL = nullptr, const DominatorTree *DT = nullptr); + enum class OverflowResult { AlwaysOverflows, MayOverflow, NeverOverflows }; + OverflowResult computeOverflowForUnsignedMul(Value *LHS, Value *RHS, + const DataLayout *DL, + AssumptionCache *AC, + const Instruction *CxtI, + const DominatorTree *DT); + OverflowResult computeOverflowForUnsignedAdd(Value *LHS, Value *RHS, + const DataLayout *DL, + AssumptionCache *AC, + const Instruction *CxtI, + const DominatorTree *DT); } // end namespace llvm #endif diff --git a/include/llvm/Bitcode/BitCodes.h b/include/llvm/Bitcode/BitCodes.h index ed2dcf8..3f7a77d 100644 --- a/include/llvm/Bitcode/BitCodes.h +++ b/include/llvm/Bitcode/BitCodes.h @@ -125,7 +125,7 @@ public: case Blob: return false; } - llvm_unreachable("Invalid encoding"); + report_fatal_error("Invalid encoding"); } /// isChar6 - Return true if this character is legal in the Char6 encoding. diff --git a/include/llvm/Bitcode/BitcodeWriterPass.h b/include/llvm/Bitcode/BitcodeWriterPass.h index eb85548..8fe9b7e 100644 --- a/include/llvm/Bitcode/BitcodeWriterPass.h +++ b/include/llvm/Bitcode/BitcodeWriterPass.h @@ -41,7 +41,7 @@ public: /// \brief Run the bitcode writer pass, and output the module to the selected /// output stream. - PreservedAnalyses run(Module *M); + PreservedAnalyses run(Module &M); static StringRef name() { return "BitcodeWriterPass"; } }; diff --git a/include/llvm/Bitcode/BitstreamReader.h b/include/llvm/Bitcode/BitstreamReader.h index ecf8235..c20a160 100644 --- a/include/llvm/Bitcode/BitstreamReader.h +++ b/include/llvm/Bitcode/BitstreamReader.h @@ -50,8 +50,8 @@ private: /// information in the BlockInfo block. Only llvm-bcanalyzer uses this. bool IgnoreBlockInfoNames; - BitstreamReader(const BitstreamReader&) LLVM_DELETED_FUNCTION; - void operator=(const BitstreamReader&) LLVM_DELETED_FUNCTION; + BitstreamReader(const BitstreamReader&) = delete; + void operator=(const BitstreamReader&) = delete; public: BitstreamReader() : IgnoreBlockInfoNames(true) { } @@ -61,9 +61,8 @@ public: init(Start, End); } - BitstreamReader(MemoryObject *bytes) : IgnoreBlockInfoNames(true) { - BitcodeBytes.reset(bytes); - } + BitstreamReader(std::unique_ptr BitcodeBytes) + : BitcodeBytes(std::move(BitcodeBytes)), IgnoreBlockInfoNames(true) {} BitstreamReader(BitstreamReader &&Other) { *this = std::move(Other); @@ -259,8 +258,8 @@ public: AF_DontAutoprocessAbbrevs = 2 }; - /// Advance the current bitstream, returning the next entry in the stream. - BitstreamEntry advance(unsigned Flags = 0) { + /// Advance the current bitstream, returning the next entry in the stream. + BitstreamEntry advance(unsigned Flags = 0) { while (1) { unsigned Code = ReadCode(); if (Code == bitc::END_BLOCK) { @@ -302,7 +301,7 @@ public: /// Reset the stream to the specified bit number. void JumpToBit(uint64_t BitNo) { - uintptr_t ByteNo = uintptr_t(BitNo/8) & ~(sizeof(word_t)-1); + size_t ByteNo = size_t(BitNo/8) & ~(sizeof(word_t)-1); unsigned WordBitNo = unsigned(BitNo & (sizeof(word_t)*8-1)); assert(canSkipToPos(ByteNo) && "Invalid location"); @@ -316,7 +315,8 @@ public: } void fillCurWord() { - assert(Size == 0 || NextChar < (unsigned)Size); + if (Size != 0 && NextChar >= Size) + report_fatal_error("Unexpected end of file"); // Read the next word from the stream. uint8_t Array[sizeof(word_t)] = {0}; @@ -491,11 +491,11 @@ private: //===--------------------------------------------------------------------===// public: - /// Return the abbreviation for the specified AbbrevId. const BitCodeAbbrev *getAbbrev(unsigned AbbrevID) { - unsigned AbbrevNo = AbbrevID-bitc::FIRST_APPLICATION_ABBREV; - assert(AbbrevNo < CurAbbrevs.size() && "Invalid abbrev #!"); + unsigned AbbrevNo = AbbrevID - bitc::FIRST_APPLICATION_ABBREV; + if (AbbrevNo >= CurAbbrevs.size()) + report_fatal_error("Invalid abbrev number"); return CurAbbrevs[AbbrevNo].get(); } diff --git a/include/llvm/Bitcode/LLVMBitCodes.h b/include/llvm/Bitcode/LLVMBitCodes.h index c42ecfe..d842167 100644 --- a/include/llvm/Bitcode/LLVMBitCodes.h +++ b/include/llvm/Bitcode/LLVMBitCodes.h @@ -137,16 +137,36 @@ namespace bitc { enum MetadataCodes { METADATA_STRING = 1, // MDSTRING: [values] - // 2 is unused. - // 3 is unused. + METADATA_VALUE = 2, // VALUE: [type num, value num] + METADATA_NODE = 3, // NODE: [n x md num] METADATA_NAME = 4, // STRING: [values] - // 5 is unused. + METADATA_DISTINCT_NODE = 5, // DISTINCT_NODE: [n x md num] METADATA_KIND = 6, // [n x [id, name]] - // 7 is unused. - METADATA_NODE = 8, // NODE: [n x (type num, value num)] - METADATA_FN_NODE = 9, // FN_NODE: [n x (type num, value num)] + METADATA_LOCATION = 7, // [distinct, line, col, scope, inlined-at?] + METADATA_OLD_NODE = 8, // OLD_NODE: [n x (type num, value num)] + METADATA_OLD_FN_NODE = 9, // OLD_FN_NODE: [n x (type num, value num)] METADATA_NAMED_NODE = 10, // NAMED_NODE: [n x mdnodes] - METADATA_ATTACHMENT = 11 // [m x [value, [n x [id, mdnode]]] + METADATA_ATTACHMENT = 11, // [m x [value, [n x [id, mdnode]]] + METADATA_GENERIC_DEBUG = 12, // [distinct, tag, vers, header, n x md num] + METADATA_SUBRANGE = 13, // [distinct, count, lo] + METADATA_ENUMERATOR = 14, // [distinct, value, name] + METADATA_BASIC_TYPE = 15, // [distinct, tag, name, size, align, enc] + METADATA_FILE = 16, // [distinct, filename, directory] + METADATA_DERIVED_TYPE = 17, // [distinct, ...] + METADATA_COMPOSITE_TYPE= 18, // [distinct, ...] + METADATA_SUBROUTINE_TYPE=19, // [distinct, flags, types] + METADATA_COMPILE_UNIT = 20, // [distinct, ...] + METADATA_SUBPROGRAM = 21, // [distinct, ...] + METADATA_LEXICAL_BLOCK = 22, // [distinct, scope, file, line, column] + METADATA_LEXICAL_BLOCK_FILE=23,//[distinct, scope, file, discriminator] + METADATA_NAMESPACE = 24, // [distinct, scope, file, name, line] + METADATA_TEMPLATE_TYPE = 25, // [distinct, scope, name, type, ...] + METADATA_TEMPLATE_VALUE= 26, // [distinct, scope, name, type, value, ...] + METADATA_GLOBAL_VAR = 27, // [distinct, ...] + METADATA_LOCAL_VAR = 28, // [distinct, ...] + METADATA_EXPRESSION = 29, // [distinct, n x element] + METADATA_OBJC_PROPERTY = 30, // [distinct, name, file, line, ...] + METADATA_IMPORTED_ENTITY=31, // [distinct, tag, scope, entity, line, name] }; // The constants block (CONSTANTS_BLOCK_ID) describes emission for each @@ -273,7 +293,7 @@ namespace bitc { FUNC_CODE_INST_BINOP = 2, // BINOP: [opcode, ty, opval, opval] FUNC_CODE_INST_CAST = 3, // CAST: [opcode, ty, opty, opval] - FUNC_CODE_INST_GEP = 4, // GEP: [n x operands] + FUNC_CODE_INST_GEP_OLD = 4, // GEP: [n x operands] FUNC_CODE_INST_SELECT = 5, // SELECT: [ty, opval, opval, opval] FUNC_CODE_INST_EXTRACTELT = 6, // EXTRACTELT: [opty, opval, opval] FUNC_CODE_INST_INSERTELT = 7, // INSERTELT: [ty, opval, opval, opval] @@ -307,7 +327,7 @@ namespace bitc { FUNC_CODE_INST_CMP2 = 28, // CMP2: [opty, opval, opval, pred] // new select on i1 or [N x i1] FUNC_CODE_INST_VSELECT = 29, // VSELECT: [ty,opval,opval,predty,pred] - FUNC_CODE_INST_INBOUNDS_GEP= 30, // INBOUNDS_GEP: [n x operands] + FUNC_CODE_INST_INBOUNDS_GEP_OLD = 30, // INBOUNDS_GEP: [n x operands] FUNC_CODE_INST_INDIRECTBR = 31, // INDIRECTBR: [opty, op0, op1, ...] // 32 is unused. FUNC_CODE_DEBUG_LOC_AGAIN = 33, // DEBUG_LOC_AGAIN @@ -325,8 +345,9 @@ namespace bitc { FUNC_CODE_INST_LANDINGPAD = 40, // LANDINGPAD: [ty,val,val,num,id0,val0...] FUNC_CODE_INST_LOADATOMIC = 41, // LOAD: [opty, op, align, vol, // ordering, synchscope] - FUNC_CODE_INST_STOREATOMIC = 42 // STORE: [ptrty,ptr,val, align, vol + FUNC_CODE_INST_STOREATOMIC = 42, // STORE: [ptrty,ptr,val, align, vol // ordering, synchscope] + FUNC_CODE_INST_GEP = 43, // GEP: [inbounds, n x operands] }; enum UseListCodes { diff --git a/include/llvm/Bitcode/ReaderWriter.h b/include/llvm/Bitcode/ReaderWriter.h index 2e8cdc7..48bdabc 100644 --- a/include/llvm/Bitcode/ReaderWriter.h +++ b/include/llvm/Bitcode/ReaderWriter.h @@ -14,6 +14,7 @@ #ifndef LLVM_BITCODE_READERWRITER_H #define LLVM_BITCODE_READERWRITER_H +#include "llvm/IR/DiagnosticInfo.h" #include "llvm/Support/ErrorOr.h" #include "llvm/Support/MemoryBuffer.h" #include @@ -30,27 +31,28 @@ namespace llvm { /// Read the header of the specified bitcode buffer and prepare for lazy /// deserialization of function bodies. If successful, this moves Buffer. On /// error, this *does not* move Buffer. - ErrorOr getLazyBitcodeModule(std::unique_ptr &&Buffer, - LLVMContext &Context); - - /// getStreamedBitcodeModule - Read the header of the specified stream - /// and prepare for lazy deserialization and streaming of function bodies. - /// On error, this returns null, and fills in *ErrMsg with an error - /// description if ErrMsg is non-null. - Module *getStreamedBitcodeModule(const std::string &name, - DataStreamer *streamer, - LLVMContext &Context, - std::string *ErrMsg = nullptr); + ErrorOr + getLazyBitcodeModule(std::unique_ptr &&Buffer, + LLVMContext &Context, + DiagnosticHandlerFunction DiagnosticHandler = nullptr); + + /// Read the header of the specified stream and prepare for lazy + /// deserialization and streaming of function bodies. + ErrorOr> getStreamedBitcodeModule( + StringRef Name, DataStreamer *Streamer, LLVMContext &Context, + DiagnosticHandlerFunction DiagnosticHandler = nullptr); /// Read the header of the specified bitcode buffer and extract just the /// triple information. If successful, this returns a string. On error, this /// returns "". - std::string getBitcodeTargetTriple(MemoryBufferRef Buffer, - LLVMContext &Context); + std::string + getBitcodeTargetTriple(MemoryBufferRef Buffer, LLVMContext &Context, + DiagnosticHandlerFunction DiagnosticHandler = nullptr); /// Read the specified bitcode file, returning the module. - ErrorOr parseBitcodeFile(MemoryBufferRef Buffer, - LLVMContext &Context); + ErrorOr + parseBitcodeFile(MemoryBufferRef Buffer, LLVMContext &Context, + DiagnosticHandlerFunction DiagnosticHandler = nullptr); /// WriteBitcodeToFile - Write the specified module to the specified /// raw output stream. For streams where it matters, the given stream @@ -141,32 +143,26 @@ namespace llvm { } const std::error_category &BitcodeErrorCategory(); - enum class BitcodeError { - ConflictingMETADATA_KINDRecords, - CouldNotFindFunctionInStream, - ExpectedConstant, - InsufficientFunctionProtos, - InvalidBitcodeSignature, - InvalidBitcodeWrapperHeader, - InvalidConstantReference, - InvalidID, // A read identifier is not found in the table it should be in. - InvalidInstructionWithNoBB, - InvalidRecord, // A read record doesn't have the expected size or structure - InvalidTypeForValue, // Type read OK, but is invalid for its use - InvalidTYPETable, - InvalidType, // We were unable to read a type - MalformedBlock, // We are unable to advance in the stream. - MalformedGlobalInitializerSet, - InvalidMultipleBlocks, // We found multiple blocks of a kind that should - // have only one - NeverResolvedValueFoundInFunction, - NeverResolvedFunctionFromBlockAddress, - InvalidValue // Invalid version, inst number, attr number, etc - }; + enum class BitcodeError { InvalidBitcodeSignature, CorruptedBitcode }; inline std::error_code make_error_code(BitcodeError E) { return std::error_code(static_cast(E), BitcodeErrorCategory()); } + class BitcodeDiagnosticInfo : public DiagnosticInfo { + const Twine &Msg; + std::error_code EC; + + public: + BitcodeDiagnosticInfo(std::error_code EC, DiagnosticSeverity Severity, + const Twine &Msg); + void print(DiagnosticPrinter &DP) const override; + std::error_code getError() const { return EC; }; + + static bool classof(const DiagnosticInfo *DI) { + return DI->getKind() == DK_Bitcode; + } + }; + } // End llvm namespace namespace std { diff --git a/include/llvm/CodeGen/Analysis.h b/include/llvm/CodeGen/Analysis.h index 3132999..c4b94ed 100644 --- a/include/llvm/CodeGen/Analysis.h +++ b/include/llvm/CodeGen/Analysis.h @@ -31,10 +31,21 @@ class SDValue; class SelectionDAG; struct EVT; -/// ComputeLinearIndex - Given an LLVM IR aggregate type and a sequence -/// of insertvalue or extractvalue indices that identify a member, return -/// the linearized index of the start of the member. +/// \brief Compute the linearized index of a member in a nested +/// aggregate/struct/array. /// +/// Given an LLVM IR aggregate type and a sequence of insertvalue or +/// extractvalue indices that identify a member, return the linearized index of +/// the start of the member, i.e the number of element in memory before the +/// seeked one. This is disconnected from the number of bytes. +/// +/// \param Ty is the type indexed by \p Indices. +/// \param Indices is an optional pointer in the indices list to the current +/// index. +/// \param IndicesEnd is the end of the indices list. +/// \param CurIndex is the current index in the recursion. +/// +/// \returns \p CurIndex plus the linear index in \p Ty the indices list. unsigned ComputeLinearIndex(Type *Ty, const unsigned *Indices, const unsigned *IndicesEnd, diff --git a/include/llvm/CodeGen/AsmPrinter.h b/include/llvm/CodeGen/AsmPrinter.h index 25b99a2..ac224d8 100644 --- a/include/llvm/CodeGen/AsmPrinter.h +++ b/include/llvm/CodeGen/AsmPrinter.h @@ -44,8 +44,8 @@ class MachineModuleInfo; class MCAsmInfo; class MCCFIInstruction; class MCContext; +class MCExpr; class MCInst; -class MCInstrInfo; class MCSection; class MCStreamer; class MCSubtargetInfo; @@ -68,7 +68,6 @@ public: /// const MCAsmInfo *MAI; - const MCInstrInfo *MII; /// This is the context for the output file that we are streaming. This owns /// all of the global MC-related objects for the generated translation unit. MCContext &OutContext; @@ -98,6 +97,11 @@ public: /// default, this is equal to CurrentFnSym. MCSymbol *CurrentFnSymForSize; + /// Map global GOT equivalent MCSymbols to GlobalVariables and keep track of + /// its number of uses by other globals. + typedef std::pair GOTEquivUsePair; + DenseMap GlobalGOTEquivs; + private: // The garbage collection metadata printer table. void *GCMetadataPrinters; // Really a DenseMap. @@ -126,12 +130,13 @@ private: DwarfDebug *DD; protected: - explicit AsmPrinter(TargetMachine &TM, MCStreamer &Streamer); + explicit AsmPrinter(TargetMachine &TM, std::unique_ptr Streamer); public: virtual ~AsmPrinter(); DwarfDebug *getDwarfDebug() { return DD; } + DwarfDebug *getDwarfDebug() const { return DD; } /// Return true if assembly output should contain comments. /// @@ -203,6 +208,8 @@ public: void emitCFIInstruction(const MachineInstr &MI); + void emitFrameAlloc(const MachineInstr &MI); + enum CFIMoveType { CFI_M_None, CFI_M_EH, CFI_M_Debug }; CFIMoveType needsCFIMoves(); @@ -234,13 +241,27 @@ public: /// void EmitAlignment(unsigned NumBits, const GlobalObject *GO = nullptr) const; - /// This method prints the label for the specified MachineBasicBlock, an - /// alignment (if present) and a comment describing it if appropriate. - void EmitBasicBlockStart(const MachineBasicBlock &MBB) const; + /// Lower the specified LLVM Constant to an MCExpr. + const MCExpr *lowerConstant(const Constant *CV); /// \brief Print a general LLVM constant to the .s file. void EmitGlobalConstant(const Constant *CV); + /// \brief Unnamed constant global variables solely contaning a pointer to + /// another globals variable act like a global variable "proxy", or GOT + /// equivalents, i.e., it's only used to hold the address of the latter. One + /// optimization is to replace accesses to these proxies by using the GOT + /// entry for the final global instead. Hence, we select GOT equivalent + /// candidates among all the module global variables, avoid emitting them + /// unnecessarily and finally replace references to them by pc relative + /// accesses to GOT entries. + void computeGlobalGOTEquivs(Module &M); + + /// \brief Constant expressions using GOT equivalent globals may not be + /// eligible for PC relative GOT entry conversion, in such cases we need to + /// emit the proxies we previously omitted in EmitGlobalVariable. + void emitGlobalGOTEquivs(); + //===------------------------------------------------------------------===// // Overridable Hooks //===------------------------------------------------------------------===// @@ -264,6 +285,12 @@ public: /// function. virtual void EmitFunctionBodyEnd() {} + /// Targets can override this to emit stuff at the start of a basic block. + /// By default, this method prints the label for the specified + /// MachineBasicBlock, an alignment (if present) and a comment describing it + /// if appropriate. + virtual void EmitBasicBlockStart(const MachineBasicBlock &MBB) const; + /// Targets can override this to emit stuff at the end of a basic block. virtual void EmitBasicBlockEnd(const MachineBasicBlock &MBB) {} @@ -299,10 +326,10 @@ public: public: /// Return the MCSymbol corresponding to the assembler temporary label with /// the specified stem and unique ID. - MCSymbol *GetTempSymbol(Twine Name, unsigned ID) const; + MCSymbol *GetTempSymbol(const Twine &Name, unsigned ID) const; /// Return an assembler temporary label with the specified stem. - MCSymbol *GetTempSymbol(Twine Name) const; + MCSymbol *GetTempSymbol(const Twine &Name) const; /// Return the MCSymbol for a private symbol with global value name as its /// base, with the specified suffix. @@ -397,7 +424,7 @@ public: const MCSymbol *SectionLabel) const; /// Get the value for DW_AT_APPLE_isa. Zero if no isa encoding specified. - virtual unsigned getISAEncoding() { return 0; } + virtual unsigned getISAEncoding(const Function *) { return 0; } /// Emit a dwarf register operation for describing /// - a small value occupying only part of a register or @@ -423,9 +450,8 @@ public: unsigned PieceOffset = 0) const; /// EmitDwarfRegOp - Emit a dwarf register operation. - /// \param Indirect whether this is a register-indirect address - virtual void EmitDwarfRegOp(ByteStreamer &BS, const MachineLocation &MLoc, - bool Indirect) const; + virtual void EmitDwarfRegOp(ByteStreamer &BS, + const MachineLocation &MLoc) const; //===------------------------------------------------------------------===// // Dwarf Lowering Routines @@ -465,6 +491,10 @@ public: unsigned AsmVariant, const char *ExtraCode, raw_ostream &OS); + /// Let the target do anything it needs to do before emitting inlineasm. + /// \p StartInfo - the subtarget info before parsing inline asm + virtual void emitInlineAsmStart() const; + /// Let the target do anything it needs to do after emitting inlineasm. /// This callback can be used restore the original mode in case the /// inlineasm contains directives to switch modes. diff --git a/include/llvm/CodeGen/BasicTTIImpl.h b/include/llvm/CodeGen/BasicTTIImpl.h new file mode 100644 index 0000000..ff85b06 --- /dev/null +++ b/include/llvm/CodeGen/BasicTTIImpl.h @@ -0,0 +1,723 @@ +//===- BasicTTIImpl.h -------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// This file provides a helper that implements much of the TTI interface in +/// terms of the target-independent code generator and TargetLowering +/// interfaces. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_BASICTTIIMPL_H +#define LLVM_CODEGEN_BASICTTIIMPL_H + +#include "llvm/Analysis/LoopInfo.h" +#include "llvm/Analysis/TargetTransformInfoImpl.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Target/TargetLowering.h" +#include "llvm/Target/TargetSubtargetInfo.h" + +namespace llvm { + +extern cl::opt PartialUnrollingThreshold; + +/// \brief Base class which can be used to help build a TTI implementation. +/// +/// This class provides as much implementation of the TTI interface as is +/// possible using the target independent parts of the code generator. +/// +/// In order to subclass it, your class must implement a getST() method to +/// return the subtarget, and a getTLI() method to return the target lowering. +/// We need these methods implemented in the derived class so that this class +/// doesn't have to duplicate storage for them. +template +class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase { +private: + typedef TargetTransformInfoImplCRTPBase 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(this) + ->getVectorInstrCost(Instruction::InsertElement, Ty, i); + if (Extract) + Cost += static_cast(this) + ->getVectorInstrCost(Instruction::ExtractElement, Ty, i); + } + + return Cost; + } + + /// Estimate the cost overhead of SK_Alternate shuffle. + unsigned getAltShuffleOverhead(Type *Ty) { + assert(Ty->isVectorTy() && "Can only shuffle vectors"); + unsigned Cost = 0; + // Shuffle cost is equal to the cost of extracting element from its argument + // plus the cost of inserting them onto the result vector. + + // e.g. <4 x float> has a mask of <0,5,2,7> i.e we need to extract from + // index 0 of first vector, index 1 of second vector,index 2 of first + // vector and finally index 3 of second vector and insert them at index + // <0,1,2,3> of result vector. + for (int i = 0, e = Ty->getVectorNumElements(); i < e; ++i) { + Cost += static_cast(this) + ->getVectorInstrCost(Instruction::InsertElement, Ty, i); + Cost += static_cast(this) + ->getVectorInstrCost(Instruction::ExtractElement, Ty, i); + } + return Cost; + } + + /// \brief Local query method delegates up to T which *must* implement this! + const TargetSubtargetInfo *getST() const { + return static_cast(this)->getST(); + } + + /// \brief Local query method delegates up to T which *must* implement this! + const TargetLoweringBase *getTLI() const { + return static_cast(this)->getTLI(); + } + +protected: + explicit BasicTTIImplBase(const TargetMachine *TM) + : BaseT(TM->getDataLayout()) {} + +public: + // Provide value semantics. MSVC requires that we spell all of these out. + BasicTTIImplBase(const BasicTTIImplBase &Arg) + : BaseT(static_cast(Arg)) {} + BasicTTIImplBase(BasicTTIImplBase &&Arg) + : BaseT(std::move(static_cast(Arg))) {} + BasicTTIImplBase &operator=(const BasicTTIImplBase &RHS) { + BaseT::operator=(static_cast(RHS)); + return *this; + } + BasicTTIImplBase &operator=(BasicTTIImplBase &&RHS) { + BaseT::operator=(std::move(static_cast(RHS))); + return *this; + } + + /// \name Scalar TTI Implementations + /// @{ + + bool hasBranchDivergence() { return false; } + + bool isLegalAddImmediate(int64_t imm) { + return getTLI()->isLegalAddImmediate(imm); + } + + bool isLegalICmpImmediate(int64_t imm) { + return getTLI()->isLegalICmpImmediate(imm); + } + + bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset, + bool HasBaseReg, int64_t Scale) { + TargetLoweringBase::AddrMode AM; + AM.BaseGV = BaseGV; + AM.BaseOffs = BaseOffset; + AM.HasBaseReg = HasBaseReg; + AM.Scale = Scale; + return getTLI()->isLegalAddressingMode(AM, Ty); + } + + int getScalingFactorCost(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset, + bool HasBaseReg, int64_t Scale) { + TargetLoweringBase::AddrMode AM; + AM.BaseGV = BaseGV; + AM.BaseOffs = BaseOffset; + AM.HasBaseReg = HasBaseReg; + AM.Scale = Scale; + return getTLI()->getScalingFactorCost(AM, Ty); + } + + bool isTruncateFree(Type *Ty1, Type *Ty2) { + return getTLI()->isTruncateFree(Ty1, Ty2); + } + + bool isProfitableToHoist(Instruction *I) { + return getTLI()->isProfitableToHoist(I); + } + + bool isTypeLegal(Type *Ty) { + EVT VT = getTLI()->getValueType(Ty); + return getTLI()->isTypeLegal(VT); + } + + unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy, + ArrayRef Arguments) { + return BaseT::getIntrinsicCost(IID, RetTy, Arguments); + } + + unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy, + ArrayRef ParamTys) { + if (IID == Intrinsic::cttz) { + if (getTLI()->isCheapToSpeculateCttz()) + return TargetTransformInfo::TCC_Basic; + return TargetTransformInfo::TCC_Expensive; + } + + if (IID == Intrinsic::ctlz) { + if (getTLI()->isCheapToSpeculateCtlz()) + return TargetTransformInfo::TCC_Basic; + return TargetTransformInfo::TCC_Expensive; + } + + return BaseT::getIntrinsicCost(IID, RetTy, ParamTys); + } + + unsigned getJumpBufAlignment() { return getTLI()->getJumpBufAlignment(); } + + unsigned getJumpBufSize() { return getTLI()->getJumpBufSize(); } + + bool shouldBuildLookupTables() { + const TargetLoweringBase *TLI = getTLI(); + return TLI->isOperationLegalOrCustom(ISD::BR_JT, MVT::Other) || + TLI->isOperationLegalOrCustom(ISD::BRIND, MVT::Other); + } + + bool haveFastSqrt(Type *Ty) { + const TargetLoweringBase *TLI = getTLI(); + EVT VT = TLI->getValueType(Ty); + return TLI->isTypeLegal(VT) && + TLI->isOperationLegalOrCustom(ISD::FSQRT, VT); + } + + unsigned getFPOpCost(Type *Ty) { + // By default, FP instructions are no more expensive since they are + // implemented in HW. Target specific TTI can override this. + return TargetTransformInfo::TCC_Basic; + } + + unsigned getOperationCost(unsigned Opcode, Type *Ty, Type *OpTy) { + const TargetLoweringBase *TLI = getTLI(); + switch (Opcode) { + default: break; + case Instruction::Trunc: { + if (TLI->isTruncateFree(OpTy, Ty)) + return TargetTransformInfo::TCC_Free; + return TargetTransformInfo::TCC_Basic; + } + case Instruction::ZExt: { + if (TLI->isZExtFree(OpTy, Ty)) + return TargetTransformInfo::TCC_Free; + return TargetTransformInfo::TCC_Basic; + } + } + + return BaseT::getOperationCost(Opcode, Ty, OpTy); + } + + void getUnrollingPreferences(Loop *L, TTI::UnrollingPreferences &UP) { + // This unrolling functionality is target independent, but to provide some + // motivation for its intended use, for x86: + + // According to the Intel 64 and IA-32 Architectures Optimization Reference + // Manual, Intel Core models and later have a loop stream detector (and + // associated uop queue) that can benefit from partial unrolling. + // The relevant requirements are: + // - The loop must have no more than 4 (8 for Nehalem and later) branches + // taken, and none of them may be calls. + // - The loop can have no more than 18 (28 for Nehalem and later) uops. + + // According to the Software Optimization Guide for AMD Family 15h + // Processors, models 30h-4fh (Steamroller and later) have a loop predictor + // and loop buffer which can benefit from partial unrolling. + // The relevant requirements are: + // - The loop must have fewer than 16 branches + // - The loop must have less than 40 uops in all executed loop branches + + // The number of taken branches in a loop is hard to estimate here, and + // benchmarking has revealed that it is better not to be conservative when + // estimating the branch count. As a result, we'll ignore the branch limits + // until someone finds a case where it matters in practice. + + unsigned MaxOps; + const TargetSubtargetInfo *ST = getST(); + if (PartialUnrollingThreshold.getNumOccurrences() > 0) + MaxOps = PartialUnrollingThreshold; + else if (ST->getSchedModel().LoopMicroOpBufferSize > 0) + MaxOps = ST->getSchedModel().LoopMicroOpBufferSize; + else + return; + + // Scan the loop: don't unroll loops with calls. + for (Loop::block_iterator I = L->block_begin(), E = L->block_end(); I != E; + ++I) { + BasicBlock *BB = *I; + + for (BasicBlock::iterator J = BB->begin(), JE = BB->end(); J != JE; ++J) + if (isa(J) || isa(J)) { + ImmutableCallSite CS(J); + if (const Function *F = CS.getCalledFunction()) { + if (!static_cast(this)->isLoweredToCall(F)) + continue; + } + + return; + } + } + + // Enable runtime and partial unrolling up to the specified size. + UP.Partial = UP.Runtime = true; + UP.PartialThreshold = UP.PartialOptSizeThreshold = MaxOps; + } + + /// @} + + /// \name Vector TTI Implementations + /// @{ + + unsigned getNumberOfRegisters(bool Vector) { return 1; } + + unsigned getRegisterBitWidth(bool Vector) { return 32; } + + unsigned getMaxInterleaveFactor() { return 1; } + + unsigned getArithmeticInstrCost( + unsigned Opcode, Type *Ty, + TTI::OperandValueKind Opd1Info = TTI::OK_AnyValue, + TTI::OperandValueKind Opd2Info = TTI::OK_AnyValue, + TTI::OperandValueProperties Opd1PropInfo = TTI::OP_None, + TTI::OperandValueProperties Opd2PropInfo = TTI::OP_None) { + // Check if any of the operands are vector operands. + const TargetLoweringBase *TLI = getTLI(); + int ISD = TLI->InstructionOpcodeToISD(Opcode); + assert(ISD && "Invalid opcode"); + + std::pair LT = TLI->getTypeLegalizationCost(Ty); + + bool IsFloat = Ty->getScalarType()->isFloatingPointTy(); + // Assume that floating point arithmetic operations cost twice as much as + // integer operations. + unsigned OpCost = (IsFloat ? 2 : 1); + + if (TLI->isOperationLegalOrPromote(ISD, LT.second)) { + // The operation is legal. Assume it costs 1. + // If the type is split to multiple registers, assume that there is some + // overhead to this. + // TODO: Once we have extract/insert subvector cost we need to use them. + if (LT.first > 1) + return LT.first * 2 * OpCost; + return LT.first * 1 * OpCost; + } + + if (!TLI->isOperationExpand(ISD, LT.second)) { + // If the operation is custom lowered then assume + // thare the code is twice as expensive. + return LT.first * 2 * OpCost; + } + + // Else, assume that we need to scalarize this op. + if (Ty->isVectorTy()) { + unsigned Num = Ty->getVectorNumElements(); + unsigned Cost = static_cast(this) + ->getArithmeticInstrCost(Opcode, Ty->getScalarType()); + // return the cost of multiple scalar invocation plus the cost of + // inserting + // and extracting the values. + return getScalarizationOverhead(Ty, true, true) + Num * Cost; + } + + // We don't know anything about this scalar instruction. + return OpCost; + } + + unsigned getShuffleCost(TTI::ShuffleKind Kind, Type *Tp, int Index, + Type *SubTp) { + if (Kind == TTI::SK_Alternate) { + return getAltShuffleOverhead(Tp); + } + return 1; + } + + unsigned getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src) { + const TargetLoweringBase *TLI = getTLI(); + int ISD = TLI->InstructionOpcodeToISD(Opcode); + assert(ISD && "Invalid opcode"); + + std::pair SrcLT = TLI->getTypeLegalizationCost(Src); + std::pair DstLT = TLI->getTypeLegalizationCost(Dst); + + // Check for NOOP conversions. + if (SrcLT.first == DstLT.first && + SrcLT.second.getSizeInBits() == DstLT.second.getSizeInBits()) { + + // Bitcast between types that are legalized to the same type are free. + if (Opcode == Instruction::BitCast || Opcode == Instruction::Trunc) + return 0; + } + + if (Opcode == Instruction::Trunc && + TLI->isTruncateFree(SrcLT.second, DstLT.second)) + return 0; + + if (Opcode == Instruction::ZExt && + TLI->isZExtFree(SrcLT.second, DstLT.second)) + return 0; + + // If the cast is marked as legal (or promote) then assume low cost. + if (SrcLT.first == DstLT.first && + TLI->isOperationLegalOrPromote(ISD, DstLT.second)) + return 1; + + // Handle scalar conversions. + if (!Src->isVectorTy() && !Dst->isVectorTy()) { + + // Scalar bitcasts are usually free. + if (Opcode == Instruction::BitCast) + return 0; + + // Just check the op cost. If the operation is legal then assume it costs + // 1. + if (!TLI->isOperationExpand(ISD, DstLT.second)) + return 1; + + // Assume that illegal scalar instruction are expensive. + return 4; + } + + // Check vector-to-vector casts. + if (Dst->isVectorTy() && Src->isVectorTy()) { + + // If the cast is between same-sized registers, then the check is simple. + if (SrcLT.first == DstLT.first && + SrcLT.second.getSizeInBits() == DstLT.second.getSizeInBits()) { + + // Assume that Zext is done using AND. + if (Opcode == Instruction::ZExt) + return 1; + + // Assume that sext is done using SHL and SRA. + if (Opcode == Instruction::SExt) + return 2; + + // Just check the op cost. If the operation is legal then assume it + // costs + // 1 and multiply by the type-legalization overhead. + if (!TLI->isOperationExpand(ISD, DstLT.second)) + return SrcLT.first * 1; + } + + // If we are converting vectors and the operation is illegal, or + // if the vectors are legalized to different types, estimate the + // scalarization costs. + unsigned Num = Dst->getVectorNumElements(); + unsigned Cost = static_cast(this)->getCastInstrCost( + Opcode, Dst->getScalarType(), Src->getScalarType()); + + // Return the cost of multiple scalar invocation plus the cost of + // inserting and extracting the values. + return getScalarizationOverhead(Dst, true, true) + Num * Cost; + } + + // We already handled vector-to-vector and scalar-to-scalar conversions. + // This + // is where we handle bitcast between vectors and scalars. We need to assume + // that the conversion is scalarized in one way or another. + if (Opcode == Instruction::BitCast) + // Illegal bitcasts are done by storing and loading from a stack slot. + return (Src->isVectorTy() ? getScalarizationOverhead(Src, false, true) + : 0) + + (Dst->isVectorTy() ? getScalarizationOverhead(Dst, true, false) + : 0); + + llvm_unreachable("Unhandled cast"); + } + + unsigned getCFInstrCost(unsigned Opcode) { + // Branches are assumed to be predicted. + return 0; + } + + unsigned getCmpSelInstrCost(unsigned Opcode, Type *ValTy, Type *CondTy) { + const TargetLoweringBase *TLI = getTLI(); + int ISD = TLI->InstructionOpcodeToISD(Opcode); + assert(ISD && "Invalid opcode"); + + // Selects on vectors are actually vector selects. + if (ISD == ISD::SELECT) { + assert(CondTy && "CondTy must exist"); + if (CondTy->isVectorTy()) + ISD = ISD::VSELECT; + } + + std::pair LT = TLI->getTypeLegalizationCost(ValTy); + + if (!(ValTy->isVectorTy() && !LT.second.isVector()) && + !TLI->isOperationExpand(ISD, LT.second)) { + // The operation is legal. Assume it costs 1. Multiply + // by the type-legalization overhead. + return LT.first * 1; + } + + // Otherwise, assume that the cast is scalarized. + if (ValTy->isVectorTy()) { + unsigned Num = ValTy->getVectorNumElements(); + if (CondTy) + CondTy = CondTy->getScalarType(); + unsigned Cost = static_cast(this)->getCmpSelInstrCost( + Opcode, ValTy->getScalarType(), CondTy); + + // Return the cost of multiple scalar invocation plus the cost of + // inserting + // and extracting the values. + return getScalarizationOverhead(ValTy, true, false) + Num * Cost; + } + + // Unknown scalar opcode. + return 1; + } + + unsigned getVectorInstrCost(unsigned Opcode, Type *Val, unsigned Index) { + std::pair LT = + getTLI()->getTypeLegalizationCost(Val->getScalarType()); + + return LT.first; + } + + unsigned getMemoryOpCost(unsigned Opcode, Type *Src, unsigned Alignment, + unsigned AddressSpace) { + assert(!Src->isVoidTy() && "Invalid type"); + std::pair LT = getTLI()->getTypeLegalizationCost(Src); + + // Assuming that all loads of legal types cost 1. + unsigned Cost = LT.first; + + if (Src->isVectorTy() && + Src->getPrimitiveSizeInBits() < LT.second.getSizeInBits()) { + // This is a vector load that legalizes to a larger type than the vector + // itself. Unless the corresponding extending load or truncating store is + // legal, then this will scalarize. + TargetLowering::LegalizeAction LA = TargetLowering::Expand; + EVT MemVT = getTLI()->getValueType(Src, true); + if (MemVT.isSimple() && MemVT != MVT::Other) { + if (Opcode == Instruction::Store) + LA = getTLI()->getTruncStoreAction(LT.second, MemVT.getSimpleVT()); + else + LA = getTLI()->getLoadExtAction(ISD::EXTLOAD, LT.second, MemVT); + } + + if (LA != TargetLowering::Legal && LA != TargetLowering::Custom) { + // This is a vector load/store for some illegal type that is scalarized. + // We must account for the cost of building or decomposing the vector. + Cost += getScalarizationOverhead(Src, Opcode != Instruction::Store, + Opcode == Instruction::Store); + } + } + + return Cost; + } + + unsigned getIntrinsicInstrCost(Intrinsic::ID IID, Type *RetTy, + ArrayRef Tys) { + unsigned ISD = 0; + switch (IID) { + default: { + // Assume that we need to scalarize this intrinsic. + unsigned ScalarizationCost = 0; + unsigned ScalarCalls = 1; + if (RetTy->isVectorTy()) { + ScalarizationCost = getScalarizationOverhead(RetTy, true, false); + ScalarCalls = std::max(ScalarCalls, RetTy->getVectorNumElements()); + } + for (unsigned i = 0, ie = Tys.size(); i != ie; ++i) { + if (Tys[i]->isVectorTy()) { + ScalarizationCost += getScalarizationOverhead(Tys[i], false, true); + ScalarCalls = std::max(ScalarCalls, RetTy->getVectorNumElements()); + } + } + + return ScalarCalls + ScalarizationCost; + } + // Look for intrinsics that can be lowered directly or turned into a scalar + // intrinsic call. + case Intrinsic::sqrt: + ISD = ISD::FSQRT; + break; + case Intrinsic::sin: + ISD = ISD::FSIN; + break; + case Intrinsic::cos: + ISD = ISD::FCOS; + break; + case Intrinsic::exp: + ISD = ISD::FEXP; + break; + case Intrinsic::exp2: + ISD = ISD::FEXP2; + break; + case Intrinsic::log: + ISD = ISD::FLOG; + break; + case Intrinsic::log10: + ISD = ISD::FLOG10; + break; + case Intrinsic::log2: + ISD = ISD::FLOG2; + break; + case Intrinsic::fabs: + ISD = ISD::FABS; + break; + case Intrinsic::minnum: + ISD = ISD::FMINNUM; + break; + case Intrinsic::maxnum: + ISD = ISD::FMAXNUM; + break; + case Intrinsic::copysign: + ISD = ISD::FCOPYSIGN; + break; + case Intrinsic::floor: + ISD = ISD::FFLOOR; + break; + case Intrinsic::ceil: + ISD = ISD::FCEIL; + break; + case Intrinsic::trunc: + ISD = ISD::FTRUNC; + break; + case Intrinsic::nearbyint: + ISD = ISD::FNEARBYINT; + break; + case Intrinsic::rint: + ISD = ISD::FRINT; + break; + case Intrinsic::round: + ISD = ISD::FROUND; + break; + case Intrinsic::pow: + ISD = ISD::FPOW; + break; + case Intrinsic::fma: + ISD = ISD::FMA; + break; + case Intrinsic::fmuladd: + ISD = ISD::FMA; + break; + // FIXME: We should return 0 whenever getIntrinsicCost == TCC_Free. + case Intrinsic::lifetime_start: + case Intrinsic::lifetime_end: + return 0; + case Intrinsic::masked_store: + return static_cast(this) + ->getMaskedMemoryOpCost(Instruction::Store, Tys[0], 0, 0); + case Intrinsic::masked_load: + return static_cast(this) + ->getMaskedMemoryOpCost(Instruction::Load, RetTy, 0, 0); + } + + const TargetLoweringBase *TLI = getTLI(); + std::pair LT = TLI->getTypeLegalizationCost(RetTy); + + if (TLI->isOperationLegalOrPromote(ISD, LT.second)) { + // The operation is legal. Assume it costs 1. + // If the type is split to multiple registers, assume that there is some + // overhead to this. + // TODO: Once we have extract/insert subvector cost we need to use them. + if (LT.first > 1) + return LT.first * 2; + return LT.first * 1; + } + + if (!TLI->isOperationExpand(ISD, LT.second)) { + // If the operation is custom lowered then assume + // thare the code is twice as expensive. + return LT.first * 2; + } + + // If we can't lower fmuladd into an FMA estimate the cost as a floating + // point mul followed by an add. + if (IID == Intrinsic::fmuladd) + return static_cast(this) + ->getArithmeticInstrCost(BinaryOperator::FMul, RetTy) + + static_cast(this) + ->getArithmeticInstrCost(BinaryOperator::FAdd, RetTy); + + // Else, assume that we need to scalarize this intrinsic. For math builtins + // this will emit a costly libcall, adding call overhead and spills. Make it + // very expensive. + if (RetTy->isVectorTy()) { + unsigned Num = RetTy->getVectorNumElements(); + unsigned Cost = static_cast(this)->getIntrinsicInstrCost( + IID, RetTy->getScalarType(), Tys); + return 10 * Cost * Num; + } + + // This is going to be turned into a library call, make it expensive. + return 10; + } + + unsigned getNumberOfParts(Type *Tp) { + std::pair LT = getTLI()->getTypeLegalizationCost(Tp); + return LT.first; + } + + unsigned getAddressComputationCost(Type *Ty, bool IsComplex) { return 0; } + + unsigned getReductionCost(unsigned Opcode, Type *Ty, bool IsPairwise) { + assert(Ty->isVectorTy() && "Expect a vector type"); + unsigned NumVecElts = Ty->getVectorNumElements(); + unsigned NumReduxLevels = Log2_32(NumVecElts); + unsigned ArithCost = + NumReduxLevels * + static_cast(this)->getArithmeticInstrCost(Opcode, Ty); + // Assume the pairwise shuffles add a cost. + unsigned ShuffleCost = + NumReduxLevels * (IsPairwise + 1) * + static_cast(this) + ->getShuffleCost(TTI::SK_ExtractSubvector, Ty, NumVecElts / 2, Ty); + return ShuffleCost + ArithCost + getScalarizationOverhead(Ty, false, true); + } + + /// @} +}; + +/// \brief Concrete BasicTTIImpl that can be used if no further customization +/// is needed. +class BasicTTIImpl : public BasicTTIImplBase { + typedef BasicTTIImplBase BaseT; + friend class BasicTTIImplBase; + + const TargetSubtargetInfo *ST; + const TargetLoweringBase *TLI; + + const TargetSubtargetInfo *getST() const { return ST; } + const TargetLoweringBase *getTLI() const { return TLI; } + +public: + explicit BasicTTIImpl(const TargetMachine *ST, Function &F); + + // Provide value semantics. MSVC requires that we spell all of these out. + BasicTTIImpl(const BasicTTIImpl &Arg) + : BaseT(static_cast(Arg)), ST(Arg.ST), TLI(Arg.TLI) {} + BasicTTIImpl(BasicTTIImpl &&Arg) + : BaseT(std::move(static_cast(Arg))), ST(std::move(Arg.ST)), + TLI(std::move(Arg.TLI)) {} + BasicTTIImpl &operator=(const BasicTTIImpl &RHS) { + BaseT::operator=(static_cast(RHS)); + ST = RHS.ST; + TLI = RHS.TLI; + return *this; + } + BasicTTIImpl &operator=(BasicTTIImpl &&RHS) { + BaseT::operator=(std::move(static_cast(RHS))); + ST = std::move(RHS.ST); + TLI = std::move(RHS.TLI); + return *this; + } +}; + +} + +#endif diff --git a/include/llvm/CodeGen/CallingConvLower.h b/include/llvm/CodeGen/CallingConvLower.h index 0b2ccc6..e2b744f 100644 --- a/include/llvm/CodeGen/CallingConvLower.h +++ b/include/llvm/CodeGen/CallingConvLower.h @@ -122,8 +122,8 @@ public: // There is no need to differentiate between a pending CCValAssign and other // kinds, as they are stored in a different list. static CCValAssign getPending(unsigned ValNo, MVT ValVT, MVT LocVT, - LocInfo HTP) { - return getReg(ValNo, ValVT, 0, LocVT, HTP); + LocInfo HTP, unsigned ExtraInfo = 0) { + return getReg(ValNo, ValVT, ExtraInfo, LocVT, HTP); } void convertToReg(unsigned RegNo) { @@ -146,6 +146,7 @@ public: unsigned getLocReg() const { assert(isRegLoc()); return Loc; } unsigned getLocMemOffset() const { assert(isMemLoc()); return Loc; } + unsigned getExtraInfo() const { return Loc; } MVT getLocVT() const { return LocVT; } LocInfo getLocInfo() const { return HTP; } @@ -158,6 +159,16 @@ public: } }; +/// Describes a register that needs to be forwarded from the prologue to a +/// musttail call. +struct ForwardedRegister { + ForwardedRegister(unsigned VReg, MCPhysReg PReg, MVT VT) + : VReg(VReg), PReg(PReg), VT(VT) {} + unsigned VReg; + MCPhysReg PReg; + MVT VT; +}; + /// CCAssignFn - This function assigns a location for Val, updating State to /// reflect the change. It returns 'true' if it failed to handle Val. typedef bool CCAssignFn(unsigned ValNo, MVT ValVT, @@ -302,13 +313,13 @@ public: /// produce a single value. void AnalyzeCallResult(MVT VT, CCAssignFn Fn); - /// getFirstUnallocated - Return the first unallocated register in the set, or - /// NumRegs if they are all allocated. - unsigned getFirstUnallocated(const MCPhysReg *Regs, unsigned NumRegs) const { - for (unsigned i = 0; i != NumRegs; ++i) + /// getFirstUnallocated - Return the index of the first unallocated register + /// in the set, or Regs.size() if they are all allocated. + unsigned getFirstUnallocated(ArrayRef Regs) const { + for (unsigned i = 0; i < Regs.size(); ++i) if (!isAllocated(Regs[i])) return i; - return NumRegs; + return Regs.size(); } /// AllocateReg - Attempt to allocate one register. If it is not available, @@ -331,9 +342,9 @@ public: /// AllocateReg - Attempt to allocate one of the specified registers. If none /// are available, return zero. Otherwise, return the first one available, /// marking it and any aliases as allocated. - unsigned AllocateReg(const MCPhysReg *Regs, unsigned NumRegs) { - unsigned FirstUnalloc = getFirstUnallocated(Regs, NumRegs); - if (FirstUnalloc == NumRegs) + unsigned AllocateReg(ArrayRef Regs) { + unsigned FirstUnalloc = getFirstUnallocated(Regs); + if (FirstUnalloc == Regs.size()) return 0; // Didn't find the reg. // Mark the register and any aliases as allocated. @@ -345,8 +356,12 @@ public: /// AllocateRegBlock - Attempt to allocate a block of RegsRequired consecutive /// registers. If this is not possible, return zero. Otherwise, return the first /// register of the block that were allocated, marking the entire block as allocated. - unsigned AllocateRegBlock(const uint16_t *Regs, unsigned NumRegs, unsigned RegsRequired) { - for (unsigned StartIdx = 0; StartIdx <= NumRegs - RegsRequired; ++StartIdx) { + unsigned AllocateRegBlock(ArrayRef Regs, unsigned RegsRequired) { + if (RegsRequired > Regs.size()) + return 0; + + for (unsigned StartIdx = 0; StartIdx <= Regs.size() - RegsRequired; + ++StartIdx) { bool BlockAvailable = true; // Check for already-allocated regs in this block for (unsigned BlockIdx = 0; BlockIdx < RegsRequired; ++BlockIdx) { @@ -368,10 +383,9 @@ public: } /// Version of AllocateReg with list of registers to be shadowed. - unsigned AllocateReg(const MCPhysReg *Regs, const MCPhysReg *ShadowRegs, - unsigned NumRegs) { - unsigned FirstUnalloc = getFirstUnallocated(Regs, NumRegs); - if (FirstUnalloc == NumRegs) + unsigned AllocateReg(ArrayRef Regs, const MCPhysReg *ShadowRegs) { + unsigned FirstUnalloc = getFirstUnallocated(Regs); + if (FirstUnalloc == Regs.size()) return 0; // Didn't find the reg. // Mark the register and any aliases as allocated. @@ -401,8 +415,8 @@ public: /// Version of AllocateStack with list of extra registers to be shadowed. /// Note that, unlike AllocateReg, this shadows ALL of the shadow registers. unsigned AllocateStack(unsigned Size, unsigned Align, - const MCPhysReg *ShadowRegs, unsigned NumShadowRegs) { - for (unsigned i = 0; i < NumShadowRegs; ++i) + ArrayRef ShadowRegs) { + for (unsigned i = 0; i < ShadowRegs.size(); ++i) MarkAllocated(ShadowRegs[i]); return AllocateStack(Size, Align); } @@ -466,6 +480,19 @@ public: return PendingLocs; } + /// Compute the remaining unused register parameters that would be used for + /// the given value type. This is useful when varargs are passed in the + /// registers that normal prototyped parameters would be passed in, or for + /// implementing perfect forwarding. + void getRemainingRegParmsForType(SmallVectorImpl &Regs, MVT VT, + CCAssignFn Fn); + + /// Compute the set of registers that need to be preserved and forwarded to + /// any musttail calls. + void analyzeMustTailForwardedRegisters( + SmallVectorImpl &Forwards, ArrayRef RegParmTypes, + CCAssignFn Fn); + private: /// MarkAllocated - Mark a register and all of its aliases as allocated. void MarkAllocated(unsigned Reg); diff --git a/include/llvm/CodeGen/CommandFlags.h b/include/llvm/CodeGen/CommandFlags.h index 973c595..9f86429 100644 --- a/include/llvm/CodeGen/CommandFlags.h +++ b/include/llvm/CodeGen/CommandFlags.h @@ -207,6 +207,10 @@ FunctionSections("function-sections", cl::desc("Emit functions into separate sections"), cl::init(false)); +cl::opt UniqueSectionNames("unique-section-names", + cl::desc("Give unique names to every section"), + cl::init(true)); + cl::opt JTableType("jump-table-type", cl::desc("Choose the type of Jump-Instruction Table for jumptable."), @@ -284,6 +288,7 @@ static inline TargetOptions InitTargetOptionsFromCodeGenFlags() { Options.UseInitArray = !UseCtors; Options.DataSections = DataSections; Options.FunctionSections = FunctionSections; + Options.UniqueSectionNames = UniqueSectionNames; Options.MCOptions = InitMCTargetOptionsFromFlags(); Options.JTType = JTableType; diff --git a/include/llvm/CodeGen/DIE.h b/include/llvm/CodeGen/DIE.h new file mode 100644 index 0000000..e310aef --- /dev/null +++ b/include/llvm/CodeGen/DIE.h @@ -0,0 +1,587 @@ +//===--- lib/CodeGen/DIE.h - DWARF Info Entries -----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Data structures for DWARF info entries. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_CODEGEN_ASMPRINTER_DIE_H +#define LLVM_LIB_CODEGEN_ASMPRINTER_DIE_H + +#include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/Dwarf.h" +#include + +namespace llvm { +class AsmPrinter; +class MCExpr; +class MCSymbol; +class raw_ostream; +class DwarfTypeUnit; + +//===--------------------------------------------------------------------===// +/// DIEAbbrevData - Dwarf abbreviation data, describes one attribute of a +/// Dwarf abbreviation. +class DIEAbbrevData { + /// Attribute - Dwarf attribute code. + /// + dwarf::Attribute Attribute; + + /// Form - Dwarf form code. + /// + dwarf::Form Form; + +public: + DIEAbbrevData(dwarf::Attribute A, dwarf::Form F) : Attribute(A), Form(F) {} + + // Accessors. + dwarf::Attribute getAttribute() const { return Attribute; } + dwarf::Form getForm() const { return Form; } + + /// Profile - Used to gather unique data for the abbreviation folding set. + /// + void Profile(FoldingSetNodeID &ID) const; +}; + +//===--------------------------------------------------------------------===// +/// DIEAbbrev - Dwarf abbreviation, describes the organization of a debug +/// information object. +class DIEAbbrev : public FoldingSetNode { + /// Unique number for node. + /// + unsigned Number; + + /// Tag - Dwarf tag code. + /// + dwarf::Tag Tag; + + /// Children - Whether or not this node has children. + /// + // This cheats a bit in all of the uses since the values in the standard + // are 0 and 1 for no children and children respectively. + bool Children; + + /// Data - Raw data bytes for abbreviation. + /// + SmallVector Data; + +public: + DIEAbbrev(dwarf::Tag T, bool C) : Tag(T), Children(C), Data() {} + + // Accessors. + dwarf::Tag getTag() const { return Tag; } + unsigned getNumber() const { return Number; } + bool hasChildren() const { return Children; } + const SmallVectorImpl &getData() const { return Data; } + void setChildrenFlag(bool hasChild) { Children = hasChild; } + void setNumber(unsigned N) { Number = N; } + + /// AddAttribute - Adds another set of attribute information to the + /// abbreviation. + void AddAttribute(dwarf::Attribute Attribute, dwarf::Form Form) { + Data.push_back(DIEAbbrevData(Attribute, Form)); + } + + /// Profile - Used to gather unique data for the abbreviation folding set. + /// + void Profile(FoldingSetNodeID &ID) const; + + /// Emit - Print the abbreviation using the specified asm printer. + /// + void Emit(AsmPrinter *AP) const; + +#ifndef NDEBUG + void print(raw_ostream &O); + void dump(); +#endif +}; + +//===--------------------------------------------------------------------===// +/// DIE - A structured debug information entry. Has an abbreviation which +/// describes its organization. +class DIEValue; + +class DIE { +protected: + /// Offset - Offset in debug info section. + /// + unsigned Offset; + + /// Size - Size of instance + children. + /// + unsigned Size; + + /// Abbrev - Buffer for constructing abbreviation. + /// + DIEAbbrev Abbrev; + + /// Children DIEs. + /// + // This can't be a vector because pointer validity is requirent for the + // Parent pointer and DIEEntry. + // It can't be a list because some clients need pointer validity before + // the object has been added to any child list + // (eg: DwarfUnit::constructVariableDIE). These aren't insurmountable, but may + // be more convoluted than beneficial. + std::vector> Children; + + DIE *Parent; + + /// Attribute values. + /// + SmallVector Values; + +protected: + DIE() + : Offset(0), Size(0), Abbrev((dwarf::Tag)0, dwarf::DW_CHILDREN_no), + Parent(nullptr) {} + +public: + explicit DIE(dwarf::Tag Tag) + : Offset(0), Size(0), Abbrev((dwarf::Tag)Tag, dwarf::DW_CHILDREN_no), + Parent(nullptr) {} + + // Accessors. + DIEAbbrev &getAbbrev() { return Abbrev; } + const DIEAbbrev &getAbbrev() const { return Abbrev; } + unsigned getAbbrevNumber() const { return Abbrev.getNumber(); } + dwarf::Tag getTag() const { return Abbrev.getTag(); } + unsigned getOffset() const { return Offset; } + unsigned getSize() const { return Size; } + const std::vector> &getChildren() const { + return Children; + } + const SmallVectorImpl &getValues() const { return Values; } + DIE *getParent() const { return Parent; } + /// Climb up the parent chain to get the compile or type unit DIE this DIE + /// belongs to. + const DIE *getUnit() const; + /// Similar to getUnit, returns null when DIE is not added to an + /// owner yet. + const DIE *getUnitOrNull() const; + void setOffset(unsigned O) { Offset = O; } + void setSize(unsigned S) { Size = S; } + + /// addValue - Add a value and attributes to a DIE. + /// + void addValue(dwarf::Attribute Attribute, dwarf::Form Form, DIEValue *Value) { + Abbrev.AddAttribute(Attribute, Form); + Values.push_back(Value); + } + + /// addChild - Add a child to the DIE. + /// + void addChild(std::unique_ptr Child) { + assert(!Child->getParent()); + Abbrev.setChildrenFlag(dwarf::DW_CHILDREN_yes); + Child->Parent = this; + Children.push_back(std::move(Child)); + } + + /// findAttribute - Find a value in the DIE with the attribute given, + /// returns NULL if no such attribute exists. + DIEValue *findAttribute(dwarf::Attribute Attribute) const; + +#ifndef NDEBUG + void print(raw_ostream &O, unsigned IndentCount = 0) const; + void dump(); +#endif +}; + +//===--------------------------------------------------------------------===// +/// DIEValue - A debug information entry value. Some of these roughly correlate +/// to DWARF attribute classes. +/// +class DIEValue { + virtual void anchor(); + +public: + enum Type { + isInteger, + isString, + isExpr, + isLabel, + isDelta, + isEntry, + isTypeSignature, + isBlock, + isLoc, + isLocList, + }; + +protected: + /// Ty - Type of data stored in the value. + /// + Type Ty; + + explicit DIEValue(Type T) : Ty(T) {} + virtual ~DIEValue() {} + +public: + // Accessors + Type getType() const { return Ty; } + + /// EmitValue - Emit value via the Dwarf writer. + /// + virtual void EmitValue(AsmPrinter *AP, dwarf::Form Form) const = 0; + + /// SizeOf - Return the size of a value in bytes. + /// + virtual unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const = 0; + +#ifndef NDEBUG + virtual void print(raw_ostream &O) const = 0; + void dump() const; +#endif +}; + +//===--------------------------------------------------------------------===// +/// DIEInteger - An integer value DIE. +/// +class DIEInteger : public DIEValue { + uint64_t Integer; + +public: + explicit DIEInteger(uint64_t I) : DIEValue(isInteger), Integer(I) {} + + /// BestForm - Choose the best form for integer. + /// + static dwarf::Form BestForm(bool IsSigned, uint64_t Int) { + if (IsSigned) { + const int64_t SignedInt = Int; + if ((char)Int == SignedInt) + return dwarf::DW_FORM_data1; + if ((short)Int == SignedInt) + return dwarf::DW_FORM_data2; + if ((int)Int == SignedInt) + return dwarf::DW_FORM_data4; + } else { + if ((unsigned char)Int == Int) + return dwarf::DW_FORM_data1; + if ((unsigned short)Int == Int) + return dwarf::DW_FORM_data2; + if ((unsigned int)Int == Int) + return dwarf::DW_FORM_data4; + } + return dwarf::DW_FORM_data8; + } + + /// EmitValue - Emit integer of appropriate size. + /// + void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override; + + uint64_t getValue() const { return Integer; } + + /// SizeOf - Determine size of integer value in bytes. + /// + unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override; + + // Implement isa/cast/dyncast. + static bool classof(const DIEValue *I) { return I->getType() == isInteger; } + +#ifndef NDEBUG + void print(raw_ostream &O) const override; +#endif +}; + +//===--------------------------------------------------------------------===// +/// DIEExpr - An expression DIE. +// +class DIEExpr : public DIEValue { + const MCExpr *Expr; + +public: + explicit DIEExpr(const MCExpr *E) : DIEValue(isExpr), Expr(E) {} + + /// EmitValue - Emit expression value. + /// + void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override; + + /// getValue - Get MCExpr. + /// + const MCExpr *getValue() const { return Expr; } + + /// SizeOf - Determine size of expression value in bytes. + /// + unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override; + + // Implement isa/cast/dyncast. + static bool classof(const DIEValue *E) { return E->getType() == isExpr; } + +#ifndef NDEBUG + void print(raw_ostream &O) const override; +#endif +}; + +//===--------------------------------------------------------------------===// +/// DIELabel - A label DIE. +// +class DIELabel : public DIEValue { + const MCSymbol *Label; + +public: + explicit DIELabel(const MCSymbol *L) : DIEValue(isLabel), Label(L) {} + + /// EmitValue - Emit label value. + /// + void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override; + + /// getValue - Get MCSymbol. + /// + const MCSymbol *getValue() const { return Label; } + + /// SizeOf - Determine size of label value in bytes. + /// + unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override; + + // Implement isa/cast/dyncast. + static bool classof(const DIEValue *L) { return L->getType() == isLabel; } + +#ifndef NDEBUG + void print(raw_ostream &O) const override; +#endif +}; + +//===--------------------------------------------------------------------===// +/// DIEDelta - A simple label difference DIE. +/// +class DIEDelta : public DIEValue { + const MCSymbol *LabelHi; + const MCSymbol *LabelLo; + +public: + DIEDelta(const MCSymbol *Hi, const MCSymbol *Lo) + : DIEValue(isDelta), LabelHi(Hi), LabelLo(Lo) {} + + /// EmitValue - Emit delta value. + /// + void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override; + + /// SizeOf - Determine size of delta value in bytes. + /// + unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override; + + // Implement isa/cast/dyncast. + static bool classof(const DIEValue *D) { return D->getType() == isDelta; } + +#ifndef NDEBUG + void print(raw_ostream &O) const override; +#endif +}; + +//===--------------------------------------------------------------------===// +/// DIEString - A container for string values. +/// +class DIEString : public DIEValue { + const DIEValue *Access; + StringRef Str; + +public: + DIEString(const DIEValue *Acc, StringRef S) + : DIEValue(isString), Access(Acc), Str(S) {} + + /// getString - Grab the string out of the object. + StringRef getString() const { return Str; } + + /// EmitValue - Emit delta value. + /// + void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override; + + /// SizeOf - Determine size of delta value in bytes. + /// + unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override; + + // Implement isa/cast/dyncast. + static bool classof(const DIEValue *D) { return D->getType() == isString; } + +#ifndef NDEBUG + void print(raw_ostream &O) const override; +#endif +}; + +//===--------------------------------------------------------------------===// +/// DIEEntry - A pointer to another debug information entry. An instance of +/// this class can also be used as a proxy for a debug information entry not +/// yet defined (ie. types.) +class DIEEntry : public DIEValue { + DIE &Entry; + +public: + explicit DIEEntry(DIE &E) : DIEValue(isEntry), Entry(E) { + } + + DIE &getEntry() const { return Entry; } + + /// EmitValue - Emit debug information entry offset. + /// + void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override; + + /// SizeOf - Determine size of debug information entry in bytes. + /// + unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override { + return Form == dwarf::DW_FORM_ref_addr ? getRefAddrSize(AP) + : sizeof(int32_t); + } + + /// Returns size of a ref_addr entry. + static unsigned getRefAddrSize(AsmPrinter *AP); + + // Implement isa/cast/dyncast. + static bool classof(const DIEValue *E) { return E->getType() == isEntry; } + +#ifndef NDEBUG + void print(raw_ostream &O) const override; +#endif +}; + +//===--------------------------------------------------------------------===// +/// \brief A signature reference to a type unit. +class DIETypeSignature : public DIEValue { + const DwarfTypeUnit &Unit; + +public: + explicit DIETypeSignature(const DwarfTypeUnit &Unit) + : DIEValue(isTypeSignature), Unit(Unit) {} + + /// \brief Emit type unit signature. + void EmitValue(AsmPrinter *Asm, dwarf::Form Form) const override; + + /// Returns size of a ref_sig8 entry. + unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override { + assert(Form == dwarf::DW_FORM_ref_sig8); + return 8; + } + + // \brief Implement isa/cast/dyncast. + static bool classof(const DIEValue *E) { + return E->getType() == isTypeSignature; + } +#ifndef NDEBUG + void print(raw_ostream &O) const override; + void dump() const; +#endif +}; + +//===--------------------------------------------------------------------===// +/// DIELoc - Represents an expression location. +// +class DIELoc : public DIEValue, public DIE { + mutable unsigned Size; // Size in bytes excluding size header. +public: + DIELoc() : DIEValue(isLoc), Size(0) {} + + /// ComputeSize - Calculate the size of the location expression. + /// + unsigned ComputeSize(AsmPrinter *AP) const; + + /// BestForm - Choose the best form for data. + /// + dwarf::Form BestForm(unsigned DwarfVersion) const { + if (DwarfVersion > 3) + return dwarf::DW_FORM_exprloc; + // Pre-DWARF4 location expressions were blocks and not exprloc. + if ((unsigned char)Size == Size) + return dwarf::DW_FORM_block1; + if ((unsigned short)Size == Size) + return dwarf::DW_FORM_block2; + if ((unsigned int)Size == Size) + return dwarf::DW_FORM_block4; + return dwarf::DW_FORM_block; + } + + /// EmitValue - Emit location data. + /// + void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override; + + /// SizeOf - Determine size of location data in bytes. + /// + unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override; + + // Implement isa/cast/dyncast. + static bool classof(const DIEValue *E) { return E->getType() == isLoc; } + +#ifndef NDEBUG + void print(raw_ostream &O) const override; +#endif +}; + +//===--------------------------------------------------------------------===// +/// DIEBlock - Represents a block of values. +// +class DIEBlock : public DIEValue, public DIE { + mutable unsigned Size; // Size in bytes excluding size header. +public: + DIEBlock() : DIEValue(isBlock), Size(0) {} + + /// ComputeSize - Calculate the size of the location expression. + /// + unsigned ComputeSize(AsmPrinter *AP) const; + + /// BestForm - Choose the best form for data. + /// + dwarf::Form BestForm() const { + if ((unsigned char)Size == Size) + return dwarf::DW_FORM_block1; + if ((unsigned short)Size == Size) + return dwarf::DW_FORM_block2; + if ((unsigned int)Size == Size) + return dwarf::DW_FORM_block4; + return dwarf::DW_FORM_block; + } + + /// EmitValue - Emit location data. + /// + void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override; + + /// SizeOf - Determine size of location data in bytes. + /// + unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override; + + // Implement isa/cast/dyncast. + static bool classof(const DIEValue *E) { return E->getType() == isBlock; } + +#ifndef NDEBUG + void print(raw_ostream &O) const override; +#endif +}; + +//===--------------------------------------------------------------------===// +/// DIELocList - Represents a pointer to a location list in the debug_loc +/// section. +// +class DIELocList : public DIEValue { + // Index into the .debug_loc vector. + size_t Index; + +public: + DIELocList(size_t I) : DIEValue(isLocList), Index(I) {} + + /// getValue - Grab the current index out. + size_t getValue() const { return Index; } + + /// EmitValue - Emit location data. + /// + void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override; + + /// SizeOf - Determine size of location data in bytes. + /// + unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override; + + // Implement isa/cast/dyncast. + static bool classof(const DIEValue *E) { return E->getType() == isLocList; } + +#ifndef NDEBUG + void print(raw_ostream &O) const override; +#endif +}; + +} // end llvm namespace + +#endif diff --git a/include/llvm/CodeGen/FastISel.h b/include/llvm/CodeGen/FastISel.h index b5405f9..1dca2ce 100644 --- a/include/llvm/CodeGen/FastISel.h +++ b/include/llvm/CodeGen/FastISel.h @@ -18,9 +18,9 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/CodeGen/CallingConvLower.h" #include "llvm/CodeGen/MachineBasicBlock.h" -#include "llvm/Target/TargetLowering.h" #include "llvm/IR/CallingConv.h" #include "llvm/IR/IntrinsicInst.h" +#include "llvm/Target/TargetLowering.h" namespace llvm { @@ -76,6 +76,8 @@ public: unsigned ResultReg; unsigned NumResultRegs; + bool IsPatchPoint; + SmallVector OutVals; SmallVector OutFlags; SmallVector OutRegs; @@ -87,7 +89,7 @@ public: IsInReg(false), DoesNotReturn(false), IsReturnValueUsed(true), IsTailCall(false), NumFixedArgs(-1), CallConv(CallingConv::C), Callee(nullptr), SymName(nullptr), CS(nullptr), Call(nullptr), - ResultReg(0), NumResultRegs(0) {} + ResultReg(0), NumResultRegs(0), IsPatchPoint(false) {} CallLoweringInfo &setCallee(Type *ResultTy, FunctionType *FuncTy, const Value *Target, ArgListTy &&ArgsList, @@ -162,6 +164,11 @@ public: return *this; } + CallLoweringInfo &setIsPatchPoint(bool Value = true) { + IsPatchPoint = Value; + return *this; + } + ArgListTy &getArgs() { return Args; } void clearOuts() { diff --git a/include/llvm/CodeGen/ForwardControlFlowIntegrity.h b/include/llvm/CodeGen/ForwardControlFlowIntegrity.h index a6232c5..ec8e2ef 100644 --- a/include/llvm/CodeGen/ForwardControlFlowIntegrity.h +++ b/include/llvm/CodeGen/ForwardControlFlowIntegrity.h @@ -18,7 +18,6 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/Pass.h" #include "llvm/Target/TargetOptions.h" - #include namespace llvm { diff --git a/include/llvm/CodeGen/FunctionLoweringInfo.h b/include/llvm/CodeGen/FunctionLoweringInfo.h index 91f20d0..e12866e 100644 --- a/include/llvm/CodeGen/FunctionLoweringInfo.h +++ b/include/llvm/CodeGen/FunctionLoweringInfo.h @@ -20,8 +20,8 @@ #include "llvm/ADT/IndexedMap.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/ISDOpcodes.h" +#include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/IR/InlineAsm.h" #include "llvm/IR/Instructions.h" #include "llvm/Target/TargetRegisterInfo.h" @@ -88,6 +88,12 @@ public: /// RegFixups - Registers which need to be replaced after isel is done. DenseMap RegFixups; + /// StatepointStackSlots - A list of temporary stack slots (frame indices) + /// used to spill values at a statepoint. We store them here to enable + /// reuse of the same stack slots across different statepoints in different + /// basic blocks. + SmallVector StatepointStackSlots; + /// MBB - The current block. MachineBasicBlock *MBB; @@ -200,6 +206,9 @@ public: return; unsigned Reg = It->second; + if (Reg == 0) + return; + LiveOutRegInfo.grow(Reg); LiveOutRegInfo[Reg].IsValid = false; } @@ -223,11 +232,6 @@ private: /// floating-point support. void ComputeUsesVAFloatArgument(const CallInst &I, MachineModuleInfo *MMI); -/// AddCatchInfo - Extract the personality and type infos from an eh.selector -/// call, and add them to the specified machine basic block. -void AddCatchInfo(const CallInst &I, - MachineModuleInfo *MMI, MachineBasicBlock *MBB); - /// AddLandingPadInfo - Extract the exception handling information from the /// landingpad instruction and add them to the specified machine module info. void AddLandingPadInfo(const LandingPadInst &I, MachineModuleInfo &MMI, diff --git a/include/llvm/CodeGen/GCMetadata.h b/include/llvm/CodeGen/GCMetadata.h index ddcc823..357b2d8 100644 --- a/include/llvm/CodeGen/GCMetadata.h +++ b/include/llvm/CodeGen/GCMetadata.h @@ -34,168 +34,173 @@ #define LLVM_CODEGEN_GCMETADATA_H #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" +#include "llvm/CodeGen/GCStrategy.h" #include "llvm/IR/DebugLoc.h" #include "llvm/Pass.h" - #include namespace llvm { - class AsmPrinter; - class GCStrategy; - class Constant; - class MCSymbol; - - namespace GC { - /// PointKind - The type of a collector-safe point. - /// - enum PointKind { - Loop, ///< Instr is a loop (backwards branch). - Return, ///< Instr is a return instruction. - PreCall, ///< Instr is a call instruction. - PostCall ///< Instr is the return address of a call. - }; - } - - /// GCPoint - Metadata for a collector-safe point in machine code. +class AsmPrinter; +class Constant; +class MCSymbol; + +/// GCPoint - Metadata for a collector-safe point in machine code. +/// +struct GCPoint { + GC::PointKind Kind; ///< The kind of the safe point. + MCSymbol *Label; ///< A label. + DebugLoc Loc; + + GCPoint(GC::PointKind K, MCSymbol *L, DebugLoc DL) + : Kind(K), Label(L), Loc(DL) {} +}; + +/// GCRoot - Metadata for a pointer to an object managed by the garbage +/// collector. +struct GCRoot { + int Num; ///< Usually a frame index. + int StackOffset; ///< Offset from the stack pointer. + const Constant *Metadata; ///< Metadata straight from the call + ///< to llvm.gcroot. + + GCRoot(int N, const Constant *MD) : Num(N), StackOffset(-1), Metadata(MD) {} +}; + +/// Garbage collection metadata for a single function. Currently, this +/// information only applies to GCStrategies which use GCRoot. +class GCFunctionInfo { +public: + typedef std::vector::iterator iterator; + typedef std::vector::iterator roots_iterator; + typedef std::vector::const_iterator live_iterator; + +private: + const Function &F; + GCStrategy &S; + uint64_t FrameSize; + std::vector Roots; + std::vector SafePoints; + + // FIXME: Liveness. A 2D BitVector, perhaps? + // + // BitVector Liveness; + // + // bool islive(int point, int root) = + // Liveness[point * SafePoints.size() + root] + // + // The bit vector is the more compact representation where >3.2% of roots + // are live per safe point (1.5% on 64-bit hosts). + +public: + GCFunctionInfo(const Function &F, GCStrategy &S); + ~GCFunctionInfo(); + + /// getFunction - Return the function to which this metadata applies. /// - struct GCPoint { - GC::PointKind Kind; ///< The kind of the safe point. - MCSymbol *Label; ///< A label. - DebugLoc Loc; - - GCPoint(GC::PointKind K, MCSymbol *L, DebugLoc DL) - : Kind(K), Label(L), Loc(DL) {} - }; - - /// GCRoot - Metadata for a pointer to an object managed by the garbage - /// collector. - struct GCRoot { - int Num; ///< Usually a frame index. - int StackOffset; ///< Offset from the stack pointer. - const Constant *Metadata; ///< Metadata straight from the call - ///< to llvm.gcroot. + const Function &getFunction() const { return F; } - GCRoot(int N, const Constant *MD) : Num(N), StackOffset(-1), Metadata(MD) {} - }; - - - /// GCFunctionInfo - Garbage collection metadata for a single function. + /// getStrategy - Return the GC strategy for the function. /// - class GCFunctionInfo { - public: - typedef std::vector::iterator iterator; - typedef std::vector::iterator roots_iterator; - typedef std::vector::const_iterator live_iterator; - - private: - const Function &F; - GCStrategy &S; - uint64_t FrameSize; - std::vector Roots; - std::vector SafePoints; - - // FIXME: Liveness. A 2D BitVector, perhaps? - // - // BitVector Liveness; - // - // bool islive(int point, int root) = - // Liveness[point * SafePoints.size() + root] - // - // The bit vector is the more compact representation where >3.2% of roots - // are live per safe point (1.5% on 64-bit hosts). - - public: - GCFunctionInfo(const Function &F, GCStrategy &S); - ~GCFunctionInfo(); - - /// getFunction - Return the function to which this metadata applies. - /// - const Function &getFunction() const { return F; } - - /// getStrategy - Return the GC strategy for the function. - /// - GCStrategy &getStrategy() { return S; } - - /// addStackRoot - Registers a root that lives on the stack. Num is the - /// stack object ID for the alloca (if the code generator is - // using MachineFrameInfo). - void addStackRoot(int Num, const Constant *Metadata) { - Roots.push_back(GCRoot(Num, Metadata)); - } - - /// removeStackRoot - Removes a root. - roots_iterator removeStackRoot(roots_iterator position) { - return Roots.erase(position); - } - - /// addSafePoint - Notes the existence of a safe point. Num is the ID of the - /// label just prior to the safe point (if the code generator is using - /// MachineModuleInfo). - void addSafePoint(GC::PointKind Kind, MCSymbol *Label, DebugLoc DL) { - SafePoints.push_back(GCPoint(Kind, Label, DL)); - } - - /// getFrameSize/setFrameSize - Records the function's frame size. - /// - uint64_t getFrameSize() const { return FrameSize; } - void setFrameSize(uint64_t S) { FrameSize = S; } - - /// begin/end - Iterators for safe points. - /// - iterator begin() { return SafePoints.begin(); } - iterator end() { return SafePoints.end(); } - size_t size() const { return SafePoints.size(); } - - /// roots_begin/roots_end - Iterators for all roots in the function. - /// - roots_iterator roots_begin() { return Roots.begin(); } - roots_iterator roots_end () { return Roots.end(); } - size_t roots_size() const { return Roots.size(); } - - /// live_begin/live_end - Iterators for live roots at a given safe point. - /// - live_iterator live_begin(const iterator &p) { return roots_begin(); } - live_iterator live_end (const iterator &p) { return roots_end(); } - size_t live_size(const iterator &p) const { return roots_size(); } - }; - - - /// GCModuleInfo - Garbage collection metadata for a whole module. - /// - class GCModuleInfo : public ImmutablePass { - typedef StringMap strategy_map_type; - typedef std::vector> list_type; - typedef DenseMap finfo_map_type; - - strategy_map_type StrategyMap; - list_type StrategyList; - finfo_map_type FInfoMap; + GCStrategy &getStrategy() { return S; } - GCStrategy *getOrCreateStrategy(const Module *M, const std::string &Name); + /// addStackRoot - Registers a root that lives on the stack. Num is the + /// stack object ID for the alloca (if the code generator is + // using MachineFrameInfo). + void addStackRoot(int Num, const Constant *Metadata) { + Roots.push_back(GCRoot(Num, Metadata)); + } - public: - typedef list_type::const_iterator iterator; + /// removeStackRoot - Removes a root. + roots_iterator removeStackRoot(roots_iterator position) { + return Roots.erase(position); + } - static char ID; + /// addSafePoint - Notes the existence of a safe point. Num is the ID of the + /// label just prior to the safe point (if the code generator is using + /// MachineModuleInfo). + void addSafePoint(GC::PointKind Kind, MCSymbol *Label, DebugLoc DL) { + SafePoints.push_back(GCPoint(Kind, Label, DL)); + } - GCModuleInfo(); + /// getFrameSize/setFrameSize - Records the function's frame size. + /// + uint64_t getFrameSize() const { return FrameSize; } + void setFrameSize(uint64_t S) { FrameSize = S; } - /// clear - Resets the pass. Any pass, which uses GCModuleInfo, should - /// call it in doFinalization(). - /// - void clear(); + /// begin/end - Iterators for safe points. + /// + iterator begin() { return SafePoints.begin(); } + iterator end() { return SafePoints.end(); } + size_t size() const { return SafePoints.size(); } - /// begin/end - Iterators for used strategies. - /// - iterator begin() const { return StrategyList.begin(); } - iterator end() const { return StrategyList.end(); } + /// roots_begin/roots_end - Iterators for all roots in the function. + /// + roots_iterator roots_begin() { return Roots.begin(); } + roots_iterator roots_end() { return Roots.end(); } + size_t roots_size() const { return Roots.size(); } - /// get - Look up function metadata. - /// - GCFunctionInfo &getFunctionInfo(const Function &F); - }; + /// live_begin/live_end - Iterators for live roots at a given safe point. + /// + live_iterator live_begin(const iterator &p) { return roots_begin(); } + live_iterator live_end(const iterator &p) { return roots_end(); } + size_t live_size(const iterator &p) const { return roots_size(); } +}; + +/// An analysis pass which caches information about the entire Module. +/// Records both the function level information used by GCRoots and a +/// cache of the 'active' gc strategy objects for the current Module. +class GCModuleInfo : public ImmutablePass { + /// An owning list of all GCStrategies which have been created + SmallVector, 1> GCStrategyList; + /// A helper map to speedup lookups into the above list + StringMap GCStrategyMap; + +public: + /// Lookup the GCStrategy object associated with the given gc name. + /// Objects are owned internally; No caller should attempt to delete the + /// returned objects. + GCStrategy *getGCStrategy(const StringRef Name); + + /// List of per function info objects. In theory, Each of these + /// may be associated with a different GC. + typedef std::vector> FuncInfoVec; + + FuncInfoVec::iterator funcinfo_begin() { return Functions.begin(); } + FuncInfoVec::iterator funcinfo_end() { return Functions.end(); } + +private: + /// Owning list of all GCFunctionInfos associated with this Module + FuncInfoVec Functions; + + /// Non-owning map to bypass linear search when finding the GCFunctionInfo + /// associated with a particular Function. + typedef DenseMap finfo_map_type; + finfo_map_type FInfoMap; + +public: + typedef SmallVector,1>::const_iterator iterator; + + static char ID; + + GCModuleInfo(); + + /// clear - Resets the pass. Any pass, which uses GCModuleInfo, should + /// call it in doFinalization(). + /// + void clear(); + /// begin/end - Iterators for used strategies. + /// + iterator begin() const { return GCStrategyList.begin(); } + iterator end() const { return GCStrategyList.end(); } + + /// get - Look up function metadata. This is currently assumed + /// have the side effect of initializing the associated GCStrategy. That + /// will soon change. + GCFunctionInfo &getFunctionInfo(const Function &F); +}; } #endif diff --git a/include/llvm/CodeGen/GCMetadataPrinter.h b/include/llvm/CodeGen/GCMetadataPrinter.h index 4a6b5ac..2208470 100644 --- a/include/llvm/CodeGen/GCMetadataPrinter.h +++ b/include/llvm/CodeGen/GCMetadataPrinter.h @@ -26,49 +26,39 @@ namespace llvm { - class GCMetadataPrinter; - - /// GCMetadataPrinterRegistry - The GC assembly printer registry uses all the - /// defaults from Registry. - typedef Registry GCMetadataPrinterRegistry; - - /// GCMetadataPrinter - Emits GC metadata as assembly code. - /// - class GCMetadataPrinter { - public: - typedef GCStrategy::list_type list_type; - typedef GCStrategy::iterator iterator; - - private: - GCStrategy *S; - - friend class AsmPrinter; - - protected: - // May only be subclassed. - GCMetadataPrinter(); - - private: - GCMetadataPrinter(const GCMetadataPrinter &) LLVM_DELETED_FUNCTION; - GCMetadataPrinter & - operator=(const GCMetadataPrinter &) LLVM_DELETED_FUNCTION; - - public: - GCStrategy &getStrategy() { return *S; } - const Module &getModule() const { return S->getModule(); } - - /// begin/end - Iterate over the collected function metadata. - iterator begin() { return S->begin(); } - iterator end() { return S->end(); } - - /// beginAssembly/finishAssembly - Emit module metadata as assembly code. - virtual void beginAssembly(AsmPrinter &AP); - - virtual void finishAssembly(AsmPrinter &AP); - - virtual ~GCMetadataPrinter(); - }; - +class GCMetadataPrinter; + +/// GCMetadataPrinterRegistry - The GC assembly printer registry uses all the +/// defaults from Registry. +typedef Registry GCMetadataPrinterRegistry; + +/// GCMetadataPrinter - Emits GC metadata as assembly code. Instances are +/// created, managed, and owned by the AsmPrinter. +class GCMetadataPrinter { +private: + GCStrategy *S; + friend class AsmPrinter; + +protected: + // May only be subclassed. + GCMetadataPrinter(); + +private: + GCMetadataPrinter(const GCMetadataPrinter &) = delete; + GCMetadataPrinter &operator=(const GCMetadataPrinter &) = delete; + +public: + GCStrategy &getStrategy() { return *S; } + + /// Called before the assembly for the module is generated by + /// the AsmPrinter (but after target specific hooks.) + virtual void beginAssembly(Module &M, GCModuleInfo &Info, AsmPrinter &AP) {} + /// Called after the assembly for the module is generated by + /// the AsmPrinter (but before target specific hooks) + virtual void finishAssembly(Module &M, GCModuleInfo &Info, AsmPrinter &AP) {} + + virtual ~GCMetadataPrinter(); +}; } #endif diff --git a/include/llvm/CodeGen/GCStrategy.h b/include/llvm/CodeGen/GCStrategy.h index 81e1f85..869f888 100644 --- a/include/llvm/CodeGen/GCStrategy.h +++ b/include/llvm/CodeGen/GCStrategy.h @@ -12,10 +12,15 @@ // specified in a function's 'gc' attribute. Algorithms are enabled by setting // flags in a subclass's constructor, and some virtual methods can be // overridden. -// -// When requested, the GCStrategy will be populated with data about each -// function which uses it. Specifically: -// +// +// GCStrategy is relevant for implementations using either gc.root or +// gc.statepoint based lowering strategies, but is currently focused mostly on +// options for gc.root. This will change over time. +// +// When requested by a subclass of GCStrategy, the gc.root implementation will +// populate GCModuleInfo and GCFunctionInfo with that about each Function in +// the Module that opts in to garbage collection. Specifically: +// // - Safe points // Garbage collection is generally only possible at certain points in code. // GCStrategy can request that the collector insert such points: @@ -23,7 +28,7 @@ // - At and after any call to a subroutine // - Before returning from the current function // - Before backwards branches (loops) -// +// // - Roots // When a reference to a GC-allocated object exists on the stack, it must be // stored in an alloca registered with llvm.gcoot. @@ -31,123 +36,142 @@ // This information can used to emit the metadata tables which are required by // the target garbage collector runtime. // +// When used with gc.statepoint, information about safepoint and roots can be +// found in the binary StackMap section after code generation. Safepoint +// placement is currently the responsibility of the frontend, though late +// insertion support is planned. gc.statepoint does not currently support +// custom stack map formats; such can be generated by parsing the standard +// stack map section if desired. +// +// The read and write barrier support can be used with either implementation. +// //===----------------------------------------------------------------------===// -#ifndef LLVM_CODEGEN_GCSTRATEGY_H -#define LLVM_CODEGEN_GCSTRATEGY_H +#ifndef LLVM_IR_GCSTRATEGY_H +#define LLVM_IR_GCSTRATEGY_H -#include "llvm/CodeGen/GCMetadata.h" -#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/ADT/Optional.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/Value.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Registry.h" #include namespace llvm { - - class GCStrategy; - - /// The GC strategy registry uses all the defaults from Registry. - /// - typedef Registry GCRegistry; - - /// GCStrategy describes a garbage collector algorithm's code generation - /// requirements, and provides overridable hooks for those needs which cannot - /// be abstractly described. - class GCStrategy { - public: - typedef std::vector> list_type; - typedef list_type::iterator iterator; - - private: - friend class GCModuleInfo; - const Module *M; - std::string Name; - - list_type Functions; - - protected: - unsigned NeededSafePoints; ///< Bitmask of required safe points. - bool CustomReadBarriers; ///< Default is to insert loads. - bool CustomWriteBarriers; ///< Default is to insert stores. - bool CustomRoots; ///< Default is to pass through to backend. - bool CustomSafePoints; ///< Default is to use NeededSafePoints - ///< to find safe points. - bool InitRoots; ///< If set, roots are nulled during lowering. - bool UsesMetadata; ///< If set, backend must emit metadata tables. - - public: - GCStrategy(); - - virtual ~GCStrategy() {} - - - /// getName - The name of the GC strategy, for debugging. - /// - const std::string &getName() const { return Name; } - - /// getModule - The module within which the GC strategy is operating. - /// - const Module &getModule() const { return *M; } - - /// needsSafePoitns - True if safe points of any kind are required. By - // default, none are recorded. - bool needsSafePoints() const { - return CustomSafePoints || NeededSafePoints != 0; - } - - /// needsSafePoint(Kind) - True if the given kind of safe point is - // required. By default, none are recorded. - bool needsSafePoint(GC::PointKind Kind) const { - return (NeededSafePoints & 1 << Kind) != 0; - } - - /// customWriteBarrier - By default, write barriers are replaced with simple - /// store instructions. If true, then - /// performCustomLowering must instead lower them. - bool customWriteBarrier() const { return CustomWriteBarriers; } - - /// customReadBarrier - By default, read barriers are replaced with simple - /// load instructions. If true, then - /// performCustomLowering must instead lower them. - bool customReadBarrier() const { return CustomReadBarriers; } - - /// customRoots - By default, roots are left for the code generator so it - /// can generate a stack map. If true, then - // performCustomLowering must delete them. - bool customRoots() const { return CustomRoots; } - - /// customSafePoints - By default, the GC analysis will find safe - /// points according to NeededSafePoints. If true, - /// then findCustomSafePoints must create them. - bool customSafePoints() const { return CustomSafePoints; } - - /// initializeRoots - If set, gcroot intrinsics should initialize their - // allocas to null before the first use. This is - // necessary for most GCs and is enabled by default. - bool initializeRoots() const { return InitRoots; } - - /// usesMetadata - If set, appropriate metadata tables must be emitted by - /// the back-end (assembler, JIT, or otherwise). - bool usesMetadata() const { return UsesMetadata; } - - /// begin/end - Iterators for function metadata. - /// - iterator begin() { return Functions.begin(); } - iterator end() { return Functions.end(); } - - /// insertFunctionMetadata - Creates metadata for a function. - /// - GCFunctionInfo *insertFunctionInfo(const Function &F); - - /// initializeCustomLowering/performCustomLowering - If any of the actions - /// are set to custom, performCustomLowering must be overriden to transform - /// the corresponding actions to LLVM IR. initializeCustomLowering is - /// optional to override. These are the only GCStrategy methods through - /// which the LLVM IR can be modified. - virtual bool initializeCustomLowering(Module &F); - virtual bool performCustomLowering(Function &F); - virtual bool findCustomSafePoints(GCFunctionInfo& FI, MachineFunction& MF); - }; - +namespace GC { +/// PointKind - The type of a collector-safe point. +/// +enum PointKind { + Loop, ///< Instr is a loop (backwards branch). + Return, ///< Instr is a return instruction. + PreCall, ///< Instr is a call instruction. + PostCall ///< Instr is the return address of a call. +}; +} + +/// GCStrategy describes a garbage collector algorithm's code generation +/// requirements, and provides overridable hooks for those needs which cannot +/// be abstractly described. GCStrategy objects must be looked up through +/// the Function. The objects themselves are owned by the Context and must +/// be immutable. +class GCStrategy { +private: + std::string Name; + friend class GCModuleInfo; + +protected: + bool UseStatepoints; /// Uses gc.statepoints as opposed to gc.roots, + /// if set, none of the other options can be + /// anything but their default values. + + unsigned NeededSafePoints; ///< Bitmask of required safe points. + bool CustomReadBarriers; ///< Default is to insert loads. + bool CustomWriteBarriers; ///< Default is to insert stores. + bool CustomRoots; ///< Default is to pass through to backend. + bool InitRoots; ///< If set, roots are nulled during lowering. + bool UsesMetadata; ///< If set, backend must emit metadata tables. + +public: + GCStrategy(); + virtual ~GCStrategy() {} + + /// Return the name of the GC strategy. This is the value of the collector + /// name string specified on functions which use this strategy. + const std::string &getName() const { return Name; } + + /// By default, write barriers are replaced with simple store + /// instructions. If true, you must provide a custom pass to lower + /// calls to @llvm.gcwrite. + bool customWriteBarrier() const { return CustomWriteBarriers; } + + /// By default, read barriers are replaced with simple load + /// instructions. If true, you must provide a custom pass to lower + /// calls to @llvm.gcread. + bool customReadBarrier() const { return CustomReadBarriers; } + + /// Returns true if this strategy is expecting the use of gc.statepoints, + /// and false otherwise. + bool useStatepoints() const { return UseStatepoints; } + + /** @name Statepoint Specific Properties */ + ///@{ + + /// If the value specified can be reliably distinguished, returns true for + /// pointers to GC managed locations and false for pointers to non-GC + /// managed locations. Note a GCStrategy can always return 'None' (i.e. an + /// empty optional indicating it can't reliably distinguish. + virtual Optional isGCManagedPointer(const Value *V) const { + return None; + } + ///@} + + /** @name GCRoot Specific Properties + * These properties and overrides only apply to collector strategies using + * GCRoot. + */ + ///@{ + + /// True if safe points of any kind are required. By default, none are + /// recorded. + bool needsSafePoints() const { return NeededSafePoints != 0; } + + /// True if the given kind of safe point is required. By default, none are + /// recorded. + bool needsSafePoint(GC::PointKind Kind) const { + return (NeededSafePoints & 1 << Kind) != 0; + } + + /// By default, roots are left for the code generator so it can generate a + /// stack map. If true, you must provide a custom pass to lower + /// calls to @llvm.gcroot. + bool customRoots() const { return CustomRoots; } + + /// If set, gcroot intrinsics should initialize their allocas to null + /// before the first use. This is necessary for most GCs and is enabled by + /// default. + bool initializeRoots() const { return InitRoots; } + + /// If set, appropriate metadata tables must be emitted by the back-end + /// (assembler, JIT, or otherwise). For statepoint, this method is + /// currently unsupported. The stackmap information can be found in the + /// StackMap section as described in the documentation. + bool usesMetadata() const { return UsesMetadata; } + + ///@} +}; + +/// Subclasses of GCStrategy are made available for use during compilation by +/// adding them to the global GCRegistry. This can done either within the +/// LLVM source tree or via a loadable plugin. An example registeration +/// would be: +/// static GCRegistry::Add X("custom-name", +/// "my custom supper fancy gc strategy"); +/// +/// Note that to use a custom GCMetadataPrinter w/gc.roots, you must also +/// register your GCMetadataPrinter subclass with the +/// GCMetadataPrinterRegistery as well. +typedef Registry GCRegistry; } #endif diff --git a/include/llvm/CodeGen/GCs.h b/include/llvm/CodeGen/GCs.h index bb170c8..5bae41e 100644 --- a/include/llvm/CodeGen/GCs.h +++ b/include/llvm/CodeGen/GCs.h @@ -15,27 +15,29 @@ #define LLVM_CODEGEN_GCS_H namespace llvm { - class GCStrategy; - class GCMetadataPrinter; +class GCStrategy; +class GCMetadataPrinter; - /// FIXME: Collector instances are not useful on their own. These no longer - /// serve any purpose except to link in the plugins. +/// FIXME: Collector instances are not useful on their own. These no longer +/// serve any purpose except to link in the plugins. - /// Creates an ocaml-compatible garbage collector. - void linkOcamlGC(); +/// Creates an ocaml-compatible garbage collector. +void linkOcamlGC(); - /// Creates an ocaml-compatible metadata printer. - void linkOcamlGCPrinter(); +/// Creates an ocaml-compatible metadata printer. +void linkOcamlGCPrinter(); - /// Creates an erlang-compatible garbage collector. - void linkErlangGC(); +/// Creates an erlang-compatible garbage collector. +void linkErlangGC(); - /// Creates an erlang-compatible metadata printer. - void linkErlangGCPrinter(); +/// Creates an erlang-compatible metadata printer. +void linkErlangGCPrinter(); - /// Creates a shadow stack garbage collector. This collector requires no code - /// generator support. - void linkShadowStackGC(); +/// Creates a shadow stack garbage collector. This collector requires no code +/// generator support. +void linkShadowStackGC(); + +void linkStatepointExampleGC(); } #endif diff --git a/include/llvm/CodeGen/ISDOpcodes.h b/include/llvm/CodeGen/ISDOpcodes.h index bbf0ad3..8a31f7e 100644 --- a/include/llvm/CodeGen/ISDOpcodes.h +++ b/include/llvm/CodeGen/ISDOpcodes.h @@ -72,6 +72,11 @@ namespace ISD { /// the parent's frame or return address, and so on. FRAMEADDR, RETURNADDR, + /// FRAME_ALLOC_RECOVER - Represents the llvm.framerecover + /// intrinsic. Materializes the offset from the frame pointer of another + /// function to the result of llvm.frameallocate. + FRAME_ALLOC_RECOVER, + /// READ_REGISTER, WRITE_REGISTER - This node represents llvm.register on /// the DAG, which implements the named register global variables extension. READ_REGISTER, @@ -224,7 +229,14 @@ namespace ISD { SMULO, UMULO, /// Simple binary floating point operators. - FADD, FSUB, FMUL, FMA, FDIV, FREM, + FADD, FSUB, FMUL, FDIV, FREM, + + /// FMA - Perform a * b + c with no intermediate rounding step. + FMA, + + /// FMAD - Perform a * b + c, while getting the same result as the + /// separately rounded operations. + FMAD, /// FCOPYSIGN(X, Y) - Return the value of X with the sign of Y. NOTE: This /// DAG node does not require that X and Y have the same type, just that the @@ -675,6 +687,11 @@ namespace ISD { ATOMIC_LOAD_UMIN, ATOMIC_LOAD_UMAX, + // Masked load and store + MLOAD, MSTORE, + // Masked gather and scatter + MGATHER, MSCATTER, + /// This corresponds to the llvm.lifetime.* intrinsics. The first operand /// is the chain and the second operand is the alloca pointer. LIFETIME_START, LIFETIME_END, @@ -688,7 +705,7 @@ namespace ISD { /// which do not reference a specific memory location should be less than /// this value. Those that do must not be less than this value, and can /// be used with SelectionDAG::getMemIntrinsicNode. - static const int FIRST_TARGET_MEMORY_OPCODE = BUILTIN_OP_END+180; + static const int FIRST_TARGET_MEMORY_OPCODE = BUILTIN_OP_END+200; //===--------------------------------------------------------------------===// /// MemIndexedMode enum - This enum defines the load / store indexed @@ -745,7 +762,7 @@ namespace ISD { LAST_LOADEXT_TYPE }; - NodeType getExtForLoadExtType(LoadExtType); + NodeType getExtForLoadExtType(bool IsFP, LoadExtType); //===--------------------------------------------------------------------===// /// ISD::CondCode enum - These are ordered carefully to make the bitfields diff --git a/include/llvm/CodeGen/LexicalScopes.h b/include/llvm/CodeGen/LexicalScopes.h index 021fd98..b3a8405 100644 --- a/include/llvm/CodeGen/LexicalScopes.h +++ b/include/llvm/CodeGen/LexicalScopes.h @@ -19,14 +19,14 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/STLExtras.h" #include "llvm/IR/DebugLoc.h" #include "llvm/IR/Metadata.h" #include "llvm/IR/ValueHandle.h" -#include #include +#include namespace llvm { class MachineInstr; @@ -48,6 +48,8 @@ public: LexicalScope(LexicalScope *P, const MDNode *D, const MDNode *I, bool A) : Parent(P), Desc(D), InlinedAtLocation(I), AbstractScope(A), LastInsn(nullptr), FirstInsn(nullptr), DFSIn(0), DFSOut(0) { + assert((!D || D->isResolved()) && "Expected resolved node"); + assert((!I || I->isResolved()) && "Expected resolved node"); if (Parent) Parent->addChild(this); } @@ -116,8 +118,8 @@ public: private: LexicalScope *Parent; // Parent to this scope. - AssertingVH Desc; // Debug info descriptor. - AssertingVH InlinedAtLocation; // Location at which this + const MDNode *Desc; // Debug info descriptor. + const MDNode *InlinedAtLocation; // Location at which this // scope is inlined. bool AbstractScope; // Abstract Scope SmallVector Children; // Scopes defined in scope. @@ -178,9 +180,11 @@ public: return I != AbstractScopeMap.end() ? &I->second : nullptr; } - /// findInlinedScope - Find an inlined scope for the given DebugLoc or return - /// NULL. - LexicalScope *findInlinedScope(DebugLoc DL); + /// findInlinedScope - Find an inlined scope for the given scope/inlined-at. + LexicalScope *findInlinedScope(const MDNode *N, const MDNode *IA) { + auto I = InlinedLexicalScopeMap.find(std::make_pair(N, IA)); + return I != InlinedLexicalScopeMap.end() ? &I->second : nullptr; + } /// findLexicalScope - Find regular lexical scope or return null. LexicalScope *findLexicalScope(const MDNode *N) { diff --git a/include/llvm/CodeGen/LinkAllCodegenComponents.h b/include/llvm/CodeGen/LinkAllCodegenComponents.h index 372c294..e7ccbfa 100644 --- a/include/llvm/CodeGen/LinkAllCodegenComponents.h +++ b/include/llvm/CodeGen/LinkAllCodegenComponents.h @@ -39,6 +39,7 @@ namespace { llvm::linkOcamlGC(); llvm::linkErlangGC(); llvm::linkShadowStackGC(); + llvm::linkStatepointExampleGC(); (void) llvm::createBURRListDAGScheduler(nullptr, llvm::CodeGenOpt::Default); diff --git a/include/llvm/CodeGen/LiveInterval.h b/include/llvm/CodeGen/LiveInterval.h index 6629e60..21634cb 100644 --- a/include/llvm/CodeGen/LiveInterval.h +++ b/include/llvm/CodeGen/LiveInterval.h @@ -27,6 +27,7 @@ #include "llvm/Support/Allocator.h" #include #include +#include namespace llvm { class CoalescerPair; @@ -119,6 +120,12 @@ namespace llvm { return isDeadDef() ? nullptr : LateVal; } + /// Returns the value alive at the end of the instruction, if any. This can + /// be a live-through value, a live def or a dead def. + VNInfo *valueOutOrDead() const { + return LateVal; + } + /// Return the value defined by this instruction, if any. This includes /// dead defs, it is the value created by the instruction's def operands. VNInfo *valueDefined() const { @@ -188,6 +195,12 @@ namespace llvm { Segments segments; // the liveness segments VNInfoList valnos; // value#'s + // The segment set is used temporarily to accelerate initial computation + // of live ranges of physical registers in computeRegUnitRange. + // After that the set is flushed to the segment vector and deleted. + typedef std::set SegmentSet; + SegmentSet *segmentSet; + typedef Segments::iterator iterator; iterator begin() { return segments.begin(); } iterator end() { return segments.end(); } @@ -204,6 +217,31 @@ namespace llvm { const_vni_iterator vni_begin() const { return valnos.begin(); } const_vni_iterator vni_end() const { return valnos.end(); } + /// Constructs a new LiveRange object. + LiveRange(bool UseSegmentSet = false) : segmentSet(nullptr) { + if (UseSegmentSet) + segmentSet = new SegmentSet(); + } + + /// Constructs a new LiveRange object by copying segments and valnos from + /// another LiveRange. + LiveRange(const LiveRange &Other, BumpPtrAllocator &Allocator) + : segmentSet(nullptr) { + assert(Other.segmentSet == nullptr && + "Copying of LiveRanges with active SegmentSets is not supported"); + + // Duplicate valnos. + for (const VNInfo *VNI : Other.valnos) { + createValueCopy(VNI, Allocator); + } + // Now we can copy segments and remap their valnos. + for (const Segment &S : Other.segments) { + segments.push_back(Segment(S.start, S.end, valnos[S.valno->id])); + } + } + + ~LiveRange() { delete segmentSet; } + /// advanceTo - Advance the specified iterator to point to the Segment /// containing the specified position, or end() if the position is past the /// end of the range. If no Segment contains this position, but the @@ -217,6 +255,14 @@ namespace llvm { return I; } + const_iterator advanceTo(const_iterator I, SlotIndex Pos) const { + assert(I != end()); + if (Pos >= endIndex()) + return end(); + while (I->end <= Pos) ++I; + return I; + } + /// find - Return an iterator pointing to the first segment that ends after /// Pos, or end(). This is the same as advanceTo(begin(), Pos), but faster /// when searching large ranges. @@ -397,17 +443,21 @@ namespace llvm { /// scanning the Other range starting at I. bool overlapsFrom(const LiveRange &Other, const_iterator I) const; + /// Returns true if all segments of the @p Other live range are completely + /// covered by this live range. + /// Adjacent live ranges do not affect the covering:the liverange + /// [1,5](5,10] covers (3,7]. + bool covers(const LiveRange &Other) const; + /// Add the specified Segment to this range, merging segments as /// appropriate. This returns an iterator to the inserted segment (which /// may have grown since it was inserted). - iterator addSegment(Segment S) { - return addSegmentFrom(S, segments.begin()); - } + iterator addSegment(Segment S); - /// extendInBlock - If this range is live before Kill in the basic block - /// that starts at StartIdx, extend it to be live up to Kill, and return - /// the value. If there is no segment before Kill, return NULL. - VNInfo *extendInBlock(SlotIndex StartIdx, SlotIndex Kill); + /// If this range is live before @p Use in the basic block that starts at + /// @p StartIdx, extend it to be live up to @p Use, and return the value. If + /// there is no segment before @p Use, return nullptr. + VNInfo *extendInBlock(SlotIndex StartIdx, SlotIndex Use); /// join - Join two live ranges (this, and other) together. This applies /// mappings to the value numbers in the LHS/RHS ranges as specified. If @@ -435,6 +485,12 @@ namespace llvm { removeSegment(S.start, S.end, RemoveDeadValNo); } + /// Remove segment pointed to by iterator @p I from this range. This does + /// not remove dead value numbers. + iterator removeSegment(iterator I) { + return segments.erase(I); + } + /// Query Liveness at Idx. /// The sub-instruction slot of Idx doesn't matter, only the instruction /// it refers to is considered. @@ -484,9 +540,9 @@ namespace llvm { /// Returns true if the live range is zero length, i.e. no live segments /// span instructions. It doesn't pay to spill such a range. bool isZeroLength(SlotIndexes *Indexes) const { - for (const_iterator i = begin(), e = end(); i != e; ++i) - if (Indexes->getNextNonNullIndex(i->start).getBaseIndex() < - i->end.getBaseIndex()) + for (const Segment &S : segments) + if (Indexes->getNextNonNullIndex(S.start).getBaseIndex() < + S.end.getBaseIndex()) return false; return true; } @@ -497,6 +553,12 @@ namespace llvm { return thisIndex < otherIndex; } + /// Flush segment set into the regular segment vector. + /// The method is to be called after the live range + /// has been created, if use of the segment set was + /// activated in the constructor of the live range. + void flushSegmentSet(); + void print(raw_ostream &OS) const; void dump() const; @@ -509,11 +571,13 @@ namespace llvm { void verify() const; #endif - private: + protected: + /// Append a segment to the list of segments. + void append(const LiveRange::Segment S); - iterator addSegmentFrom(Segment S, iterator From); - void extendSegmentEndTo(iterator I, SlotIndex NewEnd); - iterator extendSegmentStartTo(iterator I, SlotIndex NewStr); + private: + friend class LiveRangeUpdater; + void addSegmentToSet(Segment S); void markValNoForDeletion(VNInfo *V); }; @@ -529,11 +593,124 @@ namespace llvm { public: typedef LiveRange super; + /// A live range for subregisters. The LaneMask specifies which parts of the + /// super register are covered by the interval. + /// (@sa TargetRegisterInfo::getSubRegIndexLaneMask()). + class SubRange : public LiveRange { + public: + SubRange *Next; + unsigned LaneMask; + + /// Constructs a new SubRange object. + SubRange(unsigned LaneMask) + : Next(nullptr), LaneMask(LaneMask) { + } + + /// Constructs a new SubRange object by copying liveness from @p Other. + SubRange(unsigned LaneMask, const LiveRange &Other, + BumpPtrAllocator &Allocator) + : LiveRange(Other, Allocator), Next(nullptr), LaneMask(LaneMask) { + } + }; + + private: + SubRange *SubRanges; ///< Single linked list of subregister live ranges. + + public: const unsigned reg; // the register or stack slot of this interval. float weight; // weight of this interval LiveInterval(unsigned Reg, float Weight) - : reg(Reg), weight(Weight) {} + : SubRanges(nullptr), reg(Reg), weight(Weight) {} + + ~LiveInterval() { + clearSubRanges(); + } + + template + class SingleLinkedListIterator { + T *P; + public: + SingleLinkedListIterator(T *P) : P(P) {} + SingleLinkedListIterator &operator++() { + P = P->Next; + return *this; + } + SingleLinkedListIterator &operator++(int) { + SingleLinkedListIterator res = *this; + ++*this; + return res; + } + bool operator!=(const SingleLinkedListIterator &Other) { + return P != Other.operator->(); + } + bool operator==(const SingleLinkedListIterator &Other) { + return P == Other.operator->(); + } + T &operator*() const { + return *P; + } + T *operator->() const { + return P; + } + }; + + typedef SingleLinkedListIterator subrange_iterator; + subrange_iterator subrange_begin() { + return subrange_iterator(SubRanges); + } + subrange_iterator subrange_end() { + return subrange_iterator(nullptr); + } + + typedef SingleLinkedListIterator const_subrange_iterator; + const_subrange_iterator subrange_begin() const { + return const_subrange_iterator(SubRanges); + } + const_subrange_iterator subrange_end() const { + return const_subrange_iterator(nullptr); + } + + iterator_range subranges() { + return make_range(subrange_begin(), subrange_end()); + } + + iterator_range subranges() const { + return make_range(subrange_begin(), subrange_end()); + } + + /// Creates a new empty subregister live range. The range is added at the + /// beginning of the subrange list; subrange iterators stay valid. + SubRange *createSubRange(BumpPtrAllocator &Allocator, unsigned LaneMask) { + SubRange *Range = new (Allocator) SubRange(LaneMask); + appendSubRange(Range); + return Range; + } + + /// Like createSubRange() but the new range is filled with a copy of the + /// liveness information in @p CopyFrom. + SubRange *createSubRangeFrom(BumpPtrAllocator &Allocator, unsigned LaneMask, + const LiveRange &CopyFrom) { + SubRange *Range = new (Allocator) SubRange(LaneMask, CopyFrom, Allocator); + appendSubRange(Range); + return Range; + } + + /// Returns true if subregister liveness information is available. + bool hasSubRanges() const { + return SubRanges != nullptr; + } + + /// Removes all subregister liveness information. + void clearSubRanges(); + + /// Removes all subranges without any segments (subranges without segments + /// are not considered valid and should only exist temporarily). + void removeEmptySubRanges(); + + /// Construct main live range by merging the SubRanges of @p LI. + void constructMainRangeFromSubranges(const SlotIndexes &Indexes, + VNInfo::Allocator &VNIAllocator); /// getSize - Returns the sum of sizes of all the LiveRange's. /// @@ -558,9 +735,26 @@ namespace llvm { void print(raw_ostream &OS) const; void dump() const; + /// \brief Walks the interval and assert if any invariants fail to hold. + /// + /// Note that this is a no-op when asserts are disabled. +#ifdef NDEBUG + void verify(const MachineRegisterInfo *MRI = nullptr) const {} +#else + void verify(const MachineRegisterInfo *MRI = nullptr) const; +#endif + private: - LiveInterval& operator=(const LiveInterval& rhs) LLVM_DELETED_FUNCTION; + LiveInterval& operator=(const LiveInterval& rhs) = delete; + + /// Appends @p Range to SubRanges list. + void appendSubRange(SubRange *Range) { + Range->Next = SubRanges; + SubRanges = Range; + } + /// Free memory held by SubRange. + void freeSubRange(SubRange *S); }; inline raw_ostream &operator<<(raw_ostream &OS, const LiveInterval &LI) { diff --git a/include/llvm/CodeGen/LiveIntervalAnalysis.h b/include/llvm/CodeGen/LiveIntervalAnalysis.h index f9bd317..dc52c0a 100644 --- a/include/llvm/CodeGen/LiveIntervalAnalysis.h +++ b/include/llvm/CodeGen/LiveIntervalAnalysis.h @@ -27,12 +27,15 @@ #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/SlotIndexes.h" #include "llvm/Support/Allocator.h" +#include "llvm/Support/CommandLine.h" #include "llvm/Target/TargetRegisterInfo.h" #include #include namespace llvm { +extern cl::opt UseSegmentSetForPhysRegs; + class AliasAnalysis; class BitVector; class BlockFrequency; @@ -154,16 +157,11 @@ namespace llvm { bool shrinkToUses(LiveInterval *li, SmallVectorImpl *dead = nullptr); - /// \brief Walk the values in the given interval and compute which ones - /// are dead. Dead values are not deleted, however: - /// - Dead PHIDef values are marked as unused. - /// - New dead machine instructions are added to the dead vector. - /// - CanSeparate is set to true if the interval may have been separated - /// into multiple connected components. - void computeDeadValues(LiveInterval *li, - LiveRange &LR, - bool *CanSeparate, - SmallVectorImpl *dead); + /// Specialized version of + /// shrinkToUses(LiveInterval *li, SmallVectorImpl *dead) + /// that works on a subregister live range and only looks at uses matching + /// the lane mask of the subregister range. + void shrinkToUses(LiveInterval::SubRange &SR, unsigned Reg); /// extendToIndices - Extend the live range of LI to reach all points in /// Indices. The points in the Indices array must be jointly dominated by @@ -175,14 +173,15 @@ namespace llvm { /// See also LiveRangeCalc::extend(). void extendToIndices(LiveRange &LR, ArrayRef Indices); - /// pruneValue - If an LI value is live at Kill, prune its live range by - /// removing any liveness reachable from Kill. Add live range end points to + + /// If @p LR has a live value at @p Kill, prune its live range by removing + /// any liveness reachable from Kill. Add live range end points to /// EndPoints such that extendToIndices(LI, EndPoints) will reconstruct the /// value's live range. /// /// Calling pruneValue() and extendToIndices() can be used to reconstruct /// SSA form after adding defs to a virtual register. - void pruneValue(LiveInterval *LI, SlotIndex Kill, + void pruneValue(LiveRange &LR, SlotIndex Kill, SmallVectorImpl *EndPoints); SlotIndexes *getSlotIndexes() const { @@ -381,7 +380,8 @@ namespace llvm { LiveRange *LR = RegUnitRanges[Unit]; if (!LR) { // Compute missing ranges on demand. - RegUnitRanges[Unit] = LR = new LiveRange(); + // Use segment set to speed-up initial computation of the live range. + RegUnitRanges[Unit] = LR = new LiveRange(UseSegmentSetForPhysRegs); computeRegUnitRange(*LR, Unit); } return *LR; @@ -397,6 +397,15 @@ namespace llvm { return RegUnitRanges[Unit]; } + /// Remove value numbers and related live segments starting at position + /// @p Pos that are part of any liverange of physical register @p Reg or one + /// of its subregisters. + void removePhysRegDefAt(unsigned Reg, SlotIndex Pos); + + /// Remove value number and related live segments of @p LI and its subranges + /// that start at position @p Pos. + void removeVRegDefAt(LiveInterval &LI, SlotIndex Pos); + private: /// Compute live intervals for all virtual registers. void computeVirtRegs(); @@ -404,6 +413,16 @@ namespace llvm { /// Compute RegMaskSlots and RegMaskBits. void computeRegMasks(); + /// Walk the values in @p LI and check for dead values: + /// - Dead PHIDef values are marked as unused. + /// - Dead operands are marked as such. + /// - Completely dead machine instructions are added to the @p dead vector + /// if it is not nullptr. + /// Returns true if any PHI value numbers have been removed which may + /// have separated the interval into multiple connected components. + bool computeDeadValues(LiveInterval &LI, + SmallVectorImpl *dead); + static LiveInterval* createInterval(unsigned Reg); void printInstrs(raw_ostream &O) const; @@ -413,6 +432,16 @@ namespace llvm { void computeRegUnitRange(LiveRange&, unsigned Unit); void computeVirtRegInterval(LiveInterval&); + + /// Helper function for repairIntervalsInRange(), walks backwards and + /// creates/modifies live segments in @p LR to match the operands found. + /// Only full operands or operands with subregisters matching @p LaneMask + /// are considered. + void repairOldRegInRange(MachineBasicBlock::iterator Begin, + MachineBasicBlock::iterator End, + const SlotIndex endIdx, LiveRange &LR, + unsigned Reg, unsigned LaneMask = ~0u); + class HMEditor; }; } // End llvm namespace diff --git a/include/llvm/CodeGen/LiveIntervalUnion.h b/include/llvm/CodeGen/LiveIntervalUnion.h index 2f40509..967f0cb 100644 --- a/include/llvm/CodeGen/LiveIntervalUnion.h +++ b/include/llvm/CodeGen/LiveIntervalUnion.h @@ -84,10 +84,16 @@ public: bool changedSince(unsigned tag) const { return tag != Tag; } // Add a live virtual register to this union and merge its segments. - void unify(LiveInterval &VirtReg); + void unify(LiveInterval &VirtReg, const LiveRange &Range); + void unify(LiveInterval &VirtReg) { + unify(VirtReg, VirtReg); + } // Remove a live virtual register's segments from this union. - void extract(LiveInterval &VirtReg); + void extract(LiveInterval &VirtReg, const LiveRange &Range); + void extract(LiveInterval &VirtReg) { + extract(VirtReg, VirtReg); + } // Remove all inserted virtual registers. void clear() { Segments.clear(); ++Tag; } @@ -173,8 +179,8 @@ public: } private: - Query(const Query&) LLVM_DELETED_FUNCTION; - void operator=(const Query&) LLVM_DELETED_FUNCTION; + Query(const Query&) = delete; + void operator=(const Query&) = delete; }; // Array of LiveIntervalUnions. diff --git a/include/llvm/CodeGen/LivePhysRegs.h b/include/llvm/CodeGen/LivePhysRegs.h index 91e4ddc..4aa53a9 100644 --- a/include/llvm/CodeGen/LivePhysRegs.h +++ b/include/llvm/CodeGen/LivePhysRegs.h @@ -44,8 +44,8 @@ class LivePhysRegs { const TargetRegisterInfo *TRI; SparseSet LiveRegs; - LivePhysRegs(const LivePhysRegs&) LLVM_DELETED_FUNCTION; - LivePhysRegs &operator=(const LivePhysRegs&) LLVM_DELETED_FUNCTION; + LivePhysRegs(const LivePhysRegs&) = delete; + LivePhysRegs &operator=(const LivePhysRegs&) = delete; public: /// \brief Constructs a new empty LivePhysRegs set. LivePhysRegs() : TRI(nullptr), LiveRegs() {} diff --git a/include/llvm/CodeGen/MachineDominanceFrontier.h b/include/llvm/CodeGen/MachineDominanceFrontier.h index e099e71..4131194 100644 --- a/include/llvm/CodeGen/MachineDominanceFrontier.h +++ b/include/llvm/CodeGen/MachineDominanceFrontier.h @@ -26,8 +26,8 @@ public: typedef DominanceFrontierBase::iterator iterator; typedef DominanceFrontierBase::const_iterator const_iterator; - void operator=(const MachineDominanceFrontier &) LLVM_DELETED_FUNCTION; - MachineDominanceFrontier(const MachineDominanceFrontier &) LLVM_DELETED_FUNCTION; + void operator=(const MachineDominanceFrontier &) = delete; + MachineDominanceFrontier(const MachineDominanceFrontier &) = delete; static char ID; diff --git a/include/llvm/CodeGen/MachineFrameInfo.h b/include/llvm/CodeGen/MachineFrameInfo.h index 1e7fee6..6677360 100644 --- a/include/llvm/CodeGen/MachineFrameInfo.h +++ b/include/llvm/CodeGen/MachineFrameInfo.h @@ -516,6 +516,10 @@ public: /// on the stack. Returns an index with a negative value. int CreateFixedSpillStackObject(uint64_t Size, int64_t SPOffset); + /// Allocates memory at a fixed, target-specific offset from the frame + /// pointer. Marks the function as having its frame address taken. + int CreateFrameAllocation(uint64_t Size); + /// isFixedObjectIndex - Returns true if the specified index corresponds to a /// fixed stack object. bool isFixedObjectIndex(int ObjectIdx) const { diff --git a/include/llvm/CodeGen/MachineFunction.h b/include/llvm/CodeGen/MachineFunction.h index 3271410..94610ca 100644 --- a/include/llvm/CodeGen/MachineFunction.h +++ b/include/llvm/CodeGen/MachineFunction.h @@ -72,6 +72,15 @@ private: /// MachineFunction is destroyed. struct MachineFunctionInfo { virtual ~MachineFunctionInfo(); + + /// \brief Factory function: default behavior is to call new using the + /// supplied allocator. + /// + /// This function can be overridden in a derive class. + template + static Ty *create(BumpPtrAllocator &Allocator, MachineFunction &MF) { + return new (Allocator.Allocate()) Ty(MF); + } }; class MachineFunction { @@ -136,8 +145,8 @@ class MachineFunction { /// True if the function includes any inline assembly. bool HasInlineAsm; - MachineFunction(const MachineFunction &) LLVM_DELETED_FUNCTION; - void operator=(const MachineFunction&) LLVM_DELETED_FUNCTION; + MachineFunction(const MachineFunction &) = delete; + void operator=(const MachineFunction&) = delete; public: MachineFunction(const Function *Fn, const TargetMachine &TM, unsigned FunctionNum, MachineModuleInfo &MMI); @@ -167,6 +176,13 @@ public: const TargetSubtargetInfo &getSubtarget() const { return *STI; } void setSubtarget(const TargetSubtargetInfo *ST) { STI = ST; } + /// getSubtarget - This method returns a pointer to the specified type of + /// TargetSubtargetInfo. In debug builds, it verifies that the object being + /// returned is of the correct type. + template const STC &getSubtarget() const { + return *static_cast(STI); + } + /// getRegInfo - Return information about the registers currently in use. /// MachineRegisterInfo &getRegInfo() { return *RegInfo; } @@ -239,7 +255,7 @@ public: template Ty *getInfo() { if (!MFInfo) - MFInfo = new (Allocator.Allocate()) Ty(*this); + MFInfo = Ty::template create(Allocator, *this); return static_cast(MFInfo); } diff --git a/include/llvm/CodeGen/MachineInstr.h b/include/llvm/CodeGen/MachineInstr.h index d20b45b..4ba4a97 100644 --- a/include/llvm/CodeGen/MachineInstr.h +++ b/include/llvm/CodeGen/MachineInstr.h @@ -93,10 +93,10 @@ private: DebugLoc debugLoc; // Source line information. - MachineInstr(const MachineInstr&) LLVM_DELETED_FUNCTION; - void operator=(const MachineInstr&) LLVM_DELETED_FUNCTION; + MachineInstr(const MachineInstr&) = delete; + void operator=(const MachineInstr&) = delete; // Use MachineFunction::DeleteMachineInstr() instead. - ~MachineInstr() LLVM_DELETED_FUNCTION; + ~MachineInstr() = delete; // Intrusive list support friend struct ilist_traits; @@ -110,8 +110,8 @@ private: /// MachineInstr ctor - This constructor create a MachineInstr and add the /// implicit operands. It reserves space for number of operands specified by /// MCInstrDesc. An explicit DebugLoc is supplied. - MachineInstr(MachineFunction&, const MCInstrDesc &MCID, - const DebugLoc dl, bool NoImp = false); + MachineInstr(MachineFunction &, const MCInstrDesc &MCID, DebugLoc dl, + bool NoImp = false); // MachineInstrs are pool-allocated and owned by MachineFunction. friend class MachineFunction; @@ -242,7 +242,7 @@ public: /// getDebugLoc - Returns the debug location id of this MachineInstr. /// - DebugLoc getDebugLoc() const { return debugLoc; } + const DebugLoc &getDebugLoc() const { return debugLoc; } /// \brief Return the debug variable referenced by /// this DBG_VALUE instruction. @@ -1048,6 +1048,14 @@ public: bool addRegisterDead(unsigned Reg, const TargetRegisterInfo *RegInfo, bool AddIfNotFound = false); + /// Clear all dead flags on operands defining register @p Reg. + void clearRegisterDeads(unsigned Reg); + + /// Mark all subregister defs of register @p Reg with the undef flag. + /// This function is used when we determined to have a subregister def in an + /// otherwise undefined super register. + void addRegisterDefReadUndef(unsigned Reg); + /// addRegisterDefined - We have determined MI defines a register. Make sure /// there is an operand defining Reg. void addRegisterDefined(unsigned Reg, @@ -1139,7 +1147,10 @@ public: /// setDebugLoc - Replace current source information with new such. /// Avoid using this, the constructor argument is preferable. /// - void setDebugLoc(const DebugLoc dl) { debugLoc = dl; } + void setDebugLoc(DebugLoc dl) { + debugLoc = std::move(dl); + assert(debugLoc.hasTrivialDestructor() && "Expected trivial destructor"); + } /// RemoveOperand - Erase an operand from an instruction, leaving it with one /// fewer operand than it started with. diff --git a/include/llvm/CodeGen/MachineLoopInfo.h b/include/llvm/CodeGen/MachineLoopInfo.h index 4fbd46b..f7bcf45 100644 --- a/include/llvm/CodeGen/MachineLoopInfo.h +++ b/include/llvm/CodeGen/MachineLoopInfo.h @@ -74,8 +74,8 @@ class MachineLoopInfo : public MachineFunctionPass { LoopInfoBase LI; friend class LoopBase; - void operator=(const MachineLoopInfo &) LLVM_DELETED_FUNCTION; - MachineLoopInfo(const MachineLoopInfo &) LLVM_DELETED_FUNCTION; + void operator=(const MachineLoopInfo &) = delete; + MachineLoopInfo(const MachineLoopInfo &) = delete; public: static char ID; // Pass identification, replacement for typeid diff --git a/include/llvm/CodeGen/MachineModuleInfo.h b/include/llvm/CodeGen/MachineModuleInfo.h index 6653333..f171df2 100644 --- a/include/llvm/CodeGen/MachineModuleInfo.h +++ b/include/llvm/CodeGen/MachineModuleInfo.h @@ -35,6 +35,7 @@ #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/Analysis/LibCallSemantics.h" #include "llvm/IR/DebugLoc.h" #include "llvm/IR/Metadata.h" #include "llvm/IR/ValueHandle.h" @@ -66,6 +67,7 @@ struct LandingPadInfo { MachineBasicBlock *LandingPadBlock; // Landing pad block. SmallVector BeginLabels; // Labels prior to invoke. SmallVector EndLabels; // Labels after invoke. + SmallVector ClauseLabels; // Labels for each clause. MCSymbol *LandingPadLabel; // Label at beginning of landing pad. const Function *Personality; // Personality function. std::vector TypeIds; // List of type ids (filters negative) @@ -161,14 +163,26 @@ class MachineModuleInfo : public ImmutablePass { /// to _fltused on Windows targets. bool UsesVAFloatArgument; + /// UsesMorestackAddr - True if the module calls the __morestack function + /// indirectly, as is required under the large code model on x86. This is used + /// to emit a definition of a symbol, __morestack_addr, containing the + /// address. See comments in lib/Target/X86/X86FrameLowering.cpp for more + /// details. + bool UsesMorestackAddr; + + EHPersonality PersonalityTypeCache; + public: static char ID; // Pass identification, replacement for typeid struct VariableDbgInfo { - TrackingVH Var; - TrackingVH Expr; + TrackingMDNodeRef Var; + TrackingMDNodeRef Expr; unsigned Slot; DebugLoc Loc; + + VariableDbgInfo(MDNode *Var, MDNode *Expr, unsigned Slot, DebugLoc Loc) + : Var(Var), Expr(Expr), Slot(Slot), Loc(Loc) {} }; typedef SmallVector VariableDbgInfoMapTy; VariableDbgInfoMapTy VariableDbgInfos; @@ -231,6 +245,14 @@ public: UsesVAFloatArgument = b; } + bool usesMorestackAddr() const { + return UsesMorestackAddr; + } + + void setUsesMorestackAddr(bool b) { + UsesMorestackAddr = b; + } + /// \brief Returns a reference to a list of cfi instructions in the current /// function's prologue. Used to construct frame maps for debug and exception /// handling comsumers. @@ -312,6 +334,11 @@ public: /// void addCleanup(MachineBasicBlock *LandingPad); + /// Add a clause for a landing pad. Returns a new label for the clause. This + /// is used by EH schemes that have more than one landing pad. In this case, + /// each clause gets its own basic block. + MCSymbol *addClauseForLandingPad(MachineBasicBlock *LandingPad); + /// getTypeIDFor - Return the type id for the specified typeinfo. This is /// function wide. unsigned getTypeIDFor(const GlobalValue *TI); @@ -389,12 +416,14 @@ public: /// of one is required to emit exception handling info. const Function *getPersonality() const; + /// Classify the personality function amongst known EH styles. + EHPersonality getPersonalityType(); + /// setVariableDbgInfo - Collect information used to emit debugging /// information of a variable. void setVariableDbgInfo(MDNode *Var, MDNode *Expr, unsigned Slot, DebugLoc Loc) { - VariableDbgInfo Info = {Var, Expr, Slot, Loc}; - VariableDbgInfos.push_back(std::move(Info)); + VariableDbgInfos.emplace_back(Var, Expr, Slot, Loc); } VariableDbgInfoMapTy &getVariableDbgInfo() { return VariableDbgInfos; } diff --git a/include/llvm/CodeGen/MachinePassRegistry.h b/include/llvm/CodeGen/MachinePassRegistry.h index c962e68..57d1a6d 100644 --- a/include/llvm/CodeGen/MachinePassRegistry.h +++ b/include/llvm/CodeGen/MachinePassRegistry.h @@ -122,11 +122,12 @@ template class RegisterPassParser : public MachinePassRegistryListener, public cl::parser { public: - RegisterPassParser() {} + RegisterPassParser(cl::Option &O) + : cl::parser(O) {} ~RegisterPassParser() { RegistryClass::setListener(nullptr); } - void initialize(cl::Option &O) { - cl::parser::initialize(O); + void initialize() { + cl::parser::initialize(); // Add existing passes to option. for (RegistryClass *Node = RegistryClass::getList(); diff --git a/include/llvm/CodeGen/MachineRegisterInfo.h b/include/llvm/CodeGen/MachineRegisterInfo.h index 2e7f034..abb04de 100644 --- a/include/llvm/CodeGen/MachineRegisterInfo.h +++ b/include/llvm/CodeGen/MachineRegisterInfo.h @@ -52,6 +52,9 @@ private: /// accurate when after this flag is cleared. bool TracksLiveness; + /// True if subregister liveness is tracked. + bool TracksSubRegLiveness; + /// VRegInfo - Information we keep for each virtual register. /// /// Each element in this list contains the register class of the vreg and the @@ -120,8 +123,8 @@ private: /// second element. std::vector > LiveIns; - MachineRegisterInfo(const MachineRegisterInfo&) LLVM_DELETED_FUNCTION; - void operator=(const MachineRegisterInfo&) LLVM_DELETED_FUNCTION; + MachineRegisterInfo(const MachineRegisterInfo&) = delete; + void operator=(const MachineRegisterInfo&) = delete; public: explicit MachineRegisterInfo(const MachineFunction *MF); @@ -179,6 +182,12 @@ public: /// information. void invalidateLiveness() { TracksLiveness = false; } + bool tracksSubRegLiveness() const { return TracksSubRegLiveness; } + + void enableSubRegLiveness(bool Enable = true) { + TracksSubRegLiveness = Enable; + } + //===--------------------------------------------------------------------===// // Register Info //===--------------------------------------------------------------------===// @@ -584,7 +593,7 @@ public: /// virtual register, for example after removing instructions or splitting /// the live range. /// - bool recomputeRegClass(unsigned Reg, const TargetMachine&); + bool recomputeRegClass(unsigned Reg); /// createVirtualRegister - Create and return a new virtual register in the /// function with the specified register class. @@ -768,6 +777,10 @@ public: const TargetRegisterInfo &TRI, const TargetInstrInfo &TII); + /// Returns a mask covering all bits that can appear in lane masks of + /// subregisters of the virtual register @p Reg. + unsigned getMaxLaneMaskForVReg(unsigned Reg) const; + /// defusechain_iterator - This class provides iterator support for machine /// operands in the function that use or define a specific register. If /// ReturnUses is true it returns uses of registers, if ReturnDefs is true it diff --git a/include/llvm/CodeGen/MachineSSAUpdater.h b/include/llvm/CodeGen/MachineSSAUpdater.h index 486a26e..5f988ad 100644 --- a/include/llvm/CodeGen/MachineSSAUpdater.h +++ b/include/llvm/CodeGen/MachineSSAUpdater.h @@ -107,8 +107,8 @@ public: private: unsigned GetValueAtEndOfBlockInternal(MachineBasicBlock *BB); - void operator=(const MachineSSAUpdater&) LLVM_DELETED_FUNCTION; - MachineSSAUpdater(const MachineSSAUpdater&) LLVM_DELETED_FUNCTION; + void operator=(const MachineSSAUpdater&) = delete; + MachineSSAUpdater(const MachineSSAUpdater&) = delete; }; } // End llvm namespace diff --git a/include/llvm/CodeGen/MachineScheduler.h b/include/llvm/CodeGen/MachineScheduler.h index c5f66a8..a319401 100644 --- a/include/llvm/CodeGen/MachineScheduler.h +++ b/include/llvm/CodeGen/MachineScheduler.h @@ -80,7 +80,6 @@ #include "llvm/CodeGen/MachinePassRegistry.h" #include "llvm/CodeGen/RegisterPressure.h" #include "llvm/CodeGen/ScheduleDAGInstrs.h" - #include namespace llvm { diff --git a/include/llvm/CodeGen/MachineValueType.h b/include/llvm/CodeGen/MachineValueType.h index affacb0..7ad782f 100644 --- a/include/llvm/CodeGen/MachineValueType.h +++ b/include/llvm/CodeGen/MachineValueType.h @@ -15,6 +15,7 @@ #ifndef LLVM_CODEGEN_MACHINEVALUETYPE_H #define LLVM_CODEGEN_MACHINEVALUETYPE_H +#include "llvm/ADT/iterator_range.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" @@ -118,6 +119,7 @@ namespace llvm { // unspecified type. The register class // will be determined by the opcode. + FIRST_VALUETYPE = 0, // This is always the beginning of the list. LAST_VALUETYPE = 58, // This always remains at the end of the list. // This is the current maximum for LAST_VALUETYPE. @@ -150,7 +152,11 @@ namespace llvm { // iPTR - An int value the size of the pointer of the current // target. This should only be used internal to tblgen! - iPTR = 255 + iPTR = 255, + + // Any - Any type. This is used for intrinsics that have overloadings. + // This is only for tblgen's consumption! + Any = 256 }; SimpleValueType SimpleTy; @@ -165,6 +171,12 @@ namespace llvm { bool operator>=(const MVT& S) const { return SimpleTy >= S.SimpleTy; } bool operator<=(const MVT& S) const { return SimpleTy <= S.SimpleTy; } + /// isValid - Return true if this is a valid simple valuetype. + bool isValid() const { + return (SimpleTy >= MVT::FIRST_VALUETYPE && + SimpleTy < MVT::LAST_VALUETYPE); + } + /// isFloatingPoint - Return true if this is a FP, or a vector FP type. bool isFloatingPoint() const { return ((SimpleTy >= MVT::FIRST_FP_VALUETYPE && @@ -237,7 +249,8 @@ namespace llvm { /// isOverloaded - Return true if this is an overloaded type for TableGen. bool isOverloaded() const { - return (SimpleTy==MVT::iAny || SimpleTy==MVT::fAny || + return (SimpleTy==MVT::Any || + SimpleTy==MVT::iAny || SimpleTy==MVT::fAny || SimpleTy==MVT::vAny || SimpleTy==MVT::iPTRAny); } @@ -372,6 +385,7 @@ namespace llvm { case iAny: case fAny: case vAny: + case Any: llvm_unreachable("Value type is overloaded."); case Metadata: llvm_unreachable("Value type is metadata."); @@ -575,6 +589,52 @@ namespace llvm { /// returned as Other, otherwise they are invalid. static MVT getVT(Type *Ty, bool HandleUnknown = false); + private: + /// A simple iterator over the MVT::SimpleValueType enum. + struct mvt_iterator { + SimpleValueType VT; + mvt_iterator(SimpleValueType VT) : VT(VT) {} + MVT operator*() const { return VT; } + bool operator!=(const mvt_iterator &LHS) const { return VT != LHS.VT; } + mvt_iterator& operator++() { + VT = (MVT::SimpleValueType)((int)VT + 1); + assert((int)VT <= MVT::MAX_ALLOWED_VALUETYPE && + "MVT iterator overflowed."); + return *this; + } + }; + /// A range of the MVT::SimpleValueType enum. + typedef iterator_range mvt_range; + + public: + /// SimpleValueType Iteration + /// @{ + static mvt_range all_valuetypes() { + return mvt_range(MVT::FIRST_VALUETYPE, MVT::LAST_VALUETYPE); + } + static mvt_range integer_valuetypes() { + return mvt_range(MVT::FIRST_INTEGER_VALUETYPE, + (MVT::SimpleValueType)(MVT::LAST_INTEGER_VALUETYPE + 1)); + } + static mvt_range fp_valuetypes() { + return mvt_range(MVT::FIRST_FP_VALUETYPE, + (MVT::SimpleValueType)(MVT::LAST_FP_VALUETYPE + 1)); + } + static mvt_range vector_valuetypes() { + return mvt_range(MVT::FIRST_VECTOR_VALUETYPE, + (MVT::SimpleValueType)(MVT::LAST_VECTOR_VALUETYPE + 1)); + } + static mvt_range integer_vector_valuetypes() { + return mvt_range( + MVT::FIRST_INTEGER_VECTOR_VALUETYPE, + (MVT::SimpleValueType)(MVT::LAST_INTEGER_VECTOR_VALUETYPE + 1)); + } + static mvt_range fp_vector_valuetypes() { + return mvt_range( + MVT::FIRST_FP_VECTOR_VALUETYPE, + (MVT::SimpleValueType)(MVT::LAST_FP_VECTOR_VALUETYPE + 1)); + } + /// @} }; } // End llvm namespace diff --git a/include/llvm/CodeGen/PBQP/Graph.h b/include/llvm/CodeGen/PBQP/Graph.h index 4dc5674..efb723c 100644 --- a/include/llvm/CodeGen/PBQP/Graph.h +++ b/include/llvm/CodeGen/PBQP/Graph.h @@ -507,14 +507,14 @@ namespace PBQP { return getNode(NId).getAdjEdgeIds().size(); } - /// @brief Set an edge's cost matrix. + /// @brief Update an edge's cost matrix. /// @param EId Edge id. /// @param Costs New cost matrix. template - void setEdgeCosts(EdgeId EId, OtherMatrixT Costs) { + void updateEdgeCosts(EdgeId EId, OtherMatrixT Costs) { MatrixPtr AllocatedCosts = CostAlloc.getMatrix(std::move(Costs)); if (Solver) - Solver->handleSetEdgeCosts(EId, *AllocatedCosts); + Solver->handleUpdateCosts(EId, *AllocatedCosts); getEdge(EId).Costs = AllocatedCosts; } @@ -548,14 +548,14 @@ namespace PBQP { /// @brief Get the first node connected to this edge. /// @param EId Edge id. /// @return The first node connected to the given edge. - NodeId getEdgeNode1Id(EdgeId EId) { + NodeId getEdgeNode1Id(EdgeId EId) const { return getEdge(EId).getN1Id(); } /// @brief Get the second node connected to this edge. /// @param EId Edge id. /// @return The second node connected to the given edge. - NodeId getEdgeNode2Id(EdgeId EId) { + NodeId getEdgeNode2Id(EdgeId EId) const { return getEdge(EId).getN2Id(); } @@ -672,69 +672,6 @@ namespace PBQP { Edges.clear(); FreeEdgeIds.clear(); } - - /// @brief Dump a graph to an output stream. - template - void dumpToStream(OStream &OS) { - OS << nodeIds().size() << " " << edgeIds().size() << "\n"; - - for (auto NId : nodeIds()) { - const Vector& V = getNodeCosts(NId); - OS << "\n" << V.getLength() << "\n"; - assert(V.getLength() != 0 && "Empty vector in graph."); - OS << V[0]; - for (unsigned i = 1; i < V.getLength(); ++i) { - OS << " " << V[i]; - } - OS << "\n"; - } - - for (auto EId : edgeIds()) { - NodeId N1Id = getEdgeNode1Id(EId); - NodeId N2Id = getEdgeNode2Id(EId); - assert(N1Id != N2Id && "PBQP graphs shound not have self-edges."); - const Matrix& M = getEdgeCosts(EId); - OS << "\n" << N1Id << " " << N2Id << "\n" - << M.getRows() << " " << M.getCols() << "\n"; - assert(M.getRows() != 0 && "No rows in matrix."); - assert(M.getCols() != 0 && "No cols in matrix."); - for (unsigned i = 0; i < M.getRows(); ++i) { - OS << M[i][0]; - for (unsigned j = 1; j < M.getCols(); ++j) { - OS << " " << M[i][j]; - } - OS << "\n"; - } - } - } - - /// @brief Dump this graph to dbgs(). - void dump() { - dumpToStream(dbgs()); - } - - /// @brief Print a representation of this graph in DOT format. - /// @param OS Output stream to print on. - template - void printDot(OStream &OS) { - OS << "graph {\n"; - for (auto NId : nodeIds()) { - OS << " node" << NId << " [ label=\"" - << NId << ": " << getNodeCosts(NId) << "\" ]\n"; - } - OS << " edge [ len=" << nodeIds().size() << " ]\n"; - for (auto EId : edgeIds()) { - OS << " node" << getEdgeNode1Id(EId) - << " -- node" << getEdgeNode2Id(EId) - << " [ label=\""; - const Matrix &EdgeCosts = getEdgeCosts(EId); - for (unsigned i = 0; i < EdgeCosts.getRows(); ++i) { - OS << EdgeCosts.getRowAsVector(i) << "\\n"; - } - OS << "\" ]\n"; - } - OS << "}\n"; - } }; } // namespace PBQP diff --git a/include/llvm/CodeGen/PBQP/ReductionRules.h b/include/llvm/CodeGen/PBQP/ReductionRules.h index 21fde4d..d4a544b 100644 --- a/include/llvm/CodeGen/PBQP/ReductionRules.h +++ b/include/llvm/CodeGen/PBQP/ReductionRules.h @@ -132,9 +132,9 @@ namespace PBQP { } else { const Matrix &YZECosts = G.getEdgeCosts(YZEId); if (YNId == G.getEdgeNode1Id(YZEId)) { - G.setEdgeCosts(YZEId, Delta + YZECosts); + G.updateEdgeCosts(YZEId, Delta + YZECosts); } else { - G.setEdgeCosts(YZEId, Delta.transpose() + YZECosts); + G.updateEdgeCosts(YZEId, Delta.transpose() + YZECosts); } } @@ -144,6 +144,25 @@ namespace PBQP { // TODO: Try to normalize newly added/modified edge. } +#ifndef NDEBUG + // Does this Cost vector have any register options ? + template + bool hasRegisterOptions(const VectorT &V) { + unsigned VL = V.getLength(); + + // An empty or spill only cost vector does not provide any register option. + if (VL <= 1) + return false; + + // If there are registers in the cost vector, but all of them have infinite + // costs, then ... there is no available register. + for (unsigned i = 1; i < VL; ++i) + if (V[i] != std::numeric_limits::infinity()) + return true; + + return false; + } +#endif // \brief Find a solution to a fully reduced graph by backpropagation. // @@ -170,6 +189,15 @@ namespace PBQP { RawVector v = G.getNodeCosts(NId); +#ifndef NDEBUG + // Although a conservatively allocatable node can be allocated to a register, + // spilling it may provide a lower cost solution. Assert here that spilling + // is done by choice, not because there were no register available. + if (G.getNodeMetadata(NId).wasConservativelyAllocatable()) + assert(hasRegisterOptions(v) && "A conservatively allocatable node " + "must have available register options"); +#endif + for (auto EId : G.adjEdgeIds(NId)) { const Matrix& edgeCosts = G.getEdgeCosts(EId); if (NId == G.getEdgeNode1Id(EId)) { diff --git a/include/llvm/CodeGen/Passes.h b/include/llvm/CodeGen/Passes.h index b672d9d..65b17d3 100644 --- a/include/llvm/CodeGen/Passes.h +++ b/include/llvm/CodeGen/Passes.h @@ -105,6 +105,7 @@ private: AnalysisID StopAfter; bool Started; bool Stopped; + bool AddingMachinePasses; protected: TargetMachine *TM; @@ -213,7 +214,7 @@ public: /// /// This can also be used to plug a new MachineSchedStrategy into an instance /// of the standard ScheduleDAGMI: - /// return new ScheduleDAGMI(C, new MyStrategy(C)) + /// return new ScheduleDAGMI(C, make_unique(C), /* IsPostRA= */false) /// /// Return NULL to select the default (generic) machine scheduler. virtual ScheduleDAGInstrs * @@ -259,12 +260,9 @@ protected: return false; } - /// addPreRegAlloc - This method may be implemented by targets that want to - /// run passes immediately before register allocation. This should return - /// true if -print-machineinstrs should print after these passes. - virtual bool addPreRegAlloc() { - return false; - } + /// This method may be implemented by targets that want to run passes + /// immediately before register allocation. + virtual void addPreRegAlloc() { } /// createTargetRegisterAllocator - Create the register allocator pass for /// this target at the current optimization level. @@ -290,24 +288,16 @@ protected: return false; } - /// addPostRegAlloc - This method may be implemented by targets that want to - /// run passes after register allocation pass pipeline but before - /// prolog-epilog insertion. This should return true if -print-machineinstrs - /// should print after these passes. - virtual bool addPostRegAlloc() { - return false; - } + /// This method may be implemented by targets that want to run passes after + /// register allocation pass pipeline but before prolog-epilog insertion. + virtual void addPostRegAlloc() { } /// Add passes that optimize machine instructions after register allocation. virtual void addMachineLateOptimization(); - /// addPreSched2 - This method may be implemented by targets that want to - /// run passes after prolog-epilog insertion and before the second instruction - /// scheduling pass. This should return true if -print-machineinstrs should - /// print after these passes. - virtual bool addPreSched2() { - return false; - } + /// This method may be implemented by targets that want to run passes after + /// prolog-epilog insertion and before the second instruction scheduling pass. + virtual void addPreSched2() { } /// addGCPasses - Add late codegen passes that analyze code for garbage /// collection. This should return true if GC info should be printed after @@ -317,24 +307,30 @@ protected: /// Add standard basic block placement passes. virtual void addBlockPlacement(); - /// addPreEmitPass - This pass may be implemented by targets that want to run - /// passes immediately before machine code is emitted. This should return - /// true if -print-machineinstrs should print out the code after the passes. - virtual bool addPreEmitPass() { - return false; - } + /// This pass may be implemented by targets that want to run passes + /// immediately before machine code is emitted. + virtual void addPreEmitPass() { } /// Utilities for targets to add passes to the pass manager. /// /// Add a CodeGen pass at this point in the pipeline after checking overrides. /// Return the pass that was added, or zero if no pass was added. - AnalysisID addPass(AnalysisID PassID); + /// @p printAfter if true and adding a machine function pass add an extra + /// machine printer pass afterwards + /// @p verifyAfter if true and adding a machine function pass add an extra + /// machine verification pass afterwards. + AnalysisID addPass(AnalysisID PassID, bool verifyAfter = true, + bool printAfter = true); /// Add a pass to the PassManager if that pass is supposed to be run, as /// determined by the StartAfter and StopAfter options. Takes ownership of the /// pass. - void addPass(Pass *P); + /// @p printAfter if true and adding a machine function pass add an extra + /// machine printer pass afterwards + /// @p verifyAfter if true and adding a machine function pass add an extra + /// machine verification pass afterwards. + void addPass(Pass *P, bool verifyAfter = true, bool printAfter = true); /// addMachinePasses helper to create the target-selected or overriden /// regalloc pass. @@ -343,7 +339,14 @@ protected: /// printAndVerify - Add a pass to dump then verify the machine function, if /// those steps are enabled. /// - void printAndVerify(const char *Banner); + void printAndVerify(const std::string &Banner); + + /// Add a pass to print the machine function if printing is enabled. + void addPrintPass(const std::string &Banner); + + /// Add a pass to perform basic verification of the machine function if + /// verification is enabled. + void addVerifyPass(const std::string &Banner); }; } // namespace llvm @@ -351,13 +354,6 @@ protected: namespace llvm { FunctionPass *createAtomicExpandPass(const TargetMachine *TM); - /// \brief Create a basic TargetTransformInfo analysis pass. - /// - /// This pass implements the target transform info analysis using the target - /// independent information available to the LLVM code generator. - ImmutablePass * - createBasicTargetTransformInfoPass(const TargetMachine *TM); - /// createUnreachableBlockEliminationPass - The LLVM code generator does not /// work well with unreachable basic blocks (what live ranges make sense for a /// block that cannot be reached?). As such, a code generator should either @@ -514,11 +510,15 @@ namespace llvm { /// information. extern char &MachineBlockPlacementStatsID; - /// GCLowering Pass - Performs target-independent LLVM IR transformations for - /// highly portable strategies. - /// + /// GCLowering Pass - Used by gc.root to perform its default lowering + /// operations. FunctionPass *createGCLoweringPass(); + /// ShadowStackGCLowering - Implements the custom lowering mechanism + /// used by the shadow stack GC. Only runs on functions which opt in to + /// the shadow stack collector. + FunctionPass *createShadowStackGCLoweringPass(); + /// GCMachineCodeAnalysis - Target-independent pass to mark safe points /// in machine code. Must be added very late during code generation, just /// prior to output, and importantly after all CFG transformations (such as @@ -560,12 +560,16 @@ namespace llvm { /// createMachineVerifierPass - This pass verifies cenerated machine code /// instructions for correctness. /// - FunctionPass *createMachineVerifierPass(const char *Banner = nullptr); + FunctionPass *createMachineVerifierPass(const std::string& Banner); /// createDwarfEHPass - This pass mulches exception handling code into a form /// adapted to code generation. Required if using dwarf exception handling. FunctionPass *createDwarfEHPass(const TargetMachine *TM); + /// createWinEHPass - Prepares personality functions used by MSVC on Windows, + /// in addition to the Itanium LSDA based personalities. + FunctionPass *createWinEHPass(const TargetMachine *TM); + /// createSjLjEHPreparePass - This pass adapts exception handling code to use /// the GCC-style builtin setjmp/longjmp (sjlj) to handling EH control flow. /// diff --git a/include/llvm/CodeGen/RegAllocPBQP.h b/include/llvm/CodeGen/RegAllocPBQP.h index 540af08..c7bb07b 100644 --- a/include/llvm/CodeGen/RegAllocPBQP.h +++ b/include/llvm/CodeGen/RegAllocPBQP.h @@ -17,12 +17,15 @@ #define LLVM_CODEGEN_REGALLOCPBQP_H #include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/CodeGen/PBQPRAConstraint.h" #include "llvm/CodeGen/PBQP/CostAllocator.h" #include "llvm/CodeGen/PBQP/ReductionRules.h" +#include "llvm/CodeGen/PBQPRAConstraint.h" #include "llvm/Support/ErrorHandling.h" namespace llvm { + +class raw_ostream; + namespace PBQP { namespace RegAlloc { @@ -177,23 +180,38 @@ class NodeMetadata { public: typedef RegAlloc::AllowedRegVector AllowedRegVector; - typedef enum { Unprocessed, - OptimallyReducible, - ConservativelyAllocatable, - NotProvablyAllocatable } ReductionState; + // The node's reduction state. The order in this enum is important, + // as it is assumed nodes can only progress up (i.e. towards being + // optimally reducible) when reducing the graph. + typedef enum { + Unprocessed, + NotProvablyAllocatable, + ConservativelyAllocatable, + OptimallyReducible + } ReductionState; NodeMetadata() : RS(Unprocessed), NumOpts(0), DeniedOpts(0), OptUnsafeEdges(nullptr), - VReg(0) {} + VReg(0) +#ifndef NDEBUG + , everConservativelyAllocatable(false) +#endif + {} // FIXME: Re-implementing default behavior to work around MSVC. Remove once // MSVC synthesizes move constructors properly. NodeMetadata(const NodeMetadata &Other) : RS(Other.RS), NumOpts(Other.NumOpts), DeniedOpts(Other.DeniedOpts), OptUnsafeEdges(new unsigned[NumOpts]), VReg(Other.VReg), - AllowedRegs(Other.AllowedRegs) { - std::copy(&Other.OptUnsafeEdges[0], &Other.OptUnsafeEdges[NumOpts], - &OptUnsafeEdges[0]); + AllowedRegs(Other.AllowedRegs) +#ifndef NDEBUG + , everConservativelyAllocatable(Other.everConservativelyAllocatable) +#endif + { + if (NumOpts > 0) { + std::copy(&Other.OptUnsafeEdges[0], &Other.OptUnsafeEdges[NumOpts], + &OptUnsafeEdges[0]); + } } // FIXME: Re-implementing default behavior to work around MSVC. Remove once @@ -201,7 +219,11 @@ public: NodeMetadata(NodeMetadata &&Other) : RS(Other.RS), NumOpts(Other.NumOpts), DeniedOpts(Other.DeniedOpts), OptUnsafeEdges(std::move(Other.OptUnsafeEdges)), VReg(Other.VReg), - AllowedRegs(std::move(Other.AllowedRegs)) {} + AllowedRegs(std::move(Other.AllowedRegs)) +#ifndef NDEBUG + , everConservativelyAllocatable(Other.everConservativelyAllocatable) +#endif + {} // FIXME: Re-implementing default behavior to work around MSVC. Remove once // MSVC synthesizes move constructors properly. @@ -214,6 +236,9 @@ public: OptUnsafeEdges.get()); VReg = Other.VReg; AllowedRegs = Other.AllowedRegs; +#ifndef NDEBUG + everConservativelyAllocatable = Other.everConservativelyAllocatable; +#endif return *this; } @@ -226,6 +251,9 @@ public: OptUnsafeEdges = std::move(Other.OptUnsafeEdges); VReg = Other.VReg; AllowedRegs = std::move(Other.AllowedRegs); +#ifndef NDEBUG + everConservativelyAllocatable = Other.everConservativelyAllocatable; +#endif return *this; } @@ -243,10 +271,21 @@ public: } ReductionState getReductionState() const { return RS; } - void setReductionState(ReductionState RS) { this->RS = RS; } + void setReductionState(ReductionState RS) { + assert(RS >= this->RS && "A node's reduction state can not be downgraded"); + this->RS = RS; + +#ifndef NDEBUG + // Remember this state to assert later that a non-infinite register + // option was available. + if (RS == ConservativelyAllocatable) + everConservativelyAllocatable = true; +#endif + } + void handleAddEdge(const MatrixMetadata& MD, bool Transpose) { - DeniedOpts += Transpose ? MD.getWorstCol() : MD.getWorstRow(); + DeniedOpts += Transpose ? MD.getWorstRow() : MD.getWorstCol(); const bool* UnsafeOpts = Transpose ? MD.getUnsafeCols() : MD.getUnsafeRows(); for (unsigned i = 0; i < NumOpts; ++i) @@ -254,7 +293,7 @@ public: } void handleRemoveEdge(const MatrixMetadata& MD, bool Transpose) { - DeniedOpts -= Transpose ? MD.getWorstCol() : MD.getWorstRow(); + DeniedOpts -= Transpose ? MD.getWorstRow() : MD.getWorstCol(); const bool* UnsafeOpts = Transpose ? MD.getUnsafeCols() : MD.getUnsafeRows(); for (unsigned i = 0; i < NumOpts; ++i) @@ -267,6 +306,12 @@ public: &OptUnsafeEdges[NumOpts]); } +#ifndef NDEBUG + bool wasConservativelyAllocatable() const { + return everConservativelyAllocatable; + } +#endif + private: ReductionState RS; unsigned NumOpts; @@ -274,6 +319,10 @@ private: std::unique_ptr OptUnsafeEdges; unsigned VReg; GraphMetadata::AllowedRegVecRef AllowedRegs; + +#ifndef NDEBUG + bool everConservativelyAllocatable; +#endif }; class RegAllocSolverImpl { @@ -307,6 +356,8 @@ public: } void handleAddNode(NodeId NId) { + assert(G.getNodeCosts(NId).getLength() > 1 && + "PBQP Graph should not contain single or zero-option nodes"); G.getNodeMetadata(NId).setup(G.getNodeCosts(NId)); } void handleRemoveNode(NodeId NId) {} @@ -326,15 +377,7 @@ public: NodeMetadata& NMd = G.getNodeMetadata(NId); const MatrixMetadata& MMd = G.getEdgeCosts(EId).getMetadata(); NMd.handleRemoveEdge(MMd, NId == G.getEdgeNode2Id(EId)); - if (G.getNodeDegree(NId) == 3) { - // This node is becoming optimally reducible. - moveToOptimallyReducibleNodes(NId); - } else if (NMd.getReductionState() == - NodeMetadata::NotProvablyAllocatable && - NMd.isConservativelyAllocatable()) { - // This node just became conservatively allocatable. - moveToConservativelyAllocatableNodes(NId); - } + promote(NId, NMd); } void handleReconnectEdge(EdgeId EId, NodeId NId) { @@ -343,20 +386,44 @@ public: NMd.handleAddEdge(MMd, NId == G.getEdgeNode2Id(EId)); } - void handleSetEdgeCosts(EdgeId EId, const Matrix& NewCosts) { - handleRemoveEdge(EId); - + void handleUpdateCosts(EdgeId EId, const Matrix& NewCosts) { NodeId N1Id = G.getEdgeNode1Id(EId); NodeId N2Id = G.getEdgeNode2Id(EId); NodeMetadata& N1Md = G.getNodeMetadata(N1Id); NodeMetadata& N2Md = G.getNodeMetadata(N2Id); + bool Transpose = N1Id != G.getEdgeNode1Id(EId); + + // Metadata are computed incrementally. First, update them + // by removing the old cost. + const MatrixMetadata& OldMMd = G.getEdgeCosts(EId).getMetadata(); + N1Md.handleRemoveEdge(OldMMd, Transpose); + N2Md.handleRemoveEdge(OldMMd, !Transpose); + + // And update now the metadata with the new cost. const MatrixMetadata& MMd = NewCosts.getMetadata(); - N1Md.handleAddEdge(MMd, N1Id != G.getEdgeNode1Id(EId)); - N2Md.handleAddEdge(MMd, N2Id != G.getEdgeNode1Id(EId)); + N1Md.handleAddEdge(MMd, Transpose); + N2Md.handleAddEdge(MMd, !Transpose); + + // As the metadata may have changed with the update, the nodes may have + // become ConservativelyAllocatable or OptimallyReducible. + promote(N1Id, N1Md); + promote(N2Id, N2Md); } private: + void promote(NodeId NId, NodeMetadata& NMd) { + if (G.getNodeDegree(NId) == 3) { + // This node is becoming optimally reducible. + moveToOptimallyReducibleNodes(NId); + } else if (NMd.getReductionState() == + NodeMetadata::NotProvablyAllocatable && + NMd.isConservativelyAllocatable()) { + // This node just became conservatively allocatable. + moveToConservativelyAllocatableNodes(NId); + } + } + void removeFromCurrentSet(NodeId NId) { switch (G.getNodeMetadata(NId).getReductionState()) { case NodeMetadata::Unprocessed: break; @@ -497,6 +564,17 @@ private: typedef PBQP::Graph BaseT; public: PBQPRAGraph(GraphMetadata Metadata) : BaseT(Metadata) {} + + /// @brief Dump this graph to dbgs(). + void dump() const; + + /// @brief Dump this graph to an output stream. + /// @param OS Output stream to print on. + void dump(raw_ostream &OS) const; + + /// @brief Print a representation of this graph in DOT format. + /// @param OS Output stream to print on. + void printDot(raw_ostream &OS) const; }; inline Solution solve(PBQPRAGraph& G) { diff --git a/include/llvm/CodeGen/ScheduleDAG.h b/include/llvm/CodeGen/ScheduleDAG.h index 5a65d59..80aee8c 100644 --- a/include/llvm/CodeGen/ScheduleDAG.h +++ b/include/llvm/CodeGen/ScheduleDAG.h @@ -190,6 +190,12 @@ namespace llvm { return getKind() == Order && Contents.OrdKind == Barrier; } + /// isNormalMemoryOrBarrier - Test if this is could be any kind of memory + /// dependence. + bool isNormalMemoryOrBarrier() const { + return (isNormalMemory() || isBarrier()); + } + /// isMustAlias - Test if this is an Order dependence that is marked /// as "must alias", meaning that the SUnits at either end of the edge /// have a memory dependence on a known memory location. diff --git a/include/llvm/CodeGen/SelectionDAG.h b/include/llvm/CodeGen/SelectionDAG.h index fbdaf0d..dc1c80d 100644 --- a/include/llvm/CodeGen/SelectionDAG.h +++ b/include/llvm/CodeGen/SelectionDAG.h @@ -115,8 +115,8 @@ class SDDbgInfo { typedef DenseMap > DbgValMapType; DbgValMapType DbgValMap; - void operator=(const SDDbgInfo&) LLVM_DELETED_FUNCTION; - SDDbgInfo(const SDDbgInfo&) LLVM_DELETED_FUNCTION; + void operator=(const SDDbgInfo&) = delete; + SDDbgInfo(const SDDbgInfo&) = delete; public: SDDbgInfo() {} @@ -262,8 +262,8 @@ private: DenseSet &visited, int level, bool &printed); - void operator=(const SelectionDAG&) LLVM_DELETED_FUNCTION; - SelectionDAG(const SelectionDAG&) LLVM_DELETED_FUNCTION; + void operator=(const SelectionDAG&) = delete; + SelectionDAG(const SelectionDAG&) = delete; public: explicit SelectionDAG(const TargetMachine &TM, llvm::CodeGenOpt::Level); @@ -866,6 +866,12 @@ public: SDValue getIndexedStore(SDValue OrigStoe, SDLoc dl, SDValue Base, SDValue Offset, ISD::MemIndexedMode AM); + SDValue getMaskedLoad(EVT VT, SDLoc dl, SDValue Chain, SDValue Ptr, + SDValue Mask, SDValue Src0, EVT MemVT, + MachineMemOperand *MMO, ISD::LoadExtType); + SDValue getMaskedStore(SDValue Chain, SDLoc dl, SDValue Val, + SDValue Ptr, SDValue Mask, EVT MemVT, + MachineMemOperand *MMO, bool IsTrunc); /// getSrcValue - Construct a node to track a Value* through the backend. SDValue getSrcValue(const Value *v); diff --git a/include/llvm/CodeGen/SelectionDAGISel.h b/include/llvm/CodeGen/SelectionDAGISel.h index 2639402..d53e66d 100644 --- a/include/llvm/CodeGen/SelectionDAGISel.h +++ b/include/llvm/CodeGen/SelectionDAGISel.h @@ -18,8 +18,8 @@ #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/SelectionDAG.h" #include "llvm/IR/BasicBlock.h" -#include "llvm/Target/TargetSubtargetInfo.h" #include "llvm/Pass.h" +#include "llvm/Target/TargetSubtargetInfo.h" namespace llvm { class FastISel; diff --git a/include/llvm/CodeGen/SelectionDAGNodes.h b/include/llvm/CodeGen/SelectionDAGNodes.h index 4715827..0b6240f 100644 --- a/include/llvm/CodeGen/SelectionDAGNodes.h +++ b/include/llvm/CodeGen/SelectionDAGNodes.h @@ -19,7 +19,6 @@ #ifndef LLVM_CODEGEN_SELECTIONDAGNODES_H #define LLVM_CODEGEN_SELECTIONDAGNODES_H -#include "llvm/ADT/iterator_range.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/GraphTraits.h" @@ -27,6 +26,7 @@ #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/ilist_node.h" +#include "llvm/ADT/iterator_range.h" #include "llvm/CodeGen/ISDOpcodes.h" #include "llvm/CodeGen/MachineMemOperand.h" #include "llvm/CodeGen/ValueTypes.h" @@ -145,7 +145,7 @@ public: bool operator<(const SDValue &O) const { return std::tie(Node, ResNo) < std::tie(O.Node, O.ResNo); } - LLVM_EXPLICIT operator bool() const { + explicit operator bool() const { return Node != nullptr; } @@ -184,7 +184,7 @@ public: inline bool isTargetOpcode() const; inline bool isMachineOpcode() const; inline unsigned getMachineOpcode() const; - inline const DebugLoc getDebugLoc() const; + inline const DebugLoc &getDebugLoc() const; inline void dump() const; inline void dumpr() const; @@ -259,8 +259,8 @@ class SDUse { /// this operand. SDUse **Prev, *Next; - SDUse(const SDUse &U) LLVM_DELETED_FUNCTION; - void operator=(const SDUse &U) LLVM_DELETED_FUNCTION; + SDUse(const SDUse &U) = delete; + void operator=(const SDUse &U) = delete; public: SDUse() : Val(), User(nullptr), Prev(nullptr), Next(nullptr) {} @@ -476,11 +476,11 @@ public: void setIROrder(unsigned Order) { IROrder = Order; } /// getDebugLoc - Return the source location info. - const DebugLoc getDebugLoc() const { return debugLoc; } + const DebugLoc &getDebugLoc() const { return debugLoc; } /// setDebugLoc - Set source location info. Try to avoid this, putting /// it in the constructor is preferable. - void setDebugLoc(const DebugLoc dl) { debugLoc = dl; } + void setDebugLoc(DebugLoc dl) { debugLoc = std::move(dl); } /// use_iterator - This class provides iterator support for SDUse /// operands that use a specific SDNode. @@ -754,19 +754,20 @@ protected: return Ret; } - SDNode(unsigned Opc, unsigned Order, const DebugLoc dl, SDVTList VTs, + SDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTs, ArrayRef Ops) - : NodeType(Opc), OperandsNeedDelete(true), HasDebugValue(false), - SubclassData(0), NodeId(-1), - OperandList(Ops.size() ? new SDUse[Ops.size()] : nullptr), - ValueList(VTs.VTs), UseList(nullptr), - NumOperands(Ops.size()), NumValues(VTs.NumVTs), - debugLoc(dl), IROrder(Order) { + : NodeType(Opc), OperandsNeedDelete(true), HasDebugValue(false), + SubclassData(0), NodeId(-1), + OperandList(Ops.size() ? new SDUse[Ops.size()] : nullptr), + ValueList(VTs.VTs), UseList(nullptr), NumOperands(Ops.size()), + NumValues(VTs.NumVTs), debugLoc(std::move(dl)), IROrder(Order) { + assert(debugLoc.hasTrivialDestructor() && "Expected trivial destructor"); assert(NumOperands == Ops.size() && "NumOperands wasn't wide enough for its operands!"); assert(NumValues == VTs.NumVTs && "NumValues wasn't wide enough for its operands!"); for (unsigned i = 0; i != Ops.size(); ++i) { + assert(OperandList && "no operands available"); OperandList[i].setUser(this); OperandList[i].setInitial(Ops[i]); } @@ -775,11 +776,12 @@ protected: /// This constructor adds no operands itself; operands can be /// set later with InitOperands. - SDNode(unsigned Opc, unsigned Order, const DebugLoc dl, SDVTList VTs) - : NodeType(Opc), OperandsNeedDelete(false), HasDebugValue(false), - SubclassData(0), NodeId(-1), OperandList(nullptr), ValueList(VTs.VTs), - UseList(nullptr), NumOperands(0), NumValues(VTs.NumVTs), debugLoc(dl), - IROrder(Order) { + SDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTs) + : NodeType(Opc), OperandsNeedDelete(false), HasDebugValue(false), + SubclassData(0), NodeId(-1), OperandList(nullptr), ValueList(VTs.VTs), + UseList(nullptr), NumOperands(0), NumValues(VTs.NumVTs), + debugLoc(std::move(dl)), IROrder(Order) { + assert(debugLoc.hasTrivialDestructor() && "Expected trivial destructor"); assert(NumValues == VTs.NumVTs && "NumValues wasn't wide enough for its operands!"); } @@ -942,7 +944,7 @@ inline bool SDValue::use_empty() const { inline bool SDValue::hasOneUse() const { return Node->hasNUsesOfValue(1, ResNo); } -inline const DebugLoc SDValue::getDebugLoc() const { +inline const DebugLoc &SDValue::getDebugLoc() const { return Node->getDebugLoc(); } inline void SDValue::dump() const { @@ -1177,6 +1179,8 @@ public: N->getOpcode() == ISD::ATOMIC_LOAD_UMAX || N->getOpcode() == ISD::ATOMIC_LOAD || N->getOpcode() == ISD::ATOMIC_STORE || + N->getOpcode() == ISD::MLOAD || + N->getOpcode() == ISD::MSTORE || N->isMemIntrinsic() || N->isTargetMemoryOpcode(); } @@ -1413,6 +1417,12 @@ public: /// isNaN - Return true if the value is a NaN. bool isNaN() const { return Value->isNaN(); } + /// isInfinity - Return true if the value is an infinity + bool isInfinity() const { return Value->isInfinity(); } + + /// isNegative - Return true if the value is negative. + bool isNegative() const { return Value->isNegative(); } + /// isExactlyValue - We don't rely on operator== working on double values, as /// it returns true for things that are clearly not equal, like -0.0 and 0.0. /// As such, this method can be used to do an exact bit-for-bit comparison of @@ -1601,7 +1611,7 @@ public: /// BUILD_VECTORs. class BuildVectorSDNode : public SDNode { // These are constructed as SDNodes and then cast to BuildVectorSDNodes. - explicit BuildVectorSDNode() LLVM_DELETED_FUNCTION; + explicit BuildVectorSDNode() = delete; public: /// isConstantSplat - Check if this is a constant splat, and if so, find the /// smallest element size that splats the vector. If MinSplatBits is @@ -1926,6 +1936,81 @@ public: } }; +/// MaskedLoadStoreSDNode - This is a base class is used to represent MLOAD and +/// MSTORE nodes +/// +class MaskedLoadStoreSDNode : public MemSDNode { + // Operands + SDUse Ops[4]; +public: + friend class SelectionDAG; + MaskedLoadStoreSDNode(ISD::NodeType NodeTy, unsigned Order, DebugLoc dl, + SDValue *Operands, unsigned numOperands, + SDVTList VTs, EVT MemVT, MachineMemOperand *MMO) + : MemSDNode(NodeTy, Order, dl, VTs, MemVT, MMO) { + InitOperands(Ops, Operands, numOperands); + } + + // In the both nodes address is Op1, mask is Op2: + // MaskedLoadSDNode (Chain, ptr, mask, src0), src0 is a passthru value + // MaskedStoreSDNode (Chain, ptr, mask, data) + // Mask is a vector of i1 elements + const SDValue &getBasePtr() const { return getOperand(1); } + const SDValue &getMask() const { return getOperand(2); } + + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::MLOAD || + N->getOpcode() == ISD::MSTORE; + } +}; + +/// MaskedLoadSDNode - This class is used to represent an MLOAD node +/// +class MaskedLoadSDNode : public MaskedLoadStoreSDNode { +public: + friend class SelectionDAG; + MaskedLoadSDNode(unsigned Order, DebugLoc dl, SDValue *Operands, + unsigned numOperands, SDVTList VTs, ISD::LoadExtType ETy, + EVT MemVT, MachineMemOperand *MMO) + : MaskedLoadStoreSDNode(ISD::MLOAD, Order, dl, Operands, numOperands, + VTs, MemVT, MMO) { + SubclassData |= (unsigned short)ETy; + } + + ISD::LoadExtType getExtensionType() const { + return ISD::LoadExtType(SubclassData & 3); + } + const SDValue &getSrc0() const { return getOperand(3); } + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::MLOAD; + } +}; + +/// MaskedStoreSDNode - This class is used to represent an MSTORE node +/// +class MaskedStoreSDNode : public MaskedLoadStoreSDNode { + +public: + friend class SelectionDAG; + MaskedStoreSDNode(unsigned Order, DebugLoc dl, SDValue *Operands, + unsigned numOperands, SDVTList VTs, bool isTrunc, EVT MemVT, + MachineMemOperand *MMO) + : MaskedLoadStoreSDNode(ISD::MSTORE, Order, dl, Operands, numOperands, + VTs, MemVT, MMO) { + SubclassData |= (unsigned short)isTrunc; + } + /// isTruncatingStore - Return true if the op does a truncation before store. + /// For integers this is the same as doing a TRUNCATE and storing the result. + /// For floats, it is the same as doing an FP_ROUND and storing the result. + bool isTruncatingStore() const { return SubclassData & 1; } + + const SDValue &getValue() const { return getOperand(3); } + + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::MSTORE; + } +}; + /// MachineSDNode - An SDNode that represents everything that will be needed /// to construct a MachineInstr. These nodes are created during the /// instruction selection proper phase. diff --git a/include/llvm/CodeGen/SlotIndexes.h b/include/llvm/CodeGen/SlotIndexes.h index 00bb22b..9d6d6f5 100644 --- a/include/llvm/CodeGen/SlotIndexes.h +++ b/include/llvm/CodeGen/SlotIndexes.h @@ -162,7 +162,7 @@ namespace llvm { } /// Return true for a valid index. - LLVM_EXPLICIT operator bool() const { return isValid(); } + explicit operator bool() const { return isValid(); } /// Print this index to the given raw_ostream. void print(raw_ostream &os) const; diff --git a/include/llvm/CodeGen/StackMaps.h b/include/llvm/CodeGen/StackMaps.h index e343980..4e48afe 100644 --- a/include/llvm/CodeGen/StackMaps.h +++ b/include/llvm/CodeGen/StackMaps.h @@ -81,6 +81,52 @@ public: unsigned getNextScratchIdx(unsigned StartIdx = 0) const; }; +/// MI-level Statepoint operands +/// +/// Statepoint operands take the form: +/// , , [call arguments], +/// , , +/// , , [other args], +/// [gc values] +class StatepointOpers { +private: + enum { + NCallArgsPos = 0, + CallTargetPos = 1 + }; + +public: + explicit StatepointOpers(const MachineInstr *MI): + MI(MI) { } + + /// Get starting index of non call related arguments + /// (statepoint flags, vm state and gc state). + unsigned getVarIdx() const { + return MI->getOperand(NCallArgsPos).getImm() + 2; + } + + /// Returns the index of the operand containing the number of non-gc non-call + /// arguments. + unsigned getNumVMSArgsIdx() const { + return getVarIdx() + 3; + } + + /// Returns the number of non-gc non-call arguments attached to the + /// statepoint. Note that this is the number of arguments, not the number of + /// operands required to represent those arguments. + unsigned getNumVMSArgs() const { + return MI->getOperand(getNumVMSArgsIdx()).getImm(); + } + + /// Returns the target of the underlying call. + const MachineOperand &getCallTarget() const { + return MI->getOperand(CallTargetPos); + } + +private: + const MachineInstr *MI; +}; + class StackMaps { public: struct Location { @@ -132,6 +178,9 @@ public: /// \brief Generate a stackmap record for a patchpoint instruction. void recordPatchPoint(const MachineInstr &MI); + /// \brief Generate a stackmap record for a statepoint instruction. + void recordStatepoint(const MachineInstr &MI); + /// If there is any stack map data, create a stack map section and serialize /// the map info into it. This clears the stack map data structures /// afterwards. @@ -139,7 +188,6 @@ public: private: static const char *WSMP; - typedef SmallVector LocationVec; typedef SmallVector LiveOutVec; typedef MapVector ConstantPool; diff --git a/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h b/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h index 87f1401..348c634 100644 --- a/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h +++ b/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h @@ -36,6 +36,8 @@ class TargetLoweringObjectFileELF : public TargetLoweringObjectFile { bool UseInitArray; public: + TargetLoweringObjectFileELF() : UseInitArray(false) {} + virtual ~TargetLoweringObjectFileELF() {} void emitPersonalityValue(MCStreamer &Streamer, const TargetMachine &TM, @@ -54,6 +56,13 @@ public: SectionKind Kind, Mangler &Mang, const TargetMachine &TM) const override; + const MCSection * + getSectionForJumpTable(const Function &F, Mangler &Mang, + const TargetMachine &TM) const override; + + bool shouldPutJumpTableInFunctionSection(bool UsesLabelDifference, + const Function &F) const override; + /// Return an MCExpr to use for a reference to the specified type info global /// variable from exception handling information. const MCExpr * @@ -89,8 +98,6 @@ public: ArrayRef ModuleFlags, Mangler &Mang, const TargetMachine &TM) const override; - bool isSectionAtomizableBySymbols(const MCSection &Section) const override; - const MCSection * SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, Mangler &Mang, diff --git a/include/llvm/CodeGen/ValueTypes.td b/include/llvm/CodeGen/ValueTypes.td index b5fa0e8..756262f 100644 --- a/include/llvm/CodeGen/ValueTypes.td +++ b/include/llvm/CodeGen/ValueTypes.td @@ -98,3 +98,6 @@ def iAny : ValueType<0 , 254>; // Pseudo valuetype mapped to the current pointer size. def iPTR : ValueType<0 , 255>; + +// Pseudo valuetype to represent "any type of any size". +def Any : ValueType<0 , 256>; diff --git a/include/llvm/CodeGen/VirtRegMap.h b/include/llvm/CodeGen/VirtRegMap.h index eceb875..d7e9209 100644 --- a/include/llvm/CodeGen/VirtRegMap.h +++ b/include/llvm/CodeGen/VirtRegMap.h @@ -63,8 +63,8 @@ namespace llvm { /// createSpillSlot - Allocate a spill slot for RC from MFI. unsigned createSpillSlot(const TargetRegisterClass *RC); - VirtRegMap(const VirtRegMap&) LLVM_DELETED_FUNCTION; - void operator=(const VirtRegMap&) LLVM_DELETED_FUNCTION; + VirtRegMap(const VirtRegMap&) = delete; + void operator=(const VirtRegMap&) = delete; public: static char ID; diff --git a/include/llvm/Config/config.h.cmake b/include/llvm/Config/config.h.cmake index 37696eb..86ae8bb 100644 --- a/include/llvm/Config/config.h.cmake +++ b/include/llvm/Config/config.h.cmake @@ -6,9 +6,6 @@ /* Exported configuration */ #include "llvm/Config/llvm-config.h" -/* Patch version of the LLVM API */ -#cmakedefine LLVM_VERSION_PATCH ${LLVM_VERSION_PATCH} - /* Bug report URL. */ #define BUG_REPORT_URL "${BUG_REPORT_URL}" @@ -18,6 +15,9 @@ /* Define to enable crash overrides */ #cmakedefine ENABLE_CRASH_OVERRIDES +/* Define to disable C++ atexit */ +#cmakedefine DISABLE_LLVM_DYLIB_ATEXIT + /* Define if position independent code is enabled */ #cmakedefine ENABLE_PIC @@ -52,6 +52,9 @@ don't. */ #cmakedefine01 HAVE_DECL_STRERROR_S +/* Define to 1 if you have the DIA SDK installed, and to 0 if you don't. */ +#cmakedefine HAVE_DIA_SDK ${HAVE_DIA_SDK} + /* Define to 1 if you have the header file, and it defines `DIR'. */ #cmakedefine HAVE_DIRENT_H ${HAVE_DIRENT_H} @@ -219,6 +222,9 @@ /* Define to 1 if you have the `malloc_zone_statistics' function. */ #cmakedefine HAVE_MALLOC_ZONE_STATISTICS ${HAVE_MALLOC_ZONE_STATISTICS} +/* Define to 1 if you have the `mallctl` function. */ +#cmakedefine HAVE_MALLCTL ${HAVE_MALLCTL} + /* Define to 1 if you have the `mkdtemp' function. */ #cmakedefine HAVE_MKDTEMP ${HAVE_MKDTEMP} @@ -423,6 +429,9 @@ /* Have host's __chkstk */ #cmakedefine HAVE___CHKSTK ${HAVE___CHKSTK} +/* Have host's __chkstk_ms */ +#cmakedefine HAVE___CHKSTK_MS ${HAVE___CHKSTK_MS} + /* Have host's __cmpdi2 */ #cmakedefine HAVE___CMPDI2 ${HAVE___CMPDI2} @@ -459,6 +468,9 @@ /* Have host's ___chkstk */ #cmakedefine HAVE____CHKSTK ${HAVE____CHKSTK} +/* Have host's ___chkstk_ms */ +#cmakedefine HAVE____CHKSTK_MS ${HAVE____CHKSTK_MS} + /* Define if we link Polly to the tools */ #cmakedefine LINK_POLLY_INTO_TOOLS @@ -518,9 +530,6 @@ /* Type of 1st arg on ELM Callback */ #cmakedefine WIN32_ELMCB_PCSTR ${WIN32_ELMCB_PCSTR} -/* Define to empty if `const' does not conform to ANSI C. */ -#undef const - /* Define to `int' if does not define. */ #undef pid_t @@ -542,7 +551,4 @@ /* Define to 1 if you have the `_chsize_s' function. */ #cmakedefine HAVE__CHSIZE_S ${HAVE__CHSIZE_S} -/* Maximum path length */ -#cmakedefine MAXPATHLEN ${MAXPATHLEN} - #endif diff --git a/include/llvm/Config/config.h.in b/include/llvm/Config/config.h.in index 8fcf145..c317bb1 100644 --- a/include/llvm/Config/config.h.in +++ b/include/llvm/Config/config.h.in @@ -9,6 +9,9 @@ /* Define if we have libxml2 */ #undef CLANG_HAVE_LIBXML +/* Multilib suffix for libdir. */ +#undef CLANG_LIBDIR_SUFFIX + /* Relative directory for resource files */ #undef CLANG_RESOURCE_DIR @@ -64,6 +67,9 @@ don't. */ #undef HAVE_DECL_STRERROR_S +/* Define to 1 if you have the DIA SDK installed, and to 0 if you don't. */ +#undef HAVE_DIA_SDK + /* Define to 1 if you have the header file, and it defines `DIR'. */ #undef HAVE_DIRENT_H @@ -204,6 +210,9 @@ /* Define if mallinfo() is available on this platform. */ #undef HAVE_MALLINFO +/* Define if mallctl() is available on this plaform. */ +#undef HAVE_MALLCTL + /* Define to 1 if you have the header file. */ #undef HAVE_MALLOC_H @@ -417,6 +426,9 @@ /* Have host's __chkstk */ #undef HAVE___CHKSTK +/* Have host's __chkstk_ms */ +#undef HAVE___CHKSTK_MS + /* Have host's __cmpdi2 */ #undef HAVE___CMPDI2 @@ -453,6 +465,9 @@ /* Have host's ___chkstk */ #undef HAVE____CHKSTK +/* Have host's ___chkstk_ms */ +#undef HAVE____CHKSTK_MS + /* Linker version detected at compile time. */ #undef HOST_LINK_VERSION diff --git a/include/llvm/Config/llvm-config.h.cmake b/include/llvm/Config/llvm-config.h.cmake index 77201e6..d54003d 100644 --- a/include/llvm/Config/llvm-config.h.cmake +++ b/include/llvm/Config/llvm-config.h.cmake @@ -87,10 +87,13 @@ #cmakedefine LLVM_USE_OPROFILE 1 /* Major version of the LLVM API */ -#cmakedefine LLVM_VERSION_MAJOR ${LLVM_VERSION_MAJOR} +#define LLVM_VERSION_MAJOR ${LLVM_VERSION_MAJOR} /* Minor version of the LLVM API */ -#cmakedefine LLVM_VERSION_MINOR ${LLVM_VERSION_MINOR} +#define LLVM_VERSION_MINOR ${LLVM_VERSION_MINOR} + +/* Patch version of the LLVM API */ +#define LLVM_VERSION_PATCH ${LLVM_VERSION_PATCH} /* LLVM version string */ #define LLVM_VERSION_STRING "${PACKAGE_VERSION}" diff --git a/include/llvm/Config/llvm-config.h.in b/include/llvm/Config/llvm-config.h.in index 2d6add7..25a9295 100644 --- a/include/llvm/Config/llvm-config.h.in +++ b/include/llvm/Config/llvm-config.h.in @@ -92,6 +92,9 @@ /* Minor version of the LLVM API */ #undef LLVM_VERSION_MINOR +/* Patch version of the LLVM API */ +#undef LLVM_VERSION_PATCH + /* LLVM version string */ #undef LLVM_VERSION_STRING diff --git a/include/llvm/DebugInfo/DIContext.h b/include/llvm/DebugInfo/DIContext.h deleted file mode 100644 index 3aa098d..0000000 --- a/include/llvm/DebugInfo/DIContext.h +++ /dev/null @@ -1,151 +0,0 @@ -//===-- DIContext.h ---------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines DIContext, an abstract data structure that holds -// debug information data. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_DEBUGINFO_DICONTEXT_H -#define LLVM_DEBUGINFO_DICONTEXT_H - -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/Object/ObjectFile.h" -#include "llvm/Object/RelocVisitor.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/DataTypes.h" - -#include - -namespace llvm { - -class raw_ostream; - -/// DILineInfo - a format-neutral container for source line information. -struct DILineInfo { - std::string FileName; - std::string FunctionName; - uint32_t Line; - uint32_t Column; - - DILineInfo() - : FileName(""), FunctionName(""), Line(0), Column(0) {} - - bool operator==(const DILineInfo &RHS) const { - return Line == RHS.Line && Column == RHS.Column && - FileName == RHS.FileName && FunctionName == RHS.FunctionName; - } - bool operator!=(const DILineInfo &RHS) const { - return !(*this == RHS); - } -}; - -typedef SmallVector, 16> DILineInfoTable; - -/// DIInliningInfo - a format-neutral container for inlined code description. -class DIInliningInfo { - SmallVector Frames; - public: - DIInliningInfo() {} - DILineInfo getFrame(unsigned Index) const { - assert(Index < Frames.size()); - return Frames[Index]; - } - uint32_t getNumberOfFrames() const { - return Frames.size(); - } - void addFrame(const DILineInfo &Frame) { - Frames.push_back(Frame); - } -}; - -/// A DINameKind is passed to name search methods to specify a -/// preference regarding the type of name resolution the caller wants. -enum class DINameKind { None, ShortName, LinkageName }; - -/// DILineInfoSpecifier - controls which fields of DILineInfo container -/// should be filled with data. -struct DILineInfoSpecifier { - enum class FileLineInfoKind { None, Default, AbsoluteFilePath }; - typedef DINameKind FunctionNameKind; - - FileLineInfoKind FLIKind; - FunctionNameKind FNKind; - - DILineInfoSpecifier(FileLineInfoKind FLIKind = FileLineInfoKind::Default, - FunctionNameKind FNKind = FunctionNameKind::None) - : FLIKind(FLIKind), FNKind(FNKind) {} -}; - -/// Selects which debug sections get dumped. -enum DIDumpType { - DIDT_Null, - DIDT_All, - DIDT_Abbrev, - DIDT_AbbrevDwo, - DIDT_Aranges, - DIDT_Frames, - DIDT_Info, - DIDT_InfoDwo, - DIDT_Types, - DIDT_TypesDwo, - DIDT_Line, - DIDT_LineDwo, - DIDT_Loc, - DIDT_LocDwo, - DIDT_Ranges, - DIDT_Pubnames, - DIDT_Pubtypes, - DIDT_GnuPubnames, - DIDT_GnuPubtypes, - DIDT_Str, - DIDT_StrDwo, - DIDT_StrOffsetsDwo, - DIDT_AppleNames, - DIDT_AppleTypes, - DIDT_AppleNamespaces, - DIDT_AppleObjC -}; - -// In place of applying the relocations to the data we've read from disk we use -// a separate mapping table to the side and checking that at locations in the -// dwarf where we expect relocated values. This adds a bit of complexity to the -// dwarf parsing/extraction at the benefit of not allocating memory for the -// entire size of the debug info sections. -typedef DenseMap > RelocAddrMap; - -class DIContext { -public: - enum DIContextKind { - CK_DWARF - }; - DIContextKind getKind() const { return Kind; } - - DIContext(DIContextKind K) : Kind(K) {} - virtual ~DIContext(); - - /// getDWARFContext - get a context for binary DWARF data. - static DIContext *getDWARFContext(const object::ObjectFile &Obj); - - virtual void dump(raw_ostream &OS, DIDumpType DumpType = DIDT_All) = 0; - - virtual DILineInfo getLineInfoForAddress(uint64_t Address, - DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0; - virtual DILineInfoTable getLineInfoForAddressRange(uint64_t Address, - uint64_t Size, DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0; - virtual DIInliningInfo getInliningInfoForAddress(uint64_t Address, - DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0; -private: - const DIContextKind Kind; -}; - -} - -#endif diff --git a/include/llvm/DebugInfo/DWARF/DIContext.h b/include/llvm/DebugInfo/DWARF/DIContext.h new file mode 100644 index 0000000..622aa69 --- /dev/null +++ b/include/llvm/DebugInfo/DWARF/DIContext.h @@ -0,0 +1,150 @@ +//===-- DIContext.h ---------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines DIContext, an abstract data structure that holds +// debug information data. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_DICONTEXT_H +#define LLVM_DEBUGINFO_DICONTEXT_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm/Object/RelocVisitor.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/DataTypes.h" +#include + +namespace llvm { + +class raw_ostream; + +/// DILineInfo - a format-neutral container for source line information. +struct DILineInfo { + std::string FileName; + std::string FunctionName; + uint32_t Line; + uint32_t Column; + + DILineInfo() + : FileName(""), FunctionName(""), Line(0), Column(0) {} + + bool operator==(const DILineInfo &RHS) const { + return Line == RHS.Line && Column == RHS.Column && + FileName == RHS.FileName && FunctionName == RHS.FunctionName; + } + bool operator!=(const DILineInfo &RHS) const { + return !(*this == RHS); + } +}; + +typedef SmallVector, 16> DILineInfoTable; + +/// DIInliningInfo - a format-neutral container for inlined code description. +class DIInliningInfo { + SmallVector Frames; + public: + DIInliningInfo() {} + DILineInfo getFrame(unsigned Index) const { + assert(Index < Frames.size()); + return Frames[Index]; + } + uint32_t getNumberOfFrames() const { + return Frames.size(); + } + void addFrame(const DILineInfo &Frame) { + Frames.push_back(Frame); + } +}; + +/// A DINameKind is passed to name search methods to specify a +/// preference regarding the type of name resolution the caller wants. +enum class DINameKind { None, ShortName, LinkageName }; + +/// DILineInfoSpecifier - controls which fields of DILineInfo container +/// should be filled with data. +struct DILineInfoSpecifier { + enum class FileLineInfoKind { None, Default, AbsoluteFilePath }; + typedef DINameKind FunctionNameKind; + + FileLineInfoKind FLIKind; + FunctionNameKind FNKind; + + DILineInfoSpecifier(FileLineInfoKind FLIKind = FileLineInfoKind::Default, + FunctionNameKind FNKind = FunctionNameKind::None) + : FLIKind(FLIKind), FNKind(FNKind) {} +}; + +/// Selects which debug sections get dumped. +enum DIDumpType { + DIDT_Null, + DIDT_All, + DIDT_Abbrev, + DIDT_AbbrevDwo, + DIDT_Aranges, + DIDT_Frames, + DIDT_Info, + DIDT_InfoDwo, + DIDT_Types, + DIDT_TypesDwo, + DIDT_Line, + DIDT_LineDwo, + DIDT_Loc, + DIDT_LocDwo, + DIDT_Ranges, + DIDT_Pubnames, + DIDT_Pubtypes, + DIDT_GnuPubnames, + DIDT_GnuPubtypes, + DIDT_Str, + DIDT_StrDwo, + DIDT_StrOffsetsDwo, + DIDT_AppleNames, + DIDT_AppleTypes, + DIDT_AppleNamespaces, + DIDT_AppleObjC +}; + +// In place of applying the relocations to the data we've read from disk we use +// a separate mapping table to the side and checking that at locations in the +// dwarf where we expect relocated values. This adds a bit of complexity to the +// dwarf parsing/extraction at the benefit of not allocating memory for the +// entire size of the debug info sections. +typedef DenseMap > RelocAddrMap; + +class DIContext { +public: + enum DIContextKind { + CK_DWARF + }; + DIContextKind getKind() const { return Kind; } + + DIContext(DIContextKind K) : Kind(K) {} + virtual ~DIContext(); + + /// getDWARFContext - get a context for binary DWARF data. + static DIContext *getDWARFContext(const object::ObjectFile &Obj); + + virtual void dump(raw_ostream &OS, DIDumpType DumpType = DIDT_All) = 0; + + virtual DILineInfo getLineInfoForAddress(uint64_t Address, + DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0; + virtual DILineInfoTable getLineInfoForAddressRange(uint64_t Address, + uint64_t Size, DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0; + virtual DIInliningInfo getInliningInfoForAddress(uint64_t Address, + DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0; +private: + const DIContextKind Kind; +}; + +} + +#endif diff --git a/include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h b/include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h new file mode 100644 index 0000000..bb05c30 --- /dev/null +++ b/include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h @@ -0,0 +1,60 @@ +//===-- DWARFAbbreviationDeclaration.h --------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_DEBUGINFO_DWARFABBREVIATIONDECLARATION_H +#define LLVM_LIB_DEBUGINFO_DWARFABBREVIATIONDECLARATION_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/DataExtractor.h" + +namespace llvm { + +class raw_ostream; + +class DWARFAbbreviationDeclaration { + uint32_t Code; + uint32_t Tag; + bool HasChildren; + + struct AttributeSpec { + AttributeSpec(uint16_t Attr, uint16_t Form) : Attr(Attr), Form(Form) {} + uint16_t Attr; + uint16_t Form; + }; + typedef SmallVector AttributeSpecVector; + AttributeSpecVector AttributeSpecs; +public: + DWARFAbbreviationDeclaration(); + + uint32_t getCode() const { return Code; } + uint32_t getTag() const { return Tag; } + bool hasChildren() const { return HasChildren; } + + typedef iterator_range + attr_iterator_range; + + attr_iterator_range attributes() const { + return attr_iterator_range(AttributeSpecs.begin(), AttributeSpecs.end()); + } + + uint16_t getFormByIndex(uint32_t idx) const { + return idx < AttributeSpecs.size() ? AttributeSpecs[idx].Form : 0; + } + + uint32_t findAttributeIndex(uint16_t attr) const; + bool extract(DataExtractor Data, uint32_t* OffsetPtr); + void dump(raw_ostream &OS) const; + +private: + void clear(); +}; + +} + +#endif diff --git a/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h b/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h new file mode 100644 index 0000000..e34f096 --- /dev/null +++ b/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h @@ -0,0 +1,49 @@ +//===--- DWARFAcceleratorTable.h --------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/SmallVector.h" +#include "llvm/DebugInfo/DWARF/DWARFFormValue.h" +#include "llvm/DebugInfo/DWARF/DWARFRelocMap.h" +#include + +namespace llvm { + +class DWARFAcceleratorTable { + + struct Header { + uint32_t Magic; + uint16_t Version; + uint16_t HashFunction; + uint32_t NumBuckets; + uint32_t NumHashes; + uint32_t HeaderDataLength; + }; + + struct HeaderData { + typedef uint16_t AtomType; + typedef uint16_t Form; + uint32_t DIEOffsetBase; + SmallVector, 3> Atoms; + }; + + struct Header Hdr; + struct HeaderData HdrData; + DataExtractor AccelSection; + DataExtractor StringSection; + const RelocAddrMap& Relocs; +public: + DWARFAcceleratorTable(DataExtractor AccelSection, DataExtractor StringSection, + const RelocAddrMap &Relocs) + : AccelSection(AccelSection), StringSection(StringSection), Relocs(Relocs) {} + + bool extract(); + void dump(raw_ostream &OS) const; +}; + +} diff --git a/include/llvm/DebugInfo/DWARF/DWARFCompileUnit.h b/include/llvm/DebugInfo/DWARF/DWARFCompileUnit.h new file mode 100644 index 0000000..743f9c6 --- /dev/null +++ b/include/llvm/DebugInfo/DWARF/DWARFCompileUnit.h @@ -0,0 +1,31 @@ +//===-- DWARFCompileUnit.h --------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_DEBUGINFO_DWARFCOMPILEUNIT_H +#define LLVM_LIB_DEBUGINFO_DWARFCOMPILEUNIT_H + +#include "llvm/DebugInfo/DWARF/DWARFUnit.h" + +namespace llvm { + +class DWARFCompileUnit : public DWARFUnit { +public: + DWARFCompileUnit(DWARFContext &Context, const DWARFSection &Section, + const DWARFDebugAbbrev *DA, StringRef RS, StringRef SS, + StringRef SOS, StringRef AOS, bool LE, + const DWARFUnitSectionBase &UnitSection) + : DWARFUnit(Context, Section, DA, RS, SS, SOS, AOS, LE, UnitSection) {} + void dump(raw_ostream &OS); + // VTable anchor. + ~DWARFCompileUnit() override; +}; + +} + +#endif diff --git a/include/llvm/DebugInfo/DWARF/DWARFContext.h b/include/llvm/DebugInfo/DWARF/DWARFContext.h new file mode 100644 index 0000000..677242b --- /dev/null +++ b/include/llvm/DebugInfo/DWARF/DWARFContext.h @@ -0,0 +1,292 @@ +//===-- DWARFContext.h ------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===/ + +#ifndef LLVM_LIB_DEBUGINFO_DWARFCONTEXT_H +#define LLVM_LIB_DEBUGINFO_DWARFCONTEXT_H + +#include "llvm/ADT/MapVector.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/DebugInfo/DWARF/DIContext.h" +#include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h" +#include "llvm/DebugInfo/DWARF/DWARFDebugAranges.h" +#include "llvm/DebugInfo/DWARF/DWARFDebugFrame.h" +#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h" +#include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h" +#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h" +#include "llvm/DebugInfo/DWARF/DWARFSection.h" +#include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h" +#include + +namespace llvm { + +/// DWARFContext +/// This data structure is the top level entity that deals with dwarf debug +/// information parsing. The actual data is supplied through pure virtual +/// methods that a concrete implementation provides. +class DWARFContext : public DIContext { + + DWARFUnitSection CUs; + std::vector> TUs; + std::unique_ptr Abbrev; + std::unique_ptr Loc; + std::unique_ptr Aranges; + std::unique_ptr Line; + std::unique_ptr DebugFrame; + + DWARFUnitSection DWOCUs; + std::vector> DWOTUs; + std::unique_ptr AbbrevDWO; + std::unique_ptr LocDWO; + + DWARFContext(DWARFContext &) = delete; + DWARFContext &operator=(DWARFContext &) = delete; + + /// Read compile units from the debug_info section (if necessary) + /// and store them in CUs. + void parseCompileUnits(); + + /// Read type units from the debug_types sections (if necessary) + /// and store them in TUs. + void parseTypeUnits(); + + /// Read compile units from the debug_info.dwo section (if necessary) + /// and store them in DWOCUs. + void parseDWOCompileUnits(); + + /// Read type units from the debug_types.dwo section (if necessary) + /// and store them in DWOTUs. + void parseDWOTypeUnits(); + +public: + DWARFContext() : DIContext(CK_DWARF) {} + + static bool classof(const DIContext *DICtx) { + return DICtx->getKind() == CK_DWARF; + } + + void dump(raw_ostream &OS, DIDumpType DumpType = DIDT_All) override; + + typedef DWARFUnitSection::iterator_range cu_iterator_range; + typedef DWARFUnitSection::iterator_range tu_iterator_range; + typedef iterator_range>::iterator> tu_section_iterator_range; + + /// Get compile units in this context. + cu_iterator_range compile_units() { + parseCompileUnits(); + return cu_iterator_range(CUs.begin(), CUs.end()); + } + + /// Get type units in this context. + tu_section_iterator_range type_unit_sections() { + parseTypeUnits(); + return tu_section_iterator_range(TUs.begin(), TUs.end()); + } + + /// Get compile units in the DWO context. + cu_iterator_range dwo_compile_units() { + parseDWOCompileUnits(); + return cu_iterator_range(DWOCUs.begin(), DWOCUs.end()); + } + + /// Get type units in the DWO context. + tu_section_iterator_range dwo_type_unit_sections() { + parseDWOTypeUnits(); + return tu_section_iterator_range(DWOTUs.begin(), DWOTUs.end()); + } + + /// Get the number of compile units in this context. + unsigned getNumCompileUnits() { + parseCompileUnits(); + return CUs.size(); + } + + /// Get the number of compile units in this context. + unsigned getNumTypeUnits() { + parseTypeUnits(); + return TUs.size(); + } + + /// Get the number of compile units in the DWO context. + unsigned getNumDWOCompileUnits() { + parseDWOCompileUnits(); + return DWOCUs.size(); + } + + /// Get the number of compile units in the DWO context. + unsigned getNumDWOTypeUnits() { + parseDWOTypeUnits(); + return DWOTUs.size(); + } + + /// Get the compile unit at the specified index for this compile unit. + DWARFCompileUnit *getCompileUnitAtIndex(unsigned index) { + parseCompileUnits(); + return CUs[index].get(); + } + + /// Get the compile unit at the specified index for the DWO compile units. + DWARFCompileUnit *getDWOCompileUnitAtIndex(unsigned index) { + parseDWOCompileUnits(); + return DWOCUs[index].get(); + } + + /// Get a pointer to the parsed DebugAbbrev object. + const DWARFDebugAbbrev *getDebugAbbrev(); + + /// Get a pointer to the parsed DebugLoc object. + const DWARFDebugLoc *getDebugLoc(); + + /// Get a pointer to the parsed dwo abbreviations object. + const DWARFDebugAbbrev *getDebugAbbrevDWO(); + + /// Get a pointer to the parsed DebugLoc object. + const DWARFDebugLocDWO *getDebugLocDWO(); + + /// Get a pointer to the parsed DebugAranges object. + const DWARFDebugAranges *getDebugAranges(); + + /// Get a pointer to the parsed frame information object. + const DWARFDebugFrame *getDebugFrame(); + + /// Get a pointer to a parsed line table corresponding to a compile unit. + const DWARFDebugLine::LineTable *getLineTableForUnit(DWARFUnit *cu); + + DILineInfo getLineInfoForAddress(uint64_t Address, + DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; + DILineInfoTable getLineInfoForAddressRange(uint64_t Address, uint64_t Size, + DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; + DIInliningInfo getInliningInfoForAddress(uint64_t Address, + DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; + + virtual bool isLittleEndian() const = 0; + virtual uint8_t getAddressSize() const = 0; + virtual const DWARFSection &getInfoSection() = 0; + typedef MapVector> TypeSectionMap; + virtual const TypeSectionMap &getTypesSections() = 0; + virtual StringRef getAbbrevSection() = 0; + virtual const DWARFSection &getLocSection() = 0; + virtual StringRef getARangeSection() = 0; + virtual StringRef getDebugFrameSection() = 0; + virtual const DWARFSection &getLineSection() = 0; + virtual StringRef getStringSection() = 0; + virtual StringRef getRangeSection() = 0; + virtual StringRef getPubNamesSection() = 0; + virtual StringRef getPubTypesSection() = 0; + virtual StringRef getGnuPubNamesSection() = 0; + virtual StringRef getGnuPubTypesSection() = 0; + + // Sections for DWARF5 split dwarf proposal. + virtual const DWARFSection &getInfoDWOSection() = 0; + virtual const TypeSectionMap &getTypesDWOSections() = 0; + virtual StringRef getAbbrevDWOSection() = 0; + virtual const DWARFSection &getLineDWOSection() = 0; + virtual const DWARFSection &getLocDWOSection() = 0; + virtual StringRef getStringDWOSection() = 0; + virtual StringRef getStringOffsetDWOSection() = 0; + virtual StringRef getRangeDWOSection() = 0; + virtual StringRef getAddrSection() = 0; + virtual const DWARFSection& getAppleNamesSection() = 0; + virtual const DWARFSection& getAppleTypesSection() = 0; + virtual const DWARFSection& getAppleNamespacesSection() = 0; + virtual const DWARFSection& getAppleObjCSection() = 0; + + static bool isSupportedVersion(unsigned version) { + return version == 2 || version == 3 || version == 4; + } +private: + /// Return the compile unit that includes an offset (relative to .debug_info). + DWARFCompileUnit *getCompileUnitForOffset(uint32_t Offset); + + /// Return the compile unit which contains instruction with provided + /// address. + DWARFCompileUnit *getCompileUnitForAddress(uint64_t Address); +}; + +/// DWARFContextInMemory is the simplest possible implementation of a +/// DWARFContext. It assumes all content is available in memory and stores +/// pointers to it. +class DWARFContextInMemory : public DWARFContext { + virtual void anchor(); + bool IsLittleEndian; + uint8_t AddressSize; + DWARFSection InfoSection; + TypeSectionMap TypesSections; + StringRef AbbrevSection; + DWARFSection LocSection; + StringRef ARangeSection; + StringRef DebugFrameSection; + DWARFSection LineSection; + StringRef StringSection; + StringRef RangeSection; + StringRef PubNamesSection; + StringRef PubTypesSection; + StringRef GnuPubNamesSection; + StringRef GnuPubTypesSection; + + // Sections for DWARF5 split dwarf proposal. + DWARFSection InfoDWOSection; + TypeSectionMap TypesDWOSections; + StringRef AbbrevDWOSection; + DWARFSection LineDWOSection; + DWARFSection LocDWOSection; + StringRef StringDWOSection; + StringRef StringOffsetDWOSection; + StringRef RangeDWOSection; + StringRef AddrSection; + DWARFSection AppleNamesSection; + DWARFSection AppleTypesSection; + DWARFSection AppleNamespacesSection; + DWARFSection AppleObjCSection; + + SmallVector, 4> UncompressedSections; + +public: + DWARFContextInMemory(const object::ObjectFile &Obj); + bool isLittleEndian() const override { return IsLittleEndian; } + uint8_t getAddressSize() const override { return AddressSize; } + const DWARFSection &getInfoSection() override { return InfoSection; } + const TypeSectionMap &getTypesSections() override { return TypesSections; } + StringRef getAbbrevSection() override { return AbbrevSection; } + const DWARFSection &getLocSection() override { return LocSection; } + StringRef getARangeSection() override { return ARangeSection; } + StringRef getDebugFrameSection() override { return DebugFrameSection; } + const DWARFSection &getLineSection() override { return LineSection; } + StringRef getStringSection() override { return StringSection; } + StringRef getRangeSection() override { return RangeSection; } + StringRef getPubNamesSection() override { return PubNamesSection; } + StringRef getPubTypesSection() override { return PubTypesSection; } + StringRef getGnuPubNamesSection() override { return GnuPubNamesSection; } + StringRef getGnuPubTypesSection() override { return GnuPubTypesSection; } + const DWARFSection& getAppleNamesSection() override { return AppleNamesSection; } + const DWARFSection& getAppleTypesSection() override { return AppleTypesSection; } + const DWARFSection& getAppleNamespacesSection() override { return AppleNamespacesSection; } + const DWARFSection& getAppleObjCSection() override { return AppleObjCSection; } + + // Sections for DWARF5 split dwarf proposal. + const DWARFSection &getInfoDWOSection() override { return InfoDWOSection; } + const TypeSectionMap &getTypesDWOSections() override { + return TypesDWOSections; + } + StringRef getAbbrevDWOSection() override { return AbbrevDWOSection; } + const DWARFSection &getLineDWOSection() override { return LineDWOSection; } + const DWARFSection &getLocDWOSection() override { return LocDWOSection; } + StringRef getStringDWOSection() override { return StringDWOSection; } + StringRef getStringOffsetDWOSection() override { + return StringOffsetDWOSection; + } + StringRef getRangeDWOSection() override { return RangeDWOSection; } + StringRef getAddrSection() override { + return AddrSection; + } +}; + +} + +#endif diff --git a/include/llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h b/include/llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h new file mode 100644 index 0000000..2114208 --- /dev/null +++ b/include/llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h @@ -0,0 +1,63 @@ +//===-- DWARFDebugAbbrev.h --------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_DEBUGINFO_DWARFDEBUGABBREV_H +#define LLVM_LIB_DEBUGINFO_DWARFDEBUGABBREV_H + +#include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h" +#include +#include +#include + +namespace llvm { + +class DWARFAbbreviationDeclarationSet { + uint32_t Offset; + /// Code of the first abbreviation, if all abbreviations in the set have + /// consecutive codes. UINT32_MAX otherwise. + uint32_t FirstAbbrCode; + std::vector Decls; + +public: + DWARFAbbreviationDeclarationSet(); + + uint32_t getOffset() const { return Offset; } + void dump(raw_ostream &OS) const; + bool extract(DataExtractor Data, uint32_t *OffsetPtr); + + const DWARFAbbreviationDeclaration * + getAbbreviationDeclaration(uint32_t AbbrCode) const; + +private: + void clear(); +}; + +class DWARFDebugAbbrev { + typedef std::map + DWARFAbbreviationDeclarationSetMap; + + DWARFAbbreviationDeclarationSetMap AbbrDeclSets; + mutable DWARFAbbreviationDeclarationSetMap::const_iterator PrevAbbrOffsetPos; + +public: + DWARFDebugAbbrev(); + + const DWARFAbbreviationDeclarationSet * + getAbbreviationDeclarationSet(uint64_t CUAbbrOffset) const; + + void dump(raw_ostream &OS) const; + void extract(DataExtractor Data); + +private: + void clear(); +}; + +} + +#endif diff --git a/include/llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h b/include/llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h new file mode 100644 index 0000000..837a8e6 --- /dev/null +++ b/include/llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h @@ -0,0 +1,70 @@ +//===-- DWARFDebugArangeSet.h -----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_DEBUGINFO_DWARFDEBUGARANGESET_H +#define LLVM_LIB_DEBUGINFO_DWARFDEBUGARANGESET_H + +#include "llvm/ADT/iterator_range.h" +#include "llvm/Support/DataExtractor.h" +#include + +namespace llvm { + +class raw_ostream; + +class DWARFDebugArangeSet { +public: + struct Header { + // The total length of the entries for that set, not including the length + // field itself. + uint32_t Length; + // The offset from the beginning of the .debug_info section of the + // compilation unit entry referenced by the table. + uint32_t CuOffset; + // The DWARF version number. + uint16_t Version; + // The size in bytes of an address on the target architecture. For segmented + // addressing, this is the size of the offset portion of the address. + uint8_t AddrSize; + // The size in bytes of a segment descriptor on the target architecture. + // If the target system uses a flat address space, this value is 0. + uint8_t SegSize; + }; + + struct Descriptor { + uint64_t Address; + uint64_t Length; + uint64_t getEndAddress() const { return Address + Length; } + }; + +private: + typedef std::vector DescriptorColl; + typedef iterator_range desc_iterator_range; + + uint32_t Offset; + Header HeaderData; + DescriptorColl ArangeDescriptors; + +public: + DWARFDebugArangeSet() { clear(); } + void clear(); + bool extract(DataExtractor data, uint32_t *offset_ptr); + void dump(raw_ostream &OS) const; + + uint32_t getCompileUnitDIEOffset() const { return HeaderData.CuOffset; } + + desc_iterator_range descriptors() const { + return desc_iterator_range(ArangeDescriptors.begin(), + ArangeDescriptors.end()); + } +}; + +} + +#endif diff --git a/include/llvm/DebugInfo/DWARF/DWARFDebugAranges.h b/include/llvm/DebugInfo/DWARF/DWARFDebugAranges.h new file mode 100644 index 0000000..791f010 --- /dev/null +++ b/include/llvm/DebugInfo/DWARF/DWARFDebugAranges.h @@ -0,0 +1,87 @@ +//===-- DWARFDebugAranges.h -------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_DEBUGINFO_DWARFDEBUGARANGES_H +#define LLVM_LIB_DEBUGINFO_DWARFDEBUGARANGES_H + +#include "llvm/ADT/DenseSet.h" +#include "llvm/Support/DataExtractor.h" +#include + +namespace llvm { + +class DWARFContext; + +class DWARFDebugAranges { +public: + void generate(DWARFContext *CTX); + uint32_t findAddress(uint64_t Address) const; + +private: + void clear(); + void extract(DataExtractor DebugArangesData); + + // Call appendRange multiple times and then call construct. + void appendRange(uint32_t CUOffset, uint64_t LowPC, uint64_t HighPC); + void construct(); + + struct Range { + explicit Range(uint64_t LowPC = -1ULL, uint64_t HighPC = -1ULL, + uint32_t CUOffset = -1U) + : LowPC(LowPC), Length(HighPC - LowPC), CUOffset(CUOffset) {} + + void setHighPC(uint64_t HighPC) { + if (HighPC == -1ULL || HighPC <= LowPC) + Length = 0; + else + Length = HighPC - LowPC; + } + uint64_t HighPC() const { + if (Length) + return LowPC + Length; + return -1ULL; + } + + bool containsAddress(uint64_t Address) const { + return LowPC <= Address && Address < HighPC(); + } + bool operator<(const Range &other) const { + return LowPC < other.LowPC; + } + + uint64_t LowPC; // Start of address range. + uint32_t Length; // End of address range (not including this address). + uint32_t CUOffset; // Offset of the compile unit or die. + }; + + struct RangeEndpoint { + uint64_t Address; + uint32_t CUOffset; + bool IsRangeStart; + + RangeEndpoint(uint64_t Address, uint32_t CUOffset, bool IsRangeStart) + : Address(Address), CUOffset(CUOffset), IsRangeStart(IsRangeStart) {} + + bool operator<(const RangeEndpoint &Other) const { + return Address < Other.Address; + } + }; + + + typedef std::vector RangeColl; + typedef RangeColl::const_iterator RangeCollIterator; + + std::vector Endpoints; + RangeColl Aranges; + DenseSet ParsedCUOffsets; +}; + +} + +#endif diff --git a/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h b/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h new file mode 100644 index 0000000..be925cb --- /dev/null +++ b/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h @@ -0,0 +1,43 @@ +//===-- DWARFDebugFrame.h - Parsing of .debug_frame -------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_DEBUGINFO_DWARFDEBUGFRAME_H +#define LLVM_LIB_DEBUGINFO_DWARFDEBUGFRAME_H + +#include "llvm/Support/DataExtractor.h" +#include "llvm/Support/raw_ostream.h" +#include +#include + +namespace llvm { + +class FrameEntry; + +/// \brief A parsed .debug_frame section +/// +class DWARFDebugFrame { +public: + DWARFDebugFrame(); + ~DWARFDebugFrame(); + + /// \brief Dump the section data into the given stream. + void dump(raw_ostream &OS) const; + + /// \brief Parse the section from raw data. + /// data is assumed to be pointing to the beginning of the section. + void parse(DataExtractor Data); + +private: + std::vector> Entries; +}; + + +} // namespace llvm + +#endif diff --git a/include/llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h b/include/llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h new file mode 100644 index 0000000..1080327 --- /dev/null +++ b/include/llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h @@ -0,0 +1,160 @@ +//===-- DWARFDebugInfoEntry.h -----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_DEBUGINFO_DWARFDEBUGINFOENTRY_H +#define LLVM_LIB_DEBUGINFO_DWARFDEBUGINFOENTRY_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/DebugInfo/DWARF/DIContext.h" +#include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h" +#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h" +#include "llvm/Support/DataTypes.h" + +namespace llvm { + +class DWARFDebugAranges; +class DWARFCompileUnit; +class DWARFUnit; +class DWARFContext; +class DWARFFormValue; +struct DWARFDebugInfoEntryInlinedChain; + +/// DWARFDebugInfoEntryMinimal - A DIE with only the minimum required data. +class DWARFDebugInfoEntryMinimal { + /// Offset within the .debug_info of the start of this entry. + uint32_t Offset; + + /// How many to add to "this" to get the sibling. + uint32_t SiblingIdx; + + const DWARFAbbreviationDeclaration *AbbrevDecl; +public: + DWARFDebugInfoEntryMinimal() + : Offset(0), SiblingIdx(0), AbbrevDecl(nullptr) {} + + void dump(raw_ostream &OS, DWARFUnit *u, unsigned recurseDepth, + unsigned indent = 0) const; + void dumpAttribute(raw_ostream &OS, DWARFUnit *u, uint32_t *offset_ptr, + uint16_t attr, uint16_t form, unsigned indent = 0) const; + + /// Extracts a debug info entry, which is a child of a given unit, + /// starting at a given offset. If DIE can't be extracted, returns false and + /// doesn't change OffsetPtr. + bool extractFast(const DWARFUnit *U, uint32_t *OffsetPtr); + + uint32_t getTag() const { return AbbrevDecl ? AbbrevDecl->getTag() : 0; } + bool isNULL() const { return AbbrevDecl == nullptr; } + + /// Returns true if DIE represents a subprogram (not inlined). + bool isSubprogramDIE() const; + /// Returns true if DIE represents a subprogram or an inlined + /// subroutine. + bool isSubroutineDIE() const; + + uint32_t getOffset() const { return Offset; } + bool hasChildren() const { return !isNULL() && AbbrevDecl->hasChildren(); } + + // We know we are kept in a vector of contiguous entries, so we know + // our sibling will be some index after "this". + const DWARFDebugInfoEntryMinimal *getSibling() const { + return SiblingIdx > 0 ? this + SiblingIdx : nullptr; + } + + // We know we are kept in a vector of contiguous entries, so we know + // we don't need to store our child pointer, if we have a child it will + // be the next entry in the list... + const DWARFDebugInfoEntryMinimal *getFirstChild() const { + return hasChildren() ? this + 1 : nullptr; + } + + void setSibling(const DWARFDebugInfoEntryMinimal *Sibling) { + if (Sibling) { + // We know we are kept in a vector of contiguous entries, so we know + // our sibling will be some index after "this". + SiblingIdx = Sibling - this; + } else + SiblingIdx = 0; + } + + const DWARFAbbreviationDeclaration *getAbbreviationDeclarationPtr() const { + return AbbrevDecl; + } + + bool getAttributeValue(const DWARFUnit *U, const uint16_t Attr, + DWARFFormValue &FormValue) const; + + const char *getAttributeValueAsString(const DWARFUnit *U, const uint16_t Attr, + const char *FailValue) const; + + uint64_t getAttributeValueAsAddress(const DWARFUnit *U, const uint16_t Attr, + uint64_t FailValue) const; + + uint64_t getAttributeValueAsUnsignedConstant(const DWARFUnit *U, + const uint16_t Attr, + uint64_t FailValue) const; + + uint64_t getAttributeValueAsReference(const DWARFUnit *U, const uint16_t Attr, + uint64_t FailValue) const; + + uint64_t getAttributeValueAsSectionOffset(const DWARFUnit *U, + const uint16_t Attr, + uint64_t FailValue) const; + + uint64_t getRangesBaseAttribute(const DWARFUnit *U, uint64_t FailValue) const; + + /// Retrieves DW_AT_low_pc and DW_AT_high_pc from CU. + /// Returns true if both attributes are present. + bool getLowAndHighPC(const DWARFUnit *U, uint64_t &LowPC, + uint64_t &HighPC) const; + + DWARFAddressRangesVector getAddressRanges(const DWARFUnit *U) const; + + void collectChildrenAddressRanges(const DWARFUnit *U, + DWARFAddressRangesVector &Ranges) const; + + bool addressRangeContainsAddress(const DWARFUnit *U, + const uint64_t Address) const; + + /// If a DIE represents a subprogram (or inlined subroutine), + /// returns its mangled name (or short name, if mangled is missing). + /// This name may be fetched from specification or abstract origin + /// for this subprogram. Returns null if no name is found. + const char *getSubroutineName(const DWARFUnit *U, DINameKind Kind) const; + + /// Return the DIE name resolving DW_AT_sepcification or + /// DW_AT_abstract_origin references if necessary. + /// Returns null if no name is found. + const char *getName(const DWARFUnit *U, DINameKind Kind) const; + + /// Retrieves values of DW_AT_call_file, DW_AT_call_line and + /// DW_AT_call_column from DIE (or zeroes if they are missing). + void getCallerFrame(const DWARFUnit *U, uint32_t &CallFile, + uint32_t &CallLine, uint32_t &CallColumn) const; + + /// Get inlined chain for a given address, rooted at the current DIE. + /// Returns empty chain if address is not contained in address range + /// of current DIE. + DWARFDebugInfoEntryInlinedChain + getInlinedChainForAddress(const DWARFUnit *U, const uint64_t Address) const; +}; + +/// DWARFDebugInfoEntryInlinedChain - represents a chain of inlined_subroutine +/// DIEs, (possibly ending with subprogram DIE), all of which are contained +/// in some concrete inlined instance tree. Address range for each DIE +/// (except the last DIE) in this chain is contained in address +/// range for next DIE in the chain. +struct DWARFDebugInfoEntryInlinedChain { + DWARFDebugInfoEntryInlinedChain() : U(nullptr) {} + SmallVector DIEs; + const DWARFUnit *U; +}; + +} + +#endif diff --git a/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h b/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h new file mode 100644 index 0000000..0c564c4 --- /dev/null +++ b/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h @@ -0,0 +1,238 @@ +//===-- DWARFDebugLine.h ----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_DEBUGINFO_DWARFDEBUGLINE_H +#define LLVM_LIB_DEBUGINFO_DWARFDEBUGLINE_H + +#include "llvm/DebugInfo/DWARF/DIContext.h" +#include "llvm/DebugInfo/DWARF/DWARFRelocMap.h" +#include "llvm/Support/DataExtractor.h" +#include +#include +#include + +namespace llvm { + +class raw_ostream; + +class DWARFDebugLine { +public: + DWARFDebugLine(const RelocAddrMap* LineInfoRelocMap) : RelocMap(LineInfoRelocMap) {} + struct FileNameEntry { + FileNameEntry() : Name(nullptr), DirIdx(0), ModTime(0), Length(0) {} + + const char *Name; + uint64_t DirIdx; + uint64_t ModTime; + uint64_t Length; + }; + + struct Prologue { + Prologue(); + + // The size in bytes of the statement information for this compilation unit + // (not including the total_length field itself). + uint32_t TotalLength; + // Version identifier for the statement information format. + uint16_t Version; + // The number of bytes following the prologue_length field to the beginning + // of the first byte of the statement program itself. + uint32_t PrologueLength; + // The size in bytes of the smallest target machine instruction. Statement + // program opcodes that alter the address register first multiply their + // operands by this value. + uint8_t MinInstLength; + // The maximum number of individual operations that may be encoded in an + // instruction. + uint8_t MaxOpsPerInst; + // The initial value of theis_stmtregister. + uint8_t DefaultIsStmt; + // This parameter affects the meaning of the special opcodes. See below. + int8_t LineBase; + // This parameter affects the meaning of the special opcodes. See below. + uint8_t LineRange; + // The number assigned to the first special opcode. + uint8_t OpcodeBase; + std::vector StandardOpcodeLengths; + std::vector IncludeDirectories; + std::vector FileNames; + + // Length of the prologue in bytes. + uint32_t getLength() const { + return PrologueLength + sizeof(TotalLength) + sizeof(Version) + + sizeof(PrologueLength); + } + // Length of the line table data in bytes (not including the prologue). + uint32_t getStatementTableLength() const { + return TotalLength + sizeof(TotalLength) - getLength(); + } + int32_t getMaxLineIncrementForSpecialOpcode() const { + return LineBase + (int8_t)LineRange - 1; + } + + void clear(); + void dump(raw_ostream &OS) const; + bool parse(DataExtractor debug_line_data, uint32_t *offset_ptr); + }; + + // Standard .debug_line state machine structure. + struct Row { + explicit Row(bool default_is_stmt = false); + + /// Called after a row is appended to the matrix. + void postAppend(); + void reset(bool default_is_stmt); + void dump(raw_ostream &OS) const; + + static bool orderByAddress(const Row& LHS, const Row& RHS) { + return LHS.Address < RHS.Address; + } + + // The program-counter value corresponding to a machine instruction + // generated by the compiler. + uint64_t Address; + // An unsigned integer indicating a source line number. Lines are numbered + // beginning at 1. The compiler may emit the value 0 in cases where an + // instruction cannot be attributed to any source line. + uint32_t Line; + // An unsigned integer indicating a column number within a source line. + // Columns are numbered beginning at 1. The value 0 is reserved to indicate + // that a statement begins at the 'left edge' of the line. + uint16_t Column; + // An unsigned integer indicating the identity of the source file + // corresponding to a machine instruction. + uint16_t File; + // An unsigned integer whose value encodes the applicable instruction set + // architecture for the current instruction. + uint8_t Isa; + // An unsigned integer representing the DWARF path discriminator value + // for this location. + uint32_t Discriminator; + // A boolean indicating that the current instruction is the beginning of a + // statement. + uint8_t IsStmt:1, + // A boolean indicating that the current instruction is the + // beginning of a basic block. + BasicBlock:1, + // A boolean indicating that the current address is that of the + // first byte after the end of a sequence of target machine + // instructions. + EndSequence:1, + // A boolean indicating that the current address is one (of possibly + // many) where execution should be suspended for an entry breakpoint + // of a function. + PrologueEnd:1, + // A boolean indicating that the current address is one (of possibly + // many) where execution should be suspended for an exit breakpoint + // of a function. + EpilogueBegin:1; + }; + + // Represents a series of contiguous machine instructions. Line table for each + // compilation unit may consist of multiple sequences, which are not + // guaranteed to be in the order of ascending instruction address. + struct Sequence { + // Sequence describes instructions at address range [LowPC, HighPC) + // and is described by line table rows [FirstRowIndex, LastRowIndex). + uint64_t LowPC; + uint64_t HighPC; + unsigned FirstRowIndex; + unsigned LastRowIndex; + bool Empty; + + Sequence(); + void reset(); + + static bool orderByLowPC(const Sequence& LHS, const Sequence& RHS) { + return LHS.LowPC < RHS.LowPC; + } + bool isValid() const { + return !Empty && (LowPC < HighPC) && (FirstRowIndex < LastRowIndex); + } + bool containsPC(uint64_t pc) const { + return (LowPC <= pc && pc < HighPC); + } + }; + + struct LineTable { + LineTable(); + + void appendRow(const DWARFDebugLine::Row &R) { + Rows.push_back(R); + } + void appendSequence(const DWARFDebugLine::Sequence &S) { + Sequences.push_back(S); + } + + // Returns the index of the row with file/line info for a given address, + // or -1 if there is no such row. + uint32_t lookupAddress(uint64_t address) const; + + bool lookupAddressRange(uint64_t address, uint64_t size, + std::vector &result) const; + + // Extracts filename by its index in filename table in prologue. + // Returns true on success. + bool getFileNameByIndex(uint64_t FileIndex, const char *CompDir, + DILineInfoSpecifier::FileLineInfoKind Kind, + std::string &Result) const; + + // Fills the Result argument with the file and line information + // corresponding to Address. Returns true on success. + bool getFileLineInfoForAddress(uint64_t Address, const char *CompDir, + DILineInfoSpecifier::FileLineInfoKind Kind, + DILineInfo &Result) const; + + void dump(raw_ostream &OS) const; + void clear(); + + /// Parse prologue and all rows. + bool parse(DataExtractor debug_line_data, const RelocAddrMap *RMap, + uint32_t *offset_ptr); + + struct Prologue Prologue; + typedef std::vector RowVector; + typedef RowVector::const_iterator RowIter; + typedef std::vector SequenceVector; + typedef SequenceVector::const_iterator SequenceIter; + RowVector Rows; + SequenceVector Sequences; + }; + + const LineTable *getLineTable(uint32_t offset) const; + const LineTable *getOrParseLineTable(DataExtractor debug_line_data, + uint32_t offset); + +private: + struct ParsingState { + ParsingState(struct LineTable *LT); + + void resetRowAndSequence(); + void appendRowToMatrix(uint32_t offset); + + // Line table we're currently parsing. + struct LineTable *LineTable; + // The row number that starts at zero for the prologue, and increases for + // each row added to the matrix. + unsigned RowNumber; + struct Row Row; + struct Sequence Sequence; + }; + + typedef std::map LineTableMapTy; + typedef LineTableMapTy::iterator LineTableIter; + typedef LineTableMapTy::const_iterator LineTableConstIter; + + const RelocAddrMap *RelocMap; + LineTableMapTy LineTableMap; +}; + +} + +#endif diff --git a/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h b/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h new file mode 100644 index 0000000..bd44c2e5 --- /dev/null +++ b/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h @@ -0,0 +1,81 @@ +//===-- DWARFDebugLoc.h -----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_DEBUGINFO_DWARFDEBUGLOC_H +#define LLVM_LIB_DEBUGINFO_DWARFDEBUGLOC_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/DebugInfo/DWARF/DWARFRelocMap.h" +#include "llvm/Support/DataExtractor.h" + +namespace llvm { + +class raw_ostream; + +class DWARFDebugLoc { + /// A single location within a location list. + struct Entry { + /// The beginning address of the instruction range. + uint64_t Begin; + /// The ending address of the instruction range. + uint64_t End; + /// The location of the variable within the specified range. + SmallVector Loc; + }; + + /// A list of locations that contain one variable. + struct LocationList { + /// The beginning offset where this location list is stored in the debug_loc + /// section. + unsigned Offset; + /// All the locations in which the variable is stored. + SmallVector Entries; + }; + + typedef SmallVector LocationLists; + + /// A list of all the variables in the debug_loc section, each one describing + /// the locations in which the variable is stored. + LocationLists Locations; + + /// A map used to resolve binary relocations. + const RelocAddrMap &RelocMap; + +public: + DWARFDebugLoc(const RelocAddrMap &LocRelocMap) : RelocMap(LocRelocMap) {} + /// Print the location lists found within the debug_loc section. + void dump(raw_ostream &OS) const; + /// Parse the debug_loc section accessible via the 'data' parameter using the + /// specified address size to interpret the address ranges. + void parse(DataExtractor data, unsigned AddressSize); +}; + +class DWARFDebugLocDWO { + struct Entry { + uint64_t Start; + uint32_t Length; + SmallVector Loc; + }; + + struct LocationList { + unsigned Offset; + SmallVector Entries; + }; + + typedef SmallVector LocationLists; + + LocationLists Locations; + +public: + void parse(DataExtractor data); + void dump(raw_ostream &OS) const; +}; +} + +#endif diff --git a/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h b/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h new file mode 100644 index 0000000..4ee3bda --- /dev/null +++ b/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h @@ -0,0 +1,77 @@ +//===-- DWARFDebugRangeList.h -----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_DEBUGINFO_DWARFDEBUGRANGELIST_H +#define LLVM_LIB_DEBUGINFO_DWARFDEBUGRANGELIST_H + +#include "llvm/Support/DataExtractor.h" +#include + +namespace llvm { + +class raw_ostream; + +/// DWARFAddressRangesVector - represents a set of absolute address ranges. +typedef std::vector> DWARFAddressRangesVector; + +class DWARFDebugRangeList { +public: + struct RangeListEntry { + // A beginning address offset. This address offset has the size of an + // address and is relative to the applicable base address of the + // compilation unit referencing this range list. It marks the beginning + // of an address range. + uint64_t StartAddress; + // An ending address offset. This address offset again has the size of + // an address and is relative to the applicable base address of the + // compilation unit referencing this range list. It marks the first + // address past the end of the address range. The ending address must + // be greater than or equal to the beginning address. + uint64_t EndAddress; + // The end of any given range list is marked by an end of list entry, + // which consists of a 0 for the beginning address offset + // and a 0 for the ending address offset. + bool isEndOfListEntry() const { + return (StartAddress == 0) && (EndAddress == 0); + } + // A base address selection entry consists of: + // 1. The value of the largest representable address offset + // (for example, 0xffffffff when the size of an address is 32 bits). + // 2. An address, which defines the appropriate base address for + // use in interpreting the beginning and ending address offsets of + // subsequent entries of the location list. + bool isBaseAddressSelectionEntry(uint8_t AddressSize) const { + assert(AddressSize == 4 || AddressSize == 8); + if (AddressSize == 4) + return StartAddress == -1U; + else + return StartAddress == -1ULL; + } + }; + +private: + // Offset in .debug_ranges section. + uint32_t Offset; + uint8_t AddressSize; + std::vector Entries; + +public: + DWARFDebugRangeList() { clear(); } + void clear(); + void dump(raw_ostream &OS) const; + bool extract(DataExtractor data, uint32_t *offset_ptr); + /// getAbsoluteRanges - Returns absolute address ranges defined by this range + /// list. Has to be passed base address of the compile unit referencing this + /// range list. + DWARFAddressRangesVector getAbsoluteRanges(uint64_t BaseAddress) const; +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_DWARFDEBUGRANGELIST_H diff --git a/include/llvm/DebugInfo/DWARF/DWARFFormValue.h b/include/llvm/DebugInfo/DWARF/DWARFFormValue.h new file mode 100644 index 0000000..5bb6d1b --- /dev/null +++ b/include/llvm/DebugInfo/DWARF/DWARFFormValue.h @@ -0,0 +1,93 @@ +//===-- DWARFFormValue.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_DWARFFORMVALUE_H +#define LLVM_DEBUGINFO_DWARFFORMVALUE_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/Optional.h" +#include "llvm/Support/DataExtractor.h" + +namespace llvm { + +class DWARFUnit; +class raw_ostream; + +class DWARFFormValue { +public: + enum FormClass { + FC_Unknown, + FC_Address, + FC_Block, + FC_Constant, + FC_String, + FC_Flag, + FC_Reference, + FC_Indirect, + FC_SectionOffset, + FC_Exprloc + }; + +private: + struct ValueType { + ValueType() : data(nullptr) { + uval = 0; + } + + union { + uint64_t uval; + int64_t sval; + const char* cstr; + }; + const uint8_t* data; + }; + + uint16_t Form; // Form for this value. + ValueType Value; // Contains all data for the form. + +public: + DWARFFormValue(uint16_t Form = 0) : Form(Form) {} + uint16_t getForm() const { return Form; } + bool isFormClass(FormClass FC) const; + + void dump(raw_ostream &OS, const DWARFUnit *U) const; + + /// \brief extracts a value in data at offset *offset_ptr. + /// + /// The passed DWARFUnit is allowed to be nullptr, in which + /// case no relocation processing will be performed and some + /// kind of forms that depend on Unit information are disallowed. + /// \returns wether the extraction succeeded. + bool extractValue(DataExtractor data, uint32_t *offset_ptr, + const DWARFUnit *u); + bool isInlinedCStr() const { + return Value.data != nullptr && Value.data == (const uint8_t*)Value.cstr; + } + + /// getAsFoo functions below return the extracted value as Foo if only + /// DWARFFormValue has form class is suitable for representing Foo. + Optional getAsReference(const DWARFUnit *U) const; + Optional getAsUnsignedConstant() const; + Optional getAsCString(const DWARFUnit *U) const; + Optional getAsAddress(const DWARFUnit *U) const; + Optional getAsSectionOffset() const; + Optional> getAsBlock() const; + + bool skipValue(DataExtractor debug_info_data, uint32_t *offset_ptr, + const DWARFUnit *u) const; + static bool skipValue(uint16_t form, DataExtractor debug_info_data, + uint32_t *offset_ptr, const DWARFUnit *u); + + static ArrayRef getFixedFormSizes(uint8_t AddrSize, + uint16_t Version); +}; + +} + +#endif diff --git a/include/llvm/DebugInfo/DWARF/DWARFRelocMap.h b/include/llvm/DebugInfo/DWARF/DWARFRelocMap.h new file mode 100644 index 0000000..d7fe303 --- /dev/null +++ b/include/llvm/DebugInfo/DWARF/DWARFRelocMap.h @@ -0,0 +1,22 @@ +//===-- DWARFRelocMap.h -----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_DEBUGINFO_DWARFRELOCMAP_H +#define LLVM_LIB_DEBUGINFO_DWARFRELOCMAP_H + +#include "llvm/ADT/DenseMap.h" + +namespace llvm { + +typedef DenseMap > RelocAddrMap; + +} // namespace llvm + +#endif + diff --git a/include/llvm/DebugInfo/DWARF/DWARFSection.h b/include/llvm/DebugInfo/DWARF/DWARFSection.h new file mode 100644 index 0000000..f52004c --- /dev/null +++ b/include/llvm/DebugInfo/DWARF/DWARFSection.h @@ -0,0 +1,24 @@ +//===-- DWARFSection.h ------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_DEBUGINFO_DWARFSECTION_H +#define LLVM_LIB_DEBUGINFO_DWARFSECTION_H + +#include "llvm/DebugInfo/DWARF/DWARFRelocMap.h" + +namespace llvm { + +struct DWARFSection { + StringRef Data; + RelocAddrMap Relocs; +}; + +} + +#endif diff --git a/include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h b/include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h new file mode 100644 index 0000000..f24e278 --- /dev/null +++ b/include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h @@ -0,0 +1,38 @@ +//===-- DWARFTypeUnit.h -----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_DEBUGINFO_DWARFTYPEUNIT_H +#define LLVM_LIB_DEBUGINFO_DWARFTYPEUNIT_H + +#include "llvm/DebugInfo/DWARF/DWARFUnit.h" + +namespace llvm { + +class DWARFTypeUnit : public DWARFUnit { +private: + uint64_t TypeHash; + uint32_t TypeOffset; +public: + DWARFTypeUnit(DWARFContext &Context, const DWARFSection &Section, + const DWARFDebugAbbrev *DA, StringRef RS, StringRef SS, + StringRef SOS, StringRef AOS, bool LE, + const DWARFUnitSectionBase &UnitSection) + : DWARFUnit(Context, Section, DA, RS, SS, SOS, AOS, LE, UnitSection) {} + uint32_t getHeaderSize() const override { + return DWARFUnit::getHeaderSize() + 12; + } + void dump(raw_ostream &OS); +protected: + bool extractImpl(DataExtractor debug_info, uint32_t *offset_ptr) override; +}; + +} + +#endif + diff --git a/include/llvm/DebugInfo/DWARF/DWARFUnit.h b/include/llvm/DebugInfo/DWARF/DWARFUnit.h new file mode 100644 index 0000000..628852f --- /dev/null +++ b/include/llvm/DebugInfo/DWARF/DWARFUnit.h @@ -0,0 +1,285 @@ +//===-- DWARFUnit.h ---------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_DEBUGINFO_DWARFUNIT_H +#define LLVM_LIB_DEBUGINFO_DWARFUNIT_H + +#include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h" +#include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h" +#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h" +#include "llvm/DebugInfo/DWARF/DWARFRelocMap.h" +#include "llvm/DebugInfo/DWARF/DWARFSection.h" +#include + +namespace llvm { + +namespace object { +class ObjectFile; +} + +class DWARFContext; +class DWARFDebugAbbrev; +class DWARFUnit; +class StringRef; +class raw_ostream; + +/// Base class for all DWARFUnitSection classes. This provides the +/// functionality common to all unit types. +class DWARFUnitSectionBase { +public: + /// Returns the Unit that contains the given section offset in the + /// same section this Unit originated from. + virtual DWARFUnit *getUnitForOffset(uint32_t Offset) const = 0; + + void parse(DWARFContext &C, const DWARFSection &Section); + void parseDWO(DWARFContext &C, const DWARFSection &DWOSection); + +protected: + virtual void parseImpl(DWARFContext &Context, const DWARFSection &Section, + const DWARFDebugAbbrev *DA, StringRef RS, StringRef SS, + StringRef SOS, StringRef AOS, bool isLittleEndian) = 0; + + ~DWARFUnitSectionBase() {} +}; + +/// Concrete instance of DWARFUnitSection, specialized for one Unit type. +template +class DWARFUnitSection final : public SmallVector, 1>, + public DWARFUnitSectionBase { + + struct UnitOffsetComparator { + bool operator()(uint32_t LHS, + const std::unique_ptr &RHS) const { + return LHS < RHS->getNextUnitOffset(); + } + }; + + bool Parsed; + +public: + DWARFUnitSection() : Parsed(false) {} + DWARFUnitSection(DWARFUnitSection &&DUS) : + SmallVector, 1>(std::move(DUS)), Parsed(DUS.Parsed) {} + + typedef llvm::SmallVectorImpl> UnitVector; + typedef typename UnitVector::iterator iterator; + typedef llvm::iterator_range iterator_range; + + UnitType *getUnitForOffset(uint32_t Offset) const override { + auto *CU = std::upper_bound(this->begin(), this->end(), Offset, + UnitOffsetComparator()); + if (CU != this->end()) + return CU->get(); + return nullptr; + } + +private: + void parseImpl(DWARFContext &Context, const DWARFSection &Section, + const DWARFDebugAbbrev *DA, StringRef RS, StringRef SS, + StringRef SOS, StringRef AOS, bool LE) override { + if (Parsed) + return; + DataExtractor Data(Section.Data, LE, 0); + uint32_t Offset = 0; + while (Data.isValidOffset(Offset)) { + auto U = llvm::make_unique(Context, Section, DA, RS, SS, SOS, + AOS, LE, *this); + if (!U->extract(Data, &Offset)) + break; + this->push_back(std::move(U)); + Offset = this->back()->getNextUnitOffset(); + } + Parsed = true; + } +}; + +class DWARFUnit { + DWARFContext &Context; + // Section containing this DWARFUnit. + const DWARFSection &InfoSection; + + const DWARFDebugAbbrev *Abbrev; + StringRef RangeSection; + uint32_t RangeSectionBase; + StringRef StringSection; + StringRef StringOffsetSection; + StringRef AddrOffsetSection; + uint32_t AddrOffsetSectionBase; + bool isLittleEndian; + const DWARFUnitSectionBase &UnitSection; + + uint32_t Offset; + uint32_t Length; + uint16_t Version; + const DWARFAbbreviationDeclarationSet *Abbrevs; + uint8_t AddrSize; + uint64_t BaseAddr; + // The compile unit debug information entry items. + std::vector DieArray; + + class DWOHolder { + object::OwningBinary DWOFile; + std::unique_ptr DWOContext; + DWARFUnit *DWOU; + public: + DWOHolder(StringRef DWOPath); + DWARFUnit *getUnit() const { return DWOU; } + }; + std::unique_ptr DWO; + +protected: + virtual bool extractImpl(DataExtractor debug_info, uint32_t *offset_ptr); + /// Size in bytes of the unit header. + virtual uint32_t getHeaderSize() const { return 11; } + +public: + DWARFUnit(DWARFContext &Context, const DWARFSection &Section, + const DWARFDebugAbbrev *DA, StringRef RS, StringRef SS, + StringRef SOS, StringRef AOS, bool LE, + const DWARFUnitSectionBase &UnitSection); + + virtual ~DWARFUnit(); + + DWARFContext& getContext() const { return Context; } + + StringRef getStringSection() const { return StringSection; } + StringRef getStringOffsetSection() const { return StringOffsetSection; } + void setAddrOffsetSection(StringRef AOS, uint32_t Base) { + AddrOffsetSection = AOS; + AddrOffsetSectionBase = Base; + } + void setRangesSection(StringRef RS, uint32_t Base) { + RangeSection = RS; + RangeSectionBase = Base; + } + + bool getAddrOffsetSectionItem(uint32_t Index, uint64_t &Result) const; + // FIXME: Result should be uint64_t in DWARF64. + bool getStringOffsetSectionItem(uint32_t Index, uint32_t &Result) const; + + DataExtractor getDebugInfoExtractor() const { + return DataExtractor(InfoSection.Data, isLittleEndian, AddrSize); + } + DataExtractor getStringExtractor() const { + return DataExtractor(StringSection, false, 0); + } + + const RelocAddrMap *getRelocMap() const { return &InfoSection.Relocs; } + + bool extract(DataExtractor debug_info, uint32_t* offset_ptr); + + /// extractRangeList - extracts the range list referenced by this compile + /// unit from .debug_ranges section. Returns true on success. + /// Requires that compile unit is already extracted. + bool extractRangeList(uint32_t RangeListOffset, + DWARFDebugRangeList &RangeList) const; + void clear(); + uint32_t getOffset() const { return Offset; } + uint32_t getNextUnitOffset() const { return Offset + Length + 4; } + uint32_t getLength() const { return Length; } + uint16_t getVersion() const { return Version; } + const DWARFAbbreviationDeclarationSet *getAbbreviations() const { + return Abbrevs; + } + uint8_t getAddressByteSize() const { return AddrSize; } + uint64_t getBaseAddress() const { return BaseAddr; } + + void setBaseAddress(uint64_t base_addr) { + BaseAddr = base_addr; + } + + const DWARFDebugInfoEntryMinimal * + getCompileUnitDIE(bool extract_cu_die_only = true) { + extractDIEsIfNeeded(extract_cu_die_only); + return DieArray.empty() ? nullptr : &DieArray[0]; + } + + const char *getCompilationDir(); + uint64_t getDWOId(); + + void collectAddressRanges(DWARFAddressRangesVector &CURanges); + + /// getInlinedChainForAddress - fetches inlined chain for a given address. + /// Returns empty chain if there is no subprogram containing address. The + /// chain is valid as long as parsed compile unit DIEs are not cleared. + DWARFDebugInfoEntryInlinedChain getInlinedChainForAddress(uint64_t Address); + + /// getUnitSection - Return the DWARFUnitSection containing this unit. + const DWARFUnitSectionBase &getUnitSection() const { return UnitSection; } + + /// \brief Returns the number of DIEs in the unit. Parses the unit + /// if necessary. + unsigned getNumDIEs() { + extractDIEsIfNeeded(false); + return DieArray.size(); + } + + /// \brief Return the index of a DIE inside the unit's DIE vector. + /// + /// It is illegal to call this method with a DIE that hasn't be + /// created by this unit. In other word, it's illegal to call this + /// method on a DIE that isn't accessible by following + /// children/sibling links starting from this unit's + /// getCompileUnitDIE(). + uint32_t getDIEIndex(const DWARFDebugInfoEntryMinimal *DIE) { + assert(!DieArray.empty() && DIE >= &DieArray[0] && + DIE < &DieArray[0] + DieArray.size()); + return DIE - &DieArray[0]; + } + + /// \brief Return the DIE object at the given index. + const DWARFDebugInfoEntryMinimal *getDIEAtIndex(unsigned Index) const { + assert(Index < DieArray.size()); + return &DieArray[Index]; + } + + /// \brief Return the DIE object for a given offset inside the + /// unit's DIE vector. + /// + /// The unit needs to have his DIEs extracted for this method to work. + const DWARFDebugInfoEntryMinimal *getDIEForOffset(uint32_t Offset) const { + assert(!DieArray.empty()); + auto it = std::lower_bound( + DieArray.begin(), DieArray.end(), Offset, + [=](const DWARFDebugInfoEntryMinimal &LHS, uint32_t Offset) { + return LHS.getOffset() < Offset; + }); + return it == DieArray.end() ? nullptr : &*it; + } + +private: + /// Size in bytes of the .debug_info data associated with this compile unit. + size_t getDebugInfoSize() const { return Length + 4 - getHeaderSize(); } + + /// extractDIEsIfNeeded - Parses a compile unit and indexes its DIEs if it + /// hasn't already been done. Returns the number of DIEs parsed at this call. + size_t extractDIEsIfNeeded(bool CUDieOnly); + /// extractDIEsToVector - Appends all parsed DIEs to a vector. + void extractDIEsToVector(bool AppendCUDie, bool AppendNonCUDIEs, + std::vector &DIEs) const; + /// setDIERelations - We read in all of the DIE entries into our flat list + /// of DIE entries and now we need to go back through all of them and set the + /// parent, sibling and child pointers for quick DIE navigation. + void setDIERelations(); + /// clearDIEs - Clear parsed DIEs to keep memory usage low. + void clearDIEs(bool KeepCUDie); + + /// parseDWO - Parses .dwo file for current compile unit. Returns true if + /// it was actually constructed. + bool parseDWO(); + + /// getSubprogramForAddress - Returns subprogram DIE with address range + /// encompassing the provided address. The pointer is alive as long as parsed + /// compile unit DIEs are not cleared. + const DWARFDebugInfoEntryMinimal *getSubprogramForAddress(uint64_t Address); +}; + +} + +#endif diff --git a/include/llvm/DebugInfo/DWARFFormValue.h b/include/llvm/DebugInfo/DWARFFormValue.h deleted file mode 100644 index 5bb6d1b..0000000 --- a/include/llvm/DebugInfo/DWARFFormValue.h +++ /dev/null @@ -1,93 +0,0 @@ -//===-- DWARFFormValue.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_DWARFFORMVALUE_H -#define LLVM_DEBUGINFO_DWARFFORMVALUE_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/Optional.h" -#include "llvm/Support/DataExtractor.h" - -namespace llvm { - -class DWARFUnit; -class raw_ostream; - -class DWARFFormValue { -public: - enum FormClass { - FC_Unknown, - FC_Address, - FC_Block, - FC_Constant, - FC_String, - FC_Flag, - FC_Reference, - FC_Indirect, - FC_SectionOffset, - FC_Exprloc - }; - -private: - struct ValueType { - ValueType() : data(nullptr) { - uval = 0; - } - - union { - uint64_t uval; - int64_t sval; - const char* cstr; - }; - const uint8_t* data; - }; - - uint16_t Form; // Form for this value. - ValueType Value; // Contains all data for the form. - -public: - DWARFFormValue(uint16_t Form = 0) : Form(Form) {} - uint16_t getForm() const { return Form; } - bool isFormClass(FormClass FC) const; - - void dump(raw_ostream &OS, const DWARFUnit *U) const; - - /// \brief extracts a value in data at offset *offset_ptr. - /// - /// The passed DWARFUnit is allowed to be nullptr, in which - /// case no relocation processing will be performed and some - /// kind of forms that depend on Unit information are disallowed. - /// \returns wether the extraction succeeded. - bool extractValue(DataExtractor data, uint32_t *offset_ptr, - const DWARFUnit *u); - bool isInlinedCStr() const { - return Value.data != nullptr && Value.data == (const uint8_t*)Value.cstr; - } - - /// getAsFoo functions below return the extracted value as Foo if only - /// DWARFFormValue has form class is suitable for representing Foo. - Optional getAsReference(const DWARFUnit *U) const; - Optional getAsUnsignedConstant() const; - Optional getAsCString(const DWARFUnit *U) const; - Optional getAsAddress(const DWARFUnit *U) const; - Optional getAsSectionOffset() const; - Optional> getAsBlock() const; - - bool skipValue(DataExtractor debug_info_data, uint32_t *offset_ptr, - const DWARFUnit *u) const; - static bool skipValue(uint16_t form, DataExtractor debug_info_data, - uint32_t *offset_ptr, const DWARFUnit *u); - - static ArrayRef getFixedFormSizes(uint8_t AddrSize, - uint16_t Version); -}; - -} - -#endif diff --git a/include/llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h b/include/llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h new file mode 100644 index 0000000..96ce12f --- /dev/null +++ b/include/llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h @@ -0,0 +1,59 @@ +//===- ConcreteSymbolEnumerator.h -------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_CONCRETESYMBOLENUMERATOR_H +#define LLVM_DEBUGINFO_PDB_CONCRETESYMBOLENUMERATOR_H + +#include "IPDBEnumChildren.h" +#include "llvm/Support/Casting.h" +#include + +namespace llvm { + +template +class ConcreteSymbolEnumerator : public IPDBEnumChildren { +public: + ConcreteSymbolEnumerator(std::unique_ptr SymbolEnumerator) + : Enumerator(std::move(SymbolEnumerator)) {} + + virtual ~ConcreteSymbolEnumerator() {} + + uint32_t getChildCount() const override { + return Enumerator->getChildCount(); + } + + std::unique_ptr getChildAtIndex(uint32_t Index) const override { + std::unique_ptr Child = Enumerator->getChildAtIndex(Index); + return make_concrete_child(std::move(Child)); + } + + std::unique_ptr getNext() override { + std::unique_ptr Child = Enumerator->getNext(); + return make_concrete_child(std::move(Child)); + } + + void reset() override { Enumerator->reset(); } + + ConcreteSymbolEnumerator *clone() const override { + std::unique_ptr WrappedClone(Enumerator->clone()); + return new ConcreteSymbolEnumerator(std::move(WrappedClone)); + } + +private: + std::unique_ptr + make_concrete_child(std::unique_ptr Child) const { + ChildType *ConcreteChild = dyn_cast_or_null(Child.release()); + return std::unique_ptr(ConcreteChild); + } + + std::unique_ptr Enumerator; +}; +} + +#endif diff --git a/include/llvm/DebugInfo/PDB/DIA/DIADataStream.h b/include/llvm/DebugInfo/PDB/DIA/DIADataStream.h new file mode 100644 index 0000000..7b2bc14 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/DIA/DIADataStream.h @@ -0,0 +1,33 @@ +//===- DIADataStream.h - DIA implementation of IPDBDataStream ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_DIA_DIADATASTREAM_H +#define LLVM_DEBUGINFO_PDB_DIA_DIADATASTREAM_H + +#include "DIASupport.h" +#include "llvm/DebugInfo/PDB/IPDBDataStream.h" + +namespace llvm { +class DIADataStream : public IPDBDataStream { +public: + explicit DIADataStream(CComPtr DiaStreamData); + + uint32_t getRecordCount() const override; + std::string getName() const override; + llvm::Optional getItemAtIndex(uint32_t Index) const override; + bool getNext(RecordType &Record) override; + void reset() override; + DIADataStream *clone() const override; + +private: + CComPtr StreamData; +}; +} + +#endif diff --git a/include/llvm/DebugInfo/PDB/DIA/DIAEnumDebugStreams.h b/include/llvm/DebugInfo/PDB/DIA/DIAEnumDebugStreams.h new file mode 100644 index 0000000..375bcdd --- /dev/null +++ b/include/llvm/DebugInfo/PDB/DIA/DIAEnumDebugStreams.h @@ -0,0 +1,35 @@ +//==- DIAEnumDebugStreams.h - DIA Debug Stream Enumerator impl ---*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_DIA_DIAENUMDEBUGSTREAMS_H +#define LLVM_DEBUGINFO_PDB_DIA_DIAENUMDEBUGSTREAMS_H + +#include "DIASupport.h" +#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" + +namespace llvm { + +class IPDBDataStream; + +class DIAEnumDebugStreams : public IPDBEnumChildren { +public: + explicit DIAEnumDebugStreams(CComPtr DiaEnumerator); + + uint32_t getChildCount() const override; + ChildTypePtr getChildAtIndex(uint32_t Index) const override; + ChildTypePtr getNext() override; + void reset() override; + DIAEnumDebugStreams *clone() const override; + +private: + CComPtr Enumerator; +}; +} + +#endif diff --git a/include/llvm/DebugInfo/PDB/DIA/DIAEnumLineNumbers.h b/include/llvm/DebugInfo/PDB/DIA/DIAEnumLineNumbers.h new file mode 100644 index 0000000..4cc85ed --- /dev/null +++ b/include/llvm/DebugInfo/PDB/DIA/DIAEnumLineNumbers.h @@ -0,0 +1,35 @@ +//==- DIAEnumLineNumbers.h - DIA Line Number Enumerator impl -----*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_DIA_DIAENUMLINENUMBERS_H +#define LLVM_DEBUGINFO_PDB_DIA_DIAENUMLINENUMBERS_H + +#include "DIASupport.h" +#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" + +namespace llvm { + +class IPDBLineNumber; + +class DIAEnumLineNumbers : public IPDBEnumChildren { +public: + explicit DIAEnumLineNumbers(CComPtr DiaEnumerator); + + uint32_t getChildCount() const override; + ChildTypePtr getChildAtIndex(uint32_t Index) const override; + ChildTypePtr getNext() override; + void reset() override; + DIAEnumLineNumbers *clone() const override; + +private: + CComPtr Enumerator; +}; +} + +#endif diff --git a/include/llvm/DebugInfo/PDB/DIA/DIAEnumSourceFiles.h b/include/llvm/DebugInfo/PDB/DIA/DIAEnumSourceFiles.h new file mode 100644 index 0000000..88625f6 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/DIA/DIAEnumSourceFiles.h @@ -0,0 +1,37 @@ +//==- DIAEnumSourceFiles.h - DIA Source File Enumerator impl -----*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_DIA_DIAENUMSOURCEFILES_H +#define LLVM_DEBUGINFO_PDB_DIA_DIAENUMSOURCEFILES_H + +#include "DIASupport.h" +#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" + +namespace llvm { + +class DIASession; + +class DIAEnumSourceFiles : public IPDBEnumChildren { +public: + explicit DIAEnumSourceFiles(const DIASession &PDBSession, + CComPtr DiaEnumerator); + + uint32_t getChildCount() const override; + ChildTypePtr getChildAtIndex(uint32_t Index) const override; + ChildTypePtr getNext() override; + void reset() override; + DIAEnumSourceFiles *clone() const override; + +private: + const DIASession &Session; + CComPtr Enumerator; +}; +} + +#endif diff --git a/include/llvm/DebugInfo/PDB/DIA/DIAEnumSymbols.h b/include/llvm/DebugInfo/PDB/DIA/DIAEnumSymbols.h new file mode 100644 index 0000000..fe343f7 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/DIA/DIAEnumSymbols.h @@ -0,0 +1,37 @@ +//==- DIAEnumSymbols.h - DIA Symbol Enumerator impl --------------*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_DIA_DIAENUMSYMBOLS_H +#define LLVM_DEBUGINFO_PDB_DIA_DIAENUMSYMBOLS_H + +#include "DIASupport.h" +#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" + +namespace llvm { + +class DIASession; + +class DIAEnumSymbols : public IPDBEnumChildren { +public: + explicit DIAEnumSymbols(const DIASession &Session, + CComPtr DiaEnumerator); + + uint32_t getChildCount() const override; + std::unique_ptr getChildAtIndex(uint32_t Index) const override; + std::unique_ptr getNext() override; + void reset() override; + DIAEnumSymbols *clone() const override; + +private: + const DIASession &Session; + CComPtr Enumerator; +}; +} + +#endif diff --git a/include/llvm/DebugInfo/PDB/DIA/DIALineNumber.h b/include/llvm/DebugInfo/PDB/DIA/DIALineNumber.h new file mode 100644 index 0000000..5950a0d --- /dev/null +++ b/include/llvm/DebugInfo/PDB/DIA/DIALineNumber.h @@ -0,0 +1,39 @@ +//===- DIALineNumber.h - DIA implementation of IPDBLineNumber ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_DIA_DIALINENUMBER_H +#define LLVM_DEBUGINFO_PDB_DIA_DIALINENUMBER_H + +#include "DIASupport.h" +#include "llvm/DebugInfo/PDB/IPDBLineNumber.h" + +namespace llvm { +class DIALineNumber : public IPDBLineNumber { +public: + explicit DIALineNumber(CComPtr DiaLineNumber); + + uint32_t getLineNumber() const override; + uint32_t getLineNumberEnd() const override; + uint32_t getColumnNumber() const override; + uint32_t getColumnNumberEnd() const override; + uint32_t getAddressSection() const override; + uint32_t getAddressOffset() const override; + uint32_t getRelativeVirtualAddress() const override; + uint64_t getVirtualAddress() const override; + uint32_t getLength() const override; + uint32_t getSourceFileId() const override; + uint32_t getCompilandId() const override; + bool isStatement() const override; + +private: + CComPtr LineNumber; +}; +} + +#endif diff --git a/include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h b/include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h new file mode 100644 index 0000000..c71f35c --- /dev/null +++ b/include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h @@ -0,0 +1,206 @@ +//===- DIARawSymbol.h - DIA implementation of IPDBRawSymbol ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_DIA_DIARAWSYMBOL_H +#define LLVM_DEBUGINFO_PDB_DIA_DIARAWSYMBOL_H + +#include "DIASupport.h" +#include "llvm/DebugInfo/PDB/IPDBRawSymbol.h" + +namespace llvm { +class DIASession; +class DIARawSymbol : public IPDBRawSymbol { +public: + DIARawSymbol(const DIASession &PDBSession, CComPtr DiaSymbol); + + void dump(raw_ostream &OS, int Indent) const override; + + CComPtr getDiaSymbol() const { return Symbol; } + + std::unique_ptr + DIARawSymbol::findChildren(PDB_SymType Type) const override; + std::unique_ptr + findChildren(PDB_SymType Type, StringRef Name, + PDB_NameSearchFlags Flags) const override; + std::unique_ptr + findChildrenByRVA(PDB_SymType Type, StringRef Name, PDB_NameSearchFlags Flags, + uint32_t RVA) const override; + std::unique_ptr + findInlineFramesByRVA(uint32_t RVA) const override; + + void getDataBytes(llvm::SmallVector &bytes) const override; + void getFrontEndVersion(VersionInfo &Version) const override; + void getBackEndVersion(VersionInfo &Version) const override; + PDB_MemberAccess getAccess() const override; + uint32_t getAddressOffset() const override; + uint32_t getAddressSection() const override; + uint32_t getAge() const override; + uint32_t getArrayIndexTypeId() const override; + uint32_t getBaseDataOffset() const override; + uint32_t getBaseDataSlot() const override; + uint32_t getBaseSymbolId() const override; + PDB_BuiltinType getBuiltinType() const override; + uint32_t getBitPosition() const override; + PDB_CallingConv getCallingConvention() const override; + uint32_t getClassParentId() const override; + std::string getCompilerName() const override; + uint32_t getCount() const override; + uint32_t getCountLiveRanges() const override; + PDB_Lang getLanguage() const override; + uint32_t getLexicalParentId() const override; + std::string getLibraryName() const override; + uint32_t getLiveRangeStartAddressOffset() const override; + uint32_t getLiveRangeStartAddressSection() const override; + uint32_t getLiveRangeStartRelativeVirtualAddress() const override; + PDB_RegisterId getLocalBasePointerRegisterId() const override; + uint32_t getLowerBoundId() const override; + uint32_t getMemorySpaceKind() const override; + std::string getName() const override; + uint32_t getNumberOfAcceleratorPointerTags() const override; + uint32_t getNumberOfColumns() const override; + uint32_t getNumberOfModifiers() const override; + uint32_t getNumberOfRegisterIndices() const override; + uint32_t getNumberOfRows() const override; + std::string getObjectFileName() const override; + uint32_t getOemId() const override; + uint32_t getOemSymbolId() const override; + uint32_t getOffsetInUdt() const override; + PDB_Cpu getPlatform() const override; + uint32_t getRank() const override; + PDB_RegisterId getRegisterId() const override; + uint32_t getRegisterType() const override; + uint32_t getRelativeVirtualAddress() const override; + uint32_t getSamplerSlot() const override; + uint32_t getSignature() const override; + uint32_t getSizeInUdt() const override; + uint32_t getSlot() const override; + std::string getSourceFileName() const override; + uint32_t getStride() const override; + uint32_t getSubTypeId() const override; + std::string getSymbolsFileName() const override; + uint32_t getSymIndexId() const override; + uint32_t getTargetOffset() const override; + uint32_t getTargetRelativeVirtualAddress() const override; + uint64_t getTargetVirtualAddress() const override; + uint32_t getTargetSection() const override; + uint32_t getTextureSlot() const override; + uint32_t getTimeStamp() const override; + uint32_t getToken() const override; + uint32_t getTypeId() const override; + uint32_t getUavSlot() const override; + std::string getUndecoratedName() const override; + uint32_t getUnmodifiedTypeId() const override; + uint32_t getUpperBoundId() const override; + Variant getValue() const override; + uint32_t getVirtualBaseDispIndex() const override; + uint32_t getVirtualBaseOffset() const override; + uint32_t getVirtualTableShapeId() const override; + PDB_DataKind getDataKind() const override; + PDB_SymType getSymTag() const override; + PDB_UniqueId getGuid() const override; + int32_t getOffset() const override; + int32_t getThisAdjust() const override; + int32_t getVirtualBasePointerOffset() const override; + PDB_LocType getLocationType() const override; + PDB_Machine getMachineType() const override; + PDB_ThunkOrdinal getThunkOrdinal() const override; + uint64_t getLength() const override; + uint64_t getLiveRangeLength() const override; + uint64_t getVirtualAddress() const override; + PDB_UdtType getUdtKind() const override; + bool hasConstructor() const override; + bool hasCustomCallingConvention() const override; + bool hasFarReturn() const override; + bool isCode() const override; + bool isCompilerGenerated() const override; + bool isConstType() const override; + bool isEditAndContinueEnabled() const override; + bool isFunction() const override; + bool getAddressTaken() const override; + bool getNoStackOrdering() const override; + bool hasAlloca() const override; + bool hasAssignmentOperator() const override; + bool hasCTypes() const override; + bool hasCastOperator() const override; + bool hasDebugInfo() const override; + bool hasEH() const override; + bool hasEHa() const override; + bool hasInlAsm() const override; + bool hasInlineAttribute() const override; + bool hasInterruptReturn() const override; + bool hasFramePointer() const override; + bool hasLongJump() const override; + bool hasManagedCode() const override; + bool hasNestedTypes() const override; + bool hasNoInlineAttribute() const override; + bool hasNoReturnAttribute() const override; + bool hasOptimizedCodeDebugInfo() const override; + bool hasOverloadedOperator() const override; + bool hasSEH() const override; + bool hasSecurityChecks() const override; + bool hasSetJump() const override; + bool hasStrictGSCheck() const override; + bool isAcceleratorGroupSharedLocal() const override; + bool isAcceleratorPointerTagLiveRange() const override; + bool isAcceleratorStubFunction() const override; + bool isAggregated() const override; + bool isIntroVirtualFunction() const override; + bool isCVTCIL() const override; + bool isConstructorVirtualBase() const override; + bool isCxxReturnUdt() const override; + bool isDataAligned() const override; + bool isHLSLData() const override; + bool isHotpatchable() const override; + bool isIndirectVirtualBaseClass() const override; + bool isInterfaceUdt() const override; + bool isIntrinsic() const override; + bool isLTCG() const override; + bool isLocationControlFlowDependent() const override; + bool isMSILNetmodule() const override; + bool isMatrixRowMajor() const override; + bool isManagedCode() const override; + bool isMSILCode() const override; + bool isMultipleInheritance() const override; + bool isNaked() const override; + bool isNested() const override; + bool isOptimizedAway() const override; + bool isPacked() const override; + bool isPointerBasedOnSymbolValue() const override; + bool isPointerToDataMember() const override; + bool isPointerToMemberFunction() const override; + bool isPureVirtual() const override; + bool isRValueReference() const override; + bool isRefUdt() const override; + bool isReference() const override; + bool isRestrictedType() const override; + bool isReturnValue() const override; + bool isSafeBuffers() const override; + bool isScoped() const override; + bool isSdl() const override; + bool isSingleInheritance() const override; + bool isSplitted() const override; + bool isStatic() const override; + bool hasPrivateSymbols() const override; + bool isUnalignedType() const override; + bool isUnreached() const override; + bool isValueUdt() const override; + bool isVirtual() const override; + bool isVirtualBaseClass() const override; + bool isVirtualInheritance() const override; + bool isVolatileType() const override; + bool wasInlined() const override; + std::string getUnused() const override; + +private: + const DIASession &Session; + CComPtr Symbol; +}; +} + +#endif diff --git a/include/llvm/DebugInfo/PDB/DIA/DIASession.h b/include/llvm/DebugInfo/PDB/DIA/DIASession.h new file mode 100644 index 0000000..141b9b0 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/DIA/DIASession.h @@ -0,0 +1,42 @@ +//===- DIASession.h - DIA implementation of IPDBSession ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_DIA_DIASESSION_H +#define LLVM_DEBUGINFO_PDB_DIA_DIASESSION_H + +#include "DIASupport.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/DebugInfo/PDB/IPDBSession.h" + +namespace llvm { +class DIASession : public IPDBSession { +public: + explicit DIASession(CComPtr DiaSession); + + static DIASession *createFromPdb(StringRef Path); + + uint64_t getLoadAddress() const override; + void setLoadAddress(uint64_t Address) override; + std::unique_ptr getGlobalScope() const override; + std::unique_ptr getSymbolById(uint32_t SymbolId) const override; + + std::unique_ptr getAllSourceFiles() const override; + std::unique_ptr getSourceFilesForCompiland( + const PDBSymbolCompiland &Compiland) const override; + std::unique_ptr + getSourceFileById(uint32_t FileId) const override; + + std::unique_ptr getDebugStreams() const override; + +private: + CComPtr Session; +}; +} + +#endif diff --git a/include/llvm/DebugInfo/PDB/DIA/DIASourceFile.h b/include/llvm/DebugInfo/PDB/DIA/DIASourceFile.h new file mode 100644 index 0000000..c424e27 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/DIA/DIASourceFile.h @@ -0,0 +1,36 @@ +//===- DIASourceFile.h - DIA implementation of IPDBSourceFile ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_DIA_DIASOURCEFILE_H +#define LLVM_DEBUGINFO_PDB_DIA_DIASOURCEFILE_H + +#include "DIASupport.h" +#include "llvm/DebugInfo/PDB/IPDBSourceFile.h" + +namespace llvm { +class DIASession; + +class DIASourceFile : public IPDBSourceFile { +public: + explicit DIASourceFile(const DIASession &Session, + CComPtr DiaSourceFile); + + std::string getFileName() const override; + uint32_t getUniqueId() const override; + std::string getChecksum() const override; + PDB_Checksum getChecksumType() const override; + std::unique_ptr getCompilands() const override; + +private: + const DIASession &Session; + CComPtr SourceFile; +}; +} + +#endif diff --git a/include/llvm/DebugInfo/PDB/DIA/DIASupport.h b/include/llvm/DebugInfo/PDB/DIA/DIASupport.h new file mode 100644 index 0000000..407a345 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/DIA/DIASupport.h @@ -0,0 +1,33 @@ +//===- DIASupport.h - Common header includes for DIA ------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Common defines and header includes for all LLVMDebugInfoPDBDIA. The +// definitions here configure the necessary #defines and include system headers +// in the proper order for using DIA. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_DIA_DIASUPPORT_H +#define LLVM_DEBUGINFO_PDB_DIA_DIASUPPORT_H + +// Require at least Vista +#define NTDDI_VERSION NTDDI_VISTA +#define _WIN32_WINNT _WIN32_WINNT_VISTA +#define WINVER _WIN32_WINNT_VISTA +#ifndef NOMINMAX +#define NOMINMAX +#endif + +// atlbase.h has to come before windows.h +#include +#include + +// DIA headers must come after windows headers. +#include +#include + +#endif // LLVM_DEBUGINFO_PDB_DIA_DIASUPPORT_H diff --git a/include/llvm/DebugInfo/PDB/IPDBDataStream.h b/include/llvm/DebugInfo/PDB/IPDBDataStream.h new file mode 100644 index 0000000..808a0f3 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/IPDBDataStream.h @@ -0,0 +1,37 @@ +//===- IPDBDataStream.h - base interface for child enumerator -*- C++ ---*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_IPDBDATASTREAM_H +#define LLVM_DEBUGINFO_PDB_IPDBDATASTREAM_H + +#include "PDBTypes.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/SmallVector.h" + +namespace llvm { + +/// IPDBDataStream defines an interface used to represent a stream consisting +/// of a name and a series of records whose formats depend on the particular +/// stream type. +class IPDBDataStream { +public: + typedef llvm::SmallVector RecordType; + + virtual ~IPDBDataStream(); + + virtual uint32_t getRecordCount() const = 0; + virtual std::string getName() const = 0; + virtual llvm::Optional getItemAtIndex(uint32_t Index) const = 0; + virtual bool getNext(RecordType &Record) = 0; + virtual void reset() = 0; + virtual IPDBDataStream *clone() const = 0; +}; +} + +#endif diff --git a/include/llvm/DebugInfo/PDB/IPDBEnumChildren.h b/include/llvm/DebugInfo/PDB/IPDBEnumChildren.h new file mode 100644 index 0000000..645ac96 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/IPDBEnumChildren.h @@ -0,0 +1,33 @@ +//===- IPDBEnumChildren.h - base interface for child enumerator -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_IPDBENUMCHILDREN_H +#define LLVM_DEBUGINFO_PDB_IPDBENUMCHILDREN_H + +#include "PDBTypes.h" +#include + +namespace llvm { + +template class IPDBEnumChildren { +public: + typedef std::unique_ptr ChildTypePtr; + typedef IPDBEnumChildren MyType; + + virtual ~IPDBEnumChildren() {} + + virtual uint32_t getChildCount() const = 0; + virtual ChildTypePtr getChildAtIndex(uint32_t Index) const = 0; + virtual ChildTypePtr getNext() = 0; + virtual void reset() = 0; + virtual MyType *clone() const = 0; +}; +} + +#endif diff --git a/include/llvm/DebugInfo/PDB/IPDBLineNumber.h b/include/llvm/DebugInfo/PDB/IPDBLineNumber.h new file mode 100644 index 0000000..92cd58d --- /dev/null +++ b/include/llvm/DebugInfo/PDB/IPDBLineNumber.h @@ -0,0 +1,36 @@ +//===- IPDBLineNumber.h - base interface for PDB line no. info ---*- C++-*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_IPDBLINENUMBER_H +#define LLVM_DEBUGINFO_PDB_IPDBLINENUMBER_H + +#include "PDBTypes.h" + +namespace llvm { + +class IPDBLineNumber { +public: + virtual ~IPDBLineNumber(); + + virtual uint32_t getLineNumber() const = 0; + virtual uint32_t getLineNumberEnd() const = 0; + virtual uint32_t getColumnNumber() const = 0; + virtual uint32_t getColumnNumberEnd() const = 0; + virtual uint32_t getAddressSection() const = 0; + virtual uint32_t getAddressOffset() const = 0; + virtual uint32_t getRelativeVirtualAddress() const = 0; + virtual uint64_t getVirtualAddress() const = 0; + virtual uint32_t getLength() const = 0; + virtual uint32_t getSourceFileId() const = 0; + virtual uint32_t getCompilandId() const = 0; + virtual bool isStatement() const = 0; +}; +} + +#endif diff --git a/include/llvm/DebugInfo/PDB/IPDBRawSymbol.h b/include/llvm/DebugInfo/PDB/IPDBRawSymbol.h new file mode 100644 index 0000000..139bff5 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/IPDBRawSymbol.h @@ -0,0 +1,211 @@ +//===- IPDBRawSymbol.h - base interface for PDB symbol types ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_IPDBRAWSYMBOL_H +#define LLVM_DEBUGINFO_PDB_IPDBRAWSYMBOL_H + +#include "PDBTypes.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include + +namespace llvm { + +class raw_ostream; + +/// IPDBRawSymbol defines an interface used to represent an arbitrary symbol. +/// It exposes a monolithic interface consisting of accessors for the union of +/// all properties that are valid for any symbol type. This interface is then +/// wrapped by a concrete class which exposes only those set of methods valid +/// for this particular symbol type. See PDBSymbol.h for more details. +class IPDBRawSymbol { +public: + virtual ~IPDBRawSymbol(); + + virtual void dump(raw_ostream &OS, int Indent) const = 0; + + virtual std::unique_ptr + findChildren(PDB_SymType Type) const = 0; + + virtual std::unique_ptr + findChildren(PDB_SymType Type, StringRef Name, + PDB_NameSearchFlags Flags) const = 0; + virtual std::unique_ptr + findChildrenByRVA(PDB_SymType Type, StringRef Name, PDB_NameSearchFlags Flags, + uint32_t RVA) const = 0; + virtual std::unique_ptr + findInlineFramesByRVA(uint32_t RVA) const = 0; + + virtual void getDataBytes(llvm::SmallVector &bytes) const = 0; + virtual void getBackEndVersion(VersionInfo &Version) const = 0; + virtual PDB_MemberAccess getAccess() const = 0; + virtual uint32_t getAddressOffset() const = 0; + virtual uint32_t getAddressSection() const = 0; + virtual uint32_t getAge() const = 0; + virtual uint32_t getArrayIndexTypeId() const = 0; + virtual uint32_t getBaseDataOffset() const = 0; + virtual uint32_t getBaseDataSlot() const = 0; + virtual uint32_t getBaseSymbolId() const = 0; + virtual PDB_BuiltinType getBuiltinType() const = 0; + virtual uint32_t getBitPosition() const = 0; + virtual PDB_CallingConv getCallingConvention() const = 0; + virtual uint32_t getClassParentId() const = 0; + virtual std::string getCompilerName() const = 0; + virtual uint32_t getCount() const = 0; + virtual uint32_t getCountLiveRanges() const = 0; + virtual void getFrontEndVersion(VersionInfo &Version) const = 0; + virtual PDB_Lang getLanguage() const = 0; + virtual uint32_t getLexicalParentId() const = 0; + virtual std::string getLibraryName() const = 0; + virtual uint32_t getLiveRangeStartAddressOffset() const = 0; + virtual uint32_t getLiveRangeStartAddressSection() const = 0; + virtual uint32_t getLiveRangeStartRelativeVirtualAddress() const = 0; + virtual PDB_RegisterId getLocalBasePointerRegisterId() const = 0; + virtual uint32_t getLowerBoundId() const = 0; + virtual uint32_t getMemorySpaceKind() const = 0; + virtual std::string getName() const = 0; + virtual uint32_t getNumberOfAcceleratorPointerTags() const = 0; + virtual uint32_t getNumberOfColumns() const = 0; + virtual uint32_t getNumberOfModifiers() const = 0; + virtual uint32_t getNumberOfRegisterIndices() const = 0; + virtual uint32_t getNumberOfRows() const = 0; + virtual std::string getObjectFileName() const = 0; + virtual uint32_t getOemId() const = 0; + virtual uint32_t getOemSymbolId() const = 0; + virtual uint32_t getOffsetInUdt() const = 0; + virtual PDB_Cpu getPlatform() const = 0; + virtual uint32_t getRank() const = 0; + virtual PDB_RegisterId getRegisterId() const = 0; + virtual uint32_t getRegisterType() const = 0; + virtual uint32_t getRelativeVirtualAddress() const = 0; + virtual uint32_t getSamplerSlot() const = 0; + virtual uint32_t getSignature() const = 0; + virtual uint32_t getSizeInUdt() const = 0; + virtual uint32_t getSlot() const = 0; + virtual std::string getSourceFileName() const = 0; + virtual uint32_t getStride() const = 0; + virtual uint32_t getSubTypeId() const = 0; + virtual std::string getSymbolsFileName() const = 0; + virtual uint32_t getSymIndexId() const = 0; + virtual uint32_t getTargetOffset() const = 0; + virtual uint32_t getTargetRelativeVirtualAddress() const = 0; + virtual uint64_t getTargetVirtualAddress() const = 0; + virtual uint32_t getTargetSection() const = 0; + virtual uint32_t getTextureSlot() const = 0; + virtual uint32_t getTimeStamp() const = 0; + virtual uint32_t getToken() const = 0; + virtual uint32_t getTypeId() const = 0; + virtual uint32_t getUavSlot() const = 0; + virtual std::string getUndecoratedName() const = 0; + virtual uint32_t getUnmodifiedTypeId() const = 0; + virtual uint32_t getUpperBoundId() const = 0; + virtual Variant getValue() const = 0; + virtual uint32_t getVirtualBaseDispIndex() const = 0; + virtual uint32_t getVirtualBaseOffset() const = 0; + virtual uint32_t getVirtualTableShapeId() const = 0; + virtual PDB_DataKind getDataKind() const = 0; + virtual PDB_SymType getSymTag() const = 0; + virtual PDB_UniqueId getGuid() const = 0; + virtual int32_t getOffset() const = 0; + virtual int32_t getThisAdjust() const = 0; + virtual int32_t getVirtualBasePointerOffset() const = 0; + virtual PDB_LocType getLocationType() const = 0; + virtual PDB_Machine getMachineType() const = 0; + virtual PDB_ThunkOrdinal getThunkOrdinal() const = 0; + virtual uint64_t getLength() const = 0; + virtual uint64_t getLiveRangeLength() const = 0; + virtual uint64_t getVirtualAddress() const = 0; + virtual PDB_UdtType getUdtKind() const = 0; + virtual bool hasConstructor() const = 0; + virtual bool hasCustomCallingConvention() const = 0; + virtual bool hasFarReturn() const = 0; + virtual bool isCode() const = 0; + virtual bool isCompilerGenerated() const = 0; + virtual bool isConstType() const = 0; + virtual bool isEditAndContinueEnabled() const = 0; + virtual bool isFunction() const = 0; + virtual bool getAddressTaken() const = 0; + virtual bool getNoStackOrdering() const = 0; + virtual bool hasAlloca() const = 0; + virtual bool hasAssignmentOperator() const = 0; + virtual bool hasCTypes() const = 0; + virtual bool hasCastOperator() const = 0; + virtual bool hasDebugInfo() const = 0; + virtual bool hasEH() const = 0; + virtual bool hasEHa() const = 0; + virtual bool hasFramePointer() const = 0; + virtual bool hasInlAsm() const = 0; + virtual bool hasInlineAttribute() const = 0; + virtual bool hasInterruptReturn() const = 0; + virtual bool hasLongJump() const = 0; + virtual bool hasManagedCode() const = 0; + virtual bool hasNestedTypes() const = 0; + virtual bool hasNoInlineAttribute() const = 0; + virtual bool hasNoReturnAttribute() const = 0; + virtual bool hasOptimizedCodeDebugInfo() const = 0; + virtual bool hasOverloadedOperator() const = 0; + virtual bool hasSEH() const = 0; + virtual bool hasSecurityChecks() const = 0; + virtual bool hasSetJump() const = 0; + virtual bool hasStrictGSCheck() const = 0; + virtual bool isAcceleratorGroupSharedLocal() const = 0; + virtual bool isAcceleratorPointerTagLiveRange() const = 0; + virtual bool isAcceleratorStubFunction() const = 0; + virtual bool isAggregated() const = 0; + virtual bool isIntroVirtualFunction() const = 0; + virtual bool isCVTCIL() const = 0; + virtual bool isConstructorVirtualBase() const = 0; + virtual bool isCxxReturnUdt() const = 0; + virtual bool isDataAligned() const = 0; + virtual bool isHLSLData() const = 0; + virtual bool isHotpatchable() const = 0; + virtual bool isIndirectVirtualBaseClass() const = 0; + virtual bool isInterfaceUdt() const = 0; + virtual bool isIntrinsic() const = 0; + virtual bool isLTCG() const = 0; + virtual bool isLocationControlFlowDependent() const = 0; + virtual bool isMSILNetmodule() const = 0; + virtual bool isMatrixRowMajor() const = 0; + virtual bool isManagedCode() const = 0; + virtual bool isMSILCode() const = 0; + virtual bool isMultipleInheritance() const = 0; + virtual bool isNaked() const = 0; + virtual bool isNested() const = 0; + virtual bool isOptimizedAway() const = 0; + virtual bool isPacked() const = 0; + virtual bool isPointerBasedOnSymbolValue() const = 0; + virtual bool isPointerToDataMember() const = 0; + virtual bool isPointerToMemberFunction() const = 0; + virtual bool isPureVirtual() const = 0; + virtual bool isRValueReference() const = 0; + virtual bool isRefUdt() const = 0; + virtual bool isReference() const = 0; + virtual bool isRestrictedType() const = 0; + virtual bool isReturnValue() const = 0; + virtual bool isSafeBuffers() const = 0; + virtual bool isScoped() const = 0; + virtual bool isSdl() const = 0; + virtual bool isSingleInheritance() const = 0; + virtual bool isSplitted() const = 0; + virtual bool isStatic() const = 0; + virtual bool hasPrivateSymbols() const = 0; + virtual bool isUnalignedType() const = 0; + virtual bool isUnreached() const = 0; + virtual bool isValueUdt() const = 0; + virtual bool isVirtual() const = 0; + virtual bool isVirtualBaseClass() const = 0; + virtual bool isVirtualInheritance() const = 0; + virtual bool isVolatileType() const = 0; + virtual bool wasInlined() const = 0; + virtual std::string getUnused() const = 0; +}; + +} // namespace llvm + +#endif diff --git a/include/llvm/DebugInfo/PDB/IPDBSession.h b/include/llvm/DebugInfo/PDB/IPDBSession.h new file mode 100644 index 0000000..60d6f62 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/IPDBSession.h @@ -0,0 +1,56 @@ +//===- IPDBSession.h - base interface for a PDB symbol context --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_IPDBSESSION_H +#define LLVM_DEBUGINFO_PDB_IPDBSESSION_H + +#include "PDBTypes.h" +#include "llvm/Support/Casting.h" +#include + +namespace llvm { + +class PDBSymbolCompiland; +class PDBSymbolExe; + +/// IPDBSession defines an interface used to provide a context for querying +/// debug information from a debug data source (for example, a PDB). +class IPDBSession { +public: + virtual ~IPDBSession(); + + virtual uint64_t getLoadAddress() const = 0; + virtual void setLoadAddress(uint64_t Address) = 0; + virtual std::unique_ptr getGlobalScope() const = 0; + virtual std::unique_ptr getSymbolById(uint32_t SymbolId) const = 0; + + template + std::unique_ptr getConcreteSymbolById(uint32_t SymbolId) const { + auto Symbol(getSymbolById(SymbolId)); + if (!Symbol) + return nullptr; + + T *ConcreteSymbol = dyn_cast(Symbol.get()); + if (!ConcreteSymbol) + return nullptr; + Symbol.release(); + return std::unique_ptr(ConcreteSymbol); + } + + virtual std::unique_ptr getAllSourceFiles() const = 0; + virtual std::unique_ptr + getSourceFilesForCompiland(const PDBSymbolCompiland &Compiland) const = 0; + virtual std::unique_ptr + getSourceFileById(uint32_t FileId) const = 0; + + virtual std::unique_ptr getDebugStreams() const = 0; +}; +} + +#endif diff --git a/include/llvm/DebugInfo/PDB/IPDBSourceFile.h b/include/llvm/DebugInfo/PDB/IPDBSourceFile.h new file mode 100644 index 0000000..55000ef --- /dev/null +++ b/include/llvm/DebugInfo/PDB/IPDBSourceFile.h @@ -0,0 +1,37 @@ +//===- IPDBSourceFile.h - base interface for a PDB source file --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_IPDBSOURCEFILE_H +#define LLVM_DEBUGINFO_PDB_IPDBSOURCEFILE_H + +#include "PDBTypes.h" +#include +#include + +namespace llvm { + +class raw_ostream; + +/// IPDBSourceFile defines an interface used to represent source files whose +/// information are stored in the PDB. +class IPDBSourceFile { +public: + virtual ~IPDBSourceFile(); + + void dump(raw_ostream &OS, int Indent) const; + + virtual std::string getFileName() const = 0; + virtual uint32_t getUniqueId() const = 0; + virtual std::string getChecksum() const = 0; + virtual PDB_Checksum getChecksumType() const = 0; + virtual std::unique_ptr getCompilands() const = 0; +}; +} + +#endif diff --git a/include/llvm/DebugInfo/PDB/PDB.h b/include/llvm/DebugInfo/PDB/PDB.h new file mode 100644 index 0000000..7193eef --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDB.h @@ -0,0 +1,23 @@ +//===- PDB.h - base header file for creating a PDB reader -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_PDB_H +#define LLVM_DEBUGINFO_PDB_PDB_H + +#include "PDBTypes.h" +#include + +namespace llvm { +class StringRef; + +std::unique_ptr createPDBReader(PDB_ReaderType Type, + StringRef Path); +} + +#endif diff --git a/include/llvm/DebugInfo/PDB/PDBExtras.h b/include/llvm/DebugInfo/PDB/PDBExtras.h new file mode 100644 index 0000000..cbbe171 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBExtras.h @@ -0,0 +1,37 @@ +//===- PDBExtras.h - helper functions and classes for PDBs -------*- C++-*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_PDBEXTRAS_H +#define LLVM_DEBUGINFO_PDB_PDBEXTRAS_H + +#include "PDBTypes.h" +#include "llvm/Support/raw_ostream.h" +#include + +namespace llvm { +typedef std::unordered_map TagStats; + +raw_ostream &operator<<(raw_ostream &OS, const PDB_VariantType &Value); +raw_ostream &operator<<(raw_ostream &OS, const PDB_CallingConv &Conv); +raw_ostream &operator<<(raw_ostream &OS, const PDB_DataKind &Data); +raw_ostream &operator<<(raw_ostream &OS, const PDB_RegisterId &Reg); +raw_ostream &operator<<(raw_ostream &OS, const PDB_LocType &Loc); +raw_ostream &operator<<(raw_ostream &OS, const PDB_ThunkOrdinal &Thunk); +raw_ostream &operator<<(raw_ostream &OS, const PDB_Checksum &Checksum); +raw_ostream &operator<<(raw_ostream &OS, const PDB_Lang &Lang); +raw_ostream &operator<<(raw_ostream &OS, const PDB_SymType &Tag); +raw_ostream &operator<<(raw_ostream &OS, const PDB_BuiltinType &Type); +raw_ostream &operator<<(raw_ostream &OS, const PDB_UniqueId &Id); + +raw_ostream &operator<<(raw_ostream &OS, const Variant &Value); +raw_ostream &operator<<(raw_ostream &OS, const VersionInfo &Version); +raw_ostream &operator<<(raw_ostream &OS, const TagStats &Stats); +} + +#endif diff --git a/include/llvm/DebugInfo/PDB/PDBSymDumper.h b/include/llvm/DebugInfo/PDB/PDBSymDumper.h new file mode 100644 index 0000000..dee601c --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymDumper.h @@ -0,0 +1,85 @@ +//===- PDBSymDumper.h - base interface for PDB symbol dumper *- C++ -----*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_PDBSYMDUMPER_H +#define LLVM_DEBUGINFO_PDB_PDBSYMDUMPER_H + +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +class PDBSymDumper { +public: + PDBSymDumper(bool ShouldRequireImpl); + virtual ~PDBSymDumper(); + + virtual void dump(const PDBSymbolAnnotation &Symbol, raw_ostream &OS, + int Indent); + virtual void dump(const PDBSymbolBlock &Symbol, raw_ostream &OS, int Indent); + virtual void dump(const PDBSymbolCompiland &Symbol, raw_ostream &OS, + int Indent); + virtual void dump(const PDBSymbolCompilandDetails &Symbol, raw_ostream &OS, + int Indent); + virtual void dump(const PDBSymbolCompilandEnv &Symbol, raw_ostream &OS, + int Indent); + virtual void dump(const PDBSymbolCustom &Symbol, raw_ostream &OS, int Indent); + virtual void dump(const PDBSymbolData &Symbol, raw_ostream &OS, int Indent); + virtual void dump(const PDBSymbolExe &Symbol, raw_ostream &OS, int Indent); + virtual void dump(const PDBSymbolFunc &Symbol, raw_ostream &OS, int Indent); + virtual void dump(const PDBSymbolFuncDebugEnd &Symbol, raw_ostream &OS, + int Indent); + virtual void dump(const PDBSymbolFuncDebugStart &Symbol, raw_ostream &OS, + int Indent); + virtual void dump(const PDBSymbolLabel &Symbol, raw_ostream &OS, int Indent); + virtual void dump(const PDBSymbolPublicSymbol &Symbol, raw_ostream &OS, + int Indent); + virtual void dump(const PDBSymbolThunk &Symbol, raw_ostream &OS, int Indent); + virtual void dump(const PDBSymbolTypeArray &Symbol, raw_ostream &OS, + int Indent); + virtual void dump(const PDBSymbolTypeBaseClass &Symbol, raw_ostream &OS, + int Indent); + virtual void dump(const PDBSymbolTypeBuiltin &Symbol, raw_ostream &OS, + int Indent); + virtual void dump(const PDBSymbolTypeCustom &Symbol, raw_ostream &OS, + int Indent); + virtual void dump(const PDBSymbolTypeDimension &Symbol, raw_ostream &OS, + int Indent); + virtual void dump(const PDBSymbolTypeEnum &Symbol, raw_ostream &OS, + int Indent); + virtual void dump(const PDBSymbolTypeFriend &Symbol, raw_ostream &OS, + int Indent); + virtual void dump(const PDBSymbolTypeFunctionArg &Symbol, raw_ostream &OS, + int Indent); + virtual void dump(const PDBSymbolTypeFunctionSig &Symbol, raw_ostream &OS, + int Indent); + virtual void dump(const PDBSymbolTypeManaged &Symbol, raw_ostream &OS, + int Indent); + virtual void dump(const PDBSymbolTypePointer &Symbol, raw_ostream &OS, + int Indent); + virtual void dump(const PDBSymbolTypeTypedef &Symbol, raw_ostream &OS, + int Indent); + virtual void dump(const PDBSymbolTypeUDT &Symbol, raw_ostream &OS, + int Indent); + virtual void dump(const PDBSymbolTypeVTable &Symbol, raw_ostream &OS, + int Indent); + virtual void dump(const PDBSymbolTypeVTableShape &Symbol, raw_ostream &OS, + int Indent); + virtual void dump(const PDBSymbolUnknown &Symbol, raw_ostream &OS, + int Indent); + virtual void dump(const PDBSymbolUsingNamespace &Symbol, raw_ostream &OS, + int Indent); + +private: + bool RequireImpl; +}; +} + +#endif diff --git a/include/llvm/DebugInfo/PDB/PDBSymbol.h b/include/llvm/DebugInfo/PDB/PDBSymbol.h new file mode 100644 index 0000000..36005eb --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbol.h @@ -0,0 +1,98 @@ +//===- PDBSymbol.h - base class for user-facing symbol types -----*- C++-*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_IPDBSYMBOL_H +#define LLVM_DEBUGINFO_PDB_IPDBSYMBOL_H + +#include "ConcreteSymbolEnumerator.h" +#include "IPDBRawSymbol.h" +#include "PDBExtras.h" +#include "PDBTypes.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Casting.h" +#include + +#define FORWARD_SYMBOL_METHOD(MethodName) \ + auto MethodName() const->decltype(RawSymbol->MethodName()) { \ + return RawSymbol->MethodName(); \ + } + +namespace llvm { + +class IPDBRawSymbol; +class raw_ostream; + +#define DECLARE_PDB_SYMBOL_CONCRETE_TYPE(TagValue) \ + static const PDB_SymType Tag = TagValue; \ + static bool classof(const PDBSymbol *S) { return S->getSymTag() == Tag; } + +/// PDBSymbol defines the base of the inheritance hierarchy for concrete symbol +/// types (e.g. functions, executables, vtables, etc). All concrete symbol +/// types inherit from PDBSymbol and expose the exact set of methods that are +/// valid for that particular symbol type, as described in the Microsoft +/// reference "Lexical and Class Hierarchy of Symbol Types": +/// https://msdn.microsoft.com/en-us/library/370hs6k4.aspx +class PDBSymbol { +protected: + PDBSymbol(const IPDBSession &PDBSession, std::unique_ptr Symbol); + +public: + static std::unique_ptr + create(const IPDBSession &PDBSession, std::unique_ptr Symbol); + + virtual ~PDBSymbol(); + + /// Dumps the contents of a symbol a raw_ostream. By default this will just + /// call dump() on the underlying RawSymbol, which allows us to discover + /// unknown properties, but individual implementations of PDBSymbol may + /// override the behavior to only dump known fields. + virtual void dump(raw_ostream &OS, int Indent, + PDBSymDumper &Dumper) const = 0; + void defaultDump(raw_ostream &OS, int Indent) const; + + PDB_SymType getSymTag() const; + + template std::unique_ptr findOneChild() const { + auto Enumerator(findAllChildren()); + return Enumerator->getNext(); + } + + template + std::unique_ptr> findAllChildren() const { + auto BaseIter = RawSymbol->findChildren(T::Tag); + return llvm::make_unique>(std::move(BaseIter)); + } + std::unique_ptr findAllChildren(PDB_SymType Type) const; + std::unique_ptr findAllChildren() const; + + std::unique_ptr + findChildren(PDB_SymType Type, StringRef Name, + PDB_NameSearchFlags Flags) const; + std::unique_ptr findChildrenByRVA(PDB_SymType Type, + StringRef Name, + PDB_NameSearchFlags Flags, + uint32_t RVA) const; + std::unique_ptr findInlineFramesByRVA(uint32_t RVA) const; + + const IPDBRawSymbol &getRawSymbol() const { return *RawSymbol; } + IPDBRawSymbol &getRawSymbol() { return *RawSymbol; } + + const IPDBSession &getSession() const { return Session; } + + std::unique_ptr getChildStats(TagStats &Stats) const; + +protected: + const IPDBSession &Session; + const std::unique_ptr RawSymbol; +}; + +} // namespace llvm + +#endif diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolAnnotation.h b/include/llvm/DebugInfo/PDB/PDBSymbolAnnotation.h new file mode 100644 index 0000000..347e30a --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolAnnotation.h @@ -0,0 +1,39 @@ +//===- PDBSymbolAnnotation.h - Accessors for querying PDB annotations ---*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLANNOTATION_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLANNOTATION_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" +#include + +namespace llvm { + +class raw_ostream; + +class PDBSymbolAnnotation : public PDBSymbol { +public: + PDBSymbolAnnotation(const IPDBSession &PDBSession, + std::unique_ptr Symbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Annotation) + + void dump(raw_ostream &OS, int Indent, PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getAddressOffset) + FORWARD_SYMBOL_METHOD(getAddressSection) + FORWARD_SYMBOL_METHOD(getDataKind) + FORWARD_SYMBOL_METHOD(getRelativeVirtualAddress) + FORWARD_SYMBOL_METHOD(getSymIndexId) + // FORWARD_SYMBOL_METHOD(getValue) + FORWARD_SYMBOL_METHOD(getVirtualAddress) +}; +} + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLANNOTATION_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolBlock.h b/include/llvm/DebugInfo/PDB/PDBSymbolBlock.h new file mode 100644 index 0000000..a0091be --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolBlock.h @@ -0,0 +1,41 @@ +//===- PDBSymbolBlock.h - Accessors for querying PDB blocks -------------*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLBLOCK_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLBLOCK_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" +#include + +namespace llvm { + +class raw_ostream; + +class PDBSymbolBlock : public PDBSymbol { +public: + PDBSymbolBlock(const IPDBSession &PDBSession, + std::unique_ptr Symbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Block) + + void dump(raw_ostream &OS, int Indent, PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getAddressOffset) + FORWARD_SYMBOL_METHOD(getAddressSection) + FORWARD_SYMBOL_METHOD(getLength) + FORWARD_SYMBOL_METHOD(getLexicalParentId) + FORWARD_SYMBOL_METHOD(getLocationType) + FORWARD_SYMBOL_METHOD(getName) + FORWARD_SYMBOL_METHOD(getRelativeVirtualAddress) + FORWARD_SYMBOL_METHOD(getSymIndexId) + FORWARD_SYMBOL_METHOD(getVirtualAddress) +}; +} + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLBLOCK_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolCompiland.h b/include/llvm/DebugInfo/PDB/PDBSymbolCompiland.h new file mode 100644 index 0000000..055e444 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolCompiland.h @@ -0,0 +1,38 @@ +//===- PDBSymbolCompiland.h - Accessors for querying PDB compilands -----*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLCOMPILAND_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLCOMPILAND_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" +#include + +namespace llvm { + +class raw_ostream; + +class PDBSymbolCompiland : public PDBSymbol { +public: + PDBSymbolCompiland(const IPDBSession &PDBSession, + std::unique_ptr CompilandSymbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Compiland) + + void dump(raw_ostream &OS, int Indent, PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(isEditAndContinueEnabled) + FORWARD_SYMBOL_METHOD(getLexicalParentId) + FORWARD_SYMBOL_METHOD(getLibraryName) + FORWARD_SYMBOL_METHOD(getName) + FORWARD_SYMBOL_METHOD(getSourceFileName) + FORWARD_SYMBOL_METHOD(getSymIndexId) +}; +} + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLCOMPILAND_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolCompilandDetails.h b/include/llvm/DebugInfo/PDB/PDBSymbolCompilandDetails.h new file mode 100644 index 0000000..8836828 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolCompilandDetails.h @@ -0,0 +1,55 @@ +//===- PDBSymbolCompilandDetails.h - PDB compiland details ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLCOMPILANDDETAILS_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLCOMPILANDDETAILS_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +class PDBSymbolCompilandDetails : public PDBSymbol { +public: + PDBSymbolCompilandDetails(const IPDBSession &PDBSession, + std::unique_ptr Symbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::CompilandDetails) + + void dump(raw_ostream &OS, int Indent, PDBSymDumper &Dumper) const override; + + void getFrontEndVersion(VersionInfo &Version) const { + RawSymbol->getFrontEndVersion(Version); + } + + void getBackEndVersion(VersionInfo &Version) const { + RawSymbol->getBackEndVersion(Version); + } + + FORWARD_SYMBOL_METHOD(getCompilerName) + FORWARD_SYMBOL_METHOD(isEditAndContinueEnabled) + FORWARD_SYMBOL_METHOD(hasDebugInfo) + FORWARD_SYMBOL_METHOD(hasManagedCode) + FORWARD_SYMBOL_METHOD(hasSecurityChecks) + FORWARD_SYMBOL_METHOD(isCVTCIL) + FORWARD_SYMBOL_METHOD(isDataAligned) + FORWARD_SYMBOL_METHOD(isHotpatchable) + FORWARD_SYMBOL_METHOD(isLTCG) + FORWARD_SYMBOL_METHOD(isMSILNetmodule) + FORWARD_SYMBOL_METHOD(getLanguage) + FORWARD_SYMBOL_METHOD(getLexicalParentId) + FORWARD_SYMBOL_METHOD(getPlatform) + FORWARD_SYMBOL_METHOD(getSymIndexId) +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBFUNCTION_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolCompilandEnv.h b/include/llvm/DebugInfo/PDB/PDBSymbolCompilandEnv.h new file mode 100644 index 0000000..c3502a0 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolCompilandEnv.h @@ -0,0 +1,37 @@ +//===- PDBSymbolCompilandEnv.h - compiland environment variables *- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLCOMPILANDENV_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLCOMPILANDENV_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +class PDBSymbolCompilandEnv : public PDBSymbol { +public: + PDBSymbolCompilandEnv(const IPDBSession &PDBSession, + std::unique_ptr Symbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::CompilandEnv) + + void dump(raw_ostream &OS, int Indent, PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getLexicalParentId) + FORWARD_SYMBOL_METHOD(getName) + FORWARD_SYMBOL_METHOD(getSymIndexId) + std::string getValue() const; +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLCOMPILANDENV_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolCustom.h b/include/llvm/DebugInfo/PDB/PDBSymbolCustom.h new file mode 100644 index 0000000..b433dde --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolCustom.h @@ -0,0 +1,39 @@ +//===- PDBSymbolCustom.h - compiler-specific types --------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLCUSTOM_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLCUSTOM_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" +#include "llvm/ADT/SmallVector.h" + +namespace llvm { + +class raw_ostream; + +/// PDBSymbolCustom represents symbols that are compiler-specific and do not +/// fit anywhere else in the lexical hierarchy. +/// https://msdn.microsoft.com/en-us/library/d88sf09h.aspx +class PDBSymbolCustom : public PDBSymbol { +public: + PDBSymbolCustom(const IPDBSession &PDBSession, + std::unique_ptr CustomSymbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Custom) + + void dump(raw_ostream &OS, int Indent, PDBSymDumper &Dumper) const override; + + void getDataBytes(llvm::SmallVector &bytes); + FORWARD_SYMBOL_METHOD(getSymIndexId) +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLCUSTOM_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolData.h b/include/llvm/DebugInfo/PDB/PDBSymbolData.h new file mode 100644 index 0000000..8b9a657 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolData.h @@ -0,0 +1,61 @@ +//===- PDBSymbolData.h - PDB data (e.g. variable) accessors -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLDATA_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLDATA_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +class PDBSymbolData : public PDBSymbol { +public: + PDBSymbolData(const IPDBSession &PDBSession, + std::unique_ptr DataSymbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Data) + + std::unique_ptr getType() const; + + void dump(raw_ostream &OS, int Indent, PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getAccess) + FORWARD_SYMBOL_METHOD(getAddressOffset) + FORWARD_SYMBOL_METHOD(getAddressSection) + FORWARD_SYMBOL_METHOD(getAddressTaken) + FORWARD_SYMBOL_METHOD(getBitPosition) + FORWARD_SYMBOL_METHOD(getClassParentId) + FORWARD_SYMBOL_METHOD(isCompilerGenerated) + FORWARD_SYMBOL_METHOD(isConstType) + FORWARD_SYMBOL_METHOD(getDataKind) + FORWARD_SYMBOL_METHOD(isAggregated) + FORWARD_SYMBOL_METHOD(isSplitted) + FORWARD_SYMBOL_METHOD(getLength) + FORWARD_SYMBOL_METHOD(getLexicalParentId) + FORWARD_SYMBOL_METHOD(getLocationType) + FORWARD_SYMBOL_METHOD(getName) + FORWARD_SYMBOL_METHOD(getOffset) + FORWARD_SYMBOL_METHOD(getRegisterId) + FORWARD_SYMBOL_METHOD(getRelativeVirtualAddress) + FORWARD_SYMBOL_METHOD(getSlot) + FORWARD_SYMBOL_METHOD(getSymIndexId) + FORWARD_SYMBOL_METHOD(getToken) + FORWARD_SYMBOL_METHOD(getTypeId) + FORWARD_SYMBOL_METHOD(isUnalignedType) + FORWARD_SYMBOL_METHOD(getValue) + FORWARD_SYMBOL_METHOD(getVirtualAddress) + FORWARD_SYMBOL_METHOD(isVolatileType) +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLDATA_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolExe.h b/include/llvm/DebugInfo/PDB/PDBSymbolExe.h new file mode 100644 index 0000000..33046f3 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolExe.h @@ -0,0 +1,46 @@ +//===- PDBSymbolExe.h - Accessors for querying executables in a PDB ----*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLEXE_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLEXE_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" +#include + +namespace llvm { + +class raw_ostream; + +class PDBSymbolExe : public PDBSymbol { +public: + PDBSymbolExe(const IPDBSession &PDBSession, + std::unique_ptr ExeSymbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Exe) + + void dump(raw_ostream &OS, int Indent, PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getAge) + FORWARD_SYMBOL_METHOD(getGuid) + FORWARD_SYMBOL_METHOD(hasCTypes) + FORWARD_SYMBOL_METHOD(hasPrivateSymbols) + FORWARD_SYMBOL_METHOD(getMachineType) + FORWARD_SYMBOL_METHOD(getName) + FORWARD_SYMBOL_METHOD(getSignature) + FORWARD_SYMBOL_METHOD(getSymbolsFileName) + FORWARD_SYMBOL_METHOD(getSymIndexId) + +private: + void dumpChildren(raw_ostream &OS, StringRef Label, PDB_SymType ChildType, + int Indent) const; +}; +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLEXE_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolFunc.h b/include/llvm/DebugInfo/PDB/PDBSymbolFunc.h new file mode 100644 index 0000000..22ae6e0 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolFunc.h @@ -0,0 +1,80 @@ +//===- PDBSymbolFunc.h - class representing a function instance -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLFUNC_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLFUNC_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +class PDBSymbolFunc : public PDBSymbol { +public: + PDBSymbolFunc(const IPDBSession &PDBSession, + std::unique_ptr FuncSymbol); + + void dump(raw_ostream &OS, int Indent, PDBSymDumper &Dumper) const override; + + std::unique_ptr getSignature() const; + std::unique_ptr getClassParent() const; + std::unique_ptr> getArguments() const; + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Function) + + FORWARD_SYMBOL_METHOD(getAccess) + FORWARD_SYMBOL_METHOD(getAddressOffset) + FORWARD_SYMBOL_METHOD(getAddressSection) + FORWARD_SYMBOL_METHOD(getClassParentId) + FORWARD_SYMBOL_METHOD(isCompilerGenerated) + FORWARD_SYMBOL_METHOD(isConstType) + FORWARD_SYMBOL_METHOD(hasCustomCallingConvention) + FORWARD_SYMBOL_METHOD(hasFarReturn) + FORWARD_SYMBOL_METHOD(hasAlloca) + FORWARD_SYMBOL_METHOD(hasEH) + FORWARD_SYMBOL_METHOD(hasEHa) + FORWARD_SYMBOL_METHOD(hasInlAsm) + FORWARD_SYMBOL_METHOD(hasLongJump) + FORWARD_SYMBOL_METHOD(hasSEH) + FORWARD_SYMBOL_METHOD(hasSecurityChecks) + FORWARD_SYMBOL_METHOD(hasSetJump) + FORWARD_SYMBOL_METHOD(hasInterruptReturn) + FORWARD_SYMBOL_METHOD(isIntroVirtualFunction) + FORWARD_SYMBOL_METHOD(hasInlineAttribute) + FORWARD_SYMBOL_METHOD(isNaked) + FORWARD_SYMBOL_METHOD(isStatic) + FORWARD_SYMBOL_METHOD(getLength) + FORWARD_SYMBOL_METHOD(getLexicalParentId) + FORWARD_SYMBOL_METHOD(getLocalBasePointerRegisterId) + FORWARD_SYMBOL_METHOD(getLocationType) + FORWARD_SYMBOL_METHOD(getName) + FORWARD_SYMBOL_METHOD(hasFramePointer) + FORWARD_SYMBOL_METHOD(hasNoInlineAttribute) + FORWARD_SYMBOL_METHOD(hasNoReturnAttribute) + FORWARD_SYMBOL_METHOD(isUnreached) + FORWARD_SYMBOL_METHOD(getNoStackOrdering) + FORWARD_SYMBOL_METHOD(hasOptimizedCodeDebugInfo) + FORWARD_SYMBOL_METHOD(isPureVirtual) + FORWARD_SYMBOL_METHOD(getRelativeVirtualAddress) + FORWARD_SYMBOL_METHOD(getSymIndexId) + FORWARD_SYMBOL_METHOD(getToken) + FORWARD_SYMBOL_METHOD(getTypeId) + FORWARD_SYMBOL_METHOD(isUnalignedType) + FORWARD_SYMBOL_METHOD(getUndecoratedName) + FORWARD_SYMBOL_METHOD(isVirtual) + FORWARD_SYMBOL_METHOD(getVirtualAddress) + FORWARD_SYMBOL_METHOD(getVirtualBaseOffset) + FORWARD_SYMBOL_METHOD(isVolatileType) +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLFUNC_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h b/include/llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h new file mode 100644 index 0000000..bd49314 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h @@ -0,0 +1,49 @@ +//===- PDBSymbolFuncDebugEnd.h - function end bounds info -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLFUNCDEBUGEND_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLFUNCDEBUGEND_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +class PDBSymbolFuncDebugEnd : public PDBSymbol { +public: + PDBSymbolFuncDebugEnd(const IPDBSession &PDBSession, + std::unique_ptr FuncDebugEndSymbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::FuncDebugEnd) + + void dump(raw_ostream &OS, int Indent, PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getAddressOffset) + FORWARD_SYMBOL_METHOD(getAddressSection) + FORWARD_SYMBOL_METHOD(hasCustomCallingConvention) + FORWARD_SYMBOL_METHOD(hasFarReturn) + FORWARD_SYMBOL_METHOD(hasInterruptReturn) + FORWARD_SYMBOL_METHOD(isStatic) + FORWARD_SYMBOL_METHOD(getLexicalParentId) + FORWARD_SYMBOL_METHOD(getLocationType) + FORWARD_SYMBOL_METHOD(hasNoInlineAttribute) + FORWARD_SYMBOL_METHOD(hasNoReturnAttribute) + FORWARD_SYMBOL_METHOD(isUnreached) + FORWARD_SYMBOL_METHOD(getOffset) + FORWARD_SYMBOL_METHOD(hasOptimizedCodeDebugInfo) + FORWARD_SYMBOL_METHOD(getRelativeVirtualAddress) + FORWARD_SYMBOL_METHOD(getSymIndexId) + FORWARD_SYMBOL_METHOD(getVirtualAddress) +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLFUNCDEBUGEND_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h b/include/llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h new file mode 100644 index 0000000..a62eada --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h @@ -0,0 +1,49 @@ +//===- PDBSymbolFuncDebugStart.h - function start bounds info ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLFUNCDEBUGSTART_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLFUNCDEBUGSTART_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +class PDBSymbolFuncDebugStart : public PDBSymbol { +public: + PDBSymbolFuncDebugStart(const IPDBSession &PDBSession, + std::unique_ptr FuncDebugStartSymbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::FuncDebugStart) + + void dump(raw_ostream &OS, int Indent, PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getAddressOffset) + FORWARD_SYMBOL_METHOD(getAddressSection) + FORWARD_SYMBOL_METHOD(hasCustomCallingConvention) + FORWARD_SYMBOL_METHOD(hasFarReturn) + FORWARD_SYMBOL_METHOD(hasInterruptReturn) + FORWARD_SYMBOL_METHOD(isStatic) + FORWARD_SYMBOL_METHOD(getLexicalParentId) + FORWARD_SYMBOL_METHOD(getLocationType) + FORWARD_SYMBOL_METHOD(hasNoInlineAttribute) + FORWARD_SYMBOL_METHOD(hasNoReturnAttribute) + FORWARD_SYMBOL_METHOD(isUnreached) + FORWARD_SYMBOL_METHOD(getOffset) + FORWARD_SYMBOL_METHOD(hasOptimizedCodeDebugInfo) + FORWARD_SYMBOL_METHOD(getRelativeVirtualAddress) + FORWARD_SYMBOL_METHOD(getSymIndexId) + FORWARD_SYMBOL_METHOD(getVirtualAddress) +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLFUNCDEBUGSTART_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolLabel.h b/include/llvm/DebugInfo/PDB/PDBSymbolLabel.h new file mode 100644 index 0000000..d006495 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolLabel.h @@ -0,0 +1,49 @@ +//===- PDBSymbolLabel.h - label info ----------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLLABEL_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLLABEL_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +class PDBSymbolLabel : public PDBSymbol { +public: + PDBSymbolLabel(const IPDBSession &PDBSession, + std::unique_ptr LabelSymbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Label) + + void dump(raw_ostream &OS, int Indent, PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getAddressOffset) + FORWARD_SYMBOL_METHOD(getAddressSection) + FORWARD_SYMBOL_METHOD(hasCustomCallingConvention) + FORWARD_SYMBOL_METHOD(hasFarReturn) + FORWARD_SYMBOL_METHOD(hasInterruptReturn) + FORWARD_SYMBOL_METHOD(getLexicalParentId) + FORWARD_SYMBOL_METHOD(getLocationType) + FORWARD_SYMBOL_METHOD(getName) + FORWARD_SYMBOL_METHOD(hasNoInlineAttribute) + FORWARD_SYMBOL_METHOD(hasNoReturnAttribute) + FORWARD_SYMBOL_METHOD(isUnreached) + FORWARD_SYMBOL_METHOD(getOffset) + FORWARD_SYMBOL_METHOD(hasOptimizedCodeDebugInfo) + FORWARD_SYMBOL_METHOD(getRelativeVirtualAddress) + FORWARD_SYMBOL_METHOD(getSymIndexId) + FORWARD_SYMBOL_METHOD(getVirtualAddress) +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLLABEL_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h b/include/llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h new file mode 100644 index 0000000..a8de89d --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h @@ -0,0 +1,47 @@ +//===- PDBSymbolPublicSymbol.h - public symbol info -------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLPUBLICSYMBOL_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLPUBLICSYMBOL_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +class PDBSymbolPublicSymbol : public PDBSymbol { +public: + PDBSymbolPublicSymbol(const IPDBSession &PDBSession, + std::unique_ptr PublicSymbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::PublicSymbol) + + void dump(raw_ostream &OS, int Indent, PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getAddressOffset) + FORWARD_SYMBOL_METHOD(getAddressSection) + FORWARD_SYMBOL_METHOD(isCode) + FORWARD_SYMBOL_METHOD(isFunction) + FORWARD_SYMBOL_METHOD(getLength) + FORWARD_SYMBOL_METHOD(getLexicalParentId) + FORWARD_SYMBOL_METHOD(getLocationType) + FORWARD_SYMBOL_METHOD(isManagedCode) + FORWARD_SYMBOL_METHOD(isMSILCode) + FORWARD_SYMBOL_METHOD(getName) + FORWARD_SYMBOL_METHOD(getSymIndexId) + FORWARD_SYMBOL_METHOD(getRelativeVirtualAddress) + FORWARD_SYMBOL_METHOD(getVirtualAddress) + FORWARD_SYMBOL_METHOD(getUndecoratedName) +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLPUBLICSYMBOL_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolThunk.h b/include/llvm/DebugInfo/PDB/PDBSymbolThunk.h new file mode 100644 index 0000000..88588f1 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolThunk.h @@ -0,0 +1,57 @@ +//===- PDBSymbolThunk.h - Support for querying PDB thunks ---------------*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLTHUNK_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTHUNK_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" +#include + +namespace llvm { + +class raw_ostream; + +class PDBSymbolThunk : public PDBSymbol { +public: + PDBSymbolThunk(const IPDBSession &PDBSession, + std::unique_ptr ThunkSymbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Thunk) + + void dump(raw_ostream &OS, int Indent, PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getAccess) + FORWARD_SYMBOL_METHOD(getAddressOffset) + FORWARD_SYMBOL_METHOD(getAddressSection) + FORWARD_SYMBOL_METHOD(getClassParentId) + FORWARD_SYMBOL_METHOD(isConstType) + FORWARD_SYMBOL_METHOD(isIntroVirtualFunction) + FORWARD_SYMBOL_METHOD(isStatic) + FORWARD_SYMBOL_METHOD(getLength) + FORWARD_SYMBOL_METHOD(getLexicalParentId) + FORWARD_SYMBOL_METHOD(getName) + FORWARD_SYMBOL_METHOD(isPureVirtual) + FORWARD_SYMBOL_METHOD(getRelativeVirtualAddress) + FORWARD_SYMBOL_METHOD(getSymIndexId) + FORWARD_SYMBOL_METHOD(getTargetOffset) + FORWARD_SYMBOL_METHOD(getTargetRelativeVirtualAddress) + FORWARD_SYMBOL_METHOD(getTargetVirtualAddress) + FORWARD_SYMBOL_METHOD(getTargetSection) + FORWARD_SYMBOL_METHOD(getThunkOrdinal) + FORWARD_SYMBOL_METHOD(getTypeId) + FORWARD_SYMBOL_METHOD(isUnalignedType) + FORWARD_SYMBOL_METHOD(isVirtual) + FORWARD_SYMBOL_METHOD(getVirtualAddress) + FORWARD_SYMBOL_METHOD(getVirtualBaseOffset) + FORWARD_SYMBOL_METHOD(isVolatileType) +}; +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTHUNK_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeArray.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeArray.h new file mode 100644 index 0000000..ca925f9 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeArray.h @@ -0,0 +1,45 @@ +//===- PDBSymbolTypeArray.h - array type information ------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEARRAY_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEARRAY_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +class PDBSymbolTypeArray : public PDBSymbol { +public: + PDBSymbolTypeArray(const IPDBSession &PDBSession, + std::unique_ptr ArrayTypeSymbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::ArrayType) + + std::unique_ptr getElementType() const; + + void dump(raw_ostream &OS, int Indent, PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getArrayIndexTypeId) + FORWARD_SYMBOL_METHOD(isConstType) + FORWARD_SYMBOL_METHOD(getCount) + FORWARD_SYMBOL_METHOD(getLength) + FORWARD_SYMBOL_METHOD(getLexicalParentId) + FORWARD_SYMBOL_METHOD(getRank) + FORWARD_SYMBOL_METHOD(getSymIndexId) + FORWARD_SYMBOL_METHOD(getTypeId) + FORWARD_SYMBOL_METHOD(isUnalignedType) + FORWARD_SYMBOL_METHOD(isVolatileType) +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEARRAY_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h new file mode 100644 index 0000000..a3dcc02 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h @@ -0,0 +1,60 @@ +//===- PDBSymbolTypeBaseClass.h - base class type information ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEBASECLASS_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEBASECLASS_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +class PDBSymbolTypeBaseClass : public PDBSymbol { +public: + PDBSymbolTypeBaseClass(const IPDBSession &PDBSession, + std::unique_ptr Symbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::BaseClass) + + void dump(raw_ostream &OS, int Indent, PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getAccess) + FORWARD_SYMBOL_METHOD(getClassParentId) + FORWARD_SYMBOL_METHOD(hasConstructor) + FORWARD_SYMBOL_METHOD(isConstType) + FORWARD_SYMBOL_METHOD(hasAssignmentOperator) + FORWARD_SYMBOL_METHOD(hasCastOperator) + FORWARD_SYMBOL_METHOD(hasNestedTypes) + FORWARD_SYMBOL_METHOD(isIndirectVirtualBaseClass) + FORWARD_SYMBOL_METHOD(getLength) + FORWARD_SYMBOL_METHOD(getLexicalParentId) + FORWARD_SYMBOL_METHOD(getName) + FORWARD_SYMBOL_METHOD(isNested) + FORWARD_SYMBOL_METHOD(getOffset) + FORWARD_SYMBOL_METHOD(hasOverloadedOperator) + FORWARD_SYMBOL_METHOD(isPacked) + FORWARD_SYMBOL_METHOD(isScoped) + FORWARD_SYMBOL_METHOD(getSymIndexId) + FORWARD_SYMBOL_METHOD(getTypeId) + FORWARD_SYMBOL_METHOD(getUdtKind) + FORWARD_SYMBOL_METHOD(isUnalignedType) + + FORWARD_SYMBOL_METHOD(isVirtualBaseClass) + FORWARD_SYMBOL_METHOD(getVirtualBaseDispIndex) + FORWARD_SYMBOL_METHOD(getVirtualBasePointerOffset) + // FORWARD_SYMBOL_METHOD(getVirtualBaseTableType) + FORWARD_SYMBOL_METHOD(getVirtualTableShapeId) + FORWARD_SYMBOL_METHOD(isVolatileType) +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEBASECLASS_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h new file mode 100644 index 0000000..1cede08 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h @@ -0,0 +1,40 @@ +//===- PDBSymbolTypeBuiltin.h - builtin type information --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEBUILTIN_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEBUILTIN_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +class PDBSymbolTypeBuiltin : public PDBSymbol { +public: + PDBSymbolTypeBuiltin(const IPDBSession &PDBSession, + std::unique_ptr Symbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::BuiltinType) + + void dump(raw_ostream &OS, int Indent, PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getBuiltinType) + FORWARD_SYMBOL_METHOD(isConstType) + FORWARD_SYMBOL_METHOD(getLength) + FORWARD_SYMBOL_METHOD(getLexicalParentId) + FORWARD_SYMBOL_METHOD(getSymIndexId) + FORWARD_SYMBOL_METHOD(isUnalignedType) + FORWARD_SYMBOL_METHOD(isVolatileType) +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEBUILTIN_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeCustom.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeCustom.h new file mode 100644 index 0000000..90a043f --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeCustom.h @@ -0,0 +1,36 @@ +//===- PDBSymbolTypeCustom.h - custom compiler type information -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPECUSTOM_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPECUSTOM_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +class PDBSymbolTypeCustom : public PDBSymbol { +public: + PDBSymbolTypeCustom(const IPDBSession &PDBSession, + std::unique_ptr Symbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::CustomType) + + void dump(raw_ostream &OS, int Indent, PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getOemId) + FORWARD_SYMBOL_METHOD(getOemSymbolId) + FORWARD_SYMBOL_METHOD(getSymIndexId) +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPECUSTOM_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeDimension.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeDimension.h new file mode 100644 index 0000000..f871681 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeDimension.h @@ -0,0 +1,36 @@ +//===- PDBSymbolTypeDimension.h - array dimension type info -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEDIMENSION_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEDIMENSION_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +class PDBSymbolTypeDimension : public PDBSymbol { +public: + PDBSymbolTypeDimension(const IPDBSession &PDBSession, + std::unique_ptr Symbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Dimension) + + void dump(raw_ostream &OS, int Indent, PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getLowerBoundId) + FORWARD_SYMBOL_METHOD(getUpperBoundId) + FORWARD_SYMBOL_METHOD(getSymIndexId) +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEDIMENSION_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h new file mode 100644 index 0000000..2479f46 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h @@ -0,0 +1,52 @@ +//===- PDBSymbolTypeEnum.h - enum type info ---------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEENUM_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEENUM_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +class PDBSymbolTypeEnum : public PDBSymbol { +public: + PDBSymbolTypeEnum(const IPDBSession &PDBSession, + std::unique_ptr EnumTypeSymbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Enum) + + void dump(raw_ostream &OS, int Indent, PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getBuiltinType) + FORWARD_SYMBOL_METHOD(getClassParentId) + FORWARD_SYMBOL_METHOD(getUnmodifiedTypeId) + FORWARD_SYMBOL_METHOD(hasConstructor) + FORWARD_SYMBOL_METHOD(isConstType) + FORWARD_SYMBOL_METHOD(hasAssignmentOperator) + FORWARD_SYMBOL_METHOD(hasCastOperator) + FORWARD_SYMBOL_METHOD(hasNestedTypes) + FORWARD_SYMBOL_METHOD(getLength) + FORWARD_SYMBOL_METHOD(getLexicalParentId) + FORWARD_SYMBOL_METHOD(getName) + FORWARD_SYMBOL_METHOD(isNested) + FORWARD_SYMBOL_METHOD(hasOverloadedOperator) + FORWARD_SYMBOL_METHOD(isPacked) + FORWARD_SYMBOL_METHOD(isScoped) + FORWARD_SYMBOL_METHOD(getSymIndexId) + FORWARD_SYMBOL_METHOD(getTypeId) + FORWARD_SYMBOL_METHOD(isUnalignedType) + FORWARD_SYMBOL_METHOD(isVolatileType) +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEENUM_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeFriend.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeFriend.h new file mode 100644 index 0000000..964246f --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeFriend.h @@ -0,0 +1,37 @@ +//===- PDBSymbolTypeFriend.h - friend type info -----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEFRIEND_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEFRIEND_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +class PDBSymbolTypeFriend : public PDBSymbol { +public: + PDBSymbolTypeFriend(const IPDBSession &PDBSession, + std::unique_ptr Symbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Friend) + + void dump(raw_ostream &OS, int Indent, PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getClassParentId) + FORWARD_SYMBOL_METHOD(getName) + FORWARD_SYMBOL_METHOD(getSymIndexId) + FORWARD_SYMBOL_METHOD(getTypeId) +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEFRIEND_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h new file mode 100644 index 0000000..22f1455 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h @@ -0,0 +1,37 @@ +//===- PDBSymbolTypeFunctionArg.h - function arg type info ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEFUNCTIONARG_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEFUNCTIONARG_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +class PDBSymbolTypeFunctionArg : public PDBSymbol { +public: + PDBSymbolTypeFunctionArg(const IPDBSession &PDBSession, + std::unique_ptr Symbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::FunctionArg) + + void dump(raw_ostream &OS, int Indent, PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getClassParentId) + FORWARD_SYMBOL_METHOD(getLexicalParentId) + FORWARD_SYMBOL_METHOD(getSymIndexId) + FORWARD_SYMBOL_METHOD(getTypeId) +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEFUNCTIONARG_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h new file mode 100644 index 0000000..82bb1fd --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h @@ -0,0 +1,50 @@ +//===- PDBSymbolTypeFunctionSig.h - function signature type info *- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEFUNCTIONSIG_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEFUNCTIONSIG_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +class PDBSymbolTypeFunctionSig : public PDBSymbol { +public: + PDBSymbolTypeFunctionSig(const IPDBSession &PDBSession, + std::unique_ptr Symbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::FunctionSig) + + std::unique_ptr getReturnType() const; + std::unique_ptr getArguments() const; + std::unique_ptr getClassParent() const; + + void dump(raw_ostream &OS, int Indent, PDBSymDumper &Dumper) const override; + void dumpArgList(raw_ostream &OS) const; + + FORWARD_SYMBOL_METHOD(getCallingConvention) + FORWARD_SYMBOL_METHOD(getClassParentId) + FORWARD_SYMBOL_METHOD(getUnmodifiedTypeId) + FORWARD_SYMBOL_METHOD(isConstType) + FORWARD_SYMBOL_METHOD(getCount) + FORWARD_SYMBOL_METHOD(getLexicalParentId) + // FORWARD_SYMBOL_METHOD(getObjectPointerType) + FORWARD_SYMBOL_METHOD(getSymIndexId) + FORWARD_SYMBOL_METHOD(getThisAdjust) + FORWARD_SYMBOL_METHOD(getTypeId) + FORWARD_SYMBOL_METHOD(isUnalignedType) + FORWARD_SYMBOL_METHOD(isVolatileType) +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEFUNCTIONSIG_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeManaged.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeManaged.h new file mode 100644 index 0000000..42f5867 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeManaged.h @@ -0,0 +1,35 @@ +//===- PDBSymbolTypeManaged.h - managed type info ---------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEMANAGED_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEMANAGED_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +class PDBSymbolTypeManaged : public PDBSymbol { +public: + PDBSymbolTypeManaged(const IPDBSession &PDBSession, + std::unique_ptr Symbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::ManagedType) + + void dump(raw_ostream &OS, int Indent, PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getName) + FORWARD_SYMBOL_METHOD(getSymIndexId) +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEMANAGED_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypePointer.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypePointer.h new file mode 100644 index 0000000..8b2806f --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypePointer.h @@ -0,0 +1,43 @@ +//===- PDBSymbolTypePointer.h - pointer type info ---------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEPOINTER_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEPOINTER_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +class PDBSymbolTypePointer : public PDBSymbol { +public: + PDBSymbolTypePointer(const IPDBSession &PDBSession, + std::unique_ptr Symbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::PointerType) + + std::unique_ptr getPointeeType() const; + + void dump(raw_ostream &OS, int Indent, PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(isConstType) + FORWARD_SYMBOL_METHOD(getLength) + FORWARD_SYMBOL_METHOD(getLexicalParentId) + FORWARD_SYMBOL_METHOD(isReference) + FORWARD_SYMBOL_METHOD(getSymIndexId) + FORWARD_SYMBOL_METHOD(getTypeId) + FORWARD_SYMBOL_METHOD(isUnalignedType) + FORWARD_SYMBOL_METHOD(isVolatileType) +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEPOINTER_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h new file mode 100644 index 0000000..d3a9ca2 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h @@ -0,0 +1,54 @@ +//===- PDBSymbolTypeTypedef.h - typedef type info ---------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPETYPEDEF_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPETYPEDEF_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +class PDBSymbolTypeTypedef : public PDBSymbol { +public: + PDBSymbolTypeTypedef(const IPDBSession &PDBSession, + std::unique_ptr Symbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Typedef) + + void dump(raw_ostream &OS, int Indent, PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getBuiltinType) + FORWARD_SYMBOL_METHOD(getClassParentId) + FORWARD_SYMBOL_METHOD(hasConstructor) + FORWARD_SYMBOL_METHOD(isConstType) + FORWARD_SYMBOL_METHOD(hasAssignmentOperator) + FORWARD_SYMBOL_METHOD(hasCastOperator) + FORWARD_SYMBOL_METHOD(hasNestedTypes) + FORWARD_SYMBOL_METHOD(getLength) + FORWARD_SYMBOL_METHOD(getLexicalParentId) + FORWARD_SYMBOL_METHOD(getName) + FORWARD_SYMBOL_METHOD(isNested) + FORWARD_SYMBOL_METHOD(hasOverloadedOperator) + FORWARD_SYMBOL_METHOD(isPacked) + FORWARD_SYMBOL_METHOD(isReference) + FORWARD_SYMBOL_METHOD(isScoped) + FORWARD_SYMBOL_METHOD(getSymIndexId) + FORWARD_SYMBOL_METHOD(getTypeId) + FORWARD_SYMBOL_METHOD(getUdtKind) + FORWARD_SYMBOL_METHOD(isUnalignedType) + FORWARD_SYMBOL_METHOD(getVirtualTableShapeId) + FORWARD_SYMBOL_METHOD(isVolatileType) +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPETYPEDEF_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h new file mode 100644 index 0000000..bf912b8 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h @@ -0,0 +1,52 @@ +//===- PDBSymbolTypeUDT.h - UDT type info -----------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEUDT_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEUDT_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +class PDBSymbolTypeUDT : public PDBSymbol { +public: + PDBSymbolTypeUDT(const IPDBSession &PDBSession, + std::unique_ptr UDTSymbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::UDT) + + void dump(raw_ostream &OS, int Indent, PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getClassParentId) + FORWARD_SYMBOL_METHOD(getUnmodifiedTypeId) + FORWARD_SYMBOL_METHOD(hasConstructor) + FORWARD_SYMBOL_METHOD(isConstType) + FORWARD_SYMBOL_METHOD(hasAssignmentOperator) + FORWARD_SYMBOL_METHOD(hasCastOperator) + FORWARD_SYMBOL_METHOD(hasNestedTypes) + FORWARD_SYMBOL_METHOD(getLength) + FORWARD_SYMBOL_METHOD(getLexicalParentId) + FORWARD_SYMBOL_METHOD(getName) + FORWARD_SYMBOL_METHOD(isNested) + FORWARD_SYMBOL_METHOD(hasOverloadedOperator) + FORWARD_SYMBOL_METHOD(isPacked) + FORWARD_SYMBOL_METHOD(isScoped) + FORWARD_SYMBOL_METHOD(getSymIndexId) + FORWARD_SYMBOL_METHOD(getUdtKind) + FORWARD_SYMBOL_METHOD(isUnalignedType) + FORWARD_SYMBOL_METHOD(getVirtualTableShapeId) + FORWARD_SYMBOL_METHOD(isVolatileType) +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEUDT_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h new file mode 100644 index 0000000..6b6d99b --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h @@ -0,0 +1,40 @@ +//===- PDBSymbolTypeVTable.h - VTable type info -----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEVTABLE_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEVTABLE_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +class PDBSymbolTypeVTable : public PDBSymbol { +public: + PDBSymbolTypeVTable(const IPDBSession &PDBSession, + std::unique_ptr VtblSymbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::VTable) + + void dump(raw_ostream &OS, int Indent, PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getClassParentId) + FORWARD_SYMBOL_METHOD(isConstType) + FORWARD_SYMBOL_METHOD(getLexicalParentId) + FORWARD_SYMBOL_METHOD(getSymIndexId) + FORWARD_SYMBOL_METHOD(getTypeId) + FORWARD_SYMBOL_METHOD(isUnalignedType) + FORWARD_SYMBOL_METHOD(isVolatileType) +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEVTABLE_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTableShape.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTableShape.h new file mode 100644 index 0000000..e866106 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTableShape.h @@ -0,0 +1,39 @@ +//===- PDBSymbolTypeVTableShape.h - VTable shape info -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEVTABLESHAPE_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEVTABLESHAPE_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +class PDBSymbolTypeVTableShape : public PDBSymbol { +public: + PDBSymbolTypeVTableShape(const IPDBSession &PDBSession, + std::unique_ptr VtblShapeSymbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::VTableShape) + + void dump(raw_ostream &OS, int Indent, PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(isConstType) + FORWARD_SYMBOL_METHOD(getCount) + FORWARD_SYMBOL_METHOD(getLexicalParentId) + FORWARD_SYMBOL_METHOD(getSymIndexId) + FORWARD_SYMBOL_METHOD(isUnalignedType) + FORWARD_SYMBOL_METHOD(isVolatileType) +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEVTABLESHAPE_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolUnknown.h b/include/llvm/DebugInfo/PDB/PDBSymbolUnknown.h new file mode 100644 index 0000000..7f8c6f9 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolUnknown.h @@ -0,0 +1,34 @@ +//===- PDBSymbolUnknown.h - unknown symbol type -----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLUNKNOWN_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLUNKNOWN_H + +#include "PDBSymbol.h" + +namespace llvm { + +class raw_ostream; + +class PDBSymbolUnknown : public PDBSymbol { +public: + PDBSymbolUnknown(const IPDBSession &PDBSession, + std::unique_ptr UnknownSymbol); + + void dump(raw_ostream &OS, int Indent, PDBSymDumper &Dumper) const override; + + static bool classof(const PDBSymbol *S) { + return (S->getSymTag() == PDB_SymType::None || + S->getSymTag() >= PDB_SymType::Max); + } +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLUNKNOWN_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolUsingNamespace.h b/include/llvm/DebugInfo/PDB/PDBSymbolUsingNamespace.h new file mode 100644 index 0000000..59ec16b --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBSymbolUsingNamespace.h @@ -0,0 +1,36 @@ +//===- PDBSymbolUsingNamespace.h - using namespace info ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLUSINGNAMESPACE_H +#define LLVM_DEBUGINFO_PDB_PDBSYMBOLUSINGNAMESPACE_H + +#include "PDBSymbol.h" +#include "PDBTypes.h" + +namespace llvm { + +class raw_ostream; + +class PDBSymbolUsingNamespace : public PDBSymbol { +public: + PDBSymbolUsingNamespace(const IPDBSession &PDBSession, + std::unique_ptr Symbol); + + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::UsingNamespace) + + void dump(raw_ostream &OS, int Indent, PDBSymDumper &Dumper) const override; + + FORWARD_SYMBOL_METHOD(getLexicalParentId) + FORWARD_SYMBOL_METHOD(getName) + FORWARD_SYMBOL_METHOD(getSymIndexId) +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLUSINGNAMESPACE_H diff --git a/include/llvm/DebugInfo/PDB/PDBTypes.h b/include/llvm/DebugInfo/PDB/PDBTypes.h new file mode 100644 index 0000000..75b6475 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBTypes.h @@ -0,0 +1,479 @@ +//===- PDBTypes.h - Defines enums for various fields contained in PDB ---*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_PDBTYPES_H +#define LLVM_DEBUGINFO_PDB_PDBTYPES_H + +#include "llvm/Config/llvm-config.h" +#include +#include + +namespace llvm { + +class PDBSymDumper; +class PDBSymbol; + +class IPDBDataStream; +template class IPDBEnumChildren; +class IPDBRawSymbol; +class IPDBSession; +class IPDBSourceFile; + +typedef IPDBEnumChildren IPDBEnumSymbols; +typedef IPDBEnumChildren IPDBEnumSourceFiles; +typedef IPDBEnumChildren IPDBEnumDataStreams; + +class PDBSymbolExe; +class PDBSymbolCompiland; +class PDBSymbolCompilandDetails; +class PDBSymbolCompilandEnv; +class PDBSymbolFunc; +class PDBSymbolBlock; +class PDBSymbolData; +class PDBSymbolAnnotation; +class PDBSymbolLabel; +class PDBSymbolPublicSymbol; +class PDBSymbolTypeUDT; +class PDBSymbolTypeEnum; +class PDBSymbolTypeFunctionSig; +class PDBSymbolTypePointer; +class PDBSymbolTypeArray; +class PDBSymbolTypeBuiltin; +class PDBSymbolTypeTypedef; +class PDBSymbolTypeBaseClass; +class PDBSymbolTypeFriend; +class PDBSymbolTypeFunctionArg; +class PDBSymbolFuncDebugStart; +class PDBSymbolFuncDebugEnd; +class PDBSymbolUsingNamespace; +class PDBSymbolTypeVTableShape; +class PDBSymbolTypeVTable; +class PDBSymbolCustom; +class PDBSymbolThunk; +class PDBSymbolTypeCustom; +class PDBSymbolTypeManaged; +class PDBSymbolTypeDimension; +class PDBSymbolUnknown; + +/// Specifies which PDB reader implementation is to be used. Only a value +/// of PDB_ReaderType::DIA is supported. +enum class PDB_ReaderType { + DIA = 0, +}; + +/// Defines a 128-bit unique identifier. This maps to a GUID on Windows, but +/// is abstracted here for the purposes of non-Windows platforms that don't have +/// the GUID structure defined. +struct PDB_UniqueId { + uint64_t HighPart; + uint64_t LowPart; +}; + +/// An enumeration indicating the type of data contained in this table. +enum class PDB_TableType { + Symbols, + SourceFiles, + LineNumbers, + SectionContribs, + Segments, + InjectedSources, + FrameData +}; + +/// Defines flags used for enumerating child symbols. This corresponds to the +/// NameSearchOptions enumeration which is documented here: +/// https://msdn.microsoft.com/en-us/library/yat28ads.aspx +enum PDB_NameSearchFlags { + NS_Default = 0x0, + NS_CaseSensitive = 0x1, + NS_CaseInsensitive = 0x2, + NS_FileNameExtMatch = 0x4, + NS_Regex = 0x8, + NS_UndecoratedName = 0x10 +}; + +/// Specifies the hash algorithm that a source file from a PDB was hashed with. +/// This corresponds to the CV_SourceChksum_t enumeration and are documented +/// here: https://msdn.microsoft.com/en-us/library/e96az21x.aspx +enum class PDB_Checksum { None = 0, MD5 = 1, SHA1 = 2 }; + +/// These values correspond to the CV_CPU_TYPE_e enumeration, and are documented +/// here: https://msdn.microsoft.com/en-us/library/b2fc64ek.aspx +enum class PDB_Cpu { + Intel8080 = 0x0, + Intel8086 = 0x1, + Intel80286 = 0x2, + Intel80386 = 0x3, + Intel80486 = 0x4, + Pentium = 0x5, + PentiumPro = 0x6, + Pentium3 = 0x7, + MIPS = 0x10, + MIPS16 = 0x11, + MIPS32 = 0x12, + MIPS64 = 0x13, + MIPSI = 0x14, + MIPSII = 0x15, + MIPSIII = 0x16, + MIPSIV = 0x17, + MIPSV = 0x18, + M68000 = 0x20, + M68010 = 0x21, + M68020 = 0x22, + M68030 = 0x23, + M68040 = 0x24, + Alpha = 0x30, + Alpha21164 = 0x31, + Alpha21164A = 0x32, + Alpha21264 = 0x33, + Alpha21364 = 0x34, + PPC601 = 0x40, + PPC603 = 0x41, + PPC604 = 0x42, + PPC620 = 0x43, + PPCFP = 0x44, + PPCBE = 0x45, + SH3 = 0x50, + SH3E = 0x51, + SH3DSP = 0x52, + SH4 = 0x53, + SHMedia = 0x54, + ARM3 = 0x60, + ARM4 = 0x61, + ARM4T = 0x62, + ARM5 = 0x63, + ARM5T = 0x64, + ARM6 = 0x65, + ARM_XMAC = 0x66, + ARM_WMMX = 0x67, + ARM7 = 0x68, + Omni = 0x70, + Ia64 = 0x80, + Ia64_2 = 0x81, + CEE = 0x90, + AM33 = 0xa0, + M32R = 0xb0, + TriCore = 0xc0, + X64 = 0xd0, + EBC = 0xe0, + Thumb = 0xf0, + ARMNT = 0xf4, + D3D11_Shader = 0x100, +}; + +enum class PDB_Machine { + Invalid = 0xffff, + Unknown = 0x0, + Am33 = 0x13, + Amd64 = 0x8664, + Arm = 0x1C0, + ArmNT = 0x1C4, + Ebc = 0xEBC, + x86 = 0x14C, + Ia64 = 0x200, + M32R = 0x9041, + Mips16 = 0x266, + MipsFpu = 0x366, + MipsFpu16 = 0x466, + PowerPC = 0x1F0, + PowerPCFP = 0x1F1, + R4000 = 0x166, + SH3 = 0x1A2, + SH3DSP = 0x1A3, + SH4 = 0x1A6, + SH5 = 0x1A8, + Thumb = 0x1C2, + WceMipsV2 = 0x169 +}; + +/// These values correspond to the CV_call_e enumeration, and are documented +/// at the following locations: +/// https://msdn.microsoft.com/en-us/library/b2fc64ek.aspx +/// https://msdn.microsoft.com/en-us/library/windows/desktop/ms680207(v=vs.85).aspx +/// +enum class PDB_CallingConv { + NearCdecl = 0x00, + FarCdecl = 0x01, + NearPascal = 0x02, + FarPascal = 0x03, + NearFastcall = 0x04, + FarFastcall = 0x05, + Skipped = 0x06, + NearStdcall = 0x07, + FarStdcall = 0x08, + NearSyscall = 0x09, + FarSyscall = 0x0a, + Thiscall = 0x0b, + MipsCall = 0x0c, + Generic = 0x0d, + Alphacall = 0x0e, + Ppccall = 0x0f, + SuperHCall = 0x10, + Armcall = 0x11, + AM33call = 0x12, + Tricall = 0x13, + Sh5call = 0x14, + M32R = 0x15, + Clrcall = 0x16, + Inline = 0x17, + NearVectorcall = 0x18, + Reserved = 0x19, +}; + +/// These values correspond to the CV_CFL_LANG enumeration, and are documented +/// here: https://msdn.microsoft.com/en-us/library/bw3aekw6.aspx +enum class PDB_Lang { + C = 0x00, + Cpp = 0x01, + Fortran = 0x02, + Masm = 0x03, + Pascal = 0x04, + Basic = 0x05, + Cobol = 0x06, + Link = 0x07, + Cvtres = 0x08, + Cvtpgd = 0x09, + CSharp = 0x0a, + VB = 0x0b, + ILAsm = 0x0c, + Java = 0x0d, + JScript = 0x0e, + MSIL = 0x0f, + HLSL = 0x10 +}; + +/// These values correspond to the DataKind enumeration, and are documented +/// here: https://msdn.microsoft.com/en-us/library/b2x2t313.aspx +enum class PDB_DataKind { + Unknown, + Local, + StaticLocal, + Param, + ObjectPtr, + FileStatic, + Global, + Member, + StaticMember, + Constant +}; + +/// These values correspond to the SymTagEnum enumeration, and are documented +/// here: https://msdn.microsoft.com/en-us/library/bkedss5f.aspx +enum class PDB_SymType { + None, + Exe, + Compiland, + CompilandDetails, + CompilandEnv, + Function, + Block, + Data, + Annotation, + Label, + PublicSymbol, + UDT, + Enum, + FunctionSig, + PointerType, + ArrayType, + BuiltinType, + Typedef, + BaseClass, + Friend, + FunctionArg, + FuncDebugStart, + FuncDebugEnd, + UsingNamespace, + VTableShape, + VTable, + Custom, + Thunk, + CustomType, + ManagedType, + Dimension, + Max +}; + +/// These values correspond to the LocationType enumeration, and are documented +/// here: https://msdn.microsoft.com/en-us/library/f57kaez3.aspx +enum class PDB_LocType { + Null, + Static, + TLS, + RegRel, + ThisRel, + Enregistered, + BitField, + Slot, + IlRel, + MetaData, + Constant, + Max +}; + +/// These values correspond to the THUNK_ORDINAL enumeration, and are documented +/// here: https://msdn.microsoft.com/en-us/library/dh0k8hft.aspx +enum class PDB_ThunkOrdinal { + Standard, + ThisAdjustor, + Vcall, + Pcode, + UnknownLoad, + TrampIncremental, + BranchIsland +}; + +/// These values correspond to the UdtKind enumeration, and are documented +/// here: https://msdn.microsoft.com/en-us/library/wcstk66t.aspx +enum class PDB_UdtType { Struct, Class, Union, Interface }; + +/// These values correspond to the StackFrameTypeEnum enumeration, and are +/// documented here: https://msdn.microsoft.com/en-us/library/bc5207xw.aspx. +enum class PDB_StackFrameType { FPO, KernelTrap, KernelTSS, EBP, FrameData }; + +/// These values correspond to the StackFrameTypeEnum enumeration, and are +/// documented here: https://msdn.microsoft.com/en-us/library/bc5207xw.aspx. +enum class PDB_MemoryType { Code, Data, Stack, HeapCode }; + +/// These values correspond to the Basictype enumeration, and are documented +/// here: https://msdn.microsoft.com/en-us/library/4szdtzc3.aspx +enum class PDB_BuiltinType { + None = 0, + Void = 1, + Char = 2, + WCharT = 3, + Int = 6, + UInt = 7, + Float = 8, + BCD = 9, + Bool = 10, + Long = 13, + ULong = 14, + Currency = 25, + Date = 26, + Variant = 27, + Complex = 28, + Bitfield = 29, + BSTR = 30, + HResult = 31 +}; + +enum class PDB_RegisterId { + Unknown = 0, + VFrame = 30006, + AL = 1, + CL = 2, + DL = 3, + BL = 4, + AH = 5, + CH = 6, + DH = 7, + BH = 8, + AX = 9, + CX = 10, + DX = 11, + BX = 12, + SP = 13, + BP = 14, + SI = 15, + DI = 16, + EAX = 17, + ECX = 18, + EDX = 19, + EBX = 20, + ESP = 21, + EBP = 22, + ESI = 23, + EDI = 24, + ES = 25, + CS = 26, + SS = 27, + DS = 28, + FS = 29, + GS = 30, + IP = 31, + RAX = 328, + RBX = 329, + RCX = 330, + RDX = 331, + RSI = 332, + RDI = 333, + RBP = 334, + RSP = 335, + R8 = 336, + R9 = 337, + R10 = 338, + R11 = 339, + R12 = 340, + R13 = 341, + R14 = 342, + R15 = 343, +}; + +enum class PDB_MemberAccess { Private = 1, Protected = 2, Public = 3 }; + +struct VersionInfo { + uint32_t Major; + uint32_t Minor; + uint32_t Build; + uint32_t QFE; +}; + +enum PDB_VariantType { + Empty, + Unknown, + Int8, + Int16, + Int32, + Int64, + Single, + Double, + UInt8, + UInt16, + UInt32, + UInt64, + Bool, +}; + +struct Variant { + Variant() + : Type(PDB_VariantType::Empty) { + } + + PDB_VariantType Type; + union { + bool Bool; + int8_t Int8; + int16_t Int16; + int32_t Int32; + int64_t Int64; + float Single; + double Double; + uint8_t UInt8; + uint16_t UInt16; + uint32_t UInt32; + uint64_t UInt64; + void* Pointer; + }; +}; + +} // namespace llvm + +namespace std { +template <> struct hash { + typedef llvm::PDB_SymType argument_type; + typedef std::size_t result_type; + + result_type operator()(const argument_type &Arg) const { + return std::hash()(static_cast(Arg)); + } +}; +} + +#endif diff --git a/include/llvm/ExecutionEngine/ExecutionEngine.h b/include/llvm/ExecutionEngine/ExecutionEngine.h index b9c0b61..17de5c7 100644 --- a/include/llvm/ExecutionEngine/ExecutionEngine.h +++ b/include/llvm/ExecutionEngine/ExecutionEngine.h @@ -138,10 +138,17 @@ protected: /// getMemoryforGV - Allocate memory for a global variable. virtual char *getMemoryForGV(const GlobalVariable *GV); - static ExecutionEngine *(*MCJITCtor)(std::unique_ptr M, - std::string *ErrorStr, - RTDyldMemoryManager *MCJMM, - std::unique_ptr TM); + static ExecutionEngine *(*MCJITCtor)( + std::unique_ptr M, + std::string *ErrorStr, + std::unique_ptr MCJMM, + std::unique_ptr TM); + + static ExecutionEngine *(*OrcMCJITReplacementCtor)( + std::string *ErrorStr, + std::unique_ptr OrcJMM, + std::unique_ptr TM); + static ExecutionEngine *(*InterpCtor)(std::unique_ptr M, std::string *ErrorStr); @@ -463,6 +470,7 @@ public: } protected: + ExecutionEngine() : EEState(*this) {} explicit ExecutionEngine(std::unique_ptr M); void emitGlobals(); @@ -492,7 +500,7 @@ private: EngineKind::Kind WhichEngine; std::string *ErrorStr; CodeGenOpt::Level OptLevel; - RTDyldMemoryManager *MCJMM; + std::unique_ptr MCJMM; TargetOptions Options; Reloc::Model RelocModel; CodeModel::Model CMModel; @@ -500,15 +508,20 @@ private: std::string MCPU; SmallVector MAttrs; bool VerifyModules; + bool UseOrcMCJITReplacement; /// InitEngine - Does the common initialization of default options. void InitEngine(); public: + /// Default constructor for EngineBuilder. + EngineBuilder(); + /// Constructor for EngineBuilder. - EngineBuilder(std::unique_ptr M) : M(std::move(M)) { - InitEngine(); - } + EngineBuilder(std::unique_ptr M); + + // Out-of-line since we don't have the def'n of RTDyldMemoryManager here. + ~EngineBuilder(); /// setEngineKind - Controls whether the user wants the interpreter, the JIT, /// or whichever engine works. This option defaults to EngineKind::Either. @@ -523,10 +536,7 @@ public: /// to create anything other than MCJIT will cause a runtime error. If create() /// is called and is successful, the created engine takes ownership of the /// memory manager. This option defaults to NULL. - EngineBuilder &setMCJITMemoryManager(RTDyldMemoryManager *mcjmm) { - MCJMM = mcjmm; - return *this; - } + EngineBuilder &setMCJITMemoryManager(std::unique_ptr mcjmm); /// setErrorStr - Set the error string to write to on error. This option /// defaults to NULL. @@ -591,6 +601,11 @@ public: return *this; } + // \brief Use OrcMCJITReplacement instead of MCJIT. Off by default. + void setUseOrcMCJITReplacement(bool UseOrcMCJITReplacement) { + this->UseOrcMCJITReplacement = UseOrcMCJITReplacement; + } + TargetMachine *selectTarget(); /// selectTarget - Pick a target either via -march or by guessing the native diff --git a/include/llvm/ExecutionEngine/JITEventListener.h b/include/llvm/ExecutionEngine/JITEventListener.h index cef3aa2..c3edec8 100644 --- a/include/llvm/ExecutionEngine/JITEventListener.h +++ b/include/llvm/ExecutionEngine/JITEventListener.h @@ -15,6 +15,7 @@ #ifndef LLVM_EXECUTIONENGINE_JITEVENTLISTENER_H #define LLVM_EXECUTIONENGINE_JITEVENTLISTENER_H +#include "RuntimeDyld.h" #include "llvm/Config/llvm-config.h" #include "llvm/IR/DebugLoc.h" #include "llvm/Support/DataTypes.h" @@ -25,7 +26,10 @@ class Function; class MachineFunction; class OProfileWrapper; class IntelJITEventsWrapper; -class ObjectImage; + +namespace object { + class ObjectFile; +} /// JITEvent_EmittedFunctionDetails - Helper struct for containing information /// about a generated machine code function. @@ -57,7 +61,7 @@ public: public: JITEventListener() {} - virtual ~JITEventListener(); + virtual ~JITEventListener() {} /// NotifyObjectEmitted - Called after an object has been successfully /// emitted to memory. NotifyFunctionEmitted will not be called for @@ -67,11 +71,15 @@ public: /// The ObjectImage contains the generated object image /// with section headers updated to reflect the address at which sections /// were loaded and with relocations performed in-place on debug sections. - virtual void NotifyObjectEmitted(const ObjectImage &Obj) {} + virtual void NotifyObjectEmitted(const object::ObjectFile &Obj, + const RuntimeDyld::LoadedObjectInfo &L) {} /// NotifyFreeingObject - Called just before the memory associated with /// a previously emitted object is released. - virtual void NotifyFreeingObject(const ObjectImage &Obj) {} + virtual void NotifyFreeingObject(const object::ObjectFile &Obj) {} + + // Get a pointe to the GDB debugger registration listener. + static JITEventListener *createGDBRegistrationListener(); #if LLVM_USE_INTEL_JITEVENTS // Construct an IntelJITEventListener @@ -105,7 +113,8 @@ public: return nullptr; } #endif // USE_OPROFILE - +private: + virtual void anchor(); }; } // end namespace llvm. diff --git a/include/llvm/ExecutionEngine/ObjectBuffer.h b/include/llvm/ExecutionEngine/ObjectBuffer.h deleted file mode 100644 index ee4820a..0000000 --- a/include/llvm/ExecutionEngine/ObjectBuffer.h +++ /dev/null @@ -1,76 +0,0 @@ -//===---- ObjectBuffer.h - Utility class to wrap object image memory -----===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file declares a wrapper class to hold the memory into which an -// object will be generated. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_EXECUTIONENGINE_OBJECTBUFFER_H -#define LLVM_EXECUTIONENGINE_OBJECTBUFFER_H - -#include "llvm/ADT/SmallVector.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/raw_ostream.h" - -namespace llvm { - -/// This class acts as a container for the memory buffer used during generation -/// and loading of executable objects using MCJIT and RuntimeDyld. The -/// underlying memory for the object will be owned by the ObjectBuffer instance -/// throughout its lifetime. -class ObjectBuffer { - virtual void anchor(); -public: - ObjectBuffer() {} - ObjectBuffer(std::unique_ptr Buf) : Buffer(std::move(Buf)) {} - virtual ~ObjectBuffer() {} - - MemoryBufferRef getMemBuffer() const { return Buffer->getMemBufferRef(); } - - const char *getBufferStart() const { return Buffer->getBufferStart(); } - size_t getBufferSize() const { return Buffer->getBufferSize(); } - StringRef getBuffer() const { return Buffer->getBuffer(); } - StringRef getBufferIdentifier() const { - return Buffer->getBufferIdentifier(); - } - -protected: - // The memory contained in an ObjectBuffer - std::unique_ptr Buffer; -}; - -/// This class encapsulates the SmallVector and raw_svector_ostream needed to -/// generate an object using MC code emission while providing a common -/// ObjectBuffer interface for access to the memory once the object has been -/// generated. -class ObjectBufferStream : public ObjectBuffer { - void anchor() override; -public: - ObjectBufferStream() : OS(SV) {} - virtual ~ObjectBufferStream() {} - - raw_ostream &getOStream() { return OS; } - void flush() - { - OS.flush(); - - // Make the data accessible via the ObjectBuffer::Buffer - Buffer = - MemoryBuffer::getMemBuffer(StringRef(SV.data(), SV.size()), "", false); - } - -protected: - SmallVector SV; // Working buffer into which we JIT. - raw_svector_ostream OS; // streaming wrapper -}; - -} // namespace llvm - -#endif diff --git a/include/llvm/ExecutionEngine/ObjectImage.h b/include/llvm/ExecutionEngine/ObjectImage.h deleted file mode 100644 index dc142bd..0000000 --- a/include/llvm/ExecutionEngine/ObjectImage.h +++ /dev/null @@ -1,76 +0,0 @@ -//===---- ObjectImage.h - Format independent executuable object image -----===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file declares a file format independent ObjectImage class. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_EXECUTIONENGINE_OBJECTIMAGE_H -#define LLVM_EXECUTIONENGINE_OBJECTIMAGE_H - -#include "llvm/ExecutionEngine/ObjectBuffer.h" -#include "llvm/Object/ObjectFile.h" - -namespace llvm { - - -/// ObjectImage - A container class that represents an ObjectFile that has been -/// or is in the process of being loaded into memory for execution. -class ObjectImage { - ObjectImage() LLVM_DELETED_FUNCTION; - ObjectImage(const ObjectImage &other) LLVM_DELETED_FUNCTION; - virtual void anchor(); - -protected: - std::unique_ptr Buffer; - -public: - ObjectImage(std::unique_ptr Input) : Buffer(std::move(Input)) {} - virtual ~ObjectImage() {} - - virtual object::symbol_iterator begin_symbols() const = 0; - virtual object::symbol_iterator end_symbols() const = 0; - iterator_range symbols() const { - return iterator_range(begin_symbols(), - end_symbols()); - } - - virtual object::section_iterator begin_sections() const = 0; - virtual object::section_iterator end_sections() const = 0; - iterator_range sections() const { - return iterator_range(begin_sections(), - end_sections()); - } - - virtual /* Triple::ArchType */ unsigned getArch() const = 0; - - // Return the name associated with this ObjectImage. - // This is usually the name of the file or MemoryBuffer that the the - // ObjectBuffer was constructed from. - StringRef getImageName() const { return Buffer->getBufferIdentifier(); } - - // Subclasses can override these methods to update the image with loaded - // addresses for sections and common symbols - virtual void updateSectionAddress(const object::SectionRef &Sec, - uint64_t Addr) = 0; - virtual void updateSymbolAddress(const object::SymbolRef &Sym, - uint64_t Addr) = 0; - - virtual StringRef getData() const = 0; - - virtual object::ObjectFile* getObjectFile() const = 0; - - // Subclasses can override these methods to provide JIT debugging support - virtual void registerWithDebugger() = 0; - virtual void deregisterWithDebugger() = 0; -}; - -} // end namespace llvm - -#endif // LLVM_EXECUTIONENGINE_OBJECTIMAGE_H diff --git a/include/llvm/ExecutionEngine/ObjectMemoryBuffer.h b/include/llvm/ExecutionEngine/ObjectMemoryBuffer.h new file mode 100644 index 0000000..b075611 --- /dev/null +++ b/include/llvm/ExecutionEngine/ObjectMemoryBuffer.h @@ -0,0 +1,63 @@ +//===- ObjectMemoryBuffer.h - SmallVector-backed MemoryBuffrer -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares a wrapper class to hold the memory into which an +// object will be generated. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_OBJECTMEMORYBUFFER_H +#define LLVM_EXECUTIONENGINE_OBJECTMEMORYBUFFER_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/raw_ostream.h" + +namespace llvm { + +/// \brief SmallVector-backed MemoryBuffer instance. +/// +/// This class enables efficient construction of MemoryBuffers from SmallVector +/// instances. This is useful for MCJIT and Orc, where object files are streamed +/// into SmallVectors, then inspected using ObjectFile (which takes a +/// MemoryBuffer). +class ObjectMemoryBuffer : public MemoryBuffer { +public: + + /// \brief Construct an ObjectMemoryBuffer from the given SmallVector r-value. + /// + /// FIXME: It'd be nice for this to be a non-templated constructor taking a + /// SmallVectorImpl here instead of a templated one taking a SmallVector, + /// but SmallVector's move-construction/assignment currently only take + /// SmallVectors. If/when that is fixed we can simplify this constructor and + /// the following one. + ObjectMemoryBuffer(SmallVectorImpl &&SV) + : SV(std::move(SV)), BufferName("") { + init(this->SV.begin(), this->SV.end(), false); + } + + /// \brief Construct a named ObjectMemoryBuffer from the given SmallVector + /// r-value and StringRef. + ObjectMemoryBuffer(SmallVectorImpl &&SV, StringRef Name) + : SV(std::move(SV)), BufferName(Name) { + init(this->SV.begin(), this->SV.end(), false); + } + + const char* getBufferIdentifier() const override { return BufferName.c_str(); } + + BufferKind getBufferKind() const override { return MemoryBuffer_Malloc; } + +private: + SmallVector SV; + std::string BufferName; +}; + +} // namespace llvm + +#endif diff --git a/include/llvm/ExecutionEngine/Orc/CloneSubModule.h b/include/llvm/ExecutionEngine/Orc/CloneSubModule.h new file mode 100644 index 0000000..1bd3955 --- /dev/null +++ b/include/llvm/ExecutionEngine/Orc/CloneSubModule.h @@ -0,0 +1,60 @@ +//===-- CloneSubModule.h - Utilities for extracting sub-modules -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Contains utilities for extracting sub-modules. Useful for breaking up modules +// for lazy jitting. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_ORC_CLONESUBMODULE_H +#define LLVM_EXECUTIONENGINE_ORC_CLONESUBMODULE_H + +#include "llvm/ADT/DenseSet.h" +#include "llvm/Transforms/Utils/ValueMapper.h" +#include + +namespace llvm { + +class Function; +class GlobalVariable; +class Module; + +namespace orc { + +/// @brief Functor type for describing how CloneSubModule should mutate a +/// GlobalVariable. +typedef std::function HandleGlobalVariableFtor; + +/// @brief Functor type for describing how CloneSubModule should mutate a +/// Function. +typedef std::function + HandleFunctionFtor; + +/// @brief Copies the initializer from Orig to New. +/// +/// Type is suitable for implicit conversion to a HandleGlobalVariableFtor. +void copyGVInitializer(GlobalVariable &New, const GlobalVariable &Orig, + ValueToValueMapTy &VMap); + +/// @brief Copies the body of Orig to New. +/// +/// Type is suitable for implicit conversion to a HandleFunctionFtor. +void copyFunctionBody(Function &New, const Function &Orig, + ValueToValueMapTy &VMap); + +/// @brief Clone a subset of the module Src into Dst. +void CloneSubModule(Module &Dst, const Module &Src, + HandleGlobalVariableFtor HandleGlobalVariable, + HandleFunctionFtor HandleFunction, bool KeepInlineAsm); + +} // End namespace orc. +} // End namespace llvm. + +#endif // LLVM_EXECUTIONENGINE_ORC_CLONESUBMODULE_H diff --git a/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h b/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h new file mode 100644 index 0000000..0e218e2 --- /dev/null +++ b/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h @@ -0,0 +1,355 @@ +//===- CompileOnDemandLayer.h - Compile each function on demand -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// JIT layer for breaking up modules and inserting callbacks to allow +// individual functions to be compiled on demand. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_ORC_COMPILEONDEMANDLAYER_H +#define LLVM_EXECUTIONENGINE_ORC_COMPILEONDEMANDLAYER_H + +#include "IndirectionUtils.h" +#include "LookasideRTDyldMM.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ExecutionEngine/SectionMemoryManager.h" +#include + +namespace llvm { +namespace orc { + +/// @brief Compile-on-demand layer. +/// +/// Modules added to this layer have their calls indirected, and are then +/// broken up into a set of single-function modules, each of which is added +/// to the layer below in a singleton set. The lower layer can be any layer that +/// accepts IR module sets. +/// +/// It is expected that this layer will frequently be used on top of a +/// LazyEmittingLayer. The combination of the two ensures that each function is +/// compiled only when it is first called. +template +class CompileOnDemandLayer { +public: + /// @brief Lookup helper that provides compatibility with the classic + /// static-compilation symbol resolution process. + /// + /// The CompileOnDemand (COD) layer splits modules up into multiple + /// sub-modules, each held in its own llvm::Module instance, in order to + /// support lazy compilation. When a module that contains private symbols is + /// broken up symbol linkage changes may be required to enable access to + /// "private" data that now resides in a different llvm::Module instance. To + /// retain expected symbol resolution behavior for clients of the COD layer, + /// the CODScopedLookup class uses a two-tiered lookup system to resolve + /// symbols. Lookup first scans sibling modules that were split from the same + /// original module (logical-module scoped lookup), then scans all other + /// modules that have been added to the lookup scope (logical-dylib scoped + /// lookup). + class CODScopedLookup { + private: + typedef typename BaseLayerT::ModuleSetHandleT BaseLayerModuleSetHandleT; + typedef std::vector SiblingHandlesList; + typedef std::list PseudoDylibModuleSetHandlesList; + + public: + /// @brief Handle for a logical module. + typedef typename PseudoDylibModuleSetHandlesList::iterator LMHandle; + + /// @brief Construct a scoped lookup. + CODScopedLookup(BaseLayerT &BaseLayer) : BaseLayer(BaseLayer) {} + + /// @brief Start a new context for a single logical module. + LMHandle createLogicalModule() { + Handles.push_back(SiblingHandlesList()); + return std::prev(Handles.end()); + } + + /// @brief Add a concrete Module's handle to the given logical Module's + /// lookup scope. + void addToLogicalModule(LMHandle LMH, BaseLayerModuleSetHandleT H) { + LMH->push_back(H); + } + + /// @brief Remove a logical Module from the CODScopedLookup entirely. + void removeLogicalModule(LMHandle LMH) { Handles.erase(LMH); } + + /// @brief Look up a symbol in this context. + JITSymbol findSymbol(LMHandle LMH, const std::string &Name) { + if (auto Symbol = findSymbolIn(LMH, Name)) + return Symbol; + + for (auto I = Handles.begin(), E = Handles.end(); I != E; ++I) + if (I != LMH) + if (auto Symbol = findSymbolIn(I, Name)) + return Symbol; + + return nullptr; + } + + private: + + JITSymbol findSymbolIn(LMHandle LMH, const std::string &Name) { + for (auto H : *LMH) + if (auto Symbol = BaseLayer.findSymbolIn(H, Name, false)) + return Symbol; + return nullptr; + } + + BaseLayerT &BaseLayer; + PseudoDylibModuleSetHandlesList Handles; + }; + +private: + typedef typename BaseLayerT::ModuleSetHandleT BaseLayerModuleSetHandleT; + typedef std::vector BaseLayerModuleSetHandleListT; + + struct ModuleSetInfo { + // Symbol lookup - just one for the whole module set. + std::shared_ptr Lookup; + + // Logical module handles. + std::vector LMHandles; + + // List of vectors of module set handles: + // One vector per logical module - each vector holds the handles for the + // exploded modules for that logical module in the base layer. + BaseLayerModuleSetHandleListT BaseLayerModuleSetHandles; + + ModuleSetInfo(std::shared_ptr Lookup) + : Lookup(std::move(Lookup)) {} + + void releaseResources(BaseLayerT &BaseLayer) { + for (auto LMH : LMHandles) + Lookup->removeLogicalModule(LMH); + for (auto H : BaseLayerModuleSetHandles) + BaseLayer.removeModuleSet(H); + } + }; + + typedef std::list ModuleSetInfoListT; + +public: + /// @brief Handle to a set of loaded modules. + typedef typename ModuleSetInfoListT::iterator ModuleSetHandleT; + + // @brief Fallback lookup functor. + typedef std::function LookupFtor; + + /// @brief Construct a compile-on-demand layer instance. + CompileOnDemandLayer(BaseLayerT &BaseLayer, LLVMContext &Context) + : BaseLayer(BaseLayer), + CompileCallbackMgr(BaseLayer, Context, 0, 64) {} + + /// @brief Add a module to the compile-on-demand layer. + template + ModuleSetHandleT addModuleSet(ModuleSetT Ms, + LookupFtor FallbackLookup = nullptr) { + + // If the user didn't supply a fallback lookup then just use + // getSymbolAddress. + if (!FallbackLookup) + FallbackLookup = [=](const std::string &Name) { + return findSymbol(Name, true).getAddress(); + }; + + // Create a lookup context and ModuleSetInfo for this module set. + // For the purposes of symbol resolution the set Ms will be treated as if + // the modules it contained had been linked together as a dylib. + auto DylibLookup = std::make_shared(BaseLayer); + ModuleSetHandleT H = + ModuleSetInfos.insert(ModuleSetInfos.end(), ModuleSetInfo(DylibLookup)); + ModuleSetInfo &MSI = ModuleSetInfos.back(); + + // Process each of the modules in this module set. + for (auto &M : Ms) + partitionAndAdd(*M, MSI, FallbackLookup); + + return H; + } + + /// @brief Remove the module represented by the given handle. + /// + /// This will remove all modules in the layers below that were derived from + /// the module represented by H. + void removeModuleSet(ModuleSetHandleT H) { + H->releaseResources(BaseLayer); + ModuleSetInfos.erase(H); + } + + /// @brief Search for the given named symbol. + /// @param Name The name of the symbol to search for. + /// @param ExportedSymbolsOnly If true, search only for exported symbols. + /// @return A handle for the given named symbol, if it exists. + JITSymbol findSymbol(StringRef Name, bool ExportedSymbolsOnly) { + return BaseLayer.findSymbol(Name, ExportedSymbolsOnly); + } + + /// @brief Get the address of a symbol provided by this layer, or some layer + /// below this one. + JITSymbol findSymbolIn(ModuleSetHandleT H, const std::string &Name, + bool ExportedSymbolsOnly) { + BaseLayerModuleSetHandleListT &BaseLayerHandles = H->second; + for (auto &BH : BaseLayerHandles) { + if (auto Symbol = BaseLayer.findSymbolIn(BH, Name, ExportedSymbolsOnly)) + return Symbol; + } + return nullptr; + } + +private: + + void partitionAndAdd(Module &M, ModuleSetInfo &MSI, + LookupFtor FallbackLookup) { + const char *AddrSuffix = "$orc_addr"; + const char *BodySuffix = "$orc_body"; + + // We're going to break M up into a bunch of sub-modules, but we want + // internal linkage symbols to still resolve sensibly. CODScopedLookup + // provides the "logical module" concept to make this work, so create a + // new logical module for M. + auto DylibLookup = MSI.Lookup; + auto LogicalModule = DylibLookup->createLogicalModule(); + MSI.LMHandles.push_back(LogicalModule); + + // Partition M into a "globals and stubs" module, a "common symbols" module, + // and a list of single-function modules. + auto PartitionedModule = fullyPartition(M); + auto StubsModule = std::move(PartitionedModule.GlobalVars); + auto CommonsModule = std::move(PartitionedModule.Commons); + auto FunctionModules = std::move(PartitionedModule.Functions); + + // Emit the commons stright away. + auto CommonHandle = addModule(std::move(CommonsModule), MSI, LogicalModule, + FallbackLookup); + BaseLayer.emitAndFinalize(CommonHandle); + + // Map of definition names to callback-info data structures. We'll use + // this to build the compile actions for the stubs below. + typedef std::map + StubInfoMap; + StubInfoMap StubInfos; + + // Now we need to take each of the extracted Modules and add them to + // base layer. Each Module will be added individually to make sure they + // can be compiled separately, and each will get its own lookaside + // memory manager that will resolve within this logical module first. + for (auto &SubM : FunctionModules) { + + // Keep track of the stubs we create for this module so that we can set + // their compile actions. + std::vector NewStubInfos; + + // Search for function definitions and insert stubs into the stubs + // module. + for (auto &F : *SubM) { + if (F.isDeclaration()) + continue; + + std::string Name = F.getName(); + Function *Proto = StubsModule->getFunction(Name); + assert(Proto && "Failed to clone function decl into stubs module."); + auto CallbackInfo = + CompileCallbackMgr.getCompileCallback(*Proto->getFunctionType()); + GlobalVariable *FunctionBodyPointer = + createImplPointer(*Proto, Name + AddrSuffix, + CallbackInfo.getAddress()); + makeStub(*Proto, *FunctionBodyPointer); + + F.setName(Name + BodySuffix); + F.setVisibility(GlobalValue::HiddenVisibility); + + auto KV = std::make_pair(std::move(Name), std::move(CallbackInfo)); + NewStubInfos.push_back(StubInfos.insert(StubInfos.begin(), KV)); + } + + auto H = addModule(std::move(SubM), MSI, LogicalModule, FallbackLookup); + + // Set the compile actions for this module: + for (auto &KVPair : NewStubInfos) { + std::string BodyName = Mangle(KVPair->first + BodySuffix, + *M.getDataLayout()); + auto &CCInfo = KVPair->second; + CCInfo.setCompileAction( + [=](){ + return BaseLayer.findSymbolIn(H, BodyName, false).getAddress(); + }); + } + + } + + // Ok - we've processed all the partitioned modules. Now add the + // stubs/globals module and set the update actions. + auto StubsH = + addModule(std::move(StubsModule), MSI, LogicalModule, FallbackLookup); + + for (auto &KVPair : StubInfos) { + std::string AddrName = Mangle(KVPair.first + AddrSuffix, + *M.getDataLayout()); + auto &CCInfo = KVPair.second; + CCInfo.setUpdateAction( + CompileCallbackMgr.getLocalFPUpdater(StubsH, AddrName)); + } + } + + // Add the given Module to the base layer using a memory manager that will + // perform the appropriate scoped lookup (i.e. will look first with in the + // module from which it was extracted, then into the set to which that module + // belonged, and finally externally). + BaseLayerModuleSetHandleT addModule( + std::unique_ptr M, + ModuleSetInfo &MSI, + typename CODScopedLookup::LMHandle LogicalModule, + LookupFtor FallbackLookup) { + + // Add this module to the JIT with a memory manager that uses the + // DylibLookup to resolve symbols. + std::vector> MSet; + MSet.push_back(std::move(M)); + + auto DylibLookup = MSI.Lookup; + auto MM = + createLookasideRTDyldMM( + [=](const std::string &Name) { + if (auto Symbol = DylibLookup->findSymbol(LogicalModule, Name)) + return Symbol.getAddress(); + return FallbackLookup(Name); + }, + [=](const std::string &Name) { + return DylibLookup->findSymbol(LogicalModule, Name).getAddress(); + }); + + BaseLayerModuleSetHandleT H = + BaseLayer.addModuleSet(std::move(MSet), std::move(MM)); + // Add this module to the logical module lookup. + DylibLookup->addToLogicalModule(LogicalModule, H); + MSI.BaseLayerModuleSetHandles.push_back(H); + + return H; + } + + static std::string Mangle(StringRef Name, const DataLayout &DL) { + Mangler M(&DL); + std::string MangledName; + { + raw_string_ostream MangledNameStream(MangledName); + M.getNameWithPrefix(MangledNameStream, Name); + } + return MangledName; + } + + BaseLayerT &BaseLayer; + CompileCallbackMgrT CompileCallbackMgr; + ModuleSetInfoListT ModuleSetInfos; +}; + +} // End namespace orc. +} // End namespace llvm. + +#endif // LLVM_EXECUTIONENGINE_ORC_COMPILEONDEMANDLAYER_H diff --git a/include/llvm/ExecutionEngine/Orc/CompileUtils.h b/include/llvm/ExecutionEngine/Orc/CompileUtils.h new file mode 100644 index 0000000..49a1fba --- /dev/null +++ b/include/llvm/ExecutionEngine/Orc/CompileUtils.h @@ -0,0 +1,62 @@ +//===-- CompileUtils.h - Utilities for compiling IR in the JIT --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Contains utilities for compiling IR to object files. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_ORC_COMPILEUTILS_H +#define LLVM_EXECUTIONENGINE_ORC_COMPILEUTILS_H + +#include "llvm/ExecutionEngine/ObjectMemoryBuffer.h" +#include "llvm/IR/LegacyPassManager.h" +#include "llvm/MC/MCContext.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm/Target/TargetMachine.h" + +namespace llvm { +namespace orc { + +/// @brief Simple compile functor: Takes a single IR module and returns an +/// ObjectFile. +class SimpleCompiler { +public: + /// @brief Construct a simple compile functor with the given target. + SimpleCompiler(TargetMachine &TM) : TM(TM) {} + + /// @brief Compile a Module to an ObjectFile. + object::OwningBinary operator()(Module &M) const { + SmallVector ObjBufferSV; + raw_svector_ostream ObjStream(ObjBufferSV); + + legacy::PassManager PM; + MCContext *Ctx; + if (TM.addPassesToEmitMC(PM, Ctx, ObjStream)) + llvm_unreachable("Target does not support MC emission."); + PM.run(M); + ObjStream.flush(); + std::unique_ptr ObjBuffer( + new ObjectMemoryBuffer(std::move(ObjBufferSV))); + ErrorOr> Obj = + object::ObjectFile::createObjectFile(ObjBuffer->getMemBufferRef()); + // TODO: Actually report errors helpfully. + typedef object::OwningBinary OwningObj; + if (Obj) + return OwningObj(std::move(*Obj), std::move(ObjBuffer)); + return OwningObj(nullptr, nullptr); + } + +private: + TargetMachine &TM; +}; + +} // End namespace orc. +} // End namespace llvm. + +#endif // LLVM_EXECUTIONENGINE_ORC_COMPILEUTILS_H diff --git a/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h b/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h new file mode 100644 index 0000000..6a47622 --- /dev/null +++ b/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h @@ -0,0 +1,146 @@ +//===------ IRCompileLayer.h -- Eagerly compile IR for JIT ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Contains the definition for a basic, eagerly compiling layer of the JIT. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_ORC_IRCOMPILELAYER_H +#define LLVM_EXECUTIONENGINE_ORC_IRCOMPILELAYER_H + +#include "JITSymbol.h" +#include "llvm/ExecutionEngine/ObjectCache.h" +#include "llvm/ExecutionEngine/RTDyldMemoryManager.h" +#include "llvm/Object/ObjectFile.h" +#include + +namespace llvm { +namespace orc { + +/// @brief Eager IR compiling layer. +/// +/// This layer accepts sets of LLVM IR Modules (via addModuleSet). It +/// immediately compiles each IR module to an object file (each IR Module is +/// compiled separately). The resulting set of object files is then added to +/// the layer below, which must implement the object layer concept. +template class IRCompileLayer { +public: + typedef std::function(Module &)> + CompileFtor; + +private: + typedef typename BaseLayerT::ObjSetHandleT ObjSetHandleT; + + typedef std::vector> OwningObjectVec; + typedef std::vector> OwningBufferVec; + +public: + /// @brief Handle to a set of compiled modules. + typedef ObjSetHandleT ModuleSetHandleT; + + /// @brief Construct an IRCompileLayer with the given BaseLayer, which must + /// implement the ObjectLayer concept. + IRCompileLayer(BaseLayerT &BaseLayer, CompileFtor Compile) + : BaseLayer(BaseLayer), Compile(std::move(Compile)), ObjCache(nullptr) {} + + /// @brief Set an ObjectCache to query before compiling. + void setObjectCache(ObjectCache *NewCache) { ObjCache = NewCache; } + + /// @brief Compile each module in the given module set, then then add the + /// resulting set of objects to the base layer, along with the memory + // manager MM. + /// + /// @return A handle for the added modules. + template + ModuleSetHandleT addModuleSet(ModuleSetT Ms, + std::unique_ptr MM) { + OwningObjectVec Objects; + OwningBufferVec Buffers; + + for (const auto &M : Ms) { + std::unique_ptr Object; + std::unique_ptr Buffer; + + if (ObjCache) + std::tie(Object, Buffer) = tryToLoadFromObjectCache(*M).takeBinary(); + + if (!Object) { + std::tie(Object, Buffer) = Compile(*M).takeBinary(); + if (ObjCache) + ObjCache->notifyObjectCompiled(&*M, Buffer->getMemBufferRef()); + } + + Objects.push_back(std::move(Object)); + Buffers.push_back(std::move(Buffer)); + } + + ModuleSetHandleT H = + BaseLayer.addObjectSet(Objects, std::move(MM)); + + BaseLayer.takeOwnershipOfBuffers(H, std::move(Buffers)); + + return H; + } + + /// @brief Remove the module set associated with the handle H. + void removeModuleSet(ModuleSetHandleT H) { BaseLayer.removeObjectSet(H); } + + /// @brief Search for the given named symbol. + /// @param Name The name of the symbol to search for. + /// @param ExportedSymbolsOnly If true, search only for exported symbols. + /// @return A handle for the given named symbol, if it exists. + JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) { + return BaseLayer.findSymbol(Name, ExportedSymbolsOnly); + } + + /// @brief Get the address of the given symbol in the context of the set of + /// compiled modules represented by the handle H. This call is + /// forwarded to the base layer's implementation. + /// @param H The handle for the module set to search in. + /// @param Name The name of the symbol to search for. + /// @param ExportedSymbolsOnly If true, search only for exported symbols. + /// @return A handle for the given named symbol, if it is found in the + /// given module set. + JITSymbol findSymbolIn(ModuleSetHandleT H, const std::string &Name, + bool ExportedSymbolsOnly) { + return BaseLayer.findSymbolIn(H, Name, ExportedSymbolsOnly); + } + + /// @brief Immediately emit and finalize the moduleOB set represented by the + /// given handle. + /// @param H Handle for module set to emit/finalize. + void emitAndFinalize(ModuleSetHandleT H) { + BaseLayer.emitAndFinalize(H); + } + +private: + object::OwningBinary + tryToLoadFromObjectCache(const Module &M) { + std::unique_ptr ObjBuffer = ObjCache->getObject(&M); + if (!ObjBuffer) + return object::OwningBinary(); + + ErrorOr> Obj = + object::ObjectFile::createObjectFile(ObjBuffer->getMemBufferRef()); + if (!Obj) + return object::OwningBinary(); + + return object::OwningBinary(std::move(*Obj), + std::move(ObjBuffer)); + } + + BaseLayerT &BaseLayer; + CompileFtor Compile; + ObjectCache *ObjCache; +}; + +} // End namespace orc. +} // End namespace llvm. + +#endif // LLVM_EXECUTIONENGINE_ORC_IRCOMPILINGLAYER_H diff --git a/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h b/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h new file mode 100644 index 0000000..e9d3d34 --- /dev/null +++ b/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h @@ -0,0 +1,246 @@ +//===-- IndirectionUtils.h - Utilities for adding indirections --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Contains utilities for adding indirections and breaking up modules. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_ORC_INDIRECTIONUTILS_H +#define LLVM_EXECUTIONENGINE_ORC_INDIRECTIONUTILS_H + +#include "JITSymbol.h" +#include "llvm/ADT/DenseSet.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/Mangler.h" +#include "llvm/IR/Module.h" +#include + +namespace llvm { +namespace orc { + +/// @brief Base class for JITLayer independent aspects of +/// JITCompileCallbackManager. +template +class JITCompileCallbackManagerBase { +public: + + /// @brief Construct a JITCompileCallbackManagerBase. + /// @param ErrorHandlerAddress The address of an error handler in the target + /// process to be used if a compile callback fails. + /// @param NumTrampolinesPerBlock Number of trampolines to emit if there is no + /// available trampoline when getCompileCallback is + /// called. + JITCompileCallbackManagerBase(TargetAddress ErrorHandlerAddress, + unsigned NumTrampolinesPerBlock) + : ErrorHandlerAddress(ErrorHandlerAddress), + NumTrampolinesPerBlock(NumTrampolinesPerBlock) {} + + /// @brief Execute the callback for the given trampoline id. Called by the JIT + /// to compile functions on demand. + TargetAddress executeCompileCallback(TargetAddress TrampolineID) { + typename TrampolineMapT::iterator I = ActiveTrampolines.find(TrampolineID); + // FIXME: Also raise an error in the Orc error-handler when we finally have + // one. + if (I == ActiveTrampolines.end()) + return ErrorHandlerAddress; + + // Found a callback handler. Yank this trampoline out of the active list and + // put it back in the available trampolines list, then try to run the + // handler's compile and update actions. + // Moving the trampoline ID back to the available list first means there's at + // least one available trampoline if the compile action triggers a request for + // a new one. + AvailableTrampolines.push_back(I->first - TargetT::CallSize); + auto CallbackHandler = std::move(I->second); + ActiveTrampolines.erase(I); + + if (auto Addr = CallbackHandler.Compile()) { + CallbackHandler.Update(Addr); + return Addr; + } + return ErrorHandlerAddress; + } + +protected: + + typedef std::function CompileFtorT; + typedef std::function UpdateFtorT; + + struct CallbackHandler { + CompileFtorT Compile; + UpdateFtorT Update; + }; + + TargetAddress ErrorHandlerAddress; + unsigned NumTrampolinesPerBlock; + + typedef std::map TrampolineMapT; + TrampolineMapT ActiveTrampolines; + std::vector AvailableTrampolines; +}; + +/// @brief Manage compile callbacks. +template +class JITCompileCallbackManager : + public JITCompileCallbackManagerBase { +public: + + typedef typename JITCompileCallbackManagerBase::CompileFtorT + CompileFtorT; + typedef typename JITCompileCallbackManagerBase::UpdateFtorT + UpdateFtorT; + + /// @brief Construct a JITCompileCallbackManager. + /// @param JIT JIT layer to emit callback trampolines, etc. into. + /// @param Context LLVMContext to use for trampoline & resolve block modules. + /// @param ErrorHandlerAddress The address of an error handler in the target + /// process to be used if a compile callback fails. + /// @param NumTrampolinesPerBlock Number of trampolines to allocate whenever + /// there is no existing callback trampoline. + /// (Trampolines are allocated in blocks for + /// efficiency.) + JITCompileCallbackManager(JITLayerT &JIT, LLVMContext &Context, + TargetAddress ErrorHandlerAddress, + unsigned NumTrampolinesPerBlock) + : JITCompileCallbackManagerBase(ErrorHandlerAddress, + NumTrampolinesPerBlock), + JIT(JIT) { + emitResolverBlock(Context); + } + + /// @brief Handle to a newly created compile callback. Can be used to get an + /// IR constant representing the address of the trampoline, and to set + /// the compile and update actions for the callback. + class CompileCallbackInfo { + public: + CompileCallbackInfo(Constant *Addr, CompileFtorT &Compile, + UpdateFtorT &Update) + : Addr(Addr), Compile(Compile), Update(Update) {} + + Constant* getAddress() const { return Addr; } + void setCompileAction(CompileFtorT Compile) { + this->Compile = std::move(Compile); + } + void setUpdateAction(UpdateFtorT Update) { + this->Update = std::move(Update); + } + private: + Constant *Addr; + CompileFtorT &Compile; + UpdateFtorT &Update; + }; + + /// @brief Get/create a compile callback with the given signature. + CompileCallbackInfo getCompileCallback(FunctionType &FT) { + TargetAddress TrampolineAddr = getAvailableTrampolineAddr(FT.getContext()); + auto &CallbackHandler = + this->ActiveTrampolines[TrampolineAddr + TargetT::CallSize]; + Constant *AddrIntVal = + ConstantInt::get(Type::getInt64Ty(FT.getContext()), TrampolineAddr); + Constant *AddrPtrVal = + ConstantExpr::getCast(Instruction::IntToPtr, AddrIntVal, + PointerType::get(&FT, 0)); + + return CompileCallbackInfo(AddrPtrVal, CallbackHandler.Compile, + CallbackHandler.Update); + } + + /// @brief Get a functor for updating the value of a named function pointer. + UpdateFtorT getLocalFPUpdater(typename JITLayerT::ModuleSetHandleT H, + std::string Name) { + // FIXME: Move-capture Name once we can use C++14. + return [=](TargetAddress Addr) { + auto FPSym = JIT.findSymbolIn(H, Name, true); + assert(FPSym && "Cannot find function pointer to update."); + void *FPAddr = reinterpret_cast( + static_cast(FPSym.getAddress())); + memcpy(FPAddr, &Addr, sizeof(uintptr_t)); + }; + } + +private: + + std::vector> + SingletonSet(std::unique_ptr M) { + std::vector> Ms; + Ms.push_back(std::move(M)); + return Ms; + } + + void emitResolverBlock(LLVMContext &Context) { + std::unique_ptr M(new Module("resolver_block_module", + Context)); + TargetT::insertResolverBlock(*M, *this); + auto H = JIT.addModuleSet(SingletonSet(std::move(M)), nullptr); + JIT.emitAndFinalize(H); + auto ResolverBlockSymbol = + JIT.findSymbolIn(H, TargetT::ResolverBlockName, false); + assert(ResolverBlockSymbol && "Failed to insert resolver block"); + ResolverBlockAddr = ResolverBlockSymbol.getAddress(); + } + + TargetAddress getAvailableTrampolineAddr(LLVMContext &Context) { + if (this->AvailableTrampolines.empty()) + grow(Context); + assert(!this->AvailableTrampolines.empty() && + "Failed to grow available trampolines."); + TargetAddress TrampolineAddr = this->AvailableTrampolines.back(); + this->AvailableTrampolines.pop_back(); + return TrampolineAddr; + } + + void grow(LLVMContext &Context) { + assert(this->AvailableTrampolines.empty() && "Growing prematurely?"); + std::unique_ptr M(new Module("trampoline_block", Context)); + auto GetLabelName = + TargetT::insertCompileCallbackTrampolines(*M, ResolverBlockAddr, + this->NumTrampolinesPerBlock, + this->ActiveTrampolines.size()); + auto H = JIT.addModuleSet(SingletonSet(std::move(M)), nullptr); + JIT.emitAndFinalize(H); + for (unsigned I = 0; I < this->NumTrampolinesPerBlock; ++I) { + std::string Name = GetLabelName(I); + auto TrampolineSymbol = JIT.findSymbolIn(H, Name, false); + assert(TrampolineSymbol && "Failed to emit trampoline."); + this->AvailableTrampolines.push_back(TrampolineSymbol.getAddress()); + } + } + + JITLayerT &JIT; + TargetAddress ResolverBlockAddr; +}; + +GlobalVariable* createImplPointer(Function &F, const Twine &Name, + Constant *Initializer); + +void makeStub(Function &F, GlobalVariable &ImplPointer); + +typedef std::map> ModulePartitionMap; + +void partition(Module &M, const ModulePartitionMap &PMap); + +/// @brief Struct for trivial "complete" partitioning of a module. +class FullyPartitionedModule { +public: + std::unique_ptr GlobalVars; + std::unique_ptr Commons; + std::vector> Functions; + + FullyPartitionedModule() = default; + FullyPartitionedModule(FullyPartitionedModule &&S) + : GlobalVars(std::move(S.GlobalVars)), Commons(std::move(S.Commons)), + Functions(std::move(S.Functions)) {} +}; + +FullyPartitionedModule fullyPartition(Module &M); + +} // End namespace orc. +} // End namespace llvm. + +#endif // LLVM_EXECUTIONENGINE_ORC_INDIRECTIONUTILS_H diff --git a/include/llvm/ExecutionEngine/Orc/JITSymbol.h b/include/llvm/ExecutionEngine/Orc/JITSymbol.h new file mode 100644 index 0000000..a670222 --- /dev/null +++ b/include/llvm/ExecutionEngine/Orc/JITSymbol.h @@ -0,0 +1,74 @@ +//===----------- JITSymbol.h - JIT symbol abstraction -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Abstraction for target process addresses. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_ORC_JITSYMBOL_H +#define LLVM_EXECUTIONENGINE_ORC_JITSYMBOL_H + +#include "llvm/Support/DataTypes.h" +#include +#include + +namespace llvm { +namespace orc { + +/// @brief Represents an address in the target process's address space. +typedef uint64_t TargetAddress; + +/// @brief Represents a symbol in the JIT. +class JITSymbol { +public: + typedef std::function GetAddressFtor; + + /// @brief Create a 'null' symbol that represents failure to find a symbol + /// definition. + JITSymbol(std::nullptr_t) : CachedAddr(0) {} + + /// @brief Create a symbol for a definition with a known address. + JITSymbol(TargetAddress Addr) + : CachedAddr(Addr) {} + + /// @brief Create a symbol for a definition that doesn't have a known address + /// yet. + /// @param GetAddress A functor to materialize a definition (fixing the + /// address) on demand. + /// + /// This constructor allows a JIT layer to provide a reference to a symbol + /// definition without actually materializing the definition up front. The + /// user can materialize the definition at any time by calling the getAddress + /// method. + JITSymbol(GetAddressFtor GetAddress) + : CachedAddr(0), GetAddress(std::move(GetAddress)) {} + + /// @brief Returns true if the symbol exists, false otherwise. + explicit operator bool() const { return CachedAddr || GetAddress; } + + /// @brief Get the address of the symbol in the target address space. Returns + /// '0' if the symbol does not exist. + TargetAddress getAddress() { + if (GetAddress) { + CachedAddr = GetAddress(); + assert(CachedAddr && "Symbol could not be materialized."); + GetAddress = nullptr; + } + return CachedAddr; + } + +private: + TargetAddress CachedAddr; + GetAddressFtor GetAddress; +}; + +} // End namespace orc. +} // End namespace llvm. + +#endif // LLVM_EXECUTIONENGINE_ORC_JITSYMBOL_H diff --git a/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h b/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h new file mode 100644 index 0000000..2a94abe --- /dev/null +++ b/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h @@ -0,0 +1,283 @@ +//===- LazyEmittingLayer.h - Lazily emit IR to lower JIT layers -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Contains the definition for a lazy-emitting layer for the JIT. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_ORC_LAZYEMITTINGLAYER_H +#define LLVM_EXECUTIONENGINE_ORC_LAZYEMITTINGLAYER_H + +#include "JITSymbol.h" +#include "LookasideRTDyldMM.h" +#include "llvm/ExecutionEngine/RTDyldMemoryManager.h" +#include "llvm/IR/GlobalValue.h" +#include "llvm/IR/Mangler.h" +#include "llvm/IR/Module.h" +#include "llvm/ADT/StringMap.h" +#include + +namespace llvm { +namespace orc { + +/// @brief Lazy-emitting IR layer. +/// +/// This layer accepts sets of LLVM IR Modules (via addModuleSet), but does +/// not immediately emit them the layer below. Instead, emissing to the base +/// layer is deferred until the first time the client requests the address +/// (via JITSymbol::getAddress) for a symbol contained in this layer. +template class LazyEmittingLayer { +public: + typedef typename BaseLayerT::ModuleSetHandleT BaseLayerHandleT; + +private: + class EmissionDeferredSet { + public: + EmissionDeferredSet() : EmitState(NotEmitted) {} + virtual ~EmissionDeferredSet() {} + + JITSymbol find(StringRef Name, bool ExportedSymbolsOnly, BaseLayerT &B) { + switch (EmitState) { + case NotEmitted: + if (provides(Name, ExportedSymbolsOnly)) { + // Create a std::string version of Name to capture here - the argument + // (a StringRef) may go away before the lambda is executed. + // FIXME: Use capture-init when we move to C++14. + std::string PName = Name; + return JITSymbol( + [this, ExportedSymbolsOnly, PName, &B]() -> TargetAddress { + if (this->EmitState == Emitting) + return 0; + else if (this->EmitState == NotEmitted) { + this->EmitState = Emitting; + Handle = this->emitToBaseLayer(B); + this->EmitState = Emitted; + } + return B.findSymbolIn(Handle, PName, ExportedSymbolsOnly) + .getAddress(); + }); + } else + return nullptr; + case Emitting: + // Calling "emit" can trigger external symbol lookup (e.g. to check for + // pre-existing definitions of common-symbol), but it will never find in + // this module that it would not have found already, so return null from + // here. + return nullptr; + case Emitted: + return B.findSymbolIn(Handle, Name, ExportedSymbolsOnly); + } + llvm_unreachable("Invalid emit-state."); + } + + void removeModulesFromBaseLayer(BaseLayerT &BaseLayer) { + if (EmitState != NotEmitted) + BaseLayer.removeModuleSet(Handle); + } + + void emitAndFinalize(BaseLayerT &BaseLayer) { + assert(EmitState != Emitting && + "Cannot emitAndFinalize while already emitting"); + if (EmitState == NotEmitted) { + EmitState = Emitting; + Handle = emitToBaseLayer(BaseLayer); + EmitState = Emitted; + } + BaseLayer.emitAndFinalize(Handle); + } + + template + static std::unique_ptr + create(BaseLayerT &B, ModuleSetT Ms, + std::unique_ptr MM); + + protected: + virtual bool provides(StringRef Name, bool ExportedSymbolsOnly) const = 0; + virtual BaseLayerHandleT emitToBaseLayer(BaseLayerT &BaseLayer) = 0; + + private: + enum { NotEmitted, Emitting, Emitted } EmitState; + BaseLayerHandleT Handle; + }; + + template + class EmissionDeferredSetImpl : public EmissionDeferredSet { + public: + EmissionDeferredSetImpl(ModuleSetT Ms, + std::unique_ptr MM) + : Ms(std::move(Ms)), MM(std::move(MM)) {} + + protected: + + BaseLayerHandleT emitToBaseLayer(BaseLayerT &BaseLayer) override { + // We don't need the mangled names set any more: Once we've emitted this + // to the base layer we'll just look for symbols there. + MangledNames.reset(); + return BaseLayer.addModuleSet(std::move(Ms), std::move(MM)); + } + + bool provides(StringRef Name, bool ExportedSymbolsOnly) const override { + // FIXME: We could clean all this up if we had a way to reliably demangle + // names: We could just demangle name and search, rather than + // mangling everything else. + + // If we have already built the mangled name set then just search it. + if (MangledNames) { + auto VI = MangledNames->find(Name); + if (VI == MangledNames->end()) + return false; + return !ExportedSymbolsOnly || VI->second; + } + + // If we haven't built the mangled name set yet, try to build it. As an + // optimization this will leave MangledNames set to nullptr if we find + // Name in the process of building the set. + buildMangledNames(Name, ExportedSymbolsOnly); + if (!MangledNames) + return true; + return false; + } + + private: + // If the mangled name of the given GlobalValue matches the given search + // name (and its visibility conforms to the ExportedSymbolsOnly flag) then + // just return 'true'. Otherwise, add the mangled name to the Names map and + // return 'false'. + bool addGlobalValue(StringMap &Names, const GlobalValue &GV, + const Mangler &Mang, StringRef SearchName, + bool ExportedSymbolsOnly) const { + // Modules don't "provide" decls or common symbols. + if (GV.isDeclaration() || GV.hasCommonLinkage()) + return false; + + // Mangle the GV name. + std::string MangledName; + { + raw_string_ostream MangledNameStream(MangledName); + Mang.getNameWithPrefix(MangledNameStream, &GV, false); + } + + // Check whether this is the name we were searching for, and if it is then + // bail out early. + if (MangledName == SearchName) + if (!ExportedSymbolsOnly || GV.hasDefaultVisibility()) + return true; + + // Otherwise add this to the map for later. + Names[MangledName] = GV.hasDefaultVisibility(); + return false; + } + + // Build the MangledNames map. Bails out early (with MangledNames left set + // to nullptr) if the given SearchName is found while building the map. + void buildMangledNames(StringRef SearchName, + bool ExportedSymbolsOnly) const { + assert(!MangledNames && "Mangled names map already exists?"); + + auto Names = llvm::make_unique>(); + + for (const auto &M : Ms) { + Mangler Mang(M->getDataLayout()); + + for (const auto &GV : M->globals()) + if (addGlobalValue(*Names, GV, Mang, SearchName, ExportedSymbolsOnly)) + return; + + for (const auto &F : *M) + if (addGlobalValue(*Names, F, Mang, SearchName, ExportedSymbolsOnly)) + return; + } + + MangledNames = std::move(Names); + } + + ModuleSetT Ms; + std::unique_ptr MM; + mutable std::unique_ptr> MangledNames; + }; + + typedef std::list> ModuleSetListT; + + BaseLayerT &BaseLayer; + ModuleSetListT ModuleSetList; + +public: + /// @brief Handle to a set of loaded modules. + typedef typename ModuleSetListT::iterator ModuleSetHandleT; + + /// @brief Construct a lazy emitting layer. + LazyEmittingLayer(BaseLayerT &BaseLayer) : BaseLayer(BaseLayer) {} + + /// @brief Add the given set of modules to the lazy emitting layer. + template + ModuleSetHandleT addModuleSet(ModuleSetT Ms, + std::unique_ptr MM) { + return ModuleSetList.insert( + ModuleSetList.end(), + EmissionDeferredSet::create(BaseLayer, std::move(Ms), std::move(MM))); + } + + /// @brief Remove the module set represented by the given handle. + /// + /// This method will free the memory associated with the given module set, + /// both in this layer, and the base layer. + void removeModuleSet(ModuleSetHandleT H) { + (*H)->removeModulesFromBaseLayer(BaseLayer); + ModuleSetList.erase(H); + } + + /// @brief Search for the given named symbol. + /// @param Name The name of the symbol to search for. + /// @param ExportedSymbolsOnly If true, search only for exported symbols. + /// @return A handle for the given named symbol, if it exists. + JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) { + // Look for the symbol among existing definitions. + if (auto Symbol = BaseLayer.findSymbol(Name, ExportedSymbolsOnly)) + return Symbol; + + // If not found then search the deferred sets. If any of these contain a + // definition of 'Name' then they will return a JITSymbol that will emit + // the corresponding module when the symbol address is requested. + for (auto &DeferredSet : ModuleSetList) + if (auto Symbol = DeferredSet->find(Name, ExportedSymbolsOnly, BaseLayer)) + return Symbol; + + // If no definition found anywhere return a null symbol. + return nullptr; + } + + /// @brief Get the address of the given symbol in the context of the set of + /// compiled modules represented by the handle H. + JITSymbol findSymbolIn(ModuleSetHandleT H, const std::string &Name, + bool ExportedSymbolsOnly) { + return (*H)->find(Name, ExportedSymbolsOnly, BaseLayer); + } + + /// @brief Immediately emit and finalize the moduleOB set represented by the + /// given handle. + /// @param H Handle for module set to emit/finalize. + void emitAndFinalize(ModuleSetHandleT H) { + (*H)->emitAndFinalize(BaseLayer); + } + +}; + +template +template +std::unique_ptr::EmissionDeferredSet> +LazyEmittingLayer::EmissionDeferredSet::create( + BaseLayerT &B, ModuleSetT Ms, std::unique_ptr MM) { + return llvm::make_unique>(std::move(Ms), + std::move(MM)); +} + +} // End namespace orc. +} // End namespace llvm. + +#endif // LLVM_EXECUTIONENGINE_ORC_LAZYEMITTINGLAYER_H diff --git a/include/llvm/ExecutionEngine/Orc/LookasideRTDyldMM.h b/include/llvm/ExecutionEngine/Orc/LookasideRTDyldMM.h new file mode 100644 index 0000000..4456404 --- /dev/null +++ b/include/llvm/ExecutionEngine/Orc/LookasideRTDyldMM.h @@ -0,0 +1,92 @@ +//===- LookasideRTDyldMM - Redirect symbol lookup via a functor -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Defines an adapter for RuntimeDyldMM that allows lookups for external +// symbols to go via a functor. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_ORC_LOOKASIDERTDYLDMM_H +#define LLVM_EXECUTIONENGINE_ORC_LOOKASIDERTDYLDMM_H + +#include "llvm/ADT/STLExtras.h" +#include +#include + +namespace llvm { +namespace orc { + +/// @brief Defines an adapter for RuntimeDyldMM that allows lookups for external +/// symbols to go via a functor, before falling back to the lookup logic +/// provided by the underlying RuntimeDyldMM instance. +/// +/// This class is useful for redirecting symbol lookup back to various layers +/// of a JIT component stack, e.g. to enable lazy module emission. +/// +template +class LookasideRTDyldMM : public BaseRTDyldMM { +public: + /// @brief Create a LookasideRTDyldMM intance. + LookasideRTDyldMM(ExternalLookupFtor ExternalLookup, + DylibLookupFtor DylibLookup) + : ExternalLookup(std::move(ExternalLookup)), + DylibLookup(std::move(DylibLookup)) {} + + /// @brief Look up the given symbol address, first via the functor this + /// instance was created with, then (if the symbol isn't found) + /// via the underlying RuntimeDyldMM. + uint64_t getSymbolAddress(const std::string &Name) override { + if (uint64_t Addr = ExternalLookup(Name)) + return Addr; + return BaseRTDyldMM::getSymbolAddress(Name); + } + + uint64_t getSymbolAddressInLogicalDylib(const std::string &Name) override { + if (uint64_t Addr = DylibLookup(Name)) + return Addr; + return BaseRTDyldMM::getSymbolAddressInLogicalDylib(Name); + }; + + /// @brief Get a reference to the ExternalLookup functor. + ExternalLookupFtor &getExternalLookup() { return ExternalLookup; } + + /// @brief Get a const-reference to the ExternalLookup functor. + const ExternalLookupFtor &getExternalLookup() const { return ExternalLookup; } + + /// @brief Get a reference to the DylibLookup functor. + DylibLookupFtor &getDylibLookup() { return DylibLookup; } + + /// @brief Get a const-reference to the DylibLookup functor. + const DylibLookupFtor &getDylibLookup() const { return DylibLookup; } + +private: + ExternalLookupFtor ExternalLookup; + DylibLookupFtor DylibLookup; +}; + +/// @brief Create a LookasideRTDyldMM from a base memory manager type, an +/// external lookup functor, and a dylib lookup functor. +template +std::unique_ptr< + LookasideRTDyldMM> +createLookasideRTDyldMM(ExternalLookupFtor &&ExternalLookup, + DylibLookupFtor &&DylibLookup) { + typedef LookasideRTDyldMM + ThisLookasideMM; + return llvm::make_unique( + std::forward(ExternalLookup), + std::forward(DylibLookup)); +} + +} // End namespace orc. +} // End namespace llvm. + +#endif // LLVM_EXECUTIONENGINE_ORC_LOOKASIDERTDYLDMM_H diff --git a/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h b/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h new file mode 100644 index 0000000..36af0fe --- /dev/null +++ b/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h @@ -0,0 +1,267 @@ +//===- ObjectLinkingLayer.h - Add object files to a JIT process -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Contains the definition for the object layer of the JIT. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_ORC_OBJECTLINKINGLAYER_H +#define LLVM_EXECUTIONENGINE_ORC_OBJECTLINKINGLAYER_H + +#include "JITSymbol.h" +#include "LookasideRTDyldMM.h" +#include "llvm/ExecutionEngine/ExecutionEngine.h" +#include "llvm/ExecutionEngine/SectionMemoryManager.h" +#include +#include + +namespace llvm { +namespace orc { + +class ObjectLinkingLayerBase { +protected: + + /// @brief Holds a set of objects to be allocated/linked as a unit in the JIT. + /// + /// An instance of this class will be created for each set of objects added + /// via JITObjectLayer::addObjectSet. Deleting the instance (via + /// removeObjectSet) frees its memory, removing all symbol definitions that + /// had been provided by this instance. Higher level layers are responsible + /// for taking any action required to handle the missing symbols. + class LinkedObjectSet { + LinkedObjectSet(const LinkedObjectSet&) = delete; + void operator=(const LinkedObjectSet&) = delete; + public: + LinkedObjectSet(std::unique_ptr MM) + : MM(std::move(MM)), RTDyld(llvm::make_unique(&*this->MM)), + State(Raw) {} + + // MSVC 2012 cannot infer a move constructor, so write it out longhand. + LinkedObjectSet(LinkedObjectSet &&O) + : MM(std::move(O.MM)), RTDyld(std::move(O.RTDyld)), State(O.State) {} + + std::unique_ptr + addObject(const object::ObjectFile &Obj) { + return RTDyld->loadObject(Obj); + } + + TargetAddress getSymbolAddress(StringRef Name, bool ExportedSymbolsOnly) { + if (ExportedSymbolsOnly) + return RTDyld->getExportedSymbolLoadAddress(Name); + return RTDyld->getSymbolLoadAddress(Name); + } + + bool NeedsFinalization() const { return (State == Raw); } + + void Finalize() { + State = Finalizing; + RTDyld->resolveRelocations(); + RTDyld->registerEHFrames(); + MM->finalizeMemory(); + OwnedBuffers.clear(); + State = Finalized; + } + + void mapSectionAddress(const void *LocalAddress, TargetAddress TargetAddr) { + assert((State != Finalized) && + "Attempting to remap sections for finalized objects."); + RTDyld->mapSectionAddress(LocalAddress, TargetAddr); + } + + void takeOwnershipOfBuffer(std::unique_ptr B) { + OwnedBuffers.push_back(std::move(B)); + } + + private: + std::unique_ptr MM; + std::unique_ptr RTDyld; + enum { Raw, Finalizing, Finalized } State; + + // FIXME: This ownership hack only exists because RuntimeDyldELF still + // wants to be able to inspect the original object when resolving + // relocations. As soon as that can be fixed this should be removed. + std::vector> OwnedBuffers; + }; + + typedef std::list LinkedObjectSetListT; + +public: + /// @brief Handle to a set of loaded objects. + typedef LinkedObjectSetListT::iterator ObjSetHandleT; + + // Ownership hack. + // FIXME: Remove this as soon as RuntimeDyldELF can apply relocations without + // referencing the original object. + template + void takeOwnershipOfBuffers(ObjSetHandleT H, OwningMBSet MBs) { + for (auto &MB : MBs) + H->takeOwnershipOfBuffer(std::move(MB)); + } + +}; + +/// @brief Default (no-op) action to perform when loading objects. +class DoNothingOnNotifyLoaded { +public: + template + void operator()(ObjectLinkingLayerBase::ObjSetHandleT, const ObjSetT &, + const LoadResult &) {} +}; + +/// @brief Bare bones object linking layer. +/// +/// This class is intended to be used as the base layer for a JIT. It allows +/// object files to be loaded into memory, linked, and the addresses of their +/// symbols queried. All objects added to this layer can see each other's +/// symbols. +template +class ObjectLinkingLayer : public ObjectLinkingLayerBase { +public: + + /// @brief LoadedObjectInfo list. Contains a list of owning pointers to + /// RuntimeDyld::LoadedObjectInfo instances. + typedef std::vector> + LoadedObjInfoList; + + /// @brief Functor to create RTDyldMemoryManager instances. + typedef std::function()> CreateRTDyldMMFtor; + + /// @brief Functor for receiving finalization notifications. + typedef std::function NotifyFinalizedFtor; + + /// @brief Construct an ObjectLinkingLayer with the given NotifyLoaded, + /// NotifyFinalized and CreateMemoryManager functors. + ObjectLinkingLayer( + CreateRTDyldMMFtor CreateMemoryManager = CreateRTDyldMMFtor(), + NotifyLoadedFtor NotifyLoaded = NotifyLoadedFtor(), + NotifyFinalizedFtor NotifyFinalized = NotifyFinalizedFtor()) + : NotifyLoaded(std::move(NotifyLoaded)), + NotifyFinalized(std::move(NotifyFinalized)), + CreateMemoryManager(std::move(CreateMemoryManager)) {} + + /// @brief Add a set of objects (or archives) that will be treated as a unit + /// for the purposes of symbol lookup and memory management. + /// + /// @return A pair containing (1) A handle that can be used to free the memory + /// allocated for the objects, and (2) a LoadedObjInfoList containing + /// one LoadedObjInfo instance for each object at the corresponding + /// index in the Objects list. + /// + /// This version of this method allows the client to pass in an + /// RTDyldMemoryManager instance that will be used to allocate memory and look + /// up external symbol addresses for the given objects. + template + ObjSetHandleT addObjectSet(const ObjSetT &Objects, + std::unique_ptr MM) { + + if (!MM) { + assert(CreateMemoryManager && + "No memory manager or memory manager creator provided."); + MM = CreateMemoryManager(); + } + + ObjSetHandleT Handle = LinkedObjSetList.insert( + LinkedObjSetList.end(), LinkedObjectSet(std::move(MM))); + LinkedObjectSet &LOS = *Handle; + LoadedObjInfoList LoadedObjInfos; + + for (auto &Obj : Objects) + LoadedObjInfos.push_back(LOS.addObject(*Obj)); + + NotifyLoaded(Handle, Objects, LoadedObjInfos); + + return Handle; + } + + /// @brief Remove the set of objects associated with handle H. + /// + /// All memory allocated for the objects will be freed, and the sections and + /// symbols they provided will no longer be available. No attempt is made to + /// re-emit the missing symbols, and any use of these symbols (directly or + /// indirectly) will result in undefined behavior. If dependence tracking is + /// required to detect or resolve such issues it should be added at a higher + /// layer. + void removeObjectSet(ObjSetHandleT H) { + // How do we invalidate the symbols in H? + LinkedObjSetList.erase(H); + } + + /// @brief Search for the given named symbol. + /// @param Name The name of the symbol to search for. + /// @param ExportedSymbolsOnly If true, search only for exported symbols. + /// @return A handle for the given named symbol, if it exists. + JITSymbol findSymbol(StringRef Name, bool ExportedSymbolsOnly) { + for (auto I = LinkedObjSetList.begin(), E = LinkedObjSetList.end(); I != E; + ++I) + if (auto Symbol = findSymbolIn(I, Name, ExportedSymbolsOnly)) + return Symbol; + + return nullptr; + } + + /// @brief Search for the given named symbol in the context of the set of + /// loaded objects represented by the handle H. + /// @param H The handle for the object set to search in. + /// @param Name The name of the symbol to search for. + /// @param ExportedSymbolsOnly If true, search only for exported symbols. + /// @return A handle for the given named symbol, if it is found in the + /// given object set. + JITSymbol findSymbolIn(ObjSetHandleT H, StringRef Name, + bool ExportedSymbolsOnly) { + if (auto Addr = H->getSymbolAddress(Name, ExportedSymbolsOnly)) { + if (!H->NeedsFinalization()) { + // If this instance has already been finalized then we can just return + // the address. + return JITSymbol(Addr); + } else { + // If this instance needs finalization return a functor that will do it. + // The functor still needs to double-check whether finalization is + // required, in case someone else finalizes this set before the functor + // is called. + return JITSymbol( + [this, Addr, H]() { + if (H->NeedsFinalization()) { + H->Finalize(); + if (NotifyFinalized) + NotifyFinalized(H); + } + return Addr; + }); + } + } + + return nullptr; + } + + /// @brief Map section addresses for the objects associated with the handle H. + void mapSectionAddress(ObjSetHandleT H, const void *LocalAddress, + TargetAddress TargetAddr) { + H->mapSectionAddress(LocalAddress, TargetAddr); + } + + /// @brief Immediately emit and finalize the object set represented by the + /// given handle. + /// @param H Handle for object set to emit/finalize. + void emitAndFinalize(ObjSetHandleT H) { + H->Finalize(); + if (NotifyFinalized) + NotifyFinalized(H); + } + +private: + LinkedObjectSetListT LinkedObjSetList; + NotifyLoadedFtor NotifyLoaded; + NotifyFinalizedFtor NotifyFinalized; + CreateRTDyldMMFtor CreateMemoryManager; +}; + +} // End namespace orc. +} // End namespace llvm + +#endif // LLVM_EXECUTIONENGINE_ORC_OBJECTLINKINGLAYER_H diff --git a/include/llvm/ExecutionEngine/Orc/OrcTargetSupport.h b/include/llvm/ExecutionEngine/Orc/OrcTargetSupport.h new file mode 100644 index 0000000..c6f866a --- /dev/null +++ b/include/llvm/ExecutionEngine/Orc/OrcTargetSupport.h @@ -0,0 +1,56 @@ +//===-- OrcTargetSupport.h - Code to support specific targets --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Target specific code for Orc, e.g. callback assembly. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_ORC_ORCTARGETSUPPORT_H +#define LLVM_EXECUTIONENGINE_ORC_ORCTARGETSUPPORT_H + +#include "IndirectionUtils.h" + +namespace llvm { +namespace orc { + +class OrcX86_64 { +public: + static const char *ResolverBlockName; + + /// @brief Insert module-level inline callback asm into module M for the + /// symbols managed by JITResolveCallbackHandler J. + static void insertResolverBlock( + Module &M, + JITCompileCallbackManagerBase &JCBM); + + /// @brief Get a label name from the given index. + typedef std::function LabelNameFtor; + + static const unsigned CallSize = 6; + + /// @brief Insert the requested number of trampolines into the given module. + /// @param M Module to insert the call block into. + /// @param NumCalls Number of calls to create in the call block. + /// @param StartIndex Optional argument specifying the index suffix to start + /// with. + /// @return A functor that provides the symbol name for each entry in the call + /// block. + /// + static LabelNameFtor insertCompileCallbackTrampolines( + Module &M, + TargetAddress TrampolineAddr, + unsigned NumCalls, + unsigned StartIndex = 0); + +}; + +} // End namespace orc. +} // End namespace llvm. + +#endif // LLVM_EXECUTIONENGINE_ORC_ORCTARGETSUPPORT_H diff --git a/include/llvm/ExecutionEngine/OrcMCJITReplacement.h b/include/llvm/ExecutionEngine/OrcMCJITReplacement.h new file mode 100644 index 0000000..4cd5648 --- /dev/null +++ b/include/llvm/ExecutionEngine/OrcMCJITReplacement.h @@ -0,0 +1,38 @@ +//===---- OrcMCJITReplacement.h - Orc-based MCJIT replacement ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file forces OrcMCJITReplacement to link in on certain operating systems. +// (Windows). +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_ORCMCJITREPLACEMENT_H +#define LLVM_EXECUTIONENGINE_ORCMCJITREPLACEMENT_H + +#include "llvm/ExecutionEngine/ExecutionEngine.h" +#include + +extern "C" void LLVMLinkInOrcMCJITReplacement(); + +namespace { + struct ForceOrcMCJITReplacementLinking { + ForceOrcMCJITReplacementLinking() { + // We must reference OrcMCJITReplacement in such a way that compilers will + // not delete it all as dead code, even with whole program optimization, + // yet is effectively a NO-OP. As the compiler isn't smart enough to know + // that getenv() never returns -1, this will do the job. + if (std::getenv("bar") != (char*) -1) + return; + + LLVMLinkInOrcMCJITReplacement(); + } + } ForceOrcMCJITReplacementLinking; +} + +#endif diff --git a/include/llvm/ExecutionEngine/RTDyldMemoryManager.h b/include/llvm/ExecutionEngine/RTDyldMemoryManager.h index b941efc..792a499 100644 --- a/include/llvm/ExecutionEngine/RTDyldMemoryManager.h +++ b/include/llvm/ExecutionEngine/RTDyldMemoryManager.h @@ -22,7 +22,10 @@ namespace llvm { class ExecutionEngine; -class ObjectImage; + + namespace object { + class ObjectFile; + } // RuntimeDyld clients often want to handle the memory management of // what gets placed where. For JIT clients, this is the subset of @@ -31,8 +34,8 @@ class ObjectImage; // FIXME: As the RuntimeDyld fills out, additional routines will be needed // for the varying types of objects to be allocated. class RTDyldMemoryManager { - RTDyldMemoryManager(const RTDyldMemoryManager&) LLVM_DELETED_FUNCTION; - void operator=(const RTDyldMemoryManager&) LLVM_DELETED_FUNCTION; + RTDyldMemoryManager(const RTDyldMemoryManager&) = delete; + void operator=(const RTDyldMemoryManager&) = delete; public: RTDyldMemoryManager() {} virtual ~RTDyldMemoryManager(); @@ -86,6 +89,27 @@ public: return getSymbolAddressInProcess(Name); } + /// This method returns the address of the specified symbol if it exists + /// within the logical dynamic library represented by this + /// RTDyldMemoryManager. Unlike getSymbolAddress, queries through this + /// interface should return addresses for hidden symbols. + /// + /// This is of particular importance for the Orc JIT APIs, which support lazy + /// compilation by breaking up modules: Each of those broken out modules + /// must be able to resolve hidden symbols provided by the others. Clients + /// writing memory managers for MCJIT can usually ignore this method. + /// + /// This method will be queried by RuntimeDyld when checking for previous + /// definitions of common symbols. It will *not* be queried by default when + /// resolving external symbols (this minimises the link-time overhead for + /// MCJIT clients who don't care about Orc features). If you are writing a + /// RTDyldMemoryManager for Orc and want "external" symbol resolution to + /// search the logical dylib, you should override your getSymbolAddress + /// method call this method directly. + virtual uint64_t getSymbolAddressInLogicalDylib(const std::string &Name) { + return 0; + } + /// This method returns the address of the specified function. As such it is /// only useful for resolving library symbols, not code generated symbols. /// @@ -109,7 +133,7 @@ public: /// address space can use this call to remap the section addresses for the /// newly loaded object. virtual void notifyObjectLoaded(ExecutionEngine *EE, - const ObjectImage *) {} + const object::ObjectFile &) {} /// This method is called when object loading is complete and section page /// permissions can be applied. It is up to the memory manager implementation diff --git a/include/llvm/ExecutionEngine/RuntimeDyld.h b/include/llvm/ExecutionEngine/RuntimeDyld.h index 3605b9e..08cfa39 100644 --- a/include/llvm/ExecutionEngine/RuntimeDyld.h +++ b/include/llvm/ExecutionEngine/RuntimeDyld.h @@ -15,25 +15,25 @@ #define LLVM_EXECUTIONENGINE_RUNTIMEDYLD_H #include "llvm/ADT/StringRef.h" -#include "llvm/ExecutionEngine/ObjectBuffer.h" #include "llvm/ExecutionEngine/RTDyldMemoryManager.h" #include "llvm/Support/Memory.h" +#include namespace llvm { namespace object { class ObjectFile; + template class OwningBinary; } class RuntimeDyldImpl; class RuntimeDyldCheckerImpl; -class ObjectImage; class RuntimeDyld { friend class RuntimeDyldCheckerImpl; - RuntimeDyld(const RuntimeDyld &) LLVM_DELETED_FUNCTION; - void operator=(const RuntimeDyld &) LLVM_DELETED_FUNCTION; + RuntimeDyld(const RuntimeDyld &) = delete; + void operator=(const RuntimeDyld &) = delete; // RuntimeDyldImpl is the actual class. RuntimeDyld is just the public // interface. @@ -46,32 +46,49 @@ protected: // Any relocations already associated with the symbol will be re-resolved. void reassignSectionAddress(unsigned SectionID, uint64_t Addr); public: + + /// \brief Information about the loaded object. + class LoadedObjectInfo { + friend class RuntimeDyldImpl; + public: + LoadedObjectInfo(RuntimeDyldImpl &RTDyld, unsigned BeginIdx, + unsigned EndIdx) + : RTDyld(RTDyld), BeginIdx(BeginIdx), EndIdx(EndIdx) { } + + virtual ~LoadedObjectInfo() {} + + virtual object::OwningBinary + getObjectForDebug(const object::ObjectFile &Obj) const = 0; + + uint64_t getSectionLoadAddress(StringRef Name) const; + + protected: + virtual void anchor(); + + RuntimeDyldImpl &RTDyld; + unsigned BeginIdx, EndIdx; + }; + RuntimeDyld(RTDyldMemoryManager *); ~RuntimeDyld(); - /// Prepare the object contained in the input buffer for execution. - /// Ownership of the input buffer is transferred to the ObjectImage - /// instance returned from this function if successful. In the case of load - /// failure, the input buffer will be deleted. - std::unique_ptr - loadObject(std::unique_ptr InputBuffer); - - /// Prepare the referenced object file for execution. - /// Ownership of the input object is transferred to the ObjectImage - /// instance returned from this function if successful. In the case of load - /// failure, the input object will be deleted. - std::unique_ptr - loadObject(std::unique_ptr InputObject); + /// Add the referenced object file to the list of objects to be loaded and + /// relocated. + std::unique_ptr loadObject(const object::ObjectFile &O); /// Get the address of our local copy of the symbol. This may or may not /// be the address used for relocation (clients can copy the data around /// and resolve relocatons based on where they put it). void *getSymbolAddress(StringRef Name) const; - /// Get the address of the target copy of the symbol. This is the address - /// used for relocation. + /// Get the address of the target copy of the symbol (works for both exported + /// and non-exported symbols). This is the address used for relocation. uint64_t getSymbolLoadAddress(StringRef Name) const; + /// Get the address of the target copy of the symbol (works for exported + /// symbols only). This is the address used for relocation. + uint64_t getExportedSymbolLoadAddress(StringRef Name) const; + /// Resolve the relocations for all symbols we currently know about. void resolveRelocations(); diff --git a/include/llvm/ExecutionEngine/RuntimeDyldChecker.h b/include/llvm/ExecutionEngine/RuntimeDyldChecker.h index 35ceba2..23936a6 100644 --- a/include/llvm/ExecutionEngine/RuntimeDyldChecker.h +++ b/include/llvm/ExecutionEngine/RuntimeDyldChecker.h @@ -52,6 +52,7 @@ class raw_ostream; /// /// ident_expr = 'decode_operand' '(' symbol ',' operand-index ')' /// | 'next_pc' '(' symbol ')' +/// | 'stub_addr' '(' file-name ',' section-name ',' symbol ')' /// | symbol /// /// binary_expr = expr '+' expr diff --git a/include/llvm/ExecutionEngine/SectionMemoryManager.h b/include/llvm/ExecutionEngine/SectionMemoryManager.h index 1368563..b825aff 100644 --- a/include/llvm/ExecutionEngine/SectionMemoryManager.h +++ b/include/llvm/ExecutionEngine/SectionMemoryManager.h @@ -35,8 +35,8 @@ namespace llvm { /// MCJIT::finalizeObject or by calling SectionMemoryManager::finalizeMemory /// directly. Clients of MCJIT should call MCJIT::finalizeObject. class SectionMemoryManager : public RTDyldMemoryManager { - SectionMemoryManager(const SectionMemoryManager&) LLVM_DELETED_FUNCTION; - void operator=(const SectionMemoryManager&) LLVM_DELETED_FUNCTION; + SectionMemoryManager(const SectionMemoryManager&) = delete; + void operator=(const SectionMemoryManager&) = delete; public: SectionMemoryManager() { } diff --git a/include/llvm/IR/Attributes.h b/include/llvm/IR/Attributes.h index 5ff48d6..443892b 100644 --- a/include/llvm/IR/Attributes.h +++ b/include/llvm/IR/Attributes.h @@ -282,6 +282,11 @@ public: AttributeSet removeAttributes(LLVMContext &C, unsigned Index, AttributeSet Attrs) const; + /// \brief Add the dereferenceable attribute to the attribute set at the given + /// index. Since attribute sets are immutable, this returns a new set. + AttributeSet addDereferenceableAttr(LLVMContext &C, unsigned Index, + uint64_t Bytes) const; + //===--------------------------------------------------------------------===// // AttributeSet Accessors //===--------------------------------------------------------------------===// diff --git a/include/llvm/IR/BasicBlock.h b/include/llvm/IR/BasicBlock.h index 7c7dd2c..185fc29 100644 --- a/include/llvm/IR/BasicBlock.h +++ b/include/llvm/IR/BasicBlock.h @@ -82,8 +82,8 @@ private: void setParent(Function *parent); friend class SymbolTableListTraits; - BasicBlock(const BasicBlock &) LLVM_DELETED_FUNCTION; - void operator=(const BasicBlock &) LLVM_DELETED_FUNCTION; + BasicBlock(const BasicBlock &) = delete; + void operator=(const BasicBlock &) = delete; /// \brief Constructor. /// @@ -208,6 +208,14 @@ public: return const_cast(this)->getUniquePredecessor(); } + /// Return the successor of this block if it has a unique successor. + /// Otherwise return a null pointer. This method is analogous to + /// getUniquePredeccessor above. + BasicBlock *getUniqueSuccessor(); + const BasicBlock *getUniqueSuccessor() const { + return const_cast(this)->getUniqueSuccessor(); + } + //===--------------------------------------------------------------------===// /// Instruction iterator methods /// diff --git a/include/llvm/IR/CFG.h b/include/llvm/IR/CFG.h index c8be8bd..8476431 100644 --- a/include/llvm/IR/CFG.h +++ b/include/llvm/IR/CFG.h @@ -16,6 +16,7 @@ #define LLVM_IR_CFG_H #include "llvm/ADT/GraphTraits.h" +#include "llvm/ADT/iterator_range.h" #include "llvm/IR/Function.h" #include "llvm/IR/InstrTypes.h" @@ -84,6 +85,8 @@ public: typedef PredIterator pred_iterator; typedef PredIterator const_pred_iterator; +typedef llvm::iterator_range pred_range; +typedef llvm::iterator_range pred_const_range; inline pred_iterator pred_begin(BasicBlock *BB) { return pred_iterator(BB); } inline const_pred_iterator pred_begin(const BasicBlock *BB) { @@ -93,8 +96,15 @@ inline pred_iterator pred_end(BasicBlock *BB) { return pred_iterator(BB, true);} inline const_pred_iterator pred_end(const BasicBlock *BB) { return const_pred_iterator(BB, true); } - - +inline bool pred_empty(const BasicBlock *BB) { + return pred_begin(BB) == pred_end(BB); +} +inline pred_range predecessors(BasicBlock *BB) { + return pred_range(pred_begin(BB), pred_end(BB)); +} +inline pred_const_range predecessors(const BasicBlock *BB) { + return pred_const_range(pred_begin(BB), pred_end(BB)); +} //===----------------------------------------------------------------------===// // BasicBlock succ_iterator definition @@ -244,6 +254,8 @@ public: typedef SuccIterator succ_iterator; typedef SuccIterator succ_const_iterator; +typedef llvm::iterator_range succ_range; +typedef llvm::iterator_range succ_const_range; inline succ_iterator succ_begin(BasicBlock *BB) { return succ_iterator(BB->getTerminator()); @@ -257,6 +269,16 @@ inline succ_iterator succ_end(BasicBlock *BB) { inline succ_const_iterator succ_end(const BasicBlock *BB) { return succ_const_iterator(BB->getTerminator(), true); } +inline bool succ_empty(const BasicBlock *BB) { + return succ_begin(BB) == succ_end(BB); +} +inline succ_range successors(BasicBlock *BB) { + return succ_range(succ_begin(BB), succ_end(BB)); +} +inline succ_const_range successors(const BasicBlock *BB) { + return succ_const_range(succ_begin(BB), succ_end(BB)); +} + template struct isPodLike > { static const bool value = isPodLike::value; diff --git a/include/llvm/IR/CallSite.h b/include/llvm/IR/CallSite.h index df08257..a4ea243 100644 --- a/include/llvm/IR/CallSite.h +++ b/include/llvm/IR/CallSite.h @@ -78,7 +78,7 @@ public: InstrTy *getInstruction() const { return I.getPointer(); } InstrTy *operator->() const { return I.getPointer(); } - LLVM_EXPLICIT operator bool() const { return I.getPointer(); } + explicit operator bool() const { return I.getPointer(); } /// getCalledValue - Return the pointer to function that is being called. /// diff --git a/include/llvm/IR/Comdat.h b/include/llvm/IR/Comdat.h index 3e77a77..4d4c15f 100644 --- a/include/llvm/IR/Comdat.h +++ b/include/llvm/IR/Comdat.h @@ -49,7 +49,7 @@ private: friend class Module; Comdat(); Comdat(SelectionKind SK, StringMapEntry *Name); - Comdat(const Comdat &) LLVM_DELETED_FUNCTION; + Comdat(const Comdat &) = delete; // Points to the map in Module. StringMapEntry *Name; diff --git a/include/llvm/IR/Constant.h b/include/llvm/IR/Constant.h index d26991e..75499e0 100644 --- a/include/llvm/IR/Constant.h +++ b/include/llvm/IR/Constant.h @@ -39,8 +39,8 @@ namespace llvm { /// don't have to worry about the lifetime of the objects. /// @brief LLVM Constant Representation class Constant : public User { - void operator=(const Constant &) LLVM_DELETED_FUNCTION; - Constant(const Constant &) LLVM_DELETED_FUNCTION; + void operator=(const Constant &) = delete; + Constant(const Constant &) = delete; void anchor() override; protected: diff --git a/include/llvm/IR/ConstantRange.h b/include/llvm/IR/ConstantRange.h index 3d39289..5e8cd34 100644 --- a/include/llvm/IR/ConstantRange.h +++ b/include/llvm/IR/ConstantRange.h @@ -37,7 +37,7 @@ namespace llvm { -/// ConstantRange - This class represents an range of values. +/// This class represents a range of values. /// class ConstantRange { APInt Lower, Upper; @@ -59,7 +59,7 @@ public: /// assert out if the two APInt's are not the same bit width. ConstantRange(APIntMoveTy Lower, APIntMoveTy Upper); - /// makeICmpRegion - Produce the smallest range that contains all values that + /// Produce the smallest range that contains all values that /// might satisfy the comparison specified by Pred when compared to any value /// contained within Other. /// @@ -69,47 +69,46 @@ public: static ConstantRange makeICmpRegion(unsigned Pred, const ConstantRange &Other); - /// getLower - Return the lower value for this range... + /// Return the lower value for this range. /// const APInt &getLower() const { return Lower; } - /// getUpper - Return the upper value for this range... + /// Return the upper value for this range. /// const APInt &getUpper() const { return Upper; } - /// getBitWidth - get the bit width of this ConstantRange + /// Get the bit width of this ConstantRange. /// uint32_t getBitWidth() const { return Lower.getBitWidth(); } - /// isFullSet - Return true if this set contains all of the elements possible - /// for this data-type + /// Return true if this set contains all of the elements possible + /// for this data-type. /// bool isFullSet() const; - /// isEmptySet - Return true if this set contains no members. + /// Return true if this set contains no members. /// bool isEmptySet() const; - /// isWrappedSet - Return true if this set wraps around the top of the range, - /// for example: [100, 8) + /// Return true if this set wraps around the top of the range. + /// For example: [100, 8). /// bool isWrappedSet() const; - /// isSignWrappedSet - Return true if this set wraps around the INT_MIN of - /// its bitwidth, for example: i8 [120, 140). + /// Return true if this set wraps around the INT_MIN of + /// its bitwidth. For example: i8 [120, 140). /// bool isSignWrappedSet() const; - /// contains - Return true if the specified value is in the set. + /// Return true if the specified value is in the set. /// bool contains(const APInt &Val) const; - /// contains - Return true if the other range is a subset of this one. + /// Return true if the other range is a subset of this one. /// bool contains(const ConstantRange &CR) const; - /// getSingleElement - If this set contains a single element, return it, - /// otherwise return null. + /// If this set contains a single element, return it, otherwise return null. /// const APInt *getSingleElement() const { if (Upper == Lower + 1) @@ -117,35 +116,31 @@ public: return nullptr; } - /// isSingleElement - Return true if this set contains exactly one member. + /// Return true if this set contains exactly one member. /// bool isSingleElement() const { return getSingleElement() != nullptr; } - /// getSetSize - Return the number of elements in this set. + /// Return the number of elements in this set. /// APInt getSetSize() const; - /// getUnsignedMax - Return the largest unsigned value contained in the - /// ConstantRange. + /// Return the largest unsigned value contained in the ConstantRange. /// APInt getUnsignedMax() const; - /// getUnsignedMin - Return the smallest unsigned value contained in the - /// ConstantRange. + /// Return the smallest unsigned value contained in the ConstantRange. /// APInt getUnsignedMin() const; - /// getSignedMax - Return the largest signed value contained in the - /// ConstantRange. + /// Return the largest signed value contained in the ConstantRange. /// APInt getSignedMax() const; - /// getSignedMin - Return the smallest signed value contained in the - /// ConstantRange. + /// Return the smallest signed value contained in the ConstantRange. /// APInt getSignedMin() const; - /// operator== - Return true if this range is equal to another range. + /// Return true if this range is equal to another range. /// bool operator==(const ConstantRange &CR) const { return Lower == CR.Lower && Upper == CR.Upper; @@ -154,15 +149,14 @@ public: return !operator==(CR); } - /// subtract - Subtract the specified constant from the endpoints of this - /// constant range. + /// Subtract the specified constant from the endpoints of this constant range. ConstantRange subtract(const APInt &CI) const; /// \brief Subtract the specified range from this range (aka relative /// complement of the sets). ConstantRange difference(const ConstantRange &CR) const; - /// intersectWith - Return the range that results from the intersection of + /// Return the range that results from the intersection of /// this range with another range. The resultant range is guaranteed to /// include all elements contained in both input ranges, and to have the /// smallest possible set size that does so. Because there may be two @@ -171,7 +165,7 @@ public: /// ConstantRange intersectWith(const ConstantRange &CR) const; - /// unionWith - Return the range that results from the union of this range + /// Return the range that results from the union of this range /// with another range. The resultant range is guaranteed to include the /// elements of both sets, but may contain more. For example, [3, 9) union /// [12,15) is [3, 15), which includes 9, 10, and 11, which were not included @@ -179,85 +173,84 @@ public: /// ConstantRange unionWith(const ConstantRange &CR) const; - /// zeroExtend - Return a new range in the specified integer type, which must + /// Return a new range in the specified integer type, which must /// be strictly larger than the current type. The returned range will /// correspond to the possible range of values if the source range had been /// zero extended to BitWidth. ConstantRange zeroExtend(uint32_t BitWidth) const; - /// signExtend - Return a new range in the specified integer type, which must + /// Return a new range in the specified integer type, which must /// be strictly larger than the current type. The returned range will /// correspond to the possible range of values if the source range had been /// sign extended to BitWidth. ConstantRange signExtend(uint32_t BitWidth) const; - /// truncate - Return a new range in the specified integer type, which must be + /// Return a new range in the specified integer type, which must be /// strictly smaller than the current type. The returned range will /// correspond to the possible range of values if the source range had been /// truncated to the specified type. ConstantRange truncate(uint32_t BitWidth) const; - /// zextOrTrunc - make this range have the bit width given by \p BitWidth. The + /// Make this range have the bit width given by \p BitWidth. The /// value is zero extended, truncated, or left alone to make it that width. ConstantRange zextOrTrunc(uint32_t BitWidth) const; - /// sextOrTrunc - make this range have the bit width given by \p BitWidth. The + /// Make this range have the bit width given by \p BitWidth. The /// value is sign extended, truncated, or left alone to make it that width. ConstantRange sextOrTrunc(uint32_t BitWidth) const; - /// add - Return a new range representing the possible values resulting + /// Return a new range representing the possible values resulting /// from an addition of a value in this range and a value in \p Other. ConstantRange add(const ConstantRange &Other) const; - /// sub - Return a new range representing the possible values resulting + /// Return a new range representing the possible values resulting /// from a subtraction of a value in this range and a value in \p Other. ConstantRange sub(const ConstantRange &Other) const; - /// multiply - Return a new range representing the possible values resulting + /// Return a new range representing the possible values resulting /// from a multiplication of a value in this range and a value in \p Other. /// TODO: This isn't fully implemented yet. ConstantRange multiply(const ConstantRange &Other) const; - /// smax - Return a new range representing the possible values resulting + /// Return a new range representing the possible values resulting /// from a signed maximum of a value in this range and a value in \p Other. ConstantRange smax(const ConstantRange &Other) const; - /// umax - Return a new range representing the possible values resulting + /// Return a new range representing the possible values resulting /// from an unsigned maximum of a value in this range and a value in \p Other. ConstantRange umax(const ConstantRange &Other) const; - /// udiv - Return a new range representing the possible values resulting + /// Return a new range representing the possible values resulting /// from an unsigned division of a value in this range and a value in /// \p Other. ConstantRange udiv(const ConstantRange &Other) const; - /// binaryAnd - return a new range representing the possible values resulting + /// Return a new range representing the possible values resulting /// from a binary-and of a value in this range by a value in \p Other. ConstantRange binaryAnd(const ConstantRange &Other) const; - /// binaryOr - return a new range representing the possible values resulting + /// Return a new range representing the possible values resulting /// from a binary-or of a value in this range by a value in \p Other. ConstantRange binaryOr(const ConstantRange &Other) const; - /// shl - Return a new range representing the possible values resulting + /// Return a new range representing the possible values resulting /// from a left shift of a value in this range by a value in \p Other. /// TODO: This isn't fully implemented yet. ConstantRange shl(const ConstantRange &Other) const; - /// lshr - Return a new range representing the possible values resulting - /// from a logical right shift of a value in this range and a value in - /// \p Other. + /// Return a new range representing the possible values resulting from a + /// logical right shift of a value in this range and a value in \p Other. ConstantRange lshr(const ConstantRange &Other) const; - /// inverse - Return a new range that is the logical not of the current set. + /// Return a new range that is the logical not of the current set. /// ConstantRange inverse() const; - /// print - Print out the bounds to a stream... + /// Print out the bounds to a stream. /// void print(raw_ostream &OS) const; - /// dump - Allow printing from a debugger easily... + /// Allow printing from a debugger easily. /// void dump() const; }; diff --git a/include/llvm/IR/Constants.h b/include/llvm/IR/Constants.h index 1b0e1b7..59be653 100644 --- a/include/llvm/IR/Constants.h +++ b/include/llvm/IR/Constants.h @@ -46,8 +46,8 @@ template struct ConstantAggrKeyType; /// @brief Class for constant integers. class ConstantInt : public Constant { void anchor() override; - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; - ConstantInt(const ConstantInt &) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; + ConstantInt(const ConstantInt &) = delete; ConstantInt(IntegerType *Ty, const APInt& V); APInt Val; protected: @@ -228,8 +228,8 @@ public: class ConstantFP : public Constant { APFloat Val; void anchor() override; - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; - ConstantFP(const ConstantFP &) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; + ConstantFP(const ConstantFP &) = delete; friend class LLVMContextImpl; protected: ConstantFP(Type *Ty, const APFloat& V); @@ -294,8 +294,8 @@ public: /// ConstantAggregateZero - All zero aggregate value /// class ConstantAggregateZero : public Constant { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; - ConstantAggregateZero(const ConstantAggregateZero &) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; + ConstantAggregateZero(const ConstantAggregateZero &) = delete; protected: explicit ConstantAggregateZero(Type *ty) : Constant(ty, ConstantAggregateZeroVal, nullptr, 0) {} @@ -325,6 +325,9 @@ public: /// index. Constant *getElementValue(unsigned Idx) const; + /// \brief Return the number of elements in the array, vector, or struct. + unsigned getNumElements() const; + /// Methods for support type inquiry through isa, cast, and dyn_cast: /// static bool classof(const Value *V) { @@ -338,7 +341,7 @@ public: /// class ConstantArray : public Constant { friend struct ConstantAggrKeyType; - ConstantArray(const ConstantArray &) LLVM_DELETED_FUNCTION; + ConstantArray(const ConstantArray &) = delete; protected: ConstantArray(ArrayType *T, ArrayRef Val); public: @@ -380,7 +383,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantArray, Constant) // class ConstantStruct : public Constant { friend struct ConstantAggrKeyType; - ConstantStruct(const ConstantStruct &) LLVM_DELETED_FUNCTION; + ConstantStruct(const ConstantStruct &) = delete; protected: ConstantStruct(StructType *T, ArrayRef Val); public: @@ -439,7 +442,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantStruct, Constant) /// class ConstantVector : public Constant { friend struct ConstantAggrKeyType; - ConstantVector(const ConstantVector &) LLVM_DELETED_FUNCTION; + ConstantVector(const ConstantVector &) = delete; protected: ConstantVector(VectorType *T, ArrayRef Val); public: @@ -488,8 +491,8 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantVector, Constant) /// ConstantPointerNull - a constant pointer value that points to null /// class ConstantPointerNull : public Constant { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; - ConstantPointerNull(const ConstantPointerNull &) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; + ConstantPointerNull(const ConstantPointerNull &) = delete; protected: explicit ConstantPointerNull(PointerType *T) : Constant(T, @@ -539,8 +542,8 @@ class ConstantDataSequential : public Constant { /// element array of i8, or a 1-element array of i32. They'll both end up in /// the same StringMap bucket, linked up. ConstantDataSequential *Next; - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; - ConstantDataSequential(const ConstantDataSequential &) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; + ConstantDataSequential(const ConstantDataSequential &) = delete; protected: explicit ConstantDataSequential(Type *ty, ValueTy VT, const char *Data) : Constant(ty, VT, nullptr, 0), DataElements(Data), Next(nullptr) {} @@ -650,8 +653,8 @@ private: /// operands because it stores all of the elements of the constant as densely /// packed data, instead of as Value*'s. class ConstantDataArray : public ConstantDataSequential { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; - ConstantDataArray(const ConstantDataArray &) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; + ConstantDataArray(const ConstantDataArray &) = delete; void anchor() override; friend class ConstantDataSequential; explicit ConstantDataArray(Type *ty, const char *Data) @@ -673,6 +676,15 @@ public: static Constant *get(LLVMContext &Context, ArrayRef Elts); static Constant *get(LLVMContext &Context, ArrayRef Elts); + /// getFP() constructors - Return a constant with array type with an element + /// count and element type of float with precision matching the number of + /// bits in the ArrayRef passed in. (i.e. half for 16bits, float for 32bits, + /// double for 64bits) Note that this can return a ConstantAggregateZero + /// object. + static Constant *getFP(LLVMContext &Context, ArrayRef Elts); + static Constant *getFP(LLVMContext &Context, ArrayRef Elts); + static Constant *getFP(LLVMContext &Context, ArrayRef Elts); + /// getString - This method constructs a CDS and initializes it with a text /// string. The default behavior (AddNull==true) causes a null terminator to /// be placed at the end of the array (increasing the length of the string by @@ -702,8 +714,8 @@ public: /// operands because it stores all of the elements of the constant as densely /// packed data, instead of as Value*'s. class ConstantDataVector : public ConstantDataSequential { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; - ConstantDataVector(const ConstantDataVector &) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; + ConstantDataVector(const ConstantDataVector &) = delete; void anchor() override; friend class ConstantDataSequential; explicit ConstantDataVector(Type *ty, const char *Data) @@ -725,6 +737,15 @@ public: static Constant *get(LLVMContext &Context, ArrayRef Elts); static Constant *get(LLVMContext &Context, ArrayRef Elts); + /// getFP() constructors - Return a constant with vector type with an element + /// count and element type of float with the precision matching the number of + /// bits in the ArrayRef passed in. (i.e. half for 16bits, float for 32bits, + /// double for 64bits) Note that this can return a ConstantAggregateZero + /// object. + static Constant *getFP(LLVMContext &Context, ArrayRef Elts); + static Constant *getFP(LLVMContext &Context, ArrayRef Elts); + static Constant *getFP(LLVMContext &Context, ArrayRef Elts); + /// getSplat - Return a ConstantVector with the specified constant in each /// element. The specified constant has to be a of a compatible type (i8/i16/ /// i32/i64/float/double) and must be a ConstantFP or ConstantInt. @@ -753,7 +774,7 @@ public: /// BlockAddress - The address of a basic block. /// class BlockAddress : public Constant { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; void *operator new(size_t s) { return User::operator new(s, 2); } BlockAddress(Function *F, BasicBlock *BB); public: @@ -1165,8 +1186,8 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantExpr, Constant) /// LangRef.html#undefvalues for details. /// class UndefValue : public Constant { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; - UndefValue(const UndefValue &) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; + UndefValue(const UndefValue &) = delete; protected: explicit UndefValue(Type *T) : Constant(T, UndefValueVal, nullptr, 0) {} protected: @@ -1196,6 +1217,9 @@ public: /// index. UndefValue *getElementValue(unsigned Idx) const; + /// \brief Return the number of elements in the array, vector, or struct. + unsigned getNumElements() const; + void destroyConstant() override; /// Methods for support type inquiry through isa, cast, and dyn_cast: diff --git a/include/llvm/IR/DIBuilder.h b/include/llvm/IR/DIBuilder.h index 3a50609..97a7b83 100644 --- a/include/llvm/IR/DIBuilder.h +++ b/include/llvm/IR/DIBuilder.h @@ -18,6 +18,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" #include "llvm/IR/DebugInfo.h" +#include "llvm/IR/TrackingMDRef.h" #include "llvm/IR/ValueHandle.h" #include "llvm/Support/DataTypes.h" @@ -65,22 +66,34 @@ namespace llvm { Function *DeclareFn; // llvm.dbg.declare Function *ValueFn; // llvm.dbg.value - SmallVector AllEnumTypes; - /// Use TrackingVH to collect RetainTypes, since they can be updated - /// later on. - SmallVector, 4> AllRetainTypes; - SmallVector AllSubprograms; - SmallVector AllGVs; - SmallVector, 4> AllImportedModules; + SmallVector AllEnumTypes; + /// Track the RetainTypes, since they can be updated later on. + SmallVector AllRetainTypes; + SmallVector AllSubprograms; + SmallVector AllGVs; + SmallVector AllImportedModules; + + /// \brief Track nodes that may be unresolved. + SmallVector UnresolvedNodes; + bool AllowUnresolvedNodes; /// Each subprogram's preserved local variables. - DenseMap>> PreservedVariables; + DenseMap> PreservedVariables; + + DIBuilder(const DIBuilder &) = delete; + void operator=(const DIBuilder &) = delete; - DIBuilder(const DIBuilder &) LLVM_DELETED_FUNCTION; - void operator=(const DIBuilder &) LLVM_DELETED_FUNCTION; + /// \brief Create a temporary. + /// + /// Create an \a temporary node and track it in \a UnresolvedNodes. + void trackIfUnresolved(MDNode *N); public: - explicit DIBuilder(Module &M); + /// \brief Construct a builder for a module. + /// + /// If \c AllowUnresolved, collect unresolved nodes attached to the module + /// in order to resolve cycles during \a finalize(). + explicit DIBuilder(Module &M, bool AllowUnresolved = true); enum DebugEmissionKind { FullDebug=1, LineTablesOnly }; /// finalize - Construct any deferred debug info descriptors. @@ -159,8 +172,12 @@ namespace llvm { /// \brief Create debugging information entry for a pointer to member. /// @param PointeeTy Type pointed to by this pointer. + /// @param SizeInBits Size. + /// @param AlignInBits Alignment. (optional) /// @param Class Type for which this pointer points to members of. - DIDerivedType createMemberPointerType(DIType PointeeTy, DIType Class); + DIDerivedType createMemberPointerType(DIType PointeeTy, DIType Class, + uint64_t SizeInBits, + uint64_t AlignInBits = 0); /// createReferenceType - Create debugging information entry for a c++ /// style reference or rvalue reference type. @@ -316,13 +333,8 @@ namespace llvm { /// @param Scope Scope in which this type is defined. /// @param Name Type parameter name. /// @param Ty Parameter type. - /// @param File File where this type parameter is defined. - /// @param LineNo Line number. - /// @param ColumnNo Column Number. DITemplateTypeParameter - createTemplateTypeParameter(DIDescriptor Scope, StringRef Name, DIType Ty, - MDNode *File = nullptr, unsigned LineNo = 0, - unsigned ColumnNo = 0); + createTemplateTypeParameter(DIDescriptor Scope, StringRef Name, DIType Ty); /// createTemplateValueParameter - Create debugging information for template /// value parameter. @@ -330,40 +342,30 @@ namespace llvm { /// @param Name Value parameter name. /// @param Ty Parameter type. /// @param Val Constant parameter value. - /// @param File File where this type parameter is defined. - /// @param LineNo Line number. - /// @param ColumnNo Column Number. - DITemplateValueParameter - createTemplateValueParameter(DIDescriptor Scope, StringRef Name, DIType Ty, - Constant *Val, MDNode *File = nullptr, - unsigned LineNo = 0, unsigned ColumnNo = 0); + DITemplateValueParameter createTemplateValueParameter(DIDescriptor Scope, + StringRef Name, + DIType Ty, + Constant *Val); /// \brief Create debugging information for a template template parameter. /// @param Scope Scope in which this type is defined. /// @param Name Value parameter name. /// @param Ty Parameter type. /// @param Val The fully qualified name of the template. - /// @param File File where this type parameter is defined. - /// @param LineNo Line number. - /// @param ColumnNo Column Number. - DITemplateValueParameter - createTemplateTemplateParameter(DIDescriptor Scope, StringRef Name, - DIType Ty, StringRef Val, - MDNode *File = nullptr, unsigned LineNo = 0, - unsigned ColumnNo = 0); + DITemplateValueParameter createTemplateTemplateParameter(DIDescriptor Scope, + StringRef Name, + DIType Ty, + StringRef Val); /// \brief Create debugging information for a template parameter pack. /// @param Scope Scope in which this type is defined. /// @param Name Value parameter name. /// @param Ty Parameter type. /// @param Val An array of types in the pack. - /// @param File File where this type parameter is defined. - /// @param LineNo Line number. - /// @param ColumnNo Column Number. - DITemplateValueParameter - createTemplateParameterPack(DIDescriptor Scope, StringRef Name, - DIType Ty, DIArray Val, MDNode *File = nullptr, - unsigned LineNo = 0, unsigned ColumnNo = 0); + DITemplateValueParameter createTemplateParameterPack(DIDescriptor Scope, + StringRef Name, + DIType Ty, + DIArray Val); /// createArrayType - Create debugging information entry for an array. /// @param Size Array size. @@ -423,10 +425,11 @@ namespace llvm { StringRef UniqueIdentifier = StringRef()); /// \brief Create a temporary forward-declared type. - DICompositeType createReplaceableForwardDecl( + DICompositeType createReplaceableCompositeType( unsigned Tag, StringRef Name, DIDescriptor Scope, DIFile F, unsigned Line, unsigned RuntimeLang = 0, uint64_t SizeInBits = 0, - uint64_t AlignInBits = 0, StringRef UniqueIdentifier = StringRef()); + uint64_t AlignInBits = 0, unsigned Flags = DIDescriptor::FlagFwdDecl, + StringRef UniqueIdentifier = StringRef()); /// retainType - Retain DIType in a module even if it is not referenced /// through debug info anchors. @@ -437,10 +440,10 @@ namespace llvm { DIBasicType createUnspecifiedParameter(); /// getOrCreateArray - Get a DIArray, create one if required. - DIArray getOrCreateArray(ArrayRef Elements); + DIArray getOrCreateArray(ArrayRef Elements); /// getOrCreateTypeArray - Get a DITypeArray, create one if required. - DITypeArray getOrCreateTypeArray(ArrayRef Elements); + DITypeArray getOrCreateTypeArray(ArrayRef Elements); /// getOrCreateSubrange - Create a descriptor for a value range. This /// implicitly uniques the values returned. @@ -497,15 +500,16 @@ namespace llvm { /// createExpression - Create a new descriptor for the specified /// variable which has a complex address expression for its address. /// @param Addr An array of complex address operations. - DIExpression createExpression(ArrayRef Addr = None); + DIExpression createExpression(ArrayRef Addr = None); + DIExpression createExpression(ArrayRef Addr); - /// createPieceExpression - Create a descriptor to describe one part + /// createBitPieceExpression - Create a descriptor to describe one part /// of aggregate variable that is fragmented across multiple Values. /// - /// @param OffsetInBytes Offset of the piece in bytes. - /// @param SizeInBytes Size of the piece in bytes. - DIExpression createPieceExpression(unsigned OffsetInBytes, - unsigned SizeInBytes); + /// @param OffsetInBits Offset of the piece in bits. + /// @param SizeInBits Size of the piece in bits. + DIExpression createBitPieceExpression(unsigned OffsetInBits, + unsigned SizeInBits); /// createFunction - Create a new descriptor for the specified subprogram. /// See comments in DISubprogram for descriptions of these fields. @@ -685,6 +689,20 @@ namespace llvm { Instruction *insertDbgValueIntrinsic(llvm::Value *Val, uint64_t Offset, DIVariable VarInfo, DIExpression Expr, Instruction *InsertBefore); + + /// \brief Replace the vtable holder in the given composite type. + /// + /// If this creates a self reference, it may orphan some unresolved cycles + /// in the operands of \c T, so \a DIBuilder needs to track that. + void replaceVTableHolder(DICompositeType &T, DICompositeType VTableHolder); + + /// \brief Replace arrays on a composite type. + /// + /// If \c T is resolved, but the arrays aren't -- which can happen if \c T + /// has a self-reference -- \a DIBuilder needs to track the array to + /// resolve cycles. + void replaceArrays(DICompositeType &T, DIArray Elements, + DIArray TParems = DIArray()); }; } // end namespace llvm diff --git a/include/llvm/IR/DataLayout.h b/include/llvm/IR/DataLayout.h index 4580a4f..9479ba4 100644 --- a/include/llvm/IR/DataLayout.h +++ b/include/llvm/IR/DataLayout.h @@ -53,6 +53,11 @@ enum AlignTypeEnum { AGGREGATE_ALIGN = 'a' }; +// FIXME: Currently the DataLayout string carries a "preferred alignment" +// for types. As the DataLayout is module/global, this should likely be +// sunk down to an FTTI element that is queried rather than a global +// preference. + /// \brief Layout alignment element. /// /// Stores the alignment data associated with a given alignment type (integer, @@ -228,6 +233,8 @@ public: return (StackNaturalAlign != 0) && (Align > StackNaturalAlign); } + unsigned getStackAlignment() const { return StackNaturalAlign; } + bool hasMicrosoftFastStdCallMangling() const { return ManglingMode == MM_WINCOFF; } diff --git a/include/llvm/IR/DebugInfo.h b/include/llvm/IR/DebugInfo.h index 22a2138..d2e5975 100644 --- a/include/llvm/IR/DebugInfo.h +++ b/include/llvm/IR/DebugInfo.h @@ -18,11 +18,11 @@ #define LLVM_IR_DEBUGINFO_H #include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/iterator_range.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" -#include "llvm/IR/Metadata.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/IR/DebugInfoMetadata.h" #include "llvm/Support/Casting.h" #include "llvm/Support/Dwarf.h" #include "llvm/Support/ErrorHandling.h" @@ -66,10 +66,10 @@ class DIHeaderFieldIterator public: DIHeaderFieldIterator() {} - DIHeaderFieldIterator(StringRef Header) + explicit DIHeaderFieldIterator(StringRef Header) : Header(Header), Current(Header.slice(0, Header.find('\0'))) {} StringRef operator*() const { return Current; } - const StringRef * operator->() const { return &Current; } + const StringRef *operator->() const { return &Current; } DIHeaderFieldIterator &operator++() { increment(); return *this; @@ -99,6 +99,16 @@ public: return Header.slice(Current.end() - Header.begin() + 1, StringRef::npos); } + /// \brief Get the current field as a number. + /// + /// Convert the current field into a number. Return \c 0 on error. + template T getNumber() const { + T Int; + if (getCurrent().getAsInteger(0, Int)) + return 0; + return Int; + } + private: void increment() { assert(Current.data() != nullptr && "Cannot increment past the end"); @@ -122,27 +132,21 @@ public: /// The three accessibility flags are mutually exclusive and rolled together /// in the first two bits. enum { - FlagAccessibility = 1 << 0 | 1 << 1, - FlagPrivate = 1, - FlagProtected = 2, - FlagPublic = 3, - - FlagFwdDecl = 1 << 2, - FlagAppleBlock = 1 << 3, - FlagBlockByrefStruct = 1 << 4, - FlagVirtual = 1 << 5, - FlagArtificial = 1 << 6, - FlagExplicit = 1 << 7, - FlagPrototyped = 1 << 8, - FlagObjcClassComplete = 1 << 9, - FlagObjectPointer = 1 << 10, - FlagVector = 1 << 11, - FlagStaticMember = 1 << 12, - FlagIndirectVariable = 1 << 13, - FlagLValueReference = 1 << 14, - FlagRValueReference = 1 << 15 +#define HANDLE_DI_FLAG(ID, NAME) Flag##NAME = ID, +#include "llvm/IR/DebugInfoFlags.def" + FlagAccessibility = FlagPrivate | FlagProtected | FlagPublic }; + static unsigned getFlag(StringRef Flag); + static const char *getFlagString(unsigned Flag); + + /// \brief Split up a flags bitfield. + /// + /// Split \c Flags into \c SplitFlags, a vector of its components. Returns + /// any remaining (unrecognized) bits. + static unsigned splitFlags(unsigned Flags, + SmallVectorImpl &SplitFlags); + protected: const MDNode *DbgNode; @@ -168,42 +172,47 @@ public: bool Verify() const; - operator MDNode *() const { return const_cast(DbgNode); } - MDNode *operator->() const { return const_cast(DbgNode); } + MDNode *get() const { return const_cast(DbgNode); } + operator MDNode *() const { return get(); } + MDNode *operator->() const { return get(); } // An explicit operator bool so that we can do testing of DI values // easily. // FIXME: This operator bool isn't actually protecting anything at the // moment due to the conversion operator above making DIDescriptor nodes // implicitly convertable to bool. - LLVM_EXPLICIT operator bool() const { return DbgNode != nullptr; } + explicit operator bool() const { return DbgNode != nullptr; } bool operator==(DIDescriptor Other) const { return DbgNode == Other.DbgNode; } bool operator!=(DIDescriptor Other) const { return !operator==(Other); } - StringRef getHeader() const { - return getStringField(0); - } + StringRef getHeader() const { return getStringField(0); } size_t getNumHeaderFields() const { return std::distance(DIHeaderFieldIterator(getHeader()), DIHeaderFieldIterator()); } - StringRef getHeaderField(unsigned Index) const { + DIHeaderFieldIterator header_begin() const { + return DIHeaderFieldIterator(getHeader()); + } + DIHeaderFieldIterator header_end() const { return DIHeaderFieldIterator(); } + + DIHeaderFieldIterator getHeaderIterator(unsigned Index) const { // Since callers expect an empty string for out-of-range accesses, we can't // use std::advance() here. - for (DIHeaderFieldIterator I(getHeader()), E; I != E; ++I, --Index) + for (auto I = header_begin(), E = header_end(); I != E; ++I, --Index) if (!Index) - return *I; - return StringRef(); + return I; + return header_end(); + } + + StringRef getHeaderField(unsigned Index) const { + return *getHeaderIterator(Index); } template T getHeaderFieldAs(unsigned Index) const { - T Int; - if (getHeaderField(Index).getAsInteger(0, Int)) - return 0; - return Int; + return getHeaderIterator(Index).getNumber(); } uint16_t getTag() const { return getHeaderFieldAs(0); } @@ -238,6 +247,19 @@ public: void replaceAllUsesWith(MDNode *D); }; +#define RETURN_FROM_RAW(VALID, DEFAULT) \ + do { \ + if (auto *N = getRaw()) \ + return VALID; \ + return DEFAULT; \ + } while (false) +#define RETURN_DESCRIPTOR_FROM_RAW(DESC, VALID) \ + do { \ + if (auto *N = getRaw()) \ + return DESC(dyn_cast_or_null(VALID)); \ + return DESC(static_cast(nullptr)); \ + } while (false) + /// \brief This is used to represent ranges, for array bounds. class DISubrange : public DIDescriptor { friend class DIDescriptor; @@ -258,9 +280,7 @@ public: unsigned getNumElements() const { return DbgNode ? DbgNode->getNumOperands() : 0; } - T getElement(unsigned Idx) const { - return getFieldAs(Idx); - } + T getElement(unsigned Idx) const { return getFieldAs(Idx); } }; typedef DITypedArray DIArray; @@ -282,6 +302,7 @@ public: }; template class DIRef; +typedef DIRef DIDescriptorRef; typedef DIRef DIScopeRef; typedef DIRef DITypeRef; typedef DITypedArray DITypeArray; @@ -371,6 +392,12 @@ template StringRef DIRef::getName() const { return MS->getString(); } +/// \brief Handle fields that are references to DIDescriptors. +template <> +DIDescriptorRef DIDescriptor::getFieldAs(unsigned Elt) const; +/// \brief Specialize DIRef constructor for DIDescriptorRef. +template <> DIRef::DIRef(const Metadata *V); + /// \brief Handle fields that are references to DIScopes. template <> DIScopeRef DIDescriptor::getFieldAs(unsigned Elt) const; /// \brief Specialize DIRef constructor for DIScopeRef. @@ -381,7 +408,7 @@ template <> DITypeRef DIDescriptor::getFieldAs(unsigned Elt) const; /// \brief Specialize DIRef constructor for DITypeRef. template <> DIRef::DIRef(const Metadata *V); -/// \briefThis is a wrapper for a type. +/// \brief This is a wrapper for a type. /// /// FIXME: Types should be factored much better so that CV qualifiers and /// others do not require a huge and empty descriptor full of zeros. @@ -392,7 +419,7 @@ protected: public: explicit DIType(const MDNode *N = nullptr) : DIScope(N) {} - operator DITypeRef () const { + operator DITypeRef() const { assert(isType() && "constructing DITypeRef from an MDNode that is not a type"); return DITypeRef(&*getRef()); @@ -402,20 +429,12 @@ public: DIScopeRef getContext() const { return getFieldAs(2); } StringRef getName() const { return getHeaderField(1); } - unsigned getLineNumber() const { - return getHeaderFieldAs(2); - } - uint64_t getSizeInBits() const { - return getHeaderFieldAs(3); - } - uint64_t getAlignInBits() const { - return getHeaderFieldAs(4); - } + unsigned getLineNumber() const { return getHeaderFieldAs(2); } + uint64_t getSizeInBits() const { return getHeaderFieldAs(3); } + uint64_t getAlignInBits() const { return getHeaderFieldAs(4); } // FIXME: Offset is only used for DW_TAG_member nodes. Making every type // carry this is just plain insane. - uint64_t getOffsetInBits() const { - return getHeaderFieldAs(5); - } + uint64_t getOffsetInBits() const { return getHeaderFieldAs(5); } unsigned getFlags() const { return getHeaderFieldAs(6); } bool isPrivate() const { return (getFlags() & FlagAccessibility) == FlagPrivate; @@ -499,6 +518,7 @@ public: // FIXME: Make this derive from DIType directly & just store the // base type in a single DIType field. class DICompositeType : public DIDerivedType { + friend class DIBuilder; friend class DIDescriptor; void printInternal(raw_ostream &OS) const; @@ -512,20 +532,26 @@ public: assert(!isSubroutineType() && "no elements for DISubroutineType"); return getFieldAs(4); } + +private: template void setArrays(DITypedArray Elements, DIArray TParams = DIArray()) { - assert((!TParams || DbgNode->getNumOperands() == 8) && - "If you're setting the template parameters this should include a slot " - "for that!"); + assert( + (!TParams || DbgNode->getNumOperands() == 8) && + "If you're setting the template parameters this should include a slot " + "for that!"); setArraysHelper(Elements, TParams); } - unsigned getRunTimeLang() const { - return getHeaderFieldAs(7); - } + +public: + unsigned getRunTimeLang() const { return getHeaderFieldAs(7); } DITypeRef getContainingType() const { return getFieldAs(5); } +private: /// \brief Set the containing type. void setContainingType(DICompositeType ContainingType); + +public: DIArray getTemplateParams() const { return getFieldAs(6); } MDString *getIdentifier() const; @@ -663,7 +689,6 @@ public: unsigned isRValueReference() const { return (getFlags() & FlagRValueReference) != 0; } - }; /// \brief This is a wrapper for a lexical block. @@ -671,12 +696,8 @@ class DILexicalBlock : public DIScope { public: explicit DILexicalBlock(const MDNode *N = nullptr) : DIScope(N) {} DIScope getContext() const { return getFieldAs(2); } - unsigned getLineNumber() const { - return getHeaderFieldAs(1); - } - unsigned getColumnNumber() const { - return getHeaderFieldAs(2); - } + unsigned getLineNumber() const { return getHeaderFieldAs(1); } + unsigned getColumnNumber() const { return getHeaderFieldAs(2); } bool Verify() const; }; @@ -685,6 +706,8 @@ class DILexicalBlockFile : public DIScope { public: explicit DILexicalBlockFile(const MDNode *N = nullptr) : DIScope(N) {} DIScope getContext() const { + // FIXME: This logic is horrible. getScope() returns a DILexicalBlock, but + // then we check if it's a subprogram? WHAT?!? if (getScope().isSubprogram()) return getScope(); return getScope().getContext(); @@ -713,18 +736,11 @@ public: class DITemplateTypeParameter : public DIDescriptor { public: explicit DITemplateTypeParameter(const MDNode *N = nullptr) - : DIDescriptor(N) {} + : DIDescriptor(N) {} StringRef getName() const { return getHeaderField(1); } - unsigned getLineNumber() const { return getHeaderFieldAs(2); } - unsigned getColumnNumber() const { return getHeaderFieldAs(3); } - DIScopeRef getContext() const { return getFieldAs(1); } DITypeRef getType() const { return getFieldAs(2); } - StringRef getFilename() const { return getFieldAs(3).getFilename(); } - StringRef getDirectory() const { - return getFieldAs(3).getDirectory(); - } bool Verify() const; }; @@ -732,19 +748,12 @@ public: class DITemplateValueParameter : public DIDescriptor { public: explicit DITemplateValueParameter(const MDNode *N = nullptr) - : DIDescriptor(N) {} + : DIDescriptor(N) {} StringRef getName() const { return getHeaderField(1); } - unsigned getLineNumber() const { return getHeaderFieldAs(2); } - unsigned getColumnNumber() const { return getHeaderFieldAs(3); } - DIScopeRef getContext() const { return getFieldAs(1); } DITypeRef getType() const { return getFieldAs(2); } - Value *getValue() const; - StringRef getFilename() const { return getFieldAs(4).getFilename(); } - StringRef getDirectory() const { - return getFieldAs(4).getDirectory(); - } + Metadata *getValue() const; bool Verify() const; }; @@ -763,7 +772,7 @@ public: unsigned isLocalToUnit() const { return getHeaderFieldAs(5); } unsigned isDefinition() const { return getHeaderFieldAs(6); } - DIScopeRef getContext() const { return getFieldAs(1); } + DIScope getContext() const { return getFieldAs(1); } StringRef getFilename() const { return getFieldAs(2).getFilename(); } StringRef getDirectory() const { return getFieldAs(2).getDirectory(); @@ -807,11 +816,6 @@ public: return (getHeaderFieldAs(3) & FlagObjectPointer) != 0; } - /// \brief Return true if this variable is represented as a pointer. - bool isIndirect() const { - return (getHeaderFieldAs(3) & FlagIndirectVariable) != 0; - } - /// \brief If this variable is inlined then return inline location. MDNode *getInlinedAt() const; @@ -831,7 +835,13 @@ public: void printExtendedName(raw_ostream &OS) const; }; -/// \brief A complex location expression. +/// \brief A complex location expression in postfix notation. +/// +/// This is (almost) a DWARF expression that modifies the location of a +/// variable or (or the location of a single piece of a variable). +/// +/// FIXME: Instead of DW_OP_plus taking an argument, this should use DW_OP_const +/// and have DW_OP_plus consume the topmost elements on the stack. class DIExpression : public DIDescriptor { friend class DIDescriptor; void printInternal(raw_ostream &OS) const; @@ -854,24 +864,91 @@ public: uint64_t getElement(unsigned Idx) const; /// \brief Return whether this is a piece of an aggregate variable. - bool isVariablePiece() const; - /// \brief Return the offset of this piece in bytes. - uint64_t getPieceOffset() const; - /// \brief Return the size of this piece in bytes. - uint64_t getPieceSize() const; + bool isBitPiece() const; + /// \brief Return the offset of this piece in bits. + uint64_t getBitPieceOffset() const; + /// \brief Return the size of this piece in bits. + uint64_t getBitPieceSize() const; + + class iterator; + /// \brief A lightweight wrapper around an element of a DIExpression. + class Operand { + friend class iterator; + DIHeaderFieldIterator I; + Operand() {} + Operand(DIHeaderFieldIterator I) : I(I) {} + public: + /// \brief Operands such as DW_OP_piece have explicit (non-stack) arguments. + /// Argument 0 is the operand itself. + uint64_t getArg(unsigned N) const { + DIHeaderFieldIterator In = I; + std::advance(In, N); + return In.getNumber(); + } + operator uint64_t () const { return I.getNumber(); } + /// \brief Returns underlying DIHeaderFieldIterator. + const DIHeaderFieldIterator &getBase() const { return I; } + /// \brief Returns the next operand. + Operand getNext() const; + }; + + /// \brief An iterator for DIExpression elements. + class iterator : public std::iterator { + friend class Operand; + DIHeaderFieldIterator I; + Operand Tmp; + iterator(DIHeaderFieldIterator I) : I(I) {} + public: + iterator() {} + iterator(const DIExpression &Expr) : I(++Expr.header_begin()) {} + const Operand &operator*() { return Tmp = Operand(I); } + const Operand *operator->() { return &(Tmp = Operand(I)); } + iterator &operator++() { + increment(); + return *this; + } + iterator operator++(int) { + iterator X(*this); + increment(); + return X; + } + bool operator==(const iterator &X) const { return I == X.I; } + bool operator!=(const iterator &X) const { return !(*this == X); } + + private: + void increment() { + switch (**this) { + case dwarf::DW_OP_bit_piece: std::advance(I, 3); break; + case dwarf::DW_OP_plus: std::advance(I, 2); break; + case dwarf::DW_OP_deref: std::advance(I, 1); break; + default: + llvm_unreachable("unsupported operand"); + } + } + }; + + iterator begin() const; + iterator end() const; }; /// \brief This object holds location information. /// /// This object is not associated with any DWARF tag. class DILocation : public DIDescriptor { + MDLocation *getRaw() const { return dyn_cast_or_null(get()); } + public: explicit DILocation(const MDNode *N) : DIDescriptor(N) {} - unsigned getLineNumber() const { return getUnsignedField(0); } - unsigned getColumnNumber() const { return getUnsignedField(1); } - DIScope getScope() const { return getFieldAs(2); } - DILocation getOrigLocation() const { return getFieldAs(3); } + unsigned getLineNumber() const { RETURN_FROM_RAW(N->getLine(), 0); } + unsigned getColumnNumber() const { RETURN_FROM_RAW(N->getColumn(), 0); } + DIScope getScope() const { + RETURN_DESCRIPTOR_FROM_RAW(DIScope, N->getScope()); + } + DILocation getOrigLocation() const { + RETURN_DESCRIPTOR_FROM_RAW(DILocation, N->getInlinedAt()); + } StringRef getFilename() const { return getScope().getFilename(); } StringRef getDirectory() const { return getScope().getDirectory(); } bool Verify() const; @@ -892,7 +969,9 @@ public: // sure this location is a lexical block before retrieving its // value. return getScope().isLexicalBlockFile() - ? getFieldAs(2).getDiscriminator() + ? DILexicalBlockFile( + cast(cast(DbgNode)->getScope())) + .getDiscriminator() : 0; } @@ -951,14 +1030,18 @@ class DIImportedEntity : public DIDescriptor { void printInternal(raw_ostream &OS) const; public: + DIImportedEntity() = default; explicit DIImportedEntity(const MDNode *N) : DIDescriptor(N) {} DIScope getContext() const { return getFieldAs(1); } - DIScopeRef getEntity() const { return getFieldAs(2); } + DIDescriptorRef getEntity() const { return getFieldAs(2); } unsigned getLineNumber() const { return getHeaderFieldAs(1); } StringRef getName() const { return getHeaderField(2); } bool Verify() const; }; +#undef RETURN_FROM_RAW +#undef RETURN_DESCRIPTOR_FROM_RAW + /// \brief Find subprogram that is enclosing this scope. DISubprogram getDISubprogram(const MDNode *Scope); @@ -1015,6 +1098,9 @@ public: /// \brief Process DILocation. void processLocation(const Module &M, DILocation Loc); + /// \brief Process DIExpression. + void processExpression(DIExpression Expr); + /// \brief Clear all lists. void reset(); @@ -1033,7 +1119,8 @@ private: public: typedef SmallVectorImpl::const_iterator compile_unit_iterator; typedef SmallVectorImpl::const_iterator subprogram_iterator; - typedef SmallVectorImpl::const_iterator global_variable_iterator; + typedef SmallVectorImpl::const_iterator + global_variable_iterator; typedef SmallVectorImpl::const_iterator type_iterator; typedef SmallVectorImpl::const_iterator scope_iterator; diff --git a/include/llvm/IR/DebugInfoFlags.def b/include/llvm/IR/DebugInfoFlags.def new file mode 100644 index 0000000..d5de868 --- /dev/null +++ b/include/llvm/IR/DebugInfoFlags.def @@ -0,0 +1,36 @@ +//===- llvm/IR/DebugInfoFlags.def - Debug info flag definitions -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Macros for running through debug info flags. +// +//===----------------------------------------------------------------------===// + +// TODO: Add other DW-based macros. +#ifndef HANDLE_DI_FLAG +#error "Missing macro definition of HANDLE_DI_FLAG" +#endif + +HANDLE_DI_FLAG(1, Private) +HANDLE_DI_FLAG(2, Protected) +HANDLE_DI_FLAG(3, Public) +HANDLE_DI_FLAG((1 << 2), FwdDecl) +HANDLE_DI_FLAG((1 << 3), AppleBlock) +HANDLE_DI_FLAG((1 << 4), BlockByrefStruct) +HANDLE_DI_FLAG((1 << 5), Virtual) +HANDLE_DI_FLAG((1 << 6), Artificial) +HANDLE_DI_FLAG((1 << 7), Explicit) +HANDLE_DI_FLAG((1 << 8), Prototyped) +HANDLE_DI_FLAG((1 << 9), ObjcClassComplete) +HANDLE_DI_FLAG((1 << 10), ObjectPointer) +HANDLE_DI_FLAG((1 << 11), Vector) +HANDLE_DI_FLAG((1 << 12), StaticMember) +HANDLE_DI_FLAG((1 << 13), LValueReference) +HANDLE_DI_FLAG((1 << 14), RValueReference) + +#undef HANDLE_DI_FLAG diff --git a/include/llvm/IR/DebugInfoMetadata.h b/include/llvm/IR/DebugInfoMetadata.h new file mode 100644 index 0000000..4534a14 --- /dev/null +++ b/include/llvm/IR/DebugInfoMetadata.h @@ -0,0 +1,1669 @@ +//===- llvm/IR/DebugInfoMetadata.h - Debug info metadata --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Declarations for metadata specific to debug info. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_DEBUGINFOMETADATA_H +#define LLVM_IR_DEBUGINFOMETADATA_H + +#include "llvm/IR/Metadata.h" +#include "llvm/Support/Dwarf.h" + +// Helper macros for defining get() overrides. +#define DEFINE_MDNODE_GET_UNPACK_IMPL(...) __VA_ARGS__ +#define DEFINE_MDNODE_GET_UNPACK(ARGS) DEFINE_MDNODE_GET_UNPACK_IMPL ARGS +#define DEFINE_MDNODE_GET(CLASS, FORMAL, ARGS) \ + static CLASS *get(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK(FORMAL)) { \ + return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(ARGS), Uniqued); \ + } \ + static CLASS *getIfExists(LLVMContext &Context, \ + DEFINE_MDNODE_GET_UNPACK(FORMAL)) { \ + return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(ARGS), Uniqued, \ + /* ShouldCreate */ false); \ + } \ + static CLASS *getDistinct(LLVMContext &Context, \ + DEFINE_MDNODE_GET_UNPACK(FORMAL)) { \ + return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(ARGS), Distinct); \ + } \ + static Temp##CLASS getTemporary(LLVMContext &Context, \ + DEFINE_MDNODE_GET_UNPACK(FORMAL)) { \ + return Temp##CLASS( \ + getImpl(Context, DEFINE_MDNODE_GET_UNPACK(ARGS), Temporary)); \ + } + +namespace llvm { + +/// \brief Debug location. +/// +/// A debug location in source code, used for debug info and otherwise. +class MDLocation : public MDNode { + friend class LLVMContextImpl; + friend class MDNode; + + MDLocation(LLVMContext &C, StorageType Storage, unsigned Line, + unsigned Column, ArrayRef MDs); + ~MDLocation() { dropAllReferences(); } + + static MDLocation *getImpl(LLVMContext &Context, unsigned Line, + unsigned Column, Metadata *Scope, + Metadata *InlinedAt, StorageType Storage, + bool ShouldCreate = true); + + TempMDLocation cloneImpl() const { + return getTemporary(getContext(), getLine(), getColumn(), getScope(), + getInlinedAt()); + } + + // Disallow replacing operands. + void replaceOperandWith(unsigned I, Metadata *New) = delete; + +public: + DEFINE_MDNODE_GET(MDLocation, + (unsigned Line, unsigned Column, Metadata *Scope, + Metadata *InlinedAt = nullptr), + (Line, Column, Scope, InlinedAt)) + + /// \brief Return a (temporary) clone of this. + TempMDLocation clone() const { return cloneImpl(); } + + unsigned getLine() const { return SubclassData32; } + unsigned getColumn() const { return SubclassData16; } + Metadata *getScope() const { return getOperand(0); } + Metadata *getInlinedAt() const { + if (getNumOperands() == 2) + return getOperand(1); + return nullptr; + } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDLocationKind; + } +}; + +/// \brief Tagged DWARF-like metadata node. +/// +/// A metadata node with a DWARF tag (i.e., a constant named \c DW_TAG_*, +/// defined in llvm/Support/Dwarf.h). Called \a DebugNode because it's +/// potentially used for non-DWARF output. +class DebugNode : public MDNode { + friend class LLVMContextImpl; + friend class MDNode; + +protected: + DebugNode(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag, + ArrayRef Ops1, ArrayRef Ops2 = None) + : MDNode(C, ID, Storage, Ops1, Ops2) { + assert(Tag < 1u << 16); + SubclassData16 = Tag; + } + ~DebugNode() {} + + template Ty *getOperandAs(unsigned I) const { + return cast_or_null(getOperand(I)); + } + + StringRef getStringOperand(unsigned I) const { + if (auto *S = getOperandAs(I)) + return S->getString(); + return StringRef(); + } + + static MDString *getCanonicalMDString(LLVMContext &Context, StringRef S) { + if (S.empty()) + return nullptr; + return MDString::get(Context, S); + } + +public: + unsigned getTag() const { return SubclassData16; } + + static bool classof(const Metadata *MD) { + switch (MD->getMetadataID()) { + default: + return false; + case GenericDebugNodeKind: + case MDSubrangeKind: + case MDEnumeratorKind: + case MDBasicTypeKind: + case MDDerivedTypeKind: + case MDCompositeTypeKind: + case MDSubroutineTypeKind: + case MDFileKind: + case MDCompileUnitKind: + case MDSubprogramKind: + case MDLexicalBlockKind: + case MDLexicalBlockFileKind: + case MDNamespaceKind: + case MDTemplateTypeParameterKind: + case MDTemplateValueParameterKind: + case MDGlobalVariableKind: + case MDLocalVariableKind: + case MDExpressionKind: + case MDObjCPropertyKind: + case MDImportedEntityKind: + return true; + } + } +}; + +/// \brief Generic tagged DWARF-like metadata node. +/// +/// An un-specialized DWARF-like metadata node. The first operand is a +/// (possibly empty) null-separated \a MDString header that contains arbitrary +/// fields. The remaining operands are \a dwarf_operands(), and are pointers +/// to other metadata. +class GenericDebugNode : public DebugNode { + friend class LLVMContextImpl; + friend class MDNode; + + GenericDebugNode(LLVMContext &C, StorageType Storage, unsigned Hash, + unsigned Tag, ArrayRef Ops1, + ArrayRef Ops2) + : DebugNode(C, GenericDebugNodeKind, Storage, Tag, Ops1, Ops2) { + setHash(Hash); + } + ~GenericDebugNode() { dropAllReferences(); } + + void setHash(unsigned Hash) { SubclassData32 = Hash; } + void recalculateHash(); + + static GenericDebugNode *getImpl(LLVMContext &Context, unsigned Tag, + StringRef Header, + ArrayRef DwarfOps, + StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, Tag, getCanonicalMDString(Context, Header), + DwarfOps, Storage, ShouldCreate); + } + + static GenericDebugNode *getImpl(LLVMContext &Context, unsigned Tag, + MDString *Header, + ArrayRef DwarfOps, + StorageType Storage, + bool ShouldCreate = true); + + TempGenericDebugNode cloneImpl() const { + return getTemporary( + getContext(), getTag(), getHeader(), + SmallVector(dwarf_op_begin(), dwarf_op_end())); + } + +public: + unsigned getHash() const { return SubclassData32; } + + DEFINE_MDNODE_GET(GenericDebugNode, (unsigned Tag, StringRef Header, + ArrayRef DwarfOps), + (Tag, Header, DwarfOps)) + DEFINE_MDNODE_GET(GenericDebugNode, (unsigned Tag, MDString *Header, + ArrayRef DwarfOps), + (Tag, Header, DwarfOps)) + + /// \brief Return a (temporary) clone of this. + TempGenericDebugNode clone() const { return cloneImpl(); } + + unsigned getTag() const { return SubclassData16; } + StringRef getHeader() const { return getStringOperand(0); } + + op_iterator dwarf_op_begin() const { return op_begin() + 1; } + op_iterator dwarf_op_end() const { return op_end(); } + op_range dwarf_operands() const { + return op_range(dwarf_op_begin(), dwarf_op_end()); + } + + unsigned getNumDwarfOperands() const { return getNumOperands() - 1; } + const MDOperand &getDwarfOperand(unsigned I) const { + return getOperand(I + 1); + } + void replaceDwarfOperandWith(unsigned I, Metadata *New) { + replaceOperandWith(I + 1, New); + } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == GenericDebugNodeKind; + } +}; + +/// \brief Array subrange. +/// +/// TODO: Merge into node for DW_TAG_array_type, which should have a custom +/// type. +class MDSubrange : public DebugNode { + friend class LLVMContextImpl; + friend class MDNode; + + int64_t Count; + int64_t Lo; + + MDSubrange(LLVMContext &C, StorageType Storage, int64_t Count, int64_t Lo) + : DebugNode(C, MDSubrangeKind, Storage, dwarf::DW_TAG_subrange_type, + None), + Count(Count), Lo(Lo) {} + ~MDSubrange() {} + + static MDSubrange *getImpl(LLVMContext &Context, int64_t Count, int64_t Lo, + StorageType Storage, bool ShouldCreate = true); + + TempMDSubrange cloneImpl() const { + return getTemporary(getContext(), getCount(), getLo()); + } + +public: + DEFINE_MDNODE_GET(MDSubrange, (int64_t Count, int64_t Lo = 0), (Count, Lo)) + + TempMDSubrange clone() const { return cloneImpl(); } + + int64_t getLo() const { return Lo; } + int64_t getCount() const { return Count; } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDSubrangeKind; + } +}; + +/// \brief Enumeration value. +/// +/// TODO: Add a pointer to the context (DW_TAG_enumeration_type) once that no +/// longer creates a type cycle. +class MDEnumerator : public DebugNode { + friend class LLVMContextImpl; + friend class MDNode; + + int64_t Value; + + MDEnumerator(LLVMContext &C, StorageType Storage, int64_t Value, + ArrayRef Ops) + : DebugNode(C, MDEnumeratorKind, Storage, dwarf::DW_TAG_enumerator, Ops), + Value(Value) {} + ~MDEnumerator() {} + + static MDEnumerator *getImpl(LLVMContext &Context, int64_t Value, + StringRef Name, StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, Value, getCanonicalMDString(Context, Name), Storage, + ShouldCreate); + } + static MDEnumerator *getImpl(LLVMContext &Context, int64_t Value, + MDString *Name, StorageType Storage, + bool ShouldCreate = true); + + TempMDEnumerator cloneImpl() const { + return getTemporary(getContext(), getValue(), getName()); + } + +public: + DEFINE_MDNODE_GET(MDEnumerator, (int64_t Value, StringRef Name), + (Value, Name)) + DEFINE_MDNODE_GET(MDEnumerator, (int64_t Value, MDString *Name), + (Value, Name)) + + TempMDEnumerator clone() const { return cloneImpl(); } + + int64_t getValue() const { return Value; } + StringRef getName() const { return getStringOperand(0); } + + MDString *getRawName() const { return getOperandAs(0); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDEnumeratorKind; + } +}; + +/// \brief Base class for scope-like contexts. +/// +/// Base class for lexical scopes and types (which are also declaration +/// contexts). +/// +/// TODO: Separate the concepts of declaration contexts and lexical scopes. +class MDScope : public DebugNode { +protected: + MDScope(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag, + ArrayRef Ops) + : DebugNode(C, ID, Storage, Tag, Ops) {} + ~MDScope() {} + +public: + Metadata *getFile() const { return getOperand(0); } + + static bool classof(const Metadata *MD) { + switch (MD->getMetadataID()) { + default: + return false; + case MDBasicTypeKind: + case MDDerivedTypeKind: + case MDCompositeTypeKind: + case MDSubroutineTypeKind: + case MDFileKind: + case MDCompileUnitKind: + case MDSubprogramKind: + case MDLexicalBlockKind: + case MDLexicalBlockFileKind: + case MDNamespaceKind: + return true; + } + } +}; + +/// \brief Base class for types. +/// +/// TODO: Remove the hardcoded name and context, since many types don't use +/// them. +/// TODO: Split up flags. +class MDType : public MDScope { + unsigned Line; + unsigned Flags; + uint64_t SizeInBits; + uint64_t AlignInBits; + uint64_t OffsetInBits; + +protected: + MDType(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag, + unsigned Line, uint64_t SizeInBits, uint64_t AlignInBits, + uint64_t OffsetInBits, unsigned Flags, ArrayRef Ops) + : MDScope(C, ID, Storage, Tag, Ops), Line(Line), Flags(Flags), + SizeInBits(SizeInBits), AlignInBits(AlignInBits), + OffsetInBits(OffsetInBits) {} + ~MDType() {} + +public: + unsigned getLine() const { return Line; } + uint64_t getSizeInBits() const { return SizeInBits; } + uint64_t getAlignInBits() const { return AlignInBits; } + uint64_t getOffsetInBits() const { return OffsetInBits; } + unsigned getFlags() const { return Flags; } + + Metadata *getScope() const { return getOperand(1); } + StringRef getName() const { return getStringOperand(2); } + + MDString *getRawName() const { return getOperandAs(2); } + + static bool classof(const Metadata *MD) { + switch (MD->getMetadataID()) { + default: + return false; + case MDBasicTypeKind: + case MDDerivedTypeKind: + case MDCompositeTypeKind: + case MDSubroutineTypeKind: + return true; + } + } +}; + +/// \brief Basic type. +/// +/// TODO: Split out DW_TAG_unspecified_type. +/// TODO: Drop unused accessors. +class MDBasicType : public MDType { + friend class LLVMContextImpl; + friend class MDNode; + + unsigned Encoding; + + MDBasicType(LLVMContext &C, StorageType Storage, unsigned Tag, + uint64_t SizeInBits, uint64_t AlignInBits, unsigned Encoding, + ArrayRef Ops) + : MDType(C, MDBasicTypeKind, Storage, Tag, 0, SizeInBits, AlignInBits, 0, + 0, Ops), + Encoding(Encoding) {} + ~MDBasicType() {} + + static MDBasicType *getImpl(LLVMContext &Context, unsigned Tag, + StringRef Name, uint64_t SizeInBits, + uint64_t AlignInBits, unsigned Encoding, + StorageType Storage, bool ShouldCreate = true) { + return getImpl(Context, Tag, getCanonicalMDString(Context, Name), + SizeInBits, AlignInBits, Encoding, Storage, ShouldCreate); + } + static MDBasicType *getImpl(LLVMContext &Context, unsigned Tag, + MDString *Name, uint64_t SizeInBits, + uint64_t AlignInBits, unsigned Encoding, + StorageType Storage, bool ShouldCreate = true); + + TempMDBasicType cloneImpl() const { + return getTemporary(getContext(), getTag(), getName(), getSizeInBits(), + getAlignInBits(), getEncoding()); + } + +public: + DEFINE_MDNODE_GET(MDBasicType, + (unsigned Tag, StringRef Name, uint64_t SizeInBits, + uint64_t AlignInBits, unsigned Encoding), + (Tag, Name, SizeInBits, AlignInBits, Encoding)) + DEFINE_MDNODE_GET(MDBasicType, + (unsigned Tag, MDString *Name, uint64_t SizeInBits, + uint64_t AlignInBits, unsigned Encoding), + (Tag, Name, SizeInBits, AlignInBits, Encoding)) + + TempMDBasicType clone() const { return cloneImpl(); } + + unsigned getEncoding() const { return Encoding; } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDBasicTypeKind; + } +}; + +/// \brief Base class for MDDerivedType and MDCompositeType. +/// +/// TODO: Delete; they're not really related. +class MDDerivedTypeBase : public MDType { +protected: + MDDerivedTypeBase(LLVMContext &C, unsigned ID, StorageType Storage, + unsigned Tag, unsigned Line, uint64_t SizeInBits, + uint64_t AlignInBits, uint64_t OffsetInBits, unsigned Flags, + ArrayRef Ops) + : MDType(C, ID, Storage, Tag, Line, SizeInBits, AlignInBits, OffsetInBits, + Flags, Ops) {} + ~MDDerivedTypeBase() {} + +public: + Metadata *getBaseType() const { return getOperand(3); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDDerivedTypeKind || + MD->getMetadataID() == MDCompositeTypeKind || + MD->getMetadataID() == MDSubroutineTypeKind; + } +}; + +/// \brief Derived types. +/// +/// This includes qualified types, pointers, references, friends, typedefs, and +/// class members. +/// +/// TODO: Split out members (inheritance, fields, methods, etc.). +class MDDerivedType : public MDDerivedTypeBase { + friend class LLVMContextImpl; + friend class MDNode; + + MDDerivedType(LLVMContext &C, StorageType Storage, unsigned Tag, + unsigned Line, uint64_t SizeInBits, uint64_t AlignInBits, + uint64_t OffsetInBits, unsigned Flags, ArrayRef Ops) + : MDDerivedTypeBase(C, MDDerivedTypeKind, Storage, Tag, Line, SizeInBits, + AlignInBits, OffsetInBits, Flags, Ops) {} + ~MDDerivedType() {} + + static MDDerivedType *getImpl(LLVMContext &Context, unsigned Tag, + StringRef Name, Metadata *File, unsigned Line, + Metadata *Scope, Metadata *BaseType, + uint64_t SizeInBits, uint64_t AlignInBits, + uint64_t OffsetInBits, unsigned Flags, + Metadata *ExtraData, StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, Tag, getCanonicalMDString(Context, Name), File, + Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits, + Flags, ExtraData, Storage, ShouldCreate); + } + static MDDerivedType *getImpl(LLVMContext &Context, unsigned Tag, + MDString *Name, Metadata *File, unsigned Line, + Metadata *Scope, Metadata *BaseType, + uint64_t SizeInBits, uint64_t AlignInBits, + uint64_t OffsetInBits, unsigned Flags, + Metadata *ExtraData, StorageType Storage, + bool ShouldCreate = true); + + TempMDDerivedType cloneImpl() const { + return getTemporary(getContext(), getTag(), getName(), getFile(), getLine(), + getScope(), getBaseType(), getSizeInBits(), + getAlignInBits(), getOffsetInBits(), getFlags(), + getExtraData()); + } + +public: + DEFINE_MDNODE_GET(MDDerivedType, + (unsigned Tag, MDString *Name, Metadata *File, + unsigned Line, Metadata *Scope, Metadata *BaseType, + uint64_t SizeInBits, uint64_t AlignInBits, + uint64_t OffsetInBits, unsigned Flags, + Metadata *ExtraData = nullptr), + (Tag, Name, File, Line, Scope, BaseType, SizeInBits, + AlignInBits, OffsetInBits, Flags, ExtraData)) + DEFINE_MDNODE_GET(MDDerivedType, + (unsigned Tag, StringRef Name, Metadata *File, + unsigned Line, Metadata *Scope, Metadata *BaseType, + uint64_t SizeInBits, uint64_t AlignInBits, + uint64_t OffsetInBits, unsigned Flags, + Metadata *ExtraData = nullptr), + (Tag, Name, File, Line, Scope, BaseType, SizeInBits, + AlignInBits, OffsetInBits, Flags, ExtraData)) + + TempMDDerivedType clone() const { return cloneImpl(); } + + /// \brief Get extra data associated with this derived type. + /// + /// Class type for pointer-to-members, objective-c property node for ivars, + /// or global constant wrapper for static members. + /// + /// TODO: Separate out types that need this extra operand: pointer-to-member + /// types and member fields (static members and ivars). + Metadata *getExtraData() const { return getOperand(4); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDDerivedTypeKind; + } +}; + +/// \brief Base class for MDCompositeType and MDSubroutineType. +/// +/// TODO: Delete; they're not really related. +class MDCompositeTypeBase : public MDDerivedTypeBase { + unsigned RuntimeLang; + +protected: + MDCompositeTypeBase(LLVMContext &C, unsigned ID, StorageType Storage, + unsigned Tag, unsigned Line, unsigned RuntimeLang, + uint64_t SizeInBits, uint64_t AlignInBits, + uint64_t OffsetInBits, unsigned Flags, + ArrayRef Ops) + : MDDerivedTypeBase(C, ID, Storage, Tag, Line, SizeInBits, AlignInBits, + OffsetInBits, Flags, Ops), + RuntimeLang(RuntimeLang) {} + ~MDCompositeTypeBase() {} + +public: + Metadata *getElements() const { return getOperand(4); } + Metadata *getVTableHolder() const { return getOperand(5); } + Metadata *getTemplateParams() const { return getOperand(6); } + StringRef getIdentifier() const { return getStringOperand(7); } + unsigned getRuntimeLang() const { return RuntimeLang; } + + MDString *getRawIdentifier() const { return getOperandAs(7); } + + /// \brief Replace operands. + /// + /// If this \a isUniqued() and not \a isResolved(), on a uniquing collision + /// this will be RAUW'ed and deleted. Use a \a TrackingMDRef to keep track + /// of its movement if necessary. + /// @{ + void replaceElements(MDTuple *Elements) { +#ifndef NDEBUG + if (auto *Old = cast_or_null(getElements())) + for (const auto &Op : Old->operands()) + assert(std::find(Elements->op_begin(), Elements->op_end(), Op) && + "Lost a member during member list replacement"); +#endif + replaceOperandWith(4, Elements); + } + void replaceVTableHolder(Metadata *VTableHolder) { + replaceOperandWith(5, VTableHolder); + } + void replaceTemplateParams(MDTuple *TemplateParams) { + replaceOperandWith(6, TemplateParams); + } + /// @} + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDCompositeTypeKind || + MD->getMetadataID() == MDSubroutineTypeKind; + } +}; + +/// \brief Composite types. +/// +/// TODO: Detach from DerivedTypeBase (split out MDEnumType?). +/// TODO: Create a custom, unrelated node for DW_TAG_array_type. +class MDCompositeType : public MDCompositeTypeBase { + friend class LLVMContextImpl; + friend class MDNode; + + MDCompositeType(LLVMContext &C, StorageType Storage, unsigned Tag, + unsigned Line, unsigned RuntimeLang, uint64_t SizeInBits, + uint64_t AlignInBits, uint64_t OffsetInBits, unsigned Flags, + ArrayRef Ops) + : MDCompositeTypeBase(C, MDCompositeTypeKind, Storage, Tag, Line, + RuntimeLang, SizeInBits, AlignInBits, OffsetInBits, + Flags, Ops) {} + ~MDCompositeType() {} + + static MDCompositeType * + getImpl(LLVMContext &Context, unsigned Tag, StringRef Name, Metadata *File, + unsigned Line, Metadata *Scope, Metadata *BaseType, + uint64_t SizeInBits, uint64_t AlignInBits, uint64_t OffsetInBits, + uint64_t Flags, Metadata *Elements, unsigned RuntimeLang, + Metadata *VTableHolder, Metadata *TemplateParams, + StringRef Identifier, StorageType Storage, bool ShouldCreate = true) { + return getImpl(Context, Tag, getCanonicalMDString(Context, Name), File, + Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits, + Flags, Elements, RuntimeLang, VTableHolder, TemplateParams, + getCanonicalMDString(Context, Identifier), Storage, + ShouldCreate); + } + static MDCompositeType * + getImpl(LLVMContext &Context, unsigned Tag, MDString *Name, Metadata *File, + unsigned Line, Metadata *Scope, Metadata *BaseType, + uint64_t SizeInBits, uint64_t AlignInBits, uint64_t OffsetInBits, + unsigned Flags, Metadata *Elements, unsigned RuntimeLang, + Metadata *VTableHolder, Metadata *TemplateParams, + MDString *Identifier, StorageType Storage, bool ShouldCreate = true); + + TempMDCompositeType cloneImpl() const { + return getTemporary(getContext(), getTag(), getName(), getFile(), getLine(), + getScope(), getBaseType(), getSizeInBits(), + getAlignInBits(), getOffsetInBits(), getFlags(), + getElements(), getRuntimeLang(), getVTableHolder(), + getTemplateParams(), getIdentifier()); + } + +public: + DEFINE_MDNODE_GET(MDCompositeType, + (unsigned Tag, StringRef Name, Metadata *File, + unsigned Line, Metadata *Scope, Metadata *BaseType, + uint64_t SizeInBits, uint64_t AlignInBits, + uint64_t OffsetInBits, unsigned Flags, Metadata *Elements, + unsigned RuntimeLang, Metadata *VTableHolder, + Metadata *TemplateParams = nullptr, + StringRef Identifier = ""), + (Tag, Name, File, Line, Scope, BaseType, SizeInBits, + AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang, + VTableHolder, TemplateParams, Identifier)) + DEFINE_MDNODE_GET(MDCompositeType, + (unsigned Tag, MDString *Name, Metadata *File, + unsigned Line, Metadata *Scope, Metadata *BaseType, + uint64_t SizeInBits, uint64_t AlignInBits, + uint64_t OffsetInBits, unsigned Flags, Metadata *Elements, + unsigned RuntimeLang, Metadata *VTableHolder, + Metadata *TemplateParams = nullptr, + MDString *Identifier = nullptr), + (Tag, Name, File, Line, Scope, BaseType, SizeInBits, + AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang, + VTableHolder, TemplateParams, Identifier)) + + TempMDCompositeType clone() const { return cloneImpl(); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDCompositeTypeKind; + } +}; + +/// \brief Type array for a subprogram. +/// +/// TODO: Detach from CompositeType, and fold the array of types in directly +/// as operands. +class MDSubroutineType : public MDCompositeTypeBase { + friend class LLVMContextImpl; + friend class MDNode; + + MDSubroutineType(LLVMContext &C, StorageType Storage, unsigned Flags, + ArrayRef Ops) + : MDCompositeTypeBase(C, MDSubroutineTypeKind, Storage, + dwarf::DW_TAG_subroutine_type, 0, 0, 0, 0, 0, Flags, + Ops) {} + ~MDSubroutineType() {} + + static MDSubroutineType *getImpl(LLVMContext &Context, unsigned Flags, + Metadata *TypeArray, StorageType Storage, + bool ShouldCreate = true); + + TempMDSubroutineType cloneImpl() const { + return getTemporary(getContext(), getFlags(), getTypeArray()); + } + +public: + DEFINE_MDNODE_GET(MDSubroutineType, (unsigned Flags, Metadata *TypeArray), + (Flags, TypeArray)) + + TempMDSubroutineType clone() const { return cloneImpl(); } + + Metadata *getTypeArray() const { return getElements(); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDSubroutineTypeKind; + } +}; + +/// \brief File. +/// +/// TODO: Merge with directory/file node (including users). +/// TODO: Canonicalize paths on creation. +class MDFile : public MDScope { + friend class LLVMContextImpl; + friend class MDNode; + + MDFile(LLVMContext &C, StorageType Storage, ArrayRef Ops) + : MDScope(C, MDFileKind, Storage, dwarf::DW_TAG_file_type, Ops) {} + ~MDFile() {} + + static MDFile *getImpl(LLVMContext &Context, StringRef Filename, + StringRef Directory, StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, getCanonicalMDString(Context, Filename), + getCanonicalMDString(Context, Directory), Storage, + ShouldCreate); + } + static MDFile *getImpl(LLVMContext &Context, MDString *Filename, + MDString *Directory, StorageType Storage, + bool ShouldCreate = true); + + TempMDFile cloneImpl() const { + return getTemporary(getContext(), getFilename(), getDirectory()); + } + +public: + DEFINE_MDNODE_GET(MDFile, (StringRef Filename, StringRef Directory), + (Filename, Directory)) + DEFINE_MDNODE_GET(MDFile, (MDString * Filename, MDString *Directory), + (Filename, Directory)) + + TempMDFile clone() const { return cloneImpl(); } + + StringRef getFilename() const { return getStringOperand(0); } + StringRef getDirectory() const { return getStringOperand(1); } + + MDString *getRawFilename() const { return getOperandAs(0); } + MDString *getRawDirectory() const { return getOperandAs(1); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDFileKind; + } +}; + +/// \brief Compile unit. +class MDCompileUnit : public MDScope { + friend class LLVMContextImpl; + friend class MDNode; + + unsigned SourceLanguage; + bool IsOptimized; + unsigned RuntimeVersion; + unsigned EmissionKind; + + MDCompileUnit(LLVMContext &C, StorageType Storage, unsigned SourceLanguage, + bool IsOptimized, unsigned RuntimeVersion, + unsigned EmissionKind, ArrayRef Ops) + : MDScope(C, MDCompileUnitKind, Storage, dwarf::DW_TAG_compile_unit, Ops), + SourceLanguage(SourceLanguage), IsOptimized(IsOptimized), + RuntimeVersion(RuntimeVersion), EmissionKind(EmissionKind) {} + ~MDCompileUnit() {} + + static MDCompileUnit * + getImpl(LLVMContext &Context, unsigned SourceLanguage, Metadata *File, + StringRef Producer, bool IsOptimized, StringRef Flags, + unsigned RuntimeVersion, StringRef SplitDebugFilename, + unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes, + Metadata *Subprograms, Metadata *GlobalVariables, + Metadata *ImportedEntities, StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, SourceLanguage, File, + getCanonicalMDString(Context, Producer), IsOptimized, + getCanonicalMDString(Context, Flags), RuntimeVersion, + getCanonicalMDString(Context, SplitDebugFilename), + EmissionKind, EnumTypes, RetainedTypes, Subprograms, + GlobalVariables, ImportedEntities, Storage, ShouldCreate); + } + static MDCompileUnit * + getImpl(LLVMContext &Context, unsigned SourceLanguage, Metadata *File, + MDString *Producer, bool IsOptimized, MDString *Flags, + unsigned RuntimeVersion, MDString *SplitDebugFilename, + unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes, + Metadata *Subprograms, Metadata *GlobalVariables, + Metadata *ImportedEntities, StorageType Storage, + bool ShouldCreate = true); + + TempMDCompileUnit cloneImpl() const { + return getTemporary( + getContext(), getSourceLanguage(), getFile(), getProducer(), + isOptimized(), getFlags(), getRuntimeVersion(), getSplitDebugFilename(), + getEmissionKind(), getEnumTypes(), getRetainedTypes(), getSubprograms(), + getGlobalVariables(), getImportedEntities()); + } + +public: + DEFINE_MDNODE_GET(MDCompileUnit, + (unsigned SourceLanguage, Metadata *File, + StringRef Producer, bool IsOptimized, StringRef Flags, + unsigned RuntimeVersion, StringRef SplitDebugFilename, + unsigned EmissionKind, Metadata *EnumTypes, + Metadata *RetainedTypes, Metadata *Subprograms, + Metadata *GlobalVariables, Metadata *ImportedEntities), + (SourceLanguage, File, Producer, IsOptimized, Flags, + RuntimeVersion, SplitDebugFilename, EmissionKind, + EnumTypes, RetainedTypes, Subprograms, GlobalVariables, + ImportedEntities)) + DEFINE_MDNODE_GET(MDCompileUnit, + (unsigned SourceLanguage, Metadata *File, + MDString *Producer, bool IsOptimized, MDString *Flags, + unsigned RuntimeVersion, MDString *SplitDebugFilename, + unsigned EmissionKind, Metadata *EnumTypes, + Metadata *RetainedTypes, Metadata *Subprograms, + Metadata *GlobalVariables, Metadata *ImportedEntities), + (SourceLanguage, File, Producer, IsOptimized, Flags, + RuntimeVersion, SplitDebugFilename, EmissionKind, + EnumTypes, RetainedTypes, Subprograms, GlobalVariables, + ImportedEntities)) + + TempMDCompileUnit clone() const { return cloneImpl(); } + + unsigned getSourceLanguage() const { return SourceLanguage; } + bool isOptimized() const { return IsOptimized; } + unsigned getRuntimeVersion() const { return RuntimeVersion; } + unsigned getEmissionKind() const { return EmissionKind; } + StringRef getProducer() const { return getStringOperand(1); } + StringRef getFlags() const { return getStringOperand(2); } + StringRef getSplitDebugFilename() const { return getStringOperand(3); } + Metadata *getEnumTypes() const { return getOperand(4); } + Metadata *getRetainedTypes() const { return getOperand(5); } + Metadata *getSubprograms() const { return getOperand(6); } + Metadata *getGlobalVariables() const { return getOperand(7); } + Metadata *getImportedEntities() const { return getOperand(8); } + + MDString *getRawProducer() const { return getOperandAs(1); } + MDString *getRawFlags() const { return getOperandAs(2); } + MDString *getRawSplitDebugFilename() const { + return getOperandAs(3); + } + + /// \brief Replace arrays. + /// + /// If this \a isUniqued() and not \a isResolved(), it will be RAUW'ed and + /// deleted on a uniquing collision. In practice, uniquing collisions on \a + /// MDCompileUnit should be fairly rare. + /// @{ + void replaceSubprograms(MDTuple *N) { replaceOperandWith(6, N); } + void replaceGlobalVariables(MDTuple *N) { replaceOperandWith(7, N); } + /// @} + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDCompileUnitKind; + } +}; + +/// \brief Subprogram description. +/// +/// TODO: Remove DisplayName. It's always equal to Name. +/// TODO: Split up flags. +class MDSubprogram : public MDScope { + friend class LLVMContextImpl; + friend class MDNode; + + unsigned Line; + unsigned ScopeLine; + unsigned Virtuality; + unsigned VirtualIndex; + unsigned Flags; + bool IsLocalToUnit; + bool IsDefinition; + bool IsOptimized; + + MDSubprogram(LLVMContext &C, StorageType Storage, unsigned Line, + unsigned ScopeLine, unsigned Virtuality, unsigned VirtualIndex, + unsigned Flags, bool IsLocalToUnit, bool IsDefinition, + bool IsOptimized, ArrayRef Ops) + : MDScope(C, MDSubprogramKind, Storage, dwarf::DW_TAG_subprogram, Ops), + Line(Line), ScopeLine(ScopeLine), Virtuality(Virtuality), + VirtualIndex(VirtualIndex), Flags(Flags), IsLocalToUnit(IsLocalToUnit), + IsDefinition(IsDefinition), IsOptimized(IsOptimized) {} + ~MDSubprogram() {} + + static MDSubprogram * + getImpl(LLVMContext &Context, Metadata *Scope, StringRef Name, + StringRef LinkageName, Metadata *File, unsigned Line, Metadata *Type, + bool IsLocalToUnit, bool IsDefinition, unsigned ScopeLine, + Metadata *ContainingType, unsigned Virtuality, unsigned VirtualIndex, + unsigned Flags, bool IsOptimized, Metadata *Function, + Metadata *TemplateParams, Metadata *Declaration, Metadata *Variables, + StorageType Storage, bool ShouldCreate = true) { + return getImpl(Context, Scope, getCanonicalMDString(Context, Name), + getCanonicalMDString(Context, LinkageName), File, Line, Type, + IsLocalToUnit, IsDefinition, ScopeLine, ContainingType, + Virtuality, VirtualIndex, Flags, IsOptimized, Function, + TemplateParams, Declaration, Variables, Storage, + ShouldCreate); + } + static MDSubprogram * + getImpl(LLVMContext &Context, Metadata *Scope, MDString *Name, + MDString *LinkageName, Metadata *File, unsigned Line, Metadata *Type, + bool IsLocalToUnit, bool IsDefinition, unsigned ScopeLine, + Metadata *ContainingType, unsigned Virtuality, unsigned VirtualIndex, + unsigned Flags, bool IsOptimized, Metadata *Function, + Metadata *TemplateParams, Metadata *Declaration, Metadata *Variables, + StorageType Storage, bool ShouldCreate = true); + + TempMDSubprogram cloneImpl() const { + return getTemporary(getContext(), getScope(), getName(), getLinkageName(), + getFile(), getLine(), getType(), isLocalToUnit(), + isDefinition(), getScopeLine(), getContainingType(), + getVirtuality(), getVirtualIndex(), getFlags(), + isOptimized(), getFunction(), getTemplateParams(), + getDeclaration(), getVariables()); + } + +public: + DEFINE_MDNODE_GET( + MDSubprogram, + (Metadata * Scope, StringRef Name, StringRef LinkageName, Metadata *File, + unsigned Line, Metadata *Type, bool IsLocalToUnit, bool IsDefinition, + unsigned ScopeLine, Metadata *ContainingType, unsigned Virtuality, + unsigned VirtualIndex, unsigned Flags, bool IsOptimized, + Metadata *Function = nullptr, Metadata *TemplateParams = nullptr, + Metadata *Declaration = nullptr, Metadata *Variables = nullptr), + (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition, + ScopeLine, ContainingType, Virtuality, VirtualIndex, Flags, IsOptimized, + Function, TemplateParams, Declaration, Variables)) + DEFINE_MDNODE_GET( + MDSubprogram, + (Metadata * Scope, MDString *Name, MDString *LinkageName, Metadata *File, + unsigned Line, Metadata *Type, bool IsLocalToUnit, bool IsDefinition, + unsigned ScopeLine, Metadata *ContainingType, unsigned Virtuality, + unsigned VirtualIndex, unsigned Flags, bool IsOptimized, + Metadata *Function = nullptr, Metadata *TemplateParams = nullptr, + Metadata *Declaration = nullptr, Metadata *Variables = nullptr), + (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition, + ScopeLine, ContainingType, Virtuality, VirtualIndex, Flags, IsOptimized, + Function, TemplateParams, Declaration, Variables)) + + TempMDSubprogram clone() const { return cloneImpl(); } + +public: + unsigned getLine() const { return Line; } + unsigned getVirtuality() const { return Virtuality; } + unsigned getVirtualIndex() const { return VirtualIndex; } + unsigned getScopeLine() const { return ScopeLine; } + unsigned getFlags() const { return Flags; } + bool isLocalToUnit() const { return IsLocalToUnit; } + bool isDefinition() const { return IsDefinition; } + bool isOptimized() const { return IsOptimized; } + + Metadata *getScope() const { return getOperand(1); } + + StringRef getName() const { return getStringOperand(2); } + StringRef getDisplayName() const { return getStringOperand(3); } + StringRef getLinkageName() const { return getStringOperand(4); } + + MDString *getRawName() const { return getOperandAs(2); } + MDString *getRawLinkageName() const { return getOperandAs(4); } + + Metadata *getType() const { return getOperand(5); } + Metadata *getContainingType() const { return getOperand(6); } + + Metadata *getFunction() const { return getOperand(7); } + Metadata *getTemplateParams() const { return getOperand(8); } + Metadata *getDeclaration() const { return getOperand(9); } + Metadata *getVariables() const { return getOperand(10); } + + /// \brief Replace the function. + /// + /// If \a isUniqued() and not \a isResolved(), this could node will be + /// RAUW'ed and deleted out from under the caller. Use a \a TrackingMDRef if + /// that's a problem. + /// @{ + void replaceFunction(Function *F); + void replaceFunction(ConstantAsMetadata *MD) { replaceOperandWith(7, MD); } + void replaceFunction(std::nullptr_t) { replaceOperandWith(7, nullptr); } + /// @} + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDSubprogramKind; + } +}; + +class MDLexicalBlockBase : public MDScope { +protected: + MDLexicalBlockBase(LLVMContext &C, unsigned ID, StorageType Storage, + ArrayRef Ops) + : MDScope(C, ID, Storage, dwarf::DW_TAG_lexical_block, Ops) {} + ~MDLexicalBlockBase() {} + +public: + Metadata *getScope() const { return getOperand(1); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDLexicalBlockKind || + MD->getMetadataID() == MDLexicalBlockFileKind; + } +}; + +class MDLexicalBlock : public MDLexicalBlockBase { + friend class LLVMContextImpl; + friend class MDNode; + + unsigned Line; + unsigned Column; + + MDLexicalBlock(LLVMContext &C, StorageType Storage, unsigned Line, + unsigned Column, ArrayRef Ops) + : MDLexicalBlockBase(C, MDLexicalBlockKind, Storage, Ops), Line(Line), + Column(Column) {} + ~MDLexicalBlock() {} + + static MDLexicalBlock *getImpl(LLVMContext &Context, Metadata *Scope, + Metadata *File, unsigned Line, unsigned Column, + StorageType Storage, bool ShouldCreate = true); + + TempMDLexicalBlock cloneImpl() const { + return getTemporary(getContext(), getScope(), getFile(), getLine(), + getColumn()); + } + +public: + DEFINE_MDNODE_GET(MDLexicalBlock, (Metadata * Scope, Metadata *File, + unsigned Line, unsigned Column), + (Scope, File, Line, Column)) + + TempMDLexicalBlock clone() const { return cloneImpl(); } + + unsigned getLine() const { return Line; } + unsigned getColumn() const { return Column; } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDLexicalBlockKind; + } +}; + +class MDLexicalBlockFile : public MDLexicalBlockBase { + friend class LLVMContextImpl; + friend class MDNode; + + unsigned Discriminator; + + MDLexicalBlockFile(LLVMContext &C, StorageType Storage, + unsigned Discriminator, ArrayRef Ops) + : MDLexicalBlockBase(C, MDLexicalBlockFileKind, Storage, Ops), + Discriminator(Discriminator) {} + ~MDLexicalBlockFile() {} + + static MDLexicalBlockFile *getImpl(LLVMContext &Context, Metadata *Scope, + Metadata *File, unsigned Discriminator, + StorageType Storage, + bool ShouldCreate = true); + + TempMDLexicalBlockFile cloneImpl() const { + return getTemporary(getContext(), getScope(), getFile(), + getDiscriminator()); + } + +public: + DEFINE_MDNODE_GET(MDLexicalBlockFile, + (Metadata * Scope, Metadata *File, unsigned Discriminator), + (Scope, File, Discriminator)) + + TempMDLexicalBlockFile clone() const { return cloneImpl(); } + + unsigned getDiscriminator() const { return Discriminator; } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDLexicalBlockFileKind; + } +}; + +class MDNamespace : public MDScope { + friend class LLVMContextImpl; + friend class MDNode; + + unsigned Line; + + MDNamespace(LLVMContext &Context, StorageType Storage, unsigned Line, + ArrayRef Ops) + : MDScope(Context, MDNamespaceKind, Storage, dwarf::DW_TAG_namespace, + Ops), + Line(Line) {} + ~MDNamespace() {} + + static MDNamespace *getImpl(LLVMContext &Context, Metadata *Scope, + Metadata *File, StringRef Name, unsigned Line, + StorageType Storage, bool ShouldCreate = true) { + return getImpl(Context, Scope, File, getCanonicalMDString(Context, Name), + Line, Storage, ShouldCreate); + } + static MDNamespace *getImpl(LLVMContext &Context, Metadata *Scope, + Metadata *File, MDString *Name, unsigned Line, + StorageType Storage, bool ShouldCreate = true); + + TempMDNamespace cloneImpl() const { + return getTemporary(getContext(), getScope(), getFile(), getName(), + getLine()); + } + +public: + DEFINE_MDNODE_GET(MDNamespace, (Metadata * Scope, Metadata *File, + StringRef Name, unsigned Line), + (Scope, File, Name, Line)) + DEFINE_MDNODE_GET(MDNamespace, (Metadata * Scope, Metadata *File, + MDString *Name, unsigned Line), + (Scope, File, Name, Line)) + + TempMDNamespace clone() const { return cloneImpl(); } + + unsigned getLine() const { return Line; } + Metadata *getScope() const { return getOperand(1); } + StringRef getName() const { return getStringOperand(2); } + + MDString *getRawName() const { return getOperandAs(2); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDNamespaceKind; + } +}; + +/// \brief Base class for template parameters. +class MDTemplateParameter : public DebugNode { +protected: + MDTemplateParameter(LLVMContext &Context, unsigned ID, StorageType Storage, + unsigned Tag, ArrayRef Ops) + : DebugNode(Context, ID, Storage, Tag, Ops) {} + ~MDTemplateParameter() {} + +public: + StringRef getName() const { return getStringOperand(0); } + Metadata *getType() const { return getOperand(1); } + + MDString *getRawName() const { return getOperandAs(0); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDTemplateTypeParameterKind || + MD->getMetadataID() == MDTemplateValueParameterKind; + } +}; + +class MDTemplateTypeParameter : public MDTemplateParameter { + friend class LLVMContextImpl; + friend class MDNode; + + MDTemplateTypeParameter(LLVMContext &Context, StorageType Storage, + ArrayRef Ops) + : MDTemplateParameter(Context, MDTemplateTypeParameterKind, Storage, + dwarf::DW_TAG_template_type_parameter, Ops) {} + ~MDTemplateTypeParameter() {} + + static MDTemplateTypeParameter *getImpl(LLVMContext &Context, StringRef Name, + Metadata *Type, StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, getCanonicalMDString(Context, Name), Type, Storage, + ShouldCreate); + } + static MDTemplateTypeParameter *getImpl(LLVMContext &Context, MDString *Name, + Metadata *Type, StorageType Storage, + bool ShouldCreate = true); + + TempMDTemplateTypeParameter cloneImpl() const { + return getTemporary(getContext(), getName(), getType()); + } + +public: + DEFINE_MDNODE_GET(MDTemplateTypeParameter, (StringRef Name, Metadata *Type), + (Name, Type)) + DEFINE_MDNODE_GET(MDTemplateTypeParameter, (MDString * Name, Metadata *Type), + (Name, Type)) + + TempMDTemplateTypeParameter clone() const { return cloneImpl(); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDTemplateTypeParameterKind; + } +}; + +class MDTemplateValueParameter : public MDTemplateParameter { + friend class LLVMContextImpl; + friend class MDNode; + + MDTemplateValueParameter(LLVMContext &Context, StorageType Storage, + unsigned Tag, ArrayRef Ops) + : MDTemplateParameter(Context, MDTemplateValueParameterKind, Storage, Tag, + Ops) {} + ~MDTemplateValueParameter() {} + + static MDTemplateValueParameter *getImpl(LLVMContext &Context, unsigned Tag, + StringRef Name, Metadata *Type, + Metadata *Value, StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, Tag, getCanonicalMDString(Context, Name), Type, + Value, Storage, ShouldCreate); + } + static MDTemplateValueParameter *getImpl(LLVMContext &Context, unsigned Tag, + MDString *Name, Metadata *Type, + Metadata *Value, StorageType Storage, + bool ShouldCreate = true); + + TempMDTemplateValueParameter cloneImpl() const { + return getTemporary(getContext(), getTag(), getName(), getType(), + getValue()); + } + +public: + DEFINE_MDNODE_GET(MDTemplateValueParameter, (unsigned Tag, StringRef Name, + Metadata *Type, Metadata *Value), + (Tag, Name, Type, Value)) + DEFINE_MDNODE_GET(MDTemplateValueParameter, (unsigned Tag, MDString *Name, + Metadata *Type, Metadata *Value), + (Tag, Name, Type, Value)) + + TempMDTemplateValueParameter clone() const { return cloneImpl(); } + + Metadata *getValue() const { return getOperand(2); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDTemplateValueParameterKind; + } +}; + +/// \brief Base class for variables. +/// +/// TODO: Hardcode to DW_TAG_variable. +class MDVariable : public DebugNode { + unsigned Line; + +protected: + MDVariable(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag, + unsigned Line, ArrayRef Ops) + : DebugNode(C, ID, Storage, Tag, Ops), Line(Line) {} + ~MDVariable() {} + +public: + unsigned getLine() const { return Line; } + Metadata *getScope() const { return getOperand(0); } + StringRef getName() const { return getStringOperand(1); } + Metadata *getFile() const { return getOperand(2); } + Metadata *getType() const { return getOperand(3); } + + MDString *getRawName() const { return getOperandAs(1); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDLocalVariableKind || + MD->getMetadataID() == MDGlobalVariableKind; + } +}; + +/// \brief Global variables. +/// +/// TODO: Remove DisplayName. It's always equal to Name. +class MDGlobalVariable : public MDVariable { + friend class LLVMContextImpl; + friend class MDNode; + + bool IsLocalToUnit; + bool IsDefinition; + + MDGlobalVariable(LLVMContext &C, StorageType Storage, unsigned Line, + bool IsLocalToUnit, bool IsDefinition, + ArrayRef Ops) + : MDVariable(C, MDGlobalVariableKind, Storage, dwarf::DW_TAG_variable, + Line, Ops), + IsLocalToUnit(IsLocalToUnit), IsDefinition(IsDefinition) {} + ~MDGlobalVariable() {} + + static MDGlobalVariable * + getImpl(LLVMContext &Context, Metadata *Scope, StringRef Name, + StringRef LinkageName, Metadata *File, unsigned Line, Metadata *Type, + bool IsLocalToUnit, bool IsDefinition, Metadata *Variable, + Metadata *StaticDataMemberDeclaration, StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, Scope, getCanonicalMDString(Context, Name), + getCanonicalMDString(Context, LinkageName), File, Line, Type, + IsLocalToUnit, IsDefinition, Variable, + StaticDataMemberDeclaration, Storage, ShouldCreate); + } + static MDGlobalVariable * + getImpl(LLVMContext &Context, Metadata *Scope, MDString *Name, + MDString *LinkageName, Metadata *File, unsigned Line, Metadata *Type, + bool IsLocalToUnit, bool IsDefinition, Metadata *Variable, + Metadata *StaticDataMemberDeclaration, StorageType Storage, + bool ShouldCreate = true); + + TempMDGlobalVariable cloneImpl() const { + return getTemporary(getContext(), getScope(), getName(), getLinkageName(), + getFile(), getLine(), getType(), isLocalToUnit(), + isDefinition(), getVariable(), + getStaticDataMemberDeclaration()); + } + +public: + DEFINE_MDNODE_GET(MDGlobalVariable, + (Metadata * Scope, StringRef Name, StringRef LinkageName, + Metadata *File, unsigned Line, Metadata *Type, + bool IsLocalToUnit, bool IsDefinition, Metadata *Variable, + Metadata *StaticDataMemberDeclaration), + (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, + IsDefinition, Variable, StaticDataMemberDeclaration)) + DEFINE_MDNODE_GET(MDGlobalVariable, + (Metadata * Scope, MDString *Name, MDString *LinkageName, + Metadata *File, unsigned Line, Metadata *Type, + bool IsLocalToUnit, bool IsDefinition, Metadata *Variable, + Metadata *StaticDataMemberDeclaration), + (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, + IsDefinition, Variable, StaticDataMemberDeclaration)) + + TempMDGlobalVariable clone() const { return cloneImpl(); } + + bool isLocalToUnit() const { return IsLocalToUnit; } + bool isDefinition() const { return IsDefinition; } + StringRef getDisplayName() const { return getStringOperand(4); } + StringRef getLinkageName() const { return getStringOperand(5); } + Metadata *getVariable() const { return getOperand(6); } + Metadata *getStaticDataMemberDeclaration() const { return getOperand(7); } + + MDString *getRawLinkageName() const { return getOperandAs(5); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDGlobalVariableKind; + } +}; + +/// \brief Local variable. +/// +/// TODO: Split between arguments and otherwise. +/// TODO: Use \c DW_TAG_variable instead of fake tags. +/// TODO: Split up flags. +class MDLocalVariable : public MDVariable { + friend class LLVMContextImpl; + friend class MDNode; + + unsigned Arg; + unsigned Flags; + + MDLocalVariable(LLVMContext &C, StorageType Storage, unsigned Tag, + unsigned Line, unsigned Arg, unsigned Flags, + ArrayRef Ops) + : MDVariable(C, MDLocalVariableKind, Storage, Tag, Line, Ops), Arg(Arg), + Flags(Flags) {} + ~MDLocalVariable() {} + + static MDLocalVariable *getImpl(LLVMContext &Context, unsigned Tag, + Metadata *Scope, StringRef Name, + Metadata *File, unsigned Line, Metadata *Type, + unsigned Arg, unsigned Flags, + Metadata *InlinedAt, StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, Tag, Scope, getCanonicalMDString(Context, Name), + File, Line, Type, Arg, Flags, InlinedAt, Storage, + ShouldCreate); + } + static MDLocalVariable *getImpl(LLVMContext &Context, unsigned Tag, + Metadata *Scope, MDString *Name, + Metadata *File, unsigned Line, Metadata *Type, + unsigned Arg, unsigned Flags, + Metadata *InlinedAt, StorageType Storage, + bool ShouldCreate = true); + + TempMDLocalVariable cloneImpl() const { + return getTemporary(getContext(), getTag(), getScope(), getName(), + getFile(), getLine(), getType(), getArg(), getFlags(), + getInlinedAt()); + } + +public: + DEFINE_MDNODE_GET(MDLocalVariable, + (unsigned Tag, Metadata *Scope, StringRef Name, + Metadata *File, unsigned Line, Metadata *Type, + unsigned Arg, unsigned Flags, + Metadata *InlinedAt = nullptr), + (Tag, Scope, Name, File, Line, Type, Arg, Flags, InlinedAt)) + DEFINE_MDNODE_GET(MDLocalVariable, + (unsigned Tag, Metadata *Scope, MDString *Name, + Metadata *File, unsigned Line, Metadata *Type, + unsigned Arg, unsigned Flags, + Metadata *InlinedAt = nullptr), + (Tag, Scope, Name, File, Line, Type, Arg, Flags, InlinedAt)) + + TempMDLocalVariable clone() const { return cloneImpl(); } + + unsigned getArg() const { return Arg; } + unsigned getFlags() const { return Flags; } + Metadata *getInlinedAt() const { return getOperand(4); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDLocalVariableKind; + } +}; + +/// \brief DWARF expression. +/// +/// TODO: Co-allocate the expression elements. +/// TODO: Drop fake DW_TAG_expression and separate from DebugNode. +/// TODO: Separate from MDNode, or otherwise drop Distinct and Temporary +/// storage types. +class MDExpression : public DebugNode { + friend class LLVMContextImpl; + friend class MDNode; + + std::vector Elements; + + MDExpression(LLVMContext &C, StorageType Storage, ArrayRef Elements) + : DebugNode(C, MDExpressionKind, Storage, dwarf::DW_TAG_expression, None), + Elements(Elements.begin(), Elements.end()) {} + ~MDExpression() {} + + static MDExpression *getImpl(LLVMContext &Context, + ArrayRef Elements, StorageType Storage, + bool ShouldCreate = true); + + TempMDExpression cloneImpl() const { + return getTemporary(getContext(), getElements()); + } + +public: + DEFINE_MDNODE_GET(MDExpression, (ArrayRef Elements), (Elements)) + + TempMDExpression clone() const { return cloneImpl(); } + + ArrayRef getElements() const { return Elements; } + + unsigned getNumElements() const { return Elements.size(); } + uint64_t getElement(unsigned I) const { + assert(I < Elements.size() && "Index out of range"); + return Elements[I]; + } + + typedef ArrayRef::iterator element_iterator; + element_iterator elements_begin() const { return getElements().begin(); } + element_iterator elements_end() const { return getElements().end(); } + + /// \brief A lightweight wrapper around an expression operand. + /// + /// TODO: Store arguments directly and change \a MDExpression to store a + /// range of these. + class ExprOperand { + const uint64_t *Op; + + public: + explicit ExprOperand(const uint64_t *Op) : Op(Op) {} + + const uint64_t *get() const { return Op; } + + /// \brief Get the operand code. + uint64_t getOp() const { return *Op; } + + /// \brief Get an argument to the operand. + /// + /// Never returns the operand itself. + uint64_t getArg(unsigned I) const { return Op[I + 1]; } + + unsigned getNumArgs() const { return getSize() - 1; } + + /// \brief Return the size of the operand. + /// + /// Return the number of elements in the operand (1 + args). + unsigned getSize() const; + }; + + /// \brief An iterator for expression operands. + class expr_op_iterator + : public std::iterator { + ExprOperand Op; + + public: + explicit expr_op_iterator(element_iterator I) : Op(I) {} + + element_iterator getBase() const { return Op.get(); } + const ExprOperand &operator*() const { return Op; } + const ExprOperand *operator->() const { return &Op; } + + expr_op_iterator &operator++() { + increment(); + return *this; + } + expr_op_iterator operator++(int) { + expr_op_iterator T(*this); + increment(); + return T; + } + + bool operator==(const expr_op_iterator &X) const { + return getBase() == X.getBase(); + } + bool operator!=(const expr_op_iterator &X) const { + return getBase() != X.getBase(); + } + + private: + void increment() { Op = ExprOperand(getBase() + Op.getSize()); } + }; + + /// \brief Visit the elements via ExprOperand wrappers. + /// + /// These range iterators visit elements through \a ExprOperand wrappers. + /// This is not guaranteed to be a valid range unless \a isValid() gives \c + /// true. + /// + /// \pre \a isValid() gives \c true. + /// @{ + expr_op_iterator expr_op_begin() const { + return expr_op_iterator(elements_begin()); + } + expr_op_iterator expr_op_end() const { + return expr_op_iterator(elements_end()); + } + /// @} + + bool isValid() const; + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDExpressionKind; + } +}; + +class MDObjCProperty : public DebugNode { + friend class LLVMContextImpl; + friend class MDNode; + + unsigned Line; + unsigned Attributes; + + MDObjCProperty(LLVMContext &C, StorageType Storage, unsigned Line, + unsigned Attributes, ArrayRef Ops) + : DebugNode(C, MDObjCPropertyKind, Storage, dwarf::DW_TAG_APPLE_property, + Ops), + Line(Line), Attributes(Attributes) {} + ~MDObjCProperty() {} + + static MDObjCProperty * + getImpl(LLVMContext &Context, StringRef Name, Metadata *File, unsigned Line, + StringRef GetterName, StringRef SetterName, unsigned Attributes, + Metadata *Type, StorageType Storage, bool ShouldCreate = true) { + return getImpl(Context, getCanonicalMDString(Context, Name), File, Line, + getCanonicalMDString(Context, GetterName), + getCanonicalMDString(Context, SetterName), Attributes, Type, + Storage, ShouldCreate); + } + static MDObjCProperty *getImpl(LLVMContext &Context, MDString *Name, + Metadata *File, unsigned Line, + MDString *GetterName, MDString *SetterName, + unsigned Attributes, Metadata *Type, + StorageType Storage, bool ShouldCreate = true); + + TempMDObjCProperty cloneImpl() const { + return getTemporary(getContext(), getName(), getFile(), getLine(), + getGetterName(), getSetterName(), getAttributes(), + getType()); + } + +public: + DEFINE_MDNODE_GET(MDObjCProperty, + (StringRef Name, Metadata *File, unsigned Line, + StringRef GetterName, StringRef SetterName, + unsigned Attributes, Metadata *Type), + (Name, File, Line, GetterName, SetterName, Attributes, + Type)) + DEFINE_MDNODE_GET(MDObjCProperty, + (MDString * Name, Metadata *File, unsigned Line, + MDString *GetterName, MDString *SetterName, + unsigned Attributes, Metadata *Type), + (Name, File, Line, GetterName, SetterName, Attributes, + Type)) + + TempMDObjCProperty clone() const { return cloneImpl(); } + + unsigned getLine() const { return Line; } + unsigned getAttributes() const { return Attributes; } + StringRef getName() const { return getStringOperand(0); } + Metadata *getFile() const { return getOperand(1); } + StringRef getGetterName() const { return getStringOperand(2); } + StringRef getSetterName() const { return getStringOperand(3); } + Metadata *getType() const { return getOperand(4); } + + MDString *getRawName() const { return getOperandAs(0); } + MDString *getRawGetterName() const { return getOperandAs(2); } + MDString *getRawSetterName() const { return getOperandAs(3); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDObjCPropertyKind; + } +}; + +class MDImportedEntity : public DebugNode { + friend class LLVMContextImpl; + friend class MDNode; + + unsigned Line; + + MDImportedEntity(LLVMContext &C, StorageType Storage, unsigned Tag, + unsigned Line, ArrayRef Ops) + : DebugNode(C, MDImportedEntityKind, Storage, Tag, Ops), Line(Line) {} + ~MDImportedEntity() {} + + static MDImportedEntity *getImpl(LLVMContext &Context, unsigned Tag, + Metadata *Scope, Metadata *Entity, + unsigned Line, StringRef Name, + StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, Tag, Scope, Entity, Line, + getCanonicalMDString(Context, Name), Storage, ShouldCreate); + } + static MDImportedEntity *getImpl(LLVMContext &Context, unsigned Tag, + Metadata *Scope, Metadata *Entity, + unsigned Line, MDString *Name, + StorageType Storage, + bool ShouldCreate = true); + + TempMDImportedEntity cloneImpl() const { + return getTemporary(getContext(), getTag(), getScope(), getEntity(), + getLine(), getName()); + } + +public: + DEFINE_MDNODE_GET(MDImportedEntity, + (unsigned Tag, Metadata *Scope, Metadata *Entity, + unsigned Line, StringRef Name = ""), + (Tag, Scope, Entity, Line, Name)) + DEFINE_MDNODE_GET(MDImportedEntity, + (unsigned Tag, Metadata *Scope, Metadata *Entity, + unsigned Line, MDString *Name), + (Tag, Scope, Entity, Line, Name)) + + TempMDImportedEntity clone() const { return cloneImpl(); } + + unsigned getLine() const { return Line; } + Metadata *getScope() const { return getOperand(0); } + Metadata *getEntity() const { return getOperand(1); } + StringRef getName() const { return getStringOperand(2); } + + MDString *getRawName() const { return getOperandAs(2); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDImportedEntityKind; + } +}; + +} // end namespace llvm + +#undef DEFINE_MDNODE_GET_UNPACK_IMPL +#undef DEFINE_MDNODE_GET_UNPACK +#undef DEFINE_MDNODE_GET + +#endif diff --git a/include/llvm/IR/DebugLoc.h b/include/llvm/IR/DebugLoc.h index 3d969a8..86e6441 100644 --- a/include/llvm/IR/DebugLoc.h +++ b/include/llvm/IR/DebugLoc.h @@ -15,51 +15,41 @@ #ifndef LLVM_IR_DEBUGLOC_H #define LLVM_IR_DEBUGLOC_H +#include "llvm/IR/TrackingMDRef.h" #include "llvm/Support/DataTypes.h" namespace llvm { - template struct DenseMapInfo; - class MDNode; + class LLVMContext; class raw_ostream; + class MDNode; /// DebugLoc - Debug location id. This is carried by Instruction, SDNode, /// and MachineInstr to compactly encode file/line/scope information for an /// operation. class DebugLoc { - friend struct DenseMapInfo; - - /// getEmptyKey() - A private constructor that returns an unknown that is - /// not equal to the tombstone key or DebugLoc(). - static DebugLoc getEmptyKey() { - DebugLoc DL; - DL.LineCol = 1; - return DL; - } + TrackingMDNodeRef Loc; - /// getTombstoneKey() - A private constructor that returns an unknown that - /// is not equal to the empty key or DebugLoc(). - static DebugLoc getTombstoneKey() { - DebugLoc DL; - DL.LineCol = 2; - return DL; + public: + DebugLoc() {} + DebugLoc(DebugLoc &&X) : Loc(std::move(X.Loc)) {} + DebugLoc(const DebugLoc &X) : Loc(X.Loc) {} + DebugLoc &operator=(DebugLoc &&X) { + Loc = std::move(X.Loc); + return *this; + } + DebugLoc &operator=(const DebugLoc &X) { + Loc = X.Loc; + return *this; } - /// LineCol - This 32-bit value encodes the line and column number for the - /// location, encoded as 24-bits for line and 8 bits for col. A value of 0 - /// for either means unknown. - uint32_t LineCol; - - /// ScopeIdx - This is an opaque ID# for Scope/InlinedAt information, - /// decoded by LLVMContext. 0 is unknown. - int ScopeIdx; - public: - DebugLoc() : LineCol(0), ScopeIdx(0) {} // Defaults to unknown. + /// \brief Check whether this has a trivial destructor. + bool hasTrivialDestructor() const { return Loc.hasTrivialDestructor(); } /// get - Get a new DebugLoc that corresponds to the specified line/col /// scope/inline location. - static DebugLoc get(unsigned Line, unsigned Col, - MDNode *Scope, MDNode *InlinedAt = nullptr); + static DebugLoc get(unsigned Line, unsigned Col, MDNode *Scope, + MDNode *InlinedAt = nullptr); /// getFromDILocation - Translate the DILocation quad into a DebugLoc. static DebugLoc getFromDILocation(MDNode *N); @@ -68,56 +58,54 @@ namespace llvm { static DebugLoc getFromDILexicalBlock(MDNode *N); /// isUnknown - Return true if this is an unknown location. - bool isUnknown() const { return ScopeIdx == 0; } + bool isUnknown() const { return !Loc; } - unsigned getLine() const { - return (LineCol << 8) >> 8; // Mask out column. - } - - unsigned getCol() const { - return LineCol >> 24; - } + unsigned getLine() const; + unsigned getCol() const; /// getScope - This returns the scope pointer for this DebugLoc, or null if /// invalid. - MDNode *getScope(const LLVMContext &Ctx) const; + MDNode *getScope() const; + MDNode *getScope(const LLVMContext &) const { return getScope(); } /// getInlinedAt - This returns the InlinedAt pointer for this DebugLoc, or /// null if invalid or not present. - MDNode *getInlinedAt(const LLVMContext &Ctx) const; + MDNode *getInlinedAt() const; + MDNode *getInlinedAt(const LLVMContext &) const { return getInlinedAt(); } /// getScopeAndInlinedAt - Return both the Scope and the InlinedAt values. + void getScopeAndInlinedAt(MDNode *&Scope, MDNode *&IA) const; void getScopeAndInlinedAt(MDNode *&Scope, MDNode *&IA, - const LLVMContext &Ctx) const; + const LLVMContext &) const { + return getScopeAndInlinedAt(Scope, IA); + } /// getScopeNode - Get MDNode for DebugLoc's scope, or null if invalid. - MDNode *getScopeNode(const LLVMContext &Ctx) const; + MDNode *getScopeNode() const; + MDNode *getScopeNode(const LLVMContext &) const { return getScopeNode(); } // getFnDebugLoc - Walk up the scope chain of given debug loc and find line // number info for the function. - DebugLoc getFnDebugLoc(const LLVMContext &Ctx) const; + DebugLoc getFnDebugLoc() const; + DebugLoc getFnDebugLoc(const LLVMContext &) const { + return getFnDebugLoc(); + } /// getAsMDNode - This method converts the compressed DebugLoc node into a /// DILocation compatible MDNode. - MDNode *getAsMDNode(const LLVMContext &Ctx) const; + MDNode *getAsMDNode() const; + MDNode *getAsMDNode(LLVMContext &) const { return getAsMDNode(); } - bool operator==(const DebugLoc &DL) const { - return LineCol == DL.LineCol && ScopeIdx == DL.ScopeIdx; - } + bool operator==(const DebugLoc &DL) const { return Loc == DL.Loc; } bool operator!=(const DebugLoc &DL) const { return !(*this == DL); } - void dump(const LLVMContext &Ctx) const; + void dump() const; + void dump(const LLVMContext &) const { dump(); } /// \brief prints source location /path/to/file.exe:line:col @[inlined at] - void print(const LLVMContext &Ctx, raw_ostream &OS) const; + void print(raw_ostream &OS) const; + void print(const LLVMContext &, raw_ostream &OS) const { print(OS); } }; - template <> - struct DenseMapInfo { - static DebugLoc getEmptyKey() { return DebugLoc::getEmptyKey(); } - static DebugLoc getTombstoneKey() { return DebugLoc::getTombstoneKey(); } - static unsigned getHashValue(const DebugLoc &Key); - static bool isEqual(DebugLoc LHS, DebugLoc RHS) { return LHS == RHS; } - }; } // end namespace llvm #endif /* LLVM_SUPPORT_DEBUGLOC_H */ diff --git a/include/llvm/IR/DerivedTypes.h b/include/llvm/IR/DerivedTypes.h index 534d1e5..76f8064 100644 --- a/include/llvm/IR/DerivedTypes.h +++ b/include/llvm/IR/DerivedTypes.h @@ -94,8 +94,8 @@ public: /// FunctionType - Class to represent function types /// class FunctionType : public Type { - FunctionType(const FunctionType &) LLVM_DELETED_FUNCTION; - const FunctionType &operator=(const FunctionType &) LLVM_DELETED_FUNCTION; + FunctionType(const FunctionType &) = delete; + const FunctionType &operator=(const FunctionType &) = delete; FunctionType(Type *Result, ArrayRef Params, bool IsVarArgs); public: @@ -123,6 +123,9 @@ public: typedef Type::subtype_iterator param_iterator; param_iterator param_begin() const { return ContainedTys + 1; } param_iterator param_end() const { return &ContainedTys[NumContainedTys]; } + ArrayRef params() const { + return makeArrayRef(param_begin(), param_end()); + } /// Parameter type accessors. Type *getParamType(unsigned i) const { return ContainedTys[i+1]; } @@ -185,8 +188,8 @@ public: /// generator for a target expects). /// class StructType : public CompositeType { - StructType(const StructType &) LLVM_DELETED_FUNCTION; - const StructType &operator=(const StructType &) LLVM_DELETED_FUNCTION; + StructType(const StructType &) = delete; + const StructType &operator=(const StructType &) = delete; StructType(LLVMContext &C) : CompositeType(C, StructTyID), SymbolTableEntry(nullptr) {} enum { @@ -274,6 +277,9 @@ public: typedef Type::subtype_iterator element_iterator; element_iterator element_begin() const { return ContainedTys; } element_iterator element_end() const { return &ContainedTys[NumContainedTys];} + ArrayRef const elements() const { + return makeArrayRef(element_begin(), element_end()); + } /// isLayoutIdentical - Return true if this is layout identical to the /// specified struct. @@ -302,8 +308,8 @@ public: /// class SequentialType : public CompositeType { Type *ContainedType; ///< Storage for the single contained type. - SequentialType(const SequentialType &) LLVM_DELETED_FUNCTION; - const SequentialType &operator=(const SequentialType &) LLVM_DELETED_FUNCTION; + SequentialType(const SequentialType &) = delete; + const SequentialType &operator=(const SequentialType &) = delete; protected: SequentialType(TypeID TID, Type *ElType) @@ -329,8 +335,8 @@ public: class ArrayType : public SequentialType { uint64_t NumElements; - ArrayType(const ArrayType &) LLVM_DELETED_FUNCTION; - const ArrayType &operator=(const ArrayType &) LLVM_DELETED_FUNCTION; + ArrayType(const ArrayType &) = delete; + const ArrayType &operator=(const ArrayType &) = delete; ArrayType(Type *ElType, uint64_t NumEl); public: /// ArrayType::get - This static method is the primary way to construct an @@ -355,8 +361,8 @@ public: class VectorType : public SequentialType { unsigned NumElements; - VectorType(const VectorType &) LLVM_DELETED_FUNCTION; - const VectorType &operator=(const VectorType &) LLVM_DELETED_FUNCTION; + VectorType(const VectorType &) = delete; + const VectorType &operator=(const VectorType &) = delete; VectorType(Type *ElType, unsigned NumEl); public: /// VectorType::get - This static method is the primary way to construct an @@ -440,8 +446,8 @@ public: /// PointerType - Class to represent pointers. /// class PointerType : public SequentialType { - PointerType(const PointerType &) LLVM_DELETED_FUNCTION; - const PointerType &operator=(const PointerType &) LLVM_DELETED_FUNCTION; + PointerType(const PointerType &) = delete; + const PointerType &operator=(const PointerType &) = delete; explicit PointerType(Type *ElType, unsigned AddrSpace); public: /// PointerType::get - This constructs a pointer to an object of the specified diff --git a/include/llvm/IR/DiagnosticInfo.h b/include/llvm/IR/DiagnosticInfo.h index b592f89..c6a8854 100644 --- a/include/llvm/IR/DiagnosticInfo.h +++ b/include/llvm/IR/DiagnosticInfo.h @@ -45,6 +45,7 @@ enum DiagnosticSeverity { /// \brief Defines the different supported kind of a diagnostic. /// This enum should be extended with a new ID for each added concrete subclass. enum DiagnosticKind { + DK_Bitcode, DK_InlineAsm, DK_StackSize, DK_Linker, @@ -97,6 +98,8 @@ public: virtual void print(DiagnosticPrinter &DP) const = 0; }; +typedef std::function DiagnosticHandlerFunction; + /// Diagnostic information for inline asm reporting. /// This is basically a message and an optional location. class DiagnosticInfoInlineAsm : public DiagnosticInfo { diff --git a/include/llvm/IR/Dominators.h b/include/llvm/IR/Dominators.h index e2d1ccc..c1f208e 100644 --- a/include/llvm/IR/Dominators.h +++ b/include/llvm/IR/Dominators.h @@ -31,6 +31,11 @@ namespace llvm { +// FIXME: Replace this brittle forward declaration with the include of the new +// PassManager.h when doing so doesn't break the PassManagerBuilder. +template class AnalysisManager; +class PreservedAnalyses; + EXTERN_TEMPLATE_INSTANTIATION(class DomTreeNodeBase); EXTERN_TEMPLATE_INSTANTIATION(class DominatorTreeBase); @@ -69,6 +74,13 @@ public: DominatorTree() : DominatorTreeBase(false) {} + DominatorTree(DominatorTree &&Arg) + : Base(std::move(static_cast(Arg))) {} + DominatorTree &operator=(DominatorTree &&RHS) { + Base::operator=(std::move(static_cast(RHS))); + return *this; + } + /// \brief Returns *false* if the other dominator tree matches this dominator /// tree. inline bool compare(const DominatorTree &Other) const { @@ -155,6 +167,43 @@ template <> struct GraphTraits }; /// \brief Analysis pass which computes a \c DominatorTree. +class DominatorTreeAnalysis { +public: + /// \brief Provide the result typedef for this analysis pass. + typedef DominatorTree Result; + + /// \brief Opaque, unique identifier for this analysis pass. + static void *ID() { return (void *)&PassID; } + + /// \brief Run the analysis pass over a function and produce a dominator tree. + DominatorTree run(Function &F); + + /// \brief Provide access to a name for this pass for debugging purposes. + static StringRef name() { return "DominatorTreeAnalysis"; } + +private: + static char PassID; +}; + +/// \brief Printer pass for the \c DominatorTree. +class DominatorTreePrinterPass { + raw_ostream &OS; + +public: + explicit DominatorTreePrinterPass(raw_ostream &OS); + PreservedAnalyses run(Function &F, AnalysisManager *AM); + + static StringRef name() { return "DominatorTreePrinterPass"; } +}; + +/// \brief Verifier pass for the \c DominatorTree. +struct DominatorTreeVerifierPass { + PreservedAnalyses run(Function &F, AnalysisManager *AM); + + static StringRef name() { return "DominatorTreeVerifierPass"; } +}; + +/// \brief Legacy analysis pass which computes a \c DominatorTree. class DominatorTreeWrapperPass : public FunctionPass { DominatorTree DT; diff --git a/include/llvm/IR/Function.h b/include/llvm/IR/Function.h index 26d893b..0cd5afb 100644 --- a/include/llvm/IR/Function.h +++ b/include/llvm/IR/Function.h @@ -87,11 +87,14 @@ private: ValueSymbolTable *SymTab; ///< Symbol table of args/instructions AttributeSet AttributeSets; ///< Parameter attributes - // HasLazyArguments is stored in Value::SubclassData. - /*bool HasLazyArguments;*/ - - // The Calling Convention is stored in Value::SubclassData. - /*CallingConv::ID CallingConvention;*/ + /* + * Value::SubclassData + * + * bit 0 : HasLazyArguments + * bit 1 : HasPrefixData + * bit 2 : HasPrologueData + * bit 3-6: CallingConvention + */ friend class SymbolTableListTraits; @@ -102,7 +105,7 @@ private: /// needs it. The hasLazyArguments predicate returns true if the arg list /// hasn't been set up yet. bool hasLazyArguments() const { - return getSubclassDataFromValue() & 1; + return getSubclassDataFromValue() & (1<<0); } void CheckLazyArguments() const { if (hasLazyArguments()) @@ -110,8 +113,8 @@ private: } void BuildLazyArguments() const; - Function(const Function&) LLVM_DELETED_FUNCTION; - void operator=(const Function&) LLVM_DELETED_FUNCTION; + Function(const Function&) = delete; + void operator=(const Function&) = delete; /// Do the actual lookup of an intrinsic ID when the query could not be /// answered from the cache. @@ -162,11 +165,11 @@ public: /// calling convention of this function. The enum values for the known /// calling conventions are defined in CallingConv.h. CallingConv::ID getCallingConv() const { - return static_cast(getSubclassDataFromValue() >> 2); + return static_cast(getSubclassDataFromValue() >> 3); } void setCallingConv(CallingConv::ID CC) { - setValueSubclassData((getSubclassDataFromValue() & 3) | - (static_cast(CC) << 2)); + setValueSubclassData((getSubclassDataFromValue() & 7) | + (static_cast(CC) << 3)); } /// @brief Return the attribute list for this Function. @@ -215,6 +218,11 @@ public: return AttributeSets.getAttribute(AttributeSet::FunctionIndex, Kind); } + /// \brief Return the stack alignment for the function. + unsigned getFnStackAlignment() const { + return AttributeSets.getStackAlignment(AttributeSet::FunctionIndex); + } + /// hasGC/getGC/setGC/clearGC - The name of the garbage collection algorithm /// to use during code generation. bool hasGC() const; @@ -231,6 +239,9 @@ public: /// @brief removes the attributes from the list of attributes. void removeAttributes(unsigned i, AttributeSet attr); + /// @brief adds the dereferenceable attribute to the list of attributes. + void addDereferenceableAttr(unsigned i, uint64_t Bytes); + /// @brief Extract the alignment for a call or parameter (0=unknown). unsigned getParamAlignment(unsigned i) const { return AttributeSets.getParamAlignment(i); @@ -448,12 +459,19 @@ public: bool arg_empty() const; bool hasPrefixData() const { - return getSubclassDataFromValue() & 2; + return getSubclassDataFromValue() & (1<<1); } Constant *getPrefixData() const; void setPrefixData(Constant *PrefixData); + bool hasPrologueData() const { + return getSubclassDataFromValue() & (1<<2); + } + + Constant *getPrologueData() const; + void setPrologueData(Constant *PrologueData); + /// viewCFG - This function is meant for use from the debugger. You can just /// say 'call F->viewCFG()' and a ghostview window should pop up from the /// program, displaying the CFG of the current function with the code for each diff --git a/include/llvm/IR/GVMaterializer.h b/include/llvm/IR/GVMaterializer.h index a7d68ec..6f57dc2 100644 --- a/include/llvm/IR/GVMaterializer.h +++ b/include/llvm/IR/GVMaterializer.h @@ -19,11 +19,13 @@ #define LLVM_IR_GVMATERIALIZER_H #include +#include namespace llvm { class Function; class GlobalValue; class Module; +class StructType; class GVMaterializer { protected: @@ -50,6 +52,8 @@ public: /// Make sure the entire Module has been completely read. /// virtual std::error_code MaterializeModule(Module *M) = 0; + + virtual std::vector getIdentifiedStructTypes() const = 0; }; } // End llvm namespace diff --git a/include/llvm/IR/GlobalAlias.h b/include/llvm/IR/GlobalAlias.h index 075b570..d0672c8 100644 --- a/include/llvm/IR/GlobalAlias.h +++ b/include/llvm/IR/GlobalAlias.h @@ -28,8 +28,8 @@ template class GlobalAlias : public GlobalValue, public ilist_node { friend class SymbolTableListTraits; - void operator=(const GlobalAlias &) LLVM_DELETED_FUNCTION; - GlobalAlias(const GlobalAlias &) LLVM_DELETED_FUNCTION; + void operator=(const GlobalAlias &) = delete; + GlobalAlias(const GlobalAlias &) = delete; void setParent(Module *parent); diff --git a/include/llvm/IR/GlobalObject.h b/include/llvm/IR/GlobalObject.h index 546fea2..50deb08 100644 --- a/include/llvm/IR/GlobalObject.h +++ b/include/llvm/IR/GlobalObject.h @@ -24,7 +24,7 @@ class Comdat; class Module; class GlobalObject : public GlobalValue { - GlobalObject(const GlobalObject &) LLVM_DELETED_FUNCTION; + GlobalObject(const GlobalObject &) = delete; protected: GlobalObject(Type *Ty, ValueTy VTy, Use *Ops, unsigned NumOps, diff --git a/include/llvm/IR/GlobalValue.h b/include/llvm/IR/GlobalValue.h index e7b5d58..aaecc1d 100644 --- a/include/llvm/IR/GlobalValue.h +++ b/include/llvm/IR/GlobalValue.h @@ -20,7 +20,6 @@ #include "llvm/IR/Constant.h" #include "llvm/IR/DerivedTypes.h" - #include namespace llvm { @@ -30,7 +29,7 @@ class PointerType; class Module; class GlobalValue : public Constant { - GlobalValue(const GlobalValue &) LLVM_DELETED_FUNCTION; + GlobalValue(const GlobalValue &) = delete; public: /// @brief An enumeration for the kinds of linkage for global values. enum LinkageTypes { diff --git a/include/llvm/IR/GlobalVariable.h b/include/llvm/IR/GlobalVariable.h index 4189ccb..d7b81a2 100644 --- a/include/llvm/IR/GlobalVariable.h +++ b/include/llvm/IR/GlobalVariable.h @@ -34,9 +34,9 @@ template class GlobalVariable : public GlobalObject, public ilist_node { friend class SymbolTableListTraits; - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; - void operator=(const GlobalVariable &) LLVM_DELETED_FUNCTION; - GlobalVariable(const GlobalVariable &) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; + void operator=(const GlobalVariable &) = delete; + GlobalVariable(const GlobalVariable &) = delete; void setParent(Module *parent); diff --git a/include/llvm/IR/IRBuilder.h b/include/llvm/IR/IRBuilder.h index 088c7b4..33649d7 100644 --- a/include/llvm/IR/IRBuilder.h +++ b/include/llvm/IR/IRBuilder.h @@ -115,12 +115,10 @@ public: } /// \brief Set location information used by debugging information. - void SetCurrentDebugLocation(const DebugLoc &L) { - CurDbgLocation = L; - } + void SetCurrentDebugLocation(DebugLoc L) { CurDbgLocation = std::move(L); } /// \brief Get location information used by debugging information. - DebugLoc getCurrentDebugLocation() const { return CurDbgLocation; } + const DebugLoc &getCurrentDebugLocation() const { return CurDbgLocation; } /// \brief If this builder has a current debug location, set it on the /// specified instruction. @@ -200,8 +198,8 @@ public: BasicBlock::iterator Point; DebugLoc DbgLoc; - InsertPointGuard(const InsertPointGuard &) LLVM_DELETED_FUNCTION; - InsertPointGuard &operator=(const InsertPointGuard &) LLVM_DELETED_FUNCTION; + InsertPointGuard(const InsertPointGuard &) = delete; + InsertPointGuard &operator=(const InsertPointGuard &) = delete; public: InsertPointGuard(IRBuilderBase &B) @@ -221,9 +219,9 @@ public: FastMathFlags FMF; MDNode *FPMathTag; - FastMathFlagGuard(const FastMathFlagGuard &) LLVM_DELETED_FUNCTION; + FastMathFlagGuard(const FastMathFlagGuard &) = delete; FastMathFlagGuard &operator=( - const FastMathFlagGuard &) LLVM_DELETED_FUNCTION; + const FastMathFlagGuard &) = delete; public: FastMathFlagGuard(IRBuilderBase &B) @@ -429,11 +427,54 @@ public: /// If the pointer isn't i8* it will be converted. CallInst *CreateLifetimeEnd(Value *Ptr, ConstantInt *Size = nullptr); + /// \brief Create a call to Masked Load intrinsic + CallInst *CreateMaskedLoad(Value *Ptr, unsigned Align, Value *Mask, + Value *PassThru = 0, const Twine &Name = ""); + + /// \brief Create a call to Masked Store intrinsic + CallInst *CreateMaskedStore(Value *Val, Value *Ptr, unsigned Align, + Value *Mask); + /// \brief Create an assume intrinsic call that allows the optimizer to /// assume that the provided condition will be true. CallInst *CreateAssumption(Value *Cond); + /// \brief Create a call to the experimental.gc.statepoint intrinsic to + /// start a new statepoint sequence. + CallInst *CreateGCStatepoint(Value *ActualCallee, + ArrayRef CallArgs, + ArrayRef DeoptArgs, + ArrayRef GCArgs, + const Twine &Name = ""); + + // Conveninence function for the common case when CallArgs are filled in using + // makeArrayRef(CS.arg_begin(), .arg_end()); Use needs to be .get()'ed to get + // the Value *. + CallInst *CreateGCStatepoint(Value *ActualCallee, ArrayRef CallArgs, + ArrayRef DeoptArgs, + ArrayRef GCArgs, + const Twine &Name = ""); + + /// \brief Create a call to the experimental.gc.result intrinsic to extract + /// the result from a call wrapped in a statepoint. + CallInst *CreateGCResult(Instruction *Statepoint, + Type *ResultType, + const Twine &Name = ""); + + /// \brief Create a call to the experimental.gc.relocate intrinsics to + /// project the relocated value of one pointer from the statepoint. + CallInst *CreateGCRelocate(Instruction *Statepoint, + int BaseOffset, + int DerivedOffset, + Type *ResultType, + const Twine &Name = ""); + private: + /// \brief Create a call to a masked intrinsic with given Id. + /// Masked intrinsic has only one overloaded type - data type. + CallInst *CreateMaskedIntrinsic(unsigned Id, ArrayRef Ops, + Type *DataTy, const Twine &Name = ""); + Value *getCastedInt8PtrValue(Value *Ptr); }; @@ -1246,11 +1287,23 @@ public: return Insert(Folder.CreateIntCast(VC, DestTy, isSigned), Name); return Insert(CastInst::CreateIntegerCast(V, DestTy, isSigned), Name); } + + Value *CreateBitOrPointerCast(Value *V, Type *DestTy, + const Twine &Name = "") { + if (V->getType() == DestTy) + return V; + if (V->getType()->isPointerTy() && DestTy->isIntegerTy()) + return CreatePtrToInt(V, DestTy, Name); + if (V->getType()->isIntegerTy() && DestTy->isPointerTy()) + return CreateIntToPtr(V, DestTy, Name); + + return CreateBitCast(V, DestTy, Name); + } private: // \brief Provided to resolve 'CreateIntCast(Ptr, Ptr, "...")', giving a // compile time error, instead of converting the string to bool for the // isSigned parameter. - Value *CreateIntCast(Value *, Type *, const char *) LLVM_DELETED_FUNCTION; + Value *CreateIntCast(Value *, Type *, const char *) = delete; public: Value *CreateFPCast(Value *V, Type *DestTy, const Twine &Name = "") { if (V->getType() == DestTy) diff --git a/include/llvm/IR/IRPrintingPasses.h b/include/llvm/IR/IRPrintingPasses.h index afea0c3..7f2027b 100644 --- a/include/llvm/IR/IRPrintingPasses.h +++ b/include/llvm/IR/IRPrintingPasses.h @@ -58,7 +58,7 @@ public: PrintModulePass(); PrintModulePass(raw_ostream &OS, const std::string &Banner = ""); - PreservedAnalyses run(Module *M); + PreservedAnalyses run(Module &M); static StringRef name() { return "PrintModulePass"; } }; @@ -75,7 +75,7 @@ public: PrintFunctionPass(); PrintFunctionPass(raw_ostream &OS, const std::string &Banner = ""); - PreservedAnalyses run(Function *F); + PreservedAnalyses run(Function &F); static StringRef name() { return "PrintFunctionPass"; } }; diff --git a/include/llvm/IR/InlineAsm.h b/include/llvm/IR/InlineAsm.h index b2d79d0..84ae9df 100644 --- a/include/llvm/IR/InlineAsm.h +++ b/include/llvm/IR/InlineAsm.h @@ -40,8 +40,8 @@ private: friend struct InlineAsmKeyType; friend class ConstantUniqueMap; - InlineAsm(const InlineAsm &) LLVM_DELETED_FUNCTION; - void operator=(const InlineAsm&) LLVM_DELETED_FUNCTION; + InlineAsm(const InlineAsm &) = delete; + void operator=(const InlineAsm&) = delete; std::string AsmString, Constraints; bool HasSideEffects; diff --git a/include/llvm/IR/InstIterator.h b/include/llvm/IR/InstIterator.h index 75e93bd..0bb2854 100644 --- a/include/llvm/IR/InstIterator.h +++ b/include/llvm/IR/InstIterator.h @@ -127,20 +127,32 @@ typedef InstIterator, inline inst_iterator inst_begin(Function *F) { return inst_iterator(*F); } inline inst_iterator inst_end(Function *F) { return inst_iterator(*F, true); } +inline iterator_range inst_range(Function *F) { + return iterator_range(inst_begin(F), inst_end(F)); +} inline const_inst_iterator inst_begin(const Function *F) { return const_inst_iterator(*F); } inline const_inst_iterator inst_end(const Function *F) { return const_inst_iterator(*F, true); } +inline iterator_range inst_range(const Function *F) { + return iterator_range(inst_begin(F), inst_end(F)); +} inline inst_iterator inst_begin(Function &F) { return inst_iterator(F); } inline inst_iterator inst_end(Function &F) { return inst_iterator(F, true); } +inline iterator_range inst_range(Function &F) { + return iterator_range(inst_begin(F), inst_end(F)); +} inline const_inst_iterator inst_begin(const Function &F) { return const_inst_iterator(F); } inline const_inst_iterator inst_end(const Function &F) { return const_inst_iterator(F, true); } +inline iterator_range inst_range(const Function &F) { + return iterator_range(inst_begin(F), inst_end(F)); +} } // End llvm namespace diff --git a/include/llvm/IR/InstrTypes.h b/include/llvm/IR/InstrTypes.h index 186fc88..e086282 100644 --- a/include/llvm/IR/InstrTypes.h +++ b/include/llvm/IR/InstrTypes.h @@ -83,7 +83,7 @@ public: //===----------------------------------------------------------------------===// class UnaryInstruction : public Instruction { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; protected: UnaryInstruction(Type *Ty, unsigned iType, Value *V, @@ -132,7 +132,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(UnaryInstruction, Value) //===----------------------------------------------------------------------===// class BinaryOperator : public Instruction { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; protected: void init(BinaryOps iType); BinaryOperator(BinaryOps iType, Value *S1, Value *S2, Type *Ty, @@ -489,6 +489,19 @@ public: Instruction *InsertBefore = 0 ///< Place to insert the instruction ); + /// @brief Create a BitCast, a PtrToInt, or an IntToPTr cast instruction. + /// + /// If the value is a pointer type and the destination an integer type, + /// creates a PtrToInt cast. If the value is an integer type and the + /// destination a pointer type, creates an IntToPtr cast. Otherwise, creates + /// a bitcast. + static CastInst *CreateBitOrPointerCast( + Value *S, ///< The pointer value to be casted (operand 0) + Type *Ty, ///< The type to which cast should be made + const Twine &Name = "", ///< Name for the instruction + Instruction *InsertBefore = 0 ///< Place to insert the instruction + ); + /// @brief Create a ZExt, BitCast, or Trunc for int -> int casts. static CastInst *CreateIntegerCast( Value *S, ///< The pointer value to be casted (operand 0) @@ -551,6 +564,17 @@ public: Type *DestTy ///< The Type to which the value should be cast. ); + /// @brief Check whether a bitcast, inttoptr, or ptrtoint cast between these + /// types is valid and a no-op. + /// + /// This ensures that any pointer<->integer cast has enough bits in the + /// integer and any other cast is a bitcast. + static bool isBitOrNoopPointerCastable( + Type *SrcTy, ///< The Type from which the value should be cast. + Type *DestTy, ///< The Type to which the value should be cast. + const DataLayout *Layout = 0 ///< Optional DataLayout. + ); + /// Returns the opcode necessary to cast Val into Ty using usual casting /// rules. /// @brief Infer the opcode for cast operand and type @@ -650,8 +674,8 @@ public: /// This class is the base class for the comparison instructions. /// @brief Abstract base class of comparison instructions. class CmpInst : public Instruction { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; - CmpInst() LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; + CmpInst() = delete; protected: CmpInst(Type *ty, Instruction::OtherOps op, unsigned short pred, Value *LHS, Value *RHS, const Twine &Name = "", diff --git a/include/llvm/IR/Instruction.h b/include/llvm/IR/Instruction.h index ba7791c..dfece3e 100644 --- a/include/llvm/IR/Instruction.h +++ b/include/llvm/IR/Instruction.h @@ -31,8 +31,8 @@ template class SymbolTableListTraits; class Instruction : public User, public ilist_node { - void operator=(const Instruction &) LLVM_DELETED_FUNCTION; - Instruction(const Instruction &) LLVM_DELETED_FUNCTION; + void operator=(const Instruction &) = delete; + Instruction(const Instruction &) = delete; BasicBlock *Parent; DebugLoc DbgLoc; // 'dbg' Metadata cache. @@ -201,7 +201,7 @@ public: void setAAMetadata(const AAMDNodes &N); /// setDebugLoc - Set the debug location information for this instruction. - void setDebugLoc(const DebugLoc &Loc) { DbgLoc = Loc; } + void setDebugLoc(DebugLoc Loc) { DbgLoc = std::move(Loc); } /// getDebugLoc - Return the debug location for this node as a DebugLoc. const DebugLoc &getDebugLoc() const { return DbgLoc; } diff --git a/include/llvm/IR/Instructions.h b/include/llvm/IR/Instructions.h index dcf19e0..83f9d04 100644 --- a/include/llvm/IR/Instructions.h +++ b/include/llvm/IR/Instructions.h @@ -17,8 +17,8 @@ #define LLVM_IR_INSTRUCTIONS_H #include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/iterator_range.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/iterator_range.h" #include "llvm/IR/Attributes.h" #include "llvm/IR/CallingConv.h" #include "llvm/IR/DerivedTypes.h" @@ -285,7 +285,7 @@ private: /// StoreInst - an instruction for storing to memory /// class StoreInst : public Instruction { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; void AssertOK(); protected: StoreInst *clone_impl() const override; @@ -411,7 +411,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(StoreInst, Value) /// FenceInst - an instruction for ordering other memory operations /// class FenceInst : public Instruction { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; void Init(AtomicOrdering Ordering, SynchronizationScope SynchScope); protected: FenceInst *clone_impl() const override; @@ -478,7 +478,7 @@ private: /// there. Returns the value that was loaded. /// class AtomicCmpXchgInst : public Instruction { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; void Init(Value *Ptr, Value *Cmp, Value *NewVal, AtomicOrdering SuccessOrdering, AtomicOrdering FailureOrdering, SynchronizationScope SynchScope); @@ -634,7 +634,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(AtomicCmpXchgInst, Value) /// the old value. /// class AtomicRMWInst : public Instruction { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; protected: AtomicRMWInst *clone_impl() const override; public: @@ -845,6 +845,13 @@ public: return cast(Instruction::getType()); } + Type *getSourceElementType() const { + SequentialType *Ty = cast(getPointerOperandType()); + if (VectorType *VTy = dyn_cast(Ty)) + Ty = cast(VTy->getElementType()); + return Ty->getElementType(); + } + /// \brief Returns the address space of this instruction's pointer type. unsigned getAddressSpace() const { // Note that this is always the same as the pointer operand's address space @@ -1375,6 +1382,9 @@ public: /// removeAttribute - removes the attribute from the list of attributes. void removeAttribute(unsigned i, Attribute attr); + /// \brief adds the dereferenceable attribute to the list of attributes. + void addDereferenceableAttr(unsigned i, uint64_t Bytes); + /// \brief Determine whether this call has the given attribute. bool hasFnAttr(Attribute::AttrKind A) const { assert(A != Attribute::NoBuiltin && @@ -1958,7 +1968,7 @@ ExtractValueInst::ExtractValueInst(Value *Agg, class InsertValueInst : public Instruction { SmallVector Indices; - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; InsertValueInst(const InsertValueInst &IVI); void init(Value *Agg, Value *Val, ArrayRef Idxs, const Twine &NameStr); @@ -2088,7 +2098,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(InsertValueInst, Value) // scientist's overactive imagination. // class PHINode : public Instruction { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; /// ReservedSpace - The number of operands actually allocated. NumOperands is /// the number actually in use. unsigned ReservedSpace; @@ -2163,6 +2173,8 @@ public: return block_begin() + getNumOperands(); } + op_range incoming_values() { return operands(); } + /// getNumIncomingValues - Return the number of incoming edges /// unsigned getNumIncomingValues() const { return getNumOperands(); } @@ -2295,7 +2307,7 @@ class LandingPadInst : public Instruction { public: enum ClauseType { Catch, Filter }; private: - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; // Allocate space for exactly zero operands. void *operator new(size_t s) { return User::operator new(s, 0); @@ -2562,7 +2574,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(BranchInst, Value) /// SwitchInst - Multiway switch /// class SwitchInst : public TerminatorInst { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; unsigned ReservedSpace; // Operand[0] = Value to switch on // Operand[1] = Default basic block destination @@ -2871,7 +2883,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(SwitchInst, Value) /// IndirectBrInst - Indirect Branch Instruction. /// class IndirectBrInst : public TerminatorInst { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; unsigned ReservedSpace; // Operand[0] = Value to switch on // Operand[1] = Default basic block destination @@ -3056,6 +3068,9 @@ public: /// removeAttribute - removes the attribute from the list of attributes. void removeAttribute(unsigned i, Attribute attr); + /// \brief removes the dereferenceable attribute to the list of attributes. + void addDereferenceableAttr(unsigned i, uint64_t Bytes); + /// \brief Determine whether this call has the given attribute. bool hasFnAttr(Attribute::AttrKind A) const { assert(A != Attribute::NoBuiltin && @@ -3296,7 +3311,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ResumeInst, Value) /// end of the block cannot be reached. /// class UnreachableInst : public TerminatorInst { - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; protected: UnreachableInst *clone_impl() const override; diff --git a/include/llvm/IR/IntrinsicInst.h b/include/llvm/IR/IntrinsicInst.h index e3d7999..d434432 100644 --- a/include/llvm/IR/IntrinsicInst.h +++ b/include/llvm/IR/IntrinsicInst.h @@ -28,15 +28,16 @@ #include "llvm/IR/Function.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/Intrinsics.h" +#include "llvm/IR/Metadata.h" namespace llvm { /// IntrinsicInst - A useful wrapper class for inspecting calls to intrinsic /// functions. This allows the standard isa/dyncast/cast functionality to /// work with calls to intrinsic functions. class IntrinsicInst : public CallInst { - IntrinsicInst() LLVM_DELETED_FUNCTION; - IntrinsicInst(const IntrinsicInst&) LLVM_DELETED_FUNCTION; - void operator=(const IntrinsicInst&) LLVM_DELETED_FUNCTION; + IntrinsicInst() = delete; + IntrinsicInst(const IntrinsicInst&) = delete; + void operator=(const IntrinsicInst&) = delete; public: /// getIntrinsicID - Return the intrinsic ID of this intrinsic. /// @@ -81,8 +82,14 @@ namespace llvm { class DbgDeclareInst : public DbgInfoIntrinsic { public: Value *getAddress() const; - MDNode *getVariable() const { return cast(getArgOperand(1)); } - MDNode *getExpression() const { return cast(getArgOperand(2)); } + MDNode *getVariable() const { + return cast( + cast(getArgOperand(1))->getMetadata()); + } + MDNode *getExpression() const { + return cast( + cast(getArgOperand(2))->getMetadata()); + } // Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const IntrinsicInst *I) { @@ -103,8 +110,14 @@ namespace llvm { return cast( const_cast(getArgOperand(1)))->getZExtValue(); } - MDNode *getVariable() const { return cast(getArgOperand(2)); } - MDNode *getExpression() const { return cast(getArgOperand(3)); } + MDNode *getVariable() const { + return cast( + cast(getArgOperand(2))->getMetadata()); + } + MDNode *getExpression() const { + return cast( + cast(getArgOperand(3))->getMetadata()); + } // Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const IntrinsicInst *I) { @@ -322,6 +335,33 @@ namespace llvm { Value *getSrc() const { return const_cast(getArgOperand(1)); } }; + /// This represents the llvm.instrprof_increment intrinsic. + class InstrProfIncrementInst : public IntrinsicInst { + public: + static inline bool classof(const IntrinsicInst *I) { + return I->getIntrinsicID() == Intrinsic::instrprof_increment; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } + + GlobalVariable *getName() const { + return cast( + const_cast(getArgOperand(0))->stripPointerCasts()); + } + + ConstantInt *getHash() const { + return cast(const_cast(getArgOperand(1))); + } + + ConstantInt *getNumCounters() const { + return cast(const_cast(getArgOperand(2))); + } + + ConstantInt *getIndex() const { + return cast(const_cast(getArgOperand(3))); + } + }; } #endif diff --git a/include/llvm/IR/Intrinsics.h b/include/llvm/IR/Intrinsics.h index acc0e9e..a66bd2c 100644 --- a/include/llvm/IR/Intrinsics.h +++ b/include/llvm/IR/Intrinsics.h @@ -41,7 +41,7 @@ namespace Intrinsic { #undef GET_INTRINSIC_ENUM_VALUES , num_intrinsics }; - + /// Return the LLVM name for an intrinsic, such as "llvm.ppc.altivec.lvx". std::string getName(ID id, ArrayRef Tys = None); @@ -69,16 +69,17 @@ namespace Intrinsic { /// Map a MS builtin name to an intrinsic ID. ID getIntrinsicForMSBuiltin(const char *Prefix, const char *BuiltinName); - + /// This is a type descriptor which explains the type requirements of an /// intrinsic. This is returned by getIntrinsicInfoTableEntries. struct IITDescriptor { enum IITDescriptorKind { Void, VarArg, MMX, Metadata, Half, Float, Double, Integer, Vector, Pointer, Struct, - Argument, ExtendArgument, TruncArgument, HalfVecArgument + Argument, ExtendArgument, TruncArgument, HalfVecArgument, + SameVecWidthArgument, PtrToArgument, VecOfPtrsToElt } Kind; - + union { unsigned Integer_Width; unsigned Float_Width; @@ -87,8 +88,9 @@ namespace Intrinsic { unsigned Struct_NumElements; unsigned Argument_Info; }; - + enum ArgKind { + AK_Any, AK_AnyInteger, AK_AnyFloat, AK_AnyVector, @@ -96,25 +98,29 @@ namespace Intrinsic { }; unsigned getArgumentNumber() const { assert(Kind == Argument || Kind == ExtendArgument || - Kind == TruncArgument || Kind == HalfVecArgument); - return Argument_Info >> 2; + Kind == TruncArgument || Kind == HalfVecArgument || + Kind == SameVecWidthArgument || Kind == PtrToArgument || + Kind == VecOfPtrsToElt); + return Argument_Info >> 3; } ArgKind getArgumentKind() const { assert(Kind == Argument || Kind == ExtendArgument || - Kind == TruncArgument || Kind == HalfVecArgument); - return (ArgKind)(Argument_Info&3); + Kind == TruncArgument || Kind == HalfVecArgument || + Kind == SameVecWidthArgument || Kind == PtrToArgument || + Kind == VecOfPtrsToElt); + return (ArgKind)(Argument_Info & 7); } - + static IITDescriptor get(IITDescriptorKind K, unsigned Field) { IITDescriptor Result = { K, { Field } }; return Result; } }; - + /// Return the IIT table descriptor for the specified intrinsic into an array /// of IITDescriptors. void getIntrinsicInfoTableEntries(ID id, SmallVectorImpl &T); - + } // End Intrinsic namespace } // End llvm namespace diff --git a/include/llvm/IR/Intrinsics.td b/include/llvm/IR/Intrinsics.td index 98d48de..e89e65d 100644 --- a/include/llvm/IR/Intrinsics.td +++ b/include/llvm/IR/Intrinsics.td @@ -112,12 +112,19 @@ class LLVMMatchType // the intrinsic is overloaded, so the matched type should be declared as iAny. class LLVMExtendedType : LLVMMatchType; class LLVMTruncatedType : LLVMMatchType; +class LLVMVectorSameWidth + : LLVMMatchType { + ValueType ElTy = elty.VT; +} +class LLVMPointerTo : LLVMMatchType; +class LLVMVectorOfPointersToElt : LLVMMatchType; // Match the type of another intrinsic parameter that is expected to be a // vector type, but change the element count to be half as many class LLVMHalfElementsVectorType : LLVMMatchType; def llvm_void_ty : LLVMType; +def llvm_any_ty : LLVMType; def llvm_anyint_ty : LLVMType; def llvm_anyfloat_ty : LLVMType; def llvm_anyvector_ty : LLVMType; @@ -254,6 +261,10 @@ def int_gcwrite : Intrinsic<[], // def int_returnaddress : Intrinsic<[llvm_ptr_ty], [llvm_i32_ty], [IntrNoMem]>; def int_frameaddress : Intrinsic<[llvm_ptr_ty], [llvm_i32_ty], [IntrNoMem]>; +def int_frameallocate : Intrinsic<[llvm_ptr_ty], [llvm_i32_ty]>; +def int_framerecover : Intrinsic<[llvm_ptr_ty], + [llvm_ptr_ty, llvm_ptr_ty], + [IntrNoMem]>; def int_read_register : Intrinsic<[llvm_anyint_ty], [llvm_metadata_ty], [IntrNoMem], "llvm.read_register">; def int_write_register : Intrinsic<[], [llvm_metadata_ty, llvm_anyint_ty], @@ -287,6 +298,12 @@ def int_stackprotector : Intrinsic<[], [llvm_ptr_ty, llvm_ptrptr_ty], []>; def int_stackprotectorcheck : Intrinsic<[], [llvm_ptrptr_ty], [IntrReadWriteArgMem]>; +// A counter increment for instrumentation based profiling. +def int_instrprof_increment : Intrinsic<[], + [llvm_ptr_ty, llvm_i64_ty, + llvm_i32_ty, llvm_i32_ty], + []>; + //===------------------- Standard C Library Intrinsics --------------------===// // @@ -394,6 +411,11 @@ def int_eh_typeid_for : Intrinsic<[llvm_i32_ty], [llvm_ptr_ty], [IntrNoMem]>; def int_eh_return_i32 : Intrinsic<[], [llvm_i32_ty, llvm_ptr_ty]>; def int_eh_return_i64 : Intrinsic<[], [llvm_i64_ty, llvm_ptr_ty]>; +// eh.begincatch takes a pointer returned by a landingpad instruction and +// returns the exception object pointer for the exception to be handled. +def int_eh_begincatch : Intrinsic<[llvm_ptr_ty], [llvm_ptr_ty]>; +def int_eh_endcatch : Intrinsic<[], []>; + // __builtin_unwind_init is an undocumented GCC intrinsic that causes all // callee-saved registers to be saved and restored (regardless of whether they // are used) in the calling function. It is used by libgcc_eh. @@ -493,6 +515,24 @@ def int_experimental_patchpoint_i64 : Intrinsic<[llvm_i64_ty], llvm_vararg_ty], [Throws]>; + +//===------------------------ Garbage Collection Intrinsics ---------------===// +// These are documented in docs/Statepoint.rst + +def int_experimental_gc_statepoint : Intrinsic<[llvm_i32_ty], + [llvm_anyptr_ty, llvm_i32_ty, + llvm_i32_ty, llvm_vararg_ty]>; + +def int_experimental_gc_result : Intrinsic<[llvm_any_ty], [llvm_i32_ty]>; +def int_experimental_gc_relocate : Intrinsic<[llvm_anyptr_ty], + [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty]>; + +// Deprecated: will be removed in a couple of weeks +def int_experimental_gc_result_int : Intrinsic<[llvm_anyint_ty], [llvm_i32_ty]>; +def int_experimental_gc_result_float : Intrinsic<[llvm_anyfloat_ty], + [llvm_i32_ty]>; +def int_experimental_gc_result_ptr : Intrinsic<[llvm_anyptr_ty], [llvm_i32_ty]>; + //===-------------------------- Other Intrinsics --------------------------===// // def int_flt_rounds : Intrinsic<[llvm_i32_ty]>, @@ -539,6 +579,34 @@ def int_convertuu : Intrinsic<[llvm_anyint_ty], def int_clear_cache : Intrinsic<[], [llvm_ptr_ty, llvm_ptr_ty], [], "llvm.clear_cache">; +//===-------------------------- Masked Intrinsics -------------------------===// +// +def int_masked_store : Intrinsic<[], [llvm_anyvector_ty, LLVMPointerTo<0>, + llvm_i32_ty, + LLVMVectorSameWidth<0, llvm_i1_ty>], + [IntrReadWriteArgMem]>; + +def int_masked_load : Intrinsic<[llvm_anyvector_ty], + [LLVMPointerTo<0>, llvm_i32_ty, + LLVMVectorSameWidth<0, llvm_i1_ty>, LLVMMatchType<0>], + [IntrReadArgMem]>; + +def int_masked_gather: Intrinsic<[llvm_anyvector_ty], + [LLVMVectorOfPointersToElt<0>, llvm_i32_ty, + LLVMVectorSameWidth<0, llvm_i1_ty>, + LLVMMatchType<0>], + [IntrReadArgMem]>; + +def int_masked_scatter: Intrinsic<[], + [llvm_anyvector_ty, + LLVMVectorOfPointersToElt<0>, llvm_i32_ty, + LLVMVectorSameWidth<0, llvm_i1_ty>], + [IntrReadWriteArgMem]>; + +// Intrinsics to support bit sets. +def int_bitset_test : Intrinsic<[llvm_i1_ty], [llvm_ptr_ty, llvm_metadata_ty], + [IntrNoMem]>; + //===----------------------------------------------------------------------===// // Target-specific intrinsics //===----------------------------------------------------------------------===// @@ -552,3 +620,4 @@ include "llvm/IR/IntrinsicsHexagon.td" include "llvm/IR/IntrinsicsNVVM.td" include "llvm/IR/IntrinsicsMips.td" include "llvm/IR/IntrinsicsR600.td" +include "llvm/IR/IntrinsicsBPF.td" diff --git a/include/llvm/IR/IntrinsicsBPF.td b/include/llvm/IR/IntrinsicsBPF.td new file mode 100644 index 0000000..6b5110b --- /dev/null +++ b/include/llvm/IR/IntrinsicsBPF.td @@ -0,0 +1,22 @@ +//===- IntrinsicsBPF.td - Defines BPF intrinsics -----------*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines all of the BPF-specific intrinsics. +// +//===----------------------------------------------------------------------===// + +// Specialized loads from packet +let TargetPrefix = "bpf" in { // All intrinsics start with "llvm.bpf." + def int_bpf_load_byte : GCCBuiltin<"__builtin_bpf_load_byte">, + Intrinsic<[llvm_i64_ty], [llvm_ptr_ty, llvm_i64_ty], [IntrReadMem]>; + def int_bpf_load_half : GCCBuiltin<"__builtin_bpf_load_half">, + Intrinsic<[llvm_i64_ty], [llvm_ptr_ty, llvm_i64_ty], [IntrReadMem]>; + def int_bpf_load_word : GCCBuiltin<"__builtin_bpf_load_word">, + Intrinsic<[llvm_i64_ty], [llvm_ptr_ty, llvm_i64_ty], [IntrReadMem]>; +} diff --git a/include/llvm/IR/IntrinsicsHexagon.td b/include/llvm/IR/IntrinsicsHexagon.td index 8a88729..b566956 100644 --- a/include/llvm/IR/IntrinsicsHexagon.td +++ b/include/llvm/IR/IntrinsicsHexagon.td @@ -254,7 +254,7 @@ class Hexagon_qi_qiqi_Intrinsic // class Hexagon_qi_qiqiqi_Intrinsic : Hexagon_Intrinsic; // // DEF_FUNCTION_TYPE_2(SI_ftype_QIQI,BT_INT,BT_BOOL,BT_BOOL) -> @@ -434,7 +434,7 @@ class Hexagon_mem_memmemsisi_Intrinsic class Hexagon_sf_si_Intrinsic : Hexagon_Intrinsic; + [IntrNoMem, Throws]>; // // Hexagon_sf_df_Intrinsic // @@ -490,21 +490,21 @@ class Hexagon_si_df_Intrinsic class Hexagon_sf_sfsf_Intrinsic : Hexagon_Intrinsic; + [IntrNoMem, Throws]>; // -// Hexagon_qi_sfsf_Intrinsic +// Hexagon_si_sfsf_Intrinsic // -class Hexagon_qi_sfsf_Intrinsic +class Hexagon_si_sfsf_Intrinsic : Hexagon_Intrinsic; + [llvm_i32_ty], [llvm_float_ty, llvm_float_ty], + [IntrNoMem, Throws]>; // -// Hexagon_qi_sfsi_Intrinsic +// Hexagon_si_sfsi_Intrinsic // -class Hexagon_qi_sfsi_Intrinsic +class Hexagon_si_sfsi_Intrinsic : Hexagon_Intrinsic; + [llvm_i32_ty], [llvm_float_ty, llvm_i32_ty], + [IntrNoMem, Throws]>; // // Hexagon_qi_sfqi_Intrinsic // @@ -519,7 +519,7 @@ class Hexagon_sf_sfsfsf_Intrinsic : Hexagon_Intrinsic; + [IntrNoMem, Throws]>; // // Hexagon_sf_sfsfsfqi_Intrinsic // @@ -528,7 +528,7 @@ class Hexagon_sf_sfsfsfqi_Intrinsic [llvm_float_ty], [llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, Throws]>; // // Hexagon_di_dididi_Intrinsic // @@ -543,7 +543,7 @@ class Hexagon_di_dididisi_Intrinsic class Hexagon_df_si_Intrinsic : Hexagon_Intrinsic; + [IntrNoMem, Throws]>; // // Hexagon_df_di_Intrinsic // @@ -571,21 +571,21 @@ class Hexagon_df_df_Intrinsic class Hexagon_df_dfdf_Intrinsic : Hexagon_Intrinsic; + [IntrNoMem, Throws]>; // -// Hexagon_qi_dfdf_Intrinsic +// Hexagon_si_dfdf_Intrinsic // -class Hexagon_qi_dfdf_Intrinsic +class Hexagon_si_dfdf_Intrinsic : Hexagon_Intrinsic; + [llvm_i32_ty], [llvm_double_ty, llvm_double_ty], + [IntrNoMem, Throws]>; // -// Hexagon_qi_dfsi_Intrinsic +// Hexagon_si_dfsi_Intrinsic // -class Hexagon_qi_dfsi_Intrinsic +class Hexagon_si_dfsi_Intrinsic : Hexagon_Intrinsic; + [llvm_i32_ty], [llvm_double_ty, llvm_i32_ty], + [IntrNoMem, Throws]>; // // // Hexagon_df_dfdfdf_Intrinsic @@ -594,7 +594,7 @@ class Hexagon_df_dfdfdf_Intrinsic : Hexagon_Intrinsic; + [IntrNoMem, Throws]>; // // Hexagon_df_dfdfdf_Intrinsic // @@ -603,7 +603,7 @@ class Hexagon_df_dfdfdfqi_Intrinsic [llvm_double_ty], [llvm_double_ty, llvm_double_ty, llvm_double_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, Throws]>; // This one below will not be generated from iset.py. @@ -624,32 +624,32 @@ Hexagon_mem_memmemsisi_Intrinsic<"circ_ldd">; // BUILTIN_INFO(HEXAGON.C2_cmpeq,QI_ftype_SISI,2) // def int_hexagon_C2_cmpeq : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_cmpeq">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_cmpeq">; // // BUILTIN_INFO(HEXAGON.C2_cmpgt,QI_ftype_SISI,2) // def int_hexagon_C2_cmpgt : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_cmpgt">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_cmpgt">; // // BUILTIN_INFO(HEXAGON.C2_cmpgtu,QI_ftype_SISI,2) // def int_hexagon_C2_cmpgtu : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_cmpgtu">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_cmpgtu">; // // BUILTIN_INFO(HEXAGON.C2_cmpeqp,QI_ftype_DIDI,2) // def int_hexagon_C2_cmpeqp : -Hexagon_qi_didi_Intrinsic<"HEXAGON_C2_cmpeqp">; +Hexagon_si_didi_Intrinsic<"HEXAGON_C2_cmpeqp">; // // BUILTIN_INFO(HEXAGON.C2_cmpgtp,QI_ftype_DIDI,2) // def int_hexagon_C2_cmpgtp : -Hexagon_qi_didi_Intrinsic<"HEXAGON_C2_cmpgtp">; +Hexagon_si_didi_Intrinsic<"HEXAGON_C2_cmpgtp">; // // BUILTIN_INFO(HEXAGON.C2_cmpgtup,QI_ftype_DIDI,2) // def int_hexagon_C2_cmpgtup : -Hexagon_qi_didi_Intrinsic<"HEXAGON_C2_cmpgtup">; +Hexagon_si_didi_Intrinsic<"HEXAGON_C2_cmpgtup">; // // BUILTIN_INFO(HEXAGON.A4_rcmpeqi,SI_ftype_SISI,2) // @@ -674,182 +674,182 @@ Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_rcmpneq">; // BUILTIN_INFO(HEXAGON.C2_bitsset,QI_ftype_SISI,2) // def int_hexagon_C2_bitsset : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_bitsset">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_bitsset">; // // BUILTIN_INFO(HEXAGON.C2_bitsclr,QI_ftype_SISI,2) // def int_hexagon_C2_bitsclr : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_bitsclr">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_bitsclr">; // // BUILTIN_INFO(HEXAGON.C4_nbitsset,QI_ftype_SISI,2) // def int_hexagon_C4_nbitsset : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C4_nbitsset">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C4_nbitsset">; // // BUILTIN_INFO(HEXAGON.C4_nbitsclr,QI_ftype_SISI,2) // def int_hexagon_C4_nbitsclr : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C4_nbitsclr">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C4_nbitsclr">; // // BUILTIN_INFO(HEXAGON.C2_cmpeqi,QI_ftype_SISI,2) // def int_hexagon_C2_cmpeqi : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_cmpeqi">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_cmpeqi">; // // BUILTIN_INFO(HEXAGON.C2_cmpgti,QI_ftype_SISI,2) // def int_hexagon_C2_cmpgti : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_cmpgti">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_cmpgti">; // // BUILTIN_INFO(HEXAGON.C2_cmpgtui,QI_ftype_SISI,2) // def int_hexagon_C2_cmpgtui : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_cmpgtui">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_cmpgtui">; // // BUILTIN_INFO(HEXAGON.C2_cmpgei,QI_ftype_SISI,2) // def int_hexagon_C2_cmpgei : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_cmpgei">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_cmpgei">; // // BUILTIN_INFO(HEXAGON.C2_cmpgeui,QI_ftype_SISI,2) // def int_hexagon_C2_cmpgeui : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_cmpgeui">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_cmpgeui">; // // BUILTIN_INFO(HEXAGON.C2_cmplt,QI_ftype_SISI,2) // def int_hexagon_C2_cmplt : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_cmplt">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_cmplt">; // // BUILTIN_INFO(HEXAGON.C2_cmpltu,QI_ftype_SISI,2) // def int_hexagon_C2_cmpltu : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_cmpltu">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_cmpltu">; // // BUILTIN_INFO(HEXAGON.C2_bitsclri,QI_ftype_SISI,2) // def int_hexagon_C2_bitsclri : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C2_bitsclri">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_bitsclri">; // // BUILTIN_INFO(HEXAGON.C4_nbitsclri,QI_ftype_SISI,2) // def int_hexagon_C4_nbitsclri : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C4_nbitsclri">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C4_nbitsclri">; // // BUILTIN_INFO(HEXAGON.C4_cmpneqi,QI_ftype_SISI,2) // def int_hexagon_C4_cmpneqi : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C4_cmpneqi">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C4_cmpneqi">; // // BUILTIN_INFO(HEXAGON.C4_cmpltei,QI_ftype_SISI,2) // def int_hexagon_C4_cmpltei : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C4_cmpltei">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C4_cmpltei">; // // BUILTIN_INFO(HEXAGON.C4_cmplteui,QI_ftype_SISI,2) // def int_hexagon_C4_cmplteui : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C4_cmplteui">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C4_cmplteui">; // // BUILTIN_INFO(HEXAGON.C4_cmpneq,QI_ftype_SISI,2) // def int_hexagon_C4_cmpneq : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C4_cmpneq">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C4_cmpneq">; // // BUILTIN_INFO(HEXAGON.C4_cmplte,QI_ftype_SISI,2) // def int_hexagon_C4_cmplte : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C4_cmplte">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C4_cmplte">; // // BUILTIN_INFO(HEXAGON.C4_cmplteu,QI_ftype_SISI,2) // def int_hexagon_C4_cmplteu : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_C4_cmplteu">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C4_cmplteu">; // // BUILTIN_INFO(HEXAGON.C2_and,QI_ftype_QIQI,2) // def int_hexagon_C2_and : -Hexagon_qi_qiqi_Intrinsic<"HEXAGON_C2_and">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_and">; // // BUILTIN_INFO(HEXAGON.C2_or,QI_ftype_QIQI,2) // def int_hexagon_C2_or : -Hexagon_qi_qiqi_Intrinsic<"HEXAGON_C2_or">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_or">; // // BUILTIN_INFO(HEXAGON.C2_xor,QI_ftype_QIQI,2) // def int_hexagon_C2_xor : -Hexagon_qi_qiqi_Intrinsic<"HEXAGON_C2_xor">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_xor">; // // BUILTIN_INFO(HEXAGON.C2_andn,QI_ftype_QIQI,2) // def int_hexagon_C2_andn : -Hexagon_qi_qiqi_Intrinsic<"HEXAGON_C2_andn">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_andn">; // // BUILTIN_INFO(HEXAGON.C2_not,QI_ftype_QI,1) // def int_hexagon_C2_not : -Hexagon_qi_qi_Intrinsic<"HEXAGON_C2_not">; +Hexagon_si_si_Intrinsic<"HEXAGON_C2_not">; // // BUILTIN_INFO(HEXAGON.C2_orn,QI_ftype_QIQI,2) // def int_hexagon_C2_orn : -Hexagon_qi_qiqi_Intrinsic<"HEXAGON_C2_orn">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_C2_orn">; // // BUILTIN_INFO(HEXAGON.C4_and_and,QI_ftype_QIQIQI,3) // def int_hexagon_C4_and_and : -Hexagon_qi_qiqiqi_Intrinsic<"HEXAGON_C4_and_and">; +Hexagon_si_sisisi_Intrinsic<"HEXAGON_C4_and_and">; // // BUILTIN_INFO(HEXAGON.C4_and_or,QI_ftype_QIQIQI,3) // def int_hexagon_C4_and_or : -Hexagon_qi_qiqiqi_Intrinsic<"HEXAGON_C4_and_or">; +Hexagon_si_sisisi_Intrinsic<"HEXAGON_C4_and_or">; // // BUILTIN_INFO(HEXAGON.C4_or_and,QI_ftype_QIQIQI,3) // def int_hexagon_C4_or_and : -Hexagon_qi_qiqiqi_Intrinsic<"HEXAGON_C4_or_and">; +Hexagon_si_sisisi_Intrinsic<"HEXAGON_C4_or_and">; // // BUILTIN_INFO(HEXAGON.C4_or_or,QI_ftype_QIQIQI,3) // def int_hexagon_C4_or_or : -Hexagon_qi_qiqiqi_Intrinsic<"HEXAGON_C4_or_or">; +Hexagon_si_sisisi_Intrinsic<"HEXAGON_C4_or_or">; // // BUILTIN_INFO(HEXAGON.C4_and_andn,QI_ftype_QIQIQI,3) // def int_hexagon_C4_and_andn : -Hexagon_qi_qiqiqi_Intrinsic<"HEXAGON_C4_and_andn">; +Hexagon_si_sisisi_Intrinsic<"HEXAGON_C4_and_andn">; // // BUILTIN_INFO(HEXAGON.C4_and_orn,QI_ftype_QIQIQI,3) // def int_hexagon_C4_and_orn : -Hexagon_qi_qiqiqi_Intrinsic<"HEXAGON_C4_and_orn">; +Hexagon_si_sisisi_Intrinsic<"HEXAGON_C4_and_orn">; // // BUILTIN_INFO(HEXAGON.C4_or_andn,QI_ftype_QIQIQI,3) // def int_hexagon_C4_or_andn : -Hexagon_qi_qiqiqi_Intrinsic<"HEXAGON_C4_or_andn">; +Hexagon_si_sisisi_Intrinsic<"HEXAGON_C4_or_andn">; // // BUILTIN_INFO(HEXAGON.C4_or_orn,QI_ftype_QIQIQI,3) // def int_hexagon_C4_or_orn : -Hexagon_qi_qiqiqi_Intrinsic<"HEXAGON_C4_or_orn">; +Hexagon_si_sisisi_Intrinsic<"HEXAGON_C4_or_orn">; // // BUILTIN_INFO(HEXAGON.C2_pxfer_map,QI_ftype_QI,1) // def int_hexagon_C2_pxfer_map : -Hexagon_qi_qi_Intrinsic<"HEXAGON_C2_pxfer_map">; +Hexagon_si_qi_Intrinsic<"HEXAGON_C2_pxfer_map">; // // BUILTIN_INFO(HEXAGON.C2_any8,QI_ftype_QI,1) // def int_hexagon_C2_any8 : -Hexagon_qi_qi_Intrinsic<"HEXAGON_C2_any8">; +Hexagon_si_qi_Intrinsic<"HEXAGON_C2_any8">; // // BUILTIN_INFO(HEXAGON.C2_all8,QI_ftype_QI,1) // def int_hexagon_C2_all8 : -Hexagon_qi_qi_Intrinsic<"HEXAGON_C2_all8">; +Hexagon_si_qi_Intrinsic<"HEXAGON_C2_all8">; // // BUILTIN_INFO(HEXAGON.C2_vitpack,SI_ftype_QIQI,2) // @@ -889,167 +889,167 @@ Hexagon_di_qi_Intrinsic<"HEXAGON_C2_mask">; // BUILTIN_INFO(HEXAGON.A2_vcmpbeq,QI_ftype_DIDI,2) // def int_hexagon_A2_vcmpbeq : -Hexagon_qi_didi_Intrinsic<"HEXAGON_A2_vcmpbeq">; +Hexagon_si_didi_Intrinsic<"HEXAGON_A2_vcmpbeq">; // // BUILTIN_INFO(HEXAGON.A4_vcmpbeqi,QI_ftype_DISI,2) // def int_hexagon_A4_vcmpbeqi : -Hexagon_qi_disi_Intrinsic<"HEXAGON_A4_vcmpbeqi">; +Hexagon_si_disi_Intrinsic<"HEXAGON_A4_vcmpbeqi">; // // BUILTIN_INFO(HEXAGON.A4_vcmpbeq_any,QI_ftype_DIDI,2) // def int_hexagon_A4_vcmpbeq_any : -Hexagon_qi_didi_Intrinsic<"HEXAGON_A4_vcmpbeq_any">; +Hexagon_si_didi_Intrinsic<"HEXAGON_A4_vcmpbeq_any">; // // BUILTIN_INFO(HEXAGON.A2_vcmpbgtu,QI_ftype_DIDI,2) // def int_hexagon_A2_vcmpbgtu : -Hexagon_qi_didi_Intrinsic<"HEXAGON_A2_vcmpbgtu">; +Hexagon_si_didi_Intrinsic<"HEXAGON_A2_vcmpbgtu">; // // BUILTIN_INFO(HEXAGON.A4_vcmpbgtui,QI_ftype_DISI,2) // def int_hexagon_A4_vcmpbgtui : -Hexagon_qi_disi_Intrinsic<"HEXAGON_A4_vcmpbgtui">; +Hexagon_si_disi_Intrinsic<"HEXAGON_A4_vcmpbgtui">; // // BUILTIN_INFO(HEXAGON.A4_vcmpbgt,QI_ftype_DIDI,2) // def int_hexagon_A4_vcmpbgt : -Hexagon_qi_didi_Intrinsic<"HEXAGON_A4_vcmpbgt">; +Hexagon_si_didi_Intrinsic<"HEXAGON_A4_vcmpbgt">; // // BUILTIN_INFO(HEXAGON.A4_vcmpbgti,QI_ftype_DISI,2) // def int_hexagon_A4_vcmpbgti : -Hexagon_qi_disi_Intrinsic<"HEXAGON_A4_vcmpbgti">; +Hexagon_si_disi_Intrinsic<"HEXAGON_A4_vcmpbgti">; // // BUILTIN_INFO(HEXAGON.A4_cmpbeq,QI_ftype_SISI,2) // def int_hexagon_A4_cmpbeq : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmpbeq">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_cmpbeq">; // // BUILTIN_INFO(HEXAGON.A4_cmpbeqi,QI_ftype_SISI,2) // def int_hexagon_A4_cmpbeqi : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmpbeqi">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_cmpbeqi">; // // BUILTIN_INFO(HEXAGON.A4_cmpbgtu,QI_ftype_SISI,2) // def int_hexagon_A4_cmpbgtu : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmpbgtu">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_cmpbgtu">; // // BUILTIN_INFO(HEXAGON.A4_cmpbgtui,QI_ftype_SISI,2) // def int_hexagon_A4_cmpbgtui : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmpbgtui">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_cmpbgtui">; // // BUILTIN_INFO(HEXAGON.A4_cmpbgt,QI_ftype_SISI,2) // def int_hexagon_A4_cmpbgt : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmpbgt">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_cmpbgt">; // // BUILTIN_INFO(HEXAGON.A4_cmpbgti,QI_ftype_SISI,2) // def int_hexagon_A4_cmpbgti : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmpbgti">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_cmpbgti">; // // BUILTIN_INFO(HEXAGON.A2_vcmpheq,QI_ftype_DIDI,2) // def int_hexagon_A2_vcmpheq : -Hexagon_qi_didi_Intrinsic<"HEXAGON_A2_vcmpheq">; +Hexagon_si_didi_Intrinsic<"HEXAGON_A2_vcmpheq">; // // BUILTIN_INFO(HEXAGON.A2_vcmphgt,QI_ftype_DIDI,2) // def int_hexagon_A2_vcmphgt : -Hexagon_qi_didi_Intrinsic<"HEXAGON_A2_vcmphgt">; +Hexagon_si_didi_Intrinsic<"HEXAGON_A2_vcmphgt">; // // BUILTIN_INFO(HEXAGON.A2_vcmphgtu,QI_ftype_DIDI,2) // def int_hexagon_A2_vcmphgtu : -Hexagon_qi_didi_Intrinsic<"HEXAGON_A2_vcmphgtu">; +Hexagon_si_didi_Intrinsic<"HEXAGON_A2_vcmphgtu">; // // BUILTIN_INFO(HEXAGON.A4_vcmpheqi,QI_ftype_DISI,2) // def int_hexagon_A4_vcmpheqi : -Hexagon_qi_disi_Intrinsic<"HEXAGON_A4_vcmpheqi">; +Hexagon_si_disi_Intrinsic<"HEXAGON_A4_vcmpheqi">; // // BUILTIN_INFO(HEXAGON.A4_vcmphgti,QI_ftype_DISI,2) // def int_hexagon_A4_vcmphgti : -Hexagon_qi_disi_Intrinsic<"HEXAGON_A4_vcmphgti">; +Hexagon_si_disi_Intrinsic<"HEXAGON_A4_vcmphgti">; // // BUILTIN_INFO(HEXAGON.A4_vcmphgtui,QI_ftype_DISI,2) // def int_hexagon_A4_vcmphgtui : -Hexagon_qi_disi_Intrinsic<"HEXAGON_A4_vcmphgtui">; +Hexagon_si_disi_Intrinsic<"HEXAGON_A4_vcmphgtui">; // // BUILTIN_INFO(HEXAGON.A4_cmpheq,QI_ftype_SISI,2) // def int_hexagon_A4_cmpheq : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmpheq">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_cmpheq">; // // BUILTIN_INFO(HEXAGON.A4_cmphgt,QI_ftype_SISI,2) // def int_hexagon_A4_cmphgt : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmphgt">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_cmphgt">; // // BUILTIN_INFO(HEXAGON.A4_cmphgtu,QI_ftype_SISI,2) // def int_hexagon_A4_cmphgtu : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmphgtu">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_cmphgtu">; // // BUILTIN_INFO(HEXAGON.A4_cmpheqi,QI_ftype_SISI,2) // def int_hexagon_A4_cmpheqi : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmpheqi">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_cmpheqi">; // // BUILTIN_INFO(HEXAGON.A4_cmphgti,QI_ftype_SISI,2) // def int_hexagon_A4_cmphgti : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmphgti">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_cmphgti">; // // BUILTIN_INFO(HEXAGON.A4_cmphgtui,QI_ftype_SISI,2) // def int_hexagon_A4_cmphgtui : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_A4_cmphgtui">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_A4_cmphgtui">; // // BUILTIN_INFO(HEXAGON.A2_vcmpweq,QI_ftype_DIDI,2) // def int_hexagon_A2_vcmpweq : -Hexagon_qi_didi_Intrinsic<"HEXAGON_A2_vcmpweq">; +Hexagon_si_didi_Intrinsic<"HEXAGON_A2_vcmpweq">; // // BUILTIN_INFO(HEXAGON.A2_vcmpwgt,QI_ftype_DIDI,2) // def int_hexagon_A2_vcmpwgt : -Hexagon_qi_didi_Intrinsic<"HEXAGON_A2_vcmpwgt">; +Hexagon_si_didi_Intrinsic<"HEXAGON_A2_vcmpwgt">; // // BUILTIN_INFO(HEXAGON.A2_vcmpwgtu,QI_ftype_DIDI,2) // def int_hexagon_A2_vcmpwgtu : -Hexagon_qi_didi_Intrinsic<"HEXAGON_A2_vcmpwgtu">; +Hexagon_si_didi_Intrinsic<"HEXAGON_A2_vcmpwgtu">; // // BUILTIN_INFO(HEXAGON.A4_vcmpweqi,QI_ftype_DISI,2) // def int_hexagon_A4_vcmpweqi : -Hexagon_qi_disi_Intrinsic<"HEXAGON_A4_vcmpweqi">; +Hexagon_si_disi_Intrinsic<"HEXAGON_A4_vcmpweqi">; // // BUILTIN_INFO(HEXAGON.A4_vcmpwgti,QI_ftype_DISI,2) // def int_hexagon_A4_vcmpwgti : -Hexagon_qi_disi_Intrinsic<"HEXAGON_A4_vcmpwgti">; +Hexagon_si_disi_Intrinsic<"HEXAGON_A4_vcmpwgti">; // // BUILTIN_INFO(HEXAGON.A4_vcmpwgtui,QI_ftype_DISI,2) // def int_hexagon_A4_vcmpwgtui : -Hexagon_qi_disi_Intrinsic<"HEXAGON_A4_vcmpwgtui">; +Hexagon_si_disi_Intrinsic<"HEXAGON_A4_vcmpwgtui">; // // BUILTIN_INFO(HEXAGON.A4_boundscheck,QI_ftype_SIDI,2) // def int_hexagon_A4_boundscheck : -Hexagon_qi_sidi_Intrinsic<"HEXAGON_A4_boundscheck">; +Hexagon_si_sidi_Intrinsic<"HEXAGON_A4_boundscheck">; // // BUILTIN_INFO(HEXAGON.A4_tlbmatch,QI_ftype_DISI,2) // def int_hexagon_A4_tlbmatch : -Hexagon_qi_disi_Intrinsic<"HEXAGON_A4_tlbmatch">; +Hexagon_si_disi_Intrinsic<"HEXAGON_A4_tlbmatch">; // // BUILTIN_INFO(HEXAGON.C2_tfrpr,SI_ftype_QI,1) // @@ -1059,17 +1059,17 @@ Hexagon_si_qi_Intrinsic<"HEXAGON_C2_tfrpr">; // BUILTIN_INFO(HEXAGON.C2_tfrrp,QI_ftype_SI,1) // def int_hexagon_C2_tfrrp : -Hexagon_qi_si_Intrinsic<"HEXAGON_C2_tfrrp">; +Hexagon_si_si_Intrinsic<"HEXAGON_C2_tfrrp">; // // BUILTIN_INFO(HEXAGON.C4_fastcorner9,QI_ftype_QIQI,2) // def int_hexagon_C4_fastcorner9 : -Hexagon_qi_qiqi_Intrinsic<"HEXAGON_C4_fastcorner9">; +Hexagon_si_qiqi_Intrinsic<"HEXAGON_C4_fastcorner9">; // // BUILTIN_INFO(HEXAGON.C4_fastcorner9_not,QI_ftype_QIQI,2) // def int_hexagon_C4_fastcorner9_not : -Hexagon_qi_qiqi_Intrinsic<"HEXAGON_C4_fastcorner9_not">; +Hexagon_si_qiqi_Intrinsic<"HEXAGON_C4_fastcorner9_not">; // // BUILTIN_INFO(HEXAGON.M2_mpy_acc_hh_s0,SI_ftype_SISISI,3) // @@ -2849,7 +2849,7 @@ Hexagon_di_di_Intrinsic<"HEXAGON_A2_tfrp">; // BUILTIN_INFO(HEXAGON.A2_tfrpi,DI_ftype_SI,1) // def int_hexagon_A2_tfrpi : -Hexagon_di_si_Intrinsic<"HEXAGON_A2_tfrpi">; +Hexagon_di_di_Intrinsic<"HEXAGON_A2_tfrpi">; // // BUILTIN_INFO(HEXAGON.A2_zxtb,SI_ftype_SI,1) // @@ -3609,22 +3609,22 @@ Hexagon_sf_sfsfsf_Intrinsic<"HEXAGON_F2_sffms_lib">; // BUILTIN_INFO(HEXAGON.F2_sfcmpeq,QI_ftype_SFSF,2) // def int_hexagon_F2_sfcmpeq : -Hexagon_qi_sfsf_Intrinsic<"HEXAGON_F2_sfcmpeq">; +Hexagon_si_sfsf_Intrinsic<"HEXAGON_F2_sfcmpeq">; // // BUILTIN_INFO(HEXAGON.F2_sfcmpgt,QI_ftype_SFSF,2) // def int_hexagon_F2_sfcmpgt : -Hexagon_qi_sfsf_Intrinsic<"HEXAGON_F2_sfcmpgt">; +Hexagon_si_sfsf_Intrinsic<"HEXAGON_F2_sfcmpgt">; // // BUILTIN_INFO(HEXAGON.F2_sfcmpge,QI_ftype_SFSF,2) // def int_hexagon_F2_sfcmpge : -Hexagon_qi_sfsf_Intrinsic<"HEXAGON_F2_sfcmpge">; +Hexagon_si_sfsf_Intrinsic<"HEXAGON_F2_sfcmpge">; // // BUILTIN_INFO(HEXAGON.F2_sfcmpuo,QI_ftype_SFSF,2) // def int_hexagon_F2_sfcmpuo : -Hexagon_qi_sfsf_Intrinsic<"HEXAGON_F2_sfcmpuo">; +Hexagon_si_sfsf_Intrinsic<"HEXAGON_F2_sfcmpuo">; // // BUILTIN_INFO(HEXAGON.F2_sfmax,SF_ftype_SFSF,2) // @@ -3639,7 +3639,7 @@ Hexagon_sf_sfsf_Intrinsic<"HEXAGON_F2_sfmin">; // BUILTIN_INFO(HEXAGON.F2_sfclass,QI_ftype_SFSI,2) // def int_hexagon_F2_sfclass : -Hexagon_qi_sfsi_Intrinsic<"HEXAGON_F2_sfclass">; +Hexagon_si_sfsi_Intrinsic<"HEXAGON_F2_sfclass">; // // BUILTIN_INFO(HEXAGON.F2_sfimm_p,SF_ftype_SI,1) // @@ -3666,80 +3666,30 @@ Hexagon_sf_sfsf_Intrinsic<"HEXAGON_F2_sffixupd">; def int_hexagon_F2_sffixupr : Hexagon_sf_sf_Intrinsic<"HEXAGON_F2_sffixupr">; // -// BUILTIN_INFO(HEXAGON.F2_dfadd,DF_ftype_DFDF,2) -// -def int_hexagon_F2_dfadd : -Hexagon_df_dfdf_Intrinsic<"HEXAGON_F2_dfadd">; -// -// BUILTIN_INFO(HEXAGON.F2_dfsub,DF_ftype_DFDF,2) -// -def int_hexagon_F2_dfsub : -Hexagon_df_dfdf_Intrinsic<"HEXAGON_F2_dfsub">; -// -// BUILTIN_INFO(HEXAGON.F2_dfmpy,DF_ftype_DFDF,2) -// -def int_hexagon_F2_dfmpy : -Hexagon_df_dfdf_Intrinsic<"HEXAGON_F2_dfmpy">; -// -// BUILTIN_INFO(HEXAGON.F2_dffma,DF_ftype_DFDFDF,3) -// -def int_hexagon_F2_dffma : -Hexagon_df_dfdfdf_Intrinsic<"HEXAGON_F2_dffma">; -// -// BUILTIN_INFO(HEXAGON.F2_dffms,DF_ftype_DFDFDF,3) -// -def int_hexagon_F2_dffms : -Hexagon_df_dfdfdf_Intrinsic<"HEXAGON_F2_dffms">; -// -// BUILTIN_INFO(HEXAGON.F2_dffma_lib,DF_ftype_DFDFDF,3) -// -def int_hexagon_F2_dffma_lib : -Hexagon_df_dfdfdf_Intrinsic<"HEXAGON_F2_dffma_lib">; -// -// BUILTIN_INFO(HEXAGON.F2_dffms_lib,DF_ftype_DFDFDF,3) -// -def int_hexagon_F2_dffms_lib : -Hexagon_df_dfdfdf_Intrinsic<"HEXAGON_F2_dffms_lib">; -// -// BUILTIN_INFO(HEXAGON.F2_dffma_sc,DF_ftype_DFDFDFQI,4) -// -def int_hexagon_F2_dffma_sc : -Hexagon_df_dfdfdfqi_Intrinsic<"HEXAGON_F2_dffma_sc">; -// -// BUILTIN_INFO(HEXAGON.F2_dfmax,DF_ftype_DFDF,2) -// -def int_hexagon_F2_dfmax : -Hexagon_df_dfdf_Intrinsic<"HEXAGON_F2_dfmax">; -// -// BUILTIN_INFO(HEXAGON.F2_dfmin,DF_ftype_DFDF,2) -// -def int_hexagon_F2_dfmin : -Hexagon_df_dfdf_Intrinsic<"HEXAGON_F2_dfmin">; -// // BUILTIN_INFO(HEXAGON.F2_dfcmpeq,QI_ftype_DFDF,2) // def int_hexagon_F2_dfcmpeq : -Hexagon_qi_dfdf_Intrinsic<"HEXAGON_F2_dfcmpeq">; +Hexagon_si_dfdf_Intrinsic<"HEXAGON_F2_dfcmpeq">; // // BUILTIN_INFO(HEXAGON.F2_dfcmpgt,QI_ftype_DFDF,2) // def int_hexagon_F2_dfcmpgt : -Hexagon_qi_dfdf_Intrinsic<"HEXAGON_F2_dfcmpgt">; +Hexagon_si_dfdf_Intrinsic<"HEXAGON_F2_dfcmpgt">; // // BUILTIN_INFO(HEXAGON.F2_dfcmpge,QI_ftype_DFDF,2) // def int_hexagon_F2_dfcmpge : -Hexagon_qi_dfdf_Intrinsic<"HEXAGON_F2_dfcmpge">; +Hexagon_si_dfdf_Intrinsic<"HEXAGON_F2_dfcmpge">; // // BUILTIN_INFO(HEXAGON.F2_dfcmpuo,QI_ftype_DFDF,2) // def int_hexagon_F2_dfcmpuo : -Hexagon_qi_dfdf_Intrinsic<"HEXAGON_F2_dfcmpuo">; +Hexagon_si_dfdf_Intrinsic<"HEXAGON_F2_dfcmpuo">; // // BUILTIN_INFO(HEXAGON.F2_dfclass,QI_ftype_DFSI,2) // def int_hexagon_F2_dfclass : -Hexagon_qi_dfsi_Intrinsic<"HEXAGON_F2_dfclass">; +Hexagon_si_dfsi_Intrinsic<"HEXAGON_F2_dfclass">; // // BUILTIN_INFO(HEXAGON.F2_dfimm_p,DF_ftype_SI,1) // @@ -3751,21 +3701,6 @@ Hexagon_df_si_Intrinsic<"HEXAGON_F2_dfimm_p">; def int_hexagon_F2_dfimm_n : Hexagon_df_si_Intrinsic<"HEXAGON_F2_dfimm_n">; // -// BUILTIN_INFO(HEXAGON.F2_dffixupn,DF_ftype_DFDF,2) -// -def int_hexagon_F2_dffixupn : -Hexagon_df_dfdf_Intrinsic<"HEXAGON_F2_dffixupn">; -// -// BUILTIN_INFO(HEXAGON.F2_dffixupd,DF_ftype_DFDF,2) -// -def int_hexagon_F2_dffixupd : -Hexagon_df_dfdf_Intrinsic<"HEXAGON_F2_dffixupd">; -// -// BUILTIN_INFO(HEXAGON.F2_dffixupr,DF_ftype_DF,1) -// -def int_hexagon_F2_dffixupr : -Hexagon_df_df_Intrinsic<"HEXAGON_F2_dffixupr">; -// // BUILTIN_INFO(HEXAGON.F2_conv_sf2df,DF_ftype_SF,1) // def int_hexagon_F2_conv_sf2df : @@ -4494,12 +4429,12 @@ Hexagon_di_didi_Intrinsic<"HEXAGON_S2_extractup_rp">; // BUILTIN_INFO(HEXAGON.S2_tstbit_i,QI_ftype_SISI,2) // def int_hexagon_S2_tstbit_i : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_S2_tstbit_i">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_S2_tstbit_i">; // // BUILTIN_INFO(HEXAGON.S4_ntstbit_i,QI_ftype_SISI,2) // def int_hexagon_S4_ntstbit_i : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_S4_ntstbit_i">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_S4_ntstbit_i">; // // BUILTIN_INFO(HEXAGON.S2_setbit_i,SI_ftype_SISI,2) // @@ -4519,12 +4454,12 @@ Hexagon_si_sisi_Intrinsic<"HEXAGON_S2_clrbit_i">; // BUILTIN_INFO(HEXAGON.S2_tstbit_r,QI_ftype_SISI,2) // def int_hexagon_S2_tstbit_r : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_S2_tstbit_r">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_S2_tstbit_r">; // // BUILTIN_INFO(HEXAGON.S4_ntstbit_r,QI_ftype_SISI,2) // def int_hexagon_S4_ntstbit_r : -Hexagon_qi_sisi_Intrinsic<"HEXAGON_S4_ntstbit_r">; +Hexagon_si_sisi_Intrinsic<"HEXAGON_S4_ntstbit_r">; // // BUILTIN_INFO(HEXAGON.S2_setbit_r,SI_ftype_SISI,2) // @@ -4875,3 +4810,21 @@ Hexagon_di_di_Intrinsic<"HEXAGON_S2_interleave">; // def int_hexagon_S2_deinterleave : Hexagon_di_di_Intrinsic<"HEXAGON_S2_deinterleave">; + +def llvm_ptr32_ty : LLVMPointerType; +def llvm_ptr64_ty : LLVMPointerType; + +// Mark locked loads as read/write to prevent any accidental reordering. +def int_hexagon_L2_loadw_locked : +Hexagon_Intrinsic<"HEXAGON_L2_loadw_locked", [llvm_i32_ty], [llvm_ptr32_ty], + [IntrReadWriteArgMem, NoCapture<0>]>; +def int_hexagon_L4_loadd_locked : +Hexagon_Intrinsic<"HEXAGON_L4_loadd_locked", [llvm_i64_ty], [llvm_ptr64_ty], + [IntrReadWriteArgMem, NoCapture<0>]>; + +def int_hexagon_S2_storew_locked : +Hexagon_Intrinsic<"HEXAGON_S2_storew_locked", [llvm_i32_ty], + [llvm_ptr32_ty, llvm_i32_ty], [IntrReadWriteArgMem, NoCapture<0>]>; +def int_hexagon_S4_stored_locked : +Hexagon_Intrinsic<"HEXAGON_S4_stored_locked", [llvm_i32_ty], + [llvm_ptr64_ty, llvm_i64_ty], [IntrReadWriteArgMem, NoCapture<0>]>; diff --git a/include/llvm/IR/IntrinsicsPowerPC.td b/include/llvm/IR/IntrinsicsPowerPC.td index 5cdabde..110d55d 100644 --- a/include/llvm/IR/IntrinsicsPowerPC.td +++ b/include/llvm/IR/IntrinsicsPowerPC.td @@ -542,3 +542,180 @@ def int_ppc_vsx_xsmindp : PowerPC_VSX_Sca_DDD_Intrinsic<"xsmindp">; def int_ppc_vsx_xvdivdp : PowerPC_VSX_Vec_DDD_Intrinsic<"xvdivdp">; def int_ppc_vsx_xvdivsp : PowerPC_VSX_Vec_FFF_Intrinsic<"xvdivsp">; } + +//===----------------------------------------------------------------------===// +// PowerPC QPX Intrinsics. +// + +let TargetPrefix = "ppc" in { // All PPC intrinsics start with "llvm.ppc.". + /// PowerPC_QPX_Intrinsic - Base class for all QPX intrinsics. + class PowerPC_QPX_Intrinsic ret_types, + list param_types, + list properties> + : GCCBuiltin, + Intrinsic; +} + +//===----------------------------------------------------------------------===// +// PowerPC QPX Intrinsic Class Definitions. +// + +/// PowerPC_QPX_FF_Intrinsic - A PowerPC intrinsic that takes one v4f64 +/// vector and returns one. These intrinsics have no side effects. +class PowerPC_QPX_FF_Intrinsic + : PowerPC_QPX_Intrinsic; + +/// PowerPC_QPX_FFF_Intrinsic - A PowerPC intrinsic that takes two v4f64 +/// vectors and returns one. These intrinsics have no side effects. +class PowerPC_QPX_FFF_Intrinsic + : PowerPC_QPX_Intrinsic; + +/// PowerPC_QPX_FFFF_Intrinsic - A PowerPC intrinsic that takes three v4f64 +/// vectors and returns one. These intrinsics have no side effects. +class PowerPC_QPX_FFFF_Intrinsic + : PowerPC_QPX_Intrinsic; + +/// PowerPC_QPX_Load_Intrinsic - A PowerPC intrinsic that takes a pointer +/// and returns a v4f64. +class PowerPC_QPX_Load_Intrinsic + : PowerPC_QPX_Intrinsic; + +/// PowerPC_QPX_LoadPerm_Intrinsic - A PowerPC intrinsic that takes a pointer +/// and returns a v4f64 permutation. +class PowerPC_QPX_LoadPerm_Intrinsic + : PowerPC_QPX_Intrinsic; + +/// PowerPC_QPX_Store_Intrinsic - A PowerPC intrinsic that takes a pointer +/// and stores a v4f64. +class PowerPC_QPX_Store_Intrinsic + : PowerPC_QPX_Intrinsic; + +//===----------------------------------------------------------------------===// +// PowerPC QPX Intrinsic Definitions. + +let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.". + // Add Instructions + def int_ppc_qpx_qvfadd : PowerPC_QPX_FFF_Intrinsic<"qvfadd">; + def int_ppc_qpx_qvfadds : PowerPC_QPX_FFF_Intrinsic<"qvfadds">; + def int_ppc_qpx_qvfsub : PowerPC_QPX_FFF_Intrinsic<"qvfsub">; + def int_ppc_qpx_qvfsubs : PowerPC_QPX_FFF_Intrinsic<"qvfsubs">; + + // Estimate Instructions + def int_ppc_qpx_qvfre : PowerPC_QPX_FF_Intrinsic<"qvfre">; + def int_ppc_qpx_qvfres : PowerPC_QPX_FF_Intrinsic<"qvfres">; + def int_ppc_qpx_qvfrsqrte : PowerPC_QPX_FF_Intrinsic<"qvfrsqrte">; + def int_ppc_qpx_qvfrsqrtes : PowerPC_QPX_FF_Intrinsic<"qvfrsqrtes">; + + // Multiply Instructions + def int_ppc_qpx_qvfmul : PowerPC_QPX_FFF_Intrinsic<"qvfmul">; + def int_ppc_qpx_qvfmuls : PowerPC_QPX_FFF_Intrinsic<"qvfmuls">; + def int_ppc_qpx_qvfxmul : PowerPC_QPX_FFF_Intrinsic<"qvfxmul">; + def int_ppc_qpx_qvfxmuls : PowerPC_QPX_FFF_Intrinsic<"qvfxmuls">; + + // Multiply-add instructions + def int_ppc_qpx_qvfmadd : PowerPC_QPX_FFFF_Intrinsic<"qvfmadd">; + def int_ppc_qpx_qvfmadds : PowerPC_QPX_FFFF_Intrinsic<"qvfmadds">; + def int_ppc_qpx_qvfnmadd : PowerPC_QPX_FFFF_Intrinsic<"qvfnmadd">; + def int_ppc_qpx_qvfnmadds : PowerPC_QPX_FFFF_Intrinsic<"qvfnmadds">; + def int_ppc_qpx_qvfmsub : PowerPC_QPX_FFFF_Intrinsic<"qvfmsub">; + def int_ppc_qpx_qvfmsubs : PowerPC_QPX_FFFF_Intrinsic<"qvfmsubs">; + def int_ppc_qpx_qvfnmsub : PowerPC_QPX_FFFF_Intrinsic<"qvfnmsub">; + def int_ppc_qpx_qvfnmsubs : PowerPC_QPX_FFFF_Intrinsic<"qvfnmsubs">; + def int_ppc_qpx_qvfxmadd : PowerPC_QPX_FFFF_Intrinsic<"qvfxmadd">; + def int_ppc_qpx_qvfxmadds : PowerPC_QPX_FFFF_Intrinsic<"qvfxmadds">; + def int_ppc_qpx_qvfxxnpmadd : PowerPC_QPX_FFFF_Intrinsic<"qvfxxnpmadd">; + def int_ppc_qpx_qvfxxnpmadds : PowerPC_QPX_FFFF_Intrinsic<"qvfxxnpmadds">; + def int_ppc_qpx_qvfxxcpnmadd : PowerPC_QPX_FFFF_Intrinsic<"qvfxxcpnmadd">; + def int_ppc_qpx_qvfxxcpnmadds : PowerPC_QPX_FFFF_Intrinsic<"qvfxxcpnmadds">; + def int_ppc_qpx_qvfxxmadd : PowerPC_QPX_FFFF_Intrinsic<"qvfxxmadd">; + def int_ppc_qpx_qvfxxmadds : PowerPC_QPX_FFFF_Intrinsic<"qvfxxmadds">; + + // Select Instruction + def int_ppc_qpx_qvfsel : PowerPC_QPX_FFFF_Intrinsic<"qvfsel">; + + // Permute Instruction + def int_ppc_qpx_qvfperm : PowerPC_QPX_FFFF_Intrinsic<"qvfperm">; + + // Convert and Round Instructions + def int_ppc_qpx_qvfctid : PowerPC_QPX_FF_Intrinsic<"qvfctid">; + def int_ppc_qpx_qvfctidu : PowerPC_QPX_FF_Intrinsic<"qvfctidu">; + def int_ppc_qpx_qvfctidz : PowerPC_QPX_FF_Intrinsic<"qvfctidz">; + def int_ppc_qpx_qvfctiduz : PowerPC_QPX_FF_Intrinsic<"qvfctiduz">; + def int_ppc_qpx_qvfctiw : PowerPC_QPX_FF_Intrinsic<"qvfctiw">; + def int_ppc_qpx_qvfctiwu : PowerPC_QPX_FF_Intrinsic<"qvfctiwu">; + def int_ppc_qpx_qvfctiwz : PowerPC_QPX_FF_Intrinsic<"qvfctiwz">; + def int_ppc_qpx_qvfctiwuz : PowerPC_QPX_FF_Intrinsic<"qvfctiwuz">; + def int_ppc_qpx_qvfcfid : PowerPC_QPX_FF_Intrinsic<"qvfcfid">; + def int_ppc_qpx_qvfcfidu : PowerPC_QPX_FF_Intrinsic<"qvfcfidu">; + def int_ppc_qpx_qvfcfids : PowerPC_QPX_FF_Intrinsic<"qvfcfids">; + def int_ppc_qpx_qvfcfidus : PowerPC_QPX_FF_Intrinsic<"qvfcfidus">; + def int_ppc_qpx_qvfrsp : PowerPC_QPX_FF_Intrinsic<"qvfrsp">; + def int_ppc_qpx_qvfriz : PowerPC_QPX_FF_Intrinsic<"qvfriz">; + def int_ppc_qpx_qvfrin : PowerPC_QPX_FF_Intrinsic<"qvfrin">; + def int_ppc_qpx_qvfrip : PowerPC_QPX_FF_Intrinsic<"qvfrip">; + def int_ppc_qpx_qvfrim : PowerPC_QPX_FF_Intrinsic<"qvfrim">; + + // Move Instructions + def int_ppc_qpx_qvfneg : PowerPC_QPX_FF_Intrinsic<"qvfneg">; + def int_ppc_qpx_qvfabs : PowerPC_QPX_FF_Intrinsic<"qvfabs">; + def int_ppc_qpx_qvfnabs : PowerPC_QPX_FF_Intrinsic<"qvfnabs">; + def int_ppc_qpx_qvfcpsgn : PowerPC_QPX_FFF_Intrinsic<"qvfcpsgn">; + + // Compare Instructions + def int_ppc_qpx_qvftstnan : PowerPC_QPX_FFF_Intrinsic<"qvftstnan">; + def int_ppc_qpx_qvfcmplt : PowerPC_QPX_FFF_Intrinsic<"qvfcmplt">; + def int_ppc_qpx_qvfcmpgt : PowerPC_QPX_FFF_Intrinsic<"qvfcmpgt">; + def int_ppc_qpx_qvfcmpeq : PowerPC_QPX_FFF_Intrinsic<"qvfcmpeq">; + + // Load instructions + def int_ppc_qpx_qvlfd : PowerPC_QPX_Load_Intrinsic<"qvlfd">; + def int_ppc_qpx_qvlfda : PowerPC_QPX_Load_Intrinsic<"qvlfda">; + def int_ppc_qpx_qvlfs : PowerPC_QPX_Load_Intrinsic<"qvlfs">; + def int_ppc_qpx_qvlfsa : PowerPC_QPX_Load_Intrinsic<"qvlfsa">; + + def int_ppc_qpx_qvlfcda : PowerPC_QPX_Load_Intrinsic<"qvlfcda">; + def int_ppc_qpx_qvlfcd : PowerPC_QPX_Load_Intrinsic<"qvlfcd">; + def int_ppc_qpx_qvlfcsa : PowerPC_QPX_Load_Intrinsic<"qvlfcsa">; + def int_ppc_qpx_qvlfcs : PowerPC_QPX_Load_Intrinsic<"qvlfcs">; + def int_ppc_qpx_qvlfiwaa : PowerPC_QPX_Load_Intrinsic<"qvlfiwaa">; + def int_ppc_qpx_qvlfiwa : PowerPC_QPX_Load_Intrinsic<"qvlfiwa">; + def int_ppc_qpx_qvlfiwza : PowerPC_QPX_Load_Intrinsic<"qvlfiwza">; + def int_ppc_qpx_qvlfiwz : PowerPC_QPX_Load_Intrinsic<"qvlfiwz">; + + def int_ppc_qpx_qvlpcld : PowerPC_QPX_LoadPerm_Intrinsic<"qvlpcld">; + def int_ppc_qpx_qvlpcls : PowerPC_QPX_LoadPerm_Intrinsic<"qvlpcls">; + def int_ppc_qpx_qvlpcrd : PowerPC_QPX_LoadPerm_Intrinsic<"qvlpcrd">; + def int_ppc_qpx_qvlpcrs : PowerPC_QPX_LoadPerm_Intrinsic<"qvlpcrs">; + + // Store instructions + def int_ppc_qpx_qvstfd : PowerPC_QPX_Store_Intrinsic<"qvstfd">; + def int_ppc_qpx_qvstfda : PowerPC_QPX_Store_Intrinsic<"qvstfda">; + def int_ppc_qpx_qvstfs : PowerPC_QPX_Store_Intrinsic<"qvstfs">; + def int_ppc_qpx_qvstfsa : PowerPC_QPX_Store_Intrinsic<"qvstfsa">; + + def int_ppc_qpx_qvstfcda : PowerPC_QPX_Store_Intrinsic<"qvstfcda">; + def int_ppc_qpx_qvstfcd : PowerPC_QPX_Store_Intrinsic<"qvstfcd">; + def int_ppc_qpx_qvstfcsa : PowerPC_QPX_Store_Intrinsic<"qvstfcsa">; + def int_ppc_qpx_qvstfcs : PowerPC_QPX_Store_Intrinsic<"qvstfcs">; + def int_ppc_qpx_qvstfiwa : PowerPC_QPX_Store_Intrinsic<"qvstfiwa">; + def int_ppc_qpx_qvstfiw : PowerPC_QPX_Store_Intrinsic<"qvstfiw">; + + // Logical and permutation formation + def int_ppc_qpx_qvflogical : PowerPC_QPX_Intrinsic<"qvflogical", + [llvm_v4f64_ty], + [llvm_v4f64_ty, llvm_v4f64_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_ppc_qpx_qvgpci : PowerPC_QPX_Intrinsic<"qvgpci", + [llvm_v4f64_ty], [llvm_i32_ty], [IntrNoMem]>; +} + diff --git a/include/llvm/IR/IntrinsicsR600.td b/include/llvm/IR/IntrinsicsR600.td index d99c42d..5055667 100644 --- a/include/llvm/IR/IntrinsicsR600.td +++ b/include/llvm/IR/IntrinsicsR600.td @@ -76,6 +76,9 @@ def int_AMDGPU_rsq_clamped : GCCBuiltin<"__builtin_amdgpu_rsq_clamped">, def int_AMDGPU_ldexp : GCCBuiltin<"__builtin_amdgpu_ldexp">, Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, llvm_i32_ty], [IntrNoMem]>; +def int_AMDGPU_class : GCCBuiltin<"__builtin_amdgpu_class">, + Intrinsic<[llvm_i1_ty], [llvm_anyfloat_ty, llvm_i32_ty], [IntrNoMem]>; + def int_AMDGPU_read_workdim : AMDGPUReadPreloadRegisterIntrinsic < "__builtin_amdgpu_read_workdim">; diff --git a/include/llvm/IR/IntrinsicsX86.td b/include/llvm/IR/IntrinsicsX86.td index 59ff946..60deb32 100644 --- a/include/llvm/IR/IntrinsicsX86.td +++ b/include/llvm/IR/IntrinsicsX86.td @@ -453,19 +453,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_sse2_psrai_d : GCCBuiltin<"__builtin_ia32_psradi128">, Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; - - def int_x86_sse2_psll_dq : GCCBuiltin<"__builtin_ia32_pslldqi128">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_sse2_psrl_dq : GCCBuiltin<"__builtin_ia32_psrldqi128">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_sse2_psll_dq_bs : GCCBuiltin<"__builtin_ia32_pslldqi128_byteshift">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_sse2_psrl_dq_bs : GCCBuiltin<"__builtin_ia32_psrldqi128_byteshift">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, - llvm_i32_ty], [IntrNoMem]>; } // Conversion ops @@ -1363,6 +1350,12 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_avx512_mask_loadu_pd_512 : GCCBuiltin<"__builtin_ia32_loadupd512_mask">, Intrinsic<[llvm_v8f64_ty], [llvm_ptr_ty, llvm_v8f64_ty, llvm_i8_ty], [IntrReadArgMem]>; + def int_x86_avx512_mask_load_ps_512 : GCCBuiltin<"__builtin_ia32_loadaps512_mask">, + Intrinsic<[llvm_v16f32_ty], [llvm_ptr_ty, llvm_v16f32_ty, llvm_i16_ty], + [IntrReadArgMem]>; + def int_x86_avx512_mask_load_pd_512 : GCCBuiltin<"__builtin_ia32_loadapd512_mask">, + Intrinsic<[llvm_v8f64_ty], [llvm_ptr_ty, llvm_v8f64_ty, llvm_i8_ty], + [IntrReadArgMem]>; } // Conditional store ops @@ -1389,6 +1382,14 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". GCCBuiltin<"__builtin_ia32_storeupd512_mask">, Intrinsic<[], [llvm_ptr_ty, llvm_v8f64_ty, llvm_i8_ty], [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_store_ps_512 : + GCCBuiltin<"__builtin_ia32_storeaps512_mask">, + Intrinsic<[], [llvm_ptr_ty, llvm_v16f32_ty, llvm_i16_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_store_pd_512 : + GCCBuiltin<"__builtin_ia32_storeapd512_mask">, + Intrinsic<[], [llvm_ptr_ty, llvm_v8f64_ty, llvm_i8_ty], + [IntrReadWriteArgMem]>; def int_x86_avx512_mask_store_ss : GCCBuiltin<"__builtin_ia32_storess_mask">, Intrinsic<[], [llvm_ptr_ty, llvm_v4f32_ty, llvm_i8_ty], @@ -1572,19 +1573,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx2_psll_dq : GCCBuiltin<"__builtin_ia32_pslldqi256">, - Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx2_psrl_dq : GCCBuiltin<"__builtin_ia32_psrldqi256">, - Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx2_psll_dq_bs : GCCBuiltin<"__builtin_ia32_pslldqi256_byteshift">, - Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx2_psrl_dq_bs : GCCBuiltin<"__builtin_ia32_psrldqi256_byteshift">, - Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_mask_pslli_d : GCCBuiltin<"__builtin_ia32_pslldi512">, Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_i32_ty, llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; @@ -1603,6 +1591,25 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_avx512_mask_psrai_q : GCCBuiltin<"__builtin_ia32_psraqi512">, Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_i32_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; + + def int_x86_avx512_mask_psll_d : GCCBuiltin<"__builtin_ia32_pslld512_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, + llvm_v4i32_ty, llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psll_q : GCCBuiltin<"__builtin_ia32_psllq512_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, + llvm_v2i64_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psrl_d : GCCBuiltin<"__builtin_ia32_psrld512_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, + llvm_v4i32_ty, llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psrl_q : GCCBuiltin<"__builtin_ia32_psrlq512_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, + llvm_v2i64_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psra_d : GCCBuiltin<"__builtin_ia32_psrad512_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, + llvm_v4i32_ty, llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psra_q : GCCBuiltin<"__builtin_ia32_psraq512_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, + llvm_v2i64_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; } // Pack ops. @@ -1911,6 +1918,31 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_avx2_psrav_d_256 : GCCBuiltin<"__builtin_ia32_psrav8si">, Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; + + def int_x86_avx512_mask_psllv_d : GCCBuiltin<"__builtin_ia32_psllv16si_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, + llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_psllv_q : GCCBuiltin<"__builtin_ia32_psllv8di_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, + llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_psrav_d : GCCBuiltin<"__builtin_ia32_psrav16si_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, + llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_psrav_q : GCCBuiltin<"__builtin_ia32_psrav8di_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, + llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_psrlv_d : GCCBuiltin<"__builtin_ia32_psrlv16si_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, + llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_psrlv_q : GCCBuiltin<"__builtin_ia32_psrlv8di_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, + llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty], + [IntrNoMem]>; } // Gather ops @@ -2029,11 +2061,31 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_fma_mask_vfmadd_ps_256 : GCCBuiltin<"__builtin_ia32_vfmaddps256_mask">, + Intrinsic<[llvm_v8f32_ty], + [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfmadd_ps_128 : GCCBuiltin<"__builtin_ia32_vfmaddps128_mask">, + Intrinsic<[llvm_v4f32_ty], + [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, + llvm_i8_ty], + [IntrNoMem]>; def int_x86_fma_mask_vfmadd_pd_512 : GCCBuiltin<"__builtin_ia32_vfmaddpd512_mask">, Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_fma_mask_vfmadd_pd_256 : GCCBuiltin<"__builtin_ia32_vfmaddpd256_mask">, + Intrinsic<[llvm_v4f64_ty], + [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfmadd_pd_128 : GCCBuiltin<"__builtin_ia32_vfmaddpd128_mask">, + Intrinsic<[llvm_v2f64_ty], + [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, + llvm_i8_ty], + [IntrNoMem]>; def int_x86_fma_vfmsub_ss : GCCBuiltin<"__builtin_ia32_vfmsubss">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty], @@ -2063,11 +2115,31 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_fma_mask_vfmsub_ps_256 : GCCBuiltin<"__builtin_ia32_vfmsubps256_mask">, + Intrinsic<[llvm_v8f32_ty], + [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfmsub_ps_128 : GCCBuiltin<"__builtin_ia32_vfmsubps128_mask">, + Intrinsic<[llvm_v4f32_ty], + [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, + llvm_i8_ty], + [IntrNoMem]>; def int_x86_fma_mask_vfmsub_pd_512 : GCCBuiltin<"__builtin_ia32_vfmsubpd512_mask">, Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_fma_mask_vfmsub_pd_256 : GCCBuiltin<"__builtin_ia32_vfmsubpd256_mask">, + Intrinsic<[llvm_v4f64_ty], + [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfmsub_pd_128 : GCCBuiltin<"__builtin_ia32_vfmsubpd128_mask">, + Intrinsic<[llvm_v2f64_ty], + [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, + llvm_i8_ty], + [IntrNoMem]>; def int_x86_fma_vfnmadd_ss : GCCBuiltin<"__builtin_ia32_vfnmaddss">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty], @@ -2097,11 +2169,31 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_fma_mask_vfnmadd_ps_256 : GCCBuiltin<"__builtin_ia32_vfnmaddps256_mask">, + Intrinsic<[llvm_v8f32_ty], + [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfnmadd_ps_128 : GCCBuiltin<"__builtin_ia32_vfnmaddps128_mask">, + Intrinsic<[llvm_v4f32_ty], + [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, + llvm_i8_ty], + [IntrNoMem]>; def int_x86_fma_mask_vfnmadd_pd_512 : GCCBuiltin<"__builtin_ia32_vfnmaddpd512_mask">, Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_fma_mask_vfnmadd_pd_256 : GCCBuiltin<"__builtin_ia32_vfnmaddpd256_mask">, + Intrinsic<[llvm_v4f64_ty], + [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfnmadd_pd_128 : GCCBuiltin<"__builtin_ia32_vfnmaddpd128_mask">, + Intrinsic<[llvm_v2f64_ty], + [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, + llvm_i8_ty], + [IntrNoMem]>; def int_x86_fma_vfnmsub_ss : GCCBuiltin<"__builtin_ia32_vfnmsubss">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty], @@ -2131,11 +2223,31 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_fma_mask_vfnmsub_ps_256 : GCCBuiltin<"__builtin_ia32_vfnmsubps256_mask">, + Intrinsic<[llvm_v8f32_ty], + [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfnmsub_ps_128 : GCCBuiltin<"__builtin_ia32_vfnmsubps128_mask">, + Intrinsic<[llvm_v4f32_ty], + [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, + llvm_i8_ty], + [IntrNoMem]>; def int_x86_fma_mask_vfnmsub_pd_512 : GCCBuiltin<"__builtin_ia32_vfnmsubpd512_mask">, Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_fma_mask_vfnmsub_pd_256 : GCCBuiltin<"__builtin_ia32_vfnmsubpd256_mask">, + Intrinsic<[llvm_v4f64_ty], + [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfnmsub_pd_128 : GCCBuiltin<"__builtin_ia32_vfnmsubpd128_mask">, + Intrinsic<[llvm_v2f64_ty], + [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, + llvm_i8_ty], + [IntrNoMem]>; def int_x86_fma_vfmaddsub_ps : GCCBuiltin<"__builtin_ia32_vfmaddsubps">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty], @@ -2159,11 +2271,31 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_fma_mask_vfmaddsub_ps_256 : GCCBuiltin<"__builtin_ia32_vfmaddsubps256_mask">, + Intrinsic<[llvm_v8f32_ty], + [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfmaddsub_ps_128 : GCCBuiltin<"__builtin_ia32_vfmaddsubps128_mask">, + Intrinsic<[llvm_v4f32_ty], + [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, + llvm_i8_ty], + [IntrNoMem]>; def int_x86_fma_mask_vfmaddsub_pd_512 : GCCBuiltin<"__builtin_ia32_vfmaddsubpd512_mask">, Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_fma_mask_vfmaddsub_pd_256 : GCCBuiltin<"__builtin_ia32_vfmaddsubpd256_mask">, + Intrinsic<[llvm_v4f64_ty], + [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfmaddsub_pd_128 : GCCBuiltin<"__builtin_ia32_vfmaddsubpd128_mask">, + Intrinsic<[llvm_v2f64_ty], + [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, + llvm_i8_ty], + [IntrNoMem]>; def int_x86_fma_vfmsubadd_ps : GCCBuiltin<"__builtin_ia32_vfmsubaddps">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty], @@ -2187,11 +2319,31 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_fma_mask_vfmsubadd_ps_256 : GCCBuiltin<"__builtin_ia32_vfmsubaddps256_mask">, + Intrinsic<[llvm_v8f32_ty], + [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfmsubadd_ps_128 : GCCBuiltin<"__builtin_ia32_vfmsubaddps128_mask">, + Intrinsic<[llvm_v4f32_ty], + [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, + llvm_i8_ty], + [IntrNoMem]>; def int_x86_fma_mask_vfmsubadd_pd_512 : GCCBuiltin<"__builtin_ia32_vfmsubaddpd512_mask">, Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_fma_mask_vfmsubadd_pd_256 : GCCBuiltin<"__builtin_ia32_vfmsubaddpd256_mask">, + Intrinsic<[llvm_v4f64_ty], + [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfmsubadd_pd_128 : GCCBuiltin<"__builtin_ia32_vfmsubaddpd128_mask">, + Intrinsic<[llvm_v2f64_ty], + [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, + llvm_i8_ty], + [IntrNoMem]>; } //===----------------------------------------------------------------------===// @@ -3003,6 +3155,31 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". // Arithmetic ops let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + + def int_x86_avx512_mask_add_ps_512 : GCCBuiltin<"__builtin_ia32_addps512_mask">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, + llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_add_pd_512 : GCCBuiltin<"__builtin_ia32_addpd512_mask">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, + llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_sub_ps_512 : GCCBuiltin<"__builtin_ia32_subps512_mask">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, + llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_sub_pd_512 : GCCBuiltin<"__builtin_ia32_subpd512_mask">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, + llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_mul_ps_512 : GCCBuiltin<"__builtin_ia32_mulps512_mask">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, + llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_mul_pd_512 : GCCBuiltin<"__builtin_ia32_mulpd512_mask">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, + llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_div_ps_512 : GCCBuiltin<"__builtin_ia32_divps512_mask">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, + llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_div_pd_512 : GCCBuiltin<"__builtin_ia32_divpd512_mask">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, + llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; def int_x86_avx512_mask_max_ps_512 : GCCBuiltin<"__builtin_ia32_maxps512_mask">, Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; @@ -3016,12 +3193,14 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_rndscale_ss : GCCBuiltin<"__builtin_ia32_rndscaless">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_rndscale_sd : GCCBuiltin<"__builtin_ia32_rndscalesd">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, - llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_rndscale_ss : GCCBuiltin<"__builtin_ia32_rndscaless_mask">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, + llvm_i8_ty, llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_rndscale_sd : GCCBuiltin<"__builtin_ia32_rndscalesd_mask">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, + llvm_i8_ty, llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; def int_x86_avx512_sqrt_ss : GCCBuiltin<"__builtin_ia32_sqrtrndss">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; @@ -3102,22 +3281,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". [IntrNoMem]>; } -// Integer shift ops. -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_avx512_psll_dq : GCCBuiltin<"__builtin_ia32_pslldqi512">, - Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_psrl_dq : GCCBuiltin<"__builtin_ia32_psrldqi512">, - Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_psll_dq_bs : GCCBuiltin<"__builtin_ia32_pslldqi512_byteshift">, - Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_psrl_dq_bs : GCCBuiltin<"__builtin_ia32_psrldqi512_byteshift">, - Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, - llvm_i32_ty], [IntrNoMem]>; -} - // Gather and Scatter ops let TargetPrefix = "x86" in { def int_x86_avx512_gather_dpd_512 : GCCBuiltin<"__builtin_ia32_gathersiv8df">, @@ -3226,22 +3389,22 @@ let TargetPrefix = "x86" in { GCCBuiltin<"__builtin_ia32_vpconflictsi_512_mask">, Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty], - []>; + [IntrNoMem]>; def int_x86_avx512_mask_conflict_q_512 : GCCBuiltin<"__builtin_ia32_vpconflictdi_512_mask">, Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty], - []>; + [IntrNoMem]>; def int_x86_avx512_mask_lzcnt_d_512 : GCCBuiltin<"__builtin_ia32_vplzcntd_512_mask">, Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty], - []>; + [IntrNoMem]>; def int_x86_avx512_mask_lzcnt_q_512 : GCCBuiltin<"__builtin_ia32_vplzcntq_512_mask">, Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty], - []>; + [IntrNoMem]>; } // Vector blend @@ -3250,10 +3413,26 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_blend_ps_256 : GCCBuiltin<"__builtin_ia32_blendmps_256_mask">, + Intrinsic<[llvm_v8f32_ty], + [llvm_v8f32_ty, llvm_v8f32_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_blend_ps_128 : GCCBuiltin<"__builtin_ia32_blendmps_128_mask">, + Intrinsic<[llvm_v4f32_ty], + [llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty], + [IntrNoMem]>; def int_x86_avx512_mask_blend_pd_512 : GCCBuiltin<"__builtin_ia32_blendmpd_512_mask">, Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_blend_pd_256 : GCCBuiltin<"__builtin_ia32_blendmpd_256_mask">, + Intrinsic<[llvm_v4f64_ty], + [llvm_v4f64_ty, llvm_v4f64_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_blend_pd_128 : GCCBuiltin<"__builtin_ia32_blendmpd_128_mask">, + Intrinsic<[llvm_v2f64_ty], + [llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty], + [IntrNoMem]>; def int_x86_avx512_mask_blend_d_512 : GCCBuiltin<"__builtin_ia32_blendmd_512_mask">, Intrinsic<[llvm_v16i32_ty], @@ -3263,6 +3442,48 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_blend_d_256 : GCCBuiltin<"__builtin_ia32_blendmd_256_mask">, + Intrinsic<[llvm_v8i32_ty], + [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_blend_q_256 : GCCBuiltin<"__builtin_ia32_blendmq_256_mask">, + Intrinsic<[llvm_v4i64_ty], + [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_blend_d_128 : GCCBuiltin<"__builtin_ia32_blendmd_128_mask">, + Intrinsic<[llvm_v4i32_ty], + [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_blend_q_128 : GCCBuiltin<"__builtin_ia32_blendmq_128_mask">, + Intrinsic<[llvm_v2i64_ty], + [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_blend_w_512 : GCCBuiltin<"__builtin_ia32_blendmw_512_mask">, + Intrinsic<[llvm_v32i16_ty], + [llvm_v32i16_ty, llvm_v32i16_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_blend_w_256 : GCCBuiltin<"__builtin_ia32_blendmw_256_mask">, + Intrinsic<[llvm_v16i16_ty], + [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i16_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_blend_w_128 : GCCBuiltin<"__builtin_ia32_blendmw_128_mask">, + Intrinsic<[llvm_v8i16_ty], + [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_blend_b_512 : GCCBuiltin<"__builtin_ia32_blendmb_512_mask">, + Intrinsic<[llvm_v64i8_ty], + [llvm_v64i8_ty, llvm_v64i8_ty, llvm_i64_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_blend_b_256 : GCCBuiltin<"__builtin_ia32_blendmb_256_mask">, + Intrinsic<[llvm_v32i8_ty], + [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_blend_b_128 : GCCBuiltin<"__builtin_ia32_blendmb_128_mask">, + Intrinsic<[llvm_v16i8_ty], + [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i16_ty], + [IntrNoMem]>; + } let TargetPrefix = "x86" in { @@ -3307,29 +3528,29 @@ let TargetPrefix = "x86" in { [IntrNoMem]>; def int_x86_avx512_mask_cmp_b_512: GCCBuiltin<"__builtin_ia32_cmpb512_mask">, - Intrinsic<[llvm_i64_ty], [llvm_v64i8_ty, llvm_v64i8_ty, llvm_i32_ty, + Intrinsic<[llvm_i64_ty], [llvm_v64i8_ty, llvm_v64i8_ty, llvm_i8_ty, llvm_i64_ty], [IntrNoMem]>; def int_x86_avx512_mask_cmp_w_512: GCCBuiltin<"__builtin_ia32_cmpw512_mask">, - Intrinsic<[llvm_i32_ty], [llvm_v32i16_ty, llvm_v32i16_ty, llvm_i32_ty, + Intrinsic<[llvm_i32_ty], [llvm_v32i16_ty, llvm_v32i16_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; def int_x86_avx512_mask_cmp_d_512: GCCBuiltin<"__builtin_ia32_cmpd512_mask">, - Intrinsic<[llvm_i16_ty], [llvm_v16i32_ty, llvm_v16i32_ty, llvm_i32_ty, + Intrinsic<[llvm_i16_ty], [llvm_v16i32_ty, llvm_v16i32_ty, llvm_i8_ty, llvm_i16_ty], [IntrNoMem ]>; def int_x86_avx512_mask_cmp_q_512: GCCBuiltin<"__builtin_ia32_cmpq512_mask">, - Intrinsic<[llvm_i8_ty], [llvm_v8i64_ty, llvm_v8i64_ty, llvm_i32_ty, + Intrinsic<[llvm_i8_ty], [llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx512_mask_ucmp_b_512: GCCBuiltin<"__builtin_ia32_ucmpb512_mask">, - Intrinsic<[llvm_i64_ty], [llvm_v64i8_ty, llvm_v64i8_ty, llvm_i32_ty, + Intrinsic<[llvm_i64_ty], [llvm_v64i8_ty, llvm_v64i8_ty, llvm_i8_ty, llvm_i64_ty], [IntrNoMem]>; def int_x86_avx512_mask_ucmp_w_512: GCCBuiltin<"__builtin_ia32_ucmpw512_mask">, - Intrinsic<[llvm_i32_ty], [llvm_v32i16_ty, llvm_v32i16_ty, llvm_i32_ty, + Intrinsic<[llvm_i32_ty], [llvm_v32i16_ty, llvm_v32i16_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; def int_x86_avx512_mask_ucmp_d_512: GCCBuiltin<"__builtin_ia32_ucmpd512_mask">, - Intrinsic<[llvm_i16_ty], [llvm_v16i32_ty, llvm_v16i32_ty, llvm_i32_ty, + Intrinsic<[llvm_i16_ty], [llvm_v16i32_ty, llvm_v16i32_ty, llvm_i8_ty, llvm_i16_ty], [IntrNoMem]>; def int_x86_avx512_mask_ucmp_q_512: GCCBuiltin<"__builtin_ia32_ucmpq512_mask">, - Intrinsic<[llvm_i8_ty], [llvm_v8i64_ty, llvm_v8i64_ty, llvm_i32_ty, + Intrinsic<[llvm_i8_ty], [llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty, llvm_i8_ty], [IntrNoMem]>; // 256-bit @@ -3360,29 +3581,29 @@ let TargetPrefix = "x86" in { [IntrNoMem]>; def int_x86_avx512_mask_cmp_b_256: GCCBuiltin<"__builtin_ia32_cmpb256_mask">, - Intrinsic<[llvm_i32_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty, + Intrinsic<[llvm_i32_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; def int_x86_avx512_mask_cmp_w_256: GCCBuiltin<"__builtin_ia32_cmpw256_mask">, - Intrinsic<[llvm_i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i32_ty, + Intrinsic<[llvm_i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i8_ty, llvm_i16_ty], [IntrNoMem]>; def int_x86_avx512_mask_cmp_d_256: GCCBuiltin<"__builtin_ia32_cmpd256_mask">, - Intrinsic<[llvm_i8_ty], [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i32_ty, + Intrinsic<[llvm_i8_ty], [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i8_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx512_mask_cmp_q_256: GCCBuiltin<"__builtin_ia32_cmpq256_mask">, - Intrinsic<[llvm_i8_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i32_ty, + Intrinsic<[llvm_i8_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i8_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx512_mask_ucmp_b_256: GCCBuiltin<"__builtin_ia32_ucmpb256_mask">, - Intrinsic<[llvm_i32_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty, + Intrinsic<[llvm_i32_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; def int_x86_avx512_mask_ucmp_w_256: GCCBuiltin<"__builtin_ia32_ucmpw256_mask">, - Intrinsic<[llvm_i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i32_ty, + Intrinsic<[llvm_i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i8_ty, llvm_i16_ty], [IntrNoMem]>; def int_x86_avx512_mask_ucmp_d_256: GCCBuiltin<"__builtin_ia32_ucmpd256_mask">, - Intrinsic<[llvm_i8_ty], [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i32_ty, + Intrinsic<[llvm_i8_ty], [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i8_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx512_mask_ucmp_q_256: GCCBuiltin<"__builtin_ia32_ucmpq256_mask">, - Intrinsic<[llvm_i8_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i32_ty, + Intrinsic<[llvm_i8_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i8_ty, llvm_i8_ty], [IntrNoMem]>; // 128-bit @@ -3413,39 +3634,243 @@ let TargetPrefix = "x86" in { [IntrNoMem]>; def int_x86_avx512_mask_cmp_b_128: GCCBuiltin<"__builtin_ia32_cmpb128_mask">, - Intrinsic<[llvm_i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty, + Intrinsic<[llvm_i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i8_ty, llvm_i16_ty], [IntrNoMem]>; def int_x86_avx512_mask_cmp_w_128: GCCBuiltin<"__builtin_ia32_cmpw128_mask">, - Intrinsic<[llvm_i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty, + Intrinsic<[llvm_i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i8_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx512_mask_cmp_d_128: GCCBuiltin<"__builtin_ia32_cmpd128_mask">, - Intrinsic<[llvm_i8_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty, + Intrinsic<[llvm_i8_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i8_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx512_mask_cmp_q_128: GCCBuiltin<"__builtin_ia32_cmpq128_mask">, - Intrinsic<[llvm_i8_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty, + Intrinsic<[llvm_i8_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i8_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx512_mask_ucmp_b_128: GCCBuiltin<"__builtin_ia32_ucmpb128_mask">, - Intrinsic<[llvm_i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty, + Intrinsic<[llvm_i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i8_ty, llvm_i16_ty], [IntrNoMem]>; def int_x86_avx512_mask_ucmp_w_128: GCCBuiltin<"__builtin_ia32_ucmpw128_mask">, - Intrinsic<[llvm_i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty, + Intrinsic<[llvm_i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i8_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx512_mask_ucmp_d_128: GCCBuiltin<"__builtin_ia32_ucmpd128_mask">, - Intrinsic<[llvm_i8_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty, + Intrinsic<[llvm_i8_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i8_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx512_mask_ucmp_q_128: GCCBuiltin<"__builtin_ia32_ucmpq128_mask">, - Intrinsic<[llvm_i8_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty, + Intrinsic<[llvm_i8_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i8_ty, llvm_i8_ty], [IntrNoMem]>; } +// Compress, Expand +let TargetPrefix = "x86" in { + def int_x86_avx512_mask_compress_ps_512 : + GCCBuiltin<"__builtin_ia32_compresssf512_mask">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, + llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_compress_pd_512 : + GCCBuiltin<"__builtin_ia32_compressdf512_mask">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_compress_ps_256 : + GCCBuiltin<"__builtin_ia32_compresssf256_mask">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_compress_pd_256 : + GCCBuiltin<"__builtin_ia32_compressdf256_mask">, + Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_compress_ps_128 : + GCCBuiltin<"__builtin_ia32_compresssf128_mask">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_compress_pd_128 : + GCCBuiltin<"__builtin_ia32_compressdf128_mask">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, + llvm_i8_ty], [IntrNoMem]>; + + def int_x86_avx512_mask_compress_store_ps_512 : + GCCBuiltin<"__builtin_ia32_compressstoresf512_mask">, + Intrinsic<[], [llvm_ptr_ty, llvm_v16f32_ty, + llvm_i16_ty], [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_compress_store_pd_512 : + GCCBuiltin<"__builtin_ia32_compressstoredf512_mask">, + Intrinsic<[], [llvm_ptr_ty, llvm_v8f64_ty, + llvm_i8_ty], [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_compress_store_ps_256 : + GCCBuiltin<"__builtin_ia32_compressstoresf256_mask">, + Intrinsic<[], [llvm_ptr_ty, llvm_v8f32_ty, + llvm_i8_ty], [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_compress_store_pd_256 : + GCCBuiltin<"__builtin_ia32_compressstoredf256_mask">, + Intrinsic<[], [llvm_ptr_ty, llvm_v4f64_ty, + llvm_i8_ty], [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_compress_store_ps_128 : + GCCBuiltin<"__builtin_ia32_compressstoresf128_mask">, + Intrinsic<[], [llvm_ptr_ty, llvm_v4f32_ty, + llvm_i8_ty], [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_compress_store_pd_128 : + GCCBuiltin<"__builtin_ia32_compressstoredf128_mask">, + Intrinsic<[], [llvm_ptr_ty, llvm_v2f64_ty, + llvm_i8_ty], [IntrReadWriteArgMem]>; + + def int_x86_avx512_mask_compress_d_512 : + GCCBuiltin<"__builtin_ia32_compresssi512_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, + llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_compress_q_512 : + GCCBuiltin<"__builtin_ia32_compressdi512_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_compress_d_256 : + GCCBuiltin<"__builtin_ia32_compresssi256_mask">, + Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_compress_q_256 : + GCCBuiltin<"__builtin_ia32_compressdi256_mask">, + Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_compress_d_128 : + GCCBuiltin<"__builtin_ia32_compresssi128_mask">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_compress_q_128 : + GCCBuiltin<"__builtin_ia32_compressdi128_mask">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, + llvm_i8_ty], [IntrNoMem]>; + + def int_x86_avx512_mask_compress_store_d_512 : + GCCBuiltin<"__builtin_ia32_compressstoresi512_mask">, + Intrinsic<[], [llvm_ptr_ty, llvm_v16i32_ty, + llvm_i16_ty], [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_compress_store_q_512 : + GCCBuiltin<"__builtin_ia32_compressstoredi512_mask">, + Intrinsic<[], [llvm_ptr_ty, llvm_v8i64_ty, + llvm_i8_ty], [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_compress_store_d_256 : + GCCBuiltin<"__builtin_ia32_compressstoresi256_mask">, + Intrinsic<[], [llvm_ptr_ty, llvm_v8i32_ty, + llvm_i8_ty], [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_compress_store_q_256 : + GCCBuiltin<"__builtin_ia32_compressstoredi256_mask">, + Intrinsic<[], [llvm_ptr_ty, llvm_v4i64_ty, + llvm_i8_ty], [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_compress_store_d_128 : + GCCBuiltin<"__builtin_ia32_compressstoresi128_mask">, + Intrinsic<[], [llvm_ptr_ty, llvm_v4i32_ty, + llvm_i8_ty], [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_compress_store_q_128 : + GCCBuiltin<"__builtin_ia32_compressstoredi128_mask">, + Intrinsic<[], [llvm_ptr_ty, llvm_v2i64_ty, + llvm_i8_ty], [IntrReadWriteArgMem]>; + +// expand + def int_x86_avx512_mask_expand_ps_512 : + GCCBuiltin<"__builtin_ia32_expandsf512_mask">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, + llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_expand_pd_512 : + GCCBuiltin<"__builtin_ia32_expanddf512_mask">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_expand_ps_256 : + GCCBuiltin<"__builtin_ia32_expandsf256_mask">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_expand_pd_256 : + GCCBuiltin<"__builtin_ia32_expanddf256_mask">, + Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_expand_ps_128 : + GCCBuiltin<"__builtin_ia32_expandsf128_mask">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_expand_pd_128 : + GCCBuiltin<"__builtin_ia32_expanddf128_mask">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, + llvm_i8_ty], [IntrNoMem]>; + + def int_x86_avx512_mask_expand_load_ps_512 : + GCCBuiltin<"__builtin_ia32_expandloadsf512_mask">, + Intrinsic<[llvm_v16f32_ty], [llvm_ptr_ty, llvm_v16f32_ty, + llvm_i16_ty], [IntrReadArgMem]>; + def int_x86_avx512_mask_expand_load_pd_512 : + GCCBuiltin<"__builtin_ia32_expandloaddf512_mask">, + Intrinsic<[llvm_v8f64_ty], [llvm_ptr_ty, llvm_v8f64_ty, + llvm_i8_ty], [IntrReadArgMem]>; + def int_x86_avx512_mask_expand_load_ps_256 : + GCCBuiltin<"__builtin_ia32_expandloadsf256_mask">, + Intrinsic<[llvm_v8f32_ty], [llvm_ptr_ty, llvm_v8f32_ty, + llvm_i8_ty], [IntrReadArgMem]>; + def int_x86_avx512_mask_expand_load_pd_256 : + GCCBuiltin<"__builtin_ia32_expandloaddf256_mask">, + Intrinsic<[llvm_v4f64_ty], [llvm_ptr_ty, llvm_v4f64_ty, + llvm_i8_ty], [IntrReadArgMem]>; + def int_x86_avx512_mask_expand_load_ps_128 : + GCCBuiltin<"__builtin_ia32_expandloadsf128_mask">, + Intrinsic<[llvm_v4f32_ty], [llvm_ptr_ty, llvm_v4f32_ty, + llvm_i8_ty], [IntrReadArgMem]>; + def int_x86_avx512_mask_expand_load_pd_128 : + GCCBuiltin<"__builtin_ia32_expandloaddf128_mask">, + Intrinsic<[llvm_v2f64_ty], [llvm_ptr_ty, llvm_v2f64_ty, + llvm_i8_ty], [IntrReadArgMem]>; + + def int_x86_avx512_mask_expand_d_512 : + GCCBuiltin<"__builtin_ia32_expandsi512_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, + llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_expand_q_512 : + GCCBuiltin<"__builtin_ia32_expanddi512_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_expand_d_256 : + GCCBuiltin<"__builtin_ia32_expandsi256_mask">, + Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_expand_q_256 : + GCCBuiltin<"__builtin_ia32_expanddi256_mask">, + Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_expand_d_128 : + GCCBuiltin<"__builtin_ia32_expandsi128_mask">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_expand_q_128 : + GCCBuiltin<"__builtin_ia32_expanddi128_mask">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, + llvm_i8_ty], [IntrNoMem]>; + + def int_x86_avx512_mask_expand_load_d_512 : + GCCBuiltin<"__builtin_ia32_expandloadsi512_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_ptr_ty, llvm_v16i32_ty, + llvm_i16_ty], [IntrReadArgMem]>; + def int_x86_avx512_mask_expand_load_q_512 : + GCCBuiltin<"__builtin_ia32_expandloaddi512_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_ptr_ty, llvm_v8i64_ty, + llvm_i8_ty], [IntrReadArgMem]>; + def int_x86_avx512_mask_expand_load_d_256 : + GCCBuiltin<"__builtin_ia32_expandloadsi256_mask">, + Intrinsic<[llvm_v8i32_ty], [llvm_ptr_ty, llvm_v8i32_ty, + llvm_i8_ty], [IntrReadArgMem]>; + def int_x86_avx512_mask_expand_load_q_256 : + GCCBuiltin<"__builtin_ia32_expandloaddi256_mask">, + Intrinsic<[llvm_v4i64_ty], [llvm_ptr_ty, llvm_v4i64_ty, + llvm_i8_ty], [IntrReadArgMem]>; + def int_x86_avx512_mask_expand_load_d_128 : + GCCBuiltin<"__builtin_ia32_expandloadsi128_mask">, + Intrinsic<[llvm_v4i32_ty], [llvm_ptr_ty, llvm_v4i32_ty, + llvm_i8_ty], [IntrReadArgMem]>; + def int_x86_avx512_mask_expand_load_q_128 : + GCCBuiltin<"__builtin_ia32_expandloaddi128_mask">, + Intrinsic<[llvm_v2i64_ty], [llvm_ptr_ty, llvm_v2i64_ty, + llvm_i8_ty], [IntrReadArgMem]>; + +} // Misc. let TargetPrefix = "x86" in { def int_x86_avx512_mask_cmp_ps_512 : GCCBuiltin<"__builtin_ia32_cmpps512_mask">, - Intrinsic<[llvm_i16_ty], [llvm_v16f32_ty, llvm_v16f32_ty, llvm_i32_ty, + Intrinsic<[llvm_i16_ty], [llvm_v16f32_ty, llvm_v16f32_ty, llvm_i8_ty, llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; def int_x86_avx512_mask_cmp_pd_512 : GCCBuiltin<"__builtin_ia32_cmppd512_mask">, - Intrinsic<[llvm_i8_ty], [llvm_v8f64_ty, llvm_v8f64_ty, llvm_i32_ty, + Intrinsic<[llvm_i8_ty], [llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; def int_x86_avx512_mask_pand_d_512 : GCCBuiltin<"__builtin_ia32_pandd512_mask">, Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, diff --git a/include/llvm/IR/LLVMContext.h b/include/llvm/IR/LLVMContext.h index 2f18782..8c04b08 100644 --- a/include/llvm/IR/LLVMContext.h +++ b/include/llvm/IR/LLVMContext.h @@ -176,8 +176,8 @@ public: } private: - LLVMContext(LLVMContext&) LLVM_DELETED_FUNCTION; - void operator=(LLVMContext&) LLVM_DELETED_FUNCTION; + LLVMContext(LLVMContext&) = delete; + void operator=(LLVMContext&) = delete; /// addModule - Register a module as being instantiated in this context. If /// the context is deleted, the module will be deleted as well. diff --git a/include/llvm/IR/LeakDetector.h b/include/llvm/IR/LeakDetector.h deleted file mode 100644 index cb18df8..0000000 --- a/include/llvm/IR/LeakDetector.h +++ /dev/null @@ -1,92 +0,0 @@ -//===- LeakDetector.h - Provide leak detection ------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines a class that can be used to provide very simple memory leak -// checks for an API. Basically LLVM uses this to make sure that Instructions, -// for example, are deleted when they are supposed to be, and not leaked away. -// -// When compiling with NDEBUG (Release build), this class does nothing, thus -// adding no checking overhead to release builds. Note that this class is -// implemented in a very simple way, requiring completely manual manipulation -// and checking for garbage, but this is intentional: users should not be using -// this API, only other APIs should. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_LEAKDETECTOR_H -#define LLVM_IR_LEAKDETECTOR_H - -#include - -namespace llvm { - -class LLVMContext; -class Value; - -struct LeakDetector { - /// addGarbageObject - Add a pointer to the internal set of "garbage" object - /// pointers. This should be called when objects are created, or if they are - /// taken out of an owning collection. - /// - static void addGarbageObject(void *Object) { -#ifndef NDEBUG - addGarbageObjectImpl(Object); -#endif - } - - /// removeGarbageObject - Remove a pointer from our internal representation of - /// our "garbage" objects. This should be called when an object is added to - /// an "owning" collection. - /// - static void removeGarbageObject(void *Object) { -#ifndef NDEBUG - removeGarbageObjectImpl(Object); -#endif - } - - /// checkForGarbage - Traverse the internal representation of garbage - /// pointers. If there are any pointers that have been add'ed, but not - /// remove'd, big obnoxious warnings about memory leaks are issued. - /// - /// The specified message will be printed indicating when the check was - /// performed. - /// - static void checkForGarbage(LLVMContext &C, const std::string &Message) { -#ifndef NDEBUG - checkForGarbageImpl(C, Message); -#endif - } - - /// Overload the normal methods to work better with Value*'s because they are - /// by far the most common in LLVM. This does not affect the actual - /// functioning of this class, it just makes the warning messages nicer. - /// - static void addGarbageObject(const Value *Object) { -#ifndef NDEBUG - addGarbageObjectImpl(Object); -#endif - } - static void removeGarbageObject(const Value *Object) { -#ifndef NDEBUG - removeGarbageObjectImpl(Object); -#endif - } - -private: - // If we are debugging, the actual implementations will be called... - static void addGarbageObjectImpl(const Value *Object); - static void removeGarbageObjectImpl(const Value *Object); - static void addGarbageObjectImpl(void *Object); - static void removeGarbageObjectImpl(void *Object); - static void checkForGarbageImpl(LLVMContext &C, const std::string &Message); -}; - -} // End llvm namespace - -#endif diff --git a/include/llvm/IR/LegacyPassManager.h b/include/llvm/IR/LegacyPassManager.h index c967a6b..6c04e9d 100644 --- a/include/llvm/IR/LegacyPassManager.h +++ b/include/llvm/IR/LegacyPassManager.h @@ -37,9 +37,10 @@ class PassManagerBase { public: virtual ~PassManagerBase(); - /// add - Add a pass to the queue of passes to run. This passes ownership of + /// Add a pass to the queue of passes to run. This passes ownership of /// the Pass to the PassManager. When the PassManager is destroyed, the pass /// will be destroyed as well, so there is no need to delete the pass. This + /// may even destroy the pass right away if it is found to be redundant. This /// implies that all passes MUST be allocated with 'new'. virtual void add(Pass *P) = 0; }; @@ -51,10 +52,6 @@ public: PassManager(); ~PassManager(); - /// add - Add a pass to the queue of passes to run. This passes ownership of - /// the Pass to the PassManager. When the PassManager is destroyed, the pass - /// will be destroyed as well, so there is no need to delete the pass. This - /// implies that all passes MUST be allocated with 'new'. void add(Pass *P) override; /// run - Execute all of the passes scheduled for execution. Keep track of @@ -75,11 +72,6 @@ public: explicit FunctionPassManager(Module *M); ~FunctionPassManager(); - /// add - Add a pass to the queue of passes to run. This passes - /// ownership of the Pass to the PassManager. When the - /// PassManager_X is destroyed, the pass will be destroyed as well, so - /// there is no need to delete the pass. - /// This implies that all passes MUST be allocated with 'new'. void add(Pass *P) override; /// run - Execute all of the passes scheduled for execution. Keep diff --git a/include/llvm/IR/LegacyPassManagers.h b/include/llvm/IR/LegacyPassManagers.h index ab500a1..7f7889a 100644 --- a/include/llvm/IR/LegacyPassManagers.h +++ b/include/llvm/IR/LegacyPassManagers.h @@ -195,6 +195,9 @@ public: /// then return NULL. Pass *findAnalysisPass(AnalysisID AID); + /// Retrieve the PassInfo for an analysis. + const PassInfo *findAnalysisPassInfo(AnalysisID AID) const; + /// Find analysis usage information for the pass P. AnalysisUsage *findAnalysisUsage(Pass *P); @@ -251,6 +254,12 @@ private: SmallVector ImmutablePasses; DenseMap AnUsageMap; + + /// Collection of PassInfo objects found via analysis IDs and in this top + /// level manager. This is used to memoize queries to the pass registry. + /// FIXME: This is an egregious hack because querying the pass registry is + /// either slow or racy. + mutable DenseMap AnalysisPassInfos; }; diff --git a/include/llvm/IR/LegacyPassNameParser.h b/include/llvm/IR/LegacyPassNameParser.h index e2e4912..52db1c3 100644 --- a/include/llvm/IR/LegacyPassNameParser.h +++ b/include/llvm/IR/LegacyPassNameParser.h @@ -41,14 +41,12 @@ namespace llvm { // class PassNameParser : public PassRegistrationListener, public cl::parser { - cl::Option *Opt; public: - PassNameParser(); + PassNameParser(cl::Option &O); virtual ~PassNameParser(); - void initialize(cl::Option &O) { - Opt = &O; - cl::parser::initialize(O); + void initialize() { + cl::parser::initialize(); // Add all of the passes to the map that got initialized before 'this' did. enumeratePasses(); @@ -69,7 +67,7 @@ public: // Implement the PassRegistrationListener callbacks used to populate our map // void passRegistered(const PassInfo *P) override { - if (ignorablePass(P) || !Opt) return; + if (ignorablePass(P)) return; if (findOption(P->getPassArgument()) != getNumOptions()) { errs() << "Two passes with the same argument (-" << P->getPassArgument() << ") attempted to be registered!\n"; diff --git a/include/llvm/IR/MDBuilder.h b/include/llvm/IR/MDBuilder.h index d29512c..51b8b02 100644 --- a/include/llvm/IR/MDBuilder.h +++ b/include/llvm/IR/MDBuilder.h @@ -24,6 +24,8 @@ namespace llvm { class APInt; template class ArrayRef; class LLVMContext; +class Constant; +class ConstantAsMetadata; class MDNode; class MDString; @@ -36,6 +38,9 @@ public: /// \brief Return the given string as metadata. MDString *createString(StringRef Str); + /// \brief Return the given constant as metadata. + ConstantAsMetadata *createConstant(Constant *C); + //===------------------------------------------------------------------===// // FPMath metadata. //===------------------------------------------------------------------===// @@ -62,6 +67,9 @@ public: /// \brief Return metadata describing the range [Lo, Hi). MDNode *createRange(const APInt &Lo, const APInt &Hi); + /// \brief Return metadata describing the range [Lo, Hi). + MDNode *createRange(Constant *Lo, Constant *Hi); + //===------------------------------------------------------------------===// // AA metadata. //===------------------------------------------------------------------===// diff --git a/include/llvm/IR/Metadata.def b/include/llvm/IR/Metadata.def new file mode 100644 index 0000000..66589e0 --- /dev/null +++ b/include/llvm/IR/Metadata.def @@ -0,0 +1,99 @@ +//===- llvm/IR/Metadata.def - Metadata definitions --------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Macros for running through all types of metadata. +// +//===----------------------------------------------------------------------===// + +#if !(defined HANDLE_METADATA || defined HANDLE_METADATA_LEAF || \ + defined HANDLE_METADATA_BRANCH || defined HANDLE_MDNODE_LEAF || \ + defined HANDLE_MDNODE_BRANCH || \ + defined HANDLE_SPECIALIZED_MDNODE_LEAF || \ + defined HANDLE_SPECIALIZED_MDNODE_BRANCH) +#error "Missing macro definition of HANDLE_METADATA*" +#endif + +// Handler for all types of metadata. +#ifndef HANDLE_METADATA +#define HANDLE_METADATA(CLASS) +#endif + +// Handler for leaf nodes in the class hierarchy. +#ifndef HANDLE_METADATA_LEAF +#define HANDLE_METADATA_LEAF(CLASS) HANDLE_METADATA(CLASS) +#endif + +// Handler for non-leaf nodes in the class hierarchy. +#ifndef HANDLE_METADATA_BRANCH +#define HANDLE_METADATA_BRANCH(CLASS) HANDLE_METADATA(CLASS) +#endif + +// Handler for leaf nodes under MDNode. +#ifndef HANDLE_MDNODE_LEAF +#define HANDLE_MDNODE_LEAF(CLASS) HANDLE_METADATA_LEAF(CLASS) +#endif + +// Handler for non-leaf nodes under MDNode. +#ifndef HANDLE_MDNODE_BRANCH +#define HANDLE_MDNODE_BRANCH(CLASS) HANDLE_METADATA_BRANCH(CLASS) +#endif + +// Handler for specialized leaf nodes under MDNode. +#ifndef HANDLE_SPECIALIZED_MDNODE_LEAF +#define HANDLE_SPECIALIZED_MDNODE_LEAF(CLASS) HANDLE_MDNODE_LEAF(CLASS) +#endif + +// Handler for specialized non-leaf nodes under MDNode. +#ifndef HANDLE_SPECIALIZED_MDNODE_BRANCH +#define HANDLE_SPECIALIZED_MDNODE_BRANCH(CLASS) HANDLE_MDNODE_BRANCH(CLASS) +#endif + +HANDLE_METADATA_LEAF(MDString) +HANDLE_METADATA_BRANCH(ValueAsMetadata) +HANDLE_METADATA_LEAF(ConstantAsMetadata) +HANDLE_METADATA_LEAF(LocalAsMetadata) +HANDLE_MDNODE_BRANCH(MDNode) +HANDLE_MDNODE_LEAF(MDTuple) +HANDLE_SPECIALIZED_MDNODE_LEAF(MDLocation) +HANDLE_SPECIALIZED_MDNODE_BRANCH(DebugNode) +HANDLE_SPECIALIZED_MDNODE_LEAF(GenericDebugNode) +HANDLE_SPECIALIZED_MDNODE_LEAF(MDSubrange) +HANDLE_SPECIALIZED_MDNODE_LEAF(MDEnumerator) +HANDLE_SPECIALIZED_MDNODE_BRANCH(MDScope) +HANDLE_SPECIALIZED_MDNODE_BRANCH(MDType) +HANDLE_SPECIALIZED_MDNODE_LEAF(MDBasicType) +HANDLE_SPECIALIZED_MDNODE_BRANCH(MDDerivedTypeBase) +HANDLE_SPECIALIZED_MDNODE_LEAF(MDDerivedType) +HANDLE_SPECIALIZED_MDNODE_BRANCH(MDCompositeTypeBase) +HANDLE_SPECIALIZED_MDNODE_LEAF(MDCompositeType) +HANDLE_SPECIALIZED_MDNODE_LEAF(MDSubroutineType) +HANDLE_SPECIALIZED_MDNODE_LEAF(MDFile) +HANDLE_SPECIALIZED_MDNODE_LEAF(MDCompileUnit) +HANDLE_SPECIALIZED_MDNODE_LEAF(MDSubprogram) +HANDLE_SPECIALIZED_MDNODE_BRANCH(MDLexicalBlockBase) +HANDLE_SPECIALIZED_MDNODE_LEAF(MDLexicalBlock) +HANDLE_SPECIALIZED_MDNODE_LEAF(MDLexicalBlockFile) +HANDLE_SPECIALIZED_MDNODE_LEAF(MDNamespace) +HANDLE_SPECIALIZED_MDNODE_BRANCH(MDTemplateParameter) +HANDLE_SPECIALIZED_MDNODE_LEAF(MDTemplateTypeParameter) +HANDLE_SPECIALIZED_MDNODE_LEAF(MDTemplateValueParameter) +HANDLE_SPECIALIZED_MDNODE_BRANCH(MDVariable) +HANDLE_SPECIALIZED_MDNODE_LEAF(MDGlobalVariable) +HANDLE_SPECIALIZED_MDNODE_LEAF(MDLocalVariable) +HANDLE_SPECIALIZED_MDNODE_LEAF(MDExpression) +HANDLE_SPECIALIZED_MDNODE_LEAF(MDObjCProperty) +HANDLE_SPECIALIZED_MDNODE_LEAF(MDImportedEntity) + +#undef HANDLE_METADATA +#undef HANDLE_METADATA_LEAF +#undef HANDLE_METADATA_BRANCH +#undef HANDLE_MDNODE_LEAF +#undef HANDLE_MDNODE_BRANCH +#undef HANDLE_SPECIALIZED_MDNODE_LEAF +#undef HANDLE_SPECIALIZED_MDNODE_BRANCH diff --git a/include/llvm/IR/Metadata.h b/include/llvm/IR/Metadata.h index a056b0d..ff8f837 100644 --- a/include/llvm/IR/Metadata.h +++ b/include/llvm/IR/Metadata.h @@ -1,4 +1,4 @@ -//===-- llvm/Metadata.h - Metadata definitions ------------------*- C++ -*-===// +//===- llvm/IR/Metadata.h - Metadata definitions ----------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -18,11 +18,13 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/ilist_node.h" #include "llvm/ADT/iterator_range.h" +#include "llvm/IR/Constant.h" +#include "llvm/IR/MetadataTracking.h" #include "llvm/IR/Value.h" #include "llvm/Support/ErrorHandling.h" +#include namespace llvm { class LLVMContext; @@ -38,20 +40,422 @@ enum LLVMConstants : uint32_t { /// \brief Root of the metadata hierarchy. /// /// This is a root class for typeless data in the IR. -/// -/// TODO: Detach from the Value hierarchy. -class Metadata : public Value { +class Metadata { + friend class ReplaceableMetadataImpl; + + /// \brief RTTI. + const unsigned char SubclassID; + +protected: + /// \brief Active type of storage. + enum StorageType { Uniqued, Distinct, Temporary }; + + /// \brief Storage flag for non-uniqued, otherwise unowned, metadata. + unsigned Storage : 2; + // TODO: expose remaining bits to subclasses. + + unsigned short SubclassData16; + unsigned SubclassData32; + +public: + enum MetadataKind { + MDTupleKind, + MDLocationKind, + GenericDebugNodeKind, + MDSubrangeKind, + MDEnumeratorKind, + MDBasicTypeKind, + MDDerivedTypeKind, + MDCompositeTypeKind, + MDSubroutineTypeKind, + MDFileKind, + MDCompileUnitKind, + MDSubprogramKind, + MDLexicalBlockKind, + MDLexicalBlockFileKind, + MDNamespaceKind, + MDTemplateTypeParameterKind, + MDTemplateValueParameterKind, + MDGlobalVariableKind, + MDLocalVariableKind, + MDExpressionKind, + MDObjCPropertyKind, + MDImportedEntityKind, + ConstantAsMetadataKind, + LocalAsMetadataKind, + MDStringKind + }; + protected: - Metadata(LLVMContext &Context, unsigned ID); + Metadata(unsigned ID, StorageType Storage) + : SubclassID(ID), Storage(Storage), SubclassData16(0), SubclassData32(0) { + } + ~Metadata() {} + + /// \brief Default handling of a changed operand, which asserts. + /// + /// If subclasses pass themselves in as owners to a tracking node reference, + /// they must provide an implementation of this method. + void handleChangedOperand(void *, Metadata *) { + llvm_unreachable("Unimplemented in Metadata subclass"); + } + +public: + unsigned getMetadataID() const { return SubclassID; } + + /// \brief User-friendly dump. + void dump() const; + void print(raw_ostream &OS) const; + void printAsOperand(raw_ostream &OS, bool PrintType = true, + const Module *M = nullptr) const; +}; + +#define HANDLE_METADATA(CLASS) class CLASS; +#include "llvm/IR/Metadata.def" + +inline raw_ostream &operator<<(raw_ostream &OS, const Metadata &MD) { + MD.print(OS); + return OS; +} + +/// \brief Metadata wrapper in the Value hierarchy. +/// +/// A member of the \a Value hierarchy to represent a reference to metadata. +/// This allows, e.g., instrinsics to have metadata as operands. +/// +/// Notably, this is the only thing in either hierarchy that is allowed to +/// reference \a LocalAsMetadata. +class MetadataAsValue : public Value { + friend class ReplaceableMetadataImpl; + friend class LLVMContextImpl; + + Metadata *MD; + + MetadataAsValue(Type *Ty, Metadata *MD); + ~MetadataAsValue(); + + /// \brief Drop use of metadata (during teardown). + void dropUse() { MD = nullptr; } public: + static MetadataAsValue *get(LLVMContext &Context, Metadata *MD); + static MetadataAsValue *getIfExists(LLVMContext &Context, Metadata *MD); + Metadata *getMetadata() const { return MD; } + static bool classof(const Value *V) { - return V->getValueID() == GenericMDNodeVal || - V->getValueID() == MDNodeFwdDeclVal || - V->getValueID() == MDStringVal; + return V->getValueID() == MetadataAsValueVal; } + +private: + void handleChangedMetadata(Metadata *MD); + void track(); + void untrack(); }; +/// \brief Shared implementation of use-lists for replaceable metadata. +/// +/// Most metadata cannot be RAUW'ed. This is a shared implementation of +/// use-lists and associated API for the two that support it (\a ValueAsMetadata +/// and \a TempMDNode). +class ReplaceableMetadataImpl { + friend class MetadataTracking; + +public: + typedef MetadataTracking::OwnerTy OwnerTy; + +private: + LLVMContext &Context; + uint64_t NextIndex; + SmallDenseMap, 4> UseMap; + +public: + ReplaceableMetadataImpl(LLVMContext &Context) + : Context(Context), NextIndex(0) {} + ~ReplaceableMetadataImpl() { + assert(UseMap.empty() && "Cannot destroy in-use replaceable metadata"); + } + + LLVMContext &getContext() const { return Context; } + + /// \brief Replace all uses of this with MD. + /// + /// Replace all uses of this with \c MD, which is allowed to be null. + void replaceAllUsesWith(Metadata *MD); + + /// \brief Resolve all uses of this. + /// + /// Resolve all uses of this, turning off RAUW permanently. If \c + /// ResolveUsers, call \a MDNode::resolve() on any users whose last operand + /// is resolved. + void resolveAllUses(bool ResolveUsers = true); + +private: + void addRef(void *Ref, OwnerTy Owner); + void dropRef(void *Ref); + void moveRef(void *Ref, void *New, const Metadata &MD); + + static ReplaceableMetadataImpl *get(Metadata &MD); +}; + +/// \brief Value wrapper in the Metadata hierarchy. +/// +/// This is a custom value handle that allows other metadata to refer to +/// classes in the Value hierarchy. +/// +/// Because of full uniquing support, each value is only wrapped by a single \a +/// ValueAsMetadata object, so the lookup maps are far more efficient than +/// those using ValueHandleBase. +class ValueAsMetadata : public Metadata, ReplaceableMetadataImpl { + friend class ReplaceableMetadataImpl; + friend class LLVMContextImpl; + + Value *V; + + /// \brief Drop users without RAUW (during teardown). + void dropUsers() { + ReplaceableMetadataImpl::resolveAllUses(/* ResolveUsers */ false); + } + +protected: + ValueAsMetadata(unsigned ID, Value *V) + : Metadata(ID, Uniqued), ReplaceableMetadataImpl(V->getContext()), V(V) { + assert(V && "Expected valid value"); + } + ~ValueAsMetadata() {} + +public: + static ValueAsMetadata *get(Value *V); + static ConstantAsMetadata *getConstant(Value *C) { + return cast(get(C)); + } + static LocalAsMetadata *getLocal(Value *Local) { + return cast(get(Local)); + } + + static ValueAsMetadata *getIfExists(Value *V); + static ConstantAsMetadata *getConstantIfExists(Value *C) { + return cast_or_null(getIfExists(C)); + } + static LocalAsMetadata *getLocalIfExists(Value *Local) { + return cast_or_null(getIfExists(Local)); + } + + Value *getValue() const { return V; } + Type *getType() const { return V->getType(); } + LLVMContext &getContext() const { return V->getContext(); } + + static void handleDeletion(Value *V); + static void handleRAUW(Value *From, Value *To); + +protected: + /// \brief Handle collisions after \a Value::replaceAllUsesWith(). + /// + /// RAUW isn't supported directly for \a ValueAsMetadata, but if the wrapped + /// \a Value gets RAUW'ed and the target already exists, this is used to + /// merge the two metadata nodes. + void replaceAllUsesWith(Metadata *MD) { + ReplaceableMetadataImpl::replaceAllUsesWith(MD); + } + +public: + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == LocalAsMetadataKind || + MD->getMetadataID() == ConstantAsMetadataKind; + } +}; + +class ConstantAsMetadata : public ValueAsMetadata { + friend class ValueAsMetadata; + + ConstantAsMetadata(Constant *C) + : ValueAsMetadata(ConstantAsMetadataKind, C) {} + +public: + static ConstantAsMetadata *get(Constant *C) { + return ValueAsMetadata::getConstant(C); + } + static ConstantAsMetadata *getIfExists(Constant *C) { + return ValueAsMetadata::getConstantIfExists(C); + } + + Constant *getValue() const { + return cast(ValueAsMetadata::getValue()); + } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == ConstantAsMetadataKind; + } +}; + +class LocalAsMetadata : public ValueAsMetadata { + friend class ValueAsMetadata; + + LocalAsMetadata(Value *Local) + : ValueAsMetadata(LocalAsMetadataKind, Local) { + assert(!isa(Local) && "Expected local value"); + } + +public: + static LocalAsMetadata *get(Value *Local) { + return ValueAsMetadata::getLocal(Local); + } + static LocalAsMetadata *getIfExists(Value *Local) { + return ValueAsMetadata::getLocalIfExists(Local); + } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == LocalAsMetadataKind; + } +}; + +/// \brief Transitional API for extracting constants from Metadata. +/// +/// This namespace contains transitional functions for metadata that points to +/// \a Constants. +/// +/// In prehistory -- when metadata was a subclass of \a Value -- \a MDNode +/// operands could refer to any \a Value. There's was a lot of code like this: +/// +/// \code +/// MDNode *N = ...; +/// auto *CI = dyn_cast(N->getOperand(2)); +/// \endcode +/// +/// Now that \a Value and \a Metadata are in separate hierarchies, maintaining +/// the semantics for \a isa(), \a cast(), \a dyn_cast() (etc.) requires three +/// steps: cast in the \a Metadata hierarchy, extraction of the \a Value, and +/// cast in the \a Value hierarchy. Besides creating boiler-plate, this +/// requires subtle control flow changes. +/// +/// The end-goal is to create a new type of metadata, called (e.g.) \a MDInt, +/// so that metadata can refer to numbers without traversing a bridge to the \a +/// Value hierarchy. In this final state, the code above would look like this: +/// +/// \code +/// MDNode *N = ...; +/// auto *MI = dyn_cast(N->getOperand(2)); +/// \endcode +/// +/// The API in this namespace supports the transition. \a MDInt doesn't exist +/// yet, and even once it does, changing each metadata schema to use it is its +/// own mini-project. In the meantime this API prevents us from introducing +/// complex and bug-prone control flow that will disappear in the end. In +/// particular, the above code looks like this: +/// +/// \code +/// MDNode *N = ...; +/// auto *CI = mdconst::dyn_extract(N->getOperand(2)); +/// \endcode +/// +/// The full set of provided functions includes: +/// +/// mdconst::hasa <=> isa +/// mdconst::extract <=> cast +/// mdconst::extract_or_null <=> cast_or_null +/// mdconst::dyn_extract <=> dyn_cast +/// mdconst::dyn_extract_or_null <=> dyn_cast_or_null +/// +/// The target of the cast must be a subclass of \a Constant. +namespace mdconst { + +namespace detail { +template T &make(); +template struct HasDereference { + typedef char Yes[1]; + typedef char No[2]; + template struct SFINAE {}; + + template + static Yes &hasDereference(SFINAE(*make()))> * = 0); + template static No &hasDereference(...); + + static const bool value = + sizeof(hasDereference(nullptr)) == sizeof(Yes); +}; +template struct IsValidPointer { + static const bool value = std::is_base_of::value && + HasDereference::value; +}; +template struct IsValidReference { + static const bool value = std::is_base_of::value && + std::is_convertible::value; +}; +} // end namespace detail + +/// \brief Check whether Metadata has a Value. +/// +/// As an analogue to \a isa(), check whether \c MD has an \a Value inside of +/// type \c X. +template +inline typename std::enable_if::value, bool>::type +hasa(Y &&MD) { + assert(MD && "Null pointer sent into hasa"); + if (auto *V = dyn_cast(MD)) + return isa(V->getValue()); + return false; +} +template +inline + typename std::enable_if::value, bool>::type + hasa(Y &MD) { + return hasa(&MD); +} + +/// \brief Extract a Value from Metadata. +/// +/// As an analogue to \a cast(), extract the \a Value subclass \c X from \c MD. +template +inline typename std::enable_if::value, X *>::type +extract(Y &&MD) { + return cast(cast(MD)->getValue()); +} +template +inline + typename std::enable_if::value, X *>::type + extract(Y &MD) { + return extract(&MD); +} + +/// \brief Extract a Value from Metadata, allowing null. +/// +/// As an analogue to \a cast_or_null(), extract the \a Value subclass \c X +/// from \c MD, allowing \c MD to be null. +template +inline typename std::enable_if::value, X *>::type +extract_or_null(Y &&MD) { + if (auto *V = cast_or_null(MD)) + return cast(V->getValue()); + return nullptr; +} + +/// \brief Extract a Value from Metadata, if any. +/// +/// As an analogue to \a dyn_cast_or_null(), extract the \a Value subclass \c X +/// from \c MD, return null if \c MD doesn't contain a \a Value or if the \a +/// Value it does contain is of the wrong subclass. +template +inline typename std::enable_if::value, X *>::type +dyn_extract(Y &&MD) { + if (auto *V = dyn_cast(MD)) + return dyn_cast(V->getValue()); + return nullptr; +} + +/// \brief Extract a Value from Metadata, if any, allowing null. +/// +/// As an analogue to \a dyn_cast_or_null(), extract the \a Value subclass \c X +/// from \c MD, return null if \c MD doesn't contain a \a Value or if the \a +/// Value it does contain is of the wrong subclass, allowing \c MD to be null. +template +inline typename std::enable_if::value, X *>::type +dyn_extract_or_null(Y &&MD) { + if (auto *V = dyn_cast_or_null(MD)) + return dyn_cast(V->getValue()); + return nullptr; +} + +} // end namespace mdconst + //===----------------------------------------------------------------------===// /// \brief A single uniqued string. /// @@ -60,14 +464,13 @@ public: class MDString : public Metadata { friend class StringMapEntry; - virtual void anchor(); - MDString(const MDString &) LLVM_DELETED_FUNCTION; - - explicit MDString(LLVMContext &Context) - : Metadata(Context, Value::MDStringVal) {} + MDString(const MDString &) = delete; + MDString &operator=(MDString &&) = delete; + MDString &operator=(const MDString &) = delete; - /// \brief Shadow Value::getName() to prevent its use. - StringRef getName() const LLVM_DELETED_FUNCTION; + StringMapEntry *Entry; + MDString() : Metadata(MDStringKind, Uniqued), Entry(nullptr) {} + MDString(MDString &&) : Metadata(MDStringKind, Uniqued) {} public: static MDString *get(LLVMContext &Context, StringRef Str); @@ -87,9 +490,12 @@ public: /// \brief Pointer to one byte past the end of the string. iterator end() const { return getString().end(); } + const unsigned char *bytes_begin() const { return getString().bytes_begin(); } + const unsigned char *bytes_end() const { return getString().bytes_end(); } + /// \brief Methods for support type inquiry through isa, cast, and dyn_cast. - static bool classof(const Value *V) { - return V->getValueID() == MDStringVal; + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDStringKind; } }; @@ -106,7 +512,7 @@ struct AAMDNodes { bool operator!=(const AAMDNodes &A) const { return !(*this == A); } - LLVM_EXPLICIT operator bool() const { return TBAA || Scope || NoAlias; } + explicit operator bool() const { return TBAA || Scope || NoAlias; } /// \brief The tag for type-based alias analysis. MDNode *TBAA; @@ -137,21 +543,171 @@ struct DenseMapInfo { } }; -class MDNodeOperand; +/// \brief Tracking metadata reference owned by Metadata. +/// +/// Similar to \a TrackingMDRef, but it's expected to be owned by an instance +/// of \a Metadata, which has the option of registering itself for callbacks to +/// re-unique itself. +/// +/// In particular, this is used by \a MDNode. +class MDOperand { + MDOperand(MDOperand &&) = delete; + MDOperand(const MDOperand &) = delete; + MDOperand &operator=(MDOperand &&) = delete; + MDOperand &operator=(const MDOperand &) = delete; -//===----------------------------------------------------------------------===// -/// \brief Tuple of metadata. + Metadata *MD; + +public: + MDOperand() : MD(nullptr) {} + ~MDOperand() { untrack(); } + + Metadata *get() const { return MD; } + operator Metadata *() const { return get(); } + Metadata *operator->() const { return get(); } + Metadata &operator*() const { return *get(); } + + void reset() { + untrack(); + MD = nullptr; + } + void reset(Metadata *MD, Metadata *Owner) { + untrack(); + this->MD = MD; + track(Owner); + } + +private: + void track(Metadata *Owner) { + if (MD) { + if (Owner) + MetadataTracking::track(this, *MD, *Owner); + else + MetadataTracking::track(MD); + } + } + void untrack() { + assert(static_cast(this) == &MD && "Expected same address"); + if (MD) + MetadataTracking::untrack(MD); + } +}; + +template <> struct simplify_type { + typedef Metadata *SimpleType; + static SimpleType getSimplifiedValue(MDOperand &MD) { return MD.get(); } +}; + +template <> struct simplify_type { + typedef Metadata *SimpleType; + static SimpleType getSimplifiedValue(const MDOperand &MD) { return MD.get(); } +}; + +/// \brief Pointer to the context, with optional RAUW support. +/// +/// Either a raw (non-null) pointer to the \a LLVMContext, or an owned pointer +/// to \a ReplaceableMetadataImpl (which has a reference to \a LLVMContext). +class ContextAndReplaceableUses { + PointerUnion Ptr; + + ContextAndReplaceableUses() = delete; + ContextAndReplaceableUses(ContextAndReplaceableUses &&) = delete; + ContextAndReplaceableUses(const ContextAndReplaceableUses &) = delete; + ContextAndReplaceableUses &operator=(ContextAndReplaceableUses &&) = delete; + ContextAndReplaceableUses & + operator=(const ContextAndReplaceableUses &) = delete; + +public: + ContextAndReplaceableUses(LLVMContext &Context) : Ptr(&Context) {} + ContextAndReplaceableUses( + std::unique_ptr ReplaceableUses) + : Ptr(ReplaceableUses.release()) { + assert(getReplaceableUses() && "Expected non-null replaceable uses"); + } + ~ContextAndReplaceableUses() { delete getReplaceableUses(); } + + operator LLVMContext &() { return getContext(); } + + /// \brief Whether this contains RAUW support. + bool hasReplaceableUses() const { + return Ptr.is(); + } + LLVMContext &getContext() const { + if (hasReplaceableUses()) + return getReplaceableUses()->getContext(); + return *Ptr.get(); + } + ReplaceableMetadataImpl *getReplaceableUses() const { + if (hasReplaceableUses()) + return Ptr.get(); + return nullptr; + } + + /// \brief Assign RAUW support to this. + /// + /// Make this replaceable, taking ownership of \c ReplaceableUses (which must + /// not be null). + void + makeReplaceable(std::unique_ptr ReplaceableUses) { + assert(ReplaceableUses && "Expected non-null replaceable uses"); + assert(&ReplaceableUses->getContext() == &getContext() && + "Expected same context"); + delete getReplaceableUses(); + Ptr = ReplaceableUses.release(); + } + + /// \brief Drop RAUW support. + /// + /// Cede ownership of RAUW support, returning it. + std::unique_ptr takeReplaceableUses() { + assert(hasReplaceableUses() && "Expected to own replaceable uses"); + std::unique_ptr ReplaceableUses( + getReplaceableUses()); + Ptr = &ReplaceableUses->getContext(); + return ReplaceableUses; + } +}; + +struct TempMDNodeDeleter { + inline void operator()(MDNode *Node) const; +}; + +#define HANDLE_MDNODE_LEAF(CLASS) \ + typedef std::unique_ptr Temp##CLASS; +#define HANDLE_MDNODE_BRANCH(CLASS) HANDLE_MDNODE_LEAF(CLASS) +#include "llvm/IR/Metadata.def" + +/// \brief Metadata node. +/// +/// Metadata nodes can be uniqued, like constants, or distinct. Temporary +/// metadata nodes (with full support for RAUW) can be used to delay uniquing +/// until forward references are known. The basic metadata node is an \a +/// MDTuple. +/// +/// There is limited support for RAUW at construction time. At construction +/// time, if any operand is a temporary node (or an unresolved uniqued node, +/// which indicates a transitive temporary operand), the node itself will be +/// unresolved. As soon as all operands become resolved, it will drop RAUW +/// support permanently. +/// +/// If an unresolved node is part of a cycle, \a resolveCycles() needs +/// to be called on some member of the cycle once all temporary nodes have been +/// replaced. class MDNode : public Metadata { - MDNode(const MDNode &) LLVM_DELETED_FUNCTION; - void operator=(const MDNode &) LLVM_DELETED_FUNCTION; - friend class MDNodeOperand; + friend class ReplaceableMetadataImpl; friend class LLVMContextImpl; - void *operator new(size_t) LLVM_DELETED_FUNCTION; + + MDNode(const MDNode &) = delete; + void operator=(const MDNode &) = delete; + void *operator new(size_t) = delete; + + unsigned NumOperands; + unsigned NumUnresolved; protected: - void *operator new(size_t Size, unsigned NumOps); + ContextAndReplaceableUses Context; - /// \brief Required by std, but never called. + void *operator new(size_t Size, unsigned NumOps); void operator delete(void *Mem); /// \brief Required by std, but never called. @@ -164,83 +720,188 @@ protected: llvm_unreachable("Constructor throws?"); } - /// \brief Subclass data enums. - enum { - /// FunctionLocalBit - This bit is set if this MDNode is function local. - /// This is true when it (potentially transitively) contains a reference to - /// something in a function, like an argument, basicblock, or instruction. - FunctionLocalBit = 1 << 0, + MDNode(LLVMContext &Context, unsigned ID, StorageType Storage, + ArrayRef Ops1, ArrayRef Ops2 = None); + ~MDNode() {} - /// NotUniquedBit - This is set on MDNodes that are not uniqued because they - /// have a null operand. - NotUniquedBit = 1 << 1 - }; + void dropAllReferences(); - /// \brief FunctionLocal enums. - enum FunctionLocalness { - FL_Unknown = -1, - FL_No = 0, - FL_Yes = 1 - }; + MDOperand *mutable_begin() { return mutable_end() - NumOperands; } + MDOperand *mutable_end() { return reinterpret_cast(this); } - /// \brief Replace each instance of the given operand with a new value. - void replaceOperand(MDNodeOperand *Op, Value *NewVal); +public: + static inline MDTuple *get(LLVMContext &Context, ArrayRef MDs); + static inline MDTuple *getIfExists(LLVMContext &Context, + ArrayRef MDs); + static inline MDTuple *getDistinct(LLVMContext &Context, + ArrayRef MDs); + static inline TempMDTuple getTemporary(LLVMContext &Context, + ArrayRef MDs); - MDNode(LLVMContext &C, unsigned ID, ArrayRef Vals, - bool isFunctionLocal); - ~MDNode() {} + /// \brief Create a (temporary) clone of this. + TempMDNode clone() const; - static MDNode *getMDNode(LLVMContext &C, ArrayRef Vals, - FunctionLocalness FL, bool Insert = true); -public: - static MDNode *get(LLVMContext &Context, ArrayRef Vals); - /// \brief Construct MDNode with an explicit function-localness. + /// \brief Deallocate a node created by getTemporary. /// - /// Don't analyze Vals; trust isFunctionLocal. - static MDNode *getWhenValsUnresolved(LLVMContext &Context, - ArrayRef Vals, - bool isFunctionLocal); + /// Calls \c replaceAllUsesWith(nullptr) before deleting, so any remaining + /// references will be reset. + static void deleteTemporary(MDNode *N); - static MDNode *getIfExists(LLVMContext &Context, ArrayRef Vals); + LLVMContext &getContext() const { return Context.getContext(); } + + /// \brief Replace a specific operand. + void replaceOperandWith(unsigned I, Metadata *New); - /// \brief Return a temporary MDNode + /// \brief Check if node is fully resolved. /// - /// For use in constructing cyclic MDNode structures. A temporary MDNode is - /// not uniqued, may be RAUW'd, and must be manually deleted with - /// deleteTemporary. - static MDNode *getTemporary(LLVMContext &Context, ArrayRef Vals); + /// If \a isTemporary(), this always returns \c false; if \a isDistinct(), + /// this always returns \c true. + /// + /// If \a isUniqued(), returns \c true if this has already dropped RAUW + /// support (because all operands are resolved). + /// + /// As forward declarations are resolved, their containers should get + /// resolved automatically. However, if this (or one of its operands) is + /// involved in a cycle, \a resolveCycles() needs to be called explicitly. + bool isResolved() const { return !Context.hasReplaceableUses(); } - /// \brief Deallocate a node created by getTemporary. + bool isUniqued() const { return Storage == Uniqued; } + bool isDistinct() const { return Storage == Distinct; } + bool isTemporary() const { return Storage == Temporary; } + + /// \brief RAUW a temporary. /// - /// The node must not have any users. - static void deleteTemporary(MDNode *N); + /// \pre \a isTemporary() must be \c true. + void replaceAllUsesWith(Metadata *MD) { + assert(isTemporary() && "Expected temporary node"); + assert(!isResolved() && "Expected RAUW support"); + Context.getReplaceableUses()->replaceAllUsesWith(MD); + } - /// \brief Replace a specific operand. - void replaceOperandWith(unsigned i, Value *NewVal); + /// \brief Resolve cycles. + /// + /// Once all forward declarations have been resolved, force cycles to be + /// resolved. + /// + /// \pre No operands (or operands' operands, etc.) have \a isTemporary(). + void resolveCycles(); - /// \brief Return specified operand. - Value *getOperand(unsigned i) const LLVM_READONLY; + /// \brief Replace a temporary node with a permanent one. + /// + /// Try to create a uniqued version of \c N -- in place, if possible -- and + /// return it. If \c N cannot be uniqued, return a distinct node instead. + template + static typename std::enable_if::value, T *>::type + replaceWithPermanent(std::unique_ptr N) { + return cast(N.release()->replaceWithPermanentImpl()); + } - /// \brief Return number of MDNode operands. - unsigned getNumOperands() const { return NumOperands; } + /// \brief Replace a temporary node with a uniqued one. + /// + /// Create a uniqued version of \c N -- in place, if possible -- and return + /// it. Takes ownership of the temporary node. + /// + /// \pre N does not self-reference. + template + static typename std::enable_if::value, T *>::type + replaceWithUniqued(std::unique_ptr N) { + return cast(N.release()->replaceWithUniquedImpl()); + } - /// \brief Return whether MDNode is local to a function. - bool isFunctionLocal() const { - return (getSubclassDataFromValue() & FunctionLocalBit) != 0; + /// \brief Replace a temporary node with a distinct one. + /// + /// Create a distinct version of \c N -- in place, if possible -- and return + /// it. Takes ownership of the temporary node. + template + static typename std::enable_if::value, T *>::type + replaceWithDistinct(std::unique_ptr N) { + return cast(N.release()->replaceWithDistinctImpl()); } - /// \brief Return the first function-local operand's function. +private: + MDNode *replaceWithPermanentImpl(); + MDNode *replaceWithUniquedImpl(); + MDNode *replaceWithDistinctImpl(); + +protected: + /// \brief Set an operand. + /// + /// Sets the operand directly, without worrying about uniquing. + void setOperand(unsigned I, Metadata *New); + + void storeDistinctInContext(); + template + static T *storeImpl(T *N, StorageType Storage, StoreT &Store); + +private: + void handleChangedOperand(void *Ref, Metadata *New); + + void resolve(); + void resolveAfterOperandChange(Metadata *Old, Metadata *New); + void decrementUnresolvedOperandCount(); + unsigned countUnresolvedOperands(); + + /// \brief Mutate this to be "uniqued". /// - /// If this metadata is function-local and recursively has a function-local - /// operand, return the first such operand's parent function. Otherwise, - /// return null. getFunction() should not be used for performance- critical - /// code because it recursively visits all the MDNode's operands. - const Function *getFunction() const; + /// Mutate this so that \a isUniqued(). + /// \pre \a isTemporary(). + /// \pre already added to uniquing set. + void makeUniqued(); + + /// \brief Mutate this to be "distinct". + /// + /// Mutate this so that \a isDistinct(). + /// \pre \a isTemporary(). + void makeDistinct(); + + void deleteAsSubclass(); + MDNode *uniquify(); + void eraseFromStore(); + + template struct HasCachedHash; + template + static void dispatchRecalculateHash(NodeTy *N, std::true_type) { + N->recalculateHash(); + } + template + static void dispatchRecalculateHash(NodeTy *N, std::false_type) {} + template + static void dispatchResetHash(NodeTy *N, std::true_type) { + N->setHash(0); + } + template + static void dispatchResetHash(NodeTy *N, std::false_type) {} + +public: + typedef const MDOperand *op_iterator; + typedef iterator_range op_range; + + op_iterator op_begin() const { + return const_cast(this)->mutable_begin(); + } + op_iterator op_end() const { + return const_cast(this)->mutable_end(); + } + op_range operands() const { return op_range(op_begin(), op_end()); } + + const MDOperand &getOperand(unsigned I) const { + assert(I < NumOperands && "Out of range"); + return op_begin()[I]; + } + + /// \brief Return number of MDNode operands. + unsigned getNumOperands() const { return NumOperands; } /// \brief Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Value *V) { - return V->getValueID() == GenericMDNodeVal || - V->getValueID() == MDNodeFwdDeclVal; + static bool classof(const Metadata *MD) { + switch (MD->getMetadataID()) { + default: + return false; +#define HANDLE_MDNODE_LEAF(CLASS) \ + case CLASS##Kind: \ + return true; +#include "llvm/IR/Metadata.def" + } } /// \brief Check whether MDNode is a vtable access. @@ -250,72 +911,91 @@ public: static MDNode *concatenate(MDNode *A, MDNode *B); static MDNode *intersect(MDNode *A, MDNode *B); static MDNode *getMostGenericTBAA(MDNode *A, MDNode *B); - static AAMDNodes getMostGenericAA(const AAMDNodes &A, const AAMDNodes &B); static MDNode *getMostGenericFPMath(MDNode *A, MDNode *B); static MDNode *getMostGenericRange(MDNode *A, MDNode *B); - -protected: - bool isNotUniqued() const { - return (getSubclassDataFromValue() & NotUniquedBit) != 0; - } - void setIsNotUniqued(); - - // Shadow Value::setValueSubclassData with a private forwarding method so that - // any future subclasses cannot accidentally use it. - void setValueSubclassData(unsigned short D) { - Value::setValueSubclassData(D); - } + static MDNode *getMostGenericAliasScope(MDNode *A, MDNode *B); }; -/// \brief Generic metadata node. -/// -/// Generic metadata nodes, with opt-out support for uniquing. -/// -/// Although nodes are uniqued by default, \a GenericMDNode has no support for -/// RAUW. If an operand change (due to RAUW or otherwise) causes a uniquing -/// collision, the uniquing bit is dropped. +/// \brief Tuple of metadata. /// -/// TODO: Make uniquing opt-out (status: mandatory, sometimes dropped). -/// TODO: Drop support for RAUW. -class GenericMDNode : public MDNode { - friend class MDNode; +/// This is the simple \a MDNode arbitrary tuple. Nodes are uniqued by +/// default based on their operands. +class MDTuple : public MDNode { friend class LLVMContextImpl; + friend class MDNode; + + MDTuple(LLVMContext &C, StorageType Storage, unsigned Hash, + ArrayRef Vals) + : MDNode(C, MDTupleKind, Storage, Vals) { + setHash(Hash); + } + ~MDTuple() { dropAllReferences(); } - unsigned Hash; + void setHash(unsigned Hash) { SubclassData32 = Hash; } + void recalculateHash(); - GenericMDNode(LLVMContext &C, ArrayRef Vals, bool isFunctionLocal) - : MDNode(C, GenericMDNodeVal, Vals, isFunctionLocal), Hash(0) {} - ~GenericMDNode(); + static MDTuple *getImpl(LLVMContext &Context, ArrayRef MDs, + StorageType Storage, bool ShouldCreate = true); - void dropAllReferences(); + TempMDTuple cloneImpl() const { + return getTemporary(getContext(), + SmallVector(op_begin(), op_end())); + } public: /// \brief Get the hash, if any. - unsigned getHash() const { return Hash; } + unsigned getHash() const { return SubclassData32; } - static bool classof(const Value *V) { - return V->getValueID() == GenericMDNodeVal; + static MDTuple *get(LLVMContext &Context, ArrayRef MDs) { + return getImpl(Context, MDs, Uniqued); + } + static MDTuple *getIfExists(LLVMContext &Context, ArrayRef MDs) { + return getImpl(Context, MDs, Uniqued, /* ShouldCreate */ false); } -}; -/// \brief Forward declaration of metadata. -/// -/// Forward declaration of metadata, in the form of a metadata node. Unlike \a -/// GenericMDNode, this class has support for RAUW and is suitable for forward -/// references. -class MDNodeFwdDecl : public MDNode { - friend class MDNode; + /// \brief Return a distinct node. + /// + /// Return a distinct node -- i.e., a node that is not uniqued. + static MDTuple *getDistinct(LLVMContext &Context, ArrayRef MDs) { + return getImpl(Context, MDs, Distinct); + } - MDNodeFwdDecl(LLVMContext &C, ArrayRef Vals, bool isFunctionLocal) - : MDNode(C, MDNodeFwdDeclVal, Vals, isFunctionLocal) {} - ~MDNodeFwdDecl() {} + /// \brief Return a temporary node. + /// + /// For use in constructing cyclic MDNode structures. A temporary MDNode is + /// not uniqued, may be RAUW'd, and must be manually deleted with + /// deleteTemporary. + static TempMDTuple getTemporary(LLVMContext &Context, + ArrayRef MDs) { + return TempMDTuple(getImpl(Context, MDs, Temporary)); + } -public: - static bool classof(const Value *V) { - return V->getValueID() == MDNodeFwdDeclVal; + /// \brief Return a (temporary) clone of this. + TempMDTuple clone() const { return cloneImpl(); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDTupleKind; } }; +MDTuple *MDNode::get(LLVMContext &Context, ArrayRef MDs) { + return MDTuple::get(Context, MDs); +} +MDTuple *MDNode::getIfExists(LLVMContext &Context, ArrayRef MDs) { + return MDTuple::getIfExists(Context, MDs); +} +MDTuple *MDNode::getDistinct(LLVMContext &Context, ArrayRef MDs) { + return MDTuple::getDistinct(Context, MDs); +} +TempMDTuple MDNode::getTemporary(LLVMContext &Context, + ArrayRef MDs) { + return MDTuple::getTemporary(Context, MDs); +} + +void TempMDNodeDeleter::operator()(MDNode *Node) const { + MDNode::deleteTemporary(Node); +} + //===----------------------------------------------------------------------===// /// \brief A tuple of MDNodes. /// @@ -328,11 +1008,11 @@ class NamedMDNode : public ilist_node { friend struct ilist_traits; friend class LLVMContextImpl; friend class Module; - NamedMDNode(const NamedMDNode &) LLVM_DELETED_FUNCTION; + NamedMDNode(const NamedMDNode &) = delete; std::string Name; Module *Parent; - void *Operands; // SmallVector, 4> + void *Operands; // SmallVector void setParent(Module *M) { Parent = M; } @@ -390,6 +1070,7 @@ public: MDNode *getOperand(unsigned i) const; unsigned getNumOperands() const; void addOperand(MDNode *M); + void setOperand(unsigned I, MDNode *New); StringRef getName() const; void print(raw_ostream &ROS) const; void dump() const; diff --git a/include/llvm/IR/MetadataTracking.h b/include/llvm/IR/MetadataTracking.h new file mode 100644 index 0000000..541d9b3 --- /dev/null +++ b/include/llvm/IR/MetadataTracking.h @@ -0,0 +1,99 @@ +//===- llvm/IR/MetadataTracking.h - Metadata tracking ---------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Low-level functions to enable tracking of metadata that could RAUW. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_METADATATRACKING_H +#define LLVM_IR_METADATATRACKING_H + +#include "llvm/ADT/PointerUnion.h" +#include "llvm/Support/Casting.h" +#include + +namespace llvm { + +class Metadata; +class MetadataAsValue; + +/// \brief API for tracking metadata references through RAUW and deletion. +/// +/// Shared API for updating \a Metadata pointers in subclasses that support +/// RAUW. +/// +/// This API is not meant to be used directly. See \a TrackingMDRef for a +/// user-friendly tracking reference. +class MetadataTracking { +public: + /// \brief Track the reference to metadata. + /// + /// Register \c MD with \c *MD, if the subclass supports tracking. If \c *MD + /// gets RAUW'ed, \c MD will be updated to the new address. If \c *MD gets + /// deleted, \c MD will be set to \c nullptr. + /// + /// If tracking isn't supported, \c *MD will not change. + /// + /// \return true iff tracking is supported by \c MD. + static bool track(Metadata *&MD) { + return track(&MD, *MD, static_cast(nullptr)); + } + + /// \brief Track the reference to metadata for \a Metadata. + /// + /// As \a track(Metadata*&), but with support for calling back to \c Owner to + /// tell it that its operand changed. This could trigger \c Owner being + /// re-uniqued. + static bool track(void *Ref, Metadata &MD, Metadata &Owner) { + return track(Ref, MD, &Owner); + } + + /// \brief Track the reference to metadata for \a MetadataAsValue. + /// + /// As \a track(Metadata*&), but with support for calling back to \c Owner to + /// tell it that its operand changed. This could trigger \c Owner being + /// re-uniqued. + static bool track(void *Ref, Metadata &MD, MetadataAsValue &Owner) { + return track(Ref, MD, &Owner); + } + + /// \brief Stop tracking a reference to metadata. + /// + /// Stops \c *MD from tracking \c MD. + static void untrack(Metadata *&MD) { untrack(&MD, *MD); } + static void untrack(void *Ref, Metadata &MD); + + /// \brief Move tracking from one reference to another. + /// + /// Semantically equivalent to \c untrack(MD) followed by \c track(New), + /// except that ownership callbacks are maintained. + /// + /// Note: it is an error if \c *MD does not equal \c New. + /// + /// \return true iff tracking is supported by \c MD. + static bool retrack(Metadata *&MD, Metadata *&New) { + return retrack(&MD, *MD, &New); + } + static bool retrack(void *Ref, Metadata &MD, void *New); + + /// \brief Check whether metadata is replaceable. + static bool isReplaceable(const Metadata &MD); + + typedef PointerUnion OwnerTy; + +private: + /// \brief Track a reference to metadata for an owner. + /// + /// Generalized version of tracking. + static bool track(void *Ref, Metadata &MD, OwnerTy Owner); +}; + +} // end namespace llvm + +#endif diff --git a/include/llvm/IR/Module.h b/include/llvm/IR/Module.h index 7fff80a..62f4194 100644 --- a/include/llvm/IR/Module.h +++ b/include/llvm/IR/Module.h @@ -33,8 +33,6 @@ class GVMaterializer; class LLVMContext; class RandomNumberGenerator; class StructType; -template struct DenseMapInfo; -template class DenseMap; template<> struct ilist_traits : public SymbolTableListTraits { @@ -150,7 +148,7 @@ public: /// The named metadata iterators. typedef NamedMDListType::iterator named_metadata_iterator; - /// The named metadata constant interators. + /// The named metadata constant iterators. typedef NamedMDListType::const_iterator const_named_metadata_iterator; /// This enumeration defines the supported behaviors of module flags. @@ -190,16 +188,16 @@ public: ModFlagBehaviorLastVal = AppendUnique }; - /// Checks if Value represents a valid ModFlagBehavior, and stores the + /// Checks if Metadata represents a valid ModFlagBehavior, and stores the /// converted result in MFB. - static bool isValidModFlagBehavior(Value *V, ModFlagBehavior &MFB); + static bool isValidModFlagBehavior(Metadata *MD, ModFlagBehavior &MFB); struct ModuleFlagEntry { ModFlagBehavior Behavior; MDString *Key; - Value *Val; - ModuleFlagEntry(ModFlagBehavior B, MDString *K, Value *V) - : Behavior(B), Key(K), Val(V) {} + Metadata *Val; + ModuleFlagEntry(ModFlagBehavior B, MDString *K, Metadata *V) + : Behavior(B), Key(K), Val(V) {} }; /// @} @@ -219,9 +217,8 @@ private: Materializer; ///< Used to materialize GlobalValues std::string ModuleID; ///< Human readable identifier for the module std::string TargetTriple; ///< Platform target triple Module compiled on + ///< Format: (arch)(sub)-(vendor)-(sys0-(abi) void *NamedMDSymTab; ///< NamedMDNode names. - // Allow lazy initialization in const method. - mutable RandomNumberGenerator *RNG; ///< The random number generator for this module. // We need to keep the string because the C API expects us to own the string // representation. @@ -251,6 +248,12 @@ public: /// @returns the module identifier as a string const std::string &getModuleIdentifier() const { return ModuleID; } + /// \brief Get a short "name" for the module. + /// + /// This is useful for debugging or logging. It is essentially a convenience + /// wrapper around getModuleIdentifier(). + StringRef getName() const { return ModuleID; } + /// Get the data layout string for the module's target platform. This is /// equivalent to getDataLayout()->getStringRepresentation(). const std::string &getDataLayoutStr() const { return DataLayoutStr; } @@ -270,10 +273,16 @@ public: /// @returns a string containing the module-scope inline assembly blocks. const std::string &getModuleInlineAsm() const { return GlobalScopeAsm; } - /// Get the RandomNumberGenerator for this module. The RNG can be - /// seeded via -rng-seed= and is salted with the ModuleID. - /// The returned RNG should not be shared across threads. - RandomNumberGenerator &getRNG() const; + /// Get a RandomNumberGenerator salted for use with this module. The + /// RNG can be seeded via -rng-seed= and is salted with the + /// ModuleID and the provided pass salt. The returned RNG should not + /// be shared across threads or passes. + /// + /// A unique RNG per pass ensures a reproducible random stream even + /// when other randomness consuming passes are added or removed. In + /// addition, the random stream will be reproducible across LLVM + /// versions when the pass does not change. + RandomNumberGenerator *createRNG(const Pass* P) const; /// @} /// @name Module Level Mutators @@ -327,6 +336,8 @@ public: /// name. StructType *getTypeByName(StringRef Name) const; + std::vector getIdentifiedStructTypes() const; + /// @} /// @name Function Accessors /// @{ @@ -441,7 +452,7 @@ public: /// Return the corresponding value if Key appears in module flags, otherwise /// return null. - Value *getModuleFlag(StringRef Key) const; + Metadata *getModuleFlag(StringRef Key) const; /// Returns the NamedMDNode in the module that represents module-level flags. /// This method returns null if there are no module-level flags. @@ -454,7 +465,8 @@ public: /// Add a module-level flag to the module-level flags metadata. It will create /// the module-level flags named metadata if it doesn't already exist. - void addModuleFlag(ModFlagBehavior Behavior, StringRef Key, Value *Val); + void addModuleFlag(ModFlagBehavior Behavior, StringRef Key, Metadata *Val); + void addModuleFlag(ModFlagBehavior Behavior, StringRef Key, Constant *Val); void addModuleFlag(ModFlagBehavior Behavior, StringRef Key, uint32_t Val); void addModuleFlag(MDNode *Node); @@ -483,7 +495,7 @@ public: std::error_code materialize(GlobalValue *GV); /// If the GlobalValue is read in, and if the GVMaterializer supports it, /// release the memory for the function, and set it up to be materialized - /// lazily. If !isDematerializable(), this method is a noop. + /// lazily. If !isDematerializable(), this method is a no-op. void Dematerialize(GlobalValue *GV); /// Make sure all GlobalValues in this Module are fully read. @@ -618,6 +630,15 @@ public: named_metadata_end()); } + /// Destroy ConstantArrays in LLVMContext if they are not used. + /// ConstantArrays constructed during linking can cause quadratic memory + /// explosion. Releasing all unused constants can cause a 20% LTO compile-time + /// slowdown for a large application. + /// + /// NOTE: Constants are currently owned by LLVMContext. This can then only + /// be called where all uses of the LLVMContext are understood. + void dropTriviallyDeadConstantArrays(); + /// @} /// @name Utility functions for printing and dumping Module objects /// @{ diff --git a/include/llvm/IR/Operator.h b/include/llvm/IR/Operator.h index 0933f21..46935ce 100644 --- a/include/llvm/IR/Operator.h +++ b/include/llvm/IR/Operator.h @@ -34,12 +34,12 @@ class Operator : public User { private: // The Operator class is intended to be used as a utility, and is never itself // instantiated. - void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; - void *operator new(size_t s) LLVM_DELETED_FUNCTION; - Operator() LLVM_DELETED_FUNCTION; + void *operator new(size_t, unsigned) = delete; + void *operator new(size_t s) = delete; + Operator() = delete; protected: - // NOTE: Cannot use LLVM_DELETED_FUNCTION because it's not legal to delete + // NOTE: Cannot use = delete because it's not legal to delete // an overridden method that's not deleted in the base class. Cannot leave // this unimplemented because that leads to an ODR-violation. ~Operator(); @@ -504,6 +504,20 @@ public: } }; +class BitCastOperator + : public ConcreteOperator { + friend class BitCastInst; + friend class ConstantExpr; + +public: + Type *getSrcTy() const { + return getOperand(0)->getType(); + } + + Type *getDestTy() const { + return getType(); + } +}; } // End llvm namespace diff --git a/include/llvm/IR/PassManager.h b/include/llvm/IR/PassManager.h index 45985e1..c92e7c9 100644 --- a/include/llvm/IR/PassManager.h +++ b/include/llvm/IR/PassManager.h @@ -43,6 +43,9 @@ #include "llvm/ADT/SmallPtrSet.h" #include "llvm/IR/Function.h" #include "llvm/IR/Module.h" +#include "llvm/IR/PassManagerInternal.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" #include "llvm/Support/type_traits.h" #include #include @@ -91,9 +94,12 @@ public: } /// \brief Mark a particular pass as preserved, adding it to the set. - template void preserve() { + template void preserve() { preserve(PassT::ID()); } + + /// \brief Mark an abstract PassID as preserved, adding it to the set. + void preserve(void *PassID) { if (!areAllPreserved()) - PreservedPassIDs.insert(PassT::ID()); + PreservedPassIDs.insert(PassID); } /// \brief Intersect this set with another in place. @@ -140,408 +146,115 @@ public: PreservedPassIDs.count(PassID); } + /// \brief Test whether all passes are preserved. + /// + /// This is used primarily to optimize for the case of no changes which will + /// common in many scenarios. + bool areAllPreserved() const { + return PreservedPassIDs.count((void *)AllPassesID); + } + private: // Note that this must not be -1 or -2 as those are already used by the // SmallPtrSet. static const uintptr_t AllPassesID = (intptr_t)(-3); - bool areAllPreserved() const { - return PreservedPassIDs.count((void *)AllPassesID); - } - SmallPtrSet PreservedPassIDs; }; -/// \brief Implementation details of the pass manager interfaces. -namespace detail { - -/// \brief Template for the abstract base class used to dispatch -/// polymorphically over pass objects. -template struct PassConcept { - // Boiler plate necessary for the container of derived classes. - virtual ~PassConcept() {} - - /// \brief The polymorphic API which runs the pass over a given IR entity. - /// - /// Note that actual pass object can omit the analysis manager argument if - /// desired. Also that the analysis manager may be null if there is no - /// analysis manager in the pass pipeline. - virtual PreservedAnalyses run(IRUnitT IR, AnalysisManagerT *AM) = 0; - - /// \brief Polymorphic method to access the name of a pass. - virtual StringRef name() = 0; -}; - -/// \brief SFINAE metafunction for computing whether \c PassT has a run method -/// accepting an \c AnalysisManagerT. -template -class PassRunAcceptsAnalysisManager { - typedef char SmallType; - struct BigType { - char a, b; - }; - - template - struct Checker; - - template static SmallType f(Checker *); - template static BigType f(...); +// Forward declare the analysis manager template. +template class AnalysisManager; -public: - enum { Value = sizeof(f(nullptr)) == sizeof(SmallType) }; -}; - -/// \brief A template wrapper used to implement the polymorphic API. +/// \brief Manages a sequence of passes over units of IR. /// -/// Can be instantiated for any object which provides a \c run method accepting -/// an \c IRUnitT. It requires the pass to be a copyable object. When the -/// \c run method also accepts an \c AnalysisManagerT*, we pass it along. -template ::Value> -struct PassModel; - -/// \brief Specialization of \c PassModel for passes that accept an analyis -/// manager. -template -struct PassModel - : PassConcept { - explicit PassModel(PassT Pass) : Pass(std::move(Pass)) {} - // We have to explicitly define all the special member functions because MSVC - // refuses to generate them. - PassModel(const PassModel &Arg) : Pass(Arg.Pass) {} - PassModel(PassModel &&Arg) : Pass(std::move(Arg.Pass)) {} - friend void swap(PassModel &LHS, PassModel &RHS) { - using std::swap; - swap(LHS.Pass, RHS.Pass); - } - PassModel &operator=(PassModel RHS) { - swap(*this, RHS); - return *this; - } - - PreservedAnalyses run(IRUnitT IR, AnalysisManagerT *AM) override { - return Pass.run(IR, AM); - } - StringRef name() override { return PassT::name(); } - PassT Pass; -}; - -/// \brief Specialization of \c PassModel for passes that accept an analyis -/// manager. -template -struct PassModel - : PassConcept { - explicit PassModel(PassT Pass) : Pass(std::move(Pass)) {} - // We have to explicitly define all the special member functions because MSVC - // refuses to generate them. - PassModel(const PassModel &Arg) : Pass(Arg.Pass) {} - PassModel(PassModel &&Arg) : Pass(std::move(Arg.Pass)) {} - friend void swap(PassModel &LHS, PassModel &RHS) { - using std::swap; - swap(LHS.Pass, RHS.Pass); - } - PassModel &operator=(PassModel RHS) { - swap(*this, RHS); - return *this; - } - - PreservedAnalyses run(IRUnitT IR, AnalysisManagerT *AM) override { - return Pass.run(IR); - } - StringRef name() override { return PassT::name(); } - PassT Pass; -}; - -/// \brief Abstract concept of an analysis result. +/// A pass manager contains a sequence of passes to run over units of IR. It is +/// itself a valid pass over that unit of IR, and when over some given IR will +/// run each pass in sequence. This is the primary and most basic building +/// block of a pass pipeline. /// -/// This concept is parameterized over the IR unit that this result pertains -/// to. -template struct AnalysisResultConcept { - virtual ~AnalysisResultConcept() {} - - /// \brief Method to try and mark a result as invalid. - /// - /// When the outer analysis manager detects a change in some underlying - /// unit of the IR, it will call this method on all of the results cached. - /// - /// This method also receives a set of preserved analyses which can be used - /// to avoid invalidation because the pass which changed the underlying IR - /// took care to update or preserve the analysis result in some way. - /// - /// \returns true if the result is indeed invalid (the default). - virtual bool invalidate(IRUnitT IR, const PreservedAnalyses &PA) = 0; -}; - -/// \brief SFINAE metafunction for computing whether \c ResultT provides an -/// \c invalidate member function. -template class ResultHasInvalidateMethod { - typedef char SmallType; - struct BigType { - char a, b; - }; - - template - struct Checker; - - template static SmallType f(Checker *); - template static BigType f(...); - +/// If it is run with an \c AnalysisManager argument, it will propagate +/// that analysis manager to each pass it runs, as well as calling the analysis +/// manager's invalidation routine with the PreservedAnalyses of each pass it +/// runs. +template class PassManager { public: - enum { Value = sizeof(f(nullptr)) == sizeof(SmallType) }; -}; - -/// \brief Wrapper to model the analysis result concept. -/// -/// By default, this will implement the invalidate method with a trivial -/// implementation so that the actual analysis result doesn't need to provide -/// an invalidation handler. It is only selected when the invalidation handler -/// is not part of the ResultT's interface. -template ::Value> -struct AnalysisResultModel; - -/// \brief Specialization of \c AnalysisResultModel which provides the default -/// invalidate functionality. -template -struct AnalysisResultModel - : AnalysisResultConcept { - explicit AnalysisResultModel(ResultT Result) : Result(std::move(Result)) {} - // We have to explicitly define all the special member functions because MSVC - // refuses to generate them. - AnalysisResultModel(const AnalysisResultModel &Arg) : Result(Arg.Result) {} - AnalysisResultModel(AnalysisResultModel &&Arg) - : Result(std::move(Arg.Result)) {} - friend void swap(AnalysisResultModel &LHS, AnalysisResultModel &RHS) { - using std::swap; - swap(LHS.Result, RHS.Result); - } - AnalysisResultModel &operator=(AnalysisResultModel RHS) { - swap(*this, RHS); - return *this; - } - - /// \brief The model bases invalidation solely on being in the preserved set. - // - // FIXME: We should actually use two different concepts for analysis results - // rather than two different models, and avoid the indirect function call for - // ones that use the trivial behavior. - bool invalidate(IRUnitT, const PreservedAnalyses &PA) override { - return !PA.preserved(PassT::ID()); - } - - ResultT Result; -}; - -/// \brief Specialization of \c AnalysisResultModel which delegates invalidate -/// handling to \c ResultT. -template -struct AnalysisResultModel - : AnalysisResultConcept { - explicit AnalysisResultModel(ResultT Result) : Result(std::move(Result)) {} + /// \brief Construct a pass manager. + /// + /// It can be passed a flag to get debug logging as the passes are run. + PassManager(bool DebugLogging = false) : DebugLogging(DebugLogging) {} // We have to explicitly define all the special member functions because MSVC // refuses to generate them. - AnalysisResultModel(const AnalysisResultModel &Arg) : Result(Arg.Result) {} - AnalysisResultModel(AnalysisResultModel &&Arg) - : Result(std::move(Arg.Result)) {} - friend void swap(AnalysisResultModel &LHS, AnalysisResultModel &RHS) { - using std::swap; - swap(LHS.Result, RHS.Result); - } - AnalysisResultModel &operator=(AnalysisResultModel RHS) { - swap(*this, RHS); + PassManager(PassManager &&Arg) + : Passes(std::move(Arg.Passes)), + DebugLogging(std::move(Arg.DebugLogging)) {} + PassManager &operator=(PassManager &&RHS) { + Passes = std::move(RHS.Passes); + DebugLogging = std::move(RHS.DebugLogging); return *this; } - /// \brief The model delegates to the \c ResultT method. - bool invalidate(IRUnitT IR, const PreservedAnalyses &PA) override { - return Result.invalidate(IR, PA); - } + /// \brief Run all of the passes in this manager over the IR. + PreservedAnalyses run(IRUnitT &IR, AnalysisManager *AM = nullptr) { + PreservedAnalyses PA = PreservedAnalyses::all(); - ResultT Result; -}; + if (DebugLogging) + dbgs() << "Starting pass manager run.\n"; -/// \brief Abstract concept of an analysis pass. -/// -/// This concept is parameterized over the IR unit that it can run over and -/// produce an analysis result. -template -struct AnalysisPassConcept { - virtual ~AnalysisPassConcept() {} - - /// \brief Method to run this analysis over a unit of IR. - /// \returns A unique_ptr to the analysis result object to be queried by - /// users. - virtual std::unique_ptr> - run(IRUnitT IR, AnalysisManagerT *AM) = 0; -}; + for (unsigned Idx = 0, Size = Passes.size(); Idx != Size; ++Idx) { + if (DebugLogging) + dbgs() << "Running pass: " << Passes[Idx]->name() << "\n"; -/// \brief Wrapper to model the analysis pass concept. -/// -/// Can wrap any type which implements a suitable \c run method. The method -/// must accept the IRUnitT as an argument and produce an object which can be -/// wrapped in a \c AnalysisResultModel. -template ::Value> -struct AnalysisPassModel; - -/// \brief Specialization of \c AnalysisPassModel which passes an -/// \c AnalysisManager to PassT's run method. -template -struct AnalysisPassModel - : AnalysisPassConcept { - explicit AnalysisPassModel(PassT Pass) : Pass(std::move(Pass)) {} - // We have to explicitly define all the special member functions because MSVC - // refuses to generate them. - AnalysisPassModel(const AnalysisPassModel &Arg) : Pass(Arg.Pass) {} - AnalysisPassModel(AnalysisPassModel &&Arg) : Pass(std::move(Arg.Pass)) {} - friend void swap(AnalysisPassModel &LHS, AnalysisPassModel &RHS) { - using std::swap; - swap(LHS.Pass, RHS.Pass); - } - AnalysisPassModel &operator=(AnalysisPassModel RHS) { - swap(*this, RHS); - return *this; - } - - // FIXME: Replace PassT::Result with type traits when we use C++11. - typedef AnalysisResultModel - ResultModelT; - - /// \brief The model delegates to the \c PassT::run method. - /// - /// The return is wrapped in an \c AnalysisResultModel. - std::unique_ptr> - run(IRUnitT IR, AnalysisManagerT *AM) override { - return make_unique(Pass.run(IR, AM)); - } + PreservedAnalyses PassPA = Passes[Idx]->run(IR, AM); - PassT Pass; -}; + // If we have an active analysis manager at this level we want to ensure + // we update it as each pass runs and potentially invalidates analyses. + // We also update the preserved set of analyses based on what analyses we + // have already handled the invalidation for here and don't need to + // invalidate when finished. + if (AM) + PassPA = AM->invalidate(IR, std::move(PassPA)); -/// \brief Specialization of \c AnalysisPassModel which does not pass an -/// \c AnalysisManager to PassT's run method. -template -struct AnalysisPassModel - : AnalysisPassConcept { - explicit AnalysisPassModel(PassT Pass) : Pass(std::move(Pass)) {} - // We have to explicitly define all the special member functions because MSVC - // refuses to generate them. - AnalysisPassModel(const AnalysisPassModel &Arg) : Pass(Arg.Pass) {} - AnalysisPassModel(AnalysisPassModel &&Arg) : Pass(std::move(Arg.Pass)) {} - friend void swap(AnalysisPassModel &LHS, AnalysisPassModel &RHS) { - using std::swap; - swap(LHS.Pass, RHS.Pass); - } - AnalysisPassModel &operator=(AnalysisPassModel RHS) { - swap(*this, RHS); - return *this; - } - - // FIXME: Replace PassT::Result with type traits when we use C++11. - typedef AnalysisResultModel - ResultModelT; - - /// \brief The model delegates to the \c PassT::run method. - /// - /// The return is wrapped in an \c AnalysisResultModel. - std::unique_ptr> - run(IRUnitT IR, AnalysisManagerT *) override { - return make_unique(Pass.run(IR)); - } - - PassT Pass; -}; + // Finally, we intersect the final preserved analyses to compute the + // aggregate preserved set for this pass manager. + PA.intersect(std::move(PassPA)); -} // End namespace detail + // FIXME: Historically, the pass managers all called the LLVM context's + // yield function here. We don't have a generic way to acquire the + // context and it isn't yet clear what the right pattern is for yielding + // in the new pass manager so it is currently omitted. + //IR.getContext().yield(); + } -class ModuleAnalysisManager; + if (DebugLogging) + dbgs() << "Finished pass manager run.\n"; -class ModulePassManager { -public: - // We have to explicitly define all the special member functions because MSVC - // refuses to generate them. - ModulePassManager() {} - ModulePassManager(ModulePassManager &&Arg) : Passes(std::move(Arg.Passes)) {} - ModulePassManager &operator=(ModulePassManager &&RHS) { - Passes = std::move(RHS.Passes); - return *this; + return PA; } - /// \brief Run all of the module passes in this module pass manager over - /// a module. - /// - /// This method should only be called for a single module as there is the - /// expectation that the lifetime of a pass is bounded to that of a module. - PreservedAnalyses run(Module *M, ModuleAnalysisManager *AM = nullptr); - - template void addPass(ModulePassT Pass) { - Passes.emplace_back(new ModulePassModel(std::move(Pass))); + template void addPass(PassT Pass) { + typedef detail::PassModel PassModelT; + Passes.emplace_back(new PassModelT(std::move(Pass))); } - static StringRef name() { return "ModulePassManager"; } + static StringRef name() { return "PassManager"; } private: - // Pull in the concept type and model template specialized for modules. - typedef detail::PassConcept - ModulePassConcept; - template - struct ModulePassModel - : detail::PassModel { - ModulePassModel(PassT Pass) - : detail::PassModel( - std::move(Pass)) {} - }; - - ModulePassManager(const ModulePassManager &) LLVM_DELETED_FUNCTION; - ModulePassManager &operator=(const ModulePassManager &) LLVM_DELETED_FUNCTION; + typedef detail::PassConcept PassConceptT; - std::vector> Passes; -}; + PassManager(const PassManager &) = delete; + PassManager &operator=(const PassManager &) = delete; -class FunctionAnalysisManager; + std::vector> Passes; -class FunctionPassManager { -public: - // We have to explicitly define all the special member functions because MSVC - // refuses to generate them. - FunctionPassManager() {} - FunctionPassManager(FunctionPassManager &&Arg) - : Passes(std::move(Arg.Passes)) {} - FunctionPassManager &operator=(FunctionPassManager &&RHS) { - Passes = std::move(RHS.Passes); - return *this; - } - - template void addPass(FunctionPassT Pass) { - Passes.emplace_back(new FunctionPassModel(std::move(Pass))); - } - - PreservedAnalyses run(Function *F, FunctionAnalysisManager *AM = nullptr); - - static StringRef name() { return "FunctionPassManager"; } + /// \brief Flag indicating whether we should do debug logging. + bool DebugLogging; +}; -private: - // Pull in the concept type and model template specialized for functions. - typedef detail::PassConcept - FunctionPassConcept; - template - struct FunctionPassModel - : detail::PassModel { - FunctionPassModel(PassT Pass) - : detail::PassModel( - std::move(Pass)) {} - }; +/// \brief Convenience typedef for a pass manager over modules. +typedef PassManager ModulePassManager; - FunctionPassManager(const FunctionPassManager &) LLVM_DELETED_FUNCTION; - FunctionPassManager & - operator=(const FunctionPassManager &) LLVM_DELETED_FUNCTION; - - std::vector> Passes; -}; +/// \brief Convenience typedef for a pass manager over functions. +typedef PassManager FunctionPassManager; namespace detail { @@ -556,19 +269,25 @@ namespace detail { /// - invalidateImpl /// /// The details of the call pattern are within. +/// +/// Note that there is also a generic analysis manager template which implements +/// the above required functions along with common datastructures used for +/// managing analyses. This base class is factored so that if you need to +/// customize the handling of a specific IR unit, you can do so without +/// replicating *all* of the boilerplate. template class AnalysisManagerBase { DerivedT *derived_this() { return static_cast(this); } const DerivedT *derived_this() const { return static_cast(this); } - AnalysisManagerBase(const AnalysisManagerBase &) LLVM_DELETED_FUNCTION; + AnalysisManagerBase(const AnalysisManagerBase &) = delete; AnalysisManagerBase & - operator=(const AnalysisManagerBase &) LLVM_DELETED_FUNCTION; + operator=(const AnalysisManagerBase &) = delete; protected: typedef detail::AnalysisResultConcept ResultConceptT; - typedef detail::AnalysisPassConcept PassConceptT; + typedef detail::AnalysisPassConcept PassConceptT; // FIXME: Provide template aliases for the models when we're using C++11 in // a mode supporting them. @@ -588,7 +307,7 @@ public: /// /// If there is not a valid cached result in the manager already, this will /// re-run the analysis to produce a valid result. - template typename PassT::Result &getResult(IRUnitT IR) { + template typename PassT::Result &getResult(IRUnitT &IR) { assert(AnalysisPasses.count(PassT::ID()) && "This analysis pass was not registered prior to being queried"); @@ -605,7 +324,7 @@ public: /// /// \returns null if there is no cached result. template - typename PassT::Result *getCachedResult(IRUnitT IR) const { + typename PassT::Result *getCachedResult(IRUnitT &IR) const { assert(AnalysisPasses.count(PassT::ID()) && "This analysis pass was not registered prior to being queried"); @@ -627,25 +346,28 @@ public: template void registerPass(PassT Pass) { assert(!AnalysisPasses.count(PassT::ID()) && "Registered the same analysis pass twice!"); - typedef detail::AnalysisPassModel PassModelT; + typedef detail::AnalysisPassModel PassModelT; AnalysisPasses[PassT::ID()].reset(new PassModelT(std::move(Pass))); } /// \brief Invalidate a specific analysis pass for an IR module. /// /// Note that the analysis result can disregard invalidation. - template void invalidate(Module *M) { + template void invalidate(IRUnitT &IR) { assert(AnalysisPasses.count(PassT::ID()) && "This analysis pass was not registered prior to being invalidated"); - derived_this()->invalidateImpl(PassT::ID(), M); + derived_this()->invalidateImpl(PassT::ID(), IR); } /// \brief Invalidate analyses cached for an IR unit. /// /// Walk through all of the analyses pertaining to this unit of IR and /// invalidate them unless they are preserved by the PreservedAnalyses set. - void invalidate(IRUnitT IR, const PreservedAnalyses &PA) { - derived_this()->invalidateImpl(IR, PA); + /// We accept the PreservedAnalyses set by value and update it with each + /// analyis pass which has been successfully invalidated and thus can be + /// preserved going forward. The updated set is returned. + PreservedAnalyses invalidate(IRUnitT &IR, PreservedAnalyses PA) { + return derived_this()->invalidateImpl(IR, std::move(PA)); } protected: @@ -675,108 +397,153 @@ private: } // End namespace detail -/// \brief A module analysis pass manager with lazy running and caching of +/// \brief A generic analysis pass manager with lazy running and caching of /// results. -class ModuleAnalysisManager - : public detail::AnalysisManagerBase { - friend class detail::AnalysisManagerBase; - typedef detail::AnalysisManagerBase BaseT; - typedef BaseT::ResultConceptT ResultConceptT; - typedef BaseT::PassConceptT PassConceptT; - -public: - // We have to explicitly define all the special member functions because MSVC - // refuses to generate them. - ModuleAnalysisManager() {} - ModuleAnalysisManager(ModuleAnalysisManager &&Arg) - : BaseT(std::move(static_cast(Arg))), - ModuleAnalysisResults(std::move(Arg.ModuleAnalysisResults)) {} - ModuleAnalysisManager &operator=(ModuleAnalysisManager &&RHS) { - BaseT::operator=(std::move(static_cast(RHS))); - ModuleAnalysisResults = std::move(RHS.ModuleAnalysisResults); - return *this; - } - -private: - ModuleAnalysisManager(const ModuleAnalysisManager &) LLVM_DELETED_FUNCTION; - ModuleAnalysisManager & - operator=(const ModuleAnalysisManager &) LLVM_DELETED_FUNCTION; - - /// \brief Get a module pass result, running the pass if necessary. - ResultConceptT &getResultImpl(void *PassID, Module *M); - - /// \brief Get a cached module pass result or return null. - ResultConceptT *getCachedResultImpl(void *PassID, Module *M) const; - - /// \brief Invalidate a module pass result. - void invalidateImpl(void *PassID, Module *M); - - /// \brief Invalidate results across a module. - void invalidateImpl(Module *M, const PreservedAnalyses &PA); - - /// \brief Map type from module analysis pass ID to pass result concept - /// pointer. - typedef DenseMap>> - ModuleAnalysisResultMapT; - - /// \brief Cache of computed module analysis results for this module. - ModuleAnalysisResultMapT ModuleAnalysisResults; -}; - -/// \brief A function analysis manager to coordinate and cache analyses run over -/// a module. -class FunctionAnalysisManager - : public detail::AnalysisManagerBase { - friend class detail::AnalysisManagerBase; - typedef detail::AnalysisManagerBase - BaseT; - typedef BaseT::ResultConceptT ResultConceptT; - typedef BaseT::PassConceptT PassConceptT; +/// +/// This analysis manager can be used for any IR unit where the address of the +/// IR unit sufficies as its identity. It manages the cache for a unit of IR via +/// the address of each unit of IR cached. +template +class AnalysisManager + : public detail::AnalysisManagerBase, IRUnitT> { + friend class detail::AnalysisManagerBase, IRUnitT>; + typedef detail::AnalysisManagerBase, IRUnitT> BaseT; + typedef typename BaseT::ResultConceptT ResultConceptT; + typedef typename BaseT::PassConceptT PassConceptT; public: // Most public APIs are inherited from the CRTP base class. + /// \brief Construct an empty analysis manager. + /// + /// A flag can be passed to indicate that the manager should perform debug + /// logging. + AnalysisManager(bool DebugLogging = false) : DebugLogging(DebugLogging) {} + // We have to explicitly define all the special member functions because MSVC // refuses to generate them. - FunctionAnalysisManager() {} - FunctionAnalysisManager(FunctionAnalysisManager &&Arg) + AnalysisManager(AnalysisManager &&Arg) : BaseT(std::move(static_cast(Arg))), - FunctionAnalysisResults(std::move(Arg.FunctionAnalysisResults)) {} - FunctionAnalysisManager &operator=(FunctionAnalysisManager &&RHS) { + AnalysisResults(std::move(Arg.AnalysisResults)), + DebugLogging(std::move(Arg.DebugLogging)) {} + AnalysisManager &operator=(AnalysisManager &&RHS) { BaseT::operator=(std::move(static_cast(RHS))); - FunctionAnalysisResults = std::move(RHS.FunctionAnalysisResults); + AnalysisResults = std::move(RHS.AnalysisResults); + DebugLogging = std::move(RHS.DebugLogging); return *this; } /// \brief Returns true if the analysis manager has an empty results cache. - bool empty() const; + bool empty() const { + assert(AnalysisResults.empty() == AnalysisResultLists.empty() && + "The storage and index of analysis results disagree on how many " + "there are!"); + return AnalysisResults.empty(); + } - /// \brief Clear the function analysis result cache. + /// \brief Clear the analysis result cache. /// - /// This routine allows cleaning up when the set of functions itself has + /// This routine allows cleaning up when the set of IR units itself has /// potentially changed, and thus we can't even look up a a result and - /// invalidate it directly. Notably, this does *not* call invalidate - /// functions as there is nothing to be done for them. - void clear(); + /// invalidate it directly. Notably, this does *not* call invalidate functions + /// as there is nothing to be done for them. + void clear() { + AnalysisResults.clear(); + AnalysisResultLists.clear(); + } private: - FunctionAnalysisManager(const FunctionAnalysisManager &) - LLVM_DELETED_FUNCTION; - FunctionAnalysisManager & - operator=(const FunctionAnalysisManager &) LLVM_DELETED_FUNCTION; + AnalysisManager(const AnalysisManager &) = delete; + AnalysisManager &operator=(const AnalysisManager &) = delete; + + /// \brief Get an analysis result, running the pass if necessary. + ResultConceptT &getResultImpl(void *PassID, IRUnitT &IR) { + typename AnalysisResultMapT::iterator RI; + bool Inserted; + std::tie(RI, Inserted) = AnalysisResults.insert(std::make_pair( + std::make_pair(PassID, &IR), typename AnalysisResultListT::iterator())); + + // If we don't have a cached result for this function, look up the pass and + // run it to produce a result, which we then add to the cache. + if (Inserted) { + auto &P = this->lookupPass(PassID); + if (DebugLogging) + dbgs() << "Running analysis: " << P.name() << "\n"; + AnalysisResultListT &ResultList = AnalysisResultLists[&IR]; + ResultList.emplace_back(PassID, P.run(IR, this)); + RI->second = std::prev(ResultList.end()); + } - /// \brief Get a function pass result, running the pass if necessary. - ResultConceptT &getResultImpl(void *PassID, Function *F); + return *RI->second->second; + } - /// \brief Get a cached function pass result or return null. - ResultConceptT *getCachedResultImpl(void *PassID, Function *F) const; + /// \brief Get a cached analysis result or return null. + ResultConceptT *getCachedResultImpl(void *PassID, IRUnitT &IR) const { + typename AnalysisResultMapT::const_iterator RI = + AnalysisResults.find(std::make_pair(PassID, &IR)); + return RI == AnalysisResults.end() ? nullptr : &*RI->second->second; + } /// \brief Invalidate a function pass result. - void invalidateImpl(void *PassID, Function *F); + void invalidateImpl(void *PassID, IRUnitT &IR) { + typename AnalysisResultMapT::iterator RI = + AnalysisResults.find(std::make_pair(PassID, &IR)); + if (RI == AnalysisResults.end()) + return; + + if (DebugLogging) + dbgs() << "Invalidating analysis: " << this->lookupPass(PassID).name() + << "\n"; + AnalysisResultLists[&IR].erase(RI->second); + AnalysisResults.erase(RI); + } /// \brief Invalidate the results for a function.. - void invalidateImpl(Function *F, const PreservedAnalyses &PA); + PreservedAnalyses invalidateImpl(IRUnitT &IR, PreservedAnalyses PA) { + // Short circuit for a common case of all analyses being preserved. + if (PA.areAllPreserved()) + return std::move(PA); + + if (DebugLogging) + dbgs() << "Invalidating all non-preserved analyses for: " + << IR.getName() << "\n"; + + // Clear all the invalidated results associated specifically with this + // function. + SmallVector InvalidatedPassIDs; + AnalysisResultListT &ResultsList = AnalysisResultLists[&IR]; + for (typename AnalysisResultListT::iterator I = ResultsList.begin(), + E = ResultsList.end(); + I != E;) { + void *PassID = I->first; + + // Pass the invalidation down to the pass itself to see if it thinks it is + // necessary. The analysis pass can return false if no action on the part + // of the analysis manager is required for this invalidation event. + if (I->second->invalidate(IR, PA)) { + if (DebugLogging) + dbgs() << "Invalidating analysis: " << this->lookupPass(PassID).name() + << "\n"; + + InvalidatedPassIDs.push_back(I->first); + I = ResultsList.erase(I); + } else { + ++I; + } + + // After handling each pass, we mark it as preserved. Once we've + // invalidated any stale results, the rest of the system is allowed to + // start preserving this analysis again. + PA.preserve(PassID); + } + while (!InvalidatedPassIDs.empty()) + AnalysisResults.erase( + std::make_pair(InvalidatedPassIDs.pop_back_val(), &IR)); + if (ResultsList.empty()) + AnalysisResultLists.erase(&IR); + + return std::move(PA); + } /// \brief List of function analysis pass IDs and associated concept pointers. /// @@ -784,30 +551,37 @@ private: /// erases. Provides both the pass ID and concept pointer such that it is /// half of a bijection and provides storage for the actual result concept. typedef std::list>>> - FunctionAnalysisResultListT; + void *, std::unique_ptr>>> + AnalysisResultListT; /// \brief Map type from function pointer to our custom list type. - typedef DenseMap - FunctionAnalysisResultListMapT; + typedef DenseMap AnalysisResultListMapT; /// \brief Map from function to a list of function analysis results. /// /// Provides linear time removal of all analysis results for a function and /// the ultimate storage for a particular cached analysis result. - FunctionAnalysisResultListMapT FunctionAnalysisResultLists; + AnalysisResultListMapT AnalysisResultLists; /// \brief Map type from a pair of analysis ID and function pointer to an /// iterator into a particular result list. - typedef DenseMap, - FunctionAnalysisResultListT::iterator> - FunctionAnalysisResultMapT; + typedef DenseMap, + typename AnalysisResultListT::iterator> AnalysisResultMapT; /// \brief Map from an analysis ID and function to a particular cached /// analysis result. - FunctionAnalysisResultMapT FunctionAnalysisResults; + AnalysisResultMapT AnalysisResults; + + /// \brief A flag indicating whether debug logging is enabled. + bool DebugLogging; }; +/// \brief Convenience typedef for the Module analysis manager. +typedef AnalysisManager ModuleAnalysisManager; + +/// \brief Convenience typedef for the Function analysis manager. +typedef AnalysisManager FunctionAnalysisManager; + /// \brief A module analysis which acts as a proxy for a function analysis /// manager. /// @@ -822,6 +596,8 @@ public: static void *ID() { return (void *)&PassID; } + static StringRef name() { return "FunctionAnalysisManagerModuleProxy"; } + explicit FunctionAnalysisManagerModuleProxy(FunctionAnalysisManager &FAM) : FAM(&FAM) {} // We have to explicitly define all the special member functions because MSVC @@ -846,7 +622,7 @@ public: /// In debug builds, it will also assert that the analysis manager is empty /// as no queries should arrive at the function analysis manager prior to /// this analysis being requested. - Result run(Module *M); + Result run(Module &M); private: static char PassID; @@ -884,7 +660,7 @@ public: /// Regardless of whether this analysis is marked as preserved, all of the /// analyses in the \c FunctionAnalysisManager are potentially invalidated /// based on the set of preserved analyses. - bool invalidate(Module *M, const PreservedAnalyses &PA); + bool invalidate(Module &M, const PreservedAnalyses &PA); private: FunctionAnalysisManager *FAM; @@ -920,7 +696,7 @@ public: const ModuleAnalysisManager &getManager() const { return *MAM; } /// \brief Handle invalidation by ignoring it, this pass is immutable. - bool invalidate(Function *) { return false; } + bool invalidate(Function &) { return false; } private: const ModuleAnalysisManager *MAM; @@ -928,6 +704,8 @@ public: static void *ID() { return (void *)&PassID; } + static StringRef name() { return "ModuleAnalysisManagerFunctionProxy"; } + ModuleAnalysisManagerFunctionProxy(const ModuleAnalysisManager &MAM) : MAM(&MAM) {} // We have to explicitly define all the special member functions because MSVC @@ -946,7 +724,7 @@ public: /// \brief Run the analysis pass and create our proxy result object. /// Nothing to see here, it just forwards the \c MAM reference into the /// result. - Result run(Function *) { return Result(*MAM); } + Result run(Function &) { return Result(*MAM); } private: static char PassID; @@ -962,6 +740,20 @@ private: /// \c FunctionAnalysisManagerModuleProxy analysis prior to running the function /// pass over the module to enable a \c FunctionAnalysisManager to be used /// within this run safely. +/// +/// Function passes run within this adaptor can rely on having exclusive access +/// to the function they are run over. They should not read or modify any other +/// functions! Other threads or systems may be manipulating other functions in +/// the module, and so their state should never be relied on. +/// FIXME: Make the above true for all of LLVM's actual passes, some still +/// violate this principle. +/// +/// Function passes can also read the module containing the function, but they +/// should not modify that module outside of the use lists of various globals. +/// For example, a function pass is not permitted to add functions to the +/// module. +/// FIXME: Make the above true for all of LLVM's actual passes, some still +/// violate this principle. template class ModuleToFunctionPassAdaptor { public: explicit ModuleToFunctionPassAdaptor(FunctionPassT Pass) @@ -972,7 +764,8 @@ public: : Pass(Arg.Pass) {} ModuleToFunctionPassAdaptor(ModuleToFunctionPassAdaptor &&Arg) : Pass(std::move(Arg.Pass)) {} - friend void swap(ModuleToFunctionPassAdaptor &LHS, ModuleToFunctionPassAdaptor &RHS) { + friend void swap(ModuleToFunctionPassAdaptor &LHS, + ModuleToFunctionPassAdaptor &RHS) { using std::swap; swap(LHS.Pass, RHS.Pass); } @@ -982,21 +775,26 @@ public: } /// \brief Runs the function pass across every function in the module. - PreservedAnalyses run(Module *M, ModuleAnalysisManager *AM) { + PreservedAnalyses run(Module &M, ModuleAnalysisManager *AM) { FunctionAnalysisManager *FAM = nullptr; if (AM) // Setup the function analysis manager from its proxy. FAM = &AM->getResult(M).getManager(); PreservedAnalyses PA = PreservedAnalyses::all(); - for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) { - PreservedAnalyses PassPA = Pass.run(I, FAM); + for (Function &F : M) { + if (F.isDeclaration()) + continue; + + PreservedAnalyses PassPA = Pass.run(F, FAM); // We know that the function pass couldn't have invalidated any other // function's analyses (that's the contract of a function pass), so - // directly handle the function analysis manager's invalidation here. + // directly handle the function analysis manager's invalidation here and + // update our preserved set to reflect that these have already been + // handled. if (FAM) - FAM->invalidate(I, PassPA); + PassPA = FAM->invalidate(F, std::move(PassPA)); // Then intersect the preserved set so that invalidation of module // analyses will eventually occur when the module pass completes. @@ -1025,6 +823,66 @@ createModuleToFunctionPassAdaptor(FunctionPassT Pass) { return std::move(ModuleToFunctionPassAdaptor(std::move(Pass))); } +/// \brief A template utility pass to force an analysis result to be available. +/// +/// This is a no-op pass which simply forces a specific analysis pass's result +/// to be available when it is run. +template struct RequireAnalysisPass { + /// \brief Run this pass over some unit of IR. + /// + /// This pass can be run over any unit of IR and use any analysis manager + /// provided they satisfy the basic API requirements. When this pass is + /// created, these methods can be instantiated to satisfy whatever the + /// context requires. + template + PreservedAnalyses run(IRUnitT &Arg, AnalysisManager *AM) { + if (AM) + (void)AM->template getResult(Arg); + + return PreservedAnalyses::all(); + } + + static StringRef name() { return "RequireAnalysisPass"; } +}; + +/// \brief A template utility pass to force an analysis result to be +/// invalidated. +/// +/// This is a no-op pass which simply forces a specific analysis result to be +/// invalidated when it is run. +template struct InvalidateAnalysisPass { + /// \brief Run this pass over some unit of IR. + /// + /// This pass can be run over any unit of IR and use any analysis manager + /// provided they satisfy the basic API requirements. When this pass is + /// created, these methods can be instantiated to satisfy whatever the + /// context requires. + template + PreservedAnalyses run(IRUnitT &Arg, AnalysisManager *AM) { + if (AM) + // We have to directly invalidate the analysis result as we can't + // enumerate all other analyses and use the preserved set to control it. + (void)AM->template invalidate(Arg); + + return PreservedAnalyses::all(); + } + + static StringRef name() { return "InvalidateAnalysisPass"; } +}; + +/// \brief A utility pass that does nothing but preserves no analyses. +/// +/// As a consequence fo not preserving any analyses, this pass will force all +/// analysis passes to be re-run to produce fresh results if any are needed. +struct InvalidateAllAnalysesPass { + /// \brief Run this pass over some unit of IR. + template PreservedAnalyses run(IRUnitT &Arg) { + return PreservedAnalyses::none(); + } + + static StringRef name() { return "InvalidateAllAnalysesPass"; } +}; + } #endif diff --git a/include/llvm/IR/PassManagerInternal.h b/include/llvm/IR/PassManagerInternal.h new file mode 100644 index 0000000..297f5f4 --- /dev/null +++ b/include/llvm/IR/PassManagerInternal.h @@ -0,0 +1,349 @@ +//===- PassManager internal APIs and implementation details -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// +/// This header provides internal APIs and implementation details used by the +/// pass management interfaces exposed in PassManager.h. To understand more +/// context of why these particular interfaces are needed, see that header +/// file. None of these APIs should be used elsewhere. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_PASSMANAGERINTERNAL_H +#define LLVM_IR_PASSMANAGERINTERNAL_H + +#include "llvm/ADT/StringRef.h" + +namespace llvm { + +template class AnalysisManager; +class PreservedAnalyses; + +/// \brief Implementation details of the pass manager interfaces. +namespace detail { + +/// \brief Template for the abstract base class used to dispatch +/// polymorphically over pass objects. +template struct PassConcept { + // Boiler plate necessary for the container of derived classes. + virtual ~PassConcept() {} + + /// \brief The polymorphic API which runs the pass over a given IR entity. + /// + /// Note that actual pass object can omit the analysis manager argument if + /// desired. Also that the analysis manager may be null if there is no + /// analysis manager in the pass pipeline. + virtual PreservedAnalyses run(IRUnitT &IR, AnalysisManager *AM) = 0; + + /// \brief Polymorphic method to access the name of a pass. + virtual StringRef name() = 0; +}; + +/// \brief SFINAE metafunction for computing whether \c PassT has a run method +/// accepting an \c AnalysisManager. +template +class PassRunAcceptsAnalysisManager { + typedef char SmallType; + struct BigType { + char a, b; + }; + + template *)> + struct Checker; + + template static SmallType f(Checker *); + template static BigType f(...); + +public: + enum { Value = sizeof(f(nullptr)) == sizeof(SmallType) }; +}; + +/// \brief A template wrapper used to implement the polymorphic API. +/// +/// Can be instantiated for any object which provides a \c run method accepting +/// an \c IRUnitT. It requires the pass to be a copyable object. When the +/// \c run method also accepts an \c AnalysisManager*, we pass it +/// along. +template ::Value> +struct PassModel; + +/// \brief Specialization of \c PassModel for passes that accept an analyis +/// manager. +template +struct PassModel + : PassConcept { + explicit PassModel(PassT Pass) : Pass(std::move(Pass)) {} + // We have to explicitly define all the special member functions because MSVC + // refuses to generate them. + PassModel(const PassModel &Arg) : Pass(Arg.Pass) {} + PassModel(PassModel &&Arg) : Pass(std::move(Arg.Pass)) {} + friend void swap(PassModel &LHS, PassModel &RHS) { + using std::swap; + swap(LHS.Pass, RHS.Pass); + } + PassModel &operator=(PassModel RHS) { + swap(*this, RHS); + return *this; + } + + PreservedAnalysesT run(IRUnitT &IR, AnalysisManager *AM) override { + return Pass.run(IR, AM); + } + StringRef name() override { return PassT::name(); } + PassT Pass; +}; + +/// \brief Specialization of \c PassModel for passes that accept an analyis +/// manager. +template +struct PassModel + : PassConcept { + explicit PassModel(PassT Pass) : Pass(std::move(Pass)) {} + // We have to explicitly define all the special member functions because MSVC + // refuses to generate them. + PassModel(const PassModel &Arg) : Pass(Arg.Pass) {} + PassModel(PassModel &&Arg) : Pass(std::move(Arg.Pass)) {} + friend void swap(PassModel &LHS, PassModel &RHS) { + using std::swap; + swap(LHS.Pass, RHS.Pass); + } + PassModel &operator=(PassModel RHS) { + swap(*this, RHS); + return *this; + } + + PreservedAnalysesT run(IRUnitT &IR, AnalysisManager *AM) override { + return Pass.run(IR); + } + StringRef name() override { return PassT::name(); } + PassT Pass; +}; + +/// \brief Abstract concept of an analysis result. +/// +/// This concept is parameterized over the IR unit that this result pertains +/// to. +template struct AnalysisResultConcept { + virtual ~AnalysisResultConcept() {} + + /// \brief Method to try and mark a result as invalid. + /// + /// When the outer analysis manager detects a change in some underlying + /// unit of the IR, it will call this method on all of the results cached. + /// + /// This method also receives a set of preserved analyses which can be used + /// to avoid invalidation because the pass which changed the underlying IR + /// took care to update or preserve the analysis result in some way. + /// + /// \returns true if the result is indeed invalid (the default). + virtual bool invalidate(IRUnitT &IR, const PreservedAnalyses &PA) = 0; +}; + +/// \brief SFINAE metafunction for computing whether \c ResultT provides an +/// \c invalidate member function. +template class ResultHasInvalidateMethod { + typedef char SmallType; + struct BigType { + char a, b; + }; + + template + struct Checker; + + template static SmallType f(Checker *); + template static BigType f(...); + +public: + enum { Value = sizeof(f(nullptr)) == sizeof(SmallType) }; +}; + +/// \brief Wrapper to model the analysis result concept. +/// +/// By default, this will implement the invalidate method with a trivial +/// implementation so that the actual analysis result doesn't need to provide +/// an invalidation handler. It is only selected when the invalidation handler +/// is not part of the ResultT's interface. +template ::Value> +struct AnalysisResultModel; + +/// \brief Specialization of \c AnalysisResultModel which provides the default +/// invalidate functionality. +template +struct AnalysisResultModel + : AnalysisResultConcept { + explicit AnalysisResultModel(ResultT Result) : Result(std::move(Result)) {} + // We have to explicitly define all the special member functions because MSVC + // refuses to generate them. + AnalysisResultModel(const AnalysisResultModel &Arg) : Result(Arg.Result) {} + AnalysisResultModel(AnalysisResultModel &&Arg) + : Result(std::move(Arg.Result)) {} + friend void swap(AnalysisResultModel &LHS, AnalysisResultModel &RHS) { + using std::swap; + swap(LHS.Result, RHS.Result); + } + AnalysisResultModel &operator=(AnalysisResultModel RHS) { + swap(*this, RHS); + return *this; + } + + /// \brief The model bases invalidation solely on being in the preserved set. + // + // FIXME: We should actually use two different concepts for analysis results + // rather than two different models, and avoid the indirect function call for + // ones that use the trivial behavior. + bool invalidate(IRUnitT &, const PreservedAnalysesT &PA) override { + return !PA.preserved(PassT::ID()); + } + + ResultT Result; +}; + +/// \brief Specialization of \c AnalysisResultModel which delegates invalidate +/// handling to \c ResultT. +template +struct AnalysisResultModel + : AnalysisResultConcept { + explicit AnalysisResultModel(ResultT Result) : Result(std::move(Result)) {} + // We have to explicitly define all the special member functions because MSVC + // refuses to generate them. + AnalysisResultModel(const AnalysisResultModel &Arg) : Result(Arg.Result) {} + AnalysisResultModel(AnalysisResultModel &&Arg) + : Result(std::move(Arg.Result)) {} + friend void swap(AnalysisResultModel &LHS, AnalysisResultModel &RHS) { + using std::swap; + swap(LHS.Result, RHS.Result); + } + AnalysisResultModel &operator=(AnalysisResultModel RHS) { + swap(*this, RHS); + return *this; + } + + /// \brief The model delegates to the \c ResultT method. + bool invalidate(IRUnitT &IR, const PreservedAnalysesT &PA) override { + return Result.invalidate(IR, PA); + } + + ResultT Result; +}; + +/// \brief Abstract concept of an analysis pass. +/// +/// This concept is parameterized over the IR unit that it can run over and +/// produce an analysis result. +template struct AnalysisPassConcept { + virtual ~AnalysisPassConcept() {} + + /// \brief Method to run this analysis over a unit of IR. + /// \returns A unique_ptr to the analysis result object to be queried by + /// users. + virtual std::unique_ptr> + run(IRUnitT &IR, AnalysisManager *AM) = 0; + + /// \brief Polymorphic method to access the name of a pass. + virtual StringRef name() = 0; +}; + +/// \brief Wrapper to model the analysis pass concept. +/// +/// Can wrap any type which implements a suitable \c run method. The method +/// must accept the IRUnitT as an argument and produce an object which can be +/// wrapped in a \c AnalysisResultModel. +template ::Value> +struct AnalysisPassModel; + +/// \brief Specialization of \c AnalysisPassModel which passes an +/// \c AnalysisManager to PassT's run method. +template +struct AnalysisPassModel : AnalysisPassConcept { + explicit AnalysisPassModel(PassT Pass) : Pass(std::move(Pass)) {} + // We have to explicitly define all the special member functions because MSVC + // refuses to generate them. + AnalysisPassModel(const AnalysisPassModel &Arg) : Pass(Arg.Pass) {} + AnalysisPassModel(AnalysisPassModel &&Arg) : Pass(std::move(Arg.Pass)) {} + friend void swap(AnalysisPassModel &LHS, AnalysisPassModel &RHS) { + using std::swap; + swap(LHS.Pass, RHS.Pass); + } + AnalysisPassModel &operator=(AnalysisPassModel RHS) { + swap(*this, RHS); + return *this; + } + + // FIXME: Replace PassT::Result with type traits when we use C++11. + typedef AnalysisResultModel + ResultModelT; + + /// \brief The model delegates to the \c PassT::run method. + /// + /// The return is wrapped in an \c AnalysisResultModel. + std::unique_ptr> + run(IRUnitT &IR, AnalysisManager *AM) override { + return make_unique(Pass.run(IR, AM)); + } + + /// \brief The model delegates to a static \c PassT::name method. + /// + /// The returned string ref must point to constant immutable data! + StringRef name() override { return PassT::name(); } + + PassT Pass; +}; + +/// \brief Specialization of \c AnalysisPassModel which does not pass an +/// \c AnalysisManager to PassT's run method. +template +struct AnalysisPassModel : AnalysisPassConcept { + explicit AnalysisPassModel(PassT Pass) : Pass(std::move(Pass)) {} + // We have to explicitly define all the special member functions because MSVC + // refuses to generate them. + AnalysisPassModel(const AnalysisPassModel &Arg) : Pass(Arg.Pass) {} + AnalysisPassModel(AnalysisPassModel &&Arg) : Pass(std::move(Arg.Pass)) {} + friend void swap(AnalysisPassModel &LHS, AnalysisPassModel &RHS) { + using std::swap; + swap(LHS.Pass, RHS.Pass); + } + AnalysisPassModel &operator=(AnalysisPassModel RHS) { + swap(*this, RHS); + return *this; + } + + // FIXME: Replace PassT::Result with type traits when we use C++11. + typedef AnalysisResultModel + ResultModelT; + + /// \brief The model delegates to the \c PassT::run method. + /// + /// The return is wrapped in an \c AnalysisResultModel. + std::unique_ptr> + run(IRUnitT &IR, AnalysisManager *) override { + return make_unique(Pass.run(IR)); + } + + /// \brief The model delegates to a static \c PassT::name method. + /// + /// The returned string ref must point to constant immutable data! + StringRef name() override { return PassT::name(); } + + PassT Pass; +}; + +} // End namespace detail +} + +#endif diff --git a/include/llvm/IR/PatternMatch.h b/include/llvm/IR/PatternMatch.h index 4783062..f94e105 100644 --- a/include/llvm/IR/PatternMatch.h +++ b/include/llvm/IR/PatternMatch.h @@ -38,55 +38,58 @@ namespace llvm { namespace PatternMatch { -template -bool match(Val *V, const Pattern &P) { - return const_cast(P).match(V); +template bool match(Val *V, const Pattern &P) { + return const_cast(P).match(V); } - -template -struct OneUse_match { +template struct OneUse_match { SubPattern_t SubPattern; OneUse_match(const SubPattern_t &SP) : SubPattern(SP) {} - template - bool match(OpTy *V) { + template bool match(OpTy *V) { return V->hasOneUse() && SubPattern.match(V); } }; -template -inline OneUse_match m_OneUse(const T &SubPattern) { return SubPattern; } - +template inline OneUse_match m_OneUse(const T &SubPattern) { + return SubPattern; +} -template -struct class_match { - template - bool match(ITy *V) { return isa(V); } +template struct class_match { + template bool match(ITy *V) { return isa(V); } }; -/// m_Value() - Match an arbitrary value and ignore it. +/// \brief Match an arbitrary value and ignore it. inline class_match m_Value() { return class_match(); } -/// m_ConstantInt() - Match an arbitrary ConstantInt and ignore it. + +/// \brief Match an arbitrary binary operation and ignore it. +inline class_match m_BinOp() { + return class_match(); +} + +/// \brief Matches any compare instruction and ignore it. +inline class_match m_Cmp() { return class_match(); } + +/// \brief Match an arbitrary ConstantInt and ignore it. inline class_match m_ConstantInt() { return class_match(); } -/// m_Undef() - Match an arbitrary undef constant. + +/// \brief Match an arbitrary undef constant. inline class_match m_Undef() { return class_match(); } +/// \brief Match an arbitrary Constant and ignore it. inline class_match m_Constant() { return class_match(); } /// Matching combinators -template -struct match_combine_or { +template struct match_combine_or { LTy L; RTy R; - match_combine_or(const LTy &Left, const RTy &Right) : L(Left), R(Right) { } + match_combine_or(const LTy &Left, const RTy &Right) : L(Left), R(Right) {} - template - bool match(ITy *V) { + template bool match(ITy *V) { if (L.match(V)) return true; if (R.match(V)) @@ -95,15 +98,13 @@ struct match_combine_or { } }; -template -struct match_combine_and { +template struct match_combine_and { LTy L; RTy R; - match_combine_and(const LTy &Left, const RTy &Right) : L(Left), R(Right) { } + match_combine_and(const LTy &Left, const RTy &Right) : L(Left), R(Right) {} - template - bool match(ITy *V) { + template bool match(ITy *V) { if (L.match(V)) if (R.match(V)) return true; @@ -112,46 +113,44 @@ struct match_combine_and { }; /// Combine two pattern matchers matching L || R -template +template inline match_combine_or m_CombineOr(const LTy &L, const RTy &R) { return match_combine_or(L, R); } /// Combine two pattern matchers matching L && R -template +template inline match_combine_and m_CombineAnd(const LTy &L, const RTy &R) { return match_combine_and(L, R); } struct match_zero { - template - bool match(ITy *V) { - if (const Constant *C = dyn_cast(V)) + template bool match(ITy *V) { + if (const auto *C = dyn_cast(V)) return C->isNullValue(); return false; } }; -/// m_Zero() - Match an arbitrary zero/null constant. This includes +/// \brief Match an arbitrary zero/null constant. This includes /// zero_initializer for vectors and ConstantPointerNull for pointers. inline match_zero m_Zero() { return match_zero(); } struct match_neg_zero { - template - bool match(ITy *V) { - if (const Constant *C = dyn_cast(V)) + template bool match(ITy *V) { + if (const auto *C = dyn_cast(V)) return C->isNegativeZeroValue(); return false; } }; -/// m_NegZero() - Match an arbitrary zero/null constant. This includes +/// \brief Match an arbitrary zero/null constant. This includes /// zero_initializer for vectors and ConstantPointerNull for pointers. For /// floating point constants, this will match negative zero but not positive /// zero inline match_neg_zero m_NegZero() { return match_neg_zero(); } -/// m_AnyZero() - Match an arbitrary zero/null constant. This includes +/// \brief - Match an arbitrary zero/null constant. This includes /// zero_initializer for vectors and ConstantPointerNull for pointers. For /// floating point constants, this will match negative zero and positive zero inline match_combine_or m_AnyZero() { @@ -161,16 +160,14 @@ inline match_combine_or m_AnyZero() { struct apint_match { const APInt *&Res; apint_match(const APInt *&R) : Res(R) {} - template - bool match(ITy *V) { - if (ConstantInt *CI = dyn_cast(V)) { + template bool match(ITy *V) { + if (auto *CI = dyn_cast(V)) { Res = &CI->getValue(); return true; } if (V->getType()->isVectorTy()) - if (const Constant *C = dyn_cast(V)) - if (ConstantInt *CI = - dyn_cast_or_null(C->getSplatValue())) { + if (const auto *C = dyn_cast(V)) + if (auto *CI = dyn_cast_or_null(C->getSplatValue())) { Res = &CI->getValue(); return true; } @@ -178,16 +175,13 @@ struct apint_match { } }; -/// m_APInt - Match a ConstantInt or splatted ConstantVector, binding the +/// \brief Match a ConstantInt or splatted ConstantVector, binding the /// specified pointer to the contained APInt. inline apint_match m_APInt(const APInt *&Res) { return Res; } - -template -struct constantint_match { - template - bool match(ITy *V) { - if (const ConstantInt *CI = dyn_cast(V)) { +template struct constantint_match { + template bool match(ITy *V) { + if (const auto *CI = dyn_cast(V)) { const APInt &CIV = CI->getValue(); if (Val >= 0) return CIV == static_cast(Val); @@ -200,45 +194,39 @@ struct constantint_match { } }; -/// m_ConstantInt - Match a ConstantInt with a specific value. -template -inline constantint_match m_ConstantInt() { +/// \brief Match a ConstantInt with a specific value. +template inline constantint_match m_ConstantInt() { return constantint_match(); } -/// cst_pred_ty - This helper class is used to match scalar and vector constants -/// that satisfy a specified predicate. -template -struct cst_pred_ty : public Predicate { - template - bool match(ITy *V) { - if (const ConstantInt *CI = dyn_cast(V)) +/// \brief This helper class is used to match scalar and vector constants that +/// satisfy a specified predicate. +template struct cst_pred_ty : public Predicate { + template bool match(ITy *V) { + if (const auto *CI = dyn_cast(V)) return this->isValue(CI->getValue()); if (V->getType()->isVectorTy()) - if (const Constant *C = dyn_cast(V)) - if (const ConstantInt *CI = - dyn_cast_or_null(C->getSplatValue())) + if (const auto *C = dyn_cast(V)) + if (const auto *CI = dyn_cast_or_null(C->getSplatValue())) return this->isValue(CI->getValue()); return false; } }; -/// api_pred_ty - This helper class is used to match scalar and vector constants -/// that satisfy a specified predicate, and bind them to an APInt. -template -struct api_pred_ty : public Predicate { +/// \brief This helper class is used to match scalar and vector constants that +/// satisfy a specified predicate, and bind them to an APInt. +template struct api_pred_ty : public Predicate { const APInt *&Res; api_pred_ty(const APInt *&R) : Res(R) {} - template - bool match(ITy *V) { - if (const ConstantInt *CI = dyn_cast(V)) + template bool match(ITy *V) { + if (const auto *CI = dyn_cast(V)) if (this->isValue(CI->getValue())) { Res = &CI->getValue(); return true; } if (V->getType()->isVectorTy()) - if (const Constant *C = dyn_cast(V)) - if (ConstantInt *CI = dyn_cast_or_null(C->getSplatValue())) + if (const auto *C = dyn_cast(V)) + if (auto *CI = dyn_cast_or_null(C->getSplatValue())) if (this->isValue(CI->getValue())) { Res = &CI->getValue(); return true; @@ -248,12 +236,11 @@ struct api_pred_ty : public Predicate { } }; - struct is_one { bool isValue(const APInt &C) { return C == 1; } }; -/// m_One() - Match an integer 1 or a vector with all elements equal to 1. +/// \brief Match an integer 1 or a vector with all elements equal to 1. inline cst_pred_ty m_One() { return cst_pred_ty(); } inline api_pred_ty m_One(const APInt *&V) { return V; } @@ -261,34 +248,43 @@ struct is_all_ones { bool isValue(const APInt &C) { return C.isAllOnesValue(); } }; -/// m_AllOnes() - Match an integer or vector with all bits set to true. -inline cst_pred_ty m_AllOnes() {return cst_pred_ty();} +/// \brief Match an integer or vector with all bits set to true. +inline cst_pred_ty m_AllOnes() { + return cst_pred_ty(); +} inline api_pred_ty m_AllOnes(const APInt *&V) { return V; } struct is_sign_bit { bool isValue(const APInt &C) { return C.isSignBit(); } }; -/// m_SignBit() - Match an integer or vector with only the sign bit(s) set. -inline cst_pred_ty m_SignBit() {return cst_pred_ty();} +/// \brief Match an integer or vector with only the sign bit(s) set. +inline cst_pred_ty m_SignBit() { + return cst_pred_ty(); +} inline api_pred_ty m_SignBit(const APInt *&V) { return V; } struct is_power2 { bool isValue(const APInt &C) { return C.isPowerOf2(); } }; -/// m_Power2() - Match an integer or vector power of 2. +/// \brief Match an integer or vector power of 2. inline cst_pred_ty m_Power2() { return cst_pred_ty(); } inline api_pred_ty m_Power2(const APInt *&V) { return V; } -template -struct bind_ty { +struct is_maxsignedvalue { + bool isValue(const APInt &C) { return C.isMaxSignedValue(); } +}; + +inline cst_pred_ty m_MaxSignedValue() { return cst_pred_ty(); } +inline api_pred_ty m_MaxSignedValue(const APInt *&V) { return V; } + +template struct bind_ty { Class *&VR; bind_ty(Class *&V) : VR(V) {} - template - bool match(ITy *V) { - if (Class *CV = dyn_cast(V)) { + template bool match(ITy *V) { + if (auto *CV = dyn_cast(V)) { VR = CV; return true; } @@ -296,64 +292,62 @@ struct bind_ty { } }; -/// m_Value - Match a value, capturing it if we match. +/// \brief Match a value, capturing it if we match. inline bind_ty m_Value(Value *&V) { return V; } -/// m_ConstantInt - Match a ConstantInt, capturing the value if we match. +/// \brief Match a binary operator, capturing it if we match. +inline bind_ty m_BinOp(BinaryOperator *&I) { return I; } + +/// \brief Match a ConstantInt, capturing the value if we match. inline bind_ty m_ConstantInt(ConstantInt *&CI) { return CI; } -/// m_Constant - Match a Constant, capturing the value if we match. +/// \brief Match a Constant, capturing the value if we match. inline bind_ty m_Constant(Constant *&C) { return C; } -/// m_ConstantFP - Match a ConstantFP, capturing the value if we match. +/// \brief Match a ConstantFP, capturing the value if we match. inline bind_ty m_ConstantFP(ConstantFP *&C) { return C; } -/// specificval_ty - Match a specified Value*. +/// \brief Match a specified Value*. struct specificval_ty { const Value *Val; specificval_ty(const Value *V) : Val(V) {} - template - bool match(ITy *V) { - return V == Val; - } + template bool match(ITy *V) { return V == Val; } }; -/// m_Specific - Match if we have a specific specified value. +/// \brief Match if we have a specific specified value. inline specificval_ty m_Specific(const Value *V) { return V; } -/// Match a specified floating point value or vector of all elements of that -/// value. +/// \brief Match a specified floating point value or vector of all elements of +/// that value. struct specific_fpval { double Val; specific_fpval(double V) : Val(V) {} - template - bool match(ITy *V) { - if (const ConstantFP *CFP = dyn_cast(V)) + template bool match(ITy *V) { + if (const auto *CFP = dyn_cast(V)) return CFP->isExactlyValue(Val); if (V->getType()->isVectorTy()) - if (const Constant *C = dyn_cast(V)) - if (ConstantFP *CFP = dyn_cast_or_null(C->getSplatValue())) + if (const auto *C = dyn_cast(V)) + if (auto *CFP = dyn_cast_or_null(C->getSplatValue())) return CFP->isExactlyValue(Val); return false; } }; -/// Match a specific floating point value or vector with all elements equal to -/// the value. +/// \brief Match a specific floating point value or vector with all elements +/// equal to the value. inline specific_fpval m_SpecificFP(double V) { return specific_fpval(V); } -/// Match a float 1.0 or vector with all elements equal to 1.0. +/// \brief Match a float 1.0 or vector with all elements equal to 1.0. inline specific_fpval m_FPOne() { return m_SpecificFP(1.0); } struct bind_const_intval_ty { uint64_t &VR; bind_const_intval_ty(uint64_t &V) : VR(V) {} - template - bool match(ITy *V) { - if (ConstantInt *CV = dyn_cast(V)) + template bool match(ITy *V) { + if (const auto *CV = dyn_cast(V)) if (CV->getBitWidth() <= 64) { VR = CV->getZExtValue(); return true; @@ -362,14 +356,14 @@ struct bind_const_intval_ty { } }; -/// Match a specified integer value or vector of all elements of that value. +/// \brief Match a specified integer value or vector of all elements of that +// value. struct specific_intval { uint64_t Val; specific_intval(uint64_t V) : Val(V) {} - template - bool match(ITy *V) { - ConstantInt *CI = dyn_cast(V); + template bool match(ITy *V) { + const auto *CI = dyn_cast(V); if (!CI && V->getType()->isVectorTy()) if (const auto *C = dyn_cast(V)) CI = dyn_cast_or_null(C->getSplatValue()); @@ -381,156 +375,177 @@ struct specific_intval { } }; -/// Match a specific integer value or vector with all elements equal to the -/// value. +/// \brief Match a specific integer value or vector with all elements equal to +/// the value. inline specific_intval m_SpecificInt(uint64_t V) { return specific_intval(V); } -/// m_ConstantInt - Match a ConstantInt and bind to its value. This does not -/// match ConstantInts wider than 64-bits. +/// \brief Match a ConstantInt and bind to its value. This does not match +/// ConstantInts wider than 64-bits. inline bind_const_intval_ty m_ConstantInt(uint64_t &V) { return V; } //===----------------------------------------------------------------------===// +// Matcher for any binary operator. +// +template struct AnyBinaryOp_match { + LHS_t L; + RHS_t R; + + AnyBinaryOp_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {} + + template bool match(OpTy *V) { + if (auto *I = dyn_cast(V)) + return L.match(I->getOperand(0)) && R.match(I->getOperand(1)); + return false; + } +}; + +template +inline AnyBinaryOp_match m_BinOp(const LHS &L, const RHS &R) { + return AnyBinaryOp_match(L, R); +} + +//===----------------------------------------------------------------------===// // Matchers for specific binary operators. // -template +template struct BinaryOp_match { LHS_t L; RHS_t R; BinaryOp_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {} - template - bool match(OpTy *V) { + template bool match(OpTy *V) { if (V->getValueID() == Value::InstructionVal + Opcode) { - BinaryOperator *I = cast(V); + auto *I = cast(V); return L.match(I->getOperand(0)) && R.match(I->getOperand(1)); } - if (ConstantExpr *CE = dyn_cast(V)) + if (auto *CE = dyn_cast(V)) return CE->getOpcode() == Opcode && L.match(CE->getOperand(0)) && R.match(CE->getOperand(1)); return false; } }; -template -inline BinaryOp_match -m_Add(const LHS &L, const RHS &R) { +template +inline BinaryOp_match m_Add(const LHS &L, + const RHS &R) { return BinaryOp_match(L, R); } -template -inline BinaryOp_match -m_FAdd(const LHS &L, const RHS &R) { +template +inline BinaryOp_match m_FAdd(const LHS &L, + const RHS &R) { return BinaryOp_match(L, R); } -template -inline BinaryOp_match -m_Sub(const LHS &L, const RHS &R) { +template +inline BinaryOp_match m_Sub(const LHS &L, + const RHS &R) { return BinaryOp_match(L, R); } -template -inline BinaryOp_match -m_FSub(const LHS &L, const RHS &R) { +template +inline BinaryOp_match m_FSub(const LHS &L, + const RHS &R) { return BinaryOp_match(L, R); } -template -inline BinaryOp_match -m_Mul(const LHS &L, const RHS &R) { +template +inline BinaryOp_match m_Mul(const LHS &L, + const RHS &R) { return BinaryOp_match(L, R); } -template -inline BinaryOp_match -m_FMul(const LHS &L, const RHS &R) { +template +inline BinaryOp_match m_FMul(const LHS &L, + const RHS &R) { return BinaryOp_match(L, R); } -template -inline BinaryOp_match -m_UDiv(const LHS &L, const RHS &R) { +template +inline BinaryOp_match m_UDiv(const LHS &L, + const RHS &R) { return BinaryOp_match(L, R); } -template -inline BinaryOp_match -m_SDiv(const LHS &L, const RHS &R) { +template +inline BinaryOp_match m_SDiv(const LHS &L, + const RHS &R) { return BinaryOp_match(L, R); } -template -inline BinaryOp_match -m_FDiv(const LHS &L, const RHS &R) { +template +inline BinaryOp_match m_FDiv(const LHS &L, + const RHS &R) { return BinaryOp_match(L, R); } -template -inline BinaryOp_match -m_URem(const LHS &L, const RHS &R) { +template +inline BinaryOp_match m_URem(const LHS &L, + const RHS &R) { return BinaryOp_match(L, R); } -template -inline BinaryOp_match -m_SRem(const LHS &L, const RHS &R) { +template +inline BinaryOp_match m_SRem(const LHS &L, + const RHS &R) { return BinaryOp_match(L, R); } -template -inline BinaryOp_match -m_FRem(const LHS &L, const RHS &R) { +template +inline BinaryOp_match m_FRem(const LHS &L, + const RHS &R) { return BinaryOp_match(L, R); } -template -inline BinaryOp_match -m_And(const LHS &L, const RHS &R) { +template +inline BinaryOp_match m_And(const LHS &L, + const RHS &R) { return BinaryOp_match(L, R); } -template -inline BinaryOp_match -m_Or(const LHS &L, const RHS &R) { +template +inline BinaryOp_match m_Or(const LHS &L, + const RHS &R) { return BinaryOp_match(L, R); } -template -inline BinaryOp_match -m_Xor(const LHS &L, const RHS &R) { +template +inline BinaryOp_match m_Xor(const LHS &L, + const RHS &R) { return BinaryOp_match(L, R); } -template -inline BinaryOp_match -m_Shl(const LHS &L, const RHS &R) { +template +inline BinaryOp_match m_Shl(const LHS &L, + const RHS &R) { return BinaryOp_match(L, R); } -template -inline BinaryOp_match -m_LShr(const LHS &L, const RHS &R) { +template +inline BinaryOp_match m_LShr(const LHS &L, + const RHS &R) { return BinaryOp_match(L, R); } -template -inline BinaryOp_match -m_AShr(const LHS &L, const RHS &R) { +template +inline BinaryOp_match m_AShr(const LHS &L, + const RHS &R) { return BinaryOp_match(L, R); } -template +template struct OverflowingBinaryOp_match { LHS_t L; RHS_t R; - OverflowingBinaryOp_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {} + OverflowingBinaryOp_match(const LHS_t &LHS, const RHS_t &RHS) + : L(LHS), R(RHS) {} - template - bool match(OpTy *V) { - if (OverflowingBinaryOperator *Op = dyn_cast(V)) { + template bool match(OpTy *V) { + if (auto *Op = dyn_cast(V)) { if (Op->getOpcode() != Opcode) return false; if (WrapFlags & OverflowingBinaryOperator::NoUnsignedWrap && @@ -614,43 +629,42 @@ m_NUWShl(const LHS &L, const RHS &R) { //===----------------------------------------------------------------------===// // Class that matches two different binary ops. // -template +template struct BinOp2_match { LHS_t L; RHS_t R; BinOp2_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {} - template - bool match(OpTy *V) { + template bool match(OpTy *V) { if (V->getValueID() == Value::InstructionVal + Opc1 || V->getValueID() == Value::InstructionVal + Opc2) { - BinaryOperator *I = cast(V); + auto *I = cast(V); return L.match(I->getOperand(0)) && R.match(I->getOperand(1)); } - if (ConstantExpr *CE = dyn_cast(V)) + if (auto *CE = dyn_cast(V)) return (CE->getOpcode() == Opc1 || CE->getOpcode() == Opc2) && L.match(CE->getOperand(0)) && R.match(CE->getOperand(1)); return false; } }; -/// m_Shr - Matches LShr or AShr. -template +/// \brief Matches LShr or AShr. +template inline BinOp2_match m_Shr(const LHS &L, const RHS &R) { return BinOp2_match(L, R); } -/// m_LogicalShift - Matches LShr or Shl. -template +/// \brief Matches LShr or Shl. +template inline BinOp2_match m_LogicalShift(const LHS &L, const RHS &R) { return BinOp2_match(L, R); } -/// m_IDiv - Matches UDiv and SDiv. -template +/// \brief Matches UDiv and SDiv. +template inline BinOp2_match m_IDiv(const LHS &L, const RHS &R) { return BinOp2_match(L, R); @@ -659,38 +673,36 @@ m_IDiv(const LHS &L, const RHS &R) { //===----------------------------------------------------------------------===// // Class that matches exact binary ops. // -template -struct Exact_match { +template struct Exact_match { SubPattern_t SubPattern; Exact_match(const SubPattern_t &SP) : SubPattern(SP) {} - template - bool match(OpTy *V) { + template bool match(OpTy *V) { if (PossiblyExactOperator *PEO = dyn_cast(V)) return PEO->isExact() && SubPattern.match(V); return false; } }; -template -inline Exact_match m_Exact(const T &SubPattern) { return SubPattern; } +template inline Exact_match m_Exact(const T &SubPattern) { + return SubPattern; +} //===----------------------------------------------------------------------===// // Matchers for CmpInst classes // -template +template struct CmpClass_match { PredicateTy &Predicate; LHS_t L; RHS_t R; CmpClass_match(PredicateTy &Pred, const LHS_t &LHS, const RHS_t &RHS) - : Predicate(Pred), L(LHS), R(RHS) {} + : Predicate(Pred), L(LHS), R(RHS) {} - template - bool match(OpTy *V) { + template bool match(OpTy *V) { if (Class *I = dyn_cast(V)) if (L.match(I->getOperand(0)) && R.match(I->getOperand(1))) { Predicate = I->getPredicate(); @@ -700,123 +712,114 @@ struct CmpClass_match { } }; -template +template +inline CmpClass_match +m_Cmp(CmpInst::Predicate &Pred, const LHS &L, const RHS &R) { + return CmpClass_match(Pred, L, R); +} + +template inline CmpClass_match m_ICmp(ICmpInst::Predicate &Pred, const LHS &L, const RHS &R) { - return CmpClass_match(Pred, L, R); + return CmpClass_match(Pred, L, R); } -template +template inline CmpClass_match m_FCmp(FCmpInst::Predicate &Pred, const LHS &L, const RHS &R) { - return CmpClass_match(Pred, L, R); + return CmpClass_match(Pred, L, R); } //===----------------------------------------------------------------------===// // Matchers for SelectInst classes // -template +template struct SelectClass_match { Cond_t C; LHS_t L; RHS_t R; - SelectClass_match(const Cond_t &Cond, const LHS_t &LHS, - const RHS_t &RHS) - : C(Cond), L(LHS), R(RHS) {} + SelectClass_match(const Cond_t &Cond, const LHS_t &LHS, const RHS_t &RHS) + : C(Cond), L(LHS), R(RHS) {} - template - bool match(OpTy *V) { - if (SelectInst *I = dyn_cast(V)) - return C.match(I->getOperand(0)) && - L.match(I->getOperand(1)) && + template bool match(OpTy *V) { + if (auto *I = dyn_cast(V)) + return C.match(I->getOperand(0)) && L.match(I->getOperand(1)) && R.match(I->getOperand(2)); return false; } }; -template -inline SelectClass_match -m_Select(const Cond &C, const LHS &L, const RHS &R) { +template +inline SelectClass_match m_Select(const Cond &C, const LHS &L, + const RHS &R) { return SelectClass_match(C, L, R); } -/// m_SelectCst - This matches a select of two constants, e.g.: -/// m_SelectCst<-1, 0>(m_Value(V)) -template -inline SelectClass_match, constantint_match > +/// \brief This matches a select of two constants, e.g.: +/// m_SelectCst<-1, 0>(m_Value(V)) +template +inline SelectClass_match, constantint_match> m_SelectCst(const Cond &C) { return m_Select(C, m_ConstantInt(), m_ConstantInt()); } - //===----------------------------------------------------------------------===// // Matchers for CastInst classes // -template -struct CastClass_match { +template struct CastClass_match { Op_t Op; CastClass_match(const Op_t &OpMatch) : Op(OpMatch) {} - template - bool match(OpTy *V) { - if (Operator *O = dyn_cast(V)) + template bool match(OpTy *V) { + if (auto *O = dyn_cast(V)) return O->getOpcode() == Opcode && Op.match(O->getOperand(0)); return false; } }; -/// m_BitCast -template -inline CastClass_match -m_BitCast(const OpTy &Op) { +/// \brief Matches BitCast. +template +inline CastClass_match m_BitCast(const OpTy &Op) { return CastClass_match(Op); } -/// m_PtrToInt -template -inline CastClass_match -m_PtrToInt(const OpTy &Op) { +/// \brief Matches PtrToInt. +template +inline CastClass_match m_PtrToInt(const OpTy &Op) { return CastClass_match(Op); } -/// m_Trunc -template -inline CastClass_match -m_Trunc(const OpTy &Op) { +/// \brief Matches Trunc. +template +inline CastClass_match m_Trunc(const OpTy &Op) { return CastClass_match(Op); } -/// m_SExt -template -inline CastClass_match -m_SExt(const OpTy &Op) { +/// \brief Matches SExt. +template +inline CastClass_match m_SExt(const OpTy &Op) { return CastClass_match(Op); } -/// m_ZExt -template -inline CastClass_match -m_ZExt(const OpTy &Op) { +/// \brief Matches ZExt. +template +inline CastClass_match m_ZExt(const OpTy &Op) { return CastClass_match(Op); } -/// m_UIToFP -template -inline CastClass_match -m_UIToFP(const OpTy &Op) { +/// \brief Matches UIToFP. +template +inline CastClass_match m_UIToFP(const OpTy &Op) { return CastClass_match(Op); } -/// m_SIToFP -template -inline CastClass_match -m_SIToFP(const OpTy &Op) { +/// \brief Matches SIToFP. +template +inline CastClass_match m_SIToFP(const OpTy &Op) { return CastClass_match(Op); } @@ -824,46 +827,41 @@ m_SIToFP(const OpTy &Op) { // Matchers for unary operators // -template -struct not_match { +template struct not_match { LHS_t L; not_match(const LHS_t &LHS) : L(LHS) {} - template - bool match(OpTy *V) { - if (Operator *O = dyn_cast(V)) + template bool match(OpTy *V) { + if (auto *O = dyn_cast(V)) if (O->getOpcode() == Instruction::Xor) return matchIfNot(O->getOperand(0), O->getOperand(1)); return false; } + private: bool matchIfNot(Value *LHS, Value *RHS) { return (isa(RHS) || isa(RHS) || // FIXME: Remove CV. isa(RHS)) && - cast(RHS)->isAllOnesValue() && - L.match(LHS); + cast(RHS)->isAllOnesValue() && L.match(LHS); } }; -template -inline not_match m_Not(const LHS &L) { return L; } +template inline not_match m_Not(const LHS &L) { return L; } - -template -struct neg_match { +template struct neg_match { LHS_t L; neg_match(const LHS_t &LHS) : L(LHS) {} - template - bool match(OpTy *V) { - if (Operator *O = dyn_cast(V)) + template bool match(OpTy *V) { + if (auto *O = dyn_cast(V)) if (O->getOpcode() == Instruction::Sub) return matchIfNeg(O->getOperand(0), O->getOperand(1)); return false; } + private: bool matchIfNeg(Value *LHS, Value *RHS) { return ((isa(LHS) && cast(LHS)->isZero()) || @@ -872,36 +870,33 @@ private: } }; -/// m_Neg - Match an integer negate. -template -inline neg_match m_Neg(const LHS &L) { return L; } - +/// \brief Match an integer negate. +template inline neg_match m_Neg(const LHS &L) { return L; } -template -struct fneg_match { +template struct fneg_match { LHS_t L; fneg_match(const LHS_t &LHS) : L(LHS) {} - template - bool match(OpTy *V) { - if (Operator *O = dyn_cast(V)) + template bool match(OpTy *V) { + if (auto *O = dyn_cast(V)) if (O->getOpcode() == Instruction::FSub) return matchIfFNeg(O->getOperand(0), O->getOperand(1)); return false; } + private: bool matchIfFNeg(Value *LHS, Value *RHS) { - if (ConstantFP *C = dyn_cast(LHS)) + if (const auto *C = dyn_cast(LHS)) return C->isNegativeZeroValue() && L.match(RHS); return false; } }; -/// m_FNeg - Match a floating point negate. -template -inline fneg_match m_FNeg(const LHS &L) { return L; } - +/// \brief Match a floating point negate. +template inline fneg_match m_FNeg(const LHS &L) { + return L; +} //===----------------------------------------------------------------------===// // Matchers for control flow. @@ -909,13 +904,10 @@ inline fneg_match m_FNeg(const LHS &L) { return L; } struct br_match { BasicBlock *&Succ; - br_match(BasicBlock *&Succ) - : Succ(Succ) { - } + br_match(BasicBlock *&Succ) : Succ(Succ) {} - template - bool match(OpTy *V) { - if (BranchInst *BI = dyn_cast(V)) + template bool match(OpTy *V) { + if (auto *BI = dyn_cast(V)) if (BI->isUnconditional()) { Succ = BI->getSuccessor(0); return true; @@ -926,17 +918,14 @@ struct br_match { inline br_match m_UnconditionalBr(BasicBlock *&Succ) { return br_match(Succ); } -template -struct brc_match { +template struct brc_match { Cond_t Cond; BasicBlock *&T, *&F; brc_match(const Cond_t &C, BasicBlock *&t, BasicBlock *&f) - : Cond(C), T(t), F(f) { - } + : Cond(C), T(t), F(f) {} - template - bool match(OpTy *V) { - if (BranchInst *BI = dyn_cast(V)) + template bool match(OpTy *V) { + if (auto *BI = dyn_cast(V)) if (BI->isConditional() && Cond.match(BI->getCondition())) { T = BI->getSuccessor(0); F = BI->getSuccessor(1); @@ -946,31 +935,28 @@ struct brc_match { } }; -template +template inline brc_match m_Br(const Cond_t &C, BasicBlock *&T, BasicBlock *&F) { return brc_match(C, T, F); } - //===----------------------------------------------------------------------===// // Matchers for max/min idioms, eg: "select (sgt x, y), x, y" -> smax(x,y). // -template +template struct MaxMin_match { LHS_t L; RHS_t R; - MaxMin_match(const LHS_t &LHS, const RHS_t &RHS) - : L(LHS), R(RHS) {} + MaxMin_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {} - template - bool match(OpTy *V) { + template bool match(OpTy *V) { // Look for "(x pred y) ? x : y" or "(x pred y) ? y : x". - SelectInst *SI = dyn_cast(V); + auto *SI = dyn_cast(V); if (!SI) return false; - CmpInst_t *Cmp = dyn_cast(SI->getCondition()); + auto *Cmp = dyn_cast(SI->getCondition()); if (!Cmp) return false; // At this point we have a select conditioned on a comparison. Check that @@ -982,8 +968,8 @@ struct MaxMin_match { if ((TrueVal != LHS || FalseVal != RHS) && (TrueVal != RHS || FalseVal != LHS)) return false; - typename CmpInst_t::Predicate Pred = LHS == TrueVal ? - Cmp->getPredicate() : Cmp->getSwappedPredicate(); + typename CmpInst_t::Predicate Pred = + LHS == TrueVal ? Cmp->getPredicate() : Cmp->getSwappedPredicate(); // Does "(x pred y) ? x : y" represent the desired max/min operation? if (!Pred_t::match(Pred)) return false; @@ -992,83 +978,83 @@ struct MaxMin_match { } }; -/// smax_pred_ty - Helper class for identifying signed max predicates. +/// \brief Helper class for identifying signed max predicates. struct smax_pred_ty { static bool match(ICmpInst::Predicate Pred) { return Pred == CmpInst::ICMP_SGT || Pred == CmpInst::ICMP_SGE; } }; -/// smin_pred_ty - Helper class for identifying signed min predicates. +/// \brief Helper class for identifying signed min predicates. struct smin_pred_ty { static bool match(ICmpInst::Predicate Pred) { return Pred == CmpInst::ICMP_SLT || Pred == CmpInst::ICMP_SLE; } }; -/// umax_pred_ty - Helper class for identifying unsigned max predicates. +/// \brief Helper class for identifying unsigned max predicates. struct umax_pred_ty { static bool match(ICmpInst::Predicate Pred) { return Pred == CmpInst::ICMP_UGT || Pred == CmpInst::ICMP_UGE; } }; -/// umin_pred_ty - Helper class for identifying unsigned min predicates. +/// \brief Helper class for identifying unsigned min predicates. struct umin_pred_ty { static bool match(ICmpInst::Predicate Pred) { return Pred == CmpInst::ICMP_ULT || Pred == CmpInst::ICMP_ULE; } }; -/// ofmax_pred_ty - Helper class for identifying ordered max predicates. +/// \brief Helper class for identifying ordered max predicates. struct ofmax_pred_ty { static bool match(FCmpInst::Predicate Pred) { return Pred == CmpInst::FCMP_OGT || Pred == CmpInst::FCMP_OGE; } }; -/// ofmin_pred_ty - Helper class for identifying ordered min predicates. +/// \brief Helper class for identifying ordered min predicates. struct ofmin_pred_ty { static bool match(FCmpInst::Predicate Pred) { return Pred == CmpInst::FCMP_OLT || Pred == CmpInst::FCMP_OLE; } }; -/// ufmax_pred_ty - Helper class for identifying unordered max predicates. +/// \brief Helper class for identifying unordered max predicates. struct ufmax_pred_ty { static bool match(FCmpInst::Predicate Pred) { return Pred == CmpInst::FCMP_UGT || Pred == CmpInst::FCMP_UGE; } }; -/// ufmin_pred_ty - Helper class for identifying unordered min predicates. +/// \brief Helper class for identifying unordered min predicates. struct ufmin_pred_ty { static bool match(FCmpInst::Predicate Pred) { return Pred == CmpInst::FCMP_ULT || Pred == CmpInst::FCMP_ULE; } }; -template -inline MaxMin_match -m_SMax(const LHS &L, const RHS &R) { +template +inline MaxMin_match m_SMax(const LHS &L, + const RHS &R) { return MaxMin_match(L, R); } -template -inline MaxMin_match -m_SMin(const LHS &L, const RHS &R) { +template +inline MaxMin_match m_SMin(const LHS &L, + const RHS &R) { return MaxMin_match(L, R); } -template -inline MaxMin_match -m_UMax(const LHS &L, const RHS &R) { +template +inline MaxMin_match m_UMax(const LHS &L, + const RHS &R) { return MaxMin_match(L, R); } -template -inline MaxMin_match -m_UMin(const LHS &L, const RHS &R) { +template +inline MaxMin_match m_UMin(const LHS &L, + const RHS &R) { return MaxMin_match(L, R); } @@ -1081,9 +1067,9 @@ m_UMin(const LHS &L, const RHS &R) { /// /// max(L, R) iff L and R are not NaN /// m_OrdFMax(L, R) = R iff L or R are NaN -template -inline MaxMin_match -m_OrdFMax(const LHS &L, const RHS &R) { +template +inline MaxMin_match m_OrdFMax(const LHS &L, + const RHS &R) { return MaxMin_match(L, R); } @@ -1096,9 +1082,9 @@ m_OrdFMax(const LHS &L, const RHS &R) { /// /// max(L, R) iff L and R are not NaN /// m_OrdFMin(L, R) = R iff L or R are NaN -template -inline MaxMin_match -m_OrdFMin(const LHS &L, const RHS &R) { +template +inline MaxMin_match m_OrdFMin(const LHS &L, + const RHS &R) { return MaxMin_match(L, R); } @@ -1111,7 +1097,7 @@ m_OrdFMin(const LHS &L, const RHS &R) { /// /// max(L, R) iff L and R are not NaN /// m_UnordFMin(L, R) = L iff L or R are NaN -template +template inline MaxMin_match m_UnordFMax(const LHS &L, const RHS &R) { return MaxMin_match(L, R); @@ -1126,40 +1112,37 @@ m_UnordFMax(const LHS &L, const RHS &R) { /// /// max(L, R) iff L and R are not NaN /// m_UnordFMin(L, R) = L iff L or R are NaN -template +template inline MaxMin_match m_UnordFMin(const LHS &L, const RHS &R) { return MaxMin_match(L, R); } -template -struct Argument_match { +template struct Argument_match { unsigned OpI; Opnd_t Val; - Argument_match(unsigned OpIdx, const Opnd_t &V) : OpI(OpIdx), Val(V) { } + Argument_match(unsigned OpIdx, const Opnd_t &V) : OpI(OpIdx), Val(V) {} - template - bool match(OpTy *V) { + template bool match(OpTy *V) { CallSite CS(V); return CS.isCall() && Val.match(CS.getArgument(OpI)); } }; -/// Match an argument -template +/// \brief Match an argument. +template inline Argument_match m_Argument(const Opnd_t &Op) { return Argument_match(OpI, Op); } -/// Intrinsic matchers. +/// \brief Intrinsic matchers. struct IntrinsicID_match { unsigned ID; - IntrinsicID_match(Intrinsic::ID IntrID) : ID(IntrID) { } + IntrinsicID_match(Intrinsic::ID IntrID) : ID(IntrID) {} - template - bool match(OpTy *V) { - if (const CallInst *CI = dyn_cast(V)) - if (const Function *F = CI->getCalledFunction()) + template bool match(OpTy *V) { + if (const auto *CI = dyn_cast(V)) + if (const auto *F = CI->getCalledFunction()) return F->getIntrinsicID() == ID; return false; } @@ -1172,73 +1155,71 @@ struct IntrinsicID_match { template struct m_Intrinsic_Ty; -template -struct m_Intrinsic_Ty { - typedef match_combine_and > Ty; + typename T9 = void, typename T10 = void> +struct m_Intrinsic_Ty; +template struct m_Intrinsic_Ty { + typedef match_combine_and> Ty; }; -template -struct m_Intrinsic_Ty { - typedef match_combine_and::Ty, - Argument_match > Ty; +template struct m_Intrinsic_Ty { + typedef match_combine_and::Ty, Argument_match> + Ty; }; template struct m_Intrinsic_Ty { typedef match_combine_and::Ty, - Argument_match > Ty; + Argument_match> Ty; }; template struct m_Intrinsic_Ty { typedef match_combine_and::Ty, - Argument_match > Ty; + Argument_match> Ty; }; -/// Match intrinsic calls like this: -/// m_Intrinsic(m_Value(X)) -template -inline IntrinsicID_match -m_Intrinsic() { return IntrinsicID_match(IntrID); } +/// \brief Match intrinsic calls like this: +/// m_Intrinsic(m_Value(X)) +template inline IntrinsicID_match m_Intrinsic() { + return IntrinsicID_match(IntrID); +} -template -inline typename m_Intrinsic_Ty::Ty -m_Intrinsic(const T0 &Op0) { +template +inline typename m_Intrinsic_Ty::Ty m_Intrinsic(const T0 &Op0) { return m_CombineAnd(m_Intrinsic(), m_Argument<0>(Op0)); } -template -inline typename m_Intrinsic_Ty::Ty -m_Intrinsic(const T0 &Op0, const T1 &Op1) { +template +inline typename m_Intrinsic_Ty::Ty m_Intrinsic(const T0 &Op0, + const T1 &Op1) { return m_CombineAnd(m_Intrinsic(Op0), m_Argument<1>(Op1)); } -template +template inline typename m_Intrinsic_Ty::Ty m_Intrinsic(const T0 &Op0, const T1 &Op1, const T2 &Op2) { return m_CombineAnd(m_Intrinsic(Op0, Op1), m_Argument<2>(Op2)); } -template +template inline typename m_Intrinsic_Ty::Ty m_Intrinsic(const T0 &Op0, const T1 &Op1, const T2 &Op2, const T3 &Op3) { return m_CombineAnd(m_Intrinsic(Op0, Op1, Op2), m_Argument<3>(Op3)); } -// Helper intrinsic matching specializations -template -inline typename m_Intrinsic_Ty::Ty -m_BSwap(const Opnd0 &Op0) { +// Helper intrinsic matching specializations. +template +inline typename m_Intrinsic_Ty::Ty m_BSwap(const Opnd0 &Op0) { return m_Intrinsic(Op0); } -template -inline typename m_Intrinsic_Ty::Ty -m_FMin(const Opnd0 &Op0, const Opnd1 &Op1) { +template +inline typename m_Intrinsic_Ty::Ty m_FMin(const Opnd0 &Op0, + const Opnd1 &Op1) { return m_Intrinsic(Op0, Op1); } -template -inline typename m_Intrinsic_Ty::Ty -m_FMax(const Opnd0 &Op0, const Opnd1 &Op1) { +template +inline typename m_Intrinsic_Ty::Ty m_FMax(const Opnd0 &Op0, + const Opnd1 &Op1) { return m_Intrinsic(Op0, Op1); } diff --git a/include/llvm/IR/Statepoint.h b/include/llvm/IR/Statepoint.h new file mode 100644 index 0000000..38720ed --- /dev/null +++ b/include/llvm/IR/Statepoint.h @@ -0,0 +1,298 @@ +//===-- llvm/IR/Statepoint.h - gc.statepoint utilities ------ --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains utility functions and a wrapper class analogous to +// CallSite for accessing the fields of gc.statepoint, gc.relocate, and +// gc.result intrinsics +// +//===----------------------------------------------------------------------===// + +#ifndef __LLVM_IR_STATEPOINT_H +#define __LLVM_IR_STATEPOINT_H + +#include "llvm/ADT/iterator_range.h" +#include "llvm/IR/BasicBlock.h" +#include "llvm/IR/CallSite.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/Intrinsics.h" +#include "llvm/Support/Compiler.h" + +namespace llvm { + +class GCRelocateOperands; +class ImmutableStatepoint; + +bool isStatepoint(const ImmutableCallSite &CS); +bool isStatepoint(const Value *inst); +bool isStatepoint(const Value &inst); + +bool isGCRelocate(const Value *inst); +bool isGCRelocate(const ImmutableCallSite &CS); + +bool isGCResult(const Value *inst); +bool isGCResult(const ImmutableCallSite &CS); + +/// Analogous to CallSiteBase, this provides most of the actual +/// functionality for Statepoint and ImmutableStatepoint. It is +/// templatized to allow easily specializing of const and non-const +/// concrete subtypes. This is structured analogous to CallSite +/// rather than the IntrinsicInst.h helpers since we want to support +/// invokable statepoints in the near future. +/// TODO: This does not currently allow the if(Statepoint S = ...) +/// idiom used with CallSites. Consider refactoring to support. +template +class StatepointBase { + CallSiteTy StatepointCS; + void *operator new(size_t, unsigned) = delete; + void *operator new(size_t s) = delete; + + protected: + explicit StatepointBase(InstructionTy *I) : StatepointCS(I) { + assert(isStatepoint(I)); + } + explicit StatepointBase(CallSiteTy CS) : StatepointCS(CS) { + assert(isStatepoint(CS)); + } + + public: + typedef typename CallSiteTy::arg_iterator arg_iterator; + + /// Return the underlying CallSite. + CallSiteTy getCallSite() { + return StatepointCS; + } + + /// Return the value actually being called or invoked. + ValueTy *actualCallee() { + return StatepointCS.getArgument(0); + } + /// Number of arguments to be passed to the actual callee. + int numCallArgs() { + return cast(StatepointCS.getArgument(1))->getZExtValue(); + } + /// Number of additional arguments excluding those intended + /// for garbage collection. + int numTotalVMSArgs() { + return cast(StatepointCS.getArgument(3 + numCallArgs()))->getZExtValue(); + } + + typename CallSiteTy::arg_iterator call_args_begin() { + // 3 = callTarget, #callArgs, flag + int Offset = 3; + assert(Offset <= (int)StatepointCS.arg_size()); + return StatepointCS.arg_begin() + Offset; + } + typename CallSiteTy::arg_iterator call_args_end() { + int Offset = 3 + numCallArgs(); + assert(Offset <= (int)StatepointCS.arg_size()); + return StatepointCS.arg_begin() + Offset; + } + + /// range adapter for call arguments + iterator_range call_args() { + return iterator_range(call_args_begin(), call_args_end()); + } + + typename CallSiteTy::arg_iterator vm_state_begin() { + return call_args_end(); + } + typename CallSiteTy::arg_iterator vm_state_end() { + int Offset = 3 + numCallArgs() + 1 + numTotalVMSArgs(); + assert(Offset <= (int)StatepointCS.arg_size()); + return StatepointCS.arg_begin() + Offset; + } + + /// range adapter for vm state arguments + iterator_range vm_state_args() { + return iterator_range(vm_state_begin(), vm_state_end()); + } + + typename CallSiteTy::arg_iterator first_vm_state_stack_begin() { + // 6 = numTotalVMSArgs, 1st_objectID, 1st_bci, + // 1st_#stack, 1st_#local, 1st_#monitor + return vm_state_begin() + 6; + } + + typename CallSiteTy::arg_iterator gc_args_begin() { + return vm_state_end(); + } + typename CallSiteTy::arg_iterator gc_args_end() { + return StatepointCS.arg_end(); + } + + /// range adapter for gc arguments + iterator_range gc_args() { + return iterator_range(gc_args_begin(), gc_args_end()); + } + + /// Get list of all gc reloactes linked to this statepoint + /// May contain several relocations for the same base/derived pair. + /// For example this could happen due to relocations on unwinding + /// path of invoke. + std::vector getRelocates(ImmutableStatepoint &IS); + +#ifndef NDEBUG + /// Asserts if this statepoint is malformed. Common cases for failure + /// include incorrect length prefixes for variable length sections or + /// illegal values for parameters. + void verify() { + assert(numCallArgs() >= 0 && + "number of arguments to actually callee can't be negative"); + + // The internal asserts in the iterator accessors do the rest. + (void)call_args_begin(); + (void)call_args_end(); + (void)vm_state_begin(); + (void)vm_state_end(); + (void)gc_args_begin(); + (void)gc_args_end(); + } +#endif +}; + +/// A specialization of it's base class for read only access +/// to a gc.statepoint. +class ImmutableStatepoint + : public StatepointBase { + typedef StatepointBase + Base; + +public: + explicit ImmutableStatepoint(const Instruction *I) : Base(I) {} + explicit ImmutableStatepoint(ImmutableCallSite CS) : Base(CS) {} +}; + +/// A specialization of it's base class for read-write access +/// to a gc.statepoint. +class Statepoint : public StatepointBase { + typedef StatepointBase Base; + +public: + explicit Statepoint(Instruction *I) : Base(I) {} + explicit Statepoint(CallSite CS) : Base(CS) {} +}; + +/// Wraps a call to a gc.relocate and provides access to it's operands. +/// TODO: This should likely be refactored to resememble the wrappers in +/// InstrinsicInst.h. +class GCRelocateOperands { + ImmutableCallSite RelocateCS; + + public: + GCRelocateOperands(const User* U) : RelocateCS(U) { + assert(isGCRelocate(U)); + } + GCRelocateOperands(const Instruction *inst) : RelocateCS(inst) { + assert(isGCRelocate(inst)); + } + GCRelocateOperands(CallSite CS) : RelocateCS(CS) { + assert(isGCRelocate(CS)); + } + + /// Return true if this relocate is tied to the invoke statepoint. + /// This includes relocates which are on the unwinding path. + bool isTiedToInvoke() const { + const Value *Token = RelocateCS.getArgument(0); + + return isa(Token) || + isa(Token); + } + + /// Get enclosed relocate intrinsic + ImmutableCallSite getUnderlyingCallSite() { + return RelocateCS; + } + + /// The statepoint with which this gc.relocate is associated. + const Instruction *statepoint() { + const Value *token = RelocateCS.getArgument(0); + + // This takes care both of relocates for call statepoints and relocates + // on normal path of invoke statepoint. + if (!isa(token)) { + return cast(token); + } + + // This relocate is on exceptional path of an invoke statepoint + const BasicBlock *invokeBB = + cast(token)->getParent()->getUniquePredecessor(); + + assert(invokeBB && "safepoints should have unique landingpads"); + assert(invokeBB->getTerminator() && "safepoint block should be well formed"); + assert(isStatepoint(invokeBB->getTerminator())); + + return invokeBB->getTerminator(); + } + /// The index into the associate statepoint's argument list + /// which contains the base pointer of the pointer whose + /// relocation this gc.relocate describes. + unsigned basePtrIndex() { + return cast(RelocateCS.getArgument(1))->getZExtValue(); + } + /// The index into the associate statepoint's argument list which + /// contains the pointer whose relocation this gc.relocate describes. + unsigned derivedPtrIndex() { + return cast(RelocateCS.getArgument(2))->getZExtValue(); + } + Value *basePtr() { + ImmutableCallSite CS(statepoint()); + return *(CS.arg_begin() + basePtrIndex()); + } + Value *derivedPtr() { + ImmutableCallSite CS(statepoint()); + return *(CS.arg_begin() + derivedPtrIndex()); + } +}; + +template +std::vector + StatepointBase:: + getRelocates(ImmutableStatepoint &IS) { + + std::vector res; + + ImmutableCallSite StatepointCS = IS.getCallSite(); + + // Search for relocated pointers. Note that working backwards from the + // gc_relocates ensures that we only get pairs which are actually relocated + // and used after the statepoint. + for (const User *U : StatepointCS.getInstruction()->users()) { + if (isGCRelocate(U)) { + res.push_back(GCRelocateOperands(U)); + } + } + + if (!StatepointCS.isInvoke()) { + return res; + } + + // We need to scan thorough exceptional relocations if it is invoke statepoint + LandingPadInst *LandingPad = + cast(StatepointCS.getInstruction())->getLandingPadInst(); + + // Search for extract value from landingpad instruction to which + // gc relocates will be attached + for (const User *LandingPadUser : LandingPad->users()) { + if (!isa(LandingPadUser)) { + continue; + } + + // gc relocates should be attached to this extract value + for (const User *U : LandingPadUser->users()) { + if (isGCRelocate(U)) { + res.push_back(GCRelocateOperands(U)); + } + } + } + return res; +} + +} +#endif diff --git a/include/llvm/IR/TrackingMDRef.h b/include/llvm/IR/TrackingMDRef.h new file mode 100644 index 0000000..e241121 --- /dev/null +++ b/include/llvm/IR/TrackingMDRef.h @@ -0,0 +1,170 @@ +//===- llvm/IR/TrackingMDRef.h - Tracking Metadata references ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// References to metadata that track RAUW. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_TRACKINGMDREF_H +#define LLVM_IR_TRACKINGMDREF_H + +#include "llvm/IR/MetadataTracking.h" +#include "llvm/Support/Casting.h" + +namespace llvm { + +class Metadata; +class MDNode; +class ValueAsMetadata; + +/// \brief Tracking metadata reference. +/// +/// This class behaves like \a TrackingVH, but for metadata. +class TrackingMDRef { + Metadata *MD; + +public: + TrackingMDRef() : MD(nullptr) {} + explicit TrackingMDRef(Metadata *MD) : MD(MD) { track(); } + + TrackingMDRef(TrackingMDRef &&X) : MD(X.MD) { retrack(X); } + TrackingMDRef(const TrackingMDRef &X) : MD(X.MD) { track(); } + TrackingMDRef &operator=(TrackingMDRef &&X) { + if (&X == this) + return *this; + + untrack(); + MD = X.MD; + retrack(X); + return *this; + } + TrackingMDRef &operator=(const TrackingMDRef &X) { + if (&X == this) + return *this; + + untrack(); + MD = X.MD; + track(); + return *this; + } + ~TrackingMDRef() { untrack(); } + + Metadata *get() const { return MD; } + operator Metadata *() const { return get(); } + Metadata *operator->() const { return get(); } + Metadata &operator*() const { return *get(); } + + void reset() { + untrack(); + MD = nullptr; + } + void reset(Metadata *MD) { + untrack(); + this->MD = MD; + track(); + } + + /// \brief Check whether this has a trivial destructor. + /// + /// If \c MD isn't replaceable, the destructor will be a no-op. + bool hasTrivialDestructor() const { + return !MD || !MetadataTracking::isReplaceable(*MD); + } + + bool operator==(const TrackingMDRef &X) const { return MD == X.MD; } + bool operator!=(const TrackingMDRef &X) const { return MD != X.MD; } + +private: + void track() { + if (MD) + MetadataTracking::track(MD); + } + void untrack() { + if (MD) + MetadataTracking::untrack(MD); + } + void retrack(TrackingMDRef &X) { + assert(MD == X.MD && "Expected values to match"); + if (X.MD) { + MetadataTracking::retrack(X.MD, MD); + X.MD = nullptr; + } + } +}; + +/// \brief Typed tracking ref. +/// +/// Track refererences of a particular type. It's useful to use this for \a +/// MDNode and \a ValueAsMetadata. +template class TypedTrackingMDRef { + TrackingMDRef Ref; + +public: + TypedTrackingMDRef() {} + explicit TypedTrackingMDRef(T *MD) : Ref(static_cast(MD)) {} + + TypedTrackingMDRef(TypedTrackingMDRef &&X) : Ref(std::move(X.Ref)) {} + TypedTrackingMDRef(const TypedTrackingMDRef &X) : Ref(X.Ref) {} + TypedTrackingMDRef &operator=(TypedTrackingMDRef &&X) { + Ref = std::move(X.Ref); + return *this; + } + TypedTrackingMDRef &operator=(const TypedTrackingMDRef &X) { + Ref = X.Ref; + return *this; + } + + T *get() const { return (T *)Ref.get(); } + operator T *() const { return get(); } + T *operator->() const { return get(); } + T &operator*() const { return *get(); } + + bool operator==(const TypedTrackingMDRef &X) const { return Ref == X.Ref; } + bool operator!=(const TypedTrackingMDRef &X) const { return Ref != X.Ref; } + + void reset() { Ref.reset(); } + void reset(T *MD) { Ref.reset(static_cast(MD)); } + + /// \brief Check whether this has a trivial destructor. + bool hasTrivialDestructor() const { return Ref.hasTrivialDestructor(); } +}; + +typedef TypedTrackingMDRef TrackingMDNodeRef; +typedef TypedTrackingMDRef TrackingValueAsMetadataRef; + +// Expose the underlying metadata to casting. +template <> struct simplify_type { + typedef Metadata *SimpleType; + static SimpleType getSimplifiedValue(TrackingMDRef &MD) { return MD.get(); } +}; + +template <> struct simplify_type { + typedef Metadata *SimpleType; + static SimpleType getSimplifiedValue(const TrackingMDRef &MD) { + return MD.get(); + } +}; + +template struct simplify_type> { + typedef T *SimpleType; + static SimpleType getSimplifiedValue(TypedTrackingMDRef &MD) { + return MD.get(); + } +}; + +template struct simplify_type> { + typedef T *SimpleType; + static SimpleType getSimplifiedValue(const TypedTrackingMDRef &MD) { + return MD.get(); + } +}; + +} // end namespace llvm + +#endif diff --git a/include/llvm/IR/Type.h b/include/llvm/IR/Type.h index a36fb0f..c2073c7 100644 --- a/include/llvm/IR/Type.h +++ b/include/llvm/IR/Type.h @@ -313,6 +313,9 @@ public: typedef Type * const *subtype_iterator; subtype_iterator subtype_begin() const { return ContainedTys; } subtype_iterator subtype_end() const { return &ContainedTys[NumContainedTys];} + ArrayRef subtypes() const { + return makeArrayRef(subtype_begin(), subtype_end()); + } typedef std::reverse_iterator subtype_reverse_iterator; subtype_reverse_iterator subtype_rbegin() const { diff --git a/include/llvm/IR/TypeFinder.h b/include/llvm/IR/TypeFinder.h index cea66a4..73a63ad 100644 --- a/include/llvm/IR/TypeFinder.h +++ b/include/llvm/IR/TypeFinder.h @@ -31,6 +31,7 @@ class TypeFinder { // To avoid walking constant expressions multiple times and other IR // objects, we keep several helper maps. DenseSet VisitedConstants; + DenseSet VisitedMetadata; DenseSet VisitedTypes; std::vector StructTypes; diff --git a/include/llvm/IR/Use.h b/include/llvm/IR/Use.h index 033cd3e..160d71b 100644 --- a/include/llvm/IR/Use.h +++ b/include/llvm/IR/Use.h @@ -77,7 +77,7 @@ public: typedef PointerIntPair UserRef; private: - Use(const Use &U) LLVM_DELETED_FUNCTION; + Use(const Use &U) = delete; /// Destructor - Only for zap() ~Use() { diff --git a/include/llvm/IR/UseListOrder.h b/include/llvm/IR/UseListOrder.h index 5df459b..7d8205d 100644 --- a/include/llvm/IR/UseListOrder.h +++ b/include/llvm/IR/UseListOrder.h @@ -45,8 +45,8 @@ struct UseListOrder { } private: - UseListOrder(const UseListOrder &X) LLVM_DELETED_FUNCTION; - UseListOrder &operator=(const UseListOrder &X) LLVM_DELETED_FUNCTION; + UseListOrder(const UseListOrder &X) = delete; + UseListOrder &operator=(const UseListOrder &X) = delete; }; typedef std::vector UseListOrderStack; diff --git a/include/llvm/IR/User.h b/include/llvm/IR/User.h index f578227..d39378d 100644 --- a/include/llvm/IR/User.h +++ b/include/llvm/IR/User.h @@ -33,8 +33,8 @@ template struct OperandTraits; class User : public Value { - User(const User &) LLVM_DELETED_FUNCTION; - void *operator new(size_t) LLVM_DELETED_FUNCTION; + User(const User &) = delete; + void *operator new(size_t) = delete; template friend struct HungoffOperandTraits; virtual void anchor(); diff --git a/include/llvm/IR/Value.h b/include/llvm/IR/Value.h index 67665be..b7213a6 100644 --- a/include/llvm/IR/Value.h +++ b/include/llvm/IR/Value.h @@ -37,7 +37,6 @@ class GlobalVariable; class InlineAsm; class Instruction; class LLVMContext; -class MDNode; class Module; class StringRef; class Twine; @@ -70,9 +69,9 @@ class Value { Type *VTy; Use *UseList; - friend class ValueSymbolTable; // Allow ValueSymbolTable to directly mod Name. + friend class ValueAsMetadata; // Allow access to NameAndIsUsedByMD. friend class ValueHandleBase; - ValueName *Name; + PointerIntPair NameAndIsUsedByMD; const unsigned char SubclassID; // Subclass identifier (for isa/dyn_cast) unsigned char HasValueHandle : 1; // Has a ValueHandle pointing to this? @@ -107,17 +106,12 @@ protected: private: template // UseT == 'Use' or 'const Use' class use_iterator_impl - : public std::iterator { - typedef std::iterator super; - + : public std::iterator { UseT *U; explicit use_iterator_impl(UseT *u) : U(u) {} friend class Value; public: - typedef typename super::reference reference; - typedef typename super::pointer pointer; - use_iterator_impl() : U() {} bool operator==(const use_iterator_impl &x) const { return U == x.U; } @@ -148,17 +142,12 @@ private: template // UserTy == 'User' or 'const User' class user_iterator_impl - : public std::iterator { - typedef std::iterator super; - + : public std::iterator { use_iterator_impl UI; explicit user_iterator_impl(Use *U) : UI(U) {} friend class Value; public: - typedef typename super::reference reference; - typedef typename super::pointer pointer; - user_iterator_impl() {} bool operator==(const user_iterator_impl &x) const { return UI == x.UI; } @@ -189,15 +178,10 @@ private: } Use &getUse() const { return *UI; } - - /// \brief Return the operand # of this use in its User. - /// - /// FIXME: Replace all callers with a direct call to Use::getOperandNo. - unsigned getOperandNo() const { return UI->getOperandNo(); } }; - void operator=(const Value &) LLVM_DELETED_FUNCTION; - Value(const Value &) LLVM_DELETED_FUNCTION; + void operator=(const Value &) = delete; + Value(const Value &) = delete; protected: Value(Type *Ty, unsigned scid); @@ -226,10 +210,14 @@ public: LLVMContext &getContext() const; // \brief All values can potentially be named. - bool hasName() const { return Name != nullptr; } - ValueName *getValueName() const { return Name; } - void setValueName(ValueName *VN) { Name = VN; } + bool hasName() const { return getValueName() != nullptr; } + ValueName *getValueName() const { return NameAndIsUsedByMD.getPointer(); } + void setValueName(ValueName *VN) { NameAndIsUsedByMD.setPointer(VN); } + +private: + void destroyValueName(); +public: /// \brief Return a constant reference to the value's name. /// /// This is cheap and guaranteed to return the same reference as long as the @@ -258,6 +246,13 @@ public: /// guaranteed to be empty. void replaceAllUsesWith(Value *V); + /// replaceUsesOutsideBlock - Go through the uses list for this definition and + /// make each use point to "V" instead of "this" when the use is outside the + /// block. 'This's use list is expected to have at least one element. + /// Unlike replaceAllUsesWith this function does not support basic block + /// values or constant users. + void replaceUsesOutsideBlock(Value *V, BasicBlock *BB); + //---------------------------------------------------------------------- // Methods for handling the chain of uses of this Value. // @@ -276,6 +271,8 @@ public: return iterator_range(use_begin(), use_end()); } + bool user_empty() const { return UseList == nullptr; } + typedef user_iterator_impl user_iterator; typedef user_iterator_impl const_user_iterator; user_iterator user_begin() { return user_iterator(UseList); } @@ -345,9 +342,7 @@ public: ConstantStructVal, // This is an instance of ConstantStruct ConstantVectorVal, // This is an instance of ConstantVector ConstantPointerNullVal, // This is an instance of ConstantPointerNull - GenericMDNodeVal, // This is an instance of GenericMDNode - MDNodeFwdDeclVal, // This is an instance of MDNodeFwdDecl - MDStringVal, // This is an instance of MDString + MetadataAsValueVal, // This is an instance of MetadataAsValue InlineAsmVal, // This is an instance of InlineAsm InstructionVal, // This is an instance of Instruction // Enum values starting at InstructionVal are used for Instructions; @@ -397,6 +392,9 @@ public: /// \brief Return true if there is a value handle associated with this value. bool hasValueHandle() const { return HasValueHandle; } + /// \brief Return true if there is metadata referencing this value. + bool isUsedByMetadata() const { return NameAndIsUsedByMD.getInt(); } + /// \brief Strip off pointer casts, all-zero GEPs, and aliases. /// /// Returns the original uncasted value. If this is called on a non-pointer @@ -471,7 +469,8 @@ public: /// /// This is the greatest alignment value supported by load, store, and alloca /// instructions, and global values. - static const unsigned MaximumAlignment = 1u << 29; + static const unsigned MaxAlignmentExponent = 29; + static const unsigned MaximumAlignment = 1u << MaxAlignmentExponent; /// \brief Mutate the type of this Value to be of the specified type. /// @@ -680,13 +679,6 @@ template <> struct isa_impl { } }; -template <> struct isa_impl { - static inline bool doit(const Value &Val) { - return Val.getValueID() == Value::GenericMDNodeVal || - Val.getValueID() == Value::MDNodeFwdDeclVal; - } -}; - // Value* is only 4-byte aligned. template<> class PointerLikeTypeTraits { diff --git a/include/llvm/IR/ValueHandle.h b/include/llvm/IR/ValueHandle.h index 460210e..355748e 100644 --- a/include/llvm/IR/ValueHandle.h +++ b/include/llvm/IR/ValueHandle.h @@ -56,55 +56,48 @@ private: PointerIntPair PrevPair; ValueHandleBase *Next; - // A subclass may want to store some information along with the value - // pointer. Allow them to do this by making the value pointer a pointer-int - // pair. The 'setValPtrInt' and 'getValPtrInt' methods below give them this - // access. - PointerIntPair VP; + Value* V; - ValueHandleBase(const ValueHandleBase&) LLVM_DELETED_FUNCTION; + ValueHandleBase(const ValueHandleBase&) = delete; public: explicit ValueHandleBase(HandleBaseKind Kind) - : PrevPair(nullptr, Kind), Next(nullptr), VP(nullptr, 0) {} + : PrevPair(nullptr, Kind), Next(nullptr), V(nullptr) {} ValueHandleBase(HandleBaseKind Kind, Value *V) - : PrevPair(nullptr, Kind), Next(nullptr), VP(V, 0) { - if (isValid(VP.getPointer())) + : PrevPair(nullptr, Kind), Next(nullptr), V(V) { + if (isValid(V)) AddToUseList(); } ValueHandleBase(HandleBaseKind Kind, const ValueHandleBase &RHS) - : PrevPair(nullptr, Kind), Next(nullptr), VP(RHS.VP) { - if (isValid(VP.getPointer())) + : PrevPair(nullptr, Kind), Next(nullptr), V(RHS.V) { + if (isValid(V)) AddToExistingUseList(RHS.getPrevPtr()); } ~ValueHandleBase() { - if (isValid(VP.getPointer())) + if (isValid(V)) RemoveFromUseList(); } Value *operator=(Value *RHS) { - if (VP.getPointer() == RHS) return RHS; - if (isValid(VP.getPointer())) RemoveFromUseList(); - VP.setPointer(RHS); - if (isValid(VP.getPointer())) AddToUseList(); + if (V == RHS) return RHS; + if (isValid(V)) RemoveFromUseList(); + V = RHS; + if (isValid(V)) AddToUseList(); return RHS; } Value *operator=(const ValueHandleBase &RHS) { - if (VP.getPointer() == RHS.VP.getPointer()) return RHS.VP.getPointer(); - if (isValid(VP.getPointer())) RemoveFromUseList(); - VP.setPointer(RHS.VP.getPointer()); - if (isValid(VP.getPointer())) AddToExistingUseList(RHS.getPrevPtr()); - return VP.getPointer(); + if (V == RHS.V) return RHS.V; + if (isValid(V)) RemoveFromUseList(); + V = RHS.V; + if (isValid(V)) AddToExistingUseList(RHS.getPrevPtr()); + return V; } - Value *operator->() const { return getValPtr(); } - Value &operator*() const { return *getValPtr(); } + Value *operator->() const { return V; } + Value &operator*() const { return *V; } protected: - Value *getValPtr() const { return VP.getPointer(); } - - void setValPtrInt(unsigned K) { VP.setInt(K); } - unsigned getValPtrInt() const { return VP.getInt(); } + Value *getValPtr() const { return V; } static bool isValid(Value *V) { return V && @@ -123,7 +116,7 @@ private: HandleBaseKind getKind() const { return PrevPair.getInt(); } void setPrevPtr(ValueHandleBase **Ptr) { PrevPair.setPointer(Ptr); } - /// \brief Add this ValueHandle to the use list for VP. + /// \brief Add this ValueHandle to the use list for V. /// /// List is the address of either the head of the list or a Next node within /// the existing use list. @@ -132,7 +125,7 @@ private: /// \brief Add this ValueHandle to the use list after Node. void AddToExistingUseListAfter(ValueHandleBase *Node); - /// \brief Add this ValueHandle to the use list for VP. + /// \brief Add this ValueHandle to the use list for V. void AddToUseList(); /// \brief Remove this ValueHandle from its current use list. void RemoveFromUseList(); @@ -197,23 +190,20 @@ class AssertingVH friend struct DenseMapInfo >; #ifndef NDEBUG - ValueTy *getValPtr() const { - return static_cast(ValueHandleBase::getValPtr()); - } - void setValPtr(ValueTy *P) { - ValueHandleBase::operator=(GetAsValue(P)); - } + Value *getRawValPtr() const { return ValueHandleBase::getValPtr(); } + void setRawValPtr(Value *P) { ValueHandleBase::operator=(P); } #else - ValueTy *ThePtr; - ValueTy *getValPtr() const { return ThePtr; } - void setValPtr(ValueTy *P) { ThePtr = P; } + Value *ThePtr; + Value *getRawValPtr() const { return ThePtr; } + void setRawValPtr(Value *P) { ThePtr = P; } #endif - - // Convert a ValueTy*, which may be const, to the type the base - // class expects. + // Convert a ValueTy*, which may be const, to the raw Value*. static Value *GetAsValue(Value *V) { return V; } static Value *GetAsValue(const Value *V) { return const_cast(V); } + ValueTy *getValPtr() const { return static_cast(getRawValPtr()); } + void setValPtr(ValueTy *P) { setRawValPtr(GetAsValue(P)); } + public: #ifndef NDEBUG AssertingVH() : ValueHandleBase(Assert) {} @@ -221,7 +211,7 @@ public: AssertingVH(const AssertingVH &RHS) : ValueHandleBase(Assert, RHS) {} #else AssertingVH() : ThePtr(nullptr) {} - AssertingVH(ValueTy *P) : ThePtr(P) {} + AssertingVH(ValueTy *P) : ThePtr(GetAsValue(P)) {} #endif operator ValueTy*() const { @@ -244,27 +234,23 @@ public: // Specialize DenseMapInfo to allow AssertingVH to participate in DenseMap. template struct DenseMapInfo > { - typedef DenseMapInfo PointerInfo; static inline AssertingVH getEmptyKey() { - return AssertingVH(PointerInfo::getEmptyKey()); + AssertingVH Res; + Res.setRawValPtr(DenseMapInfo::getEmptyKey()); + return Res; } - static inline T* getTombstoneKey() { - return AssertingVH(PointerInfo::getTombstoneKey()); + static inline AssertingVH getTombstoneKey() { + AssertingVH Res; + Res.setRawValPtr(DenseMapInfo::getTombstoneKey()); + return Res; } static unsigned getHashValue(const AssertingVH &Val) { - return PointerInfo::getHashValue(Val); + return DenseMapInfo::getHashValue(Val.getRawValPtr()); } -#ifndef NDEBUG static bool isEqual(const AssertingVH &LHS, const AssertingVH &RHS) { - // Avoid downcasting AssertingVH to T*, as empty/tombstone keys may not - // be properly aligned pointers to T*. - return LHS.ValueHandleBase::getValPtr() == RHS.ValueHandleBase::getValPtr(); + return DenseMapInfo::isEqual(LHS.getRawValPtr(), + RHS.getRawValPtr()); } -#else - static bool isEqual(const AssertingVH &LHS, const AssertingVH &RHS) { - return LHS == RHS; - } -#endif }; template diff --git a/include/llvm/IR/ValueMap.h b/include/llvm/IR/ValueMap.h index aa8a29d..08d6d17 100644 --- a/include/llvm/IR/ValueMap.h +++ b/include/llvm/IR/ValueMap.h @@ -27,11 +27,13 @@ #define LLVM_IR_VALUEMAP_H #include "llvm/ADT/DenseMap.h" +#include "llvm/IR/TrackingMDRef.h" #include "llvm/IR/ValueHandle.h" #include "llvm/Support/Mutex.h" #include "llvm/Support/UniqueLock.h" #include "llvm/Support/type_traits.h" #include +#include namespace llvm { @@ -79,11 +81,13 @@ class ValueMap { friend class ValueMapCallbackVH; typedef ValueMapCallbackVH ValueMapCVH; typedef DenseMap > MapT; + typedef DenseMap MDMapT; typedef typename Config::ExtraData ExtraData; MapT Map; + std::unique_ptr MDMap; ExtraData Data; - ValueMap(const ValueMap&) LLVM_DELETED_FUNCTION; - ValueMap& operator=(const ValueMap&) LLVM_DELETED_FUNCTION; + ValueMap(const ValueMap&) = delete; + ValueMap& operator=(const ValueMap&) = delete; public: typedef KeyT key_type; typedef ValueT mapped_type; @@ -91,12 +95,19 @@ public: typedef unsigned size_type; explicit ValueMap(unsigned NumInitBuckets = 64) - : Map(NumInitBuckets), Data() {} + : Map(NumInitBuckets), Data() {} explicit ValueMap(const ExtraData &Data, unsigned NumInitBuckets = 64) - : Map(NumInitBuckets), Data(Data) {} + : Map(NumInitBuckets), Data(Data) {} ~ValueMap() {} + bool hasMD() const { return MDMap; } + MDMapT &MD() { + if (!MDMap) + MDMap.reset(new MDMapT); + return *MDMap; + } + typedef ValueMapIterator iterator; typedef ValueMapConstIterator const_iterator; inline iterator begin() { return iterator(Map.begin()); } @@ -110,7 +121,10 @@ public: /// Grow the map so that it has at least Size buckets. Does not shrink void resize(size_t Size) { Map.resize(Size); } - void clear() { Map.clear(); } + void clear() { + Map.clear(); + MDMap.reset(); + } /// Return 1 if the specified key is in the map, 0 otherwise. size_type count(const KeyT &Val) const { @@ -210,6 +224,9 @@ class ValueMapCallbackVH : public CallbackVH { : CallbackVH(const_cast(static_cast(Key))), Map(Map) {} + // Private constructor used to create empty/tombstone DenseMap keys. + ValueMapCallbackVH(Value *V) : CallbackVH(V), Map(nullptr) {} + public: KeyT Unwrap() const { return cast_or_null(getValPtr()); } @@ -252,19 +269,18 @@ public: template struct DenseMapInfo > { typedef ValueMapCallbackVH VH; - typedef DenseMapInfo PointerInfo; static inline VH getEmptyKey() { - return VH(PointerInfo::getEmptyKey(), nullptr); + return VH(DenseMapInfo::getEmptyKey()); } static inline VH getTombstoneKey() { - return VH(PointerInfo::getTombstoneKey(), nullptr); + return VH(DenseMapInfo::getTombstoneKey()); } static unsigned getHashValue(const VH &Val) { - return PointerInfo::getHashValue(Val.Unwrap()); + return DenseMapInfo::getHashValue(Val.Unwrap()); } static unsigned getHashValue(const KeyT &Val) { - return PointerInfo::getHashValue(Val); + return DenseMapInfo::getHashValue(Val); } static bool isEqual(const VH &LHS, const VH &RHS) { return LHS == RHS; diff --git a/include/llvm/IR/Verifier.h b/include/llvm/IR/Verifier.h index 0272e20..43bd123 100644 --- a/include/llvm/IR/Verifier.h +++ b/include/llvm/IR/Verifier.h @@ -77,8 +77,8 @@ class VerifierPass { public: explicit VerifierPass(bool FatalErrors = true) : FatalErrors(FatalErrors) {} - PreservedAnalyses run(Module *M); - PreservedAnalyses run(Function *F); + PreservedAnalyses run(Module &M); + PreservedAnalyses run(Function &F); static StringRef name() { return "VerifierPass"; } }; diff --git a/include/llvm/InitializePasses.h b/include/llvm/InitializePasses.h index a4bc598..bcf8cf2 100644 --- a/include/llvm/InitializePasses.h +++ b/include/llvm/InitializePasses.h @@ -40,7 +40,7 @@ void initializeObjCARCOpts(PassRegistry&); void initializeVectorization(PassRegistry&); /// initializeInstCombine - Initialize all passes linked into the -/// ScalarOpts library. +/// InstCombine library. void initializeInstCombine(PassRegistry&); /// initializeIPO - Initialize all passes linked into the IPO library. @@ -65,6 +65,7 @@ void initializeTarget(PassRegistry&); void initializeAAEvalPass(PassRegistry&); void initializeAddDiscriminatorsPass(PassRegistry&); void initializeADCEPass(PassRegistry&); +void initializeBDCEPass(PassRegistry&); void initializeAliasAnalysisAnalysisGroup(PassRegistry&); void initializeAliasAnalysisCounterPass(PassRegistry&); void initializeAliasDebuggerPass(PassRegistry&); @@ -77,7 +78,6 @@ void initializeAlignmentFromAssumptionsPass(PassRegistry&); void initializeBarrierNoopPass(PassRegistry&); void initializeBasicAliasAnalysisPass(PassRegistry&); void initializeCallGraphWrapperPassPass(PassRegistry &); -void initializeBasicTTIPass(PassRegistry&); void initializeBlockExtractorPassPass(PassRegistry&); void initializeBlockFrequencyInfoPass(PassRegistry&); void initializeBoundsCheckingPass(PassRegistry&); @@ -106,7 +106,6 @@ void initializeDAEPass(PassRegistry&); void initializeDAHPass(PassRegistry&); void initializeDCEPass(PassRegistry&); void initializeDSEPass(PassRegistry&); -void initializeDebugIRPass(PassRegistry&); void initializeDebugInfoVerifierLegacyPassPass(PassRegistry &); void initializeDeadInstEliminationPass(PassRegistry&); void initializeDeadMachineInstructionElimPass(PassRegistry&); @@ -122,6 +121,7 @@ void initializeEarlyIfConverterPass(PassRegistry&); void initializeEdgeBundlesPass(PassRegistry&); void initializeExpandPostRAPass(PassRegistry&); void initializeGCOVProfilerPass(PassRegistry&); +void initializeInstrProfilingPass(PassRegistry&); void initializeAddressSanitizerPass(PassRegistry&); void initializeAddressSanitizerModulePass(PassRegistry&); void initializeMemorySanitizerPass(PassRegistry&); @@ -129,9 +129,8 @@ void initializeThreadSanitizerPass(PassRegistry&); void initializeSanitizerCoverageModulePass(PassRegistry&); void initializeDataFlowSanitizerPass(PassRegistry&); void initializeScalarizerPass(PassRegistry&); -void initializeEarlyCSEPass(PassRegistry&); +void initializeEarlyCSELegacyPassPass(PassRegistry &); void initializeExpandISelPseudosPass(PassRegistry&); -void initializeFindUsedTypesPass(PassRegistry&); void initializeFunctionAttrsPass(PassRegistry&); void initializeGCMachineCodeAnalysisPass(PassRegistry&); void initializeGCModuleInfoPass(PassRegistry&); @@ -143,9 +142,10 @@ void initializeIPCPPass(PassRegistry&); void initializeIPSCCPPass(PassRegistry&); void initializeIVUsersPass(PassRegistry&); void initializeIfConverterPass(PassRegistry&); +void initializeInductiveRangeCheckEliminationPass(PassRegistry&); void initializeIndVarSimplifyPass(PassRegistry&); void initializeInlineCostAnalysisPass(PassRegistry&); -void initializeInstCombinerPass(PassRegistry&); +void initializeInstructionCombiningPassPass(PassRegistry&); void initializeInstCountPass(PassRegistry&); void initializeInstNamerPass(PassRegistry&); void initializeInternalizePassPass(PassRegistry&); @@ -167,7 +167,7 @@ void initializeLoaderPassPass(PassRegistry&); void initializeLocalStackSlotPassPass(PassRegistry&); void initializeLoopDeletionPass(PassRegistry&); void initializeLoopExtractorPass(PassRegistry&); -void initializeLoopInfoPass(PassRegistry&); +void initializeLoopInfoWrapperPassPass(PassRegistry&); void initializeLoopInstSimplifyPass(PassRegistry&); void initializeLoopRotatePass(PassRegistry&); void initializeLoopSimplifyPass(PassRegistry&); @@ -178,6 +178,7 @@ void initializeLoopUnrollPass(PassRegistry&); void initializeLoopUnswitchPass(PassRegistry&); void initializeLoopIdiomRecognizePass(PassRegistry&); void initializeLowerAtomicPass(PassRegistry&); +void initializeLowerBitSetsPass(PassRegistry&); void initializeLowerExpectIntrinsicPass(PassRegistry&); void initializeLowerIntrinsicsPass(PassRegistry&); void initializeLowerInvokePass(PassRegistry&); @@ -200,6 +201,7 @@ void initializeMachineTraceMetricsPass(PassRegistry&); void initializeMachineVerifierPassPass(PassRegistry&); void initializeMemCpyOptPass(PassRegistry&); void initializeMemDepPrinterPass(PassRegistry&); +void initializeMemDerefPrinterPass(PassRegistry&); void initializeMemoryDependenceAnalysisPass(PassRegistry&); void initializeMergedLoadStoreMotionPass(PassRegistry &); void initializeMetaRenamerPass(PassRegistry&); @@ -238,6 +240,7 @@ void initializeRegionOnlyPrinterPass(PassRegistry&); void initializeRegionOnlyViewerPass(PassRegistry&); void initializeRegionPrinterPass(PassRegistry&); void initializeRegionViewerPass(PassRegistry&); +void initializeRewriteStatepointsForGCPass(PassRegistry&); void initializeSCCPPass(PassRegistry&); void initializeSROAPass(PassRegistry&); void initializeSROA_DTPass(PassRegistry&); @@ -245,6 +248,7 @@ void initializeSROA_SSAUpPass(PassRegistry&); void initializeScalarEvolutionAliasAnalysisPass(PassRegistry&); void initializeScalarEvolutionPass(PassRegistry&); void initializeSimpleInlinerPass(PassRegistry&); +void initializeShadowStackGCLoweringPass(PassRegistry&); void initializeRegisterCoalescerPass(PassRegistry&); void initializeSingleLoopExtractorPass(PassRegistry&); void initializeSinkingPass(PassRegistry&); @@ -254,6 +258,7 @@ void initializeSpillPlacementPass(PassRegistry&); void initializeStackProtectorPass(PassRegistry&); void initializeStackColoringPass(PassRegistry&); void initializeStackSlotColoringPass(PassRegistry&); +void initializeStraightLineStrengthReducePass(PassRegistry &); void initializeStripDeadDebugInfoPass(PassRegistry&); void initializeStripDeadPrototypesPassPass(PassRegistry&); void initializeStripDebugDeclarePass(PassRegistry&); @@ -263,11 +268,9 @@ void initializeTailCallElimPass(PassRegistry&); void initializeTailDuplicatePassPass(PassRegistry&); void initializeTargetPassConfigPass(PassRegistry&); void initializeDataLayoutPassPass(PassRegistry &); -void initializeTargetTransformInfoAnalysisGroup(PassRegistry&); -void initializeFunctionTargetTransformInfoPass(PassRegistry &); -void initializeNoTTIPass(PassRegistry&); -void initializeTargetLibraryInfoPass(PassRegistry&); -void initializeAssumptionTrackerPass(PassRegistry &); +void initializeTargetTransformInfoWrapperPassPass(PassRegistry &); +void initializeTargetLibraryInfoWrapperPassPass(PassRegistry &); +void initializeAssumptionCacheTrackerPass(PassRegistry &); void initializeTwoAddressInstructionPassPass(PassRegistry&); void initializeTypeBasedAliasAnalysisPass(PassRegistry&); void initializeScopedNoAliasAAPass(PassRegistry&); @@ -280,6 +283,7 @@ void initializeVirtRegRewriterPass(PassRegistry&); void initializeInstSimplifierPass(PassRegistry&); void initializeUnpackMachineBundlesPass(PassRegistry&); void initializeFinalizeMachineBundlesPass(PassRegistry&); +void initializeLoopAccessAnalysisPass(PassRegistry&); void initializeLoopVectorizePass(PassRegistry&); void initializeSLPVectorizerPass(PassRegistry&); void initializeBBVectorizePass(PassRegistry&); @@ -288,6 +292,10 @@ void initializeStackMapLivenessPass(PassRegistry&); void initializeMachineCombinerPass(PassRegistry &); void initializeLoadCombinePass(PassRegistry&); void initializeRewriteSymbolsPass(PassRegistry&); +void initializeWinEHPreparePass(PassRegistry&); +void initializePlaceBackedgeSafepointsImplPass(PassRegistry&); +void initializePlaceSafepointsPass(PassRegistry&); +void initializeDwarfEHPreparePass(PassRegistry&); } #endif diff --git a/include/llvm/LTO/LTOCodeGenerator.h b/include/llvm/LTO/LTOCodeGenerator.h index 0c9ce4a..56d27ca 100644 --- a/include/llvm/LTO/LTOCodeGenerator.h +++ b/include/llvm/LTO/LTOCodeGenerator.h @@ -67,6 +67,9 @@ struct LTOCodeGenerator { // Merge given module, return true on success. bool addModule(struct LTOModule *); + // Set the destination module. + void setModule(struct LTOModule *); + void setTargetOptions(TargetOptions options); void setDebugInfo(lto_debug_model); void setCodePICModel(lto_codegen_model); @@ -117,6 +120,18 @@ struct LTOCodeGenerator { bool disableVectorization, std::string &errMsg); + // Optimizes the merged module. Returns true on success. + bool optimize(bool disableOpt, + bool disableInline, + bool disableGVNLoadPRE, + bool disableVectorization, + std::string &errMsg); + + // Compiles the merged optimized module into a single object file. It brings + // the object to a buffer, and returns the buffer to the caller. Return NULL + // if the compilation was not successful. + const void *compileOptimized(size_t *length, std::string &errMsg); + void setDiagnosticHandler(lto_diagnostic_handler_t, void *); LLVMContext &getContext() { return Context; } @@ -124,9 +139,8 @@ struct LTOCodeGenerator { private: void initializeLTOPasses(); - bool generateObjectFile(raw_ostream &out, bool disableOpt, bool disableInline, - bool disableGVNLoadPRE, bool disableVectorization, - std::string &errMsg); + bool compileOptimized(raw_ostream &out, std::string &errMsg); + bool compileOptimizedToFile(const char **name, std::string &errMsg); void applyScopeRestrictions(); void applyRestriction(GlobalValue &GV, ArrayRef Libcalls, std::vector &MustPreserveList, @@ -141,6 +155,7 @@ private: typedef StringMap StringSet; void initialize(); + void destroyMergedModule(); std::unique_ptr OwnedContext; LLVMContext &Context; Linker IRLinker; @@ -158,6 +173,7 @@ private: TargetOptions Options; lto_diagnostic_handler_t DiagHandler; void *DiagContext; + LTOModule *OwnedModule; }; } #endif diff --git a/include/llvm/LinkAllPasses.h b/include/llvm/LinkAllPasses.h index 66e4e9c..18343e2 100644 --- a/include/llvm/LinkAllPasses.h +++ b/include/llvm/LinkAllPasses.h @@ -18,7 +18,6 @@ #include "llvm/Analysis/AliasSetTracker.h" #include "llvm/Analysis/CallPrinter.h" #include "llvm/Analysis/DomPrinter.h" -#include "llvm/Analysis/FindUsedTypes.h" #include "llvm/Analysis/IntervalPartition.h" #include "llvm/Analysis/Lint.h" #include "llvm/Analysis/Passes.h" @@ -33,8 +32,8 @@ #include "llvm/Transforms/Instrumentation.h" #include "llvm/Transforms/ObjCARC.h" #include "llvm/Transforms/Scalar.h" -#include "llvm/Transforms/Utils/UnifyFunctionExitNodes.h" #include "llvm/Transforms/Utils/SymbolRewriter.h" +#include "llvm/Transforms/Utils/UnifyFunctionExitNodes.h" #include "llvm/Transforms/Vectorize.h" #include @@ -50,6 +49,7 @@ namespace { (void) llvm::createAAEvalPass(); (void) llvm::createAggressiveDCEPass(); + (void) llvm::createBitTrackingDCEPass(); (void) llvm::createAliasAnalysisCounterPass(); (void) llvm::createAliasDebugger(); (void) llvm::createArgumentPromotionPass(); @@ -79,6 +79,7 @@ namespace { (void) llvm::createDomOnlyViewerPass(); (void) llvm::createDomViewerPass(); (void) llvm::createGCOVProfilerPass(); + (void) llvm::createInstrProfilingPass(); (void) llvm::createFunctionInliningPass(); (void) llvm::createAlwaysInlinerPass(); (void) llvm::createGlobalDCEPass(); @@ -86,6 +87,7 @@ namespace { (void) llvm::createGlobalsModRefPass(); (void) llvm::createIPConstantPropagationPass(); (void) llvm::createIPSCCPPass(); + (void) llvm::createInductiveRangeCheckEliminationPass(); (void) llvm::createIndVarSimplifyPass(); (void) llvm::createInstructionCombiningPass(); (void) llvm::createInternalizePass(); @@ -166,9 +168,10 @@ namespace { (void) llvm::createScalarizerPass(); (void) llvm::createSeparateConstOffsetFromGEPPass(); (void) llvm::createRewriteSymbolsPass(); + (void) llvm::createStraightLineStrengthReducePass(); + (void) llvm::createMemDerefPrinter(); (void)new llvm::IntervalPartition(); - (void)new llvm::FindUsedTypes(); (void)new llvm::ScalarEvolution(); ((llvm::Function*)nullptr)->viewCFGOnly(); llvm::RGPassManager RGM; diff --git a/include/llvm/Linker/Linker.h b/include/llvm/Linker/Linker.h index c957cc2..aac9dcd 100644 --- a/include/llvm/Linker/Linker.h +++ b/include/llvm/Linker/Linker.h @@ -10,45 +10,81 @@ #ifndef LLVM_LINKER_LINKER_H #define LLVM_LINKER_LINKER_H -#include "llvm/ADT/SmallPtrSet.h" - -#include +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DenseSet.h" +#include "llvm/IR/DiagnosticInfo.h" namespace llvm { -class DiagnosticInfo; class Module; class StructType; +class Type; /// This class provides the core functionality of linking in LLVM. It keeps a /// pointer to the merged module so far. It doesn't take ownership of the /// module since it is assumed that the user of this class will want to do /// something with it after the linking. class Linker { - public: - typedef std::function - DiagnosticHandlerFunction; +public: + struct StructTypeKeyInfo { + struct KeyTy { + ArrayRef ETypes; + bool IsPacked; + KeyTy(ArrayRef E, bool P); + KeyTy(const StructType *ST); + bool operator==(const KeyTy &that) const; + bool operator!=(const KeyTy &that) const; + }; + static StructType *getEmptyKey(); + static StructType *getTombstoneKey(); + static unsigned getHashValue(const KeyTy &Key); + static unsigned getHashValue(const StructType *ST); + static bool isEqual(const KeyTy &LHS, const StructType *RHS); + static bool isEqual(const StructType *LHS, const StructType *RHS); + }; + + typedef DenseSet NonOpaqueStructTypeSet; + typedef DenseSet OpaqueStructTypeSet; + + struct IdentifiedStructTypeSet { + // The set of opaque types is the composite module. + OpaqueStructTypeSet OpaqueStructTypes; + + // The set of identified but non opaque structures in the composite module. + NonOpaqueStructTypeSet NonOpaqueStructTypes; + + void addNonOpaque(StructType *Ty); + void addOpaque(StructType *Ty); + StructType *findNonOpaque(ArrayRef ETypes, bool IsPacked); + bool hasType(StructType *Ty); + }; + + Linker(Module *M, DiagnosticHandlerFunction DiagnosticHandler); + Linker(Module *M); + ~Linker(); + + Module *getModule() const { return Composite; } + void deleteModule(); + + /// \brief Link \p Src into the composite. The source is destroyed. + /// Returns true on error. + bool linkInModule(Module *Src); - Linker(Module *M, DiagnosticHandlerFunction DiagnosticHandler); - Linker(Module *M); - ~Linker(); + /// \brief Set the composite to the passed-in module. + void setModule(Module *Dst); - Module *getModule() const { return Composite; } - void deleteModule(); + static bool LinkModules(Module *Dest, Module *Src, + DiagnosticHandlerFunction DiagnosticHandler); - /// \brief Link \p Src into the composite. The source is destroyed. - /// Returns true on error. - bool linkInModule(Module *Src); + static bool LinkModules(Module *Dest, Module *Src); - static bool LinkModules(Module *Dest, Module *Src, - DiagnosticHandlerFunction DiagnosticHandler); +private: + void init(Module *M, DiagnosticHandlerFunction DiagnosticHandler); + Module *Composite; - static bool LinkModules(Module *Dest, Module *Src); + IdentifiedStructTypeSet IdentifiedStructTypes; - private: - void init(Module *M, DiagnosticHandlerFunction DiagnosticHandler); - Module *Composite; - SmallPtrSet IdentifiedStructTypes; - DiagnosticHandlerFunction DiagnosticHandler; + DiagnosticHandlerFunction DiagnosticHandler; }; } // End llvm namespace diff --git a/include/llvm/MC/MCAsmBackend.h b/include/llvm/MC/MCAsmBackend.h index 15a956b..56da95d 100644 --- a/include/llvm/MC/MCAsmBackend.h +++ b/include/llvm/MC/MCAsmBackend.h @@ -32,8 +32,8 @@ class raw_ostream; /// MCAsmBackend - Generic interface to target specific assembler backends. class MCAsmBackend { - MCAsmBackend(const MCAsmBackend &) LLVM_DELETED_FUNCTION; - void operator=(const MCAsmBackend &) LLVM_DELETED_FUNCTION; + MCAsmBackend(const MCAsmBackend &) = delete; + void operator=(const MCAsmBackend &) = delete; protected: // Can only create subclasses. MCAsmBackend(); @@ -61,20 +61,6 @@ public: /// markers. If not, data region directives will be ignored. bool hasDataInCodeSupport() const { return HasDataInCodeSupport; } - /// doesSectionRequireSymbols - Check whether the given section requires that - /// all symbols (even temporaries) have symbol table entries. - virtual bool doesSectionRequireSymbols(const MCSection &Section) const { - return false; - } - - /// isSectionAtomizable - Check whether the given section can be split into - /// atoms. - /// - /// \see MCAssembler::isSymbolLinkerVisible(). - virtual bool isSectionAtomizable(const MCSection &Section) const { - return true; - } - /// @name Target Fixup Interfaces /// @{ diff --git a/include/llvm/MC/MCAsmInfo.h b/include/llvm/MC/MCAsmInfo.h index 4f38aac..ee245e9 100644 --- a/include/llvm/MC/MCAsmInfo.h +++ b/include/llvm/MC/MCAsmInfo.h @@ -42,11 +42,11 @@ enum class EncodingType { } enum class ExceptionHandling { - None, /// No exception support - DwarfCFI, /// DWARF-like instruction based exceptions - SjLj, /// setjmp/longjmp based exceptions - ARM, /// ARM EHABI - ItaniumWinEH, /// Itanium EH built on Windows unwind info (.pdata and .xdata) + None, /// No exception support + DwarfCFI, /// DWARF-like instruction based exceptions + SjLj, /// setjmp/longjmp based exceptions + ARM, /// ARM EHABI + WinEH, /// Windows Exception Handling }; namespace LCOMM { @@ -123,6 +123,10 @@ protected: /// file. Defaults to "L" const char *PrivateGlobalPrefix; + /// This prefix is used for labels for basic blocks. Defaults to the same as + /// PrivateGlobalPrefix. + const char *PrivateLabelPrefix; + /// This prefix is used for symbols that should be passed through the /// assembler but be removed by the linker. This is 'l' on Darwin, currently /// used for some ObjC metadata. The default of "" meast that for this system @@ -215,7 +219,8 @@ protected: //===--- Global Variable Emission Directives --------------------------===// - /// This is the directive used to declare a global entity. Defaults to NULL. + /// This is the directive used to declare a global entity. Defaults to + /// ".globl". const char *GlobalDirective; /// True if the expression @@ -264,6 +269,9 @@ protected: /// to false. bool HasNoDeadStrip; + /// Used to declare a global as being a weak symbol. Defaults to ".weak". + const char *WeakDirective; + /// This directive, if non-null, is used to declare a global as being a weak /// undefined symbol. Defaults to NULL. const char *WeakRefDirective; @@ -373,6 +381,12 @@ public: return nullptr; } + /// \brief True if the section is atomized using the symbols in it. + /// This is false if the section is not atomized at all (most ELF sections) or + /// if it is atomized based on its contents (MachO' __TEXT,__cstring for + /// example). + virtual bool isSectionAtomizableBySymbols(const MCSection &Section) const; + virtual const MCExpr *getExprForPersonalitySymbol(const MCSymbol *Sym, unsigned Encoding, MCStreamer &Streamer) const; @@ -414,6 +428,7 @@ public: bool useAssignmentForEHBegin() const { return UseAssignmentForEHBegin; } const char *getPrivateGlobalPrefix() const { return PrivateGlobalPrefix; } + const char *getPrivateLabelPrefix() const { return PrivateLabelPrefix; } bool hasLinkerPrivateGlobalPrefix() const { return LinkerPrivateGlobalPrefix[0] != '\0'; } @@ -452,6 +467,7 @@ public: bool hasSingleParameterDotFile() const { return HasSingleParameterDotFile; } bool hasIdentDirective() const { return HasIdentDirective; } bool hasNoDeadStrip() const { return HasNoDeadStrip; } + const char *getWeakDirective() const { return WeakDirective; } const char *getWeakRefDirective() const { return WeakRefDirective; } bool hasWeakDefDirective() const { return HasWeakDefDirective; } bool hasWeakDefCanBeHiddenDirective() const { @@ -473,13 +489,16 @@ public: ExceptionHandling getExceptionHandlingType() const { return ExceptionsType; } WinEH::EncodingType getWinEHEncodingType() const { return WinEHEncodingType; } - /// Return true if the exception handling type uses the language-specific data - /// area (LSDA) format specified by the Itanium C++ ABI. - bool usesItaniumLSDAForExceptions() const { + /// Returns true if the exception handling method for the platform uses call + /// frame information to unwind. + bool usesCFIForEH() const { return (ExceptionsType == ExceptionHandling::DwarfCFI || ExceptionsType == ExceptionHandling::ARM || - // This Windows EH type uses the Itanium LSDA encoding. - ExceptionsType == ExceptionHandling::ItaniumWinEH); + ExceptionsType == ExceptionHandling::WinEH); + } + + bool usesWindowsCFI() const { + return ExceptionsType == ExceptionHandling::WinEH; } bool doesDwarfUseRelocationsAcrossSections() const { diff --git a/include/llvm/MC/MCAsmInfoDarwin.h b/include/llvm/MC/MCAsmInfoDarwin.h index 3d249f9..d587c3c 100644 --- a/include/llvm/MC/MCAsmInfoDarwin.h +++ b/include/llvm/MC/MCAsmInfoDarwin.h @@ -19,9 +19,9 @@ namespace llvm { class MCAsmInfoDarwin : public MCAsmInfo { - virtual void anchor(); public: explicit MCAsmInfoDarwin(); + bool isSectionAtomizableBySymbols(const MCSection &Section) const override; }; } diff --git a/include/llvm/MC/MCAssembler.h b/include/llvm/MC/MCAssembler.h index 681a317..8c56f88 100644 --- a/include/llvm/MC/MCAssembler.h +++ b/include/llvm/MC/MCAssembler.h @@ -11,6 +11,7 @@ #define LLVM_MC_MCASSEMBLER_H #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DenseSet.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallString.h" @@ -46,8 +47,8 @@ class MCAsmBackend; class MCFragment : public ilist_node { friend class MCAsmLayout; - MCFragment(const MCFragment&) LLVM_DELETED_FUNCTION; - void operator=(const MCFragment&) LLVM_DELETED_FUNCTION; + MCFragment(const MCFragment&) = delete; + void operator=(const MCFragment&) = delete; public: enum FragmentType { @@ -562,8 +563,8 @@ public: class MCSectionData : public ilist_node { friend class MCAsmLayout; - MCSectionData(const MCSectionData&) LLVM_DELETED_FUNCTION; - void operator=(const MCSectionData&) LLVM_DELETED_FUNCTION; + MCSectionData(const MCSectionData&) = delete; + void operator=(const MCSectionData&) = delete; public: typedef iplist FragmentListType; @@ -864,8 +865,8 @@ public: unsigned Update; } VersionMinInfoType; private: - MCAssembler(const MCAssembler&) LLVM_DELETED_FUNCTION; - void operator=(const MCAssembler&) LLVM_DELETED_FUNCTION; + MCAssembler(const MCAssembler&) = delete; + void operator=(const MCAssembler&) = delete; MCContext &Context; @@ -881,6 +882,8 @@ private: iplist Symbols; + DenseSet LocalsUsedInReloc; + /// The map of sections to their associated assembler backend data. // // FIXME: Avoid this indirection? @@ -980,6 +983,9 @@ private: MCFragment &F, const MCFixup &Fixup); public: + void addLocalUsedInReloc(const MCSymbol &Sym); + bool isLocalUsedInReloc(const MCSymbol &Sym) const; + /// Compute the effective fragment size assuming it is laid out at the given /// \p SectionAddress and \p FragmentOffset. uint64_t computeFragmentSize(const MCAsmLayout &Layout, diff --git a/include/llvm/MC/MCCodeEmitter.h b/include/llvm/MC/MCCodeEmitter.h index d3b5617..ddf0f82 100644 --- a/include/llvm/MC/MCCodeEmitter.h +++ b/include/llvm/MC/MCCodeEmitter.h @@ -22,8 +22,8 @@ template class SmallVectorImpl; /// MCCodeEmitter - Generic instruction encoding interface. class MCCodeEmitter { private: - MCCodeEmitter(const MCCodeEmitter &) LLVM_DELETED_FUNCTION; - void operator=(const MCCodeEmitter &) LLVM_DELETED_FUNCTION; + MCCodeEmitter(const MCCodeEmitter &) = delete; + void operator=(const MCCodeEmitter &) = delete; protected: // Can only create subclasses. MCCodeEmitter(); diff --git a/include/llvm/MC/MCContext.h b/include/llvm/MC/MCContext.h index f209448..cd96dfd 100644 --- a/include/llvm/MC/MCContext.h +++ b/include/llvm/MC/MCContext.h @@ -47,8 +47,8 @@ namespace llvm { /// of the sections that it creates. /// class MCContext { - MCContext(const MCContext&) LLVM_DELETED_FUNCTION; - MCContext &operator=(const MCContext&) LLVM_DELETED_FUNCTION; + MCContext(const MCContext&) = delete; + MCContext &operator=(const MCContext&) = delete; public: typedef StringMap SymbolTable; private: @@ -237,6 +237,8 @@ namespace llvm { MCSymbol *getOrCreateSectionSymbol(const MCSectionELF &Section); + MCSymbol *getOrCreateFrameAllocSymbol(StringRef FuncName); + /// LookupSymbol - Get the symbol for \p Name, or null. MCSymbol *LookupSymbol(StringRef Name) const; MCSymbol *LookupSymbol(const Twine &Name) const; @@ -269,11 +271,15 @@ namespace llvm { } const MCSectionELF *getELFSection(StringRef Section, unsigned Type, - unsigned Flags, SectionKind Kind); + unsigned Flags); + + const MCSectionELF *getELFSection(StringRef Section, unsigned Type, + unsigned Flags, unsigned EntrySize, + StringRef Group); const MCSectionELF *getELFSection(StringRef Section, unsigned Type, - unsigned Flags, SectionKind Kind, - unsigned EntrySize, StringRef Group); + unsigned Flags, unsigned EntrySize, + StringRef Group, bool Unique); void renameELFSection(const MCSectionELF *Section, StringRef Name); diff --git a/include/llvm/MC/MCDwarf.h b/include/llvm/MC/MCDwarf.h index a221d26..c266acf 100644 --- a/include/llvm/MC/MCDwarf.h +++ b/include/llvm/MC/MCDwarf.h @@ -16,16 +16,16 @@ #define LLVM_MC_MCDWARF_H #include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/StringMap.h" #include "llvm/ADT/MapVector.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/Dwarf.h" #include "llvm/Support/raw_ostream.h" #include -#include #include #include +#include namespace llvm { class MCAsmBackend; diff --git a/include/llvm/MC/MCELFObjectWriter.h b/include/llvm/MC/MCELFObjectWriter.h index 421e7a0..9763635 100644 --- a/include/llvm/MC/MCELFObjectWriter.h +++ b/include/llvm/MC/MCELFObjectWriter.h @@ -41,6 +41,7 @@ protected: public: static uint8_t getOSABI(Triple::OSType OSType) { switch (OSType) { + case Triple::PS4: case Triple::FreeBSD: return ELF::ELFOSABI_FREEBSD; case Triple::Linux: diff --git a/include/llvm/MC/MCExpr.h b/include/llvm/MC/MCExpr.h index f0e8611..5e2ef3f 100644 --- a/include/llvm/MC/MCExpr.h +++ b/include/llvm/MC/MCExpr.h @@ -44,8 +44,8 @@ public: private: ExprKind Kind; - MCExpr(const MCExpr&) LLVM_DELETED_FUNCTION; - void operator=(const MCExpr&) LLVM_DELETED_FUNCTION; + MCExpr(const MCExpr&) = delete; + void operator=(const MCExpr&) = delete; bool EvaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm, const MCAsmLayout *Layout, @@ -194,6 +194,7 @@ public: VK_ARM_TARGET1, VK_ARM_TARGET2, VK_ARM_PREL31, + VK_ARM_SBREL, // symbol(sbrel) VK_ARM_TLSLDO, // symbol(tlsldo) VK_ARM_TLSCALL, // symbol(tlscall) VK_ARM_TLSDESC, // symbol(tlsdesc) diff --git a/include/llvm/MC/MCInst.h b/include/llvm/MC/MCInst.h index 6918280..aed7347 100644 --- a/include/llvm/MC/MCInst.h +++ b/include/llvm/MC/MCInst.h @@ -31,7 +31,7 @@ class MCInst; /// MCOperand - Instances of this class represent operands of the MCInst class. /// This is a simple discriminated union. class MCOperand { - enum MachineOperandType { + enum MachineOperandType : unsigned char { kInvalid, ///< Uninitialized. kRegister, ///< Register operand. kImmediate, ///< Immediate operand. @@ -39,7 +39,7 @@ class MCOperand { kExpr, ///< Relocatable immediate operand. kInst ///< Sub-instruction operand. }; - unsigned char Kind; + MachineOperandType Kind; union { unsigned RegVal; @@ -139,7 +139,7 @@ public: return Op; } - void print(raw_ostream &OS, const MCAsmInfo *MAI) const; + void print(raw_ostream &OS) const; void dump() const; }; @@ -169,33 +169,35 @@ public: } void clear() { Operands.clear(); } - size_t size() { return Operands.size(); } + size_t size() const { return Operands.size(); } typedef SmallVectorImpl::iterator iterator; + typedef SmallVectorImpl::const_iterator const_iterator; iterator begin() { return Operands.begin(); } - iterator end() { return Operands.end(); } + const_iterator begin() const { return Operands.begin(); } + iterator end() { return Operands.end(); } + const_iterator end() const { return Operands.end(); } iterator insert(iterator I, const MCOperand &Op) { return Operands.insert(I, Op); } - void print(raw_ostream &OS, const MCAsmInfo *MAI) const; + void print(raw_ostream &OS) const; void dump() const; /// \brief Dump the MCInst as prettily as possible using the additional MC /// structures, if given. Operators are separated by the \p Separator /// string. - void dump_pretty(raw_ostream &OS, const MCAsmInfo *MAI = nullptr, - const MCInstPrinter *Printer = nullptr, + void dump_pretty(raw_ostream &OS, const MCInstPrinter *Printer = nullptr, StringRef Separator = " ") const; }; inline raw_ostream& operator<<(raw_ostream &OS, const MCOperand &MO) { - MO.print(OS, nullptr); + MO.print(OS); return OS; } inline raw_ostream& operator<<(raw_ostream &OS, const MCInst &MI) { - MI.print(OS, nullptr); + MI.print(OS); return OS; } diff --git a/include/llvm/MC/MCInstPrinter.h b/include/llvm/MC/MCInstPrinter.h index 95124c3..dce3a06 100644 --- a/include/llvm/MC/MCInstPrinter.h +++ b/include/llvm/MC/MCInstPrinter.h @@ -95,12 +95,14 @@ public: void setPrintImmHex(HexStyle::Style Value) { PrintHexStyle = Value; } /// Utility function to print immediates in decimal or hex. - format_object1 formatImm(const int64_t Value) const { return PrintImmHex ? formatHex(Value) : formatDec(Value); } + format_object formatImm(int64_t Value) const { + return PrintImmHex ? formatHex(Value) : formatDec(Value); + } /// Utility functions to print decimal/hexadecimal values. - format_object1 formatDec(const int64_t Value) const; - format_object1 formatHex(const int64_t Value) const; - format_object1 formatHex(const uint64_t Value) const; + format_object formatDec(int64_t Value) const; + format_object formatHex(int64_t Value) const; + format_object formatHex(uint64_t Value) const; }; } // namespace llvm diff --git a/include/llvm/MC/MCInstrDesc.h b/include/llvm/MC/MCInstrDesc.h index d4f93c1..3609893 100644 --- a/include/llvm/MC/MCInstrDesc.h +++ b/include/llvm/MC/MCInstrDesc.h @@ -44,11 +44,12 @@ namespace MCOI { /// Operand Type - Operands are tagged with one of the values of this enum. enum OperandType { - OPERAND_UNKNOWN, - OPERAND_IMMEDIATE, - OPERAND_REGISTER, - OPERAND_MEMORY, - OPERAND_PCREL + OPERAND_UNKNOWN = 0, + OPERAND_IMMEDIATE = 1, + OPERAND_REGISTER = 2, + OPERAND_MEMORY = 3, + OPERAND_PCREL = 4, + OPERAND_FIRST_TARGET = 5 }; } diff --git a/include/llvm/MC/MCLabel.h b/include/llvm/MC/MCLabel.h index f531de8..a386deb 100644 --- a/include/llvm/MC/MCLabel.h +++ b/include/llvm/MC/MCLabel.h @@ -32,8 +32,8 @@ namespace llvm { MCLabel(unsigned instance) : Instance(instance) {} - MCLabel(const MCLabel&) LLVM_DELETED_FUNCTION; - void operator=(const MCLabel&) LLVM_DELETED_FUNCTION; + MCLabel(const MCLabel&) = delete; + void operator=(const MCLabel&) = delete; public: /// getInstance - Get the current instance of this Directional Local Label. unsigned getInstance() const { return Instance; } diff --git a/include/llvm/MC/MCLinkerOptimizationHint.h b/include/llvm/MC/MCLinkerOptimizationHint.h index 1f91b0d..890d638 100644 --- a/include/llvm/MC/MCLinkerOptimizationHint.h +++ b/include/llvm/MC/MCLinkerOptimizationHint.h @@ -18,8 +18,8 @@ #define LLVM_MC_MCLINKEROPTIMIZATIONHINT_H #include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/StringSwitch.h" #include "llvm/MC/MCMachObjectWriter.h" #include "llvm/Support/raw_ostream.h" diff --git a/include/llvm/MC/MCMachObjectWriter.h b/include/llvm/MC/MCMachObjectWriter.h index 0c5aa8a..e4681c0 100644 --- a/include/llvm/MC/MCMachObjectWriter.h +++ b/include/llvm/MC/MCMachObjectWriter.h @@ -68,12 +68,10 @@ public: /// @name API /// @{ - virtual void RecordRelocation(MachObjectWriter *Writer, - const MCAssembler &Asm, + virtual void RecordRelocation(MachObjectWriter *Writer, MCAssembler &Asm, const MCAsmLayout &Layout, const MCFragment *Fragment, - const MCFixup &Fixup, - MCValue Target, + const MCFixup &Fixup, MCValue Target, uint64_t &FixedValue) = 0; /// @} @@ -97,8 +95,14 @@ class MachObjectWriter : public MCObjectWriter { /// @name Relocation Data /// @{ - llvm::DenseMap > Relocations; + struct RelAndSymbol { + const MCSymbolData *Sym; + MachO::any_relocation_info MRE; + RelAndSymbol(const MCSymbolData *Sym, const MachO::any_relocation_info &MRE) + : Sym(Sym), MRE(MRE) {} + }; + + llvm::DenseMap> Relocations; llvm::DenseMap IndirectSymBase; /// @} @@ -213,9 +217,15 @@ public: // - Input errors, where something cannot be correctly encoded. 'as' allows // these through in many cases. - void addRelocation(const MCSectionData *SD, + // Add a relocation to be output in the object file. At the time this is + // called, the symbol indexes are not know, so if the relocation refers + // to a symbol it should be passed as \p RelSymbol so that it can be updated + // afterwards. If the relocation doesn't refer to a symbol, nullptr should be + // used. + void addRelocation(const MCSymbolData *RelSymbol, const MCSectionData *SD, MachO::any_relocation_info &MRE) { - Relocations[SD].push_back(MRE); + RelAndSymbol P(RelSymbol, MRE); + Relocations[SD].push_back(P); } void RecordScatteredRelocation(const MCAssembler &Asm, @@ -231,7 +241,7 @@ public: const MCFixup &Fixup, MCValue Target, uint64_t &FixedValue); - void RecordRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout, + void RecordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout, const MCFragment *Fragment, const MCFixup &Fixup, MCValue Target, bool &IsPCRel, uint64_t &FixedValue) override; diff --git a/include/llvm/MC/MCObjectWriter.h b/include/llvm/MC/MCObjectWriter.h index 55c828c..430075c 100644 --- a/include/llvm/MC/MCObjectWriter.h +++ b/include/llvm/MC/MCObjectWriter.h @@ -37,8 +37,8 @@ class MCValue; /// The object writer also contains a number of helper methods for writing /// binary data to the output stream. class MCObjectWriter { - MCObjectWriter(const MCObjectWriter &) LLVM_DELETED_FUNCTION; - void operator=(const MCObjectWriter &) LLVM_DELETED_FUNCTION; + MCObjectWriter(const MCObjectWriter &) = delete; + void operator=(const MCObjectWriter &) = delete; protected: raw_ostream &OS; @@ -76,12 +76,10 @@ public: /// post layout binding. The implementation is responsible for storing /// information about the relocation so that it can be emitted during /// WriteObject(). - virtual void RecordRelocation(const MCAssembler &Asm, - const MCAsmLayout &Layout, + virtual void RecordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout, const MCFragment *Fragment, const MCFixup &Fixup, MCValue Target, - bool &IsPCRel, - uint64_t &FixedValue) = 0; + bool &IsPCRel, uint64_t &FixedValue) = 0; /// \brief Check whether the difference (A - B) between two symbol /// references is fully resolved. diff --git a/include/llvm/MC/MCParser/AsmLexer.h b/include/llvm/MC/MCParser/AsmLexer.h index a9a30f1..2f681d6 100644 --- a/include/llvm/MC/MCParser/AsmLexer.h +++ b/include/llvm/MC/MCParser/AsmLexer.h @@ -31,8 +31,8 @@ class AsmLexer : public MCAsmLexer { StringRef CurBuf; bool isAtStartOfLine; - void operator=(const AsmLexer&) LLVM_DELETED_FUNCTION; - AsmLexer(const AsmLexer&) LLVM_DELETED_FUNCTION; + void operator=(const AsmLexer&) = delete; + AsmLexer(const AsmLexer&) = delete; protected: /// LexToken - Read the next token and return its code. diff --git a/include/llvm/MC/MCParser/MCAsmLexer.h b/include/llvm/MC/MCParser/MCAsmLexer.h index b05891c..14f8ade 100644 --- a/include/llvm/MC/MCParser/MCAsmLexer.h +++ b/include/llvm/MC/MCParser/MCAsmLexer.h @@ -124,8 +124,8 @@ class MCAsmLexer { SMLoc ErrLoc; std::string Err; - MCAsmLexer(const MCAsmLexer &) LLVM_DELETED_FUNCTION; - void operator=(const MCAsmLexer &) LLVM_DELETED_FUNCTION; + MCAsmLexer(const MCAsmLexer &) = delete; + void operator=(const MCAsmLexer &) = delete; protected: // Can only create subclasses. const char *TokStart; bool SkipSpace; diff --git a/include/llvm/MC/MCParser/MCAsmParser.h b/include/llvm/MC/MCParser/MCAsmParser.h index 34188e6..83ffbb5 100644 --- a/include/llvm/MC/MCParser/MCAsmParser.h +++ b/include/llvm/MC/MCParser/MCAsmParser.h @@ -68,8 +68,8 @@ public: ExtensionDirectiveHandler; private: - MCAsmParser(const MCAsmParser &) LLVM_DELETED_FUNCTION; - void operator=(const MCAsmParser &) LLVM_DELETED_FUNCTION; + MCAsmParser(const MCAsmParser &) = delete; + void operator=(const MCAsmParser &) = delete; MCTargetAsmParser *TargetParser; diff --git a/include/llvm/MC/MCParser/MCAsmParserExtension.h b/include/llvm/MC/MCParser/MCAsmParserExtension.h index bfc0afa..53515d7 100644 --- a/include/llvm/MC/MCParser/MCAsmParserExtension.h +++ b/include/llvm/MC/MCParser/MCAsmParserExtension.h @@ -21,8 +21,8 @@ class Twine; /// which is implemented by target and object file assembly parser /// implementations. class MCAsmParserExtension { - MCAsmParserExtension(const MCAsmParserExtension &) LLVM_DELETED_FUNCTION; - void operator=(const MCAsmParserExtension &) LLVM_DELETED_FUNCTION; + MCAsmParserExtension(const MCAsmParserExtension &) = delete; + void operator=(const MCAsmParserExtension &) = delete; MCAsmParser *Parser; diff --git a/include/llvm/MC/MCRegisterInfo.h b/include/llvm/MC/MCRegisterInfo.h index df556e7..8e25ee1 100644 --- a/include/llvm/MC/MCRegisterInfo.h +++ b/include/llvm/MC/MCRegisterInfo.h @@ -114,6 +114,10 @@ struct MCRegisterDesc { // RegUnits - Points to the list of register units. The low 4 bits holds the // Scale, the high bits hold an offset into DiffLists. See MCRegUnitIterator. uint32_t RegUnits; + + /// Index into list with lane mask sequences. The sequence contains a lanemask + /// for every register unit. + uint16_t RegUnitLaneMasks; }; /// MCRegisterInfo base class - We assume that the target defines a static @@ -157,6 +161,8 @@ private: unsigned NumRegUnits; // Number of regunits. const MCPhysReg (*RegUnitRoots)[2]; // Pointer to regunit root table. const MCPhysReg *DiffLists; // Pointer to the difflists array + const unsigned *RegUnitMaskSequences; // Pointer to lane mask sequences + // for register units. const char *RegStrings; // Pointer to the string table. const char *RegClassStrings; // Pointer to the class strings. const uint16_t *SubRegIndices; // Pointer to the subreg lookup @@ -227,8 +233,10 @@ public: // These iterators are allowed to sub-class DiffListIterator and access // internal list pointers. friend class MCSubRegIterator; + friend class MCSubRegIndexIterator; friend class MCSuperRegIterator; friend class MCRegUnitIterator; + friend class MCRegUnitMaskIterator; friend class MCRegUnitRootIterator; /// \brief Initialize MCRegisterInfo, called by TableGen @@ -239,6 +247,7 @@ public: const MCPhysReg (*RURoots)[2], unsigned NRU, const MCPhysReg *DL, + const unsigned *RUMS, const char *Strings, const char *ClassStrings, const uint16_t *SubIndices, @@ -251,6 +260,7 @@ public: PCReg = PC; Classes = C; DiffLists = DL; + RegUnitMaskSequences = RUMS; RegStrings = Strings; RegClassStrings = ClassStrings; NumClasses = NC; @@ -452,6 +462,38 @@ public: } }; +/// Iterator that enumerates the sub-registers of a Reg and the associated +/// sub-register indices. +class MCSubRegIndexIterator { + MCSubRegIterator SRIter; + const uint16_t *SRIndex; +public: + /// Constructs an iterator that traverses subregisters and their + /// associated subregister indices. + MCSubRegIndexIterator(unsigned Reg, const MCRegisterInfo *MCRI) + : SRIter(Reg, MCRI) { + SRIndex = MCRI->SubRegIndices + MCRI->get(Reg).SubRegIndices; + } + + /// Returns current sub-register. + unsigned getSubReg() const { + return *SRIter; + } + /// Returns sub-register index of the current sub-register. + unsigned getSubRegIndex() const { + return *SRIndex; + } + + /// Returns true if this iterator is not yet at the end. + bool isValid() const { return SRIter.isValid(); } + + /// Moves to the next position. + void operator++() { + ++SRIter; + ++SRIndex; + } +}; + /// MCSuperRegIterator enumerates all super-registers of Reg. /// If IncludeSelf is set, Reg itself is included in the list. class MCSuperRegIterator : public MCRegisterInfo::DiffListIterator { @@ -513,6 +555,36 @@ public: } }; +/// MCRegUnitIterator enumerates a list of register units and their associated +/// lane masks for Reg. The register units are in ascending numerical order. +class MCRegUnitMaskIterator { + MCRegUnitIterator RUIter; + const unsigned *MaskListIter; +public: + MCRegUnitMaskIterator() {} + /// Constructs an iterator that traverses the register units and their + /// associated LaneMasks in Reg. + MCRegUnitMaskIterator(unsigned Reg, const MCRegisterInfo *MCRI) + : RUIter(Reg, MCRI) { + uint16_t Idx = MCRI->get(Reg).RegUnitLaneMasks; + MaskListIter = &MCRI->RegUnitMaskSequences[Idx]; + } + + /// Returns a (RegUnit, LaneMask) pair. + std::pair operator*() const { + return std::make_pair(*RUIter, *MaskListIter); + } + + /// Returns true if this iterator is not yet at the end. + bool isValid() const { return RUIter.isValid(); } + + /// Moves to the next position. + void operator++() { + ++MaskListIter; + ++RUIter; + } +}; + // Each register unit has one or two root registers. The complete set of // registers containing a register unit is the union of the roots and their // super-registers. All registers aliasing Unit can be visited like this: diff --git a/include/llvm/MC/MCRelocationInfo.h b/include/llvm/MC/MCRelocationInfo.h index 9dab900..40e0217 100644 --- a/include/llvm/MC/MCRelocationInfo.h +++ b/include/llvm/MC/MCRelocationInfo.h @@ -28,8 +28,8 @@ class MCContext; /// \brief Create MCExprs from relocations found in an object file. class MCRelocationInfo { - MCRelocationInfo(const MCRelocationInfo &) LLVM_DELETED_FUNCTION; - void operator=(const MCRelocationInfo &) LLVM_DELETED_FUNCTION; + MCRelocationInfo(const MCRelocationInfo &) = delete; + void operator=(const MCRelocationInfo &) = delete; protected: MCContext &Ctx; diff --git a/include/llvm/MC/MCSection.h b/include/llvm/MC/MCSection.h index de2678a..8aec9c8 100644 --- a/include/llvm/MC/MCSection.h +++ b/include/llvm/MC/MCSection.h @@ -35,8 +35,8 @@ namespace llvm { }; private: - MCSection(const MCSection&) LLVM_DELETED_FUNCTION; - void operator=(const MCSection&) LLVM_DELETED_FUNCTION; + MCSection(const MCSection&) = delete; + void operator=(const MCSection&) = delete; protected: MCSection(SectionVariant V, SectionKind K) : Variant(V), Kind(K) {} SectionVariant Variant; diff --git a/include/llvm/MC/MCSectionELF.h b/include/llvm/MC/MCSectionELF.h index 5ec23f1..6d864b4 100644 --- a/include/llvm/MC/MCSectionELF.h +++ b/include/llvm/MC/MCSectionELF.h @@ -39,6 +39,8 @@ class MCSectionELF : public MCSection { /// below. unsigned Flags; + bool Unique; + /// EntrySize - The size of each entry in this section. This size only /// makes sense for sections that contain fixed-sized entries. If a /// section does not contain fixed-sized entries 'EntrySize' will be 0. @@ -48,10 +50,10 @@ class MCSectionELF : public MCSection { private: friend class MCContext; - MCSectionELF(StringRef Section, unsigned type, unsigned flags, - SectionKind K, unsigned entrySize, const MCSymbol *group) - : MCSection(SV_ELF, K), SectionName(Section), Type(type), Flags(flags), - EntrySize(entrySize), Group(group) {} + MCSectionELF(StringRef Section, unsigned type, unsigned flags, SectionKind K, + unsigned entrySize, const MCSymbol *group, bool Unique) + : MCSection(SV_ELF, K), SectionName(Section), Type(type), Flags(flags), + Unique(Unique), EntrySize(entrySize), Group(group) {} ~MCSectionELF(); void setSectionName(StringRef Name) { SectionName = Name; } @@ -92,10 +94,6 @@ public: static bool classof(const MCSection *S) { return S->getVariant() == SV_ELF; } - - // Return the entry size for sections with fixed-width data. - static unsigned DetermineEntrySize(SectionKind Kind); - }; } // end namespace llvm diff --git a/include/llvm/MC/MCStreamer.h b/include/llvm/MC/MCStreamer.h index df896a6..f0be77f 100644 --- a/include/llvm/MC/MCStreamer.h +++ b/include/llvm/MC/MCStreamer.h @@ -49,14 +49,14 @@ typedef std::pair MCSectionSubPair; /// /// If target foo wants to use this, it should implement 3 classes: /// * FooTargetStreamer : public MCTargetStreamer -/// * FooTargetAsmSreamer : public FooTargetStreamer +/// * FooTargetAsmStreamer : public FooTargetStreamer /// * FooTargetELFStreamer : public FooTargetStreamer /// /// FooTargetStreamer should have a pure virtual method for each directive. For /// example, for a ".bar symbol_name" directive, it should have /// virtual emitBar(const MCSymbol &Symbol) = 0; /// -/// The FooTargetAsmSreamer and FooTargetELFStreamer classes implement the +/// The FooTargetAsmStreamer and FooTargetELFStreamer classes implement the /// method. The assembly streamer just prints ".bar symbol_name". The object /// streamer does whatever is needed to implement .bar in the object file. /// @@ -66,8 +66,9 @@ typedef std::pair MCSectionSubPair; /// MCTargetStreamer &TS = OutStreamer.getTargetStreamer(); /// FooTargetStreamer &ATS = static_cast(TS); /// -/// The base classes FooTargetAsmSreamer and FooTargetELFStreamer should *never* -/// be treated differently. Callers should always talk to a FooTargetStreamer. +/// The base classes FooTargetAsmStreamer and FooTargetELFStreamer should +/// *never* be treated differently. Callers should always talk to a +/// FooTargetStreamer. class MCTargetStreamer { protected: MCStreamer &Streamer; @@ -138,6 +139,7 @@ public: StringRef StringValue = ""); virtual void emitFPU(unsigned FPU); virtual void emitArch(unsigned Arch); + virtual void emitArchExtension(unsigned ArchExt); virtual void emitObjectArch(unsigned Arch); virtual void finishAttributeSection(); virtual void emitInst(uint32_t Inst, char Suffix = '\0'); @@ -174,8 +176,8 @@ class MCStreamer { MCContext &Context; std::unique_ptr TargetStreamer; - MCStreamer(const MCStreamer &) LLVM_DELETED_FUNCTION; - MCStreamer &operator=(const MCStreamer &) LLVM_DELETED_FUNCTION; + MCStreamer(const MCStreamer &) = delete; + MCStreamer &operator=(const MCStreamer &) = delete; std::vector DwarfFrameInfos; MCDwarfFrameInfo *getCurrentDwarfFrameInfo(); diff --git a/include/llvm/MC/MCSubtargetInfo.h b/include/llvm/MC/MCSubtargetInfo.h index 9d09bd8..3984a1f 100644 --- a/include/llvm/MC/MCSubtargetInfo.h +++ b/include/llvm/MC/MCSubtargetInfo.h @@ -28,6 +28,7 @@ class StringRef; /// class MCSubtargetInfo { std::string TargetTriple; // Target triple + std::string CPU; // CPU being targeted. ArrayRef ProcFeatures; // Processor feature list ArrayRef ProcDesc; // Processor descriptions @@ -59,6 +60,11 @@ public: return TargetTriple; } + /// getCPU - Return the CPU string. + StringRef getCPU() const { + return CPU; + } + /// getFeatureBits - Return the feature bits. /// uint64_t getFeatureBits() const { @@ -136,6 +142,15 @@ public: /// Initialize an InstrItineraryData instance. void initInstrItins(InstrItineraryData &InstrItins) const; + + /// Check whether the CPU string is valid. + bool isCPUStringValid(StringRef CPU) { + auto Found = std::find_if(ProcDesc.begin(), ProcDesc.end(), + [=](const SubtargetFeatureKV &KV) { + return CPU == KV.Key; + }); + return Found != ProcDesc.end(); + } }; } // End llvm namespace diff --git a/include/llvm/MC/MCSymbol.h b/include/llvm/MC/MCSymbol.h index 0b3c3ce..53443b0 100644 --- a/include/llvm/MC/MCSymbol.h +++ b/include/llvm/MC/MCSymbol.h @@ -53,6 +53,9 @@ namespace llvm { /// "Lfoo" or ".foo". unsigned IsTemporary : 1; + /// \brief True if this symbol can be redefined. + unsigned IsRedefinable : 1; + /// IsUsed - True if this symbol has been used. mutable unsigned IsUsed : 1; @@ -61,10 +64,10 @@ namespace llvm { friend class MCContext; MCSymbol(StringRef name, bool isTemporary) : Name(name), Section(nullptr), Value(nullptr), - IsTemporary(isTemporary), IsUsed(false) {} + IsTemporary(isTemporary), IsRedefinable(false), IsUsed(false) {} - MCSymbol(const MCSymbol&) LLVM_DELETED_FUNCTION; - void operator=(const MCSymbol&) LLVM_DELETED_FUNCTION; + MCSymbol(const MCSymbol&) = delete; + void operator=(const MCSymbol&) = delete; public: /// getName - Get the symbol name. StringRef getName() const { return Name; } @@ -79,6 +82,19 @@ namespace llvm { bool isUsed() const { return IsUsed; } void setUsed(bool Value) const { IsUsed = Value; } + /// \brief Check if this symbol is redefinable. + bool isRedefinable() const { return IsRedefinable; } + /// \brief Mark this symbol as redefinable. + void setRedefinable(bool Value) { IsRedefinable = Value; } + /// \brief Prepare this symbol to be redefined. + void redefineIfPossible() { + if (IsRedefinable) { + Value = nullptr; + Section = nullptr; + IsRedefinable = false; + } + } + /// @} /// @name Associated Sections /// @{ diff --git a/include/llvm/MC/MCSymbolizer.h b/include/llvm/MC/MCSymbolizer.h index cbbb591..20e7b81 100644 --- a/include/llvm/MC/MCSymbolizer.h +++ b/include/llvm/MC/MCSymbolizer.h @@ -38,8 +38,8 @@ class raw_ostream; /// operands are actually symbolizable, and in what way. I don't think this /// information exists right now. class MCSymbolizer { - MCSymbolizer(const MCSymbolizer &) LLVM_DELETED_FUNCTION; - void operator=(const MCSymbolizer &) LLVM_DELETED_FUNCTION; + MCSymbolizer(const MCSymbolizer &) = delete; + void operator=(const MCSymbolizer &) = delete; protected: MCContext &Ctx; diff --git a/include/llvm/MC/MCTargetAsmParser.h b/include/llvm/MC/MCTargetAsmParser.h index cf92307..8412b1d 100644 --- a/include/llvm/MC/MCTargetAsmParser.h +++ b/include/llvm/MC/MCTargetAsmParser.h @@ -13,7 +13,6 @@ #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCParser/MCAsmParserExtension.h" #include "llvm/MC/MCTargetOptions.h" - #include namespace llvm { @@ -92,8 +91,8 @@ public: }; private: - MCTargetAsmParser(const MCTargetAsmParser &) LLVM_DELETED_FUNCTION; - void operator=(const MCTargetAsmParser &) LLVM_DELETED_FUNCTION; + MCTargetAsmParser(const MCTargetAsmParser &) = delete; + void operator=(const MCTargetAsmParser &) = delete; protected: // Can only create subclasses. MCTargetAsmParser(); diff --git a/include/llvm/MC/MCTargetOptions.h b/include/llvm/MC/MCTargetOptions.h index de79bae..ce28a19 100644 --- a/include/llvm/MC/MCTargetOptions.h +++ b/include/llvm/MC/MCTargetOptions.h @@ -10,8 +10,12 @@ #ifndef LLVM_MC_MCTARGETOPTIONS_H #define LLVM_MC_MCTARGETOPTIONS_H +#include + namespace llvm { +class StringRef; + class MCTargetOptions { public: enum AsmInstrumentation { @@ -31,6 +35,11 @@ public: bool ShowMCInst : 1; bool AsmVerbose : 1; int DwarfVersion; + /// getABIName - If this returns a non-empty string this represents the + /// textual name of the ABI that we want the backend to use, e.g. o32, or + /// aapcs-linux. + StringRef getABIName() const; + std::string ABIName; MCTargetOptions(); }; @@ -45,7 +54,8 @@ inline bool operator==(const MCTargetOptions &LHS, const MCTargetOptions &RHS) { ARE_EQUAL(ShowMCEncoding) && ARE_EQUAL(ShowMCInst) && ARE_EQUAL(AsmVerbose) && - ARE_EQUAL(DwarfVersion)); + ARE_EQUAL(DwarfVersion) && + ARE_EQUAL(ABIName)); #undef ARE_EQUAL } diff --git a/include/llvm/MC/MCTargetOptionsCommandFlags.h b/include/llvm/MC/MCTargetOptionsCommandFlags.h index 6d4eb0e..af23a92 100644 --- a/include/llvm/MC/MCTargetOptionsCommandFlags.h +++ b/include/llvm/MC/MCTargetOptionsCommandFlags.h @@ -15,8 +15,8 @@ #ifndef LLVM_MC_MCTARGETOPTIONSCOMMANDFLAGS_H #define LLVM_MC_MCTARGETOPTIONSCOMMANDFLAGS_H -#include "llvm/Support/CommandLine.h" #include "llvm/MC/MCTargetOptions.h" +#include "llvm/Support/CommandLine.h" using namespace llvm; cl::opt AsmInstrumentation( @@ -40,6 +40,11 @@ cl::opt ShowMCInst("asm-show-inst", cl::desc("Emit internal instruction representation to " "assembly file")); +cl::opt +ABIName("target-abi", cl::Hidden, + cl::desc("The name of the ABI to be targeted from the backend."), + cl::init("")); + static inline MCTargetOptions InitMCTargetOptionsFromFlags() { MCTargetOptions Options; Options.SanitizeAddress = @@ -47,6 +52,7 @@ static inline MCTargetOptions InitMCTargetOptionsFromFlags() { Options.MCRelaxAll = RelaxAll; Options.DwarfVersion = DwarfVersion; Options.ShowMCInst = ShowMCInst; + Options.ABIName = ABIName; return Options; } diff --git a/include/llvm/MC/MCValue.h b/include/llvm/MC/MCValue.h index dd86979..175fed0 100644 --- a/include/llvm/MC/MCValue.h +++ b/include/llvm/MC/MCValue.h @@ -55,7 +55,7 @@ public: bool isAbsolute() const { return !SymA && !SymB; } /// print - Print the value to the stream \p OS. - void print(raw_ostream &OS, const MCAsmInfo *MAI) const; + void print(raw_ostream &OS) const; /// dump - Print the value to stderr. void dump() const; diff --git a/include/llvm/MC/MCWinCOFFObjectWriter.h b/include/llvm/MC/MCWinCOFFObjectWriter.h index dad7bb5..956e436 100644 --- a/include/llvm/MC/MCWinCOFFObjectWriter.h +++ b/include/llvm/MC/MCWinCOFFObjectWriter.h @@ -11,10 +11,11 @@ #define LLVM_MC_MCWINCOFFOBJECTWRITER_H namespace llvm { - class MCFixup; - class MCObjectWriter; - class MCValue; - class raw_ostream; +class MCAsmBackend; +class MCFixup; +class MCObjectWriter; +class MCValue; +class raw_ostream; class MCWinCOFFObjectTargetWriter { virtual void anchor(); @@ -27,9 +28,9 @@ namespace llvm { virtual ~MCWinCOFFObjectTargetWriter() {} unsigned getMachine() const { return Machine; } - virtual unsigned getRelocType(const MCValue &Target, - const MCFixup &Fixup, - bool IsCrossSection) const = 0; + virtual unsigned getRelocType(const MCValue &Target, const MCFixup &Fixup, + bool IsCrossSection, + const MCAsmBackend &MAB) const = 0; virtual bool recordRelocation(const MCFixup &) const { return true; } }; diff --git a/include/llvm/MC/SectionKind.h b/include/llvm/MC/SectionKind.h index 85a91c6..9e8b68f 100644 --- a/include/llvm/MC/SectionKind.h +++ b/include/llvm/MC/SectionKind.h @@ -55,7 +55,6 @@ class SectionKind { /// MergeableConst - These are sections for merging fixed-length /// constants together. For example, this can be used to unique /// constant pool entries etc. - MergeableConst, /// MergeableConst4 - This is a section used by 4-byte constants, /// for example, floats. @@ -151,8 +150,8 @@ public: bool isMergeable4ByteCString() const { return K == Mergeable4ByteCString; } bool isMergeableConst() const { - return K == MergeableConst || K == MergeableConst4 || - K == MergeableConst8 || K == MergeableConst16; + return K == MergeableConst4 || K == MergeableConst8 || + K == MergeableConst16; } bool isMergeableConst4() const { return K == MergeableConst4; } bool isMergeableConst8() const { return K == MergeableConst8; } @@ -216,7 +215,6 @@ public: static SectionKind getMergeable4ByteCString() { return get(Mergeable4ByteCString); } - static SectionKind getMergeableConst() { return get(MergeableConst); } static SectionKind getMergeableConst4() { return get(MergeableConst4); } static SectionKind getMergeableConst8() { return get(MergeableConst8); } static SectionKind getMergeableConst16() { return get(MergeableConst16); } diff --git a/include/llvm/Object/Archive.h b/include/llvm/Object/Archive.h index 7c03dcd..4f8e281 100644 --- a/include/llvm/Object/Archive.h +++ b/include/llvm/Object/Archive.h @@ -14,8 +14,8 @@ #ifndef LLVM_OBJECT_ARCHIVE_H #define LLVM_OBJECT_ARCHIVE_H -#include "llvm/ADT/iterator_range.h" #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/iterator_range.h" #include "llvm/Object/Binary.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ErrorOr.h" @@ -41,6 +41,9 @@ struct ArchiveMemberHeader { sys::fs::perms getAccessMode() const; sys::TimeValue getLastModified() const; + llvm::StringRef getRawLastModified() const { + return StringRef(LastModified, sizeof(LastModified)).rtrim(" "); + } unsigned getUID() const; unsigned getGID() const; }; @@ -78,17 +81,23 @@ public: sys::TimeValue getLastModified() const { return getHeader()->getLastModified(); } + StringRef getRawLastModified() const { + return getHeader()->getRawLastModified(); + } unsigned getUID() const { return getHeader()->getUID(); } unsigned getGID() const { return getHeader()->getGID(); } sys::fs::perms getAccessMode() const { return getHeader()->getAccessMode(); } /// \return the size of the archive member without the header or padding. - uint64_t getSize() const { return Data.size() - StartOfFile; } + uint64_t getSize() const; + /// \return the size in the archive header for this member. + uint64_t getRawSize() const; StringRef getBuffer() const { return StringRef(Data.data() + StartOfFile, getSize()); } + uint64_t getChildOffset() const; ErrorOr getMemoryBufferRef() const; @@ -169,13 +178,12 @@ public: enum Kind { K_GNU, + K_MIPS64, K_BSD, K_COFF }; - Kind kind() const { - return Format; - } + Kind kind() const { return (Kind)Format; } child_iterator child_begin(bool SkipInternal = true) const; child_iterator child_end() const; @@ -196,12 +204,14 @@ public: child_iterator findSym(StringRef name) const; bool hasSymbolTable() const; + child_iterator getSymbolTableChild() const { return SymbolTable; } private: child_iterator SymbolTable; child_iterator StringTable; child_iterator FirstRegular; - Kind Format; + unsigned Format : 2; + unsigned IsThin : 1; }; } diff --git a/include/llvm/Object/Binary.h b/include/llvm/Object/Binary.h index 4b2b7e6..a3d6d0d 100644 --- a/include/llvm/Object/Binary.h +++ b/include/llvm/Object/Binary.h @@ -28,8 +28,8 @@ namespace object { class Binary { private: - Binary() LLVM_DELETED_FUNCTION; - Binary(const Binary &other) LLVM_DELETED_FUNCTION; + Binary() = delete; + Binary(const Binary &other) = delete; unsigned int TypeID; diff --git a/include/llvm/Object/COFF.h b/include/llvm/Object/COFF.h index 3368d68..522bf68 100644 --- a/include/llvm/Object/COFF.h +++ b/include/llvm/Object/COFF.h @@ -276,12 +276,14 @@ public: } const StringTableOffset &getStringTableOffset() const { + assert(isSet() && "COFFSymbolRef points to nothing!"); return CS16 ? CS16->Name.Offset : CS32->Name.Offset; } uint32_t getValue() const { return CS16 ? CS16->Value : CS32->Value; } int32_t getSectionNumber() const { + assert(isSet() && "COFFSymbolRef points to nothing!"); if (CS16) { // Reserved sections are returned as negative numbers. if (CS16->SectionNumber <= COFF::MaxNumberOfSections16) @@ -291,13 +293,18 @@ public: return static_cast(CS32->SectionNumber); } - uint16_t getType() const { return CS16 ? CS16->Type : CS32->Type; } + uint16_t getType() const { + assert(isSet() && "COFFSymbolRef points to nothing!"); + return CS16 ? CS16->Type : CS32->Type; + } uint8_t getStorageClass() const { + assert(isSet() && "COFFSymbolRef points to nothing!"); return CS16 ? CS16->StorageClass : CS32->StorageClass; } uint8_t getNumberOfAuxSymbols() const { + assert(isSet() && "COFFSymbolRef points to nothing!"); return CS16 ? CS16->NumberOfAuxSymbols : CS32->NumberOfAuxSymbols; } @@ -360,6 +367,8 @@ public: } private: + bool isSet() const { return CS16 || CS32; } + const coff_symbol16 *CS16; const coff_symbol32 *CS32; }; @@ -593,9 +602,6 @@ protected: bool isSectionData(DataRefImpl Sec) const override; bool isSectionBSS(DataRefImpl Sec) const override; bool isSectionVirtual(DataRefImpl Sec) const override; - bool isSectionZeroInit(DataRefImpl Sec) const override; - bool isSectionReadOnlyData(DataRefImpl Sec) const override; - bool isSectionRequiredForExecution(DataRefImpl Sec) const override; bool sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb) const override; relocation_iterator section_rel_begin(DataRefImpl Sec) const override; relocation_iterator section_rel_end(DataRefImpl Sec) const override; diff --git a/include/llvm/Object/ELFObjectFile.h b/include/llvm/Object/ELFObjectFile.h index 3fcd98d..e7eba97 100644 --- a/include/llvm/Object/ELFObjectFile.h +++ b/include/llvm/Object/ELFObjectFile.h @@ -48,6 +48,9 @@ public: virtual std::error_code getSymbolVersion(SymbolRef Symb, StringRef &Version, bool &IsDefault) const = 0; + virtual uint64_t getSectionFlags(SectionRef Sec) const = 0; + virtual uint32_t getSectionType(SectionRef Sec) const = 0; + static inline bool classof(const Binary *v) { return v->isELF(); } }; @@ -97,10 +100,7 @@ protected: bool isSectionText(DataRefImpl Sec) const override; bool isSectionData(DataRefImpl Sec) const override; bool isSectionBSS(DataRefImpl Sec) const override; - bool isSectionRequiredForExecution(DataRefImpl Sec) const override; bool isSectionVirtual(DataRefImpl Sec) const override; - bool isSectionZeroInit(DataRefImpl Sec) const override; - bool isSectionReadOnlyData(DataRefImpl Sec) const override; bool sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb) const override; relocation_iterator section_rel_begin(DataRefImpl Sec) const override; relocation_iterator section_rel_end(DataRefImpl Sec) const override; @@ -177,6 +177,20 @@ protected: return DRI; } + bool isExportedToOtherDSO(const Elf_Sym *ESym) const { + unsigned char Binding = ESym->getBinding(); + unsigned char Visibility = ESym->getVisibility(); + + // A symbol is exported if its binding is either GLOBAL or WEAK, and its + // visibility is either DEFAULT or PROTECTED. All other symbols are not + // exported. + if ((Binding == ELF::STB_GLOBAL || Binding == ELF::STB_WEAK) && + (Visibility == ELF::STV_DEFAULT || Visibility == ELF::STV_PROTECTED)) + return true; + + return false; + } + // This flag is used for classof, to distinguish ELFObjectFile from // its subclass. If more subclasses will be created, this flag will // have to become an enum. @@ -201,6 +215,9 @@ public: std::error_code getSymbolVersion(SymbolRef Symb, StringRef &Version, bool &IsDefault) const override; + uint64_t getSectionFlags(SectionRef Sec) const override; + uint32_t getSectionType(SectionRef Sec) const override; + uint8_t getBytesInAddress() const override; StringRef getFileFormatName() const override; unsigned getArch() const override; @@ -262,6 +279,18 @@ std::error_code ELFObjectFile::getSymbolVersion(SymbolRef SymRef, } template +uint64_t ELFObjectFile::getSectionFlags(SectionRef Sec) const { + DataRefImpl DRI = Sec.getRawDataRefImpl(); + return toELFShdrIter(DRI)->sh_flags; +} + +template +uint32_t ELFObjectFile::getSectionType(SectionRef Sec) const { + DataRefImpl DRI = Sec.getRawDataRefImpl(); + return toELFShdrIter(DRI)->sh_type; +} + +template std::error_code ELFObjectFile::getSymbolAddress(DataRefImpl Symb, uint64_t &Result) const { const Elf_Sym *ESym = getSymbol(Symb); @@ -280,12 +309,16 @@ std::error_code ELFObjectFile::getSymbolAddress(DataRefImpl Symb, const Elf_Ehdr *Header = EF.getHeader(); Result = ESym->st_value; - // Clear the ARM/Thumb indicator flag. - if (Header->e_machine == ELF::EM_ARM && ESym->getType() == ELF::STT_FUNC) + // Clear the ARM/Thumb or microMIPS indicator flag. + if ((Header->e_machine == ELF::EM_ARM || Header->e_machine == ELF::EM_MIPS) && + ESym->getType() == ELF::STT_FUNC) Result &= ~1; - if (Header->e_type == ELF::ET_REL) - Result += EF.getSection(ESym)->sh_addr; + if (Header->e_type == ELF::ET_REL) { + const typename ELFFile::Elf_Shdr * Section = EF.getSection(ESym); + if (Section != nullptr) + Result += Section->sh_addr; + } return object_error::success; } @@ -373,6 +406,9 @@ uint32_t ELFObjectFile::getSymbolFlags(DataRefImpl Symb) const { EF.getSymbolTableIndex(ESym) == ELF::SHN_COMMON) Result |= SymbolRef::SF_Common; + if (isExportedToOtherDSO(ESym)) + Result |= SymbolRef::SF_Exported; + return Result; } @@ -451,27 +487,11 @@ bool ELFObjectFile::isSectionBSS(DataRefImpl Sec) const { } template -bool ELFObjectFile::isSectionRequiredForExecution(DataRefImpl Sec) const { - return toELFShdrIter(Sec)->sh_flags & ELF::SHF_ALLOC; -} - -template bool ELFObjectFile::isSectionVirtual(DataRefImpl Sec) const { return toELFShdrIter(Sec)->sh_type == ELF::SHT_NOBITS; } template -bool ELFObjectFile::isSectionZeroInit(DataRefImpl Sec) const { - return toELFShdrIter(Sec)->sh_type == ELF::SHT_NOBITS; -} - -template -bool ELFObjectFile::isSectionReadOnlyData(DataRefImpl Sec) const { - Elf_Shdr_Iter EShdr = toELFShdrIter(Sec); - return !(EShdr->sh_flags & (ELF::SHF_WRITE | ELF::SHF_EXECINSTR)); -} - -template bool ELFObjectFile::sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb) const { Elf_Sym_Iter ESym = toELFSymIter(Symb); diff --git a/include/llvm/Object/ELFTypes.h b/include/llvm/Object/ELFTypes.h index 4bc0c7c..9a97f7b 100644 --- a/include/llvm/Object/ELFTypes.h +++ b/include/llvm/Object/ELFTypes.h @@ -302,7 +302,10 @@ struct Elf_Rel_Base, false> { assert(!isMips64EL); return r_info; } - void setRInfo(uint32_t R) { r_info = R; } + void setRInfo(uint32_t R, bool IsMips64EL) { + assert(!IsMips64EL); + r_info = R; + } }; template @@ -321,9 +324,12 @@ struct Elf_Rel_Base, false> { return (t << 32) | ((t >> 8) & 0xff000000) | ((t >> 24) & 0x00ff0000) | ((t >> 40) & 0x0000ff00) | ((t >> 56) & 0x000000ff); } - void setRInfo(uint64_t R) { - // FIXME: Add mips64el support. - r_info = R; + void setRInfo(uint64_t R, bool IsMips64EL) { + if (IsMips64EL) + r_info = (R >> 32) | ((R & 0xff000000) << 8) | ((R & 0x00ff0000) << 24) | + ((R & 0x0000ff00) << 40) | ((R & 0x000000ff) << 56); + else + r_info = R; } }; @@ -338,7 +344,10 @@ struct Elf_Rel_Base, true> { assert(!isMips64EL); return r_info; } - void setRInfo(uint32_t R) { r_info = R; } + void setRInfo(uint32_t R, bool IsMips64EL) { + assert(!IsMips64EL); + r_info = R; + } }; template @@ -358,9 +367,12 @@ struct Elf_Rel_Base, true> { return (t << 32) | ((t >> 8) & 0xff000000) | ((t >> 24) & 0x00ff0000) | ((t >> 40) & 0x0000ff00) | ((t >> 56) & 0x000000ff); } - void setRInfo(uint64_t R) { - // FIXME: Add mips64el support. - r_info = R; + void setRInfo(uint64_t R, bool IsMips64EL) { + if (IsMips64EL) + r_info = (R >> 32) | ((R & 0xff000000) << 8) | ((R & 0x00ff0000) << 24) | + ((R & 0x0000ff00) << 40) | ((R & 0x000000ff) << 56); + else + r_info = R; } }; @@ -380,10 +392,14 @@ struct Elf_Rel_Impl, uint32_t getType(bool isMips64EL) const { return (uint32_t)(this->getRInfo(isMips64EL) & 0xffffffffL); } - void setSymbol(uint32_t s) { setSymbolAndType(s, getType()); } - void setType(uint32_t t) { setSymbolAndType(getSymbol(), t); } - void setSymbolAndType(uint32_t s, uint32_t t) { - this->setRInfo(((uint64_t)s << 32) + (t & 0xffffffffL)); + void setSymbol(uint32_t s, bool IsMips64EL) { + setSymbolAndType(s, getType(), IsMips64EL); + } + void setType(uint32_t t, bool IsMips64EL) { + setSymbolAndType(getSymbol(), t, IsMips64EL); + } + void setSymbolAndType(uint32_t s, uint32_t t, bool IsMips64EL) { + this->setRInfo(((uint64_t)s << 32) + (t & 0xffffffffL), IsMips64EL); } }; @@ -401,10 +417,14 @@ struct Elf_Rel_Impl, unsigned char getType(bool isMips64EL) const { return (unsigned char)(this->getRInfo(isMips64EL) & 0x0ff); } - void setSymbol(uint32_t s) { setSymbolAndType(s, getType()); } - void setType(unsigned char t) { setSymbolAndType(getSymbol(), t); } - void setSymbolAndType(uint32_t s, unsigned char t) { - this->setRInfo((s << 8) + t); + void setSymbol(uint32_t s, bool IsMips64EL) { + setSymbolAndType(s, getType(), IsMips64EL); + } + void setType(unsigned char t, bool IsMips64EL) { + setSymbolAndType(getSymbol(), t, IsMips64EL); + } + void setSymbolAndType(uint32_t s, unsigned char t, bool IsMips64EL) { + this->setRInfo((s << 8) + t, IsMips64EL); } }; diff --git a/include/llvm/Object/ELFYAML.h b/include/llvm/Object/ELFYAML.h index 687611d..45cbdbd 100644 --- a/include/llvm/Object/ELFYAML.h +++ b/include/llvm/Object/ELFYAML.h @@ -40,7 +40,8 @@ LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_ELFOSABI) // Just use 64, since it can hold 32-bit values too. LLVM_YAML_STRONG_TYPEDEF(uint64_t, ELF_EF) LLVM_YAML_STRONG_TYPEDEF(uint32_t, ELF_SHT) -LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_REL) +LLVM_YAML_STRONG_TYPEDEF(uint32_t, ELF_REL) +LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_RSS) // Just use 64, since it can hold 32-bit values too. LLVM_YAML_STRONG_TYPEDEF(uint64_t, ELF_SHF) LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_STT) @@ -71,14 +72,20 @@ struct LocalGlobalWeakSymbols { std::vector Global; std::vector Weak; }; + +struct SectionOrType { + StringRef sectionNameOrType; +}; + struct Section { - enum class SectionKind { RawContent, Relocation }; + enum class SectionKind { Group, RawContent, Relocation }; SectionKind Kind; StringRef Name; ELF_SHT Type; ELF_SHF Flags; llvm::yaml::Hex64 Address; StringRef Link; + StringRef Info; llvm::yaml::Hex64 AddressAlign; Section(SectionKind Kind) : Kind(Kind) {} virtual ~Section(); @@ -91,6 +98,17 @@ struct RawContentSection : Section { return S->Kind == SectionKind::RawContent; } }; + +struct Group : Section { + // Members of a group contain a flag and a list of section indices + // that are part of the group. + std::vector Members; + Group() : Section(SectionKind::Group) {} + static bool classof(const Section *S) { + return S->Kind == SectionKind::Group; + } +}; + struct Relocation { llvm::yaml::Hex64 Offset; int64_t Addend; @@ -98,7 +116,6 @@ struct Relocation { StringRef Symbol; }; struct RelocationSection : Section { - StringRef Info; std::vector Relocations; RelocationSection() : Section(SectionKind::Relocation) {} static bool classof(const Section *S) { @@ -121,6 +138,7 @@ struct Object { LLVM_YAML_IS_SEQUENCE_VECTOR(std::unique_ptr) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::Symbol) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::Relocation) +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::SectionOrType) namespace llvm { namespace yaml { @@ -186,6 +204,11 @@ struct ScalarEnumerationTraits { }; template <> +struct ScalarEnumerationTraits { + static void enumeration(IO &IO, ELFYAML::ELF_RSS &Value); +}; + +template <> struct MappingTraits { static void mapping(IO &IO, ELFYAML::FileHeader &FileHdr); }; @@ -215,6 +238,10 @@ struct MappingTraits { static void mapping(IO &IO, ELFYAML::Object &Object); }; +template <> struct MappingTraits { + static void mapping(IO &IO, ELFYAML::SectionOrType §ionOrType); +}; + } // end namespace yaml } // end namespace llvm diff --git a/include/llvm/Object/IRObjectFile.h b/include/llvm/Object/IRObjectFile.h index b650d5d..74f4666 100644 --- a/include/llvm/Object/IRObjectFile.h +++ b/include/llvm/Object/IRObjectFile.h @@ -36,7 +36,10 @@ public: std::error_code printSymbolName(raw_ostream &OS, DataRefImpl Symb) const override; uint32_t getSymbolFlags(DataRefImpl Symb) const override; - const GlobalValue *getSymbolGV(DataRefImpl Symb) const; + GlobalValue *getSymbolGV(DataRefImpl Symb); + const GlobalValue *getSymbolGV(DataRefImpl Symb) const { + return const_cast(this)->getSymbolGV(Symb); + } basic_symbol_iterator symbol_begin_impl() const override; basic_symbol_iterator symbol_end_impl() const override; @@ -46,6 +49,7 @@ public: Module &getModule() { return *M; } + std::unique_ptr takeModule(); static inline bool classof(const Binary *v) { return v->isIR(); @@ -61,8 +65,8 @@ public: static ErrorOr findBitcodeInMemBuffer(MemoryBufferRef Object); - static ErrorOr> - createIRObjectFile(MemoryBufferRef Object, LLVMContext &Context); + static ErrorOr> create(MemoryBufferRef Object, + LLVMContext &Context); }; } } diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h index 768cda6..a552aca 100644 --- a/include/llvm/Object/MachO.h +++ b/include/llvm/Object/MachO.h @@ -200,6 +200,7 @@ public: // MachO specific. std::error_code getIndirectName(DataRefImpl Symb, StringRef &Res) const; + unsigned getSectionType(SectionRef Sec) const; std::error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const override; @@ -223,10 +224,7 @@ public: bool isSectionText(DataRefImpl Sec) const override; bool isSectionData(DataRefImpl Sec) const override; bool isSectionBSS(DataRefImpl Sec) const override; - bool isSectionRequiredForExecution(DataRefImpl Sec) const override; bool isSectionVirtual(DataRefImpl Sec) const override; - bool isSectionZeroInit(DataRefImpl Sec) const override; - bool isSectionReadOnlyData(DataRefImpl Sec) const override; bool sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb) const override; relocation_iterator section_rel_begin(DataRefImpl Sec) const override; relocation_iterator section_rel_end(DataRefImpl Sec) const override; @@ -348,8 +346,8 @@ public: getSegmentLoadCommand(const LoadCommandInfo &L) const; MachO::segment_command_64 getSegment64LoadCommand(const LoadCommandInfo &L) const; - MachO::linker_options_command - getLinkerOptionsLoadCommand(const LoadCommandInfo &L) const; + MachO::linker_option_command + getLinkerOptionLoadCommand(const LoadCommandInfo &L) const; MachO::version_min_command getVersionMinLoadCommand(const LoadCommandInfo &L) const; MachO::dylib_command @@ -360,10 +358,30 @@ public: getDylinkerCommand(const LoadCommandInfo &L) const; MachO::uuid_command getUuidCommand(const LoadCommandInfo &L) const; + MachO::rpath_command + getRpathCommand(const LoadCommandInfo &L) const; MachO::source_version_command getSourceVersionCommand(const LoadCommandInfo &L) const; MachO::entry_point_command getEntryPointCommand(const LoadCommandInfo &L) const; + MachO::encryption_info_command + getEncryptionInfoCommand(const LoadCommandInfo &L) const; + MachO::encryption_info_command_64 + getEncryptionInfoCommand64(const LoadCommandInfo &L) const; + MachO::sub_framework_command + getSubFrameworkCommand(const LoadCommandInfo &L) const; + MachO::sub_umbrella_command + getSubUmbrellaCommand(const LoadCommandInfo &L) const; + MachO::sub_library_command + getSubLibraryCommand(const LoadCommandInfo &L) const; + MachO::sub_client_command + getSubClientCommand(const LoadCommandInfo &L) const; + MachO::routines_command + getRoutinesCommand(const LoadCommandInfo &L) const; + MachO::routines_command_64 + getRoutinesCommand64(const LoadCommandInfo &L) const; + MachO::thread_command + getThreadCommand(const LoadCommandInfo &L) const; MachO::any_relocation_info getRelocation(DataRefImpl Rel) const; MachO::data_in_code_entry getDice(DataRefImpl Rel) const; @@ -377,6 +395,7 @@ public: MachO::symtab_command getSymtabLoadCommand() const; MachO::dysymtab_command getDysymtabLoadCommand() const; MachO::linkedit_data_command getDataInCodeLoadCommand() const; + MachO::linkedit_data_command getLinkOptHintsLoadCommand() const; ArrayRef getDyldInfoRebaseOpcodes() const; ArrayRef getDyldInfoBindOpcodes() const; ArrayRef getDyldInfoWeakBindOpcodes() const; @@ -419,6 +438,7 @@ private: const char *SymtabLoadCmd; const char *DysymtabLoadCmd; const char *DataInCodeLoadCmd; + const char *LinkOptHintsLoadCmd; const char *DyldInfoLoadCmd; const char *UuidLoadCmd; bool HasPageZeroSegment; diff --git a/include/llvm/Object/MachOUniversal.h b/include/llvm/Object/MachOUniversal.h index 46cf3fb..93f6654 100644 --- a/include/llvm/Object/MachOUniversal.h +++ b/include/llvm/Object/MachOUniversal.h @@ -16,8 +16,8 @@ #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Triple.h" -#include "llvm/Object/Binary.h" #include "llvm/Object/Archive.h" +#include "llvm/Object/Binary.h" #include "llvm/Object/MachO.h" #include "llvm/Support/ErrorOr.h" #include "llvm/Support/MachO.h" @@ -51,6 +51,10 @@ public: ObjectForArch getNext() const { return ObjectForArch(Parent, Index + 1); } uint32_t getCPUType() const { return Header.cputype; } + uint32_t getCPUSubType() const { return Header.cpusubtype; } + uint32_t getOffset() const { return Header.offset; } + uint32_t getSize() const { return Header.size; } + uint32_t getAlign() const { return Header.align; } std::string getArchTypeName() const { Triple T = MachOObjectFile::getArch(Header.cputype, Header.cpusubtype); return T.getArchName(); @@ -58,7 +62,7 @@ public: ErrorOr> getAsObjectFile() const; - std::error_code getAsArchive(std::unique_ptr &Result) const; + ErrorOr> getAsArchive() const; }; class object_iterator { diff --git a/include/llvm/Object/ObjectFile.h b/include/llvm/Object/ObjectFile.h index 68b873a..b7e19b9 100644 --- a/include/llvm/Object/ObjectFile.h +++ b/include/llvm/Object/ObjectFile.h @@ -105,10 +105,7 @@ public: bool isText() const; bool isData() const; bool isBSS() const; - bool isRequiredForExecution() const; bool isVirtual() const; - bool isZeroInit() const; - bool isReadOnlyData() const; bool containsSymbol(SymbolRef S) const; @@ -121,6 +118,7 @@ public: section_iterator getRelocatedSection() const; DataRefImpl getRawDataRefImpl() const; + const ObjectFile *getObject() const; }; /// SymbolRef - This is a value type class that represents a single symbol in @@ -182,8 +180,8 @@ public: /// figures out which type to create. class ObjectFile : public SymbolicFile { virtual void anchor(); - ObjectFile() LLVM_DELETED_FUNCTION; - ObjectFile(const ObjectFile &other) LLVM_DELETED_FUNCTION; + ObjectFile() = delete; + ObjectFile(const ObjectFile &other) = delete; protected: ObjectFile(unsigned int Type, MemoryBufferRef Source); @@ -233,11 +231,8 @@ protected: virtual bool isSectionText(DataRefImpl Sec) const = 0; virtual bool isSectionData(DataRefImpl Sec) const = 0; virtual bool isSectionBSS(DataRefImpl Sec) const = 0; - virtual bool isSectionRequiredForExecution(DataRefImpl Sec) const = 0; // A section is 'virtual' if its contents aren't present in the object image. virtual bool isSectionVirtual(DataRefImpl Sec) const = 0; - virtual bool isSectionZeroInit(DataRefImpl Sec) const = 0; - virtual bool isSectionReadOnlyData(DataRefImpl Sec) const = 0; virtual bool sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb) const = 0; virtual relocation_iterator section_rel_begin(DataRefImpl Sec) const = 0; @@ -417,22 +412,10 @@ inline bool SectionRef::isBSS() const { return OwningObject->isSectionBSS(SectionPimpl); } -inline bool SectionRef::isRequiredForExecution() const { - return OwningObject->isSectionRequiredForExecution(SectionPimpl); -} - inline bool SectionRef::isVirtual() const { return OwningObject->isSectionVirtual(SectionPimpl); } -inline bool SectionRef::isZeroInit() const { - return OwningObject->isSectionZeroInit(SectionPimpl); -} - -inline bool SectionRef::isReadOnlyData() const { - return OwningObject->isSectionReadOnlyData(SectionPimpl); -} - inline bool SectionRef::containsSymbol(SymbolRef S) const { return OwningObject->sectionContainsSymbol(SectionPimpl, S.getRawDataRefImpl()); @@ -454,6 +437,10 @@ inline DataRefImpl SectionRef::getRawDataRefImpl() const { return SectionPimpl; } +inline const ObjectFile *SectionRef::getObject() const { + return OwningObject; +} + /// RelocationRef inline RelocationRef::RelocationRef(DataRefImpl RelocationP, const ObjectFile *Owner) diff --git a/include/llvm/Object/SymbolicFile.h b/include/llvm/Object/SymbolicFile.h index 435799a..f7b7cb4 100644 --- a/include/llvm/Object/SymbolicFile.h +++ b/include/llvm/Object/SymbolicFile.h @@ -87,9 +87,10 @@ public: SF_Absolute = 1U << 3, // Absolute symbol SF_Common = 1U << 4, // Symbol has common linkage SF_Indirect = 1U << 5, // Symbol is an alias to another symbol - SF_FormatSpecific = 1U << 6, // Specific to the object file format + SF_Exported = 1U << 6, // Symbol is visible to other DSOs + SF_FormatSpecific = 1U << 7, // Specific to the object file format // (e.g. section symbols) - SF_Thumb = 1U << 7 // Thumb symbol in a 32-bit ARM binary + SF_Thumb = 1U << 8, // Thumb symbol in a 32-bit ARM binary }; BasicSymbolRef() : OwningObject(nullptr) { } diff --git a/include/llvm/Option/Arg.h b/include/llvm/Option/Arg.h index dcaa540..9459a3d 100644 --- a/include/llvm/Option/Arg.h +++ b/include/llvm/Option/Arg.h @@ -29,8 +29,8 @@ class ArgList; /// The Arg class encodes just enough information to be able to /// derive the argument values efficiently. class Arg { - Arg(const Arg &) LLVM_DELETED_FUNCTION; - void operator=(const Arg &) LLVM_DELETED_FUNCTION; + Arg(const Arg &) = delete; + void operator=(const Arg &) = delete; private: /// \brief The option this argument is an instance of. diff --git a/include/llvm/Option/ArgList.h b/include/llvm/Option/ArgList.h index 3f8547e..f5ded94 100644 --- a/include/llvm/Option/ArgList.h +++ b/include/llvm/Option/ArgList.h @@ -91,8 +91,8 @@ public: /// and to iterate over groups of arguments. class ArgList { private: - ArgList(const ArgList &) LLVM_DELETED_FUNCTION; - void operator=(const ArgList &) LLVM_DELETED_FUNCTION; + ArgList(const ArgList &) = delete; + void operator=(const ArgList &) = delete; public: typedef SmallVector arglist_type; diff --git a/include/llvm/Option/OptSpecifier.h b/include/llvm/Option/OptSpecifier.h index b7caa6e..7206bf2 100644 --- a/include/llvm/Option/OptSpecifier.h +++ b/include/llvm/Option/OptSpecifier.h @@ -21,7 +21,7 @@ namespace opt { unsigned ID; private: - explicit OptSpecifier(bool) LLVM_DELETED_FUNCTION; + explicit OptSpecifier(bool) = delete; public: OptSpecifier() : ID(0) {} diff --git a/include/llvm/Pass.h b/include/llvm/Pass.h index c2b9f95..6e92d96 100644 --- a/include/llvm/Pass.h +++ b/include/llvm/Pass.h @@ -83,8 +83,8 @@ class Pass { AnalysisResolver *Resolver; // Used to resolve analysis const void *PassID; PassKind Kind; - void operator=(const Pass&) LLVM_DELETED_FUNCTION; - Pass(const Pass &) LLVM_DELETED_FUNCTION; + void operator=(const Pass&) = delete; + Pass(const Pass &) = delete; public: explicit Pass(PassKind K, char &pid) diff --git a/include/llvm/PassAnalysisSupport.h b/include/llvm/PassAnalysisSupport.h index 9164305..38adb2d 100644 --- a/include/llvm/PassAnalysisSupport.h +++ b/include/llvm/PassAnalysisSupport.h @@ -120,7 +120,7 @@ public: class PMDataManager; class AnalysisResolver { private: - AnalysisResolver() LLVM_DELETED_FUNCTION; + AnalysisResolver() = delete; public: explicit AnalysisResolver(PMDataManager &P) : PM(P) { } diff --git a/include/llvm/PassInfo.h b/include/llvm/PassInfo.h index d53daf1..d107618 100644 --- a/include/llvm/PassInfo.h +++ b/include/llvm/PassInfo.h @@ -138,8 +138,8 @@ public: } private: - void operator=(const PassInfo &) LLVM_DELETED_FUNCTION; - PassInfo(const PassInfo &) LLVM_DELETED_FUNCTION; + void operator=(const PassInfo &) = delete; + PassInfo(const PassInfo &) = delete; }; } diff --git a/include/llvm/PassManager.h b/include/llvm/PassManager.h deleted file mode 100644 index 2a191b3..0000000 --- a/include/llvm/PassManager.h +++ /dev/null @@ -1,39 +0,0 @@ -//===- llvm/PassManager.h - Container for Passes ----------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This is a legacy redirect header for the old PassManager. It is intended to -// be used by clients that have not been converted to be aware of the new pass -// management infrastructure being built for LLVM, which is every client -// initially. Eventually this header (and the legacy management layer) will go -// away, but we want to minimize changes to out-of-tree users of LLVM in the -// interim. -// -// Note that this header *must not* be included into the same file as the new -// pass management infrastructure is included. Things will break spectacularly. -// If you are starting that conversion, you should switch to explicitly -// including LegacyPassManager.h and using the legacy namespace. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_PASSMANAGER_H -#define LLVM_PASSMANAGER_H - -#include "llvm/IR/LegacyPassManager.h" - -namespace llvm { - -// Pull these into the llvm namespace so that existing code that expects it -// there can find it. -using legacy::PassManagerBase; -using legacy::PassManager; -using legacy::FunctionPassManager; - -} - -#endif diff --git a/include/llvm/ProfileData/CoverageMapping.h b/include/llvm/ProfileData/CoverageMapping.h index 38fc8ca..4d393b3 100644 --- a/include/llvm/ProfileData/CoverageMapping.h +++ b/include/llvm/ProfileData/CoverageMapping.h @@ -19,6 +19,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/Hashing.h" #include "llvm/ADT/iterator.h" +#include "llvm/Support/Debug.h" #include "llvm/Support/ErrorOr.h" #include "llvm/Support/raw_ostream.h" #include @@ -27,7 +28,7 @@ namespace llvm { class IndexedInstrProfReader; namespace coverage { -class ObjectFileCoverageMappingReader; +class CoverageMappingReader; class CoverageMapping; struct CounterExpressions; @@ -62,8 +63,12 @@ public: unsigned getExpressionID() const { return ID; } - bool operator==(const Counter &Other) const { - return Kind == Other.Kind && ID == Other.ID; + friend bool operator==(const Counter &LHS, const Counter &RHS) { + return LHS.Kind == RHS.Kind && LHS.ID == RHS.ID; + } + + friend bool operator!=(const Counter &LHS, const Counter &RHS) { + return !(LHS == RHS); } friend bool operator<(const Counter &LHS, const Counter &RHS) { @@ -153,24 +158,40 @@ struct CounterMappingRegion { SkippedRegion }; - static const unsigned EncodingHasCodeBeforeBits = 1; - Counter Count; unsigned FileID, ExpandedFileID; unsigned LineStart, ColumnStart, LineEnd, ColumnEnd; RegionKind Kind; - /// \brief A flag that is set to true when there is already code before - /// this region on the same line. - /// This is useful to accurately compute the execution counts for a line. - bool HasCodeBefore; - - CounterMappingRegion(Counter Count, unsigned FileID, unsigned LineStart, - unsigned ColumnStart, unsigned LineEnd, - unsigned ColumnEnd, bool HasCodeBefore = false, - RegionKind Kind = CodeRegion) - : Count(Count), FileID(FileID), ExpandedFileID(0), LineStart(LineStart), - ColumnStart(ColumnStart), LineEnd(LineEnd), ColumnEnd(ColumnEnd), - Kind(Kind), HasCodeBefore(HasCodeBefore) {} + + CounterMappingRegion(Counter Count, unsigned FileID, unsigned ExpandedFileID, + unsigned LineStart, unsigned ColumnStart, + unsigned LineEnd, unsigned ColumnEnd, RegionKind Kind) + : Count(Count), FileID(FileID), ExpandedFileID(ExpandedFileID), + LineStart(LineStart), ColumnStart(ColumnStart), LineEnd(LineEnd), + ColumnEnd(ColumnEnd), Kind(Kind) {} + + static CounterMappingRegion + makeRegion(Counter Count, unsigned FileID, unsigned LineStart, + unsigned ColumnStart, unsigned LineEnd, unsigned ColumnEnd) { + return CounterMappingRegion(Count, FileID, 0, LineStart, ColumnStart, + LineEnd, ColumnEnd, CodeRegion); + } + + static CounterMappingRegion + makeExpansion(unsigned FileID, unsigned ExpandedFileID, unsigned LineStart, + unsigned ColumnStart, unsigned LineEnd, unsigned ColumnEnd) { + return CounterMappingRegion(Counter(), FileID, ExpandedFileID, LineStart, + ColumnStart, LineEnd, ColumnEnd, + ExpansionRegion); + } + + static CounterMappingRegion + makeSkipped(unsigned FileID, unsigned LineStart, unsigned ColumnStart, + unsigned LineEnd, unsigned ColumnEnd) { + return CounterMappingRegion(Counter(), FileID, 0, LineStart, ColumnStart, + LineEnd, ColumnEnd, SkippedRegion); + } + inline std::pair startLoc() const { return std::pair(LineStart, ColumnStart); @@ -216,8 +237,10 @@ public: ArrayRef CounterValues = ArrayRef()) : Expressions(Expressions), CounterValues(CounterValues) {} + void setCounts(ArrayRef Counts) { CounterValues = Counts; } + void dump(const Counter &C, llvm::raw_ostream &OS) const; - void dump(const Counter &C) const { dump(C, llvm::outs()); } + void dump(const Counter &C) const { dump(C, dbgs()); } /// \brief Return the number of times that a region of code associated with /// this counter was executed. @@ -235,10 +258,14 @@ struct FunctionRecord { /// \brief The number of times this function was executed. uint64_t ExecutionCount; - FunctionRecord(StringRef Name, ArrayRef Filenames, - uint64_t ExecutionCount) - : Name(Name), Filenames(Filenames.begin(), Filenames.end()), - ExecutionCount(ExecutionCount) {} + FunctionRecord(StringRef Name, ArrayRef Filenames) + : Name(Name), Filenames(Filenames.begin(), Filenames.end()) {} + + void pushRegion(CounterMappingRegion Region, uint64_t Count) { + if (CountedRegions.empty()) + ExecutionCount = Count; + CountedRegions.emplace_back(Region, Count); + } }; /// \brief Iterator over Functions, optionally filtered to a single file. @@ -312,10 +339,22 @@ struct CoverageSegment { CoverageSegment(unsigned Line, unsigned Col, bool IsRegionEntry) : Line(Line), Col(Col), Count(0), HasCount(false), IsRegionEntry(IsRegionEntry) {} + + CoverageSegment(unsigned Line, unsigned Col, uint64_t Count, + bool IsRegionEntry) + : Line(Line), Col(Col), Count(Count), HasCount(true), + IsRegionEntry(IsRegionEntry) {} + + friend bool operator==(const CoverageSegment &L, const CoverageSegment &R) { + return std::tie(L.Line, L.Col, L.Count, L.HasCount, L.IsRegionEntry) == + std::tie(R.Line, R.Col, R.Count, R.HasCount, R.IsRegionEntry); + } + void setCount(uint64_t NewCount) { Count = NewCount; HasCount = true; } + void addCount(uint64_t NewCount) { setCount(Count + NewCount); } }; @@ -363,7 +402,7 @@ class CoverageMapping { public: /// \brief Load the coverage mapping using the given readers. static ErrorOr> - load(ObjectFileCoverageMappingReader &CoverageReader, + load(CoverageMappingReader &CoverageReader, IndexedInstrProfReader &ProfileReader); /// \brief Load the coverage mapping from the given files. diff --git a/include/llvm/ProfileData/CoverageMappingReader.h b/include/llvm/ProfileData/CoverageMappingReader.h index 73b0248..6714366 100644 --- a/include/llvm/ProfileData/CoverageMappingReader.h +++ b/include/llvm/ProfileData/CoverageMappingReader.h @@ -15,20 +15,19 @@ #ifndef LLVM_PROFILEDATA_COVERAGEMAPPINGREADER_H #define LLVM_PROFILEDATA_COVERAGEMAPPINGREADER_H -#include "llvm/ProfileData/InstrProf.h" -#include "llvm/ProfileData/CoverageMapping.h" -#include "llvm/Object/ObjectFile.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" -#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm/ProfileData/CoverageMapping.h" +#include "llvm/ProfileData/InstrProf.h" #include "llvm/Support/FileSystem.h" - +#include "llvm/Support/MemoryBuffer.h" #include namespace llvm { namespace coverage { -class ObjectFileCoverageMappingReader; +class CoverageMappingReader; /// \brief Coverage mapping information for a single function. struct CoverageMappingRecord { @@ -42,15 +41,14 @@ struct CoverageMappingRecord { /// \brief A file format agnostic iterator over coverage mapping data. class CoverageMappingIterator : public std::iterator { - ObjectFileCoverageMappingReader *Reader; + CoverageMappingReader *Reader; CoverageMappingRecord Record; void increment(); public: CoverageMappingIterator() : Reader(nullptr) {} - CoverageMappingIterator(ObjectFileCoverageMappingReader *Reader) - : Reader(Reader) { + CoverageMappingIterator(CoverageMappingReader *Reader) : Reader(Reader) { increment(); } @@ -68,6 +66,14 @@ public: CoverageMappingRecord *operator->() { return &Record; } }; +class CoverageMappingReader { +public: + virtual std::error_code readNextRecord(CoverageMappingRecord &Record) = 0; + CoverageMappingIterator begin() { return CoverageMappingIterator(this); } + CoverageMappingIterator end() { return CoverageMappingIterator(); } + virtual ~CoverageMappingReader() {} +}; + /// \brief Base class for the raw coverage mapping and filenames data readers. class RawCoverageReader { protected: @@ -91,10 +97,9 @@ protected: class RawCoverageFilenamesReader : public RawCoverageReader { std::vector &Filenames; - RawCoverageFilenamesReader(const RawCoverageFilenamesReader &) - LLVM_DELETED_FUNCTION; + RawCoverageFilenamesReader(const RawCoverageFilenamesReader &) = delete; RawCoverageFilenamesReader & - operator=(const RawCoverageFilenamesReader &) LLVM_DELETED_FUNCTION; + operator=(const RawCoverageFilenamesReader &) = delete; public: RawCoverageFilenamesReader(StringRef Data, std::vector &Filenames) @@ -105,29 +110,27 @@ public: /// \brief Reader for the raw coverage mapping data. class RawCoverageMappingReader : public RawCoverageReader { - StringRef FunctionName; ArrayRef TranslationUnitFilenames; std::vector &Filenames; std::vector &Expressions; std::vector &MappingRegions; - RawCoverageMappingReader(const RawCoverageMappingReader &) - LLVM_DELETED_FUNCTION; + RawCoverageMappingReader(const RawCoverageMappingReader &) = delete; RawCoverageMappingReader & - operator=(const RawCoverageMappingReader &) LLVM_DELETED_FUNCTION; + operator=(const RawCoverageMappingReader &) = delete; public: - RawCoverageMappingReader(StringRef FunctionName, StringRef MappingData, + RawCoverageMappingReader(StringRef MappingData, ArrayRef TranslationUnitFilenames, std::vector &Filenames, std::vector &Expressions, std::vector &MappingRegions) - : RawCoverageReader(MappingData), FunctionName(FunctionName), + : RawCoverageReader(MappingData), TranslationUnitFilenames(TranslationUnitFilenames), Filenames(Filenames), Expressions(Expressions), MappingRegions(MappingRegions) {} - std::error_code read(CoverageMappingRecord &Record); + std::error_code read(); private: std::error_code decodeCounter(unsigned Value, Counter &C); @@ -139,7 +142,7 @@ private: /// \brief Reader for the coverage mapping data that is emitted by the /// frontend and stored in an object file. -class ObjectFileCoverageMappingReader { +class BinaryCoverageReader : public CoverageMappingReader { public: struct ProfileMappingRecord { CoverageMappingVersion Version; @@ -158,8 +161,6 @@ public: }; private: - std::error_code LastError; - object::OwningBinary Object; std::vector Filenames; std::vector MappingRecords; size_t CurrentRecord; @@ -167,40 +168,16 @@ private: std::vector Expressions; std::vector MappingRegions; - ObjectFileCoverageMappingReader(const ObjectFileCoverageMappingReader &) - LLVM_DELETED_FUNCTION; - ObjectFileCoverageMappingReader & - operator=(const ObjectFileCoverageMappingReader &) LLVM_DELETED_FUNCTION; - - /// \brief Set the current error_code and return same. - std::error_code error(std::error_code EC) { - LastError = EC; - return EC; - } + BinaryCoverageReader(const BinaryCoverageReader &) = delete; + BinaryCoverageReader &operator=(const BinaryCoverageReader &) = delete; - /// \brief Clear the current error code and return a successful one. - std::error_code success() { return error(instrprof_error::success); } + BinaryCoverageReader() : CurrentRecord(0) {} public: - ObjectFileCoverageMappingReader(StringRef FileName); - ObjectFileCoverageMappingReader( - std::unique_ptr &ObjectBuffer, - sys::fs::file_magic Type = sys::fs::file_magic::unknown); - - std::error_code readHeader(); - std::error_code readNextRecord(CoverageMappingRecord &Record); - - /// Iterator over profile data. - CoverageMappingIterator begin() { return CoverageMappingIterator(this); } - CoverageMappingIterator end() { return CoverageMappingIterator(); } + static ErrorOr> + create(std::unique_ptr &ObjectBuffer); - /// \brief Return true if the reader has finished reading the profile data. - bool isEOF() { return LastError == instrprof_error::eof; } - /// \brief Return true if the reader encountered an error reading profiling - /// data. - bool hasError() { return LastError && !isEOF(); } - /// \brief Get the current error code. - std::error_code getError() { return LastError; } + std::error_code readNextRecord(CoverageMappingRecord &Record) override; }; } // end namespace coverage diff --git a/include/llvm/ProfileData/CoverageMappingWriter.h b/include/llvm/ProfileData/CoverageMappingWriter.h index cf16140..2e3b037 100644 --- a/include/llvm/ProfileData/CoverageMappingWriter.h +++ b/include/llvm/ProfileData/CoverageMappingWriter.h @@ -15,9 +15,9 @@ #ifndef LLVM_PROFILEDATA_COVERAGEMAPPINGWRITER_H #define LLVM_PROFILEDATA_COVERAGEMAPPINGWRITER_H -#include "llvm/ProfileData/CoverageMapping.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringMap.h" +#include "llvm/ProfileData/CoverageMapping.h" #include "llvm/Support/raw_ostream.h" namespace llvm { diff --git a/include/llvm/ProfileData/InstrProfReader.h b/include/llvm/ProfileData/InstrProfReader.h index 38c5310..63a6ac6 100644 --- a/include/llvm/ProfileData/InstrProfReader.h +++ b/include/llvm/ProfileData/InstrProfReader.h @@ -18,12 +18,11 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ProfileData/InstrProf.h" +#include "llvm/Support/EndianStream.h" #include "llvm/Support/ErrorOr.h" #include "llvm/Support/LineIterator.h" #include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/EndianStream.h" #include "llvm/Support/OnDiskHashTable.h" - #include namespace llvm { @@ -96,6 +95,9 @@ public: /// Factory method to create an appropriately typed reader for the given /// instrprof file. static ErrorOr> create(std::string Path); + + static ErrorOr> + create(std::unique_ptr Buffer); }; /// Reader for the simple text based instrprof format. @@ -115,9 +117,8 @@ private: /// The current set of counter values. std::vector Counts; - TextInstrProfReader(const TextInstrProfReader &) LLVM_DELETED_FUNCTION; - TextInstrProfReader &operator=(const TextInstrProfReader &) - LLVM_DELETED_FUNCTION; + TextInstrProfReader(const TextInstrProfReader &) = delete; + TextInstrProfReader &operator=(const TextInstrProfReader &) = delete; public: TextInstrProfReader(std::unique_ptr DataBuffer_) : DataBuffer(std::move(DataBuffer_)), Line(*DataBuffer, true, '#') {} @@ -168,9 +169,8 @@ private: const char *NamesStart; const char *ProfileEnd; - RawInstrProfReader(const RawInstrProfReader &) LLVM_DELETED_FUNCTION; - RawInstrProfReader &operator=(const RawInstrProfReader &) - LLVM_DELETED_FUNCTION; + RawInstrProfReader(const RawInstrProfReader &) = delete; + RawInstrProfReader &operator=(const RawInstrProfReader &) = delete; public: RawInstrProfReader(std::unique_ptr DataBuffer) : DataBuffer(std::move(DataBuffer)) { } @@ -274,9 +274,8 @@ private: /// The maximal execution count among all functions. uint64_t MaxFunctionCount; - IndexedInstrProfReader(const IndexedInstrProfReader &) LLVM_DELETED_FUNCTION; - IndexedInstrProfReader &operator=(const IndexedInstrProfReader &) - LLVM_DELETED_FUNCTION; + IndexedInstrProfReader(const IndexedInstrProfReader &) = delete; + IndexedInstrProfReader &operator=(const IndexedInstrProfReader &) = delete; public: IndexedInstrProfReader(std::unique_ptr DataBuffer) : DataBuffer(std::move(DataBuffer)), Index(nullptr), CurrentOffset(0) {} @@ -296,8 +295,11 @@ public: uint64_t getMaximumFunctionCount() { return MaxFunctionCount; } /// Factory method to create an indexed reader. - static std::error_code - create(std::string Path, std::unique_ptr &Result); + static ErrorOr> + create(std::string Path); + + static ErrorOr> + create(std::unique_ptr Buffer); }; } // end namespace llvm diff --git a/include/llvm/ProfileData/InstrProfWriter.h b/include/llvm/ProfileData/InstrProfWriter.h index e76f668..ce0bb52 100644 --- a/include/llvm/ProfileData/InstrProfWriter.h +++ b/include/llvm/ProfileData/InstrProfWriter.h @@ -20,8 +20,8 @@ #include "llvm/ADT/StringMap.h" #include "llvm/ProfileData/InstrProf.h" #include "llvm/Support/DataTypes.h" +#include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/raw_ostream.h" - #include namespace llvm { @@ -42,8 +42,13 @@ public: std::error_code addFunctionCounts(StringRef FunctionName, uint64_t FunctionHash, ArrayRef Counters); - /// Ensure that all data is written to disk. + /// Write the profile to \c OS void write(raw_fd_ostream &OS); + /// Write the profile, returning the raw data. For testing. + std::unique_ptr writeBuffer(); + +private: + std::pair writeImpl(raw_ostream &OS); }; } // end namespace llvm diff --git a/include/llvm/ProfileData/SampleProf.h b/include/llvm/ProfileData/SampleProf.h index 5c70b31..df0a055 100644 --- a/include/llvm/ProfileData/SampleProf.h +++ b/include/llvm/ProfileData/SampleProf.h @@ -19,7 +19,6 @@ #include "llvm/ADT/StringMap.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" - #include namespace llvm { diff --git a/include/llvm/ProfileData/SampleProfReader.h b/include/llvm/ProfileData/SampleProfReader.h index c20b815..c082a1a 100644 --- a/include/llvm/ProfileData/SampleProfReader.h +++ b/include/llvm/ProfileData/SampleProfReader.h @@ -14,12 +14,12 @@ #define LLVM_PROFILEDATA_SAMPLEPROFREADER_H #include "llvm/ADT/DenseMap.h" -#include "llvm/IR/DiagnosticInfo.h" -#include "llvm/IR/Function.h" -#include "llvm/IR/LLVMContext.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" +#include "llvm/IR/DiagnosticInfo.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/LLVMContext.h" #include "llvm/ProfileData/SampleProf.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" diff --git a/include/llvm/Support/ARMBuildAttributes.h b/include/llvm/Support/ARMBuildAttributes.h index 07340de..96a8219 100644 --- a/include/llvm/Support/ARMBuildAttributes.h +++ b/include/llvm/Support/ARMBuildAttributes.h @@ -171,6 +171,8 @@ enum { WCharWidth4Bytes = 4, // sizeof(wchar_t) == 4 // Tag_ABI_FP_denormal, (=20), uleb128 + PositiveZero = 0, + IEEEDenormals = 1, PreserveFPSign = 2, // sign when flushed-to-zero is preserved // Tag_ABI_FP_number_model, (=23), uleb128 @@ -198,6 +200,9 @@ enum { // Tag_FP_HP_extension, (=36), uleb128 AllowHPFP = 1, // Allow use of Half Precision FP + // Tag_FP_16bit_format, (=38), uleb128 + FP16FormatIEEE = 1, + // Tag_MPextension_use, (=42), uleb128 AllowMP = 1, // Allow use of MP extensions diff --git a/include/llvm/Support/COFF.h b/include/llvm/Support/COFF.h index 150bce5..7f54822 100644 --- a/include/llvm/Support/COFF.h +++ b/include/llvm/Support/COFF.h @@ -664,16 +664,16 @@ namespace COFF { } }; - enum CodeViewLineTableIdentifiers { - DEBUG_SECTION_MAGIC = 0x4, - DEBUG_SYMBOL_SUBSECTION = 0xF1, - DEBUG_LINE_TABLE_SUBSECTION = 0xF2, + enum CodeViewIdentifiers { + DEBUG_SECTION_MAGIC = 0x4, + DEBUG_SYMBOL_SUBSECTION = 0xF1, + DEBUG_LINE_TABLE_SUBSECTION = 0xF2, DEBUG_STRING_TABLE_SUBSECTION = 0xF3, - DEBUG_INDEX_SUBSECTION = 0xF4, + DEBUG_INDEX_SUBSECTION = 0xF4, // Symbol subsections are split into records of different types. DEBUG_SYMBOL_TYPE_PROC_START = 0x1147, - DEBUG_SYMBOL_TYPE_PROC_END = 0x114F + DEBUG_SYMBOL_TYPE_PROC_END = 0x114F }; inline bool isReservedSectionNumber(int32_t SectionNumber) { diff --git a/include/llvm/Support/Casting.h b/include/llvm/Support/Casting.h index beed31a..6ba5efa 100644 --- a/include/llvm/Support/Casting.h +++ b/include/llvm/Support/Casting.h @@ -243,6 +243,26 @@ inline typename cast_retty::ret_type cast(Y *Val) { // accepted. // template +LLVM_ATTRIBUTE_UNUSED_RESULT inline typename std::enable_if< + !is_simple_type::value, typename cast_retty::ret_type>::type +cast_or_null(const Y &Val) { + if (!Val) + return nullptr; + assert(isa(Val) && "cast_or_null() argument of incompatible type!"); + return cast(Val); +} + +template +LLVM_ATTRIBUTE_UNUSED_RESULT inline typename std::enable_if< + !is_simple_type::value, typename cast_retty::ret_type>::type +cast_or_null(Y &Val) { + if (!Val) + return nullptr; + assert(isa(Val) && "cast_or_null() argument of incompatible type!"); + return cast(Val); +} + +template LLVM_ATTRIBUTE_UNUSED_RESULT inline typename cast_retty::ret_type cast_or_null(Y *Val) { if (!Val) return nullptr; @@ -282,6 +302,20 @@ dyn_cast(Y *Val) { // value is accepted. // template +LLVM_ATTRIBUTE_UNUSED_RESULT inline typename std::enable_if< + !is_simple_type::value, typename cast_retty::ret_type>::type +dyn_cast_or_null(const Y &Val) { + return (Val && isa(Val)) ? cast(Val) : nullptr; +} + +template +LLVM_ATTRIBUTE_UNUSED_RESULT inline typename std::enable_if< + !is_simple_type::value, typename cast_retty::ret_type>::type +dyn_cast_or_null(Y &Val) { + return (Val && isa(Val)) ? cast(Val) : nullptr; +} + +template LLVM_ATTRIBUTE_UNUSED_RESULT inline typename cast_retty::ret_type dyn_cast_or_null(Y *Val) { return (Val && isa(Val)) ? cast(Val) : nullptr; diff --git a/include/llvm/Support/CommandLine.h b/include/llvm/Support/CommandLine.h index 2b5c9c5..64c5d96 100644 --- a/include/llvm/Support/CommandLine.h +++ b/include/llvm/Support/CommandLine.h @@ -20,6 +20,7 @@ #ifndef LLVM_SUPPORT_COMMANDLINE_H #define LLVM_SUPPORT_COMMANDLINE_H +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/Twine.h" @@ -40,7 +41,7 @@ namespace cl { //===----------------------------------------------------------------------===// // ParseCommandLineOptions - Command line option processing entry point. // -void ParseCommandLineOptions(int argc, const char * const *argv, +void ParseCommandLineOptions(int argc, const char *const *argv, const char *Overview = nullptr); //===----------------------------------------------------------------------===// @@ -66,25 +67,33 @@ void SetVersionPrinter(void (*func)()); /// information specific to the tool. void AddExtraVersionPrinter(void (*func)()); - // PrintOptionValues - Print option values. // With -print-options print the difference between option values and defaults. // With -print-all-options print all option values. // (Currently not perfect, but best-effort.) void PrintOptionValues(); -// MarkOptionsChanged - Internal helper function. -void MarkOptionsChanged(); +// Forward declaration - AddLiteralOption needs to be up here to make gcc happy. +class Option; + +/// \brief Adds a new option for parsing and provides the option it refers to. +/// +/// \param O pointer to the option +/// \param Name the string name for the option to handle during parsing +/// +/// Literal options are used by some parsers to register special option values. +/// This is how the PassNameParser registers pass names for opt. +void AddLiteralOption(Option &O, const char *Name); //===----------------------------------------------------------------------===// // Flags permitted to be passed to command line arguments // -enum NumOccurrencesFlag { // Flags for the number of occurrences allowed - Optional = 0x00, // Zero or One occurrence - ZeroOrMore = 0x01, // Zero or more occurrences allowed - Required = 0x02, // One occurrence required - OneOrMore = 0x03, // One or more occurrences required +enum NumOccurrencesFlag { // Flags for the number of occurrences allowed + Optional = 0x00, // Zero or One occurrence + ZeroOrMore = 0x01, // Zero or more occurrences allowed + Required = 0x02, // One occurrence required + OneOrMore = 0x03, // One or more occurrences required // ConsumeAfter - Indicates that this option is fed anything that follows the // last positional argument required by the application (it is an error if @@ -93,20 +102,20 @@ enum NumOccurrencesFlag { // Flags for the number of occurrences allowed // found. Once a filename is found, all of the succeeding arguments are // passed, unprocessed, to the ConsumeAfter option. // - ConsumeAfter = 0x04 + ConsumeAfter = 0x04 }; -enum ValueExpected { // Is a value required for the option? +enum ValueExpected { // Is a value required for the option? // zero reserved for the unspecified value - ValueOptional = 0x01, // The value can appear... or not - ValueRequired = 0x02, // The value is required to appear! - ValueDisallowed = 0x03 // A value may not be specified (for flags) + ValueOptional = 0x01, // The value can appear... or not + ValueRequired = 0x02, // The value is required to appear! + ValueDisallowed = 0x03 // A value may not be specified (for flags) }; -enum OptionHidden { // Control whether -help shows this option - NotHidden = 0x00, // Option included in -help & -help-hidden - Hidden = 0x01, // -help doesn't, but -help-hidden does - ReallyHidden = 0x02 // Neither -help nor -help-hidden show this arg +enum OptionHidden { // Control whether -help shows this option + NotHidden = 0x00, // Option included in -help & -help-hidden + Hidden = 0x01, // -help doesn't, but -help-hidden does + ReallyHidden = 0x02 // Neither -help nor -help-hidden show this arg }; // Formatting flags - This controls special features that the option might have @@ -125,16 +134,16 @@ enum OptionHidden { // Control whether -help shows this option // enum FormattingFlags { - NormalFormatting = 0x00, // Nothing special - Positional = 0x01, // Is a positional argument, no '-' required - Prefix = 0x02, // Can this option directly prefix its value? - Grouping = 0x03 // Can this option group with other options? + NormalFormatting = 0x00, // Nothing special + Positional = 0x01, // Is a positional argument, no '-' required + Prefix = 0x02, // Can this option directly prefix its value? + Grouping = 0x03 // Can this option group with other options? }; -enum MiscFlags { // Miscellaneous flags to adjust argument - CommaSeparated = 0x01, // Should this cl::list split between commas? - PositionalEatsArgs = 0x02, // Should this positional cl::list eat -args? - Sink = 0x04 // Should this cl::list eat all unknown options? +enum MiscFlags { // Miscellaneous flags to adjust argument + CommaSeparated = 0x01, // Should this cl::list split between commas? + PositionalEatsArgs = 0x02, // Should this positional cl::list eat -args? + Sink = 0x04 // Should this cl::list eat all unknown options? }; //===----------------------------------------------------------------------===// @@ -145,9 +154,13 @@ private: const char *const Name; const char *const Description; void registerCategory(); + public: - OptionCategory(const char *const Name, const char *const Description = nullptr) - : Name(Name), Description(Description) { registerCategory(); } + OptionCategory(const char *const Name, + const char *const Description = nullptr) + : Name(Name), Description(Description) { + registerCategory(); + } const char *getName() const { return Name; } const char *getDescription() const { return Description; } }; @@ -176,7 +189,7 @@ class Option { // Out of line virtual function to provide home for the class. virtual void anchor(); - int NumOccurrences; // The number of times specified + int NumOccurrences; // The number of times specified // Occurrences, HiddenFlag, and Formatting are all enum types but to avoid // problems with signed enums in bitfields. unsigned Occurrences : 3; // enum NumOccurrencesFlag @@ -186,22 +199,21 @@ class Option { unsigned HiddenFlag : 2; // enum OptionHidden unsigned Formatting : 2; // enum FormattingFlags unsigned Misc : 3; - unsigned Position; // Position of last occurrence of the option - unsigned AdditionalVals;// Greater than 0 for multi-valued option. - Option *NextRegistered; // Singly linked list of registered options. + unsigned Position; // Position of last occurrence of the option + unsigned AdditionalVals; // Greater than 0 for multi-valued option. public: const char *ArgStr; // The argument string itself (ex: "help", "o") const char *HelpStr; // The descriptive text message for -help const char *ValueStr; // String describing what the value of this option is OptionCategory *Category; // The Category this option belongs to + bool FullyInitialized; // Has addArguemnt been called? inline enum NumOccurrencesFlag getNumOccurrencesFlag() const { return (enum NumOccurrencesFlag)Occurrences; } inline enum ValueExpected getValueExpectedFlag() const { - return Value ? ((enum ValueExpected)Value) - : getValueExpectedFlagDefault(); + return Value ? ((enum ValueExpected)Value) : getValueExpectedFlagDefault(); } inline enum OptionHidden getOptionHiddenFlag() const { return (enum OptionHidden)HiddenFlag; @@ -209,9 +221,7 @@ public: inline enum FormattingFlags getFormattingFlag() const { return (enum FormattingFlags)Formatting; } - inline unsigned getMiscFlags() const { - return Misc; - } + inline unsigned getMiscFlags() const { return Misc; } inline unsigned getPosition() const { return Position; } inline unsigned getNumAdditionalVals() const { return AdditionalVals; } @@ -221,28 +231,27 @@ public: //-------------------------------------------------------------------------=== // Accessor functions set by OptionModifiers // - void setArgStr(const char *S) { ArgStr = S; } + void setArgStr(const char *S); void setDescription(const char *S) { HelpStr = S; } void setValueStr(const char *S) { ValueStr = S; } - void setNumOccurrencesFlag(enum NumOccurrencesFlag Val) { - Occurrences = Val; - } + void setNumOccurrencesFlag(enum NumOccurrencesFlag Val) { Occurrences = Val; } void setValueExpectedFlag(enum ValueExpected Val) { Value = Val; } void setHiddenFlag(enum OptionHidden Val) { HiddenFlag = Val; } void setFormattingFlag(enum FormattingFlags V) { Formatting = V; } void setMiscFlag(enum MiscFlags M) { Misc |= M; } void setPosition(unsigned pos) { Position = pos; } void setCategory(OptionCategory &C) { Category = &C; } + protected: explicit Option(enum NumOccurrencesFlag OccurrencesFlag, enum OptionHidden Hidden) - : NumOccurrences(0), Occurrences(OccurrencesFlag), Value(0), - HiddenFlag(Hidden), Formatting(NormalFormatting), Misc(0), - Position(0), AdditionalVals(0), NextRegistered(nullptr), - ArgStr(""), HelpStr(""), ValueStr(""), Category(&GeneralCategory) { - } + : NumOccurrences(0), Occurrences(OccurrencesFlag), Value(0), + HiddenFlag(Hidden), Formatting(NormalFormatting), Misc(0), Position(0), + AdditionalVals(0), ArgStr(""), HelpStr(""), ValueStr(""), + Category(&GeneralCategory), FullyInitialized(false) {} inline void setNumAdditionalVals(unsigned n) { AdditionalVals = n; } + public: // addArgument - Register this argument with the commandline system. // @@ -254,8 +263,6 @@ public: /// For testing purposes only. void removeArgument(); - Option *getNextRegisteredOption() const { return NextRegistered; } - // Return the width of the option tag for printing... virtual size_t getOptionWidth() const = 0; @@ -266,12 +273,12 @@ public: virtual void printOptionValue(size_t GlobalWidth, bool Force) const = 0; - virtual void getExtraOptionNames(SmallVectorImpl &) {} + virtual void getExtraOptionNames(SmallVectorImpl &) {} // addOccurrence - Wrapper around handleOccurrence that enforces Flags. // - virtual bool addOccurrence(unsigned pos, StringRef ArgName, - StringRef Value, bool MultiArg = false); + virtual bool addOccurrence(unsigned pos, StringRef ArgName, StringRef Value, + bool MultiArg = false); // Prints option name followed by message. Always returns true. bool error(const Twine &Message, StringRef ArgName = StringRef()); @@ -281,7 +288,6 @@ public: virtual ~Option() {} }; - //===----------------------------------------------------------------------===// // Command line option modifiers that can be used to modify the behavior of // command line option parsers... @@ -306,36 +312,31 @@ struct value_desc { // the default constructor for the argument type does not give you what you // want. This is only valid on "opt" arguments, not on "list" arguments. // -template -struct initializer { +template struct initializer { const Ty &Init; initializer(const Ty &Val) : Init(Val) {} - template - void apply(Opt &O) const { O.setInitialValue(Init); } + template void apply(Opt &O) const { O.setInitialValue(Init); } }; -template -initializer init(const Ty &Val) { +template initializer init(const Ty &Val) { return initializer(Val); } - // location - Allow the user to specify which external variable they want to // store the results of the command line argument processing into, if they don't // want to store it in the option itself. // -template -struct LocationClass { +template struct LocationClass { Ty &Loc; LocationClass(Ty &L) : Loc(L) {} - template - void apply(Opt &O) const { O.setLocation(O, Loc); } + template void apply(Opt &O) const { O.setLocation(O, Loc); } }; -template -LocationClass location(Ty &L) { return LocationClass(L); } +template LocationClass location(Ty &L) { + return LocationClass(L); +} // cat - Specifiy the Option category for the command line argument to belong // to. @@ -343,11 +344,9 @@ struct cat { OptionCategory &Category; cat(OptionCategory &c) : Category(c) {} - template - void apply(Opt &O) const { O.setCategory(Category); } + template void apply(Opt &O) const { O.setCategory(Category); } }; - //===----------------------------------------------------------------------===// // OptionValue class @@ -360,11 +359,11 @@ private: virtual void anchor(); }; -template struct OptionValue; +template struct OptionValue; // The default value safely does nothing. Option value printing is only // best-effort. -template +template struct OptionValueBase : public GenericOptionValue { // Temporary storage for argument passing. typedef OptionValue WrapperType; @@ -374,21 +373,20 @@ struct OptionValueBase : public GenericOptionValue { const DataType &getValue() const { llvm_unreachable("no default value"); } // Some options may take their value from a different data type. - template - void setValue(const DT& /*V*/) {} + template void setValue(const DT & /*V*/) {} - bool compare(const DataType &/*V*/) const { return false; } + bool compare(const DataType & /*V*/) const { return false; } - bool compare(const GenericOptionValue& /*V*/) const override { + bool compare(const GenericOptionValue & /*V*/) const override { return false; } }; // Simple copy of the option value. -template -class OptionValueCopy : public GenericOptionValue { +template class OptionValueCopy : public GenericOptionValue { DataType Value; bool Valid; + public: OptionValueCopy() : Valid(false) {} @@ -399,37 +397,36 @@ public: return Value; } - void setValue(const DataType &V) { Valid = true; Value = V; } - - bool compare(const DataType &V) const { - return Valid && (Value != V); + void setValue(const DataType &V) { + Valid = true; + Value = V; } + bool compare(const DataType &V) const { return Valid && (Value != V); } + bool compare(const GenericOptionValue &V) const override { const OptionValueCopy &VC = - static_cast< const OptionValueCopy& >(V); - if (!VC.hasValue()) return false; + static_cast &>(V); + if (!VC.hasValue()) + return false; return compare(VC.getValue()); } }; // Non-class option values. -template +template struct OptionValueBase : OptionValueCopy { typedef DataType WrapperType; }; // Top-level option class. -template +template struct OptionValue : OptionValueBase::value> { OptionValue() {} - OptionValue(const DataType& V) { - this->setValue(V); - } + OptionValue(const DataType &V) { this->setValue(V); } // Some options may take their value from a different data type. - template - OptionValue &operator=(const DT& V) { + template OptionValue &operator=(const DT &V) { this->setValue(V); return *this; } @@ -437,36 +434,33 @@ struct OptionValue : OptionValueBase::value> { // Other safe-to-copy-by-value common option types. enum boolOrDefault { BOU_UNSET, BOU_TRUE, BOU_FALSE }; -template<> +template <> struct OptionValue : OptionValueCopy { typedef cl::boolOrDefault WrapperType; OptionValue() {} - OptionValue(const cl::boolOrDefault& V) { - this->setValue(V); - } - OptionValue &operator=(const cl::boolOrDefault& V) { + OptionValue(const cl::boolOrDefault &V) { this->setValue(V); } + OptionValue &operator=(const cl::boolOrDefault &V) { setValue(V); return *this; } + private: void anchor() override; }; -template<> -struct OptionValue : OptionValueCopy { +template <> struct OptionValue : OptionValueCopy { typedef StringRef WrapperType; OptionValue() {} - OptionValue(const std::string& V) { - this->setValue(V); - } - OptionValue &operator=(const std::string& V) { + OptionValue(const std::string &V) { this->setValue(V); } + OptionValue &operator=(const std::string &V) { setValue(V); return *this; } + private: void anchor() override; }; @@ -476,20 +470,20 @@ private: // #define clEnumVal(ENUMVAL, DESC) #ENUMVAL, int(ENUMVAL), DESC #define clEnumValN(ENUMVAL, FLAGNAME, DESC) FLAGNAME, int(ENUMVAL), DESC -#define clEnumValEnd (reinterpret_cast(0)) +#define clEnumValEnd (reinterpret_cast(0)) // values - For custom data types, allow specifying a group of values together // as the values that go into the mapping that the option handler uses. Note // that the values list must always have a 0 at the end of the list to indicate // that the list has ended. // -template -class ValuesClass { +template class ValuesClass { // Use a vector instead of a map, because the lists should be short, // the overhead is less, and most importantly, it keeps them in the order // inserted so we can print our option out nicely. - SmallVector >,4> Values; + SmallVector>, 4> Values; void processValues(va_list Vals); + public: ValuesClass(const char *EnumName, DataType Val, const char *Desc, va_list ValueArgs) { @@ -500,13 +494,12 @@ public: while (const char *enumName = va_arg(ValueArgs, const char *)) { DataType EnumVal = static_cast(va_arg(ValueArgs, int)); const char *EnumDesc = va_arg(ValueArgs, const char *); - Values.push_back(std::make_pair(enumName, // Add value to value map + Values.push_back(std::make_pair(enumName, // Add value to value map std::make_pair(EnumVal, EnumDesc))); } } - template - void apply(Opt &O) const { + template void apply(Opt &O) const { for (size_t i = 0, e = Values.size(); i != e; ++i) O.getParser().addLiteralOption(Values[i].first, Values[i].second.first, Values[i].second.second); @@ -516,11 +509,11 @@ public: template ValuesClass LLVM_END_WITH_NULL values(const char *Arg, DataType Val, const char *Desc, ...) { - va_list ValueArgs; - va_start(ValueArgs, Desc); - ValuesClass Vals(Arg, Val, Desc, ValueArgs); - va_end(ValueArgs); - return Vals; + va_list ValueArgs; + va_start(ValueArgs, Desc); + ValuesClass Vals(Arg, Val, Desc, ValueArgs); + va_end(ValueArgs); + return Vals; } //===----------------------------------------------------------------------===// @@ -539,13 +532,16 @@ class generic_parser_base { protected: class GenericOptionInfo { public: - GenericOptionInfo(const char *name, const char *helpStr) : - Name(name), HelpStr(helpStr) {} + GenericOptionInfo(const char *name, const char *helpStr) + : Name(name), HelpStr(helpStr) {} const char *Name; const char *HelpStr; }; + public: - virtual ~generic_parser_base() {} // Base class should have virtual-dtor + generic_parser_base(Option &O) : Owner(O) {} + + virtual ~generic_parser_base() {} // Base class should have virtual-dtor // getNumOptions - Virtual function implemented by generic subclass to // indicate how many entries are in Values. @@ -576,30 +572,24 @@ public: // // Template definition ensures that the option and default have the same // DataType (via the same AnyOptionValue). - template + template void printOptionDiff(const Option &O, const AnyOptionValue &V, const AnyOptionValue &Default, size_t GlobalWidth) const { printGenericOptionDiff(O, V, Default, GlobalWidth); } - void initialize(Option &O) { - // All of the modifiers for the option have been processed by now, so the - // argstr field should be stable, copy it down now. - // - hasArgStr = O.hasArgStr(); - } + void initialize() {} - void getExtraOptionNames(SmallVectorImpl &OptionNames) { + void getExtraOptionNames(SmallVectorImpl &OptionNames) { // If there has been no argstr specified, that means that we need to add an // argument for every possible option. This ensures that our options are // vectored to us. - if (!hasArgStr) + if (!Owner.hasArgStr()) for (unsigned i = 0, e = getNumOptions(); i != e; ++i) OptionNames.push_back(getOption(i)); } - enum ValueExpected getValueExpectedFlagDefault() const { // If there is an ArgStr specified, then we are of the form: // @@ -612,7 +602,7 @@ public: // // If this is the case, we cannot allow a value. // - if (hasArgStr) + if (Owner.hasArgStr()) return ValueRequired; else return ValueDisallowed; @@ -624,7 +614,7 @@ public: unsigned findOption(const char *Name); protected: - bool hasArgStr; + Option &Owner; }; // Default parser implementation - This implementation depends on having a @@ -633,17 +623,18 @@ protected: // command line option for -help. Because this is a simple mapping parser, the // data type can be any unsupported type. // -template -class parser : public generic_parser_base { +template class parser : public generic_parser_base { protected: class OptionInfo : public GenericOptionInfo { public: - OptionInfo(const char *name, DataType v, const char *helpStr) : - GenericOptionInfo(name, helpStr), V(v) {} + OptionInfo(const char *name, DataType v, const char *helpStr) + : GenericOptionInfo(name, helpStr), V(v) {} OptionValue V; }; SmallVector Values; + public: + parser(Option &O) : generic_parser_base(O) {} typedef DataType parser_data_type; // Implement virtual functions needed by generic_parser_base @@ -661,7 +652,7 @@ public: // parse - Return true on error. bool parse(Option &O, StringRef ArgName, StringRef Arg, DataType &V) { StringRef ArgVal; - if (hasArgStr) + if (Owner.hasArgStr()) ArgVal = Arg; else ArgVal = ArgName; @@ -682,7 +673,7 @@ public: assert(findOption(Name) == Values.size() && "Option already exists!"); OptionInfo X(Name, static_cast(V), HelpStr); Values.push_back(X); - MarkOptionsChanged(); + AddLiteralOption(Owner, Name); } /// removeLiteralOption - Remove the specified option. @@ -690,24 +681,26 @@ public: void removeLiteralOption(const char *Name) { unsigned N = findOption(Name); assert(N != Values.size() && "Option not found!"); - Values.erase(Values.begin()+N); + Values.erase(Values.begin() + N); } }; //-------------------------------------------------- // basic_parser - Super class of parsers to provide boilerplate code // -class basic_parser_impl { // non-template implementation of basic_parser +class basic_parser_impl { // non-template implementation of basic_parser public: + basic_parser_impl(Option &O) {} + virtual ~basic_parser_impl() {} enum ValueExpected getValueExpectedFlagDefault() const { return ValueRequired; } - void getExtraOptionNames(SmallVectorImpl &) {} + void getExtraOptionNames(SmallVectorImpl &) {} - void initialize(Option &) {} + void initialize() {} // Return the width of the option tag for printing... size_t getOptionWidth(const Option &O) const; @@ -735,9 +728,9 @@ protected: // basic_parser - The real basic parser is just a template wrapper that provides // a typedef for the provided data type. // -template -class basic_parser : public basic_parser_impl { +template class basic_parser : public basic_parser_impl { public: + basic_parser(Option &O) : basic_parser_impl(O) {} typedef DataType parser_data_type; typedef OptionValue OptVal; }; @@ -745,18 +738,14 @@ public: //-------------------------------------------------- // parser // -template<> -class parser : public basic_parser { - const char *ArgStr; +template <> class parser : public basic_parser { public: + parser(Option &O) : basic_parser(O) {} // parse - Return true on error. bool parse(Option &O, StringRef ArgName, StringRef Arg, bool &Val); - template - void initialize(Opt &O) { - ArgStr = O.ArgStr; - } + void initialize() {} enum ValueExpected getValueExpectedFlagDefault() const { return ValueOptional; @@ -776,9 +765,10 @@ EXTERN_TEMPLATE_INSTANTIATION(class basic_parser); //-------------------------------------------------- // parser -template<> -class parser : public basic_parser { +template <> class parser : public basic_parser { public: + parser(Option &O) : basic_parser(O) {} + // parse - Return true on error. bool parse(Option &O, StringRef ArgName, StringRef Arg, boolOrDefault &Val); @@ -801,9 +791,10 @@ EXTERN_TEMPLATE_INSTANTIATION(class basic_parser); //-------------------------------------------------- // parser // -template<> -class parser : public basic_parser { +template <> class parser : public basic_parser { public: + parser(Option &O) : basic_parser(O) {} + // parse - Return true on error. bool parse(Option &O, StringRef ArgName, StringRef Arg, int &Val); @@ -819,13 +810,13 @@ public: EXTERN_TEMPLATE_INSTANTIATION(class basic_parser); - //-------------------------------------------------- // parser // -template<> -class parser : public basic_parser { +template <> class parser : public basic_parser { public: + parser(Option &O) : basic_parser(O) {} + // parse - Return true on error. bool parse(Option &O, StringRef ArgName, StringRef Arg, unsigned &Val); @@ -844,9 +835,11 @@ EXTERN_TEMPLATE_INSTANTIATION(class basic_parser); //-------------------------------------------------- // parser // -template<> +template <> class parser : public basic_parser { public: + parser(Option &O) : basic_parser(O) {} + // parse - Return true on error. bool parse(Option &O, StringRef ArgName, StringRef Arg, unsigned long long &Val); @@ -866,9 +859,10 @@ EXTERN_TEMPLATE_INSTANTIATION(class basic_parser); //-------------------------------------------------- // parser // -template<> -class parser : public basic_parser { +template <> class parser : public basic_parser { public: + parser(Option &O) : basic_parser(O) {} + // parse - Return true on error. bool parse(Option &O, StringRef ArgName, StringRef Arg, double &Val); @@ -887,9 +881,10 @@ EXTERN_TEMPLATE_INSTANTIATION(class basic_parser); //-------------------------------------------------- // parser // -template<> -class parser : public basic_parser { +template <> class parser : public basic_parser { public: + parser(Option &O) : basic_parser(O) {} + // parse - Return true on error. bool parse(Option &O, StringRef ArgName, StringRef Arg, float &Val); @@ -908,9 +903,10 @@ EXTERN_TEMPLATE_INSTANTIATION(class basic_parser); //-------------------------------------------------- // parser // -template<> -class parser : public basic_parser { +template <> class parser : public basic_parser { public: + parser(Option &O) : basic_parser(O) {} + // parse - Return true on error. bool parse(Option &, StringRef, StringRef Arg, std::string &Value) { Value = Arg.str(); @@ -932,9 +928,10 @@ EXTERN_TEMPLATE_INSTANTIATION(class basic_parser); //-------------------------------------------------- // parser // -template<> -class parser : public basic_parser { +template <> class parser : public basic_parser { public: + parser(Option &O) : basic_parser(O) {} + // parse - Return true on error. bool parse(Option &, StringRef, StringRef Arg, char &Value) { Value = Arg[0]; @@ -960,7 +957,7 @@ EXTERN_TEMPLATE_INSTANTIATION(class basic_parser); // parser to handle all the template nastiness. // This overloaded function is selected by the generic parser. -template +template void printOptionDiff(const Option &O, const generic_parser_base &P, const DT &V, const OptionValue
&Default, size_t GlobalWidth) { OptionValue
OV = V; @@ -969,18 +966,16 @@ void printOptionDiff(const Option &O, const generic_parser_base &P, const DT &V, // This is instantiated for basic parsers when the parsed value has a different // type than the option value. e.g. HelpPrinter. -template -struct OptionDiffPrinter { - void print(const Option &O, const parser P, const ValDT &/*V*/, - const OptionValue &/*Default*/, size_t GlobalWidth) { +template struct OptionDiffPrinter { + void print(const Option &O, const parser P, const ValDT & /*V*/, + const OptionValue & /*Default*/, size_t GlobalWidth) { P.printOptionNoValue(O, GlobalWidth); } }; // This is instantiated for basic parsers when the parsed value has the same // type as the option value. -template -struct OptionDiffPrinter { +template struct OptionDiffPrinter { void print(const Option &O, const parser
P, const DT &V, const OptionValue
&Default, size_t GlobalWidth) { P.printOptionDiff(O, V, Default, GlobalWidth); @@ -989,15 +984,14 @@ struct OptionDiffPrinter { // This overloaded function is selected by the basic parser, which may parse a // different type than the option type. -template +template void printOptionDiff( - const Option &O, - const basic_parser &P, - const ValDT &V, const OptionValue &Default, - size_t GlobalWidth) { + const Option &O, + const basic_parser &P, + const ValDT &V, const OptionValue &Default, size_t GlobalWidth) { OptionDiffPrinter printer; - printer.print(O, static_cast(P), V, Default, + printer.print(O, static_cast(P), V, Default, GlobalWidth); } @@ -1007,46 +1001,53 @@ void printOptionDiff( // not correctly respond to the apply method). Because the syntax to use this // is a pain, we have the 'apply' method below to handle the nastiness... // -template struct applicator { - template - static void opt(const Mod &M, Opt &O) { M.apply(O); } +template struct applicator { + template static void opt(const Mod &M, Opt &O) { M.apply(O); } }; // Handle const char* as a special case... -template struct applicator { - template - static void opt(const char *Str, Opt &O) { O.setArgStr(Str); } +template struct applicator { + template static void opt(const char *Str, Opt &O) { + O.setArgStr(Str); + } }; -template struct applicator { - template - static void opt(const char *Str, Opt &O) { O.setArgStr(Str); } +template struct applicator { + template static void opt(const char *Str, Opt &O) { + O.setArgStr(Str); + } }; -template<> struct applicator { - template - static void opt(const char *Str, Opt &O) { O.setArgStr(Str); } +template <> struct applicator { + template static void opt(const char *Str, Opt &O) { + O.setArgStr(Str); + } }; -template<> struct applicator { +template <> struct applicator { static void opt(NumOccurrencesFlag N, Option &O) { O.setNumOccurrencesFlag(N); } }; -template<> struct applicator { +template <> struct applicator { static void opt(ValueExpected VE, Option &O) { O.setValueExpectedFlag(VE); } }; -template<> struct applicator { +template <> struct applicator { static void opt(OptionHidden OH, Option &O) { O.setHiddenFlag(OH); } }; -template<> struct applicator { +template <> struct applicator { static void opt(FormattingFlags FF, Option &O) { O.setFormattingFlag(FF); } }; -template<> struct applicator { +template <> struct applicator { static void opt(MiscFlags MF, Option &O) { O.setMiscFlag(MF); } }; -// apply method - Apply a modifier to an option in a type safe way. -template -void apply(const Mod &M, Opt *O) { +// apply method - Apply modifiers to an option in a type safe way. +template +void apply(Opt *O, const Mod &M, const Mods &... Ms) { + applicator::opt(M, *O); + apply(O, Ms...); +} + +template void apply(Opt *O, const Mod &M) { applicator::opt(M, *O); } @@ -1057,16 +1058,17 @@ void apply(const Mod &M, Opt *O) { // assumes the user will specify a variable to store the data into with the // cl::location(x) modifier. // -template +template class opt_storage { - DataType *Location; // Where to store the object... + DataType *Location; // Where to store the object... OptionValue Default; void check_location() const { assert(Location && "cl::location(...) not specified for a command " - "line option with external storage, " - "or cl::init specified before cl::location()!!"); + "line option with external storage, " + "or cl::init specified before cl::location()!!"); } + public: opt_storage() : Location(nullptr) {} @@ -1078,16 +1080,21 @@ public: return false; } - template - void setValue(const T &V, bool initial = false) { + template void setValue(const T &V, bool initial = false) { check_location(); *Location = V; if (initial) Default = V; } - DataType &getValue() { check_location(); return *Location; } - const DataType &getValue() const { check_location(); return *Location; } + DataType &getValue() { + check_location(); + return *Location; + } + const DataType &getValue() const { + check_location(); + return *Location; + } operator DataType() const { return this->getValue(); } @@ -1098,13 +1105,12 @@ public: // inherit from a class, we do so. This makes us exactly compatible with the // object in all cases that it is used. // -template -class opt_storage : public DataType { +template +class opt_storage : public DataType { public: OptionValue Default; - template - void setValue(const T &V, bool initial = false) { + template void setValue(const T &V, bool initial = false) { DataType::operator=(V); if (initial) Default = V; @@ -1120,8 +1126,7 @@ public: // this case, we store an instance through containment, and overload operators // to get at the value. // -template -class opt_storage { +template class opt_storage { public: DataType Value; OptionValue Default; @@ -1130,8 +1135,7 @@ public: // type. opt_storage() : Value(DataType()), Default(DataType()) {} - template - void setValue(const T &V, bool initial = false) { + template void setValue(const T &V, bool initial = false) { Value = V; if (initial) Default = V; @@ -1147,12 +1151,11 @@ public: DataType operator->() const { return Value; } }; - //===----------------------------------------------------------------------===// // opt - A scalar command line option. // template > + class ParserClass = parser> class opt : public Option, public opt_storage::value> { @@ -1161,9 +1164,9 @@ class opt : public Option, bool handleOccurrence(unsigned pos, StringRef ArgName, StringRef Arg) override { typename ParserClass::parser_data_type Val = - typename ParserClass::parser_data_type(); + typename ParserClass::parser_data_type(); if (Parser.parse(*this, ArgName, Arg, Val)) - return true; // Parse error! + return true; // Parse error! this->setValue(Val); this->setPosition(pos); return false; @@ -1172,102 +1175,50 @@ class opt : public Option, enum ValueExpected getValueExpectedFlagDefault() const override { return Parser.getValueExpectedFlagDefault(); } - void getExtraOptionNames(SmallVectorImpl &OptionNames) override { + void + getExtraOptionNames(SmallVectorImpl &OptionNames) override { return Parser.getExtraOptionNames(OptionNames); } // Forward printing stuff to the parser... - size_t getOptionWidth() const override {return Parser.getOptionWidth(*this);} + size_t getOptionWidth() const override { + return Parser.getOptionWidth(*this); + } void printOptionInfo(size_t GlobalWidth) const override { Parser.printOptionInfo(*this, GlobalWidth); } void printOptionValue(size_t GlobalWidth, bool Force) const override { if (Force || this->getDefault().compare(this->getValue())) { - cl::printOptionDiff( - *this, Parser, this->getValue(), this->getDefault(), GlobalWidth); + cl::printOptionDiff(*this, Parser, this->getValue(), + this->getDefault(), GlobalWidth); } } void done() { addArgument(); - Parser.initialize(*this); + Parser.initialize(); } + + // Command line options should not be copyable + opt(const opt &) = delete; + opt &operator=(const opt &) = delete; + public: // setInitialValue - Used by the cl::init modifier... void setInitialValue(const DataType &V) { this->setValue(V, true); } ParserClass &getParser() { return Parser; } - template - DataType &operator=(const T &Val) { + template DataType &operator=(const T &Val) { this->setValue(Val); return this->getValue(); } - // One option... - template - explicit opt(const M0t &M0) : Option(Optional, NotHidden) { - apply(M0, this); - done(); - } - - // Two options... - template - opt(const M0t &M0, const M1t &M1) : Option(Optional, NotHidden) { - apply(M0, this); apply(M1, this); - done(); - } - - // Three options... - template - opt(const M0t &M0, const M1t &M1, - const M2t &M2) : Option(Optional, NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); - done(); - } - // Four options... - template - opt(const M0t &M0, const M1t &M1, const M2t &M2, - const M3t &M3) : Option(Optional, NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); - done(); - } - // Five options... - template - opt(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, - const M4t &M4) : Option(Optional, NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); - apply(M4, this); - done(); - } - // Six options... - template - opt(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, - const M4t &M4, const M5t &M5) : Option(Optional, NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); - apply(M4, this); apply(M5, this); - done(); - } - // Seven options... - template - opt(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, - const M4t &M4, const M5t &M5, - const M6t &M6) : Option(Optional, NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); - apply(M4, this); apply(M5, this); apply(M6, this); - done(); - } - // Eight options... - template - opt(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, - const M4t &M4, const M5t &M5, const M6t &M6, - const M7t &M7) : Option(Optional, NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); - apply(M4, this); apply(M5, this); apply(M6, this); apply(M7, this); + template + explicit opt(const Mods &... Ms) + : Option(Optional, NotHidden), Parser(*this) { + apply(this, Ms...); done(); } }; @@ -1285,9 +1236,8 @@ EXTERN_TEMPLATE_INSTANTIATION(class opt); // assumes the user will specify a variable to store the data into with the // cl::location(x) modifier. // -template -class list_storage { - StorageClass *Location; // Where to store the object... +template class list_storage { + StorageClass *Location; // Where to store the object... public: list_storage() : Location(0) {} @@ -1299,32 +1249,30 @@ public: return false; } - template - void addValue(const T &V) { + template void addValue(const T &V) { assert(Location != 0 && "cl::location(...) not specified for a command " - "line option with external storage!"); + "line option with external storage!"); Location->push_back(V); } }; - // Define how to hold a class type object, such as a string. Since we can // inherit from a class, we do so. This makes us exactly compatible with the // object in all cases that it is used. // -template +template class list_storage : public std::vector { public: - template - void addValue(const T &V) { std::vector::push_back(V); } + template void addValue(const T &V) { + std::vector::push_back(V); + } }; - //===----------------------------------------------------------------------===// // list - A list of command line options. // template > + class ParserClass = parser> class list : public Option, public list_storage { std::vector Positions; ParserClass Parser; @@ -1332,16 +1280,17 @@ class list : public Option, public list_storage { enum ValueExpected getValueExpectedFlagDefault() const override { return Parser.getValueExpectedFlagDefault(); } - void getExtraOptionNames(SmallVectorImpl &OptionNames) override { + void + getExtraOptionNames(SmallVectorImpl &OptionNames) override { return Parser.getExtraOptionNames(OptionNames); } bool handleOccurrence(unsigned pos, StringRef ArgName, StringRef Arg) override { typename ParserClass::parser_data_type Val = - typename ParserClass::parser_data_type(); + typename ParserClass::parser_data_type(); if (Parser.parse(*this, ArgName, Arg, Val)) - return true; // Parse Error! + return true; // Parse Error! list_storage::addValue(Val); setPosition(pos); Positions.push_back(pos); @@ -1349,19 +1298,26 @@ class list : public Option, public list_storage { } // Forward printing stuff to the parser... - size_t getOptionWidth() const override {return Parser.getOptionWidth(*this);} + size_t getOptionWidth() const override { + return Parser.getOptionWidth(*this); + } void printOptionInfo(size_t GlobalWidth) const override { Parser.printOptionInfo(*this, GlobalWidth); } // Unimplemented: list options don't currently store their default value. - void printOptionValue(size_t /*GlobalWidth*/, - bool /*Force*/) const override {} + void printOptionValue(size_t /*GlobalWidth*/, bool /*Force*/) const override { + } void done() { addArgument(); - Parser.initialize(*this); + Parser.initialize(); } + + // Command line options should not be copyable + list(const list &) = delete; + list &operator=(const list &) = delete; + public: ParserClass &getParser() { return Parser; } @@ -1370,71 +1326,12 @@ public: return Positions[optnum]; } - void setNumAdditionalVals(unsigned n) { - Option::setNumAdditionalVals(n); - } + void setNumAdditionalVals(unsigned n) { Option::setNumAdditionalVals(n); } - // One option... - template - explicit list(const M0t &M0) : Option(ZeroOrMore, NotHidden) { - apply(M0, this); - done(); - } - // Two options... - template - list(const M0t &M0, const M1t &M1) : Option(ZeroOrMore, NotHidden) { - apply(M0, this); apply(M1, this); - done(); - } - // Three options... - template - list(const M0t &M0, const M1t &M1, const M2t &M2) - : Option(ZeroOrMore, NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); - done(); - } - // Four options... - template - list(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3) - : Option(ZeroOrMore, NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); - done(); - } - // Five options... - template - list(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, - const M4t &M4) : Option(ZeroOrMore, NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); - apply(M4, this); - done(); - } - // Six options... - template - list(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, - const M4t &M4, const M5t &M5) : Option(ZeroOrMore, NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); - apply(M4, this); apply(M5, this); - done(); - } - // Seven options... - template - list(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, - const M4t &M4, const M5t &M5, const M6t &M6) - : Option(ZeroOrMore, NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); - apply(M4, this); apply(M5, this); apply(M6, this); - done(); - } - // Eight options... - template - list(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, - const M4t &M4, const M5t &M5, const M6t &M6, - const M7t &M7) : Option(ZeroOrMore, NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); - apply(M4, this); apply(M5, this); apply(M6, this); apply(M7, this); + template + explicit list(const Mods &... Ms) + : Option(ZeroOrMore, NotHidden), Parser(*this) { + apply(this, Ms...); done(); } }; @@ -1445,10 +1342,11 @@ struct multi_val { explicit multi_val(unsigned N) : AdditionalVals(N) {} template - void apply(list &L) const { L.setNumAdditionalVals(AdditionalVals); } + void apply(list &L) const { + L.setNumAdditionalVals(AdditionalVals); + } }; - //===----------------------------------------------------------------------===// // bits_storage class @@ -1456,15 +1354,13 @@ struct multi_val { // assumes the user will specify a variable to store the data into with the // cl::location(x) modifier. // -template -class bits_storage { - unsigned *Location; // Where to store the bits... +template class bits_storage { + unsigned *Location; // Where to store the bits... - template - static unsigned Bit(const T &V) { + template static unsigned Bit(const T &V) { unsigned BitPos = reinterpret_cast(V); assert(BitPos < sizeof(unsigned) * CHAR_BIT && - "enum exceeds width of bit vector!"); + "enum exceeds width of bit vector!"); return 1 << BitPos; } @@ -1478,57 +1374,45 @@ public: return false; } - template - void addValue(const T &V) { + template void addValue(const T &V) { assert(Location != 0 && "cl::location(...) not specified for a command " - "line option with external storage!"); + "line option with external storage!"); *Location |= Bit(V); } unsigned getBits() { return *Location; } - template - bool isSet(const T &V) { + template bool isSet(const T &V) { return (*Location & Bit(V)) != 0; } }; - // Define how to hold bits. Since we can inherit from a class, we do so. // This makes us exactly compatible with the bits in all cases that it is used. // -template -class bits_storage { - unsigned Bits; // Where to store the bits... +template class bits_storage { + unsigned Bits; // Where to store the bits... - template - static unsigned Bit(const T &V) { + template static unsigned Bit(const T &V) { unsigned BitPos = (unsigned)V; assert(BitPos < sizeof(unsigned) * CHAR_BIT && - "enum exceeds width of bit vector!"); + "enum exceeds width of bit vector!"); return 1 << BitPos; } public: - template - void addValue(const T &V) { - Bits |= Bit(V); - } + template void addValue(const T &V) { Bits |= Bit(V); } unsigned getBits() { return Bits; } - template - bool isSet(const T &V) { - return (Bits & Bit(V)) != 0; - } + template bool isSet(const T &V) { return (Bits & Bit(V)) != 0; } }; - //===----------------------------------------------------------------------===// // bits - A bit vector of command options. // template > + class ParserClass = parser> class bits : public Option, public bits_storage { std::vector Positions; ParserClass Parser; @@ -1536,16 +1420,17 @@ class bits : public Option, public bits_storage { enum ValueExpected getValueExpectedFlagDefault() const override { return Parser.getValueExpectedFlagDefault(); } - void getExtraOptionNames(SmallVectorImpl &OptionNames) override { + void + getExtraOptionNames(SmallVectorImpl &OptionNames) override { return Parser.getExtraOptionNames(OptionNames); } bool handleOccurrence(unsigned pos, StringRef ArgName, StringRef Arg) override { typename ParserClass::parser_data_type Val = - typename ParserClass::parser_data_type(); + typename ParserClass::parser_data_type(); if (Parser.parse(*this, ArgName, Arg, Val)) - return true; // Parse Error! + return true; // Parse Error! this->addValue(Val); setPosition(pos); Positions.push_back(pos); @@ -1553,19 +1438,26 @@ class bits : public Option, public bits_storage { } // Forward printing stuff to the parser... - size_t getOptionWidth() const override {return Parser.getOptionWidth(*this);} + size_t getOptionWidth() const override { + return Parser.getOptionWidth(*this); + } void printOptionInfo(size_t GlobalWidth) const override { Parser.printOptionInfo(*this, GlobalWidth); } // Unimplemented: bits options don't currently store their default values. - void printOptionValue(size_t /*GlobalWidth*/, - bool /*Force*/) const override {} + void printOptionValue(size_t /*GlobalWidth*/, bool /*Force*/) const override { + } void done() { addArgument(); - Parser.initialize(*this); + Parser.initialize(); } + + // Command line options should not be copyable + bits(const bits &) = delete; + bits &operator=(const bits &) = delete; + public: ParserClass &getParser() { return Parser; } @@ -1574,67 +1466,10 @@ public: return Positions[optnum]; } - // One option... - template - explicit bits(const M0t &M0) : Option(ZeroOrMore, NotHidden) { - apply(M0, this); - done(); - } - // Two options... - template - bits(const M0t &M0, const M1t &M1) : Option(ZeroOrMore, NotHidden) { - apply(M0, this); apply(M1, this); - done(); - } - // Three options... - template - bits(const M0t &M0, const M1t &M1, const M2t &M2) - : Option(ZeroOrMore, NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); - done(); - } - // Four options... - template - bits(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3) - : Option(ZeroOrMore, NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); - done(); - } - // Five options... - template - bits(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, - const M4t &M4) : Option(ZeroOrMore, NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); - apply(M4, this); - done(); - } - // Six options... - template - bits(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, - const M4t &M4, const M5t &M5) : Option(ZeroOrMore, NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); - apply(M4, this); apply(M5, this); - done(); - } - // Seven options... - template - bits(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, - const M4t &M4, const M5t &M5, const M6t &M6) - : Option(ZeroOrMore, NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); - apply(M4, this); apply(M5, this); apply(M6, this); - done(); - } - // Eight options... - template - bits(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, - const M4t &M4, const M5t &M5, const M6t &M6, - const M7t &M7) : Option(ZeroOrMore, NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); - apply(M4, this); apply(M5, this); apply(M6, this); apply(M7, this); + template + explicit bits(const Mods &... Ms) + : Option(ZeroOrMore, NotHidden), Parser(*this) { + apply(this, Ms...); done(); } }; @@ -1646,11 +1481,11 @@ public: class alias : public Option { Option *AliasFor; bool handleOccurrence(unsigned pos, StringRef /*ArgName*/, - StringRef Arg) override { + StringRef Arg) override { return AliasFor->handleOccurrence(pos, AliasFor->ArgStr, Arg); } - bool addOccurrence(unsigned pos, StringRef /*ArgName*/, - StringRef Value, bool MultiArg = false) override { + bool addOccurrence(unsigned pos, StringRef /*ArgName*/, StringRef Value, + bool MultiArg = false) override { return AliasFor->addOccurrence(pos, AliasFor->ArgStr, Value, MultiArg); } // Handle printing stuff... @@ -1658,8 +1493,8 @@ class alias : public Option { void printOptionInfo(size_t GlobalWidth) const override; // Aliases do not need to print their values. - void printOptionValue(size_t /*GlobalWidth*/, - bool /*Force*/) const override {} + void printOptionValue(size_t /*GlobalWidth*/, bool /*Force*/) const override { + } ValueExpected getValueExpectedFlagDefault() const override { return AliasFor->getValueExpectedFlag(); @@ -1670,8 +1505,13 @@ class alias : public Option { error("cl::alias must have argument name specified!"); if (!AliasFor) error("cl::alias must have an cl::aliasopt(option) specified!"); - addArgument(); + addArgument(); } + + // Command line options should not be copyable + alias(const alias &) = delete; + alias &operator=(const alias &) = delete; + public: void setAliasFor(Option &O) { if (AliasFor) @@ -1679,31 +1519,10 @@ public: AliasFor = &O; } - // One option... - template - explicit alias(const M0t &M0) : Option(Optional, Hidden), AliasFor(nullptr) { - apply(M0, this); - done(); - } - // Two options... - template - alias(const M0t &M0, const M1t &M1) - : Option(Optional, Hidden), AliasFor(nullptr) { - apply(M0, this); apply(M1, this); - done(); - } - // Three options... - template - alias(const M0t &M0, const M1t &M1, const M2t &M2) - : Option(Optional, Hidden), AliasFor(nullptr) { - apply(M0, this); apply(M1, this); apply(M2, this); - done(); - } - // Four options... - template - alias(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3) - : Option(Optional, Hidden), AliasFor(nullptr) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); + template + explicit alias(const Mods &... Ms) + : Option(Optional, Hidden), AliasFor(nullptr) { + apply(this, Ms...); done(); } }; @@ -1720,8 +1539,8 @@ struct aliasopt { // printed to stderr at the end of the regular help, just before // exit is called. struct extrahelp { - const char * morehelp; - explicit extrahelp(const char* help); + const char *morehelp; + explicit extrahelp(const char *help); }; void PrintVersionMessage(); @@ -1733,8 +1552,7 @@ void PrintVersionMessage(); /// /// \param Hidden if true will print hidden options /// \param Categorized if true print options in categories -void PrintHelpMessage(bool Hidden=false, bool Categorized=false); - +void PrintHelpMessage(bool Hidden = false, bool Categorized = false); //===----------------------------------------------------------------------===// // Public interface for accessing registered options. @@ -1743,9 +1561,7 @@ void PrintHelpMessage(bool Hidden=false, bool Categorized=false); /// \brief Use this to get a StringMap to all registered named options /// (e.g. -help). Note \p Map Should be an empty StringMap. /// -/// \param [out] Map will be filled with mappings where the key is the -/// Option argument string (e.g. "help") and value is the corresponding -/// Option*. +/// \return A reference to the StringMap used by the cl APIs to parse options. /// /// Access to unnamed arguments (i.e. positional) are not provided because /// it is expected that the client already has access to these. @@ -1753,8 +1569,7 @@ void PrintHelpMessage(bool Hidden=false, bool Categorized=false); /// Typical usage: /// \code /// main(int argc,char* argv[]) { -/// StringMap opts; -/// llvm::cl::getRegisteredOptions(opts); +/// StringMap &opts = llvm::cl::getRegisteredOptions(); /// assert(opts.count("help") == 1) /// opts["help"]->setDescription("Show alphabetical help information") /// // More code @@ -1766,7 +1581,11 @@ void PrintHelpMessage(bool Hidden=false, bool Categorized=false); /// This interface is useful for modifying options in libraries that are out of /// the control of the client. The options should be modified before calling /// llvm::cl::ParseCommandLineOptions(). -void getRegisteredOptions(StringMap &Map); +/// +/// Hopefully this API can be depricated soon. Any situation where options need +/// to be modified by tools or libraries should be handled by sane APIs rather +/// than just handing around a global list. +StringMap