From 8c621e02cc2a6e12d135d68d14ad4a1dc6c81cfb Mon Sep 17 00:00:00 2001 From: dim Date: Fri, 21 Mar 2014 17:56:32 +0000 Subject: [PATCH] MFC 254790 (by emaste): Import llvm r187614 (git 44c8e34), for lldb's use: Author: Daniel Malea Date: Thu Aug 1 21:18:16 2013 +0000 Fixed the Intel-syntax X86 disassembler to respect the (existing) option for hexadecimal immediates, to match AT&T syntax. This also brings a new option for C-vs-MASM-style hex. Patch by Richard Mitton Reviewed: http://llvm-reviews.chandlerc.com/D1243 MFC 258003 (by emaste): Merge upstream LLVM r182803: [Mips] Add Mips specific dynamic table entry tags. This is to support an upcoming LLDB snapshot update. Reviewed by: dim@ Sponsored by: DARPA, AFRL MFC 258005: Merge upstream LLVM r192118: Formally added an explicit enum for DWARF TLS support. No functionality change. Reviewed by: dim@ Sponsored by: DARPA, AFRL MFC 261991: Upgrade our copy of llvm/clang to 3.4 release. This version supports all of the features in the current working draft of the upcoming C++ standard, provisionally named C++1y. The code generator's performance is greatly increased, and the loop auto-vectorizer is now enabled at -Os and -O2 in addition to -O3. The PowerPC backend has made several major improvements to code generation quality and compile time, and the X86, SPARC, ARM32, Aarch64 and SystemZ backends have all seen major feature work. Release notes for llvm and clang can be found here: MFC 262303: Pull in r197521 from upstream clang trunk (by rdivacky): Use the integrated assembler by default on FreeBSD/ppc and ppc64. Requested by: jhibbits MFC 262611: Pull in r196874 from upstream llvm trunk: Fix a crash that occurs when PWD is invalid. MCJIT needs to be able to run in hostile environments, even when PWD is invalid. There's no need to crash MCJIT in this case. The obvious fix is to simply leave MCContext's CompilationDir empty when PWD can't be determined. This way, MCJIT clients, and other clients that link with LLVM don't need a valid working directory. If we do want to guarantee valid CompilationDir, that should be done only for clients of getCompilationDir(). This is as simple as checking for an empty string. The only current use of getCompilationDir is EmitGenDwarfInfo, which won't conceivably run with an invalid working dir. However, in the purely hypothetically and untestable case that this happens, the AT_comp_dir will be omitted from the compilation_unit DIE. This should help fix assertions occurring with ports-mgmt/tinderbox, when it is using jails, and sometimes invalidates clang's current working directory. Reported by: decke MFC 262809: Pull in r203007 from upstream clang trunk: Don't produce an alias between destructors with different calling conventions. Fixes pr19007. (Please note that is an LLVM PR identifier, not a FreeBSD one.) This should fix Firefox and/or libxul crashes (due to problems with regparm/stdcall calling conventions) on i386. Reported by: multiple users on freebsd-current PR: bin/187103 MFC 263048: Repair recognition of "CC" as an alias for the C++ compiler, since it was silently broken by upstream for a Windows-specific use-case. Apparently some versions of CMake still rely on this archaic feature... Reported by: rakuco MFC 263049: Garbage collect the old way of adding the libstdc++ include directories in clang's InitHeaderSearch.cpp. This has been superseded by David Chisnall's commit in r255321. Moreover, if libc++ is used, the libstdc++ include directories should not be in the search path at all. These directories are now only used if you pass -stdlib=libstdc++. git-svn-id: svn://svn.freebsd.org/base/stable/9@263509 ccf9f872-aa2e-dd11-9fc8-001c23d0bc1f --- ObsoleteFiles.inc | 37 + UPDATING | 3 + contrib/gcc/libgcc2.c | 4 +- contrib/gcc/libgcc2.h | 2 +- contrib/llvm/LICENSE.TXT | 1 + contrib/llvm/include/llvm-c/BitReader.h | 4 +- contrib/llvm/include/llvm-c/BitWriter.h | 4 +- contrib/llvm/include/llvm-c/Core.h | 174 +- contrib/llvm/include/llvm-c/Disassembler.h | 19 +- contrib/llvm/include/llvm-c/ExecutionEngine.h | 36 +- contrib/llvm/include/llvm-c/IRReader.h | 40 + .../llvm/include/llvm-c/LinkTimeOptimizer.h | 4 +- contrib/llvm/include/llvm-c/Object.h | 1 - contrib/llvm/include/llvm-c/Support.h | 35 + contrib/llvm/include/llvm-c/Target.h | 108 +- contrib/llvm/include/llvm-c/TargetMachine.h | 28 +- .../llvm/include/llvm-c/Transforms/Scalar.h | 6 + contrib/llvm/include/llvm-c/lto.h | 42 +- contrib/llvm/include/llvm/ADT/APFloat.h | 998 +- contrib/llvm/include/llvm/ADT/APInt.h | 1483 +-- contrib/llvm/include/llvm/ADT/APSInt.h | 12 +- contrib/llvm/include/llvm/ADT/ArrayRef.h | 14 +- contrib/llvm/include/llvm/ADT/BitVector.h | 23 +- contrib/llvm/include/llvm/ADT/DenseMap.h | 17 +- contrib/llvm/include/llvm/ADT/FoldingSet.h | 5 +- contrib/llvm/include/llvm/ADT/ImmutableMap.h | 1 + contrib/llvm/include/llvm/ADT/ImmutableSet.h | 13 + contrib/llvm/include/llvm/ADT/IntervalMap.h | 6 +- contrib/llvm/include/llvm/ADT/NullablePtr.h | 52 - contrib/llvm/include/llvm/ADT/OwningPtr.h | 5 +- .../llvm/include/llvm/ADT/PointerIntPair.h | 3 +- contrib/llvm/include/llvm/ADT/PointerUnion.h | 23 +- contrib/llvm/include/llvm/ADT/STLExtras.h | 28 +- contrib/llvm/include/llvm/ADT/SetVector.h | 2 +- .../llvm/include/llvm/ADT/SmallBitVector.h | 42 +- contrib/llvm/include/llvm/ADT/SmallPtrSet.h | 2 +- contrib/llvm/include/llvm/ADT/SmallVector.h | 4 +- .../llvm/include/llvm/ADT/SparseBitVector.h | 12 +- contrib/llvm/include/llvm/ADT/StringExtras.h | 43 + contrib/llvm/include/llvm/ADT/StringMap.h | 11 + contrib/llvm/include/llvm/ADT/StringRef.h | 14 +- contrib/llvm/include/llvm/ADT/Triple.h | 38 +- contrib/llvm/include/llvm/ADT/ilist.h | 6 +- .../llvm/include/llvm/ADT/polymorphic_ptr.h | 117 + .../include/llvm/Analysis/AliasAnalysis.h | 4 + .../llvm/Analysis/BlockFrequencyImpl.h | 117 +- .../llvm/Analysis/BlockFrequencyInfo.h | 12 +- .../llvm/Analysis/BranchProbabilityInfo.h | 4 + contrib/llvm/include/llvm/Analysis/CFG.h | 83 + .../llvm/include/llvm/Analysis/CFGPrinter.h | 31 +- .../llvm/include/llvm/Analysis/CallGraph.h | 73 +- .../include/llvm/Analysis/ConstantFolding.h | 6 +- .../llvm/Analysis/DependenceAnalysis.h | 42 +- .../llvm/include/llvm/Analysis/Dominators.h | 20 + .../llvm/include/llvm/Analysis/InlineCost.h | 3 +- .../llvm/Analysis/InstructionSimplify.h | 2 +- contrib/llvm/include/llvm/Analysis/LoopInfo.h | 35 +- .../llvm/include/llvm/Analysis/LoopInfoImpl.h | 41 +- contrib/llvm/include/llvm/Analysis/LoopPass.h | 2 +- .../include/llvm/Analysis/MemoryBuiltins.h | 35 +- contrib/llvm/include/llvm/Analysis/Passes.h | 65 +- .../include/llvm/Analysis/PathNumbering.h | 304 - .../include/llvm/Analysis/PathProfileInfo.h | 112 - .../include/llvm/Analysis/PostDominators.h | 5 + .../include/llvm/Analysis/ProfileDataLoader.h | 140 - .../include/llvm/Analysis/ProfileDataTypes.h | 39 - .../llvm/include/llvm/Analysis/ProfileInfo.h | 247 - .../include/llvm/Analysis/ProfileInfoLoader.h | 81 - .../include/llvm/Analysis/ProfileInfoTypes.h | 52 - .../llvm/include/llvm/Analysis/RegionPass.h | 4 +- .../include/llvm/Analysis/ScalarEvolution.h | 67 +- .../llvm/Analysis/ScalarEvolutionExpander.h | 4 +- .../Analysis/ScalarEvolutionExpressions.h | 148 +- .../llvm/Analysis/TargetTransformInfo.h | 75 +- .../include/llvm/Analysis/ValueTracking.h | 3 +- contrib/llvm/include/llvm/AutoUpgrade.h | 40 +- contrib/llvm/include/llvm/Bitcode/Archive.h | 538 - .../include/llvm/Bitcode/BitstreamReader.h | 5 +- .../include/llvm/Bitcode/BitstreamWriter.h | 3 +- .../llvm/include/llvm/Bitcode/LLVMBitCodes.h | 45 +- contrib/llvm/include/llvm/CodeGen/Analysis.h | 9 + .../llvm/include/llvm/CodeGen/AsmPrinter.h | 52 +- .../include/llvm/CodeGen/CalcSpillWeights.h | 51 +- .../include/llvm/CodeGen/CallingConvLower.h | 4 +- .../llvm/include/llvm/CodeGen/CommandFlags.h | 16 +- contrib/llvm/include/llvm/CodeGen/FastISel.h | 284 +- .../llvm/CodeGen/FunctionLoweringInfo.h | 4 +- .../llvm/include/llvm/CodeGen/ISDOpcodes.h | 28 +- .../llvm/include/llvm/CodeGen/LexicalScopes.h | 18 +- .../llvm/include/llvm/CodeGen/LiveInterval.h | 605 +- .../llvm/CodeGen/LiveIntervalAnalysis.h | 81 +- .../include/llvm/CodeGen/LiveIntervalUnion.h | 2 +- .../llvm/include/llvm/CodeGen/LiveRangeEdit.h | 44 +- .../llvm/include/llvm/CodeGen/LiveRegUnits.h | 88 + .../llvm/include/llvm/CodeGen/LiveVariables.h | 4 +- .../include/llvm/CodeGen/MachineBasicBlock.h | 29 +- .../CodeGen/MachineBranchProbabilityInfo.h | 2 +- .../llvm/CodeGen/MachineConstantPool.h | 10 +- .../include/llvm/CodeGen/MachineFrameInfo.h | 13 +- .../llvm/include/llvm/CodeGen/MachineInstr.h | 21 +- .../llvm/CodeGen/MachineInstrBuilder.h | 45 + .../include/llvm/CodeGen/MachineModuleInfo.h | 16 +- .../include/llvm/CodeGen/MachineOperand.h | 4 +- .../llvm/CodeGen/MachineRegisterInfo.h | 95 +- .../include/llvm/CodeGen/MachineRelocation.h | 2 +- .../include/llvm/CodeGen/MachineScheduler.h | 135 +- .../llvm/include/llvm/CodeGen/PBQP/Graph.h | 418 +- .../include/llvm/CodeGen/PBQP/HeuristicBase.h | 62 +- .../llvm/CodeGen/PBQP/HeuristicSolver.h | 296 +- .../llvm/CodeGen/PBQP/Heuristics/Briggs.h | 210 +- .../llvm/include/llvm/CodeGen/PBQP/Solution.h | 19 +- contrib/llvm/include/llvm/CodeGen/Passes.h | 60 +- .../include/llvm/CodeGen/PseudoSourceValue.h | 2 +- .../llvm/include/llvm/CodeGen/RegAllocPBQP.h | 23 +- .../include/llvm/CodeGen/RegisterClassInfo.h | 15 +- .../include/llvm/CodeGen/RegisterPressure.h | 168 +- .../include/llvm/CodeGen/RegisterScavenging.h | 4 +- .../include/llvm/CodeGen/RuntimeLibcalls.h | 38 +- .../llvm/include/llvm/CodeGen/ScheduleDAG.h | 33 +- .../include/llvm/CodeGen/ScheduleDAGInstrs.h | 35 +- .../llvm/include/llvm/CodeGen/SelectionDAG.h | 308 +- .../include/llvm/CodeGen/SelectionDAGISel.h | 12 +- .../include/llvm/CodeGen/SelectionDAGNodes.h | 276 +- .../llvm/include/llvm/CodeGen/SlotIndexes.h | 13 +- contrib/llvm/include/llvm/CodeGen/StackMaps.h | 175 + .../include/llvm/CodeGen/StackProtector.h | 127 + .../include/llvm/CodeGen/TargetSchedule.h | 36 +- .../llvm/include/llvm/CodeGen/ValueTypes.h | 115 +- .../llvm/include/llvm/CodeGen/ValueTypes.td | 75 +- contrib/llvm/include/llvm/DIBuilder.h | 186 +- contrib/llvm/include/llvm/DebugInfo.h | 1575 +-- .../llvm/include/llvm/DebugInfo/DIContext.h | 23 +- .../include/llvm/DebugInfo/DWARFFormValue.h | 67 +- .../llvm/ExecutionEngine/ExecutionEngine.h | 153 +- .../llvm/ExecutionEngine/JITMemoryManager.h | 16 - .../llvm/ExecutionEngine/ObjectBuffer.h | 3 + .../llvm/ExecutionEngine/ObjectCache.h | 25 +- .../llvm/ExecutionEngine/ObjectImage.h | 1 + .../ExecutionEngine/RTDyldMemoryManager.h | 112 + .../llvm/ExecutionEngine/RuntimeDyld.h | 62 +- .../ExecutionEngine/SectionMemoryManager.h | 90 +- contrib/llvm/include/llvm/GVMaterializer.h | 12 +- contrib/llvm/include/llvm/IR/Argument.h | 5 + contrib/llvm/include/llvm/IR/Attributes.h | 9 +- contrib/llvm/include/llvm/IR/CallingConv.h | 14 +- contrib/llvm/include/llvm/IR/Constants.h | 17 +- contrib/llvm/include/llvm/IR/DataLayout.h | 34 +- contrib/llvm/include/llvm/IR/Function.h | 61 +- contrib/llvm/include/llvm/IR/GlobalAlias.h | 15 +- contrib/llvm/include/llvm/IR/GlobalValue.h | 21 +- contrib/llvm/include/llvm/IR/GlobalVariable.h | 4 +- contrib/llvm/include/llvm/IR/IRBuilder.h | 139 +- contrib/llvm/include/llvm/IR/InlineAsm.h | 2 +- contrib/llvm/include/llvm/IR/InstrTypes.h | 20 +- contrib/llvm/include/llvm/IR/Instruction.def | 35 +- contrib/llvm/include/llvm/IR/Instructions.h | 481 +- contrib/llvm/include/llvm/IR/Intrinsics.h | 2 +- contrib/llvm/include/llvm/IR/Intrinsics.td | 48 +- .../llvm/include/llvm/IR/IntrinsicsAArch64.td | 388 + contrib/llvm/include/llvm/IR/IntrinsicsARM.td | 81 +- .../llvm/include/llvm/IR/IntrinsicsMips.td | 1368 +++ .../llvm/include/llvm/IR/IntrinsicsNVVM.td | 2 - .../llvm/include/llvm/IR/IntrinsicsPowerPC.td | 5 + contrib/llvm/include/llvm/IR/IntrinsicsX86.td | 553 +- .../llvm/include/llvm/IR/IntrinsicsXCore.td | 12 +- contrib/llvm/include/llvm/IR/LLVMContext.h | 22 +- .../llvm/include/llvm/IR/LegacyPassManager.h | 111 + .../LegacyPassManagers.h} | 2 +- contrib/llvm/include/llvm/IR/Metadata.h | 12 +- contrib/llvm/include/llvm/IR/Module.h | 23 +- contrib/llvm/include/llvm/IR/Operator.h | 4 +- contrib/llvm/include/llvm/IR/PassManager.h | 383 + contrib/llvm/include/llvm/IR/Type.h | 8 + contrib/llvm/include/llvm/IR/TypeBuilder.h | 2 +- contrib/llvm/include/llvm/IR/Use.h | 1 - contrib/llvm/include/llvm/IR/Value.h | 75 +- contrib/llvm/include/llvm/InitializePasses.h | 27 +- contrib/llvm/include/llvm/InstVisitor.h | 1 + .../llvm/include/llvm/LTO/LTOCodeGenerator.h | 153 + contrib/llvm/include/llvm/LTO/LTOModule.h | 196 + contrib/llvm/include/llvm/LinkAllPasses.h | 15 +- contrib/llvm/include/llvm/Linker.h | 2 + contrib/llvm/include/llvm/MC/MCAsmBackend.h | 20 +- contrib/llvm/include/llvm/MC/MCAsmInfo.h | 111 +- contrib/llvm/include/llvm/MC/MCAsmInfoELF.h | 23 + contrib/llvm/include/llvm/MC/MCAssembler.h | 21 + contrib/llvm/include/llvm/MC/MCAtom.h | 183 +- contrib/llvm/include/llvm/MC/MCCodeGenInfo.h | 3 + contrib/llvm/include/llvm/MC/MCContext.h | 35 +- contrib/llvm/include/llvm/MC/MCDisassembler.h | 39 +- contrib/llvm/include/llvm/MC/MCDwarf.h | 766 +- .../llvm/include/llvm/MC/MCELFObjectWriter.h | 14 - contrib/llvm/include/llvm/MC/MCELFStreamer.h | 42 +- .../llvm/include/llvm/MC/MCELFSymbolFlags.h | 2 +- contrib/llvm/include/llvm/MC/MCExpr.h | 66 +- .../include/llvm/MC/MCExternalSymbolizer.h | 58 + contrib/llvm/include/llvm/MC/MCFunction.h | 142 + contrib/llvm/include/llvm/MC/MCInstPrinter.h | 28 +- .../llvm/include/llvm/MC/MCInstrAnalysis.h | 11 +- contrib/llvm/include/llvm/MC/MCInstrDesc.h | 35 +- .../llvm/include/llvm/MC/MCInstrItineraries.h | 10 +- .../llvm/include/llvm/MC/MCMachOSymbolFlags.h | 6 +- .../llvm/include/llvm/MC/MCMachObjectWriter.h | 11 +- contrib/llvm/include/llvm/MC/MCModule.h | 117 +- contrib/llvm/include/llvm/MC/MCModuleYAML.h | 41 + .../include/llvm/MC/MCObjectDisassembler.h | 175 + .../llvm/include/llvm/MC/MCObjectFileInfo.h | 14 + .../llvm/include/llvm/MC/MCObjectStreamer.h | 28 +- .../llvm/include/llvm/MC/MCObjectSymbolizer.h | 81 + .../llvm/include/llvm/MC/MCParser/AsmLexer.h | 1 + .../include/llvm/MC/MCParser/MCAsmParser.h | 2 +- contrib/llvm/include/llvm/MC/MCRegisterInfo.h | 130 +- .../llvm/include/llvm/MC/MCRelocationInfo.h | 55 + contrib/llvm/include/llvm/MC/MCSchedule.h | 81 +- contrib/llvm/include/llvm/MC/MCSectionCOFF.h | 36 +- contrib/llvm/include/llvm/MC/MCSectionMachO.h | 2 +- contrib/llvm/include/llvm/MC/MCStreamer.h | 1341 +-- .../llvm/include/llvm/MC/MCSubtargetInfo.h | 3 + contrib/llvm/include/llvm/MC/MCSymbolizer.h | 81 + .../llvm/include/llvm/MC/MCTargetAsmParser.h | 11 +- .../include/llvm/MC/MCWinCOFFObjectWriter.h | 1 + .../llvm/include/llvm/MC/MachineLocation.h | 37 +- .../llvm/include/llvm/MC/SubtargetFeature.h | 15 +- contrib/llvm/include/llvm/Object/Archive.h | 109 +- contrib/llvm/include/llvm/Object/Binary.h | 5 + contrib/llvm/include/llvm/Object/COFF.h | 186 +- contrib/llvm/include/llvm/Object/COFFYAML.h | 141 + contrib/llvm/include/llvm/Object/ELF.h | 2914 +----- .../llvm/include/llvm/Object/ELFObjectFile.h | 1027 ++ contrib/llvm/include/llvm/Object/ELFTypes.h | 463 + contrib/llvm/include/llvm/Object/ELFYAML.h | 163 + contrib/llvm/include/llvm/Object/Error.h | 25 +- contrib/llvm/include/llvm/Object/MachO.h | 171 +- .../llvm/include/llvm/Object/MachOFormat.h | 415 - .../llvm/include/llvm/Object/MachOUniversal.h | 102 + contrib/llvm/include/llvm/Object/ObjectFile.h | 60 +- .../llvm/include/llvm/Object/RelocVisitor.h | 88 +- contrib/llvm/include/llvm/Object/YAML.h | 116 + contrib/llvm/include/llvm/Option/ArgList.h | 9 + contrib/llvm/include/llvm/Option/OptParser.td | 8 +- contrib/llvm/include/llvm/Option/OptTable.h | 32 +- contrib/llvm/include/llvm/Option/Option.h | 18 +- contrib/llvm/include/llvm/PassManager.h | 104 +- contrib/llvm/include/llvm/Support/Allocator.h | 15 +- .../include/llvm/Support/BlockFrequency.h | 26 +- contrib/llvm/include/llvm/Support/CFG.h | 8 +- contrib/llvm/include/llvm/Support/COFF.h | 30 +- contrib/llvm/include/llvm/Support/CallSite.h | 17 +- contrib/llvm/include/llvm/Support/Casting.h | 27 +- .../llvm/include/llvm/Support/CommandLine.h | 61 +- contrib/llvm/include/llvm/Support/Compiler.h | 82 +- .../llvm/include/llvm/Support/Compression.h | 2 + .../llvm/include/llvm/Support/ConstantRange.h | 12 +- .../llvm/include/llvm/Support/ConvertUTF.h | 24 +- .../llvm/include/llvm/Support/DataTypes.h.in | 10 +- contrib/llvm/include/llvm/Support/Debug.h | 4 +- contrib/llvm/include/llvm/Support/DebugLoc.h | 4 +- contrib/llvm/include/llvm/Support/Dwarf.h | 252 +- contrib/llvm/include/llvm/Support/ELF.h | 289 +- contrib/llvm/include/llvm/Support/ErrorOr.h | 266 +- .../llvm/include/llvm/Support/FileSystem.h | 390 +- .../llvm/include/llvm/Support/FileUtilities.h | 4 +- .../include/llvm/Support/FormattedStream.h | 47 +- contrib/llvm/include/llvm/Support/GCOV.h | 105 +- .../llvm/Support/GetElementPtrTypeIterator.h | 2 +- .../llvm/include/llvm/Support/GraphWriter.h | 44 +- contrib/llvm/include/llvm/Support/Host.h | 4 +- .../include/llvm/Support/IntegersSubset.h | 540 - .../llvm/Support/IntegersSubsetMapping.h | 588 -- contrib/llvm/include/llvm/Support/LEB128.h | 18 +- contrib/llvm/include/llvm/Support/MD5.h | 71 + contrib/llvm/include/llvm/Support/MachO.h | 823 +- .../llvm/include/llvm/Support/ManagedStatic.h | 1 - .../llvm/include/llvm/Support/MathExtras.h | 361 +- .../llvm/include/llvm/Support/MemoryBuffer.h | 31 +- .../llvm/include/llvm/Support/MemoryObject.h | 11 +- .../include/llvm/Support/PassNameParser.h | 13 +- contrib/llvm/include/llvm/Support/Path.h | 381 +- contrib/llvm/include/llvm/Support/PathV1.h | 743 -- contrib/llvm/include/llvm/Support/PathV2.h | 381 - .../llvm/include/llvm/Support/PatternMatch.h | 21 +- .../include/llvm/Support/PrettyStackTrace.h | 10 +- contrib/llvm/include/llvm/Support/Process.h | 40 +- contrib/llvm/include/llvm/Support/Program.h | 212 +- .../include/llvm/Support/RecyclingAllocator.h | 8 +- contrib/llvm/include/llvm/Support/Regex.h | 4 + contrib/llvm/include/llvm/Support/Registry.h | 2 + contrib/llvm/include/llvm/Support/Signals.h | 4 +- contrib/llvm/include/llvm/Support/Solaris.h | 9 + contrib/llvm/include/llvm/Support/SourceMgr.h | 22 +- .../llvm/Support/StreamableMemoryObject.h | 18 +- .../llvm/Support/StringRefMemoryObject.h | 41 + .../llvm/include/llvm/Support/SystemUtils.h | 10 - .../include/llvm/Support/TargetRegistry.h | 242 +- contrib/llvm/include/llvm/Support/TimeValue.h | 5 +- .../include/llvm/Support/ToolOutputFile.h | 4 +- contrib/llvm/include/llvm/Support/Unicode.h | 62 + .../include/llvm/Support/UnicodeCharRanges.h | 96 + contrib/llvm/include/llvm/Support/Valgrind.h | 4 +- .../llvm/include/llvm/Support/ValueHandle.h | 5 +- .../llvm/include/llvm/Support/YAMLParser.h | 84 +- .../llvm/include/llvm/Support/YAMLTraits.h | 56 +- .../llvm/include/llvm/Support/raw_ostream.h | 19 +- contrib/llvm/include/llvm/TableGen/Record.h | 82 +- .../llvm}/TableGen/StringToOffsetTable.h | 0 .../include/llvm/TableGen/TableGenBackend.h | 2 +- contrib/llvm/include/llvm/Target/CostTable.h | 35 +- contrib/llvm/include/llvm/Target/Mangler.h | 23 +- contrib/llvm/include/llvm/Target/Target.td | 63 +- .../include/llvm/Target/TargetCallingConv.h | 8 +- .../include/llvm/Target/TargetCallingConv.td | 6 + .../include/llvm/Target/TargetFrameLowering.h | 5 + .../include/llvm/Target/TargetInstrInfo.h | 73 +- .../include/llvm/Target/TargetLibraryInfo.h | 31 +- .../llvm/include/llvm/Target/TargetLowering.h | 1500 +-- .../llvm/Target/TargetLoweringObjectFile.h | 8 + .../llvm/include/llvm/Target/TargetMachine.h | 21 +- .../llvm/include/llvm/Target/TargetOpcodes.h | 19 +- .../llvm/include/llvm/Target/TargetOptions.h | 60 +- .../include/llvm/Target/TargetRegisterInfo.h | 45 +- .../include/llvm/Target/TargetSchedule.td | 20 +- .../include/llvm/Target/TargetSelectionDAG.td | 4 + .../llvm/Target/TargetSelectionDAGInfo.h | 74 +- .../include/llvm/Target/TargetSubtargetInfo.h | 18 + contrib/llvm/include/llvm/Transforms/IPO.h | 10 +- .../llvm/Transforms/IPO/PassManagerBuilder.h | 17 +- .../include/llvm/Transforms/Instrumentation.h | 67 +- contrib/llvm/include/llvm/Transforms/Scalar.h | 61 +- .../llvm/Transforms/Utils/BasicBlockUtils.h | 31 +- .../include/llvm/Transforms/Utils/BlackList.h | 59 - .../include/llvm/Transforms/Utils/Cloning.h | 3 +- .../llvm/Transforms/Utils/GlobalStatus.h | 82 + .../include/llvm/Transforms/Utils/Local.h | 43 +- .../include/llvm/Transforms/Utils/LoopUtils.h | 26 + .../llvm/Transforms/Utils/ModuleUtils.h | 8 + .../llvm/Transforms/Utils/PromoteMemToReg.h | 24 +- .../llvm/Transforms/Utils/SSAUpdater.h | 104 +- .../llvm/Transforms/Utils/SpecialCaseList.h | 110 + .../Transforms/Utils/UnifyFunctionExitNodes.h | 2 +- .../llvm/Transforms/Utils/ValueMapper.h | 31 +- .../llvm/include/llvm/Transforms/Vectorize.h | 2 +- contrib/llvm/lib/Analysis/AliasAnalysis.cpp | 47 +- contrib/llvm/lib/Analysis/AliasSetTracker.cpp | 2 - contrib/llvm/lib/Analysis/Analysis.cpp | 11 +- .../llvm/lib/Analysis/BasicAliasAnalysis.cpp | 122 +- .../llvm/lib/Analysis/BlockFrequencyInfo.cpp | 118 +- .../lib/Analysis/BranchProbabilityInfo.cpp | 115 +- contrib/llvm/lib/Analysis/CFG.cpp | 245 + contrib/llvm/lib/Analysis/CaptureTracking.cpp | 8 +- contrib/llvm/lib/Analysis/ConstantFolding.cpp | 228 +- contrib/llvm/lib/Analysis/CostModel.cpp | 289 +- contrib/llvm/lib/Analysis/Delinearization.cpp | 133 + .../llvm/lib/Analysis/DependenceAnalysis.cpp | 85 +- contrib/llvm/lib/Analysis/IPA/CallGraph.cpp | 230 +- .../lib/Analysis/IPA/CallGraphSCCPass.cpp | 2 +- .../llvm/lib/Analysis/IPA/GlobalsModRef.cpp | 2 +- contrib/llvm/lib/Analysis/IPA/IPA.cpp | 3 +- contrib/llvm/lib/Analysis/IPA/InlineCost.cpp | 159 +- .../llvm/lib/Analysis/InstructionSimplify.cpp | 46 +- contrib/llvm/lib/Analysis/LazyValueInfo.cpp | 8 +- contrib/llvm/lib/Analysis/Lint.cpp | 42 +- contrib/llvm/lib/Analysis/LoopInfo.cpp | 97 +- contrib/llvm/lib/Analysis/LoopPass.cpp | 4 + contrib/llvm/lib/Analysis/MemoryBuiltins.cpp | 114 +- .../lib/Analysis/MemoryDependenceAnalysis.cpp | 15 +- contrib/llvm/lib/Analysis/PathNumbering.cpp | 521 - contrib/llvm/lib/Analysis/PathProfileInfo.cpp | 433 - .../llvm/lib/Analysis/PathProfileVerifier.cpp | 206 - .../llvm/lib/Analysis/ProfileDataLoader.cpp | 155 - .../lib/Analysis/ProfileDataLoaderPass.cpp | 188 - .../lib/Analysis/ProfileEstimatorPass.cpp | 426 - contrib/llvm/lib/Analysis/ProfileInfo.cpp | 1079 -- .../llvm/lib/Analysis/ProfileInfoLoader.cpp | 155 - .../lib/Analysis/ProfileInfoLoaderPass.cpp | 267 - .../llvm/lib/Analysis/ProfileVerifierPass.cpp | 383 - contrib/llvm/lib/Analysis/RegionInfo.cpp | 6 +- contrib/llvm/lib/Analysis/ScalarEvolution.cpp | 1112 ++- .../lib/Analysis/ScalarEvolutionExpander.cpp | 145 +- .../Analysis/ScalarEvolutionNormalization.cpp | 18 +- .../llvm/lib/Analysis/TargetTransformInfo.cpp | 76 +- .../lib/Analysis/TypeBasedAliasAnalysis.cpp | 116 +- contrib/llvm/lib/Analysis/ValueTracking.cpp | 88 +- contrib/llvm/lib/Archive/Archive.cpp | 262 - contrib/llvm/lib/Archive/ArchiveInternals.h | 88 - contrib/llvm/lib/Archive/ArchiveReader.cpp | 633 -- contrib/llvm/lib/Archive/ArchiveWriter.cpp | 489 - contrib/llvm/lib/AsmParser/LLLexer.cpp | 9 +- contrib/llvm/lib/AsmParser/LLParser.cpp | 87 +- contrib/llvm/lib/AsmParser/LLParser.h | 4 +- contrib/llvm/lib/AsmParser/LLToken.h | 9 +- contrib/llvm/lib/AsmParser/Parser.cpp | 2 +- .../llvm/lib/Bitcode/Reader/BitcodeReader.cpp | 928 +- .../llvm/lib/Bitcode/Reader/BitcodeReader.h | 104 +- .../lib/Bitcode/Reader/BitstreamReader.cpp | 13 +- contrib/llvm/lib/Bitcode/Writer/BitWriter.cpp | 2 +- .../llvm/lib/Bitcode/Writer/BitcodeWriter.cpp | 226 +- .../lib/Bitcode/Writer/ValueEnumerator.cpp | 5 + .../llvm/lib/Bitcode/Writer/ValueEnumerator.h | 2 +- .../lib/CodeGen/AggressiveAntiDepBreaker.cpp | 6 +- contrib/llvm/lib/CodeGen/Analysis.cpp | 475 +- .../lib/CodeGen/AsmPrinter/ARMException.cpp | 18 +- .../lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 418 +- .../CodeGen/AsmPrinter/AsmPrinterDwarf.cpp | 49 +- .../AsmPrinter/AsmPrinterInlineAsm.cpp | 4 +- contrib/llvm/lib/CodeGen/AsmPrinter/DIE.cpp | 137 +- contrib/llvm/lib/CodeGen/AsmPrinter/DIE.h | 174 +- .../llvm/lib/CodeGen/AsmPrinter/DIEHash.cpp | 507 + contrib/llvm/lib/CodeGen/AsmPrinter/DIEHash.h | 147 + .../CodeGen/AsmPrinter/DwarfAccelTable.cpp | 87 +- .../lib/CodeGen/AsmPrinter/DwarfAccelTable.h | 124 +- .../CodeGen/AsmPrinter/DwarfCFIException.cpp | 2 +- .../CodeGen/AsmPrinter/DwarfCompileUnit.cpp | 1456 +-- .../lib/CodeGen/AsmPrinter/DwarfCompileUnit.h | 337 +- .../lib/CodeGen/AsmPrinter/DwarfDebug.cpp | 1668 ++-- .../llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h | 268 +- .../lib/CodeGen/AsmPrinter/DwarfException.h | 4 +- .../lib/CodeGen/BasicTargetTransformInfo.cpp | 90 +- contrib/llvm/lib/CodeGen/BranchFolding.cpp | 19 +- contrib/llvm/lib/CodeGen/BranchFolding.h | 6 +- contrib/llvm/lib/CodeGen/CalcSpillWeights.cpp | 41 +- contrib/llvm/lib/CodeGen/CallingConvLower.cpp | 2 +- contrib/llvm/lib/CodeGen/CodeGen.cpp | 2 - .../lib/CodeGen/CriticalAntiDepBreaker.cpp | 8 +- .../llvm/lib/CodeGen/CriticalAntiDepBreaker.h | 2 +- contrib/llvm/lib/CodeGen/DFAPacketizer.cpp | 3 +- .../CodeGen/DeadMachineInstructionElim.cpp | 4 +- contrib/llvm/lib/CodeGen/DwarfEHPrepare.cpp | 16 +- contrib/llvm/lib/CodeGen/ExecutionDepsFix.cpp | 127 +- .../llvm/lib/CodeGen/ExpandPostRAPseudos.cpp | 2 +- contrib/llvm/lib/CodeGen/IfConversion.cpp | 229 +- contrib/llvm/lib/CodeGen/InlineSpiller.cpp | 222 +- .../llvm/lib/CodeGen/InterferenceCache.cpp | 8 +- contrib/llvm/lib/CodeGen/InterferenceCache.h | 2 +- .../llvm/lib/CodeGen/IntrinsicLowering.cpp | 5 +- .../llvm/lib/CodeGen/LLVMTargetMachine.cpp | 50 +- contrib/llvm/lib/CodeGen/LexicalScopes.cpp | 10 +- .../llvm/lib/CodeGen/LiveDebugVariables.cpp | 92 +- contrib/llvm/lib/CodeGen/LiveDebugVariables.h | 4 +- contrib/llvm/lib/CodeGen/LiveInterval.cpp | 401 +- .../llvm/lib/CodeGen/LiveIntervalAnalysis.cpp | 283 +- contrib/llvm/lib/CodeGen/LiveRangeCalc.cpp | 56 +- contrib/llvm/lib/CodeGen/LiveRangeCalc.h | 38 +- contrib/llvm/lib/CodeGen/LiveRangeEdit.cpp | 246 +- contrib/llvm/lib/CodeGen/LiveRegMatrix.cpp | 6 +- contrib/llvm/lib/CodeGen/LiveRegUnits.cpp | 111 + contrib/llvm/lib/CodeGen/LiveVariables.cpp | 37 +- .../llvm/lib/CodeGen/MachineBasicBlock.cpp | 8 +- .../lib/CodeGen/MachineBlockFrequencyInfo.cpp | 5 - .../lib/CodeGen/MachineBlockPlacement.cpp | 26 +- contrib/llvm/lib/CodeGen/MachineCSE.cpp | 8 +- .../lib/CodeGen/MachineCopyPropagation.cpp | 5 +- contrib/llvm/lib/CodeGen/MachineFunction.cpp | 57 +- contrib/llvm/lib/CodeGen/MachineInstr.cpp | 65 +- contrib/llvm/lib/CodeGen/MachineLICM.cpp | 20 +- .../llvm/lib/CodeGen/MachineModuleInfo.cpp | 7 +- .../llvm/lib/CodeGen/MachineRegisterInfo.cpp | 56 +- .../llvm/lib/CodeGen/MachineSSAUpdater.cpp | 2 +- contrib/llvm/lib/CodeGen/MachineScheduler.cpp | 1456 ++- contrib/llvm/lib/CodeGen/MachineSink.cpp | 38 +- .../llvm/lib/CodeGen/MachineTraceMetrics.cpp | 10 +- contrib/llvm/lib/CodeGen/MachineVerifier.cpp | 418 +- contrib/llvm/lib/CodeGen/PHIElimination.cpp | 30 +- .../llvm/lib/CodeGen/PHIEliminationUtils.h | 2 +- contrib/llvm/lib/CodeGen/Passes.cpp | 31 +- .../llvm/lib/CodeGen/PeepholeOptimizer.cpp | 250 +- .../llvm/lib/CodeGen/PostRASchedulerList.cpp | 47 +- .../llvm/lib/CodeGen/ProcessImplicitDefs.cpp | 2 +- .../llvm/lib/CodeGen/PrologEpilogInserter.cpp | 430 +- .../llvm/lib/CodeGen/PrologEpilogInserter.h | 103 +- contrib/llvm/lib/CodeGen/RegAllocBase.cpp | 16 +- contrib/llvm/lib/CodeGen/RegAllocBase.h | 7 +- contrib/llvm/lib/CodeGen/RegAllocBasic.cpp | 18 +- contrib/llvm/lib/CodeGen/RegAllocFast.cpp | 60 +- contrib/llvm/lib/CodeGen/RegAllocGreedy.cpp | 199 +- contrib/llvm/lib/CodeGen/RegAllocPBQP.cpp | 64 +- .../llvm/lib/CodeGen/RegisterClassInfo.cpp | 32 + .../llvm/lib/CodeGen/RegisterCoalescer.cpp | 249 +- contrib/llvm/lib/CodeGen/RegisterPressure.cpp | 496 +- .../llvm/lib/CodeGen/RegisterScavenging.cpp | 19 +- contrib/llvm/lib/CodeGen/ScheduleDAG.cpp | 10 +- .../llvm/lib/CodeGen/ScheduleDAGInstrs.cpp | 139 +- .../lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 2537 +++-- .../lib/CodeGen/SelectionDAG/FastISel.cpp | 85 +- .../SelectionDAG/FunctionLoweringInfo.cpp | 46 +- .../lib/CodeGen/SelectionDAG/InstrEmitter.cpp | 48 +- .../lib/CodeGen/SelectionDAG/InstrEmitter.h | 2 +- .../lib/CodeGen/SelectionDAG/LegalizeDAG.cpp | 581 +- .../SelectionDAG/LegalizeFloatTypes.cpp | 225 +- .../SelectionDAG/LegalizeIntegerTypes.cpp | 399 +- .../CodeGen/SelectionDAG/LegalizeTypes.cpp | 80 +- .../lib/CodeGen/SelectionDAG/LegalizeTypes.h | 39 +- .../SelectionDAG/LegalizeTypesGeneric.cpp | 123 +- .../SelectionDAG/LegalizeVectorOps.cpp | 78 +- .../SelectionDAG/LegalizeVectorTypes.cpp | 532 +- .../SelectionDAG/ResourcePriorityQueue.cpp | 21 +- .../lib/CodeGen/SelectionDAG/SDNodeOrdering.h | 56 - .../CodeGen/SelectionDAG/ScheduleDAGFast.cpp | 12 +- .../SelectionDAG/ScheduleDAGRRList.cpp | 33 +- .../SelectionDAG/ScheduleDAGSDNodes.cpp | 39 +- .../lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 859 +- .../SelectionDAG/SelectionDAGBuilder.cpp | 1801 ++-- .../SelectionDAG/SelectionDAGBuilder.h | 272 +- .../SelectionDAG/SelectionDAGDumper.cpp | 19 +- .../CodeGen/SelectionDAG/SelectionDAGISel.cpp | 347 +- .../CodeGen/SelectionDAG/TargetLowering.cpp | 156 +- contrib/llvm/lib/CodeGen/ShrinkWrapping.cpp | 1152 --- contrib/llvm/lib/CodeGen/SjLjEHPrepare.cpp | 218 +- contrib/llvm/lib/CodeGen/SpillPlacement.cpp | 159 +- contrib/llvm/lib/CodeGen/SpillPlacement.h | 7 +- contrib/llvm/lib/CodeGen/Spiller.cpp | 33 +- contrib/llvm/lib/CodeGen/SplitKit.cpp | 63 +- contrib/llvm/lib/CodeGen/SplitKit.h | 4 +- contrib/llvm/lib/CodeGen/StackColoring.cpp | 40 +- contrib/llvm/lib/CodeGen/StackMaps.cpp | 314 + contrib/llvm/lib/CodeGen/StackProtector.cpp | 485 +- .../llvm/lib/CodeGen/StackSlotColoring.cpp | 100 +- .../llvm/lib/CodeGen/StrongPHIElimination.cpp | 825 -- contrib/llvm/lib/CodeGen/TailDuplication.cpp | 38 +- contrib/llvm/lib/CodeGen/TargetInstrInfo.cpp | 80 +- .../llvm/lib/CodeGen/TargetLoweringBase.cpp | 67 +- .../CodeGen/TargetLoweringObjectFileImpl.cpp | 48 +- .../llvm/lib/CodeGen/TargetOptionsImpl.cpp | 31 +- .../llvm/lib/CodeGen/TargetRegisterInfo.cpp | 18 +- contrib/llvm/lib/CodeGen/TargetSchedule.cpp | 73 +- .../lib/CodeGen/TwoAddressInstructionPass.cpp | 6 +- .../llvm/lib/CodeGen/UnreachableBlockElim.cpp | 4 - contrib/llvm/lib/CodeGen/VirtRegMap.cpp | 46 +- .../DWARFAbbreviationDeclaration.cpp | 76 +- .../DebugInfo/DWARFAbbreviationDeclaration.h | 29 +- contrib/llvm/lib/DebugInfo/DWARFAttribute.h | 30 - .../llvm/lib/DebugInfo/DWARFCompileUnit.cpp | 258 +- contrib/llvm/lib/DebugInfo/DWARFCompileUnit.h | 125 +- contrib/llvm/lib/DebugInfo/DWARFContext.cpp | 327 +- contrib/llvm/lib/DebugInfo/DWARFContext.h | 93 +- .../lib/DebugInfo/DWARFDebugArangeSet.cpp | 49 - .../llvm/lib/DebugInfo/DWARFDebugArangeSet.h | 5 - .../llvm/lib/DebugInfo/DWARFDebugAranges.cpp | 206 +- .../llvm/lib/DebugInfo/DWARFDebugAranges.h | 92 +- .../lib/DebugInfo/DWARFDebugInfoEntry.cpp | 311 +- .../llvm/lib/DebugInfo/DWARFDebugInfoEntry.h | 90 +- contrib/llvm/lib/DebugInfo/DWARFDebugLine.cpp | 2 +- contrib/llvm/lib/DebugInfo/DWARFDebugLoc.cpp | 74 + contrib/llvm/lib/DebugInfo/DWARFDebugLoc.h | 60 + contrib/llvm/lib/DebugInfo/DWARFFormValue.cpp | 310 +- contrib/llvm/lib/DebugInfo/DWARFTypeUnit.cpp | 39 + contrib/llvm/lib/DebugInfo/DWARFTypeUnit.h | 35 + contrib/llvm/lib/DebugInfo/DWARFUnit.cpp | 365 + contrib/llvm/lib/DebugInfo/DWARFUnit.h | 168 + .../lib/ExecutionEngine/ExecutionEngine.cpp | 63 +- .../ExecutionEngineBindings.cpp | 111 +- .../IntelJITEvents/IntelJITEventsWrapper.h | 2 +- .../ExecutionEngine/Interpreter/Execution.cpp | 746 +- .../Interpreter/ExternalFunctions.cpp | 31 +- .../ExecutionEngine/Interpreter/Interpreter.h | 6 + contrib/llvm/lib/ExecutionEngine/JIT/JIT.cpp | 156 - .../ExecutionEngine/JIT/JITDwarfEmitter.cpp | 596 -- .../lib/ExecutionEngine/JIT/JITDwarfEmitter.h | 77 - .../lib/ExecutionEngine/JIT/JITEmitter.cpp | 52 +- .../ExecutionEngine/JIT/JITMemoryManager.cpp | 44 +- .../llvm/lib/ExecutionEngine/MCJIT/MCJIT.cpp | 296 +- .../llvm/lib/ExecutionEngine/MCJIT/MCJIT.h | 244 +- .../MCJIT/SectionMemoryManager.cpp | 112 +- .../OProfileJIT/OProfileJITEventListener.cpp | 66 + .../OProfileJIT/OProfileWrapper.cpp | 17 +- .../ExecutionEngine/RTDyldMemoryManager.cpp | 282 + .../RuntimeDyld/JITRegistrar.h | 1 + .../RuntimeDyld/ObjectImageCommon.h | 1 + .../RuntimeDyld/RuntimeDyld.cpp | 220 +- .../RuntimeDyld/RuntimeDyldELF.cpp | 462 +- .../RuntimeDyld/RuntimeDyldELF.h | 55 +- .../RuntimeDyld/RuntimeDyldImpl.h | 104 +- .../RuntimeDyld/RuntimeDyldMachO.cpp | 172 +- .../RuntimeDyld/RuntimeDyldMachO.h | 32 +- .../llvm/lib/ExecutionEngine/TargetSelect.cpp | 8 + contrib/llvm/lib/IR/AsmWriter.cpp | 137 +- contrib/llvm/lib/IR/AsmWriter.h | 118 + contrib/llvm/lib/IR/AttributeImpl.h | 220 +- contrib/llvm/lib/IR/Attributes.cpp | 153 +- contrib/llvm/lib/IR/AutoUpgrade.cpp | 118 +- contrib/llvm/lib/IR/ConstantFold.cpp | 93 +- contrib/llvm/lib/IR/Constants.cpp | 66 +- contrib/llvm/lib/IR/Core.cpp | 118 +- contrib/llvm/lib/IR/DIBuilder.cpp | 589 +- contrib/llvm/lib/IR/DataLayout.cpp | 26 +- contrib/llvm/lib/IR/DebugInfo.cpp | 803 +- contrib/llvm/lib/IR/Function.cpp | 56 +- contrib/llvm/lib/IR/GCOV.cpp | 297 +- contrib/llvm/lib/IR/Globals.cpp | 16 +- contrib/llvm/lib/IR/Instruction.cpp | 25 +- contrib/llvm/lib/IR/Instructions.cpp | 369 +- contrib/llvm/lib/IR/LLVMContextImpl.h | 5 + contrib/llvm/lib/IR/LegacyPassManager.cpp | 1920 ++++ contrib/llvm/lib/IR/Metadata.cpp | 8 +- contrib/llvm/lib/IR/Module.cpp | 75 +- contrib/llvm/lib/IR/PassManager.cpp | 1985 +--- contrib/llvm/lib/IR/PassRegistry.cpp | 21 +- contrib/llvm/lib/IR/Type.cpp | 6 +- contrib/llvm/lib/IR/TypeFinder.cpp | 31 +- contrib/llvm/lib/IR/Value.cpp | 74 +- contrib/llvm/lib/IR/ValueTypes.cpp | 10 + contrib/llvm/lib/IR/Verifier.cpp | 439 +- contrib/llvm/lib/IRReader/IRReader.cpp | 40 +- contrib/llvm/lib/LTO/LTOCodeGenerator.cpp | 521 + contrib/llvm/lib/LTO/LTOModule.cpp | 794 ++ contrib/llvm/lib/Linker/LinkModules.cpp | 168 +- contrib/llvm/lib/MC/ELFObjectWriter.cpp | 76 +- contrib/llvm/lib/MC/MCAsmBackend.cpp | 4 +- contrib/llvm/lib/MC/MCAsmInfo.cpp | 15 +- contrib/llvm/lib/MC/MCAsmInfoCOFF.cpp | 1 - contrib/llvm/lib/MC/MCAsmInfoDarwin.cpp | 2 - contrib/llvm/lib/MC/MCAsmInfoELF.cpp | 23 + contrib/llvm/lib/MC/MCAsmStreamer.cpp | 310 +- contrib/llvm/lib/MC/MCAssembler.cpp | 17 +- contrib/llvm/lib/MC/MCAtom.cpp | 123 +- contrib/llvm/lib/MC/MCContext.cpp | 84 +- contrib/llvm/lib/MC/MCDisassembler.cpp | 42 + .../lib/MC/MCDisassembler/Disassembler.cpp | 171 +- .../llvm/lib/MC/MCDisassembler/Disassembler.h | 9 + contrib/llvm/lib/MC/MCDwarf.cpp | 210 +- contrib/llvm/lib/MC/MCELF.cpp | 7 +- .../llvm/lib/MC/MCELFObjectTargetWriter.cpp | 18 +- contrib/llvm/lib/MC/MCELFStreamer.cpp | 122 +- contrib/llvm/lib/MC/MCExpr.cpp | 205 +- contrib/llvm/lib/MC/MCExternalSymbolizer.cpp | 181 + contrib/llvm/lib/MC/MCFunction.cpp | 81 + contrib/llvm/lib/MC/MCInstPrinter.cpp | 65 +- contrib/llvm/lib/MC/MCInstrAnalysis.cpp | 9 +- contrib/llvm/lib/MC/MCMachOStreamer.cpp | 36 +- contrib/llvm/lib/MC/MCModule.cpp | 125 +- contrib/llvm/lib/MC/MCModuleYAML.cpp | 461 + contrib/llvm/lib/MC/MCNullStreamer.cpp | 20 +- contrib/llvm/lib/MC/MCObjectDisassembler.cpp | 584 ++ contrib/llvm/lib/MC/MCObjectFileInfo.cpp | 41 +- contrib/llvm/lib/MC/MCObjectStreamer.cpp | 48 +- contrib/llvm/lib/MC/MCObjectSymbolizer.cpp | 310 + contrib/llvm/lib/MC/MCParser/AsmLexer.cpp | 58 +- contrib/llvm/lib/MC/MCParser/AsmParser.cpp | 1658 ++-- .../llvm/lib/MC/MCParser/COFFAsmParser.cpp | 284 +- .../llvm/lib/MC/MCParser/DarwinAsmParser.cpp | 43 +- contrib/llvm/lib/MC/MCParser/ELFAsmParser.cpp | 121 +- contrib/llvm/lib/MC/MCPureStreamer.cpp | 20 +- contrib/llvm/lib/MC/MCRegisterInfo.cpp | 12 + contrib/llvm/lib/MC/MCRelocationInfo.cpp | 39 + contrib/llvm/lib/MC/MCSectionCOFF.cpp | 24 +- contrib/llvm/lib/MC/MCSectionELF.cpp | 57 +- contrib/llvm/lib/MC/MCStreamer.cpp | 149 +- contrib/llvm/lib/MC/MCSubtargetInfo.cpp | 9 +- contrib/llvm/lib/MC/MCSymbol.cpp | 17 +- contrib/llvm/lib/MC/MCSymbolizer.cpp | 20 + contrib/llvm/lib/MC/MCWin64EH.cpp | 50 +- contrib/llvm/lib/MC/MachObjectWriter.cpp | 117 +- contrib/llvm/lib/MC/SubtargetFeature.cpp | 8 +- contrib/llvm/lib/MC/WinCOFFObjectWriter.cpp | 106 +- contrib/llvm/lib/MC/WinCOFFStreamer.cpp | 27 +- contrib/llvm/lib/Object/Archive.cpp | 279 +- contrib/llvm/lib/Object/Binary.cpp | 57 +- contrib/llvm/lib/Object/COFFObjectFile.cpp | 438 +- contrib/llvm/lib/Object/COFFYAML.cpp | 281 + contrib/llvm/lib/Object/ELF.cpp | 714 ++ contrib/llvm/lib/Object/ELFObjectFile.cpp | 5 +- contrib/llvm/lib/Object/ELFYAML.cpp | 338 + contrib/llvm/lib/Object/Error.cpp | 10 +- contrib/llvm/lib/Object/MachOObjectFile.cpp | 897 +- contrib/llvm/lib/Object/MachOUniversal.cpp | 139 + contrib/llvm/lib/Object/Object.cpp | 5 +- contrib/llvm/lib/Object/ObjectFile.cpp | 66 +- contrib/llvm/lib/Object/YAML.cpp | 68 + contrib/llvm/lib/Option/ArgList.cpp | 15 + contrib/llvm/lib/Option/OptTable.cpp | 111 +- contrib/llvm/lib/Option/Option.cpp | 53 +- contrib/llvm/lib/Support/APFloat.cpp | 696 +- contrib/llvm/lib/Support/APInt.cpp | 62 +- contrib/llvm/lib/Support/Allocator.cpp | 7 +- contrib/llvm/lib/Support/BlockFrequency.cpp | 150 +- contrib/llvm/lib/Support/CommandLine.cpp | 352 +- contrib/llvm/lib/Support/Compression.cpp | 7 + contrib/llvm/lib/Support/ConstantRange.cpp | 21 +- .../llvm/lib/Support/ConvertUTFWrapper.cpp | 55 + .../llvm/lib/Support/CrashRecoveryContext.cpp | 44 +- contrib/llvm/lib/Support/DataStream.cpp | 15 +- contrib/llvm/lib/Support/Disassembler.cpp | 10 +- contrib/llvm/lib/Support/Dwarf.cpp | 62 +- contrib/llvm/lib/Support/DynamicLibrary.cpp | 41 +- contrib/llvm/lib/Support/Errno.cpp | 33 +- contrib/llvm/lib/Support/ErrorHandling.cpp | 22 + contrib/llvm/lib/Support/FileOutputBuffer.cpp | 29 +- contrib/llvm/lib/Support/FileUtilities.cpp | 33 +- contrib/llvm/lib/Support/FormattedStream.cpp | 45 +- contrib/llvm/lib/Support/GraphWriter.cpp | 71 +- contrib/llvm/lib/Support/Host.cpp | 217 +- contrib/llvm/lib/Support/Locale.cpp | 33 +- contrib/llvm/lib/Support/LocaleGeneric.inc | 17 - contrib/llvm/lib/Support/LocaleWindows.inc | 15 - contrib/llvm/lib/Support/LocaleXlocale.inc | 61 - contrib/llvm/lib/Support/LockFileManager.cpp | 31 +- contrib/llvm/lib/Support/MD5.cpp | 286 + contrib/llvm/lib/Support/MemoryBuffer.cpp | 132 +- contrib/llvm/lib/Support/MemoryObject.cpp | 6 +- contrib/llvm/lib/Support/Path.cpp | 1132 ++- contrib/llvm/lib/Support/PathV2.cpp | 949 -- contrib/llvm/lib/Support/PrettyStackTrace.cpp | 58 +- contrib/llvm/lib/Support/Process.cpp | 18 + contrib/llvm/lib/Support/Program.cpp | 51 +- contrib/llvm/lib/Support/Regex.cpp | 9 +- contrib/llvm/lib/Support/SmallPtrSet.cpp | 9 +- contrib/llvm/lib/Support/SourceMgr.cpp | 21 +- .../lib/Support/StreamableMemoryObject.cpp | 11 +- contrib/llvm/lib/Support/StringRef.cpp | 31 +- .../lib/Support/StringRefMemoryObject.cpp | 29 + contrib/llvm/lib/Support/SystemUtils.cpp | 22 - contrib/llvm/lib/Support/TargetRegistry.cpp | 6 +- contrib/llvm/lib/Support/ThreadLocal.cpp | 2 +- contrib/llvm/lib/Support/Timer.cpp | 4 +- contrib/llvm/lib/Support/ToolOutputFile.cpp | 20 +- contrib/llvm/lib/Support/Triple.cpp | 27 +- contrib/llvm/lib/Support/Unicode.cpp | 367 + contrib/llvm/lib/Support/Unix/Memory.inc | 7 + contrib/llvm/lib/Support/Unix/Path.inc | 1197 ++- contrib/llvm/lib/Support/Unix/PathV2.inc | 693 -- contrib/llvm/lib/Support/Unix/Process.inc | 119 +- contrib/llvm/lib/Support/Unix/Program.inc | 217 +- contrib/llvm/lib/Support/Unix/Signals.inc | 18 +- contrib/llvm/lib/Support/Unix/ThreadLocal.inc | 2 +- contrib/llvm/lib/Support/Unix/TimeValue.inc | 19 +- contrib/llvm/lib/Support/Unix/Unix.h | 14 +- .../lib/Support/Windows/DynamicLibrary.inc | 15 +- contrib/llvm/lib/Support/Windows/Memory.inc | 4 +- contrib/llvm/lib/Support/Windows/Path.inc | 1712 ++-- contrib/llvm/lib/Support/Windows/PathV2.inc | 1022 -- contrib/llvm/lib/Support/Windows/Process.inc | 116 +- contrib/llvm/lib/Support/Windows/Program.inc | 288 +- contrib/llvm/lib/Support/Windows/RWMutex.inc | 4 +- contrib/llvm/lib/Support/Windows/Signals.inc | 56 +- .../llvm/lib/Support/Windows/TimeValue.inc | 38 +- contrib/llvm/lib/Support/Windows/Windows.h | 30 +- contrib/llvm/lib/Support/YAMLParser.cpp | 111 +- contrib/llvm/lib/Support/YAMLTraits.cpp | 100 +- contrib/llvm/lib/Support/raw_ostream.cpp | 48 +- contrib/llvm/lib/TableGen/Main.cpp | 2 +- contrib/llvm/lib/TableGen/Record.cpp | 31 +- contrib/llvm/lib/TableGen/TGParser.cpp | 12 +- contrib/llvm/lib/Target/AArch64/AArch64.td | 7 +- .../lib/Target/AArch64/AArch64AsmPrinter.cpp | 172 +- .../lib/Target/AArch64/AArch64AsmPrinter.h | 4 - .../Target/AArch64/AArch64BranchFixupPass.cpp | 2 +- .../lib/Target/AArch64/AArch64CallingConv.td | 9 +- .../Target/AArch64/AArch64FrameLowering.cpp | 35 +- .../lib/Target/AArch64/AArch64FrameLowering.h | 2 +- .../Target/AArch64/AArch64ISelDAGToDAG.cpp | 1065 +- .../Target/AArch64/AArch64ISelLowering.cpp | 1814 +++- .../lib/Target/AArch64/AArch64ISelLowering.h | 147 +- .../lib/Target/AArch64/AArch64InstrFormats.td | 528 + .../lib/Target/AArch64/AArch64InstrInfo.cpp | 105 +- .../lib/Target/AArch64/AArch64InstrInfo.h | 4 - .../lib/Target/AArch64/AArch64InstrInfo.td | 87 +- .../lib/Target/AArch64/AArch64InstrNEON.td | 8671 +++++++++++++++++ .../lib/Target/AArch64/AArch64MCInstLower.cpp | 7 +- .../Target/AArch64/AArch64RegisterInfo.cpp | 7 +- .../lib/Target/AArch64/AArch64RegisterInfo.h | 7 +- .../lib/Target/AArch64/AArch64RegisterInfo.td | 176 +- .../lib/Target/AArch64/AArch64Subtarget.cpp | 28 +- .../lib/Target/AArch64/AArch64Subtarget.h | 20 +- .../Target/AArch64/AArch64TargetMachine.cpp | 1 + .../AArch64/AsmParser/AArch64AsmParser.cpp | 521 +- .../Disassembler/AArch64Disassembler.cpp | 795 +- .../InstPrinter/AArch64InstPrinter.cpp | 131 + .../AArch64/InstPrinter/AArch64InstPrinter.h | 14 +- .../MCTargetDesc/AArch64AsmBackend.cpp | 4 +- .../MCTargetDesc/AArch64ELFStreamer.cpp | 20 +- .../AArch64/MCTargetDesc/AArch64MCAsmInfo.cpp | 5 +- .../AArch64/MCTargetDesc/AArch64MCAsmInfo.h | 10 +- .../MCTargetDesc/AArch64MCCodeEmitter.cpp | 106 +- .../MCTargetDesc/AArch64MCTargetDesc.cpp | 21 +- .../MCTargetDesc/AArch64MCTargetDesc.h | 5 +- .../AArch64/TargetInfo/AArch64TargetInfo.cpp | 2 +- .../Target/AArch64/Utils/AArch64BaseInfo.cpp | 68 +- .../Target/AArch64/Utils/AArch64BaseInfo.h | 65 +- .../llvm/lib/Target/ARM/A15SDOptimizer.cpp | 13 +- contrib/llvm/lib/Target/ARM/ARM.td | 94 +- contrib/llvm/lib/Target/ARM/ARMAsmPrinter.cpp | 605 +- contrib/llvm/lib/Target/ARM/ARMAsmPrinter.h | 8 +- .../llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp | 470 +- .../llvm/lib/Target/ARM/ARMBaseInstrInfo.h | 28 +- .../lib/Target/ARM/ARMBaseRegisterInfo.cpp | 99 +- .../llvm/lib/Target/ARM/ARMBaseRegisterInfo.h | 27 +- contrib/llvm/lib/Target/ARM/ARMBuildAttrs.h | 71 +- contrib/llvm/lib/Target/ARM/ARMCallingConv.td | 26 +- .../llvm/lib/Target/ARM/ARMCodeEmitter.cpp | 6 +- .../lib/Target/ARM/ARMConstantIslandPass.cpp | 3 +- .../lib/Target/ARM/ARMConstantPoolValue.cpp | 50 +- .../lib/Target/ARM/ARMConstantPoolValue.h | 33 + .../lib/Target/ARM/ARMExpandPseudoInsts.cpp | 75 +- contrib/llvm/lib/Target/ARM/ARMFPUName.def | 32 + contrib/llvm/lib/Target/ARM/ARMFPUName.h | 26 + contrib/llvm/lib/Target/ARM/ARMFastISel.cpp | 375 +- contrib/llvm/lib/Target/ARM/ARMFeatures.h | 93 + .../llvm/lib/Target/ARM/ARMFrameLowering.cpp | 156 +- .../lib/Target/ARM/ARMHazardRecognizer.cpp | 10 +- .../llvm/lib/Target/ARM/ARMHazardRecognizer.h | 13 +- .../llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp | 562 +- .../llvm/lib/Target/ARM/ARMISelLowering.cpp | 1722 +++- contrib/llvm/lib/Target/ARM/ARMISelLowering.h | 72 +- .../llvm/lib/Target/ARM/ARMInstrFormats.td | 290 +- contrib/llvm/lib/Target/ARM/ARMInstrInfo.cpp | 34 +- contrib/llvm/lib/Target/ARM/ARMInstrInfo.td | 885 +- contrib/llvm/lib/Target/ARM/ARMInstrNEON.td | 451 +- contrib/llvm/lib/Target/ARM/ARMInstrThumb.td | 263 +- contrib/llvm/lib/Target/ARM/ARMInstrThumb2.td | 849 +- contrib/llvm/lib/Target/ARM/ARMInstrVFP.td | 348 +- .../lib/Target/ARM/ARMLoadStoreOptimizer.cpp | 115 +- .../llvm/lib/Target/ARM/ARMMCInstLower.cpp | 2 +- .../lib/Target/ARM/ARMMachineFunctionInfo.h | 78 +- .../llvm/lib/Target/ARM/ARMRegisterInfo.cpp | 5 +- contrib/llvm/lib/Target/ARM/ARMRegisterInfo.h | 6 +- .../llvm/lib/Target/ARM/ARMRegisterInfo.td | 84 +- contrib/llvm/lib/Target/ARM/ARMSchedule.td | 18 + contrib/llvm/lib/Target/ARM/ARMScheduleA9.td | 196 +- .../llvm/lib/Target/ARM/ARMScheduleSwift.td | 944 +- .../lib/Target/ARM/ARMSelectionDAGInfo.cpp | 4 +- .../llvm/lib/Target/ARM/ARMSelectionDAGInfo.h | 4 +- contrib/llvm/lib/Target/ARM/ARMSubtarget.cpp | 120 +- contrib/llvm/lib/Target/ARM/ARMSubtarget.h | 79 +- .../llvm/lib/Target/ARM/ARMTargetMachine.cpp | 15 +- .../lib/Target/ARM/ARMTargetObjectFile.cpp | 2 +- .../lib/Target/ARM/ARMTargetTransformInfo.cpp | 113 +- .../lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 1429 ++- .../ARM/Disassembler/ARMDisassembler.cpp | 817 +- .../Target/ARM/InstPrinter/ARMInstPrinter.cpp | 284 +- .../Target/ARM/InstPrinter/ARMInstPrinter.h | 4 + .../ARM/MCTargetDesc/ARMAddressingModes.h | 12 +- .../Target/ARM/MCTargetDesc/ARMAsmBackend.cpp | 53 +- .../lib/Target/ARM/MCTargetDesc/ARMBaseInfo.h | 61 +- .../ARM/MCTargetDesc/ARMELFStreamer.cpp | 735 +- .../Target/ARM/MCTargetDesc/ARMELFStreamer.h | 27 - .../Target/ARM/MCTargetDesc/ARMMCAsmInfo.cpp | 2 - .../Target/ARM/MCTargetDesc/ARMMCAsmInfo.h | 3 +- .../ARM/MCTargetDesc/ARMMCCodeEmitter.cpp | 102 +- .../ARM/MCTargetDesc/ARMMCTargetDesc.cpp | 93 +- .../Target/ARM/MCTargetDesc/ARMMCTargetDesc.h | 16 +- .../MCTargetDesc/ARMMachORelocationInfo.cpp | 43 + .../ARM/MCTargetDesc/ARMMachObjectWriter.cpp | 129 +- .../ARM/MCTargetDesc/ARMUnwindOpAsm.cpp | 157 +- .../Target/ARM/MCTargetDesc/ARMUnwindOpAsm.h | 73 +- .../lib/Target/ARM/Thumb1FrameLowering.cpp | 36 +- .../llvm/lib/Target/ARM/Thumb1InstrInfo.cpp | 2 +- .../lib/Target/ARM/Thumb1RegisterInfo.cpp | 20 +- .../llvm/lib/Target/ARM/Thumb1RegisterInfo.h | 2 +- .../llvm/lib/Target/ARM/Thumb2ITBlockPass.cpp | 71 +- .../llvm/lib/Target/ARM/Thumb2InstrInfo.cpp | 25 +- .../lib/Target/ARM/Thumb2RegisterInfo.cpp | 6 +- .../llvm/lib/Target/ARM/Thumb2RegisterInfo.h | 6 +- .../llvm/lib/Target/CppBackend/CPPBackend.cpp | 27 +- contrib/llvm/lib/Target/Hexagon/Hexagon.h | 6 +- contrib/llvm/lib/Target/Hexagon/Hexagon.td | 30 +- .../lib/Target/Hexagon/HexagonAsmPrinter.cpp | 4 +- .../Hexagon/HexagonCallingConvLower.cpp | 8 +- .../Target/Hexagon/HexagonCallingConvLower.h | 5 +- .../Target/Hexagon/HexagonCopyToCombine.cpp | 677 ++ .../Target/Hexagon/HexagonFrameLowering.cpp | 80 +- .../Target/Hexagon/HexagonHardwareLoops.cpp | 10 +- .../Target/Hexagon/HexagonISelDAGToDAG.cpp | 72 +- .../Target/Hexagon/HexagonISelLowering.cpp | 104 +- .../lib/Target/Hexagon/HexagonISelLowering.h | 17 +- .../lib/Target/Hexagon/HexagonInstrFormats.td | 5 +- .../lib/Target/Hexagon/HexagonInstrInfo.cpp | 857 +- .../lib/Target/Hexagon/HexagonInstrInfo.h | 15 +- .../lib/Target/Hexagon/HexagonInstrInfo.td | 105 +- .../lib/Target/Hexagon/HexagonInstrInfoV4.td | 265 +- .../lib/Target/Hexagon/HexagonInstrInfoV5.td | 23 +- .../lib/Target/Hexagon/HexagonMCInstLower.cpp | 2 +- .../HexagonMachineFunctionInfo.cpp} | 8 +- .../Hexagon/HexagonMachineFunctionInfo.h | 6 +- .../Hexagon/HexagonMachineScheduler.cpp | 21 +- .../Target/Hexagon/HexagonMachineScheduler.h | 5 +- .../Target/Hexagon/HexagonNewValueJump.cpp | 1 + .../lib/Target/Hexagon/HexagonPeephole.cpp | 2 +- .../Target/Hexagon/HexagonRegisterInfo.cpp | 26 +- .../lib/Target/Hexagon/HexagonRegisterInfo.h | 8 +- .../lib/Target/Hexagon/HexagonRegisterInfo.td | 4 +- .../Hexagon/HexagonSelectionDAGInfo.cpp | 2 +- .../Target/Hexagon/HexagonSelectionDAGInfo.h | 2 +- .../Hexagon/HexagonSplitConst32AndConst64.cpp | 174 + .../lib/Target/Hexagon/HexagonSubtarget.cpp | 2 + .../lib/Target/Hexagon/HexagonSubtarget.h | 2 +- .../Target/Hexagon/HexagonTargetMachine.cpp | 31 +- .../Hexagon/HexagonTargetObjectFile.cpp | 8 +- .../Target/Hexagon/HexagonTargetObjectFile.h | 1 + .../Target/Hexagon/HexagonVLIWPacketizer.cpp | 1833 +--- .../InstPrinter/HexagonInstPrinter.cpp | 15 +- .../Hexagon/MCTargetDesc/HexagonBaseInfo.h | 5 +- .../Hexagon/MCTargetDesc/HexagonMCAsmInfo.cpp | 6 +- .../Hexagon/MCTargetDesc/HexagonMCAsmInfo.h | 9 +- .../MCTargetDesc/HexagonMCTargetDesc.cpp | 11 +- .../MBlaze/AsmParser/MBlazeAsmParser.cpp | 572 -- .../Disassembler/MBlazeDisassembler.cpp | 719 -- .../MBlaze/Disassembler/MBlazeDisassembler.h | 49 - .../MBlaze/InstPrinter/MBlazeInstPrinter.cpp | 71 - .../MBlaze/InstPrinter/MBlazeInstPrinter.h | 43 - contrib/llvm/lib/Target/MBlaze/MBlaze.h | 32 - contrib/llvm/lib/Target/MBlaze/MBlaze.td | 73 - .../lib/Target/MBlaze/MBlazeAsmPrinter.cpp | 326 - .../lib/Target/MBlaze/MBlazeCallingConv.td | 24 - .../Target/MBlaze/MBlazeDelaySlotFiller.cpp | 254 - .../lib/Target/MBlaze/MBlazeFrameLowering.cpp | 488 - .../lib/Target/MBlaze/MBlazeFrameLowering.h | 56 - .../lib/Target/MBlaze/MBlazeISelDAGToDAG.cpp | 277 - .../lib/Target/MBlaze/MBlazeISelLowering.cpp | 1154 --- .../lib/Target/MBlaze/MBlazeISelLowering.h | 179 - .../llvm/lib/Target/MBlaze/MBlazeInstrFPU.td | 219 - .../llvm/lib/Target/MBlaze/MBlazeInstrFSL.td | 229 - .../lib/Target/MBlaze/MBlazeInstrFormats.td | 228 - .../lib/Target/MBlaze/MBlazeInstrInfo.cpp | 297 - .../llvm/lib/Target/MBlaze/MBlazeInstrInfo.h | 240 - .../llvm/lib/Target/MBlaze/MBlazeInstrInfo.td | 1051 -- .../lib/Target/MBlaze/MBlazeIntrinsicInfo.cpp | 112 - .../lib/Target/MBlaze/MBlazeIntrinsicInfo.h | 33 - .../lib/Target/MBlaze/MBlazeIntrinsics.td | 131 - .../lib/Target/MBlaze/MBlazeMCInstLower.cpp | 167 - .../lib/Target/MBlaze/MBlazeMCInstLower.h | 47 - .../lib/Target/MBlaze/MBlazeMachineFunction.h | 169 - .../lib/Target/MBlaze/MBlazeRegisterInfo.cpp | 145 - .../lib/Target/MBlaze/MBlazeRegisterInfo.h | 71 - .../lib/Target/MBlaze/MBlazeRegisterInfo.td | 148 - .../lib/Target/MBlaze/MBlazeRelocations.h | 47 - .../llvm/lib/Target/MBlaze/MBlazeSchedule.td | 50 - .../llvm/lib/Target/MBlaze/MBlazeSchedule3.td | 236 - .../llvm/lib/Target/MBlaze/MBlazeSchedule5.td | 267 - .../Target/MBlaze/MBlazeSelectionDAGInfo.h | 31 - .../lib/Target/MBlaze/MBlazeSubtarget.cpp | 56 - .../llvm/lib/Target/MBlaze/MBlazeSubtarget.h | 75 - .../lib/Target/MBlaze/MBlazeTargetMachine.cpp | 81 - .../lib/Target/MBlaze/MBlazeTargetMachine.h | 80 - .../Target/MBlaze/MBlazeTargetObjectFile.cpp | 90 - .../Target/MBlaze/MBlazeTargetObjectFile.h | 40 - .../MBlaze/MCTargetDesc/MBlazeAsmBackend.cpp | 171 - .../MBlaze/MCTargetDesc/MBlazeBaseInfo.h | 237 - .../MCTargetDesc/MBlazeELFObjectWriter.cpp | 77 - .../MBlaze/MCTargetDesc/MBlazeMCAsmInfo.cpp | 26 - .../MBlaze/MCTargetDesc/MBlazeMCAsmInfo.h | 30 - .../MCTargetDesc/MBlazeMCCodeEmitter.cpp | 222 - .../MCTargetDesc/MBlazeMCTargetDesc.cpp | 141 - .../MBlaze/MCTargetDesc/MBlazeMCTargetDesc.h | 56 - .../MBlaze/TargetInfo/MBlazeTargetInfo.cpp | 19 - .../MSP430/MCTargetDesc/MSP430MCAsmInfo.cpp | 5 +- .../MSP430/MCTargetDesc/MSP430MCAsmInfo.h | 7 +- .../lib/Target/MSP430/MSP430AsmPrinter.cpp | 2 +- .../lib/Target/MSP430/MSP430CallingConv.td | 7 +- .../lib/Target/MSP430/MSP430FrameLowering.h | 4 +- .../lib/Target/MSP430/MSP430ISelDAGToDAG.cpp | 9 +- .../lib/Target/MSP430/MSP430ISelLowering.cpp | 191 +- .../lib/Target/MSP430/MSP430ISelLowering.h | 13 +- .../lib/Target/MSP430/MSP430InstrInfo.cpp | 7 +- .../llvm/lib/Target/MSP430/MSP430InstrInfo.h | 1 + .../llvm/lib/Target/MSP430/MSP430InstrInfo.td | 4 +- .../lib/Target/MSP430/MSP430MCInstLower.cpp | 2 +- .../lib/Target/MSP430/MSP430RegisterInfo.cpp | 6 +- .../lib/Target/MSP430/MSP430RegisterInfo.h | 3 +- .../lib/Target/MSP430/MSP430RegisterInfo.td | 2 +- .../lib/Target/MSP430/MSP430TargetMachine.cpp | 4 +- contrib/llvm/lib/Target/Mangler.cpp | 149 +- .../Target/Mips/AsmParser/MipsAsmParser.cpp | 1572 ++- .../Mips/Disassembler/MipsDisassembler.cpp | 446 +- .../Mips/InstPrinter/MipsInstPrinter.cpp | 89 +- .../Target/Mips/InstPrinter/MipsInstPrinter.h | 9 +- .../Mips/MCTargetDesc/MipsAsmBackend.cpp | 43 +- .../Mips/MCTargetDesc/MipsDirectObjLower.cpp | 81 - .../Mips/MCTargetDesc/MipsDirectObjLower.h | 28 - .../Mips/MCTargetDesc/MipsELFObjectWriter.cpp | 39 + .../Mips/MCTargetDesc/MipsELFStreamer.cpp | 89 - .../Mips/MCTargetDesc/MipsELFStreamer.h | 43 - .../Target/Mips/MCTargetDesc/MipsFixupKinds.h | 39 + .../Mips/MCTargetDesc/MipsMCAsmInfo.cpp | 3 +- .../Target/Mips/MCTargetDesc/MipsMCAsmInfo.h | 7 +- .../Mips/MCTargetDesc/MipsMCCodeEmitter.cpp | 210 +- .../Mips/MCTargetDesc/MipsMCTargetDesc.cpp | 49 +- .../Mips/MCTargetDesc/MipsMCTargetDesc.h | 16 +- .../Mips/MCTargetDesc/MipsTargetStreamer.cpp | 67 + contrib/llvm/lib/Target/Mips/MSA.txt | 78 + .../lib/Target/Mips/MicroMipsInstrFormats.td | 196 +- .../lib/Target/Mips/MicroMipsInstrInfo.td | 228 +- contrib/llvm/lib/Target/Mips/Mips.h | 1 - contrib/llvm/lib/Target/Mips/Mips.td | 3 + .../lib/Target/Mips/Mips16FrameLowering.cpp | 26 +- .../lib/Target/Mips/Mips16FrameLowering.h | 2 +- .../llvm/lib/Target/Mips/Mips16HardFloat.cpp | 517 + .../llvm/lib/Target/Mips/Mips16HardFloat.h | 54 + .../lib/Target/Mips/Mips16ISelDAGToDAG.cpp | 21 +- .../llvm/lib/Target/Mips/Mips16ISelDAGToDAG.h | 2 +- .../lib/Target/Mips/Mips16ISelLowering.cpp | 239 +- .../llvm/lib/Target/Mips/Mips16ISelLowering.h | 4 +- .../lib/Target/Mips/Mips16InstrFormats.td | 18 +- .../llvm/lib/Target/Mips/Mips16InstrInfo.cpp | 203 +- .../llvm/lib/Target/Mips/Mips16InstrInfo.h | 15 +- .../llvm/lib/Target/Mips/Mips16InstrInfo.td | 188 +- .../lib/Target/Mips/Mips16RegisterInfo.cpp | 17 +- .../llvm/lib/Target/Mips/Mips16RegisterInfo.h | 4 +- .../llvm/lib/Target/Mips/Mips64InstrInfo.td | 440 +- .../lib/Target/Mips/MipsAnalyzeImmediate.cpp | 2 +- .../lib/Target/Mips/MipsAnalyzeImmediate.h | 10 +- .../llvm/lib/Target/Mips/MipsAsmPrinter.cpp | 141 +- contrib/llvm/lib/Target/Mips/MipsAsmPrinter.h | 25 +- .../llvm/lib/Target/Mips/MipsCallingConv.td | 30 +- .../llvm/lib/Target/Mips/MipsCodeEmitter.cpp | 40 +- contrib/llvm/lib/Target/Mips/MipsCondMov.td | 210 +- .../Target/Mips/MipsConstantIslandPass.cpp | 1470 ++- .../llvm/lib/Target/Mips/MipsDSPInstrInfo.td | 468 +- .../lib/Target/Mips/MipsDelaySlotFiller.cpp | 38 +- .../llvm/lib/Target/Mips/MipsISelDAGToDAG.cpp | 80 +- .../llvm/lib/Target/Mips/MipsISelDAGToDAG.h | 38 + .../llvm/lib/Target/Mips/MipsISelLowering.cpp | 824 +- .../llvm/lib/Target/Mips/MipsISelLowering.h | 184 +- contrib/llvm/lib/Target/Mips/MipsInstrFPU.td | 456 +- .../llvm/lib/Target/Mips/MipsInstrFormats.td | 143 +- .../llvm/lib/Target/Mips/MipsInstrInfo.cpp | 43 +- contrib/llvm/lib/Target/Mips/MipsInstrInfo.h | 16 +- contrib/llvm/lib/Target/Mips/MipsInstrInfo.td | 983 +- contrib/llvm/lib/Target/Mips/MipsJITInfo.cpp | 6 +- .../llvm/lib/Target/Mips/MipsLongBranch.cpp | 25 +- .../llvm/lib/Target/Mips/MipsMCInstLower.cpp | 5 +- .../llvm/lib/Target/Mips/MipsMCInstLower.h | 4 +- .../lib/Target/Mips/MipsMSAInstrFormats.td | 406 + .../llvm/lib/Target/Mips/MipsMSAInstrInfo.td | 3694 +++++++ .../lib/Target/Mips/MipsMachineFunction.cpp | 72 +- .../lib/Target/Mips/MipsMachineFunction.h | 103 +- contrib/llvm/lib/Target/Mips/MipsOs16.cpp | 45 +- .../llvm/lib/Target/Mips/MipsRegisterInfo.cpp | 79 +- .../llvm/lib/Target/Mips/MipsRegisterInfo.h | 8 +- .../llvm/lib/Target/Mips/MipsRegisterInfo.td | 411 +- .../lib/Target/Mips/MipsSEFrameLowering.cpp | 184 +- .../lib/Target/Mips/MipsSEFrameLowering.h | 2 +- .../lib/Target/Mips/MipsSEISelDAGToDAG.cpp | 443 +- .../llvm/lib/Target/Mips/MipsSEISelDAGToDAG.h | 48 +- .../lib/Target/Mips/MipsSEISelLowering.cpp | 2329 ++++- .../llvm/lib/Target/Mips/MipsSEISelLowering.h | 48 +- .../llvm/lib/Target/Mips/MipsSEInstrInfo.cpp | 310 +- .../llvm/lib/Target/Mips/MipsSEInstrInfo.h | 40 +- .../lib/Target/Mips/MipsSERegisterInfo.cpp | 85 +- .../llvm/lib/Target/Mips/MipsSERegisterInfo.h | 5 +- contrib/llvm/lib/Target/Mips/MipsSchedule.td | 15 +- .../llvm/lib/Target/Mips/MipsSubtarget.cpp | 34 +- contrib/llvm/lib/Target/Mips/MipsSubtarget.h | 31 +- .../lib/Target/Mips/MipsTargetMachine.cpp | 21 +- .../llvm/lib/Target/Mips/MipsTargetMachine.h | 6 + .../llvm/lib/Target/Mips/MipsTargetStreamer.h | 44 + .../NVPTX/InstPrinter/NVPTXInstPrinter.cpp | 290 +- .../NVPTX/InstPrinter/NVPTXInstPrinter.h | 53 + .../Target/NVPTX/MCTargetDesc/NVPTXBaseInfo.h | 1 - .../NVPTX/MCTargetDesc/NVPTXMCAsmInfo.cpp | 12 +- .../NVPTX/MCTargetDesc/NVPTXMCAsmInfo.h | 2 +- .../NVPTX/MCTargetDesc/NVPTXMCTargetDesc.cpp | 17 + .../llvm/lib/Target/NVPTX/ManagedStringPool.h | 2 +- contrib/llvm/lib/Target/NVPTX/NVPTX.h | 55 +- contrib/llvm/lib/Target/NVPTX/NVPTX.td | 6 + .../lib/Target/NVPTX/NVPTXAllocaHoisting.cpp | 2 +- .../llvm/lib/Target/NVPTX/NVPTXAsmPrinter.cpp | 595 +- .../llvm/lib/Target/NVPTX/NVPTXAsmPrinter.h | 27 +- .../lib/Target/NVPTX/NVPTXFrameLowering.cpp | 41 +- .../lib/Target/NVPTX/NVPTXGenericToNVVM.cpp | 4 +- .../lib/Target/NVPTX/NVPTXISelDAGToDAG.cpp | 1045 +- .../llvm/lib/Target/NVPTX/NVPTXISelDAGToDAG.h | 31 +- .../lib/Target/NVPTX/NVPTXISelLowering.cpp | 1627 +++- .../llvm/lib/Target/NVPTX/NVPTXISelLowering.h | 39 +- .../llvm/lib/Target/NVPTX/NVPTXInstrInfo.cpp | 51 +- .../llvm/lib/Target/NVPTX/NVPTXInstrInfo.h | 1 + .../llvm/lib/Target/NVPTX/NVPTXInstrInfo.td | 2114 ++-- .../llvm/lib/Target/NVPTX/NVPTXIntrinsics.td | 632 +- contrib/llvm/lib/Target/NVPTX/NVPTXMCExpr.cpp | 46 + contrib/llvm/lib/Target/NVPTX/NVPTXMCExpr.h | 83 + .../Target/NVPTX/NVPTXPrologEpilogPass.cpp | 225 + .../lib/Target/NVPTX/NVPTXRegisterInfo.cpp | 13 +- .../llvm/lib/Target/NVPTX/NVPTXRegisterInfo.h | 2 +- .../lib/Target/NVPTX/NVPTXRegisterInfo.td | 26 +- contrib/llvm/lib/Target/NVPTX/NVPTXSection.h | 4 +- .../lib/Target/NVPTX/NVPTXSplitBBatBar.cpp | 2 +- .../llvm/lib/Target/NVPTX/NVPTXSubtarget.cpp | 20 +- .../llvm/lib/Target/NVPTX/NVPTXSubtarget.h | 2 +- .../lib/Target/NVPTX/NVPTXTargetMachine.cpp | 64 +- .../lib/Target/NVPTX/NVPTXTargetObjectFile.h | 44 +- contrib/llvm/lib/Target/NVPTX/NVVMReflect.cpp | 4 +- .../Target/PowerPC/AsmParser/PPCAsmParser.cpp | 738 +- .../PowerPC/InstPrinter/PPCInstPrinter.cpp | 189 +- .../PowerPC/InstPrinter/PPCInstPrinter.h | 18 +- .../PowerPC/MCTargetDesc/PPCAsmBackend.cpp | 101 +- .../MCTargetDesc/PPCELFObjectWriter.cpp | 340 +- .../PowerPC/MCTargetDesc/PPCFixupKinds.h | 28 +- .../PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp | 9 +- .../PowerPC/MCTargetDesc/PPCMCAsmInfo.h | 3 +- .../PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp | 102 +- .../Target/PowerPC/MCTargetDesc/PPCMCExpr.cpp | 155 + .../Target/PowerPC/MCTargetDesc/PPCMCExpr.h | 96 + .../PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp | 84 +- .../PowerPC/MCTargetDesc/PPCMCTargetDesc.h | 8 +- .../MCTargetDesc/PPCMachObjectWriter.cpp | 389 + .../PowerPC/MCTargetDesc/PPCPredicates.cpp | 32 + .../PowerPC/MCTargetDesc/PPCPredicates.h | 32 +- contrib/llvm/lib/Target/PowerPC/PPC.h | 24 +- contrib/llvm/lib/Target/PowerPC/PPC.td | 66 +- .../llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp | 218 +- .../llvm/lib/Target/PowerPC/PPCCTRLoops.cpp | 1164 +-- .../llvm/lib/Target/PowerPC/PPCCallingConv.td | 70 +- .../lib/Target/PowerPC/PPCCodeEmitter.cpp | 51 +- .../llvm/lib/Target/PowerPC/PPCFastISel.cpp | 2236 +++++ .../lib/Target/PowerPC/PPCFrameLowering.cpp | 635 +- .../lib/Target/PowerPC/PPCFrameLowering.h | 10 + .../Target/PowerPC/PPCHazardRecognizers.cpp | 6 +- .../lib/Target/PowerPC/PPCHazardRecognizers.h | 4 +- .../lib/Target/PowerPC/PPCISelDAGToDAG.cpp | 111 +- .../lib/Target/PowerPC/PPCISelLowering.cpp | 1056 +- .../llvm/lib/Target/PowerPC/PPCISelLowering.h | 143 +- .../llvm/lib/Target/PowerPC/PPCInstr64Bit.td | 165 +- .../lib/Target/PowerPC/PPCInstrAltivec.td | 52 +- .../lib/Target/PowerPC/PPCInstrFormats.td | 71 +- .../llvm/lib/Target/PowerPC/PPCInstrInfo.cpp | 65 +- .../llvm/lib/Target/PowerPC/PPCInstrInfo.h | 7 +- .../llvm/lib/Target/PowerPC/PPCInstrInfo.td | 805 +- .../llvm/lib/Target/PowerPC/PPCJITInfo.cpp | 40 +- .../lib/Target/PowerPC/PPCMCInstLower.cpp | 62 +- .../Target/PowerPC/PPCMachineFunctionInfo.h | 9 +- .../lib/Target/PowerPC/PPCRegisterInfo.cpp | 264 +- .../llvm/lib/Target/PowerPC/PPCRegisterInfo.h | 11 +- .../lib/Target/PowerPC/PPCRegisterInfo.td | 20 +- .../llvm/lib/Target/PowerPC/PPCSchedule.td | 8 + .../llvm/lib/Target/PowerPC/PPCScheduleA2.td | 841 +- .../lib/Target/PowerPC/PPCScheduleE500mc.td | 2 + .../lib/Target/PowerPC/PPCScheduleE5500.td | 1 + .../llvm/lib/Target/PowerPC/PPCSubtarget.cpp | 154 +- .../llvm/lib/Target/PowerPC/PPCSubtarget.h | 28 +- .../lib/Target/PowerPC/PPCTargetMachine.cpp | 16 +- .../Target/PowerPC/PPCTargetObjectFile.cpp | 67 + .../lib/Target/PowerPC/PPCTargetObjectFile.h | 35 + .../lib/Target/PowerPC/PPCTargetStreamer.h | 23 + .../Target/PowerPC/PPCTargetTransformInfo.cpp | 9 + .../PowerPC/TargetInfo/PowerPCTargetInfo.cpp | 5 +- contrib/llvm/lib/Target/R600/AMDGPU.h | 66 +- contrib/llvm/lib/Target/R600/AMDGPU.td | 85 + .../llvm/lib/Target/R600/AMDGPUAsmPrinter.cpp | 86 +- .../llvm/lib/Target/R600/AMDGPUAsmPrinter.h | 12 +- .../llvm/lib/Target/R600/AMDGPUCallingConv.td | 46 +- .../lib/Target/R600/AMDGPUFrameLowering.cpp | 23 +- .../lib/Target/R600/AMDGPUISelDAGToDAG.cpp | 585 ++ .../lib/Target/R600/AMDGPUISelLowering.cpp | 445 +- .../llvm/lib/Target/R600/AMDGPUISelLowering.h | 56 +- .../Target/R600/AMDGPUIndirectAddressing.cpp | 343 - .../llvm/lib/Target/R600/AMDGPUInstrInfo.cpp | 140 +- .../llvm/lib/Target/R600/AMDGPUInstrInfo.h | 50 +- .../llvm/lib/Target/R600/AMDGPUInstrInfo.td | 22 +- .../lib/Target/R600/AMDGPUInstructions.td | 268 +- .../llvm/lib/Target/R600/AMDGPUIntrinsics.td | 2 + .../lib/Target/R600/AMDGPUMCInstLower.cpp | 43 +- .../lib/Target/R600/AMDGPUMachineFunction.cpp | 9 +- .../lib/Target/R600/AMDGPUMachineFunction.h | 9 +- .../lib/Target/R600/AMDGPURegisterInfo.cpp | 38 +- .../llvm/lib/Target/R600/AMDGPURegisterInfo.h | 11 +- .../lib/Target/R600/AMDGPURegisterInfo.td | 3 +- .../llvm/lib/Target/R600/AMDGPUSubtarget.cpp | 78 +- .../llvm/lib/Target/R600/AMDGPUSubtarget.h | 33 +- .../lib/Target/R600/AMDGPUTargetMachine.cpp | 81 +- .../lib/Target/R600/AMDGPUTargetMachine.h | 61 +- .../Target/R600/AMDGPUTargetTransformInfo.cpp | 90 + contrib/llvm/lib/Target/R600/AMDIL.h | 121 - .../llvm/lib/Target/R600/AMDIL7XXDevice.cpp | 115 - contrib/llvm/lib/Target/R600/AMDIL7XXDevice.h | 72 - contrib/llvm/lib/Target/R600/AMDILBase.td | 64 - .../lib/Target/R600/AMDILCFGStructurizer.cpp | 4155 +++----- contrib/llvm/lib/Target/R600/AMDILDevice.cpp | 132 - contrib/llvm/lib/Target/R600/AMDILDevice.h | 117 - .../llvm/lib/Target/R600/AMDILDeviceInfo.cpp | 97 - .../llvm/lib/Target/R600/AMDILDeviceInfo.h | 88 - contrib/llvm/lib/Target/R600/AMDILDevices.h | 19 - .../lib/Target/R600/AMDILEvergreenDevice.cpp | 169 - .../lib/Target/R600/AMDILEvergreenDevice.h | 93 - .../lib/Target/R600/AMDILISelDAGToDAG.cpp | 667 -- .../lib/Target/R600/AMDILISelLowering.cpp | 61 +- .../llvm/lib/Target/R600/AMDILInstrInfo.td | 67 +- .../lib/Target/R600/AMDILIntrinsicInfo.cpp | 4 +- .../llvm/lib/Target/R600/AMDILNIDevice.cpp | 65 - contrib/llvm/lib/Target/R600/AMDILNIDevice.h | 57 - .../llvm/lib/Target/R600/AMDILSIDevice.cpp | 48 - contrib/llvm/lib/Target/R600/AMDILSIDevice.h | 39 - .../R600/InstPrinter/AMDGPUInstPrinter.cpp | 137 +- .../R600/InstPrinter/AMDGPUInstPrinter.h | 4 + .../R600/MCTargetDesc/AMDGPUAsmBackend.cpp | 8 +- .../R600/MCTargetDesc/AMDGPUMCAsmInfo.cpp | 13 +- .../R600/MCTargetDesc/AMDGPUMCAsmInfo.h | 4 +- .../MCTargetDesc/AMDGPUMCCodeEmitter.cpp} | 16 +- .../R600/MCTargetDesc/AMDGPUMCCodeEmitter.h | 1 + .../R600/MCTargetDesc/AMDGPUMCTargetDesc.cpp | 2 +- .../R600/MCTargetDesc/AMDGPUMCTargetDesc.h | 4 +- .../R600/MCTargetDesc/R600MCCodeEmitter.cpp | 102 +- contrib/llvm/lib/Target/R600/Processors.td | 48 +- .../lib/Target/R600/R600ClauseMergePass.cpp | 204 + .../Target/R600/R600ControlFlowFinalizer.cpp | 152 +- contrib/llvm/lib/Target/R600/R600Defines.h | 122 +- .../lib/Target/R600/R600EmitClauseMarkers.cpp | 164 +- .../Target/R600/R600ExpandSpecialInstrs.cpp | 90 +- .../llvm/lib/Target/R600/R600ISelLowering.cpp | 1299 ++- .../llvm/lib/Target/R600/R600ISelLowering.h | 14 +- .../llvm/lib/Target/R600/R600InstrFormats.td | 492 + .../llvm/lib/Target/R600/R600InstrInfo.cpp | 825 +- contrib/llvm/lib/Target/R600/R600InstrInfo.h | 121 +- .../llvm/lib/Target/R600/R600Instructions.td | 1785 ++-- .../llvm/lib/Target/R600/R600Intrinsics.td | 44 + .../Target/R600/R600MachineFunctionInfo.cpp | 6 +- .../lib/Target/R600/R600MachineFunctionInfo.h | 3 +- .../lib/Target/R600/R600MachineScheduler.cpp | 300 +- .../lib/Target/R600/R600MachineScheduler.h | 44 +- .../R600/R600OptimizeVectorRegisters.cpp | 380 + .../llvm/lib/Target/R600/R600Packetizer.cpp | 311 +- .../llvm/lib/Target/R600/R600RegisterInfo.cpp | 53 +- .../llvm/lib/Target/R600/R600RegisterInfo.h | 13 +- .../llvm/lib/Target/R600/R600RegisterInfo.td | 79 +- contrib/llvm/lib/Target/R600/R600Schedule.td | 6 +- .../R600/R600TextureIntrinsicsReplacer.cpp | 303 + .../lib/Target/R600/SIAnnotateControlFlow.cpp | 16 +- contrib/llvm/lib/Target/R600/SIDefines.h | 16 + .../llvm/lib/Target/R600/SIFixSGPRCopies.cpp | 263 + .../llvm/lib/Target/R600/SIISelLowering.cpp | 756 +- contrib/llvm/lib/Target/R600/SIISelLowering.h | 31 +- .../llvm/lib/Target/R600/SIInsertWaits.cpp | 34 +- .../llvm/lib/Target/R600/SIInstrFormats.td | 116 +- contrib/llvm/lib/Target/R600/SIInstrInfo.cpp | 524 +- contrib/llvm/lib/Target/R600/SIInstrInfo.h | 80 +- contrib/llvm/lib/Target/R600/SIInstrInfo.td | 286 +- .../llvm/lib/Target/R600/SIInstructions.td | 798 +- contrib/llvm/lib/Target/R600/SIIntrinsics.td | 26 +- .../lib/Target/R600/SILowerControlFlow.cpp | 38 +- .../lib/Target/R600/SIMachineFunctionInfo.cpp | 4 + .../lib/Target/R600/SIMachineFunctionInfo.h | 1 + .../llvm/lib/Target/R600/SIRegisterInfo.cpp | 88 +- contrib/llvm/lib/Target/R600/SIRegisterInfo.h | 26 +- .../llvm/lib/Target/R600/SIRegisterInfo.td | 18 +- .../llvm/lib/Target/R600/SITypeRewriter.cpp | 162 + .../R600/TargetInfo/AMDGPUTargetInfo.cpp | 2 +- .../llvm/lib/Target/Sparc/DelaySlotFiller.cpp | 267 +- contrib/llvm/lib/Target/Sparc/FPMover.cpp | 141 - .../Target/Sparc/MCTargetDesc/SparcBaseInfo.h | 22 +- .../Sparc/MCTargetDesc/SparcMCAsmInfo.cpp | 15 +- .../Sparc/MCTargetDesc/SparcMCAsmInfo.h | 7 +- contrib/llvm/lib/Target/Sparc/Sparc.h | 24 +- contrib/llvm/lib/Target/Sparc/Sparc.td | 6 +- .../llvm/lib/Target/Sparc/SparcAsmPrinter.cpp | 112 +- .../llvm/lib/Target/Sparc/SparcCallingConv.td | 13 +- .../lib/Target/Sparc/SparcCodeEmitter.cpp | 245 + .../lib/Target/Sparc/SparcFrameLowering.cpp | 228 +- .../lib/Target/Sparc/SparcFrameLowering.h | 20 +- .../lib/Target/Sparc/SparcISelDAGToDAG.cpp | 20 +- .../lib/Target/Sparc/SparcISelLowering.cpp | 1169 ++- .../llvm/lib/Target/Sparc/SparcISelLowering.h | 50 +- .../llvm/lib/Target/Sparc/SparcInstr64Bit.td | 103 +- .../lib/Target/Sparc/SparcInstrFormats.td | 92 +- .../llvm/lib/Target/Sparc/SparcInstrInfo.cpp | 177 +- .../llvm/lib/Target/Sparc/SparcInstrInfo.h | 15 +- .../llvm/lib/Target/Sparc/SparcInstrInfo.td | 528 +- .../llvm/lib/Target/Sparc/SparcJITInfo.cpp | 165 + contrib/llvm/lib/Target/Sparc/SparcJITInfo.h | 67 + .../Target/Sparc/SparcMachineFunctionInfo.h | 12 +- .../lib/Target/Sparc/SparcRegisterInfo.cpp | 166 +- .../llvm/lib/Target/Sparc/SparcRegisterInfo.h | 10 +- .../lib/Target/Sparc/SparcRegisterInfo.td | 124 +- .../llvm/lib/Target/Sparc/SparcRelocations.h | 41 + .../llvm/lib/Target/Sparc/SparcSubtarget.cpp | 33 +- .../llvm/lib/Target/Sparc/SparcSubtarget.h | 16 +- .../lib/Target/Sparc/SparcTargetMachine.cpp | 9 +- .../lib/Target/Sparc/SparcTargetMachine.h | 6 + .../Sparc/TargetInfo/SparcTargetInfo.cpp | 8 +- .../SystemZ/AsmParser/SystemZAsmParser.cpp | 475 +- .../Disassembler/SystemZDisassembler.cpp | 323 + .../InstPrinter/SystemZInstPrinter.cpp | 23 +- .../SystemZ/InstPrinter/SystemZInstPrinter.h | 3 +- .../MCTargetDesc/SystemZMCAsmBackend.cpp | 49 +- .../SystemZ/MCTargetDesc/SystemZMCAsmInfo.cpp | 4 +- .../SystemZ/MCTargetDesc/SystemZMCAsmInfo.h | 7 +- .../MCTargetDesc/SystemZMCCodeEmitter.cpp | 114 +- .../MCTargetDesc/SystemZMCTargetDesc.cpp | 81 +- .../MCTargetDesc/SystemZMCTargetDesc.h | 38 +- contrib/llvm/lib/Target/SystemZ/README.txt | 65 +- contrib/llvm/lib/Target/SystemZ/SystemZ.h | 42 +- contrib/llvm/lib/Target/SystemZ/SystemZ.td | 7 +- .../lib/Target/SystemZ/SystemZAsmPrinter.cpp | 136 +- .../lib/Target/SystemZ/SystemZCallingConv.td | 4 +- .../SystemZ/SystemZConstantPoolValue.cpp | 2 +- .../lib/Target/SystemZ/SystemZElimCompare.cpp | 471 + .../Target/SystemZ/SystemZFrameLowering.cpp | 108 +- .../lib/Target/SystemZ/SystemZFrameLowering.h | 27 +- .../Target/SystemZ/SystemZISelDAGToDAG.cpp | 603 +- .../Target/SystemZ/SystemZISelLowering.cpp | 1523 ++- .../lib/Target/SystemZ/SystemZISelLowering.h | 139 +- .../llvm/lib/Target/SystemZ/SystemZInstrFP.td | 320 +- .../lib/Target/SystemZ/SystemZInstrFormats.td | 1242 ++- .../lib/Target/SystemZ/SystemZInstrInfo.cpp | 907 +- .../lib/Target/SystemZ/SystemZInstrInfo.h | 150 +- .../lib/Target/SystemZ/SystemZInstrInfo.td | 1226 ++- .../lib/Target/SystemZ/SystemZLongBranch.cpp | 462 + .../lib/Target/SystemZ/SystemZMCInstLower.cpp | 116 +- .../lib/Target/SystemZ/SystemZMCInstLower.h | 15 +- .../SystemZMachineFunctionInfo.cpp} | 13 +- .../SystemZ/SystemZMachineFunctionInfo.h | 12 +- .../lib/Target/SystemZ/SystemZOperands.td | 153 +- .../lib/Target/SystemZ/SystemZOperators.td | 208 +- .../lib/Target/SystemZ/SystemZPatterns.td | 99 +- .../lib/Target/SystemZ/SystemZProcessors.td | 46 + .../Target/SystemZ/SystemZRegisterInfo.cpp | 37 +- .../lib/Target/SystemZ/SystemZRegisterInfo.h | 16 +- .../lib/Target/SystemZ/SystemZRegisterInfo.td | 71 +- .../SystemZ/SystemZSelectionDAGInfo.cpp | 293 + .../Target/SystemZ/SystemZSelectionDAGInfo.h | 80 + .../lib/Target/SystemZ/SystemZShortenInst.cpp | 163 + .../lib/Target/SystemZ/SystemZSubtarget.cpp | 15 +- .../lib/Target/SystemZ/SystemZSubtarget.h | 22 + .../Target/SystemZ/SystemZTargetMachine.cpp | 50 +- .../lib/Target/SystemZ/SystemZTargetMachine.h | 4 +- contrib/llvm/lib/Target/Target.cpp | 8 + contrib/llvm/lib/Target/TargetLibraryInfo.cpp | 44 +- .../lib/Target/TargetLoweringObjectFile.cpp | 20 +- contrib/llvm/lib/Target/TargetMachine.cpp | 6 +- contrib/llvm/lib/Target/TargetMachineC.cpp | 56 +- .../llvm/lib/Target/TargetSubtargetInfo.cpp | 19 + .../lib/Target/X86/AsmParser/X86AsmParser.cpp | 412 +- .../X86/Disassembler/X86Disassembler.cpp | 145 +- .../X86/Disassembler/X86DisassemblerDecoder.c | 267 +- .../X86/Disassembler/X86DisassemblerDecoder.h | 106 +- .../X86DisassemblerDecoderCommon.h | 165 +- .../X86/InstPrinter/X86ATTInstPrinter.cpp | 37 +- .../X86/InstPrinter/X86ATTInstPrinter.h | 22 +- .../X86/InstPrinter/X86IntelInstPrinter.cpp | 32 +- .../X86/InstPrinter/X86IntelInstPrinter.h | 52 +- .../Target/X86/MCTargetDesc/X86AsmBackend.cpp | 403 +- .../lib/Target/X86/MCTargetDesc/X86BaseInfo.h | 82 +- .../X86/MCTargetDesc/X86ELFObjectWriter.cpp | 22 +- .../X86/MCTargetDesc/X86ELFRelocationInfo.cpp | 135 + .../Target/X86/MCTargetDesc/X86MCAsmInfo.cpp | 6 +- .../Target/X86/MCTargetDesc/X86MCAsmInfo.h | 3 +- .../X86/MCTargetDesc/X86MCCodeEmitter.cpp | 335 +- .../X86/MCTargetDesc/X86MCTargetDesc.cpp | 35 +- .../Target/X86/MCTargetDesc/X86MCTargetDesc.h | 13 +- .../MCTargetDesc/X86MachORelocationInfo.cpp | 116 + .../X86/MCTargetDesc/X86MachObjectWriter.cpp | 177 +- .../MCTargetDesc/X86WinCOFFObjectWriter.cpp | 2 +- contrib/llvm/lib/Target/X86/X86.td | 71 +- contrib/llvm/lib/Target/X86/X86AsmPrinter.cpp | 86 +- contrib/llvm/lib/Target/X86/X86AsmPrinter.h | 20 +- contrib/llvm/lib/Target/X86/X86CallingConv.h | 35 + contrib/llvm/lib/Target/X86/X86CallingConv.td | 95 +- .../llvm/lib/Target/X86/X86CodeEmitter.cpp | 47 +- contrib/llvm/lib/Target/X86/X86FastISel.cpp | 463 +- contrib/llvm/lib/Target/X86/X86FixupLEAs.cpp | 2 +- .../llvm/lib/Target/X86/X86FloatingPoint.cpp | 18 +- .../llvm/lib/Target/X86/X86FrameLowering.cpp | 337 +- .../llvm/lib/Target/X86/X86FrameLowering.h | 27 - .../llvm/lib/Target/X86/X86ISelDAGToDAG.cpp | 225 +- .../llvm/lib/Target/X86/X86ISelLowering.cpp | 3106 ++++-- contrib/llvm/lib/Target/X86/X86ISelLowering.h | 136 +- contrib/llvm/lib/Target/X86/X86InstrAVX512.td | 3526 +++++++ .../llvm/lib/Target/X86/X86InstrArithmetic.td | 250 +- .../llvm/lib/Target/X86/X86InstrCompiler.td | 130 +- .../llvm/lib/Target/X86/X86InstrControl.td | 5 +- .../llvm/lib/Target/X86/X86InstrExtension.td | 68 +- contrib/llvm/lib/Target/X86/X86InstrFMA.td | 77 +- .../llvm/lib/Target/X86/X86InstrFPStack.td | 30 +- .../llvm/lib/Target/X86/X86InstrFormats.td | 181 +- .../lib/Target/X86/X86InstrFragmentsSIMD.td | 141 +- contrib/llvm/lib/Target/X86/X86InstrInfo.cpp | 996 +- contrib/llvm/lib/Target/X86/X86InstrInfo.h | 26 +- contrib/llvm/lib/Target/X86/X86InstrInfo.td | 601 +- contrib/llvm/lib/Target/X86/X86InstrMMX.td | 78 +- contrib/llvm/lib/Target/X86/X86InstrSSE.td | 1833 ++-- contrib/llvm/lib/Target/X86/X86InstrSVM.td | 18 +- .../lib/Target/X86/X86InstrShiftRotate.td | 136 +- contrib/llvm/lib/Target/X86/X86InstrSystem.td | 76 +- contrib/llvm/lib/Target/X86/X86InstrTSX.td | 7 + contrib/llvm/lib/Target/X86/X86InstrXOP.td | 146 +- contrib/llvm/lib/Target/X86/X86JITInfo.cpp | 3 +- .../llvm/lib/Target/X86/X86MCInstLower.cpp | 270 +- .../llvm/lib/Target/X86/X86RegisterInfo.cpp | 89 +- contrib/llvm/lib/Target/X86/X86RegisterInfo.h | 10 +- .../llvm/lib/Target/X86/X86RegisterInfo.td | 92 +- .../llvm/lib/Target/X86/X86SchedHaswell.td | 14 +- .../lib/Target/X86/X86SchedSandyBridge.td | 13 +- contrib/llvm/lib/Target/X86/X86Schedule.td | 73 +- .../llvm/lib/Target/X86/X86ScheduleAtom.td | 41 +- contrib/llvm/lib/Target/X86/X86ScheduleSLM.td | 668 ++ .../lib/Target/X86/X86SelectionDAGInfo.cpp | 6 +- .../llvm/lib/Target/X86/X86SelectionDAGInfo.h | 4 +- contrib/llvm/lib/Target/X86/X86Subtarget.cpp | 60 +- contrib/llvm/lib/Target/X86/X86Subtarget.h | 43 +- .../llvm/lib/Target/X86/X86TargetMachine.cpp | 10 +- .../lib/Target/X86/X86TargetObjectFile.cpp | 10 +- .../llvm/lib/Target/X86/X86TargetObjectFile.h | 3 + .../lib/Target/X86/X86TargetTransformInfo.cpp | 234 +- contrib/llvm/lib/Target/X86/X86VZeroUpper.cpp | 45 +- .../XCore/Disassembler/XCoreDisassembler.cpp | 8 +- .../XCore/MCTargetDesc/XCoreMCAsmInfo.cpp | 10 +- .../XCore/MCTargetDesc/XCoreMCAsmInfo.h | 6 +- .../XCore/MCTargetDesc/XCoreMCTargetDesc.cpp | 10 +- contrib/llvm/lib/Target/XCore/XCore.h | 2 + .../llvm/lib/Target/XCore/XCoreAsmPrinter.cpp | 80 +- .../lib/Target/XCore/XCoreFrameLowering.cpp | 107 +- .../lib/Target/XCore/XCoreISelDAGToDAG.cpp | 14 +- .../lib/Target/XCore/XCoreISelLowering.cpp | 200 +- .../llvm/lib/Target/XCore/XCoreISelLowering.h | 24 +- .../llvm/lib/Target/XCore/XCoreInstrInfo.cpp | 17 +- .../llvm/lib/Target/XCore/XCoreInstrInfo.h | 7 +- .../llvm/lib/Target/XCore/XCoreInstrInfo.td | 26 +- .../Target/XCore/XCoreLowerThreadLocal.cpp | 114 +- .../lib/Target/XCore/XCoreMCInstLower.cpp | 2 +- .../lib/Target/XCore/XCoreRegisterInfo.cpp | 6 +- .../llvm/lib/Target/XCore/XCoreRegisterInfo.h | 4 +- .../lib/Target/XCore/XCoreTargetMachine.cpp | 9 + .../lib/Target/XCore/XCoreTargetMachine.h | 2 + .../Target/XCore/XCoreTargetTransformInfo.cpp | 83 + .../lib/Transforms/IPO/ArgumentPromotion.cpp | 31 +- .../llvm/lib/Transforms/IPO/ConstantMerge.cpp | 11 +- .../IPO/DeadArgumentElimination.cpp | 138 +- contrib/llvm/lib/Transforms/IPO/ExtractGV.cpp | 54 +- .../llvm/lib/Transforms/IPO/FunctionAttrs.cpp | 437 +- contrib/llvm/lib/Transforms/IPO/GlobalDCE.cpp | 3 + contrib/llvm/lib/Transforms/IPO/GlobalOpt.cpp | 514 +- .../llvm/lib/Transforms/IPO/InlineAlways.cpp | 2 +- .../llvm/lib/Transforms/IPO/InlineSimple.cpp | 4 +- contrib/llvm/lib/Transforms/IPO/Inliner.cpp | 27 +- .../llvm/lib/Transforms/IPO/Internalize.cpp | 136 +- .../lib/Transforms/IPO/MergeFunctions.cpp | 77 +- .../lib/Transforms/IPO/PassManagerBuilder.cpp | 62 +- contrib/llvm/lib/Transforms/IPO/PruneEH.cpp | 14 +- .../llvm/lib/Transforms/IPO/StripSymbols.cpp | 231 +- .../lib/Transforms/InstCombine/InstCombine.h | 16 +- .../InstCombine/InstCombineAddSub.cpp | 49 +- .../InstCombine/InstCombineAndOrXor.cpp | 263 +- .../InstCombine/InstCombineCalls.cpp | 46 +- .../InstCombine/InstCombineCasts.cpp | 168 +- .../InstCombine/InstCombineCompares.cpp | 392 +- .../InstCombineLoadStoreAlloca.cpp | 30 +- .../InstCombine/InstCombineMulDivRem.cpp | 385 +- .../Transforms/InstCombine/InstCombinePHI.cpp | 14 +- .../InstCombine/InstCombineSelect.cpp | 15 +- .../InstCombineSimplifyDemanded.cpp | 3 +- .../InstCombine/InstCombineVectorOps.cpp | 321 +- .../InstCombine/InstCombineWorklist.h | 9 +- .../InstCombine/InstructionCombining.cpp | 114 +- .../Instrumentation/AddressSanitizer.cpp | 366 +- .../Transforms/Instrumentation/BlackList.cpp | 126 - .../Instrumentation/BoundsChecking.cpp | 6 +- .../Instrumentation/DataFlowSanitizer.cpp | 1397 +++ .../Transforms/Instrumentation/DebugIR.cpp | 618 ++ .../lib/Transforms/Instrumentation/DebugIR.h | 99 + .../Instrumentation/EdgeProfiling.cpp | 117 - .../Instrumentation/GCOVProfiling.cpp | 93 +- .../Instrumentation/Instrumentation.cpp | 4 +- .../Instrumentation/MemorySanitizer.cpp | 537 +- .../Instrumentation/OptimalEdgeProfiling.cpp | 225 - .../Instrumentation/PathProfiling.cpp | 1424 --- .../Instrumentation/ProfilingUtils.cpp | 169 - .../Instrumentation/ProfilingUtils.h | 36 - .../Instrumentation/ThreadSanitizer.cpp | 18 +- .../ObjCARC/ARCRuntimeEntryPoints.h | 186 + .../Transforms/ObjCARC/DependencyAnalysis.h | 2 +- contrib/llvm/lib/Transforms/ObjCARC/ObjCARC.h | 6 +- .../ObjCARC/ObjCARCAliasAnalysis.cpp | 2 +- .../Transforms/ObjCARC/ObjCARCAliasAnalysis.h | 2 +- .../Transforms/ObjCARC/ObjCARCContract.cpp | 110 +- .../lib/Transforms/ObjCARC/ObjCARCOpts.cpp | 760 +- .../lib/Transforms/ObjCARC/ObjCARCUtil.cpp | 4 +- .../Transforms/ObjCARC/ProvenanceAnalysis.h | 2 +- contrib/llvm/lib/Transforms/Scalar/ADCE.cpp | 2 +- .../Transforms/Scalar/BasicBlockPlacement.cpp | 152 - .../lib/Transforms/Scalar/CodeGenPrepare.cpp | 105 +- .../llvm/lib/Transforms/Scalar/EarlyCSE.cpp | 10 - .../lib/Transforms/Scalar/FlattenCFGPass.cpp | 79 + contrib/llvm/lib/Transforms/Scalar/GVN.cpp | 252 +- .../lib/Transforms/Scalar/GlobalMerge.cpp | 18 +- .../lib/Transforms/Scalar/IndVarSimplify.cpp | 91 +- .../lib/Transforms/Scalar/JumpThreading.cpp | 89 +- .../lib/Transforms/Scalar/LoopDeletion.cpp | 10 +- .../Transforms/Scalar/LoopIdiomRecognize.cpp | 74 +- .../lib/Transforms/Scalar/LoopRerollPass.cpp | 1184 +++ .../Transforms/Scalar/LoopStrengthReduce.cpp | 136 +- .../lib/Transforms/Scalar/LoopUnrollPass.cpp | 42 +- .../lib/Transforms/Scalar/LoopUnswitch.cpp | 229 +- .../lib/Transforms/Scalar/MemCpyOptimizer.cpp | 23 +- .../Scalar/PartiallyInlineLibCalls.cpp | 156 + .../lib/Transforms/Scalar/Reassociate.cpp | 41 +- contrib/llvm/lib/Transforms/Scalar/SCCP.cpp | 14 +- contrib/llvm/lib/Transforms/Scalar/SROA.cpp | 2802 +++--- .../lib/Transforms/Scalar/SampleProfile.cpp | 479 + contrib/llvm/lib/Transforms/Scalar/Scalar.cpp | 16 +- .../Scalar/ScalarReplAggregates.cpp | 51 +- .../lib/Transforms/Scalar/SimplifyCFGPass.cpp | 194 +- .../Transforms/Scalar/SimplifyLibCalls.cpp | 247 - .../Scalar/StructurizeCFG.cpp} | 178 +- .../Scalar/TailRecursionElimination.cpp | 170 +- .../lib/Transforms/Utils/BasicBlockUtils.cpp | 175 +- .../Transforms/Utils/BreakCriticalEdges.cpp | 43 +- .../lib/Transforms/Utils/CloneFunction.cpp | 5 +- .../lib/Transforms/Utils/CodeExtractor.cpp | 7 +- .../lib/Transforms/Utils/DemoteRegToStack.cpp | 1 + .../llvm/lib/Transforms/Utils/FlattenCFG.cpp | 486 + .../lib/Transforms/Utils/GlobalStatus.cpp | 183 + .../lib/Transforms/Utils/InlineFunction.cpp | 3 +- contrib/llvm/lib/Transforms/Utils/LCSSA.cpp | 15 +- contrib/llvm/lib/Transforms/Utils/Local.cpp | 473 +- .../lib/Transforms/Utils/LoopSimplify.cpp | 23 +- .../llvm/lib/Transforms/Utils/LoopUnroll.cpp | 8 +- .../Transforms/Utils/LowerExpectIntrinsic.cpp | 2 +- .../llvm/lib/Transforms/Utils/LowerInvoke.cpp | 21 +- .../llvm/lib/Transforms/Utils/LowerSwitch.cpp | 62 +- .../llvm/lib/Transforms/Utils/MetaRenamer.cpp | 2 +- .../llvm/lib/Transforms/Utils/ModuleUtils.cpp | 18 + .../Utils/PromoteMemoryToRegister.cpp | 1082 +- .../llvm/lib/Transforms/Utils/SSAUpdater.cpp | 50 +- .../llvm/lib/Transforms/Utils/SimplifyCFG.cpp | 311 +- .../lib/Transforms/Utils/SimplifyIndVar.cpp | 2 +- .../lib/Transforms/Utils/SimplifyLibCalls.cpp | 323 +- .../lib/Transforms/Utils/SpecialCaseList.cpp | 222 + .../llvm/lib/Transforms/Utils/ValueMapper.cpp | 29 +- .../lib/Transforms/Vectorize/BBVectorize.cpp | 90 +- .../Transforms/Vectorize/LoopVectorize.cpp | 2795 ++++-- .../Transforms/Vectorize/SLPVectorizer.cpp | 2529 ++++- .../lib/Transforms/Vectorize/VecUtils.cpp | 730 -- .../llvm/lib/Transforms/Vectorize/VecUtils.h | 164 - contrib/llvm/tools/bugpoint/BugDriver.cpp | 4 +- contrib/llvm/tools/bugpoint/BugDriver.h | 4 +- contrib/llvm/tools/bugpoint/CrashDebugger.cpp | 20 +- .../llvm/tools/bugpoint/ExecutionDriver.cpp | 63 +- .../llvm/tools/bugpoint/ExtractFunction.cpp | 30 +- contrib/llvm/tools/bugpoint/FindBugs.cpp | 3 +- .../llvm/tools/bugpoint/Miscompilation.cpp | 101 +- .../llvm/tools/bugpoint/OptimizerDriver.cpp | 99 +- contrib/llvm/tools/bugpoint/ToolRunner.cpp | 201 +- contrib/llvm/tools/bugpoint/ToolRunner.h | 60 +- contrib/llvm/tools/bugpoint/bugpoint.cpp | 6 +- .../include/clang-c/CXCompilationDatabase.h | 20 +- .../tools/clang/include/clang-c/CXString.h | 2 +- .../llvm/tools/clang/include/clang-c/Index.h | 70 +- .../clang/include/clang/ARCMigrate/ARCMT.h | 2 + .../include/clang/ARCMigrate/ARCMTActions.h | 6 +- .../include/clang/ARCMigrate/FileRemapper.h | 1 - .../tools/clang/include/clang/AST/APValue.h | 7 + .../clang/include/clang/AST/ASTConsumer.h | 21 + .../clang/include/clang/AST/ASTContext.h | 310 +- .../clang/include/clang/AST/ASTDiagnostic.h | 2 +- .../tools/clang/include/clang/AST/ASTFwd.h | 28 + .../clang/include/clang/AST/ASTImporter.h | 8 + .../tools/clang/include/clang/AST/ASTLambda.h | 80 + .../include/clang/AST/ASTMutationListener.h | 17 + .../clang/include/clang/AST/ASTTypeTraits.h | 387 +- .../include/clang/AST/ASTUnresolvedSet.h | 42 +- .../tools/clang/include/clang/AST/ASTVector.h | 55 +- .../llvm/tools/clang/include/clang/AST/Attr.h | 3 +- .../clang/include/clang/AST/CXXInheritance.h | 4 +- .../clang/include/clang/AST/CanonicalType.h | 2 +- .../tools/clang/include/clang/AST/CharUnits.h | 21 +- .../tools/clang/include/clang/AST/Comment.h | 20 +- .../include/clang/AST/CommentCommandTraits.h | 5 + .../include/clang/AST/CommentCommands.td | 11 + .../include/clang/AST/CommentDiagnostic.h | 2 +- .../clang/include/clang/AST/CommentParser.h | 6 +- .../clang/include/clang/AST/CommentSema.h | 9 +- .../llvm/tools/clang/include/clang/AST/Decl.h | 367 +- .../clang/include/clang/AST/DeclAccessPair.h | 9 +- .../tools/clang/include/clang/AST/DeclBase.h | 163 +- .../tools/clang/include/clang/AST/DeclCXX.h | 1014 +- .../include/clang/AST/DeclContextInternals.h | 48 +- .../clang/include/clang/AST/DeclFriend.h | 4 +- .../clang/include/clang/AST/DeclLookups.h | 22 +- .../tools/clang/include/clang/AST/DeclObjC.h | 47 +- .../clang/include/clang/AST/DeclOpenMP.h | 26 +- .../clang/include/clang/AST/DeclTemplate.h | 691 +- .../clang/include/clang/AST/DeclarationName.h | 12 +- .../include/clang/AST/EvaluatedExprVisitor.h | 2 +- .../llvm/tools/clang/include/clang/AST/Expr.h | 245 +- .../tools/clang/include/clang/AST/ExprCXX.h | 688 +- .../tools/clang/include/clang/AST/ExprObjC.h | 23 +- .../include/clang/AST/ExternalASTSource.h | 7 +- .../clang/include/clang/AST/GlobalDecl.h | 1 + .../include/clang/AST/LambdaMangleContext.h | 38 - .../tools/clang/include/clang/AST/Mangle.h | 117 +- .../clang/AST/MangleNumberingContext.h | 59 + .../include/clang/AST/NestedNameSpecifier.h | 6 +- .../tools/clang/include/clang/AST/ParentMap.h | 5 + .../clang/include/clang/AST/PrettyPrinter.h | 13 +- .../clang/include/clang/AST/RawCommentList.h | 31 +- .../clang/include/clang/AST/RecordLayout.h | 55 +- .../include/clang/AST/RecursiveASTVisitor.h | 330 +- .../clang/include/clang/AST/Redeclarable.h | 52 +- .../llvm/tools/clang/include/clang/AST/Stmt.h | 104 +- .../tools/clang/include/clang/AST/StmtCXX.h | 4 +- .../clang/include/clang/AST/StmtIterator.h | 32 +- .../tools/clang/include/clang/AST/StmtObjC.h | 9 +- .../clang/include/clang/AST/StmtOpenMP.h | 528 + .../clang/include/clang/AST/StmtVisitor.h | 36 + .../clang/include/clang/AST/TemplateBase.h | 108 +- .../llvm/tools/clang/include/clang/AST/Type.h | 111 +- .../tools/clang/include/clang/AST/TypeLoc.h | 142 +- .../clang/include/clang/AST/TypeNodes.def | 3 +- .../clang/include/clang/AST/TypeOrdering.h | 16 +- .../clang/include/clang/AST/TypeVisitor.h | 44 +- .../clang/include/clang/AST/UnresolvedSet.h | 15 +- .../clang/include/clang/AST/VTTBuilder.h | 49 +- .../clang/include/clang/AST/VTableBuilder.h | 301 +- .../clang/ASTMatchers/ASTMatchFinder.h | 21 +- .../include/clang/ASTMatchers/ASTMatchers.h | 718 +- .../clang/ASTMatchers/ASTMatchersInternal.h | 786 +- .../clang/ASTMatchers/ASTMatchersMacros.h | 189 +- .../clang/ASTMatchers/Dynamic/Diagnostics.h | 185 + .../clang/ASTMatchers/Dynamic/Parser.h | 151 + .../clang/ASTMatchers/Dynamic/Registry.h | 75 + .../clang/ASTMatchers/Dynamic/VariantValue.h | 261 + .../clang/Analysis/Analyses/Consumed.h | 264 + .../clang/Analysis/Analyses/FormatString.h | 8 +- .../clang/Analysis/Analyses/ThreadSafety.h | 4 +- .../Analysis/Analyses/UninitializedValues.h | 22 +- .../include/clang/Analysis/AnalysisContext.h | 6 +- .../clang/Analysis/AnalysisDiagnostic.h | 2 +- .../tools/clang/include/clang/Analysis/CFG.h | 90 +- .../clang/include/clang/Analysis/CallGraph.h | 4 +- .../Analysis/FlowSensitive/DataflowSolver.h | 3 +- .../Analysis/Support/BlkExprDeclBitVector.h | 307 - .../Analysis/Visitors/CFGRecStmtDeclVisitor.h | 107 - .../Analysis/Visitors/CFGRecStmtVisitor.h | 59 - .../clang/Analysis/Visitors/CFGStmtVisitor.h | 175 - .../tools/clang/include/clang/Basic/ABI.h | 142 +- .../tools/clang/include/clang/Basic/Attr.td | 268 +- .../clang/include/clang/Basic/AttrKinds.h | 2 +- .../clang/include/clang/Basic/Builtins.def | 469 +- .../clang/include/clang/Basic/Builtins.h | 21 +- .../include/clang/Basic/BuiltinsAArch64.def | 7 + .../clang/include/clang/Basic/BuiltinsARM.def | 25 +- .../include/clang/Basic/BuiltinsMips.def | 712 ++ .../include/clang/Basic/BuiltinsNVPTX.def | 744 +- .../clang/include/clang/Basic/BuiltinsX86.def | 16 +- .../include/clang/Basic/BuiltinsXCore.def | 22 + .../clang/include/clang/Basic/CapturedStmt.h | 3 +- .../clang/include/clang/Basic/DeclNodes.td | 4 + .../clang/include/clang/Basic/Diagnostic.h | 16 +- .../clang/include/clang/Basic/Diagnostic.td | 43 +- .../include/clang/Basic/DiagnosticASTKinds.td | 16 + .../clang/Basic/DiagnosticCommentKinds.td | 4 + .../clang/Basic/DiagnosticCommonKinds.td | 20 +- .../clang/Basic/DiagnosticDriverKinds.td | 24 +- .../clang/Basic/DiagnosticFrontendKinds.td | 7 +- .../include/clang/Basic/DiagnosticGroups.td | 102 +- .../clang/include/clang/Basic/DiagnosticIDs.h | 34 +- .../include/clang/Basic/DiagnosticLexKinds.td | 66 +- .../include/clang/Basic/DiagnosticOptions.def | 1 + .../clang/Basic/DiagnosticParseKinds.td | 81 +- .../clang/Basic/DiagnosticSemaKinds.td | 760 +- .../Basic/DiagnosticSerializationKinds.td | 13 +- .../clang/include/clang/Basic/FileManager.h | 36 +- .../include/clang/Basic/FileSystemStatCache.h | 47 +- .../include/clang/Basic/IdentifierTable.h | 82 +- .../tools/clang/include/clang/Basic/Lambda.h | 15 +- .../clang/include/clang/Basic/LangOptions.def | 33 +- .../clang/include/clang/Basic/LangOptions.h | 7 + .../tools/clang/include/clang/Basic/Linkage.h | 40 +- .../tools/clang/include/clang/Basic/Module.h | 57 +- .../clang/include/clang/Basic/ObjCRuntime.h | 7 +- .../clang/include/clang/Basic/OpenMPKinds.def | 31 +- .../clang/include/clang/Basic/OpenMPKinds.h | 28 + .../clang/include/clang/Basic/OperatorKinds.h | 2 +- .../include/clang/Basic/PartialDiagnostic.h | 21 + .../clang/include/clang/Basic/Sanitizers.def | 23 +- .../include/clang/Basic/SourceLocation.h | 2 +- .../clang/include/clang/Basic/SourceManager.h | 58 +- .../clang/include/clang/Basic/Specifiers.h | 33 +- .../clang/include/clang/Basic/StmtNodes.td | 6 + .../include/clang/Basic/TargetBuiltins.h | 14 +- .../clang/include/clang/Basic/TargetCXXABI.h | 24 +- .../clang/include/clang/Basic/TargetInfo.h | 47 +- .../clang/include/clang/Basic/TargetOptions.h | 3 + .../clang/include/clang/Basic/TemplateKinds.h | 3 + .../clang/include/clang/Basic/TokenKinds.def | 17 +- .../clang/include/clang/Basic/TypeTraits.h | 1 + .../clang/include/clang/Basic/Visibility.h | 16 +- .../clang/include/clang/Basic/arm_neon.td | 888 +- .../include/clang/CodeGen/CGFunctionInfo.h | 361 + .../include/clang/CodeGen/CodeGenABITypes.h | 80 + .../tools/clang/include/clang/Driver/Action.h | 14 +- .../tools/clang/include/clang/Driver/Arg.h | 133 - .../clang/include/clang/Driver/ArgList.h | 442 - .../clang/include/clang/Driver/CC1AsOptions.h | 13 +- .../include/clang/Driver/CC1AsOptions.td | 11 +- .../clang/include/clang/Driver/CC1Options.td | 43 +- .../include/clang/Driver/CLCompatOptions.td | 255 + .../clang/include/clang/Driver/Compilation.h | 55 +- .../tools/clang/include/clang/Driver/Driver.h | 77 +- .../include/clang/Driver/DriverDiagnostic.h | 2 +- .../tools/clang/include/clang/Driver/Job.h | 71 +- .../clang/include/clang/Driver/OptParser.td | 152 - .../clang/include/clang/Driver/OptSpecifier.h | 41 - .../clang/include/clang/Driver/OptTable.h | 161 - .../tools/clang/include/clang/Driver/Option.h | 204 - .../clang/include/clang/Driver/Options.h | 28 +- .../clang/include/clang/Driver/Options.td | 535 +- .../include/clang/Driver/SanitizerArgs.h | 147 + .../tools/clang/include/clang/Driver/Tool.h | 13 +- .../clang/include/clang/Driver/ToolChain.h | 102 +- .../clang/include/clang/Driver/Types.def | 2 +- .../tools/clang/include/clang/Driver/Types.h | 4 +- .../tools/clang/include/clang/Driver/Util.h | 5 +- .../tools/clang/include/clang/Edit/Commit.h | 16 +- .../clang/include/clang/Edit/EditedSource.h | 9 +- .../clang/include/clang/Edit/Rewriters.h | 8 +- .../tools/clang/include/clang/Format/Format.h | 286 +- .../include/clang/Frontend/ASTConsumers.h | 9 +- .../clang/include/clang/Frontend/ASTUnit.h | 14 +- .../include/clang/Frontend/CodeGenOptions.def | 14 +- .../include/clang/Frontend/CodeGenOptions.h | 12 + .../include/clang/Frontend/CompilerInstance.h | 36 +- .../clang/Frontend/CompilerInvocation.h | 15 +- .../clang/Frontend/DependencyOutputOptions.h | 2 + .../include/clang/Frontend/FrontendAction.h | 10 +- .../include/clang/Frontend/FrontendActions.h | 10 +- .../clang/Frontend/FrontendDiagnostic.h | 2 +- .../include/clang/Frontend/FrontendOptions.h | 33 +- .../include/clang/Frontend/TextDiagnostic.h | 3 +- .../clang/include/clang/Frontend/Utils.h | 23 +- .../clang/include/clang/Index/CommentToXML.h | 50 + .../clang/include/clang/Index/USRGeneration.h | 54 + .../clang/include/clang/Lex/DirectoryLookup.h | 10 +- .../clang/include/clang/Lex/HeaderSearch.h | 65 +- .../include/clang/Lex/HeaderSearchOptions.h | 8 +- .../clang/include/clang/Lex/LexDiagnostic.h | 2 +- .../tools/clang/include/clang/Lex/Lexer.h | 69 +- .../clang/include/clang/Lex/LiteralSupport.h | 20 +- .../tools/clang/include/clang/Lex/MacroInfo.h | 4 +- .../clang/include/clang/Lex/ModuleLoader.h | 4 + .../tools/clang/include/clang/Lex/ModuleMap.h | 86 +- .../include/clang/Lex/MultipleIncludeOpt.h | 56 +- .../clang/include/clang/Lex/PPCallbacks.h | 95 +- .../clang/Lex/PPConditionalDirectiveRecord.h | 5 +- .../tools/clang/include/clang/Lex/PTHLexer.h | 2 +- .../include/clang/Lex/PreprocessingRecord.h | 3 +- .../clang/include/clang/Lex/Preprocessor.h | 79 +- .../include/clang/Lex/PreprocessorLexer.h | 6 +- .../tools/clang/include/clang/Lex/Token.h | 9 +- .../clang/include/clang/Lex/TokenLexer.h | 4 +- .../include/clang/Parse/ParseDiagnostic.h | 2 +- .../tools/clang/include/clang/Parse/Parser.h | 185 +- .../include/clang/Rewrite/Core/HTMLRewrite.h | 2 +- .../include/clang/Rewrite/Core/Rewriter.h | 17 +- .../clang/Sema/AnalysisBasedWarnings.h | 1 + .../clang/include/clang/Sema/AttributeList.h | 233 +- .../include/clang/Sema/CodeCompleteConsumer.h | 20 +- .../tools/clang/include/clang/Sema/DeclSpec.h | 120 +- .../include/clang/Sema/DelayedDiagnostic.h | 24 +- .../include/clang/Sema/ExternalSemaSource.h | 44 +- .../include/clang/Sema/IdentifierResolver.h | 10 - .../clang/include/clang/Sema/Initialization.h | 117 +- .../tools/clang/include/clang/Sema/Lookup.h | 119 +- .../clang/Sema/MultiplexExternalSemaSource.h | 30 + .../tools/clang/include/clang/Sema/Overload.h | 77 +- .../clang/include/clang/Sema/Ownership.h | 24 +- .../tools/clang/include/clang/Sema/Scope.h | 23 +- .../clang/include/clang/Sema/ScopeInfo.h | 269 +- .../tools/clang/include/clang/Sema/Sema.h | 970 +- .../clang/include/clang/Sema/SemaDiagnostic.h | 2 +- .../clang/include/clang/Sema/SemaInternal.h | 39 +- .../clang/include/clang/Sema/SemaLambda.h | 39 + .../tools/clang/include/clang/Sema/Template.h | 123 +- .../include/clang/Sema/TemplateDeduction.h | 122 +- .../clang/include/clang/Sema/TypoCorrection.h | 105 +- .../include/clang/Serialization/ASTBitCodes.h | 30 +- .../include/clang/Serialization/ASTReader.h | 61 +- .../include/clang/Serialization/ASTWriter.h | 23 +- .../clang/Serialization/GlobalModuleIndex.h | 1 + .../clang/Serialization/ModuleManager.h | 6 +- .../Serialization/SerializationDiagnostic.h | 2 +- .../StaticAnalyzer/Checkers/ObjCRetainCount.h | 223 + .../clang/StaticAnalyzer/Core/Analyses.def | 12 +- .../StaticAnalyzer/Core/AnalyzerOptions.h | 25 +- .../Core/BugReporter/BugReporter.h | 19 +- .../StaticAnalyzer/Core/BugReporter/BugType.h | 11 +- .../BugReporter}/CommonBugCategories.h | 11 +- .../Core/BugReporter/PathDiagnostic.h | 56 +- .../clang/StaticAnalyzer/Core/Checker.h | 63 +- .../StaticAnalyzer/Core/CheckerManager.h | 64 +- .../StaticAnalyzer/Core/CheckerRegistry.h | 7 +- .../Core/PathDiagnosticConsumers.h | 18 +- .../Core/PathSensitive/AnalysisManager.h | 4 + .../Core/PathSensitive/CallEvent.h | 33 +- .../Core/PathSensitive/ExplodedGraph.h | 2 +- .../Core/PathSensitive/ExprEngine.h | 6 +- .../Core/PathSensitive/MemRegion.h | 48 +- .../Core/PathSensitive/ProgramState.h | 22 +- .../Core/PathSensitive/SValBuilder.h | 3 +- .../StaticAnalyzer/Core/PathSensitive/SVals.h | 2 +- .../StaticAnalyzer/Core/PathSensitive/Store.h | 19 +- .../Core/PathSensitive/SubEngine.h | 2 +- .../clang/Tooling/ArgumentsAdjusters.h | 6 + .../clang/Tooling/CommonOptionsParser.h | 2 +- .../clang/Tooling/CompilationDatabase.h | 14 + .../clang/include/clang/Tooling/Refactoring.h | 103 +- .../include/clang/Tooling/ReplacementsYaml.h | 88 + .../clang/include/clang/Tooling/Tooling.h | 170 +- .../llvm/tools/clang/lib/ARCMigrate/ARCMT.cpp | 13 +- .../clang/lib/ARCMigrate/FileRemapper.cpp | 57 +- .../tools/clang/lib/ARCMigrate/ObjCMT.cpp | 1572 ++- .../lib/ARCMigrate/TransUnbridgedCasts.cpp | 11 +- .../tools/clang/lib/ARCMigrate/Transforms.cpp | 22 +- .../tools/clang/lib/ARCMigrate/Transforms.h | 6 +- contrib/llvm/tools/clang/lib/AST/APValue.cpp | 34 + .../llvm/tools/clang/lib/AST/ASTContext.cpp | 816 +- .../tools/clang/lib/AST/ASTDiagnostic.cpp | 83 +- .../llvm/tools/clang/lib/AST/ASTDumper.cpp | 219 +- .../llvm/tools/clang/lib/AST/ASTImporter.cpp | 291 +- .../tools/clang/lib/AST/ASTTypeTraits.cpp | 105 + contrib/llvm/tools/clang/lib/AST/AttrImpl.cpp | 1 + contrib/llvm/tools/clang/lib/AST/CXXABI.h | 8 +- .../tools/clang/lib/AST/CXXInheritance.cpp | 14 +- contrib/llvm/tools/clang/lib/AST/Comment.cpp | 15 +- .../clang/lib/AST/CommentCommandTraits.cpp | 43 + .../llvm/tools/clang/lib/AST/CommentLexer.cpp | 21 +- .../tools/clang/lib/AST/CommentParser.cpp | 21 + .../llvm/tools/clang/lib/AST/CommentSema.cpp | 145 +- contrib/llvm/tools/clang/lib/AST/Decl.cpp | 800 +- contrib/llvm/tools/clang/lib/AST/DeclBase.cpp | 195 +- contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp | 198 +- .../llvm/tools/clang/lib/AST/DeclFriend.cpp | 5 + contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp | 86 +- .../llvm/tools/clang/lib/AST/DeclOpenMP.cpp | 11 +- .../llvm/tools/clang/lib/AST/DeclPrinter.cpp | 29 +- .../llvm/tools/clang/lib/AST/DeclTemplate.cpp | 357 +- .../tools/clang/lib/AST/DeclarationName.cpp | 142 +- contrib/llvm/tools/clang/lib/AST/DumpXML.cpp | 1055 -- contrib/llvm/tools/clang/lib/AST/Expr.cpp | 462 +- contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp | 268 +- .../clang/lib/AST/ExprClassification.cpp | 13 +- .../llvm/tools/clang/lib/AST/ExprConstant.cpp | 1981 +++- .../llvm/tools/clang/lib/AST/InheritViz.cpp | 38 +- .../tools/clang/lib/AST/ItaniumCXXABI.cpp | 18 + .../tools/clang/lib/AST/ItaniumMangle.cpp | 577 +- contrib/llvm/tools/clang/lib/AST/Mangle.cpp | 153 +- ...Context.cpp => MangleNumberingContext.cpp} | 28 +- .../tools/clang/lib/AST/MicrosoftCXXABI.cpp | 21 + .../tools/clang/lib/AST/MicrosoftMangle.cpp | 990 +- .../clang/lib/AST/NestedNameSpecifier.cpp | 3 +- .../llvm/tools/clang/lib/AST/ParentMap.cpp | 30 +- .../tools/clang/lib/AST/RawCommentList.cpp | 106 +- .../llvm/tools/clang/lib/AST/RecordLayout.cpp | 9 +- .../clang/lib/AST/RecordLayoutBuilder.cpp | 1484 +-- contrib/llvm/tools/clang/lib/AST/Stmt.cpp | 266 +- .../llvm/tools/clang/lib/AST/StmtIterator.cpp | 63 +- .../llvm/tools/clang/lib/AST/StmtPrinter.cpp | 112 +- .../llvm/tools/clang/lib/AST/StmtProfile.cpp | 75 +- .../llvm/tools/clang/lib/AST/TemplateBase.cpp | 81 +- contrib/llvm/tools/clang/lib/AST/Type.cpp | 126 +- contrib/llvm/tools/clang/lib/AST/TypeLoc.cpp | 53 +- .../llvm/tools/clang/lib/AST/TypePrinter.cpp | 134 +- .../tools/clang/lib/AST/VTableBuilder.cpp | 1662 +++- .../clang/lib/ASTMatchers/ASTMatchFinder.cpp | 425 +- .../lib/ASTMatchers/ASTMatchersInternal.cpp | 95 +- .../lib/ASTMatchers/Dynamic/Diagnostics.cpp | 220 + .../lib/ASTMatchers/Dynamic/Marshallers.h | 453 + .../clang/lib/ASTMatchers/Dynamic/Parser.cpp | 420 + .../lib/ASTMatchers/Dynamic/Registry.cpp | 345 + .../lib/ASTMatchers/Dynamic/VariantValue.cpp | 256 + .../lib/Analysis/AnalysisDeclContext.cpp | 39 +- contrib/llvm/tools/clang/lib/Analysis/CFG.cpp | 330 +- .../lib/Analysis/CFGReachabilityAnalysis.cpp | 9 +- .../tools/clang/lib/Analysis/Consumed.cpp | 1521 +++ .../tools/clang/lib/Analysis/FormatString.cpp | 50 +- .../clang/lib/Analysis/LiveVariables.cpp | 3 +- .../clang/lib/Analysis/PrintfFormatString.cpp | 31 +- .../clang/lib/Analysis/ReachableCode.cpp | 13 +- .../clang/lib/Analysis/ScanfFormatString.cpp | 18 +- .../tools/clang/lib/Analysis/ThreadSafety.cpp | 160 +- .../lib/Analysis/UninitializedValues.cpp | 30 +- .../llvm/tools/clang/lib/Basic/Builtins.cpp | 32 +- .../tools/clang/lib/Basic/DiagnosticIDs.cpp | 104 +- .../tools/clang/lib/Basic/FileManager.cpp | 149 +- .../clang/lib/Basic/FileSystemStatCache.cpp | 60 +- .../tools/clang/lib/Basic/IdentifierTable.cpp | 52 +- contrib/llvm/tools/clang/lib/Basic/Module.cpp | 84 +- .../tools/clang/lib/Basic/ObjCRuntime.cpp | 8 +- .../tools/clang/lib/Basic/OpenMPKinds.cpp | 94 +- .../clang/lib/Basic/OperatorPrecedence.cpp | 2 +- .../tools/clang/lib/Basic/SourceManager.cpp | 216 +- .../llvm/tools/clang/lib/Basic/TargetInfo.cpp | 79 +- .../llvm/tools/clang/lib/Basic/Targets.cpp | 2173 +++-- .../llvm/tools/clang/lib/Basic/Version.cpp | 2 +- .../llvm/tools/clang/lib/CodeGen/ABIInfo.h | 147 +- .../tools/clang/lib/CodeGen/BackendUtil.cpp | 40 +- .../llvm/tools/clang/lib/CodeGen/CGAtomic.cpp | 127 +- .../llvm/tools/clang/lib/CodeGen/CGBlocks.cpp | 40 +- .../tools/clang/lib/CodeGen/CGBuiltin.cpp | 2556 ++++- .../tools/clang/lib/CodeGen/CGCUDARuntime.cpp | 4 +- .../llvm/tools/clang/lib/CodeGen/CGCXX.cpp | 255 +- .../llvm/tools/clang/lib/CodeGen/CGCXXABI.cpp | 42 +- .../llvm/tools/clang/lib/CodeGen/CGCXXABI.h | 157 +- .../llvm/tools/clang/lib/CodeGen/CGCall.cpp | 235 +- contrib/llvm/tools/clang/lib/CodeGen/CGCall.h | 200 +- .../llvm/tools/clang/lib/CodeGen/CGClass.cpp | 393 +- .../tools/clang/lib/CodeGen/CGCleanup.cpp | 39 +- .../llvm/tools/clang/lib/CodeGen/CGCleanup.h | 12 +- .../tools/clang/lib/CodeGen/CGDebugInfo.cpp | 1355 ++- .../tools/clang/lib/CodeGen/CGDebugInfo.h | 176 +- .../llvm/tools/clang/lib/CodeGen/CGDecl.cpp | 119 +- .../tools/clang/lib/CodeGen/CGDeclCXX.cpp | 80 +- .../tools/clang/lib/CodeGen/CGException.cpp | 33 +- .../llvm/tools/clang/lib/CodeGen/CGExpr.cpp | 939 +- .../tools/clang/lib/CodeGen/CGExprAgg.cpp | 285 +- .../tools/clang/lib/CodeGen/CGExprCXX.cpp | 235 +- .../tools/clang/lib/CodeGen/CGExprComplex.cpp | 167 +- .../clang/lib/CodeGen/CGExprConstant.cpp | 95 +- .../tools/clang/lib/CodeGen/CGExprScalar.cpp | 402 +- .../llvm/tools/clang/lib/CodeGen/CGObjC.cpp | 30 +- .../tools/clang/lib/CodeGen/CGObjCGNU.cpp | 59 +- .../tools/clang/lib/CodeGen/CGObjCMac.cpp | 29 +- .../tools/clang/lib/CodeGen/CGObjCRuntime.cpp | 1 + .../llvm/tools/clang/lib/CodeGen/CGRTTI.cpp | 62 +- .../lib/CodeGen/CGRecordLayoutBuilder.cpp | 54 +- .../llvm/tools/clang/lib/CodeGen/CGStmt.cpp | 184 +- .../llvm/tools/clang/lib/CodeGen/CGVTT.cpp | 34 +- .../tools/clang/lib/CodeGen/CGVTables.cpp | 362 +- .../llvm/tools/clang/lib/CodeGen/CGVTables.h | 40 +- .../llvm/tools/clang/lib/CodeGen/CGValue.h | 30 +- .../clang/lib/CodeGen/CodeGenABITypes.cpp | 69 + .../tools/clang/lib/CodeGen/CodeGenAction.cpp | 17 + .../clang/lib/CodeGen/CodeGenFunction.cpp | 152 +- .../tools/clang/lib/CodeGen/CodeGenFunction.h | 714 +- .../tools/clang/lib/CodeGen/CodeGenModule.cpp | 723 +- .../tools/clang/lib/CodeGen/CodeGenModule.h | 120 +- .../tools/clang/lib/CodeGen/CodeGenTBAA.cpp | 73 +- .../tools/clang/lib/CodeGen/CodeGenTBAA.h | 2 +- .../tools/clang/lib/CodeGen/CodeGenTypes.cpp | 7 +- .../tools/clang/lib/CodeGen/CodeGenTypes.h | 7 +- .../tools/clang/lib/CodeGen/EHScopeStack.h | 489 + .../tools/clang/lib/CodeGen/ItaniumCXXABI.cpp | 514 +- .../clang/lib/CodeGen/MicrosoftCXXABI.cpp | 1289 ++- .../clang/lib/CodeGen/MicrosoftVBTables.cpp | 233 + .../clang/lib/CodeGen/MicrosoftVBTables.h | 129 + .../tools/clang/lib/CodeGen/ModuleBuilder.cpp | 36 + .../tools/clang/lib/CodeGen/TargetInfo.cpp | 842 +- .../llvm/tools/clang/lib/CodeGen/TargetInfo.h | 34 +- .../llvm/tools/clang/lib/Driver/Action.cpp | 1 + contrib/llvm/tools/clang/lib/Driver/Arg.cpp | 123 - .../llvm/tools/clang/lib/Driver/ArgList.cpp | 423 - .../tools/clang/lib/Driver/CC1AsOptions.cpp | 21 +- .../tools/clang/lib/Driver/Compilation.cpp | 199 +- .../llvm/tools/clang/lib/Driver/Driver.cpp | 512 +- .../tools/clang/lib/Driver/DriverOptions.cpp | 19 +- .../llvm/tools/clang/lib/Driver/InputInfo.h | 11 +- contrib/llvm/tools/clang/lib/Driver/Job.cpp | 163 +- .../llvm/tools/clang/lib/Driver/OptTable.cpp | 388 - .../llvm/tools/clang/lib/Driver/Option.cpp | 200 - .../tools/clang/lib/Driver/SanitizerArgs.cpp | 389 + .../tools/clang/lib/Driver/SanitizerArgs.h | 220 - .../llvm/tools/clang/lib/Driver/ToolChain.cpp | 64 +- .../tools/clang/lib/Driver/ToolChains.cpp | 1199 ++- .../llvm/tools/clang/lib/Driver/ToolChains.h | 300 +- contrib/llvm/tools/clang/lib/Driver/Tools.cpp | 2242 +++-- contrib/llvm/tools/clang/lib/Driver/Tools.h | 188 +- contrib/llvm/tools/clang/lib/Driver/Types.cpp | 17 +- .../clang/lib/Driver/WindowsToolChain.cpp | 55 +- contrib/llvm/tools/clang/lib/Edit/Commit.cpp | 14 +- .../tools/clang/lib/Format/BreakableToken.cpp | 504 +- .../tools/clang/lib/Format/BreakableToken.h | 349 +- .../clang/lib/Format/ContinuationIndenter.cpp | 884 ++ .../clang/lib/Format/ContinuationIndenter.h | 327 + .../llvm/tools/clang/lib/Format/Encoding.h | 144 + .../llvm/tools/clang/lib/Format/Format.cpp | 2231 +++-- .../tools/clang/lib/Format/FormatToken.cpp | 204 + .../llvm/tools/clang/lib/Format/FormatToken.h | 452 + .../tools/clang/lib/Format/TokenAnnotator.cpp | 1096 ++- .../tools/clang/lib/Format/TokenAnnotator.h | 257 +- .../clang/lib/Format/UnwrappedLineParser.cpp | 862 +- .../clang/lib/Format/UnwrappedLineParser.h | 163 +- .../clang/lib/Format/WhitespaceManager.cpp | 413 +- .../clang/lib/Format/WhitespaceManager.h | 182 +- .../tools/clang/lib/Frontend/ASTConsumers.cpp | 54 +- .../llvm/tools/clang/lib/Frontend/ASTUnit.cpp | 294 +- .../tools/clang/lib/Frontend/CacheTokens.cpp | 45 +- .../lib/Frontend/ChainedIncludesSource.cpp | 6 +- .../clang/lib/Frontend/CompilerInstance.cpp | 219 +- .../clang/lib/Frontend/CompilerInvocation.cpp | 281 +- .../CreateInvocationFromCommandLine.cpp | 9 +- .../clang/lib/Frontend/DependencyFile.cpp | 4 +- .../clang/lib/Frontend/FrontendAction.cpp | 12 +- .../clang/lib/Frontend/FrontendActions.cpp | 27 +- .../clang/lib/Frontend/FrontendOptions.cpp | 1 - .../clang/lib/Frontend/HeaderIncludeGen.cpp | 24 +- .../clang/lib/Frontend/InitHeaderSearch.cpp | 55 +- .../clang/lib/Frontend/InitPreprocessor.cpp | 76 +- .../clang/lib/Frontend/MultiplexConsumer.cpp | 20 + .../lib/Frontend/PrintPreprocessedOutput.cpp | 97 +- .../clang/lib/Frontend/TextDiagnostic.cpp | 64 +- .../lib/Frontend/TextDiagnosticPrinter.cpp | 3 +- .../lib/Frontend/VerifyDiagnosticConsumer.cpp | 8 +- .../ExecuteCompilerInvocation.cpp | 60 +- contrib/llvm/tools/clang/lib/Headers/Intrin.h | 784 ++ .../llvm/tools/clang/lib/Headers/avx2intrin.h | 25 +- .../llvm/tools/clang/lib/Headers/avxintrin.h | 22 +- .../llvm/tools/clang/lib/Headers/emmintrin.h | 34 +- .../llvm/tools/clang/lib/Headers/f16cintrin.h | 4 +- .../llvm/tools/clang/lib/Headers/immintrin.h | 4 + contrib/llvm/tools/clang/lib/Headers/limits.h | 6 +- .../llvm/tools/clang/lib/Headers/module.map | 11 + .../tools/clang/lib/Headers/prfchwintrin.h | 5 + .../tools/clang/lib/Headers/rdseedintrin.h | 4 + .../llvm/tools/clang/lib/Headers/rtmintrin.h | 5 + .../llvm/tools/clang/lib/Headers/shaintrin.h | 74 + .../llvm/tools/clang/lib/Headers/smmintrin.h | 15 +- .../llvm/tools/clang/lib/Headers/tbmintrin.h | 158 + contrib/llvm/tools/clang/lib/Headers/tgmath.h | 6 +- contrib/llvm/tools/clang/lib/Headers/unwind.h | 159 +- .../llvm/tools/clang/lib/Headers/x86intrin.h | 4 + .../llvm/tools/clang/lib/Headers/xmmintrin.h | 18 +- .../llvm/tools/clang/lib/Headers/xopintrin.h | 393 + .../tools/clang/lib/Index/CommentToXML.cpp | 1136 +++ .../clang/lib/Index/SimpleFormatContext.h | 77 + .../tools/clang/lib/Index/USRGeneration.cpp | 803 ++ .../llvm/tools/clang/lib/Lex/HeaderMap.cpp | 2 +- .../llvm/tools/clang/lib/Lex/HeaderSearch.cpp | 125 +- contrib/llvm/tools/clang/lib/Lex/Lexer.cpp | 470 +- .../tools/clang/lib/Lex/LiteralSupport.cpp | 156 +- .../llvm/tools/clang/lib/Lex/ModuleMap.cpp | 392 +- .../lib/Lex/PPConditionalDirectiveRecord.cpp | 4 +- .../llvm/tools/clang/lib/Lex/PPDirectives.cpp | 219 +- .../tools/clang/lib/Lex/PPExpressions.cpp | 29 +- .../tools/clang/lib/Lex/PPLexerChange.cpp | 86 +- .../tools/clang/lib/Lex/PPMacroExpansion.cpp | 280 +- contrib/llvm/tools/clang/lib/Lex/PTHLexer.cpp | 89 +- contrib/llvm/tools/clang/lib/Lex/Pragma.cpp | 206 +- .../clang/lib/Lex/PreprocessingRecord.cpp | 3 +- .../llvm/tools/clang/lib/Lex/Preprocessor.cpp | 48 +- .../tools/clang/lib/Lex/PreprocessorLexer.cpp | 5 +- .../llvm/tools/clang/lib/Lex/TokenLexer.cpp | 61 +- .../tools/clang/lib/Lex/UnicodeCharSets.h | 102 +- .../llvm/tools/clang/lib/Parse/ParseAST.cpp | 2 +- .../clang/lib/Parse/ParseCXXInlineMethods.cpp | 548 +- .../llvm/tools/clang/lib/Parse/ParseDecl.cpp | 723 +- .../tools/clang/lib/Parse/ParseDeclCXX.cpp | 427 +- .../llvm/tools/clang/lib/Parse/ParseExpr.cpp | 172 +- .../tools/clang/lib/Parse/ParseExprCXX.cpp | 252 +- .../llvm/tools/clang/lib/Parse/ParseInit.cpp | 10 +- .../llvm/tools/clang/lib/Parse/ParseObjc.cpp | 109 +- .../tools/clang/lib/Parse/ParseOpenMP.cpp | 347 +- .../tools/clang/lib/Parse/ParsePragma.cpp | 85 +- .../llvm/tools/clang/lib/Parse/ParsePragma.h | 15 +- .../llvm/tools/clang/lib/Parse/ParseStmt.cpp | 209 +- .../tools/clang/lib/Parse/ParseTemplate.cpp | 115 +- .../tools/clang/lib/Parse/ParseTentative.cpp | 418 +- contrib/llvm/tools/clang/lib/Parse/Parser.cpp | 184 +- .../clang/lib/Parse/RAIIObjectsForParser.h | 7 +- .../clang/lib/Rewrite/Core/HTMLRewrite.cpp | 5 +- .../tools/clang/lib/Rewrite/Core/Rewriter.cpp | 5 +- .../lib/Rewrite/Frontend/FixItRewriter.cpp | 2 +- .../lib/Rewrite/Frontend/FrontendActions.cpp | 10 +- .../Rewrite/Frontend/InclusionRewriter.cpp | 71 +- .../lib/Rewrite/Frontend/RewriteMacros.cpp | 2 +- .../Rewrite/Frontend/RewriteModernObjC.cpp | 208 +- .../lib/Rewrite/Frontend/RewriteObjC.cpp | 66 +- .../clang/lib/Sema/AnalysisBasedWarnings.cpp | 213 +- .../tools/clang/lib/Sema/AttributeList.cpp | 40 +- .../llvm/tools/clang/lib/Sema/DeclSpec.cpp | 100 +- .../clang/lib/Sema/IdentifierResolver.cpp | 40 +- .../tools/clang/lib/Sema/JumpDiagnostics.cpp | 9 +- .../lib/Sema/MultiplexExternalSemaSource.cpp | 31 + .../llvm/tools/clang/lib/Sema/ScopeInfo.cpp | 15 + contrib/llvm/tools/clang/lib/Sema/Sema.cpp | 188 +- .../llvm/tools/clang/lib/Sema/SemaAccess.cpp | 30 +- .../llvm/tools/clang/lib/Sema/SemaAttr.cpp | 42 +- .../tools/clang/lib/Sema/SemaCXXScopeSpec.cpp | 50 +- .../llvm/tools/clang/lib/Sema/SemaCast.cpp | 142 +- .../tools/clang/lib/Sema/SemaChecking.cpp | 844 +- .../tools/clang/lib/Sema/SemaCodeComplete.cpp | 218 +- .../llvm/tools/clang/lib/Sema/SemaDecl.cpp | 2400 +++-- .../tools/clang/lib/Sema/SemaDeclAttr.cpp | 1947 ++-- .../llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp | 2110 ++-- .../tools/clang/lib/Sema/SemaDeclObjC.cpp | 408 +- .../clang/lib/Sema/SemaExceptionSpec.cpp | 204 +- .../llvm/tools/clang/lib/Sema/SemaExpr.cpp | 2490 +++-- .../llvm/tools/clang/lib/Sema/SemaExprCXX.cpp | 972 +- .../tools/clang/lib/Sema/SemaExprMember.cpp | 175 +- .../tools/clang/lib/Sema/SemaExprObjC.cpp | 296 +- .../tools/clang/lib/Sema/SemaFixItUtils.cpp | 28 +- .../llvm/tools/clang/lib/Sema/SemaInit.cpp | 1166 ++- .../llvm/tools/clang/lib/Sema/SemaLambda.cpp | 948 +- .../llvm/tools/clang/lib/Sema/SemaLookup.cpp | 924 +- .../tools/clang/lib/Sema/SemaObjCProperty.cpp | 444 +- .../llvm/tools/clang/lib/Sema/SemaOpenMP.cpp | 1207 ++- .../tools/clang/lib/Sema/SemaOverload.cpp | 1531 +-- .../tools/clang/lib/Sema/SemaPseudoObject.cpp | 39 +- .../llvm/tools/clang/lib/Sema/SemaStmt.cpp | 573 +- .../llvm/tools/clang/lib/Sema/SemaStmtAsm.cpp | 11 +- .../tools/clang/lib/Sema/SemaTemplate.cpp | 1386 ++- .../clang/lib/Sema/SemaTemplateDeduction.cpp | 699 +- .../lib/Sema/SemaTemplateInstantiate.cpp | 295 +- .../lib/Sema/SemaTemplateInstantiateDecl.cpp | 1403 ++- .../clang/lib/Sema/SemaTemplateVariadic.cpp | 97 +- .../llvm/tools/clang/lib/Sema/SemaType.cpp | 804 +- .../clang/lib/Sema/TargetAttributesSema.cpp | 136 +- .../llvm/tools/clang/lib/Sema/TreeTransform.h | 691 +- .../tools/clang/lib/Sema/TypeLocBuilder.cpp | 136 + .../tools/clang/lib/Sema/TypeLocBuilder.h | 86 +- .../clang/lib/Serialization/ASTCommon.cpp | 5 +- .../tools/clang/lib/Serialization/ASTCommon.h | 4 +- .../clang/lib/Serialization/ASTReader.cpp | 293 +- .../clang/lib/Serialization/ASTReaderDecl.cpp | 772 +- .../clang/lib/Serialization/ASTReaderStmt.cpp | 145 +- .../clang/lib/Serialization/ASTWriter.cpp | 229 +- .../clang/lib/Serialization/ASTWriterDecl.cpp | 170 +- .../clang/lib/Serialization/ASTWriterStmt.cpp | 110 +- .../clang/lib/Serialization/GeneratePCH.cpp | 17 +- .../lib/Serialization/GlobalModuleIndex.cpp | 8 +- .../clang/lib/Serialization/ModuleManager.cpp | 13 +- .../Checkers/BasicObjCFoundationChecks.cpp | 365 +- .../Checkers/BuiltinFunctionChecker.cpp | 30 +- .../Checkers/CStringChecker.cpp | 84 +- .../Checkers/CStringSyntaxChecker.cpp | 3 +- .../Checkers/CallAndMessageChecker.cpp | 59 +- .../Checkers/CheckSecuritySyntaxOnly.cpp | 63 +- .../Checkers/CheckSizeofPointer.cpp | 5 +- .../Checkers/CheckerDocumentation.cpp | 2 +- .../lib/StaticAnalyzer/Checkers/Checkers.td | 8 + .../StaticAnalyzer/Checkers/ClangSACheckers.h | 2 +- .../Checkers/DeadStoresChecker.cpp | 42 +- .../StaticAnalyzer/Checkers/DebugCheckers.cpp | 49 +- .../Checkers/DirectIvarAssignment.cpp | 50 +- .../Checkers/DynamicTypePropagation.cpp | 4 +- .../Checkers/ExprInspectionChecker.cpp | 20 + .../Checkers/GenericTaintChecker.cpp | 3 +- .../Checkers/IdempotentOperationChecker.cpp | 19 +- .../Checkers/IdenticalExprChecker.cpp | 226 + .../StaticAnalyzer/Checkers/MallocChecker.cpp | 120 +- .../MallocOverflowSecurityChecker.cpp | 4 +- .../Checkers/MallocSizeofChecker.cpp | 2 +- .../Checkers/NoReturnFunctionChecker.cpp | 27 +- .../Checkers/ObjCContainersASTChecker.cpp | 3 +- .../Checkers/RetainCountChecker.cpp | 220 +- .../Checkers/SimpleStreamChecker.cpp | 8 +- .../Checkers/UndefResultChecker.cpp | 9 + .../UndefinedArraySubscriptChecker.cpp | 3 +- .../Checkers/UndefinedAssignmentChecker.cpp | 8 + .../Checkers/UnreachableCodeChecker.cpp | 3 + .../Checkers/VirtualCallChecker.cpp | 4 +- .../StaticAnalyzer/Core/AnalyzerOptions.cpp | 12 + .../lib/StaticAnalyzer/Core/BugReporter.cpp | 1194 ++- .../Core/BugReporterVisitors.cpp | 90 +- .../lib/StaticAnalyzer/Core/CallEvent.cpp | 61 +- .../StaticAnalyzer/Core/CheckerContext.cpp | 2 +- .../StaticAnalyzer/Core/CheckerManager.cpp | 42 +- .../CommonBugCategories.cpp | 10 +- .../lib/StaticAnalyzer/Core/ExplodedGraph.cpp | 6 +- .../lib/StaticAnalyzer/Core/ExprEngine.cpp | 143 +- .../lib/StaticAnalyzer/Core/ExprEngineC.cpp | 79 +- .../lib/StaticAnalyzer/Core/ExprEngineCXX.cpp | 92 +- .../Core/ExprEngineCallAndReturn.cpp | 45 +- .../StaticAnalyzer/Core/HTMLDiagnostics.cpp | 59 +- .../lib/StaticAnalyzer/Core/MemRegion.cpp | 85 +- .../StaticAnalyzer/Core/PathDiagnostic.cpp | 83 +- .../StaticAnalyzer/Core/PlistDiagnostics.cpp | 28 +- .../Core/PrettyStackTraceLocationContext.h | 45 + .../lib/StaticAnalyzer/Core/ProgramState.cpp | 126 +- .../lib/StaticAnalyzer/Core/RegionStore.cpp | 139 +- .../lib/StaticAnalyzer/Core/SValBuilder.cpp | 36 +- .../Core/SimpleConstraintManager.cpp | 59 +- .../Core/SimpleConstraintManager.h | 6 - .../StaticAnalyzer/Core/SimpleSValBuilder.cpp | 212 +- .../clang/lib/StaticAnalyzer/Core/Store.cpp | 5 +- .../lib/StaticAnalyzer/Core/SymbolManager.cpp | 6 +- .../Core/TextPathDiagnostics.cpp | 72 - .../Frontend/AnalysisConsumer.cpp | 120 +- .../clang/lib/Tooling/ArgumentsAdjusters.cpp | 29 +- .../clang/lib/Tooling/CommonOptionsParser.cpp | 5 +- .../clang/lib/Tooling/CompilationDatabase.cpp | 185 +- .../tools/clang/lib/Tooling/FileMatchTrie.cpp | 2 +- .../lib/Tooling/JSONCompilationDatabase.cpp | 4 +- .../tools/clang/lib/Tooling/Refactoring.cpp | 190 +- .../llvm/tools/clang/lib/Tooling/Tooling.cpp | 232 +- .../tools/clang/tools/driver/cc1_main.cpp | 7 +- .../tools/clang/tools/driver/cc1as_main.cpp | 46 +- .../llvm/tools/clang/tools/driver/driver.cpp | 208 +- .../clang/utils/TableGen/ClangAttrEmitter.cpp | 395 +- .../ClangCommentCommandInfoEmitter.cpp | 1 + .../TableGen/ClangDiagnosticsEmitter.cpp | 172 +- .../clang/utils/TableGen/NeonEmitter.cpp | 1508 ++- .../clang/utils/TableGen/OptParserEmitter.cpp | 275 - .../tools/clang/utils/TableGen/TableGen.cpp | 191 +- .../clang/utils/TableGen/TableGenBackends.h | 6 +- contrib/llvm/tools/llc/llc.cpp | 9 +- .../tools/lli/ChildTarget/ChildTarget.cpp | 242 + .../lli/ChildTarget/Unix/ChildTarget.inc | 166 + .../lli/ChildTarget/Windows/ChildTarget.inc | 44 + .../llvm/tools/lli/RecordingMemoryManager.cpp | 128 - .../llvm/tools/lli/RecordingMemoryManager.h | 87 - .../llvm/tools/lli/RemoteMemoryManager.cpp | 206 + contrib/llvm/tools/lli/RemoteMemoryManager.h | 114 + contrib/llvm/tools/lli/RemoteTarget.cpp | 31 + contrib/llvm/tools/lli/RemoteTarget.h | 27 +- .../llvm/tools/lli/RemoteTargetExternal.cpp | 162 + contrib/llvm/tools/lli/RemoteTargetExternal.h | 118 + contrib/llvm/tools/lli/RemoteTargetMessage.h | 45 + .../tools/lli/Unix/RemoteTargetExternal.inc | 96 + .../lli/Windows/RemoteTargetExternal.inc | 35 + contrib/llvm/tools/lli/lli.cpp | 322 +- contrib/llvm/tools/llvm-ar/llvm-ar.cpp | 1146 ++- contrib/llvm/tools/llvm-as/llvm-as.cpp | 5 +- .../tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp | 3 +- .../llvm/tools/llvm-diff/DifferenceEngine.cpp | 10 +- contrib/llvm/tools/llvm-diff/llvm-diff.cpp | 2 +- contrib/llvm/tools/llvm-dis/llvm-dis.cpp | 5 +- .../llvm/tools/llvm-extract/llvm-extract.cpp | 5 +- contrib/llvm/tools/llvm-link/llvm-link.cpp | 18 +- contrib/llvm/tools/llvm-mc/Disassembler.cpp | 72 +- contrib/llvm/tools/llvm-mc/llvm-mc.cpp | 22 +- contrib/llvm/tools/llvm-nm/llvm-nm.cpp | 279 +- contrib/llvm/tools/llvm-objdump/COFFDump.cpp | 50 +- contrib/llvm/tools/llvm-objdump/ELFDump.cpp | 30 +- .../llvm/tools/llvm-objdump/MCFunction.cpp | 138 - contrib/llvm/tools/llvm-objdump/MCFunction.h | 100 - contrib/llvm/tools/llvm-objdump/MachODump.cpp | 456 +- .../llvm/tools/llvm-objdump/llvm-objdump.cpp | 246 +- .../llvm/tools/llvm-objdump/llvm-objdump.h | 22 +- contrib/llvm/tools/llvm-prof/llvm-prof.cpp | 293 - .../llvm/tools/llvm-ranlib/llvm-ranlib.cpp | 98 - .../llvm/tools/llvm-readobj/COFFDumper.cpp | 126 +- contrib/llvm/tools/llvm-readobj/ELFDumper.cpp | 427 +- .../llvm/tools/llvm-readobj/MachODumper.cpp | 75 +- .../llvm/tools/llvm-readobj/llvm-readobj.cpp | 7 +- .../llvm/tools/llvm-rtdyld/llvm-rtdyld.cpp | 30 +- .../llvm/tools/llvm-stress/llvm-stress.cpp | 9 +- .../tools/llvm-symbolizer/LLVMSymbolize.cpp | 254 +- .../tools/llvm-symbolizer/LLVMSymbolize.h | 40 +- .../tools/llvm-symbolizer/llvm-symbolizer.cpp | 6 +- contrib/llvm/tools/macho-dump/macho-dump.cpp | 245 +- contrib/llvm/tools/opt/opt.cpp | 55 +- .../llvm/utils/TableGen/AsmMatcherEmitter.cpp | 278 +- .../llvm/utils/TableGen/AsmWriterEmitter.cpp | 138 +- contrib/llvm/utils/TableGen/AsmWriterInst.cpp | 55 +- .../utils/TableGen/CodeGenDAGPatterns.cpp | 160 +- .../llvm/utils/TableGen/CodeGenDAGPatterns.h | 6 +- .../utils/TableGen/CodeGenInstruction.cpp | 17 +- .../llvm/utils/TableGen/CodeGenInstruction.h | 3 + .../llvm/utils/TableGen/CodeGenIntrinsics.h | 4 +- .../llvm/utils/TableGen/CodeGenMapTable.cpp | 1 - .../llvm/utils/TableGen/CodeGenRegisters.cpp | 244 +- .../llvm/utils/TableGen/CodeGenRegisters.h | 43 +- .../llvm/utils/TableGen/CodeGenSchedule.cpp | 63 +- contrib/llvm/utils/TableGen/CodeGenSchedule.h | 5 +- contrib/llvm/utils/TableGen/CodeGenTarget.cpp | 15 +- .../llvm/utils/TableGen/DAGISelEmitter.cpp | 16 +- .../llvm/utils/TableGen/DAGISelMatcher.cpp | 6 +- contrib/llvm/utils/TableGen/DAGISelMatcher.h | 32 +- .../utils/TableGen/DAGISelMatcherEmitter.cpp | 15 +- .../llvm/utils/TableGen/DAGISelMatcherOpt.cpp | 6 +- .../llvm/utils/TableGen/FastISelEmitter.cpp | 92 +- .../utils/TableGen/FixedLenDecoderEmitter.cpp | 22 +- .../llvm/utils/TableGen/InstrInfoEmitter.cpp | 205 +- .../llvm/utils/TableGen/IntrinsicEmitter.cpp | 178 +- .../llvm/utils/TableGen/OptParserEmitter.cpp | 40 +- .../utils/TableGen/RegisterInfoEmitter.cpp | 83 +- .../utils/TableGen/SequenceToOffsetTable.h | 1 + contrib/llvm/utils/TableGen/SetTheory.cpp | 49 +- .../llvm/utils/TableGen/SubtargetEmitter.cpp | 20 +- contrib/llvm/utils/TableGen/TGValueTypes.cpp | 11 +- .../utils/TableGen/X86DisassemblerTables.cpp | 244 +- .../utils/TableGen/X86DisassemblerTables.h | 60 +- .../utils/TableGen/X86RecognizableInstr.cpp | 306 +- .../utils/TableGen/X86RecognizableInstr.h | 12 + etc/mtree/BSD.include.dist | 2 +- lib/clang/Makefile | 2 +- lib/clang/clang.build.mk | 21 +- lib/clang/include/Makefile | 17 +- lib/clang/include/PPCGenFastISel.inc | 2 + lib/clang/include/clang/Basic/Version.inc | 8 +- .../include/clang/Parse/AttrExprArgs.inc | 2 - .../include/clang/Parse/AttrIdentifierArg.inc | 2 + lib/clang/include/clang/Parse/AttrTypeArg.inc | 2 + .../include/clang/Sema/AttrParsedAttrImpl.inc | 2 + lib/clang/include/llvm/Config/config.h | 107 +- lib/clang/include/llvm/Config/llvm-config.h | 5 +- lib/clang/libclanganalysis/Makefile | 1 + lib/clang/libclangast/Makefile | 4 +- lib/clang/libclangcodegen/Makefile | 3 + lib/clang/libclangdriver/Makefile | 6 +- lib/clang/libclangparse/Makefile | 5 +- lib/clang/libclangsema/Makefile | 4 +- .../libclangstaticanalyzercheckers/Makefile | 4 +- lib/clang/libclangstaticanalyzercore/Makefile | 4 +- lib/clang/libllvmanalysis/Makefile | 12 +- lib/clang/libllvmarchive/Makefile | 12 - lib/clang/libllvmarmdesc/Makefile | 3 +- lib/clang/libllvmasmprinter/Makefile | 1 + lib/clang/libllvmcodegen/Makefile | 4 +- lib/clang/libllvmcore/Makefile | 1 + lib/clang/libllvmdebuginfo/Makefile | 5 +- lib/clang/libllvmexecutionengine/Makefile | 1 + lib/clang/libllvminstrumentation/Makefile | 7 +- lib/clang/libllvmjit/Makefile | 1 - lib/clang/libllvmmc/Makefile | 8 + lib/clang/libllvmmipscodegen/Makefile | 1 + lib/clang/libllvmmipsdesc/Makefile | 5 +- lib/clang/libllvmobject/Makefile | 7 +- lib/clang/libllvmoption/Makefile | 13 + lib/clang/libllvmpowerpccodegen/Makefile | 3 + lib/clang/libllvmpowerpcdesc/Makefile | 6 +- lib/clang/libllvmscalaropts/Makefile | 13 +- lib/clang/libllvmsupport/Makefile | 6 +- lib/clang/libllvmtransformutils/Makefile | 3 + lib/clang/libllvmvectorize/Makefile | 1 - lib/clang/libllvmx86desc/Makefile | 4 +- share/mk/bsd.sys.mk | 2 +- sys/amd64/conf/GENERIC | 2 +- sys/conf/kern.mk | 2 +- sys/i386/conf/GENERIC | 2 +- sys/i386/conf/XEN | 2 +- sys/sys/param.h | 2 +- tools/build/mk/OptionalObsoleteFiles.inc | 155 +- usr.bin/clang/Makefile | 2 - usr.bin/clang/bugpoint/bugpoint.1 | 14 +- usr.bin/clang/clang-tblgen/Makefile | 1 - usr.bin/clang/clang.prog.mk | 3 + usr.bin/clang/clang/Makefile | 5 +- usr.bin/clang/clang/clang.1 | 104 +- usr.bin/clang/llc/Makefile | 4 +- usr.bin/clang/llc/llc.1 | 38 +- usr.bin/clang/lli/Makefile | 6 +- usr.bin/clang/lli/lli.1 | 6 +- usr.bin/clang/llvm-ar/Makefile | 2 +- usr.bin/clang/llvm-ar/llvm-ar.1 | 146 +- usr.bin/clang/llvm-as/llvm-as.1 | 14 +- .../clang/llvm-bcanalyzer/llvm-bcanalyzer.1 | 6 +- usr.bin/clang/llvm-diff/llvm-diff.1 | 6 +- usr.bin/clang/llvm-dis/llvm-dis.1 | 8 +- usr.bin/clang/llvm-extract/llvm-extract.1 | 35 +- usr.bin/clang/llvm-link/llvm-link.1 | 6 +- usr.bin/clang/llvm-mc/Makefile | 4 +- usr.bin/clang/llvm-nm/Makefile | 1 - usr.bin/clang/llvm-nm/llvm-nm.1 | 22 +- usr.bin/clang/llvm-objdump/Makefile | 7 +- usr.bin/clang/llvm-prof/Makefile | 18 - usr.bin/clang/llvm-prof/llvm-prof.1 | 86 - usr.bin/clang/llvm-ranlib/Makefile | 15 - usr.bin/clang/llvm-ranlib/llvm-ranlib.1 | 80 - usr.bin/clang/llvm-rtdyld/Makefile | 4 +- usr.bin/clang/opt/Makefile | 4 +- usr.bin/clang/opt/opt.1 | 30 +- usr.bin/clang/tblgen/tblgen.1 | 16 +- 2339 files changed, 259708 insertions(+), 138204 deletions(-) create mode 100644 contrib/llvm/include/llvm-c/IRReader.h create mode 100644 contrib/llvm/include/llvm-c/Support.h delete mode 100644 contrib/llvm/include/llvm/ADT/NullablePtr.h create mode 100644 contrib/llvm/include/llvm/ADT/polymorphic_ptr.h create mode 100644 contrib/llvm/include/llvm/Analysis/CFG.h delete mode 100644 contrib/llvm/include/llvm/Analysis/PathNumbering.h delete mode 100644 contrib/llvm/include/llvm/Analysis/PathProfileInfo.h delete mode 100644 contrib/llvm/include/llvm/Analysis/ProfileDataLoader.h delete mode 100644 contrib/llvm/include/llvm/Analysis/ProfileDataTypes.h delete mode 100644 contrib/llvm/include/llvm/Analysis/ProfileInfo.h delete mode 100644 contrib/llvm/include/llvm/Analysis/ProfileInfoLoader.h delete mode 100644 contrib/llvm/include/llvm/Analysis/ProfileInfoTypes.h delete mode 100644 contrib/llvm/include/llvm/Bitcode/Archive.h create mode 100644 contrib/llvm/include/llvm/CodeGen/LiveRegUnits.h create mode 100644 contrib/llvm/include/llvm/CodeGen/StackMaps.h create mode 100644 contrib/llvm/include/llvm/CodeGen/StackProtector.h create mode 100644 contrib/llvm/include/llvm/ExecutionEngine/RTDyldMemoryManager.h create mode 100644 contrib/llvm/include/llvm/IR/IntrinsicsAArch64.td create mode 100644 contrib/llvm/include/llvm/IR/LegacyPassManager.h rename contrib/llvm/include/llvm/{PassManagers.h => IR/LegacyPassManagers.h} (99%) create mode 100644 contrib/llvm/include/llvm/IR/PassManager.h create mode 100644 contrib/llvm/include/llvm/LTO/LTOCodeGenerator.h create mode 100644 contrib/llvm/include/llvm/LTO/LTOModule.h create mode 100644 contrib/llvm/include/llvm/MC/MCAsmInfoELF.h create mode 100644 contrib/llvm/include/llvm/MC/MCExternalSymbolizer.h create mode 100644 contrib/llvm/include/llvm/MC/MCFunction.h create mode 100644 contrib/llvm/include/llvm/MC/MCModuleYAML.h create mode 100644 contrib/llvm/include/llvm/MC/MCObjectDisassembler.h create mode 100644 contrib/llvm/include/llvm/MC/MCObjectSymbolizer.h create mode 100644 contrib/llvm/include/llvm/MC/MCRelocationInfo.h create mode 100644 contrib/llvm/include/llvm/MC/MCSymbolizer.h create mode 100644 contrib/llvm/include/llvm/Object/COFFYAML.h create mode 100644 contrib/llvm/include/llvm/Object/ELFObjectFile.h create mode 100644 contrib/llvm/include/llvm/Object/ELFTypes.h create mode 100644 contrib/llvm/include/llvm/Object/ELFYAML.h delete mode 100644 contrib/llvm/include/llvm/Object/MachOFormat.h create mode 100644 contrib/llvm/include/llvm/Object/MachOUniversal.h create mode 100644 contrib/llvm/include/llvm/Object/YAML.h delete mode 100644 contrib/llvm/include/llvm/Support/IntegersSubset.h delete mode 100644 contrib/llvm/include/llvm/Support/IntegersSubsetMapping.h create mode 100644 contrib/llvm/include/llvm/Support/MD5.h delete mode 100644 contrib/llvm/include/llvm/Support/PathV1.h delete mode 100644 contrib/llvm/include/llvm/Support/PathV2.h create mode 100644 contrib/llvm/include/llvm/Support/StringRefMemoryObject.h create mode 100644 contrib/llvm/include/llvm/Support/Unicode.h create mode 100644 contrib/llvm/include/llvm/Support/UnicodeCharRanges.h rename contrib/llvm/{utils => include/llvm}/TableGen/StringToOffsetTable.h (100%) delete mode 100644 contrib/llvm/include/llvm/Transforms/Utils/BlackList.h create mode 100644 contrib/llvm/include/llvm/Transforms/Utils/GlobalStatus.h create mode 100644 contrib/llvm/include/llvm/Transforms/Utils/LoopUtils.h create mode 100644 contrib/llvm/include/llvm/Transforms/Utils/SpecialCaseList.h create mode 100644 contrib/llvm/lib/Analysis/CFG.cpp create mode 100644 contrib/llvm/lib/Analysis/Delinearization.cpp delete mode 100644 contrib/llvm/lib/Analysis/PathNumbering.cpp delete mode 100644 contrib/llvm/lib/Analysis/PathProfileInfo.cpp delete mode 100644 contrib/llvm/lib/Analysis/PathProfileVerifier.cpp delete mode 100644 contrib/llvm/lib/Analysis/ProfileDataLoader.cpp delete mode 100644 contrib/llvm/lib/Analysis/ProfileDataLoaderPass.cpp delete mode 100644 contrib/llvm/lib/Analysis/ProfileEstimatorPass.cpp delete mode 100644 contrib/llvm/lib/Analysis/ProfileInfo.cpp delete mode 100644 contrib/llvm/lib/Analysis/ProfileInfoLoader.cpp delete mode 100644 contrib/llvm/lib/Analysis/ProfileInfoLoaderPass.cpp delete mode 100644 contrib/llvm/lib/Analysis/ProfileVerifierPass.cpp delete mode 100644 contrib/llvm/lib/Archive/Archive.cpp delete mode 100644 contrib/llvm/lib/Archive/ArchiveInternals.h delete mode 100644 contrib/llvm/lib/Archive/ArchiveReader.cpp delete mode 100644 contrib/llvm/lib/Archive/ArchiveWriter.cpp create mode 100644 contrib/llvm/lib/CodeGen/AsmPrinter/DIEHash.cpp create mode 100644 contrib/llvm/lib/CodeGen/AsmPrinter/DIEHash.h create mode 100644 contrib/llvm/lib/CodeGen/LiveRegUnits.cpp delete mode 100644 contrib/llvm/lib/CodeGen/SelectionDAG/SDNodeOrdering.h delete mode 100644 contrib/llvm/lib/CodeGen/ShrinkWrapping.cpp create mode 100644 contrib/llvm/lib/CodeGen/StackMaps.cpp delete mode 100644 contrib/llvm/lib/CodeGen/StrongPHIElimination.cpp delete mode 100644 contrib/llvm/lib/DebugInfo/DWARFAttribute.h create mode 100644 contrib/llvm/lib/DebugInfo/DWARFDebugLoc.cpp create mode 100644 contrib/llvm/lib/DebugInfo/DWARFDebugLoc.h create mode 100644 contrib/llvm/lib/DebugInfo/DWARFTypeUnit.cpp create mode 100644 contrib/llvm/lib/DebugInfo/DWARFTypeUnit.h create mode 100644 contrib/llvm/lib/DebugInfo/DWARFUnit.cpp create mode 100644 contrib/llvm/lib/DebugInfo/DWARFUnit.h delete mode 100644 contrib/llvm/lib/ExecutionEngine/JIT/JITDwarfEmitter.cpp delete mode 100644 contrib/llvm/lib/ExecutionEngine/JIT/JITDwarfEmitter.h create mode 100644 contrib/llvm/lib/ExecutionEngine/RTDyldMemoryManager.cpp create mode 100644 contrib/llvm/lib/IR/AsmWriter.h create mode 100644 contrib/llvm/lib/IR/LegacyPassManager.cpp create mode 100644 contrib/llvm/lib/LTO/LTOCodeGenerator.cpp create mode 100644 contrib/llvm/lib/LTO/LTOModule.cpp create mode 100644 contrib/llvm/lib/MC/MCAsmInfoELF.cpp create mode 100644 contrib/llvm/lib/MC/MCExternalSymbolizer.cpp create mode 100644 contrib/llvm/lib/MC/MCFunction.cpp create mode 100644 contrib/llvm/lib/MC/MCModuleYAML.cpp create mode 100644 contrib/llvm/lib/MC/MCObjectDisassembler.cpp create mode 100644 contrib/llvm/lib/MC/MCObjectSymbolizer.cpp create mode 100644 contrib/llvm/lib/MC/MCRelocationInfo.cpp create mode 100644 contrib/llvm/lib/MC/MCSymbolizer.cpp create mode 100644 contrib/llvm/lib/Object/COFFYAML.cpp create mode 100644 contrib/llvm/lib/Object/ELF.cpp create mode 100644 contrib/llvm/lib/Object/ELFYAML.cpp create mode 100644 contrib/llvm/lib/Object/MachOUniversal.cpp create mode 100644 contrib/llvm/lib/Object/YAML.cpp delete mode 100644 contrib/llvm/lib/Support/LocaleGeneric.inc delete mode 100644 contrib/llvm/lib/Support/LocaleWindows.inc delete mode 100644 contrib/llvm/lib/Support/LocaleXlocale.inc create mode 100644 contrib/llvm/lib/Support/MD5.cpp delete mode 100644 contrib/llvm/lib/Support/PathV2.cpp create mode 100644 contrib/llvm/lib/Support/StringRefMemoryObject.cpp create mode 100644 contrib/llvm/lib/Support/Unicode.cpp delete mode 100644 contrib/llvm/lib/Support/Unix/PathV2.inc delete mode 100644 contrib/llvm/lib/Support/Windows/PathV2.inc create mode 100644 contrib/llvm/lib/Target/AArch64/AArch64InstrNEON.td create mode 100644 contrib/llvm/lib/Target/ARM/ARMFPUName.def create mode 100644 contrib/llvm/lib/Target/ARM/ARMFPUName.h create mode 100644 contrib/llvm/lib/Target/ARM/ARMFeatures.h delete mode 100644 contrib/llvm/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.h create mode 100644 contrib/llvm/lib/Target/ARM/MCTargetDesc/ARMMachORelocationInfo.cpp create mode 100644 contrib/llvm/lib/Target/Hexagon/HexagonCopyToCombine.cpp rename contrib/llvm/lib/Target/{MBlaze/MBlazeMachineFunction.cpp => Hexagon/HexagonMachineFunctionInfo.cpp} (59%) create mode 100644 contrib/llvm/lib/Target/Hexagon/HexagonSplitConst32AndConst64.cpp delete mode 100644 contrib/llvm/lib/Target/MBlaze/AsmParser/MBlazeAsmParser.cpp delete mode 100644 contrib/llvm/lib/Target/MBlaze/Disassembler/MBlazeDisassembler.cpp delete mode 100644 contrib/llvm/lib/Target/MBlaze/Disassembler/MBlazeDisassembler.h delete mode 100644 contrib/llvm/lib/Target/MBlaze/InstPrinter/MBlazeInstPrinter.cpp delete mode 100644 contrib/llvm/lib/Target/MBlaze/InstPrinter/MBlazeInstPrinter.h delete mode 100644 contrib/llvm/lib/Target/MBlaze/MBlaze.h delete mode 100644 contrib/llvm/lib/Target/MBlaze/MBlaze.td delete mode 100644 contrib/llvm/lib/Target/MBlaze/MBlazeAsmPrinter.cpp delete mode 100644 contrib/llvm/lib/Target/MBlaze/MBlazeCallingConv.td delete mode 100644 contrib/llvm/lib/Target/MBlaze/MBlazeDelaySlotFiller.cpp delete mode 100644 contrib/llvm/lib/Target/MBlaze/MBlazeFrameLowering.cpp delete mode 100644 contrib/llvm/lib/Target/MBlaze/MBlazeFrameLowering.h delete mode 100644 contrib/llvm/lib/Target/MBlaze/MBlazeISelDAGToDAG.cpp delete mode 100644 contrib/llvm/lib/Target/MBlaze/MBlazeISelLowering.cpp delete mode 100644 contrib/llvm/lib/Target/MBlaze/MBlazeISelLowering.h delete mode 100644 contrib/llvm/lib/Target/MBlaze/MBlazeInstrFPU.td delete mode 100644 contrib/llvm/lib/Target/MBlaze/MBlazeInstrFSL.td delete mode 100644 contrib/llvm/lib/Target/MBlaze/MBlazeInstrFormats.td delete mode 100644 contrib/llvm/lib/Target/MBlaze/MBlazeInstrInfo.cpp delete mode 100644 contrib/llvm/lib/Target/MBlaze/MBlazeInstrInfo.h delete mode 100644 contrib/llvm/lib/Target/MBlaze/MBlazeInstrInfo.td delete mode 100644 contrib/llvm/lib/Target/MBlaze/MBlazeIntrinsicInfo.cpp delete mode 100644 contrib/llvm/lib/Target/MBlaze/MBlazeIntrinsicInfo.h delete mode 100644 contrib/llvm/lib/Target/MBlaze/MBlazeIntrinsics.td delete mode 100644 contrib/llvm/lib/Target/MBlaze/MBlazeMCInstLower.cpp delete mode 100644 contrib/llvm/lib/Target/MBlaze/MBlazeMCInstLower.h delete mode 100644 contrib/llvm/lib/Target/MBlaze/MBlazeMachineFunction.h delete mode 100644 contrib/llvm/lib/Target/MBlaze/MBlazeRegisterInfo.cpp delete mode 100644 contrib/llvm/lib/Target/MBlaze/MBlazeRegisterInfo.h delete mode 100644 contrib/llvm/lib/Target/MBlaze/MBlazeRegisterInfo.td delete mode 100644 contrib/llvm/lib/Target/MBlaze/MBlazeRelocations.h delete mode 100644 contrib/llvm/lib/Target/MBlaze/MBlazeSchedule.td delete mode 100644 contrib/llvm/lib/Target/MBlaze/MBlazeSchedule3.td delete mode 100644 contrib/llvm/lib/Target/MBlaze/MBlazeSchedule5.td delete mode 100644 contrib/llvm/lib/Target/MBlaze/MBlazeSelectionDAGInfo.h delete mode 100644 contrib/llvm/lib/Target/MBlaze/MBlazeSubtarget.cpp delete mode 100644 contrib/llvm/lib/Target/MBlaze/MBlazeSubtarget.h delete mode 100644 contrib/llvm/lib/Target/MBlaze/MBlazeTargetMachine.cpp delete mode 100644 contrib/llvm/lib/Target/MBlaze/MBlazeTargetMachine.h delete mode 100644 contrib/llvm/lib/Target/MBlaze/MBlazeTargetObjectFile.cpp delete mode 100644 contrib/llvm/lib/Target/MBlaze/MBlazeTargetObjectFile.h delete mode 100644 contrib/llvm/lib/Target/MBlaze/MCTargetDesc/MBlazeAsmBackend.cpp delete mode 100644 contrib/llvm/lib/Target/MBlaze/MCTargetDesc/MBlazeBaseInfo.h delete mode 100644 contrib/llvm/lib/Target/MBlaze/MCTargetDesc/MBlazeELFObjectWriter.cpp delete mode 100644 contrib/llvm/lib/Target/MBlaze/MCTargetDesc/MBlazeMCAsmInfo.cpp delete mode 100644 contrib/llvm/lib/Target/MBlaze/MCTargetDesc/MBlazeMCAsmInfo.h delete mode 100644 contrib/llvm/lib/Target/MBlaze/MCTargetDesc/MBlazeMCCodeEmitter.cpp delete mode 100644 contrib/llvm/lib/Target/MBlaze/MCTargetDesc/MBlazeMCTargetDesc.cpp delete mode 100644 contrib/llvm/lib/Target/MBlaze/MCTargetDesc/MBlazeMCTargetDesc.h delete mode 100644 contrib/llvm/lib/Target/MBlaze/TargetInfo/MBlazeTargetInfo.cpp delete mode 100644 contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsDirectObjLower.cpp delete mode 100644 contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsDirectObjLower.h delete mode 100644 contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.cpp delete mode 100644 contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.h create mode 100644 contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp create mode 100644 contrib/llvm/lib/Target/Mips/MSA.txt create mode 100644 contrib/llvm/lib/Target/Mips/Mips16HardFloat.cpp create mode 100644 contrib/llvm/lib/Target/Mips/Mips16HardFloat.h create mode 100644 contrib/llvm/lib/Target/Mips/MipsMSAInstrFormats.td create mode 100644 contrib/llvm/lib/Target/Mips/MipsMSAInstrInfo.td create mode 100644 contrib/llvm/lib/Target/Mips/MipsTargetStreamer.h create mode 100644 contrib/llvm/lib/Target/NVPTX/InstPrinter/NVPTXInstPrinter.h create mode 100644 contrib/llvm/lib/Target/NVPTX/NVPTXMCExpr.cpp create mode 100644 contrib/llvm/lib/Target/NVPTX/NVPTXMCExpr.h create mode 100644 contrib/llvm/lib/Target/NVPTX/NVPTXPrologEpilogPass.cpp create mode 100644 contrib/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCExpr.cpp create mode 100644 contrib/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCExpr.h create mode 100644 contrib/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMachObjectWriter.cpp create mode 100644 contrib/llvm/lib/Target/PowerPC/PPCFastISel.cpp create mode 100644 contrib/llvm/lib/Target/PowerPC/PPCTargetObjectFile.cpp create mode 100644 contrib/llvm/lib/Target/PowerPC/PPCTargetObjectFile.h create mode 100644 contrib/llvm/lib/Target/PowerPC/PPCTargetStreamer.h create mode 100644 contrib/llvm/lib/Target/R600/AMDGPUISelDAGToDAG.cpp delete mode 100644 contrib/llvm/lib/Target/R600/AMDGPUIndirectAddressing.cpp create mode 100644 contrib/llvm/lib/Target/R600/AMDGPUTargetTransformInfo.cpp delete mode 100644 contrib/llvm/lib/Target/R600/AMDIL.h delete mode 100644 contrib/llvm/lib/Target/R600/AMDIL7XXDevice.cpp delete mode 100644 contrib/llvm/lib/Target/R600/AMDIL7XXDevice.h delete mode 100644 contrib/llvm/lib/Target/R600/AMDILDevice.cpp delete mode 100644 contrib/llvm/lib/Target/R600/AMDILDevice.h delete mode 100644 contrib/llvm/lib/Target/R600/AMDILDeviceInfo.cpp delete mode 100644 contrib/llvm/lib/Target/R600/AMDILDeviceInfo.h delete mode 100644 contrib/llvm/lib/Target/R600/AMDILDevices.h delete mode 100644 contrib/llvm/lib/Target/R600/AMDILEvergreenDevice.cpp delete mode 100644 contrib/llvm/lib/Target/R600/AMDILEvergreenDevice.h delete mode 100644 contrib/llvm/lib/Target/R600/AMDILISelDAGToDAG.cpp delete mode 100644 contrib/llvm/lib/Target/R600/AMDILNIDevice.cpp delete mode 100644 contrib/llvm/lib/Target/R600/AMDILNIDevice.h delete mode 100644 contrib/llvm/lib/Target/R600/AMDILSIDevice.cpp delete mode 100644 contrib/llvm/lib/Target/R600/AMDILSIDevice.h rename contrib/llvm/lib/Target/{MBlaze/MBlazeSelectionDAGInfo.cpp => R600/MCTargetDesc/AMDGPUMCCodeEmitter.cpp} (51%) create mode 100644 contrib/llvm/lib/Target/R600/R600ClauseMergePass.cpp create mode 100644 contrib/llvm/lib/Target/R600/R600InstrFormats.td create mode 100644 contrib/llvm/lib/Target/R600/R600OptimizeVectorRegisters.cpp create mode 100644 contrib/llvm/lib/Target/R600/R600TextureIntrinsicsReplacer.cpp create mode 100644 contrib/llvm/lib/Target/R600/SIFixSGPRCopies.cpp create mode 100644 contrib/llvm/lib/Target/R600/SITypeRewriter.cpp delete mode 100644 contrib/llvm/lib/Target/Sparc/FPMover.cpp create mode 100644 contrib/llvm/lib/Target/Sparc/SparcCodeEmitter.cpp create mode 100644 contrib/llvm/lib/Target/Sparc/SparcJITInfo.cpp create mode 100644 contrib/llvm/lib/Target/Sparc/SparcJITInfo.h create mode 100644 contrib/llvm/lib/Target/Sparc/SparcRelocations.h create mode 100644 contrib/llvm/lib/Target/SystemZ/Disassembler/SystemZDisassembler.cpp create mode 100644 contrib/llvm/lib/Target/SystemZ/SystemZElimCompare.cpp create mode 100644 contrib/llvm/lib/Target/SystemZ/SystemZLongBranch.cpp rename contrib/llvm/lib/Target/{NVPTX/NVPTXNumRegisters.h => SystemZ/SystemZMachineFunctionInfo.cpp} (55%) create mode 100644 contrib/llvm/lib/Target/SystemZ/SystemZProcessors.td create mode 100644 contrib/llvm/lib/Target/SystemZ/SystemZSelectionDAGInfo.cpp create mode 100644 contrib/llvm/lib/Target/SystemZ/SystemZSelectionDAGInfo.h create mode 100644 contrib/llvm/lib/Target/SystemZ/SystemZShortenInst.cpp create mode 100644 contrib/llvm/lib/Target/X86/MCTargetDesc/X86ELFRelocationInfo.cpp create mode 100644 contrib/llvm/lib/Target/X86/MCTargetDesc/X86MachORelocationInfo.cpp create mode 100644 contrib/llvm/lib/Target/X86/X86CallingConv.h create mode 100644 contrib/llvm/lib/Target/X86/X86InstrAVX512.td create mode 100644 contrib/llvm/lib/Target/X86/X86ScheduleSLM.td create mode 100644 contrib/llvm/lib/Target/XCore/XCoreTargetTransformInfo.cpp delete mode 100644 contrib/llvm/lib/Transforms/Instrumentation/BlackList.cpp create mode 100644 contrib/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp create mode 100644 contrib/llvm/lib/Transforms/Instrumentation/DebugIR.cpp create mode 100644 contrib/llvm/lib/Transforms/Instrumentation/DebugIR.h delete mode 100644 contrib/llvm/lib/Transforms/Instrumentation/EdgeProfiling.cpp delete mode 100644 contrib/llvm/lib/Transforms/Instrumentation/OptimalEdgeProfiling.cpp delete mode 100644 contrib/llvm/lib/Transforms/Instrumentation/PathProfiling.cpp delete mode 100644 contrib/llvm/lib/Transforms/Instrumentation/ProfilingUtils.cpp delete mode 100644 contrib/llvm/lib/Transforms/Instrumentation/ProfilingUtils.h create mode 100644 contrib/llvm/lib/Transforms/ObjCARC/ARCRuntimeEntryPoints.h delete mode 100644 contrib/llvm/lib/Transforms/Scalar/BasicBlockPlacement.cpp create mode 100644 contrib/llvm/lib/Transforms/Scalar/FlattenCFGPass.cpp create mode 100644 contrib/llvm/lib/Transforms/Scalar/LoopRerollPass.cpp create mode 100644 contrib/llvm/lib/Transforms/Scalar/PartiallyInlineLibCalls.cpp create mode 100644 contrib/llvm/lib/Transforms/Scalar/SampleProfile.cpp delete mode 100644 contrib/llvm/lib/Transforms/Scalar/SimplifyLibCalls.cpp rename contrib/llvm/lib/{Target/R600/AMDGPUStructurizeCFG.cpp => Transforms/Scalar/StructurizeCFG.cpp} (84%) create mode 100644 contrib/llvm/lib/Transforms/Utils/FlattenCFG.cpp create mode 100644 contrib/llvm/lib/Transforms/Utils/GlobalStatus.cpp create mode 100644 contrib/llvm/lib/Transforms/Utils/SpecialCaseList.cpp delete mode 100644 contrib/llvm/lib/Transforms/Vectorize/VecUtils.cpp delete mode 100644 contrib/llvm/lib/Transforms/Vectorize/VecUtils.h create mode 100644 contrib/llvm/tools/clang/include/clang/AST/ASTFwd.h create mode 100644 contrib/llvm/tools/clang/include/clang/AST/ASTLambda.h delete mode 100644 contrib/llvm/tools/clang/include/clang/AST/LambdaMangleContext.h create mode 100644 contrib/llvm/tools/clang/include/clang/AST/MangleNumberingContext.h create mode 100644 contrib/llvm/tools/clang/include/clang/AST/StmtOpenMP.h create mode 100644 contrib/llvm/tools/clang/include/clang/ASTMatchers/Dynamic/Diagnostics.h create mode 100644 contrib/llvm/tools/clang/include/clang/ASTMatchers/Dynamic/Parser.h create mode 100644 contrib/llvm/tools/clang/include/clang/ASTMatchers/Dynamic/Registry.h create mode 100644 contrib/llvm/tools/clang/include/clang/ASTMatchers/Dynamic/VariantValue.h create mode 100644 contrib/llvm/tools/clang/include/clang/Analysis/Analyses/Consumed.h delete mode 100644 contrib/llvm/tools/clang/include/clang/Analysis/Support/BlkExprDeclBitVector.h delete mode 100644 contrib/llvm/tools/clang/include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h delete mode 100644 contrib/llvm/tools/clang/include/clang/Analysis/Visitors/CFGRecStmtVisitor.h delete mode 100644 contrib/llvm/tools/clang/include/clang/Analysis/Visitors/CFGStmtVisitor.h create mode 100644 contrib/llvm/tools/clang/include/clang/Basic/BuiltinsXCore.def create mode 100644 contrib/llvm/tools/clang/include/clang/CodeGen/CGFunctionInfo.h create mode 100644 contrib/llvm/tools/clang/include/clang/CodeGen/CodeGenABITypes.h delete mode 100644 contrib/llvm/tools/clang/include/clang/Driver/Arg.h delete mode 100644 contrib/llvm/tools/clang/include/clang/Driver/ArgList.h create mode 100644 contrib/llvm/tools/clang/include/clang/Driver/CLCompatOptions.td delete mode 100644 contrib/llvm/tools/clang/include/clang/Driver/OptParser.td delete mode 100644 contrib/llvm/tools/clang/include/clang/Driver/OptSpecifier.h delete mode 100644 contrib/llvm/tools/clang/include/clang/Driver/OptTable.h delete mode 100644 contrib/llvm/tools/clang/include/clang/Driver/Option.h create mode 100644 contrib/llvm/tools/clang/include/clang/Driver/SanitizerArgs.h create mode 100644 contrib/llvm/tools/clang/include/clang/Index/CommentToXML.h create mode 100644 contrib/llvm/tools/clang/include/clang/Index/USRGeneration.h create mode 100644 contrib/llvm/tools/clang/include/clang/Sema/SemaLambda.h create mode 100644 contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Checkers/ObjCRetainCount.h rename contrib/llvm/tools/clang/include/clang/StaticAnalyzer/{Checkers => Core/BugReporter}/CommonBugCategories.h (61%) create mode 100644 contrib/llvm/tools/clang/include/clang/Tooling/ReplacementsYaml.h create mode 100644 contrib/llvm/tools/clang/lib/AST/ASTTypeTraits.cpp delete mode 100644 contrib/llvm/tools/clang/lib/AST/DumpXML.cpp rename contrib/llvm/tools/clang/lib/AST/{LambdaMangleContext.cpp => MangleNumberingContext.cpp} (55%) create mode 100644 contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Diagnostics.cpp create mode 100644 contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Marshallers.h create mode 100644 contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Parser.cpp create mode 100644 contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/Registry.cpp create mode 100644 contrib/llvm/tools/clang/lib/ASTMatchers/Dynamic/VariantValue.cpp create mode 100644 contrib/llvm/tools/clang/lib/Analysis/Consumed.cpp create mode 100644 contrib/llvm/tools/clang/lib/CodeGen/CodeGenABITypes.cpp create mode 100644 contrib/llvm/tools/clang/lib/CodeGen/EHScopeStack.h create mode 100644 contrib/llvm/tools/clang/lib/CodeGen/MicrosoftVBTables.cpp create mode 100644 contrib/llvm/tools/clang/lib/CodeGen/MicrosoftVBTables.h delete mode 100644 contrib/llvm/tools/clang/lib/Driver/Arg.cpp delete mode 100644 contrib/llvm/tools/clang/lib/Driver/ArgList.cpp delete mode 100644 contrib/llvm/tools/clang/lib/Driver/OptTable.cpp delete mode 100644 contrib/llvm/tools/clang/lib/Driver/Option.cpp create mode 100644 contrib/llvm/tools/clang/lib/Driver/SanitizerArgs.cpp delete mode 100644 contrib/llvm/tools/clang/lib/Driver/SanitizerArgs.h create mode 100644 contrib/llvm/tools/clang/lib/Format/ContinuationIndenter.cpp create mode 100644 contrib/llvm/tools/clang/lib/Format/ContinuationIndenter.h create mode 100644 contrib/llvm/tools/clang/lib/Format/Encoding.h create mode 100644 contrib/llvm/tools/clang/lib/Format/FormatToken.cpp create mode 100644 contrib/llvm/tools/clang/lib/Format/FormatToken.h create mode 100644 contrib/llvm/tools/clang/lib/Headers/Intrin.h create mode 100644 contrib/llvm/tools/clang/lib/Headers/shaintrin.h create mode 100644 contrib/llvm/tools/clang/lib/Headers/tbmintrin.h create mode 100644 contrib/llvm/tools/clang/lib/Index/CommentToXML.cpp create mode 100644 contrib/llvm/tools/clang/lib/Index/SimpleFormatContext.h create mode 100644 contrib/llvm/tools/clang/lib/Index/USRGeneration.cpp create mode 100644 contrib/llvm/tools/clang/lib/Sema/TypeLocBuilder.cpp create mode 100644 contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp rename contrib/llvm/tools/clang/lib/StaticAnalyzer/{Checkers => Core}/CommonBugCategories.cpp (64%) create mode 100644 contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/PrettyStackTraceLocationContext.h delete mode 100644 contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/TextPathDiagnostics.cpp delete mode 100644 contrib/llvm/tools/clang/utils/TableGen/OptParserEmitter.cpp create mode 100644 contrib/llvm/tools/lli/ChildTarget/ChildTarget.cpp create mode 100644 contrib/llvm/tools/lli/ChildTarget/Unix/ChildTarget.inc create mode 100644 contrib/llvm/tools/lli/ChildTarget/Windows/ChildTarget.inc delete mode 100644 contrib/llvm/tools/lli/RecordingMemoryManager.cpp delete mode 100644 contrib/llvm/tools/lli/RecordingMemoryManager.h create mode 100644 contrib/llvm/tools/lli/RemoteMemoryManager.cpp create mode 100644 contrib/llvm/tools/lli/RemoteMemoryManager.h create mode 100644 contrib/llvm/tools/lli/RemoteTargetExternal.cpp create mode 100644 contrib/llvm/tools/lli/RemoteTargetExternal.h create mode 100644 contrib/llvm/tools/lli/RemoteTargetMessage.h create mode 100644 contrib/llvm/tools/lli/Unix/RemoteTargetExternal.inc create mode 100644 contrib/llvm/tools/lli/Windows/RemoteTargetExternal.inc delete mode 100644 contrib/llvm/tools/llvm-objdump/MCFunction.cpp delete mode 100644 contrib/llvm/tools/llvm-objdump/MCFunction.h delete mode 100644 contrib/llvm/tools/llvm-prof/llvm-prof.cpp delete mode 100644 contrib/llvm/tools/llvm-ranlib/llvm-ranlib.cpp create mode 100644 lib/clang/include/PPCGenFastISel.inc delete mode 100644 lib/clang/include/clang/Parse/AttrExprArgs.inc create mode 100644 lib/clang/include/clang/Parse/AttrIdentifierArg.inc create mode 100644 lib/clang/include/clang/Parse/AttrTypeArg.inc create mode 100644 lib/clang/include/clang/Sema/AttrParsedAttrImpl.inc delete mode 100644 lib/clang/libllvmarchive/Makefile create mode 100644 lib/clang/libllvmoption/Makefile delete mode 100644 usr.bin/clang/llvm-prof/Makefile delete mode 100644 usr.bin/clang/llvm-prof/llvm-prof.1 delete mode 100644 usr.bin/clang/llvm-ranlib/Makefile delete mode 100644 usr.bin/clang/llvm-ranlib/llvm-ranlib.1 diff --git a/ObsoleteFiles.inc b/ObsoleteFiles.inc index d402adcaa..44986fccb 100644 --- a/ObsoleteFiles.inc +++ b/ObsoleteFiles.inc @@ -38,6 +38,43 @@ # xargs -n1 | sort | uniq -d; # done +# 20140321: new clang import which bumps version from 3.3 to 3.4. +OLD_FILES+=usr/bin/llvm-prof +OLD_FILES+=usr/bin/llvm-ranlib +OLD_FILES+=usr/include/clang/3.3/__wmmintrin_aes.h +OLD_FILES+=usr/include/clang/3.3/__wmmintrin_pclmul.h +OLD_FILES+=usr/include/clang/3.3/altivec.h +OLD_FILES+=usr/include/clang/3.3/ammintrin.h +OLD_FILES+=usr/include/clang/3.3/avx2intrin.h +OLD_FILES+=usr/include/clang/3.3/avxintrin.h +OLD_FILES+=usr/include/clang/3.3/bmi2intrin.h +OLD_FILES+=usr/include/clang/3.3/bmiintrin.h +OLD_FILES+=usr/include/clang/3.3/cpuid.h +OLD_FILES+=usr/include/clang/3.3/emmintrin.h +OLD_FILES+=usr/include/clang/3.3/f16cintrin.h +OLD_FILES+=usr/include/clang/3.3/fma4intrin.h +OLD_FILES+=usr/include/clang/3.3/fmaintrin.h +OLD_FILES+=usr/include/clang/3.3/immintrin.h +OLD_FILES+=usr/include/clang/3.3/lzcntintrin.h +OLD_FILES+=usr/include/clang/3.3/mm3dnow.h +OLD_FILES+=usr/include/clang/3.3/mm_malloc.h +OLD_FILES+=usr/include/clang/3.3/mmintrin.h +OLD_FILES+=usr/include/clang/3.3/module.map +OLD_FILES+=usr/include/clang/3.3/nmmintrin.h +OLD_FILES+=usr/include/clang/3.3/pmmintrin.h +OLD_FILES+=usr/include/clang/3.3/popcntintrin.h +OLD_FILES+=usr/include/clang/3.3/prfchwintrin.h +OLD_FILES+=usr/include/clang/3.3/rdseedintrin.h +OLD_FILES+=usr/include/clang/3.3/rtmintrin.h +OLD_FILES+=usr/include/clang/3.3/smmintrin.h +OLD_FILES+=usr/include/clang/3.3/tmmintrin.h +OLD_FILES+=usr/include/clang/3.3/wmmintrin.h +OLD_FILES+=usr/include/clang/3.3/x86intrin.h +OLD_FILES+=usr/include/clang/3.3/xmmintrin.h +OLD_FILES+=usr/include/clang/3.3/xopintrin.h +OLD_FILES+=usr/share/man/man1/llvm-prof.1.gz +OLD_FILES+=usr/share/man/man1/llvm-ranlib.1.gz +OLD_DIRS+=usr/include/clang/3.3 # 20140314: libssh becomes private OLD_FILES+=usr/lib/libssh.a OLD_FILES+=usr/lib/libssh.so diff --git a/UPDATING b/UPDATING index 7f06274be..f9a95c5a2 100644 --- a/UPDATING +++ b/UPDATING @@ -11,6 +11,9 @@ handbook: Items affecting the ports and packages system can be found in /usr/ports/UPDATING. Please read that file before running portupgrade. +20140321: + Clang and llvm have been upgraded to 3.4 release. + 20140216: The nve(4) driver for NVIDIA nForce MCP Ethernet adapters has been deprecated and will not be part of FreeBSD 11.0 and later diff --git a/contrib/gcc/libgcc2.c b/contrib/gcc/libgcc2.c index 851bdd073..f51fd57e0 100644 --- a/contrib/gcc/libgcc2.c +++ b/contrib/gcc/libgcc2.c @@ -1983,8 +1983,8 @@ __eprintf (const char *string, const char *expression, /* Clear part of an instruction cache. */ void -__clear_cache (char *beg __attribute__((__unused__)), - char *end __attribute__((__unused__))) +__clear_cache (void *beg __attribute__((__unused__)), + void *end __attribute__((__unused__))) { #ifdef CLEAR_INSN_CACHE CLEAR_INSN_CACHE (beg, end); diff --git a/contrib/gcc/libgcc2.h b/contrib/gcc/libgcc2.h index c13f0c76b..51b5debf8 100644 --- a/contrib/gcc/libgcc2.h +++ b/contrib/gcc/libgcc2.h @@ -35,7 +35,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #endif extern int __gcc_bcmp (const unsigned char *, const unsigned char *, size_t); -extern void __clear_cache (char *, char *); +extern void __clear_cache (void *, void *); extern void __eprintf (const char *, const char *, unsigned int, const char *) __attribute__ ((__noreturn__)); diff --git a/contrib/llvm/LICENSE.TXT b/contrib/llvm/LICENSE.TXT index aa7b11922..66d6647ff 100644 --- a/contrib/llvm/LICENSE.TXT +++ b/contrib/llvm/LICENSE.TXT @@ -68,3 +68,4 @@ Google Test llvm/utils/unittest/googletest OpenBSD regex llvm/lib/Support/{reg*, COPYRIGHT.regex} pyyaml tests llvm/test/YAMLParser/{*.data, LICENSE.TXT} ARM contributions llvm/lib/Target/ARM/LICENSE.TXT +md5 contributions llvm/lib/Support/MD5.cpp llvm/include/llvm/Support/MD5.h diff --git a/contrib/llvm/include/llvm-c/BitReader.h b/contrib/llvm/include/llvm-c/BitReader.h index 522803518..7af209bdf 100644 --- a/contrib/llvm/include/llvm-c/BitReader.h +++ b/contrib/llvm/include/llvm-c/BitReader.h @@ -34,7 +34,7 @@ extern "C" { /* Builds a module from the bitcode in the specified memory buffer, returning a reference to the module via the OutModule parameter. Returns 0 on success. - Optionally returns a human-readable error message via OutMessage. */ + Optionally returns a human-readable error message via OutMessage. */ LLVMBool LLVMParseBitcode(LLVMMemoryBufferRef MemBuf, LLVMModuleRef *OutModule, char **OutMessage); @@ -44,7 +44,7 @@ LLVMBool LLVMParseBitcodeInContext(LLVMContextRef ContextRef, /** Reads a module from the specified path, returning via the OutMP parameter a module provider which performs lazy deserialization. Returns 0 on success. - Optionally returns a human-readable error message via OutMessage. */ + Optionally returns a human-readable error message via OutMessage. */ LLVMBool LLVMGetBitcodeModuleInContext(LLVMContextRef ContextRef, LLVMMemoryBufferRef MemBuf, LLVMModuleRef *OutM, diff --git a/contrib/llvm/include/llvm-c/BitWriter.h b/contrib/llvm/include/llvm-c/BitWriter.h index ba5a6778c..f605e2453 100644 --- a/contrib/llvm/include/llvm-c/BitWriter.h +++ b/contrib/llvm/include/llvm-c/BitWriter.h @@ -34,7 +34,7 @@ extern "C" { /*===-- Operations on modules ---------------------------------------------===*/ -/** Writes a module to the specified path. Returns 0 on success. */ +/** Writes a module to the specified path. Returns 0 on success. */ int LLVMWriteBitcodeToFile(LLVMModuleRef M, const char *Path); /** Writes a module to an open file descriptor. Returns 0 on success. */ @@ -42,7 +42,7 @@ int LLVMWriteBitcodeToFD(LLVMModuleRef M, int FD, int ShouldClose, int Unbuffered); /** Deprecated for LLVMWriteBitcodeToFD. Writes a module to an open file - descriptor. Returns 0 on success. Closes the Handle. */ + descriptor. Returns 0 on success. Closes the Handle. */ int LLVMWriteBitcodeToFileHandle(LLVMModuleRef M, int Handle); /** diff --git a/contrib/llvm/include/llvm-c/Core.h b/contrib/llvm/include/llvm-c/Core.h index 6b62f3326..9953d52ed 100644 --- a/contrib/llvm/include/llvm-c/Core.h +++ b/contrib/llvm/include/llvm-c/Core.h @@ -165,7 +165,9 @@ typedef enum { a temporary measure until the API/ABI impact to the C API is understood and the path forward agreed upon. LLVMAddressSafety = 1ULL << 32, - LLVMStackProtectStrongAttribute = 1ULL<<33 + LLVMStackProtectStrongAttribute = 1ULL<<33, + LLVMCold = 1ULL << 34, + LLVMOptimizeNone = 1ULL << 35 */ } LLVMAttribute; @@ -220,6 +222,7 @@ typedef enum { LLVMPtrToInt = 39, LLVMIntToPtr = 40, LLVMBitCast = 41, + LLVMAddrSpaceCast = 60, /* Other Operators */ LLVMICmp = 42, @@ -272,7 +275,7 @@ typedef enum { LLVMLinkOnceAnyLinkage, /**< Keep one copy of function when linking (inline)*/ LLVMLinkOnceODRLinkage, /**< Same, but only replaced by something equivalent. */ - LLVMLinkOnceODRAutoHideLinkage, /**< Like LinkOnceODR, but possibly hidden. */ + LLVMLinkOnceODRAutoHideLinkage, /**< Obsolete */ LLVMWeakAnyLinkage, /**< Keep one copy of function when linking (weak) */ LLVMWeakODRLinkage, /**< Same, but only replaced by something equivalent. */ @@ -299,6 +302,8 @@ typedef enum { LLVMCCallConv = 0, LLVMFastCallConv = 8, LLVMColdCallConv = 9, + LLVMWebKitJSCallConv = 12, + LLVMAnyRegCallConv = 13, LLVMX86StdcallCallConv = 64, LLVMX86FastcallCallConv = 65 } LLVMCallConv; @@ -352,26 +357,26 @@ typedef enum { LLVMAtomicOrderingNotAtomic = 0, /**< A load or store which is not atomic */ LLVMAtomicOrderingUnordered = 1, /**< Lowest level of atomicity, guarantees somewhat sane results, lock free. */ - LLVMAtomicOrderingMonotonic = 2, /**< guarantees that if you take all the - operations affecting a specific address, + LLVMAtomicOrderingMonotonic = 2, /**< guarantees that if you take all the + operations affecting a specific address, a consistent ordering exists */ - LLVMAtomicOrderingAcquire = 4, /**< Acquire provides a barrier of the sort - necessary to acquire a lock to access other + LLVMAtomicOrderingAcquire = 4, /**< Acquire provides a barrier of the sort + necessary to acquire a lock to access other memory with normal loads and stores. */ - LLVMAtomicOrderingRelease = 5, /**< Release is similar to Acquire, but with - a barrier of the sort necessary to release + LLVMAtomicOrderingRelease = 5, /**< Release is similar to Acquire, but with + a barrier of the sort necessary to release a lock. */ - LLVMAtomicOrderingAcquireRelease = 6, /**< provides both an Acquire and a - Release barrier (for fences and + LLVMAtomicOrderingAcquireRelease = 6, /**< provides both an Acquire and a + Release barrier (for fences and operations which both read and write memory). */ - LLVMAtomicOrderingSequentiallyConsistent = 7 /**< provides Acquire semantics - for loads and Release - semantics for stores. - Additionally, it guarantees - that a total ordering exists - between all - SequentiallyConsistent + LLVMAtomicOrderingSequentiallyConsistent = 7 /**< provides Acquire semantics + for loads and Release + semantics for stores. + Additionally, it guarantees + that a total ordering exists + between all + SequentiallyConsistent operations. */ } LLVMAtomicOrdering; @@ -384,16 +389,16 @@ typedef enum { LLVMAtomicRMWBinOpOr, /**< OR a value and return the old one */ LLVMAtomicRMWBinOpXor, /**< Xor a value and return the old one */ LLVMAtomicRMWBinOpMax, /**< Sets the value if it's greater than the - original using a signed comparison and return + original using a signed comparison and return the old one */ LLVMAtomicRMWBinOpMin, /**< Sets the value if it's Smaller than the - original using a signed comparison and return + original using a signed comparison and return the old one */ LLVMAtomicRMWBinOpUMax, /**< Sets the value if it's greater than the - original using an unsigned comparison and return + original using an unsigned comparison and return the old one */ LLVMAtomicRMWBinOpUMin /**< Sets the value if it's greater than the - original using an unsigned comparison and return + original using an unsigned comparison and return the old one */ } LLVMAtomicRMWBinOp; @@ -406,13 +411,37 @@ void LLVMInitializeCore(LLVMPassRegistryRef R); /** Deallocate and destroy all ManagedStatic variables. @see llvm::llvm_shutdown @see ManagedStatic */ -void LLVMShutdown(); +void LLVMShutdown(void); /*===-- Error handling ----------------------------------------------------===*/ +char *LLVMCreateMessage(const char *Message); void LLVMDisposeMessage(char *Message); +typedef void (*LLVMFatalErrorHandler)(const char *Reason); + +/** + * Install a fatal error handler. By default, if LLVM detects a fatal error, it + * will call exit(1). This may not be appropriate in many contexts. For example, + * doing exit(1) will bypass many crash reporting/tracing system tools. This + * function allows you to install a callback that will be invoked prior to the + * call to exit(1). + */ +void LLVMInstallFatalErrorHandler(LLVMFatalErrorHandler Handler); + +/** + * Reset the fatal error handler. This resets LLVM's fatal error handling + * behavior to the default. + */ +void LLVMResetFatalErrorHandler(void); + +/** + * Enable LLVM's built-in stack trace code. This intercepts the OS's crash + * signals and prints which component of LLVM you were in at the time if the + * crash. + */ +void LLVMEnablePrettyStackTrace(void); /** * @defgroup LLVMCCoreContext Contexts @@ -458,7 +487,7 @@ unsigned LLVMGetMDKindID(const char* Name, unsigned SLen); /** * @defgroup LLVMCCoreModule Modules * - * Modules represent the top-level structure in a LLVM program. An LLVM + * Modules represent the top-level structure in an LLVM program. An LLVM * module is effectively a translation unit or a collection of * translation units merged together. * @@ -537,6 +566,14 @@ void LLVMDumpModule(LLVMModuleRef M); LLVMBool LLVMPrintModuleToFile(LLVMModuleRef M, const char *Filename, char **ErrorMessage); +/** + * Return a string representation of the module. Use + * LLVMDisposeMessage to free the string. + * + * @see Module::print() + */ +char *LLVMPrintModuleToString(LLVMModuleRef M); + /** * Set inline assembly for a module. * @@ -688,6 +725,21 @@ LLVMBool LLVMTypeIsSized(LLVMTypeRef Ty); */ LLVMContextRef LLVMGetTypeContext(LLVMTypeRef Ty); +/** + * Dump a representation of a type to stderr. + * + * @see llvm::Type::dump() + */ +void LLVMDumpType(LLVMTypeRef Val); + +/** + * Return a string representation of the type. Use + * LLVMDisposeMessage to free the string. + * + * @see llvm::Type::print() + */ +char *LLVMPrintTypeToString(LLVMTypeRef Val); + /** * @defgroup LLVMCCoreTypeInt Integer Types * @@ -1039,7 +1091,7 @@ LLVMTypeRef LLVMX86MMXType(void); * hierarchy of classes within this type. Depending on the instance * obtained, not all APIs are available. * - * Callers can determine the type of a LLVMValueRef by calling the + * Callers can determine the type of an LLVMValueRef by calling the * LLVMIsA* family of functions (e.g. LLVMIsAArgument()). These * functions are defined by a macro, so it isn't obvious which are * available by looking at the Doxygen source code. Instead, look at the @@ -1061,6 +1113,9 @@ LLVMTypeRef LLVMX86MMXType(void); macro(BlockAddress) \ macro(ConstantAggregateZero) \ macro(ConstantArray) \ + macro(ConstantDataSequential) \ + macro(ConstantDataArray) \ + macro(ConstantDataVector) \ macro(ConstantExpr) \ macro(ConstantFP) \ macro(ConstantInt) \ @@ -1105,6 +1160,7 @@ LLVMTypeRef LLVMX86MMXType(void); macro(UnaryInstruction) \ macro(AllocaInst) \ macro(CastInst) \ + macro(AddrSpaceCastInst) \ macro(BitCastInst) \ macro(FPExtInst) \ macro(FPToSIInst) \ @@ -1159,6 +1215,14 @@ void LLVMSetValueName(LLVMValueRef Val, const char *Name); */ void LLVMDumpValue(LLVMValueRef Val); +/** + * Return a string representation of the value. Use + * LLVMDisposeMessage to free the string. + * + * @see llvm::Value::print() + */ +char *LLVMPrintValueToString(LLVMValueRef Val); + /** * Replace all uses of a value with another one. * @@ -1179,7 +1243,7 @@ LLVMBool LLVMIsUndef(LLVMValueRef Val); /** * Convert value instances between types. * - * Internally, a LLVMValueRef is "pinned" to a specific type. This + * Internally, an LLVMValueRef is "pinned" to a specific type. This * series of functions allows you to cast an instance to a specific * type. * @@ -1201,7 +1265,7 @@ LLVM_FOR_EACH_VALUE_SUBCLASS(LLVM_DECLARE_VALUE_CAST) * This module defines functions that allow you to inspect the uses of a * LLVMValueRef. * - * It is possible to obtain a LLVMUseRef for any LLVMValueRef instance. + * It is possible to obtain an LLVMUseRef for any LLVMValueRef instance. * Each LLVMUseRef (which corresponds to a llvm::Use instance) holds a * llvm::User and llvm::Value. * @@ -1568,6 +1632,7 @@ LLVMValueRef LLVMConstFPToSI(LLVMValueRef ConstantVal, LLVMTypeRef ToType); LLVMValueRef LLVMConstPtrToInt(LLVMValueRef ConstantVal, LLVMTypeRef ToType); LLVMValueRef LLVMConstIntToPtr(LLVMValueRef ConstantVal, LLVMTypeRef ToType); LLVMValueRef LLVMConstBitCast(LLVMValueRef ConstantVal, LLVMTypeRef ToType); +LLVMValueRef LLVMConstAddrSpaceCast(LLVMValueRef ConstantVal, LLVMTypeRef ToType); LLVMValueRef LLVMConstZExtOrBitCast(LLVMValueRef ConstantVal, LLVMTypeRef ToType); LLVMValueRef LLVMConstSExtOrBitCast(LLVMValueRef ConstantVal, @@ -1623,8 +1688,33 @@ const char *LLVMGetSection(LLVMValueRef Global); void LLVMSetSection(LLVMValueRef Global, const char *Section); LLVMVisibility LLVMGetVisibility(LLVMValueRef Global); void LLVMSetVisibility(LLVMValueRef Global, LLVMVisibility Viz); -unsigned LLVMGetAlignment(LLVMValueRef Global); -void LLVMSetAlignment(LLVMValueRef Global, unsigned Bytes); + +/** + * @defgroup LLVMCCoreValueWithAlignment Values with alignment + * + * Functions in this group only apply to values with alignment, i.e. + * global variables, load and store instructions. + */ + +/** + * Obtain the preferred alignment of the value. + * @see llvm::LoadInst::getAlignment() + * @see llvm::StoreInst::getAlignment() + * @see llvm::GlobalValue::getAlignment() + */ +unsigned LLVMGetAlignment(LLVMValueRef V); + +/** + * Set the preferred alignment of the value. + * @see llvm::LoadInst::setAlignment() + * @see llvm::StoreInst::setAlignment() + * @see llvm::GlobalValue::setAlignment() + */ +void LLVMSetAlignment(LLVMValueRef V, unsigned Bytes); + +/** + * @} + */ /** * @defgroup LLVMCoreValueConstantGlobalVariable Global Variables @@ -1804,7 +1894,7 @@ LLVMValueRef LLVMGetParam(LLVMValueRef Fn, unsigned Index); /** * Obtain the function to which this argument belongs. * - * Unlike other functions in this group, this one takes a LLVMValueRef + * Unlike other functions in this group, this one takes an LLVMValueRef * that corresponds to a llvm::Attribute. * * The returned LLVMValueRef is the llvm::Function to which this @@ -1829,7 +1919,7 @@ LLVMValueRef LLVMGetLastParam(LLVMValueRef Fn); /** * Obtain the next parameter to a function. * - * This takes a LLVMValueRef obtained from LLVMGetFirstParam() (which is + * This takes an LLVMValueRef obtained from LLVMGetFirstParam() (which is * actually a wrapped iterator) and obtains the next parameter from the * underlying iterator. */ @@ -1978,12 +2068,12 @@ void LLVMGetMDNodeOperands(LLVMValueRef V, LLVMValueRef *Dest); LLVMValueRef LLVMBasicBlockAsValue(LLVMBasicBlockRef BB); /** - * Determine whether a LLVMValueRef is itself a basic block. + * Determine whether an LLVMValueRef is itself a basic block. */ LLVMBool LLVMValueIsBasicBlock(LLVMValueRef Val); /** - * Convert a LLVMValueRef to a LLVMBasicBlockRef instance. + * Convert an LLVMValueRef to an LLVMBasicBlockRef instance. */ LLVMBasicBlockRef LLVMValueAsBasicBlock(LLVMValueRef Val); @@ -2140,7 +2230,7 @@ LLVMValueRef LLVMGetFirstInstruction(LLVMBasicBlockRef BB); /** * Obtain the last instruction in a basic block. * - * The returned LLVMValueRef corresponds to a LLVM:Instruction. + * The returned LLVMValueRef corresponds to an LLVM:Instruction. */ LLVMValueRef LLVMGetLastInstruction(LLVMBasicBlockRef BB); @@ -2322,12 +2412,12 @@ void LLVMAddIncoming(LLVMValueRef PhiNode, LLVMValueRef *IncomingValues, unsigned LLVMCountIncoming(LLVMValueRef PhiNode); /** - * Obtain an incoming value to a PHI node as a LLVMValueRef. + * Obtain an incoming value to a PHI node as an LLVMValueRef. */ LLVMValueRef LLVMGetIncomingValue(LLVMValueRef PhiNode, unsigned Index); /** - * Obtain an incoming value to a PHI node as a LLVMBasicBlockRef. + * Obtain an incoming value to a PHI node as an LLVMBasicBlockRef. */ LLVMBasicBlockRef LLVMGetIncomingBlock(LLVMValueRef PhiNode, unsigned Index); @@ -2518,6 +2608,8 @@ LLVMValueRef LLVMBuildIntToPtr(LLVMBuilderRef, LLVMValueRef Val, LLVMTypeRef DestTy, const char *Name); LLVMValueRef LLVMBuildBitCast(LLVMBuilderRef, LLVMValueRef Val, LLVMTypeRef DestTy, const char *Name); +LLVMValueRef LLVMBuildAddrSpaceCast(LLVMBuilderRef, LLVMValueRef Val, + LLVMTypeRef DestTy, const char *Name); LLVMValueRef LLVMBuildZExtOrBitCast(LLVMBuilderRef, LLVMValueRef Val, LLVMTypeRef DestTy, const char *Name); LLVMValueRef LLVMBuildSExtOrBitCast(LLVMBuilderRef, LLVMValueRef Val, @@ -2571,9 +2663,9 @@ LLVMValueRef LLVMBuildIsNotNull(LLVMBuilderRef, LLVMValueRef Val, const char *Name); LLVMValueRef LLVMBuildPtrDiff(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, const char *Name); -LLVMValueRef LLVMBuildAtomicRMW(LLVMBuilderRef B,LLVMAtomicRMWBinOp op, - LLVMValueRef PTR, LLVMValueRef Val, - LLVMAtomicOrdering ordering, +LLVMValueRef LLVMBuildAtomicRMW(LLVMBuilderRef B,LLVMAtomicRMWBinOp op, + LLVMValueRef PTR, LLVMValueRef Val, + LLVMAtomicOrdering ordering, LLVMBool singleThread); /** @@ -2706,16 +2798,16 @@ void LLVMDisposePassManager(LLVMPassManagerRef PM); initialization succeeded. Must be executed in isolation from all other LLVM api calls. @see llvm::llvm_start_multithreaded */ -LLVMBool LLVMStartMultithreaded(); +LLVMBool LLVMStartMultithreaded(void); /** Deallocate structures necessary to make LLVM safe for multithreading. Must be executed in isolation from all other LLVM api calls. @see llvm::llvm_stop_multithreaded */ -void LLVMStopMultithreaded(); +void LLVMStopMultithreaded(void); /** Check whether LLVM is executing in thread-safe mode or not. @see llvm::llvm_is_multithreaded */ -LLVMBool LLVMIsMultithreaded(); +LLVMBool LLVMIsMultithreaded(void); /** * @} diff --git a/contrib/llvm/include/llvm-c/Disassembler.h b/contrib/llvm/include/llvm-c/Disassembler.h index df65a7b20..79bcfcdab 100644 --- a/contrib/llvm/include/llvm-c/Disassembler.h +++ b/contrib/llvm/include/llvm-c/Disassembler.h @@ -42,7 +42,7 @@ typedef void *LLVMDisasmContextRef; * instruction are specified by the Offset parameter and its byte widith is the * size parameter. For instructions sets with fixed widths and one symbolic * operand per instruction, the Offset parameter will be zero and Size parameter - * will be the instruction width. The information is returned in TagBuf and is + * will be the instruction width. The information is returned in TagBuf and is * Triple specific with its specific information defined by the value of * TagType for that Triple. If symbolic information is returned the function * returns 1, otherwise it returns 0. @@ -58,7 +58,7 @@ typedef int (*LLVMOpInfoCallback)(void *DisInfo, uint64_t PC, * SubtractSymbol can be link edited independent of each other. Many other * platforms only allow a relocatable expression of the form AddSymbol + Offset * to be encoded. - * + * * The LLVMOpInfoCallback() for the TagType value of 1 uses the struct * LLVMOpInfo1. The value of the relocatable expression for the operand, * including any PC adjustment, is passed in to the call back in the Value @@ -130,6 +130,17 @@ typedef const char *(*LLVMSymbolLookupCallback)(void *DisInfo, /* The output reference is to a cstring address in a literal pool. */ #define LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr 3 +/* The output reference is to a Objective-C CoreFoundation string. */ +#define LLVMDisassembler_ReferenceType_Out_Objc_CFString_Ref 4 +/* The output reference is to a Objective-C message. */ +#define LLVMDisassembler_ReferenceType_Out_Objc_Message 5 +/* The output reference is to a Objective-C message ref. */ +#define LLVMDisassembler_ReferenceType_Out_Objc_Message_Ref 6 +/* The output reference is to a Objective-C selector ref. */ +#define LLVMDisassembler_ReferenceType_Out_Objc_Selector_Ref 7 +/* The output reference is to a Objective-C class ref. */ +#define LLVMDisassembler_ReferenceType_Out_Objc_Class_Ref 8 + #ifdef __cplusplus extern "C" { #endif /* !defined(__cplusplus) */ @@ -170,6 +181,10 @@ int LLVMSetDisasmOptions(LLVMDisasmContextRef DC, uint64_t Options); #define LLVMDisassembler_Option_PrintImmHex 2 /* The option use the other assembler printer variant */ #define LLVMDisassembler_Option_AsmPrinterVariant 4 +/* The option to set comment on instructions */ +#define LLVMDisassembler_Option_SetInstrComments 8 + /* The option to print latency information alongside instructions */ +#define LLVMDisassembler_Option_PrintLatency 16 /** * Dispose of a disassembler context. diff --git a/contrib/llvm/include/llvm-c/ExecutionEngine.h b/contrib/llvm/include/llvm-c/ExecutionEngine.h index 8fae77def..356431220 100644 --- a/contrib/llvm/include/llvm-c/ExecutionEngine.h +++ b/contrib/llvm/include/llvm-c/ExecutionEngine.h @@ -40,12 +40,14 @@ void LLVMLinkInInterpreter(void); typedef struct LLVMOpaqueGenericValue *LLVMGenericValueRef; typedef struct LLVMOpaqueExecutionEngine *LLVMExecutionEngineRef; +typedef struct LLVMOpaqueMCJITMemoryManager *LLVMMCJITMemoryManagerRef; struct LLVMMCJITCompilerOptions { unsigned OptLevel; LLVMCodeModel CodeModel; LLVMBool NoFramePointerElim; LLVMBool EnableFastISel; + LLVMMCJITMemoryManagerRef MCJMM; }; /*===-- Operations on generic values --------------------------------------===*/ @@ -167,12 +169,44 @@ void LLVMAddGlobalMapping(LLVMExecutionEngineRef EE, LLVMValueRef Global, void *LLVMGetPointerToGlobal(LLVMExecutionEngineRef EE, LLVMValueRef Global); +/*===-- Operations on memory managers -------------------------------------===*/ + +typedef uint8_t *(*LLVMMemoryManagerAllocateCodeSectionCallback)( + void *Opaque, uintptr_t Size, unsigned Alignment, unsigned SectionID, + const char *SectionName); +typedef uint8_t *(*LLVMMemoryManagerAllocateDataSectionCallback)( + void *Opaque, uintptr_t Size, unsigned Alignment, unsigned SectionID, + const char *SectionName, LLVMBool IsReadOnly); +typedef LLVMBool (*LLVMMemoryManagerFinalizeMemoryCallback)( + void *Opaque, char **ErrMsg); +typedef void (*LLVMMemoryManagerDestroyCallback)(void *Opaque); + +/** + * Create a simple custom MCJIT memory manager. This memory manager can + * intercept allocations in a module-oblivious way. This will return NULL + * if any of the passed functions are NULL. + * + * @param Opaque An opaque client object to pass back to the callbacks. + * @param AllocateCodeSection Allocate a block of memory for executable code. + * @param AllocateDataSection Allocate a block of memory for data. + * @param FinalizeMemory Set page permissions and flush cache. Return 0 on + * success, 1 on error. + */ +LLVMMCJITMemoryManagerRef LLVMCreateSimpleMCJITMemoryManager( + void *Opaque, + LLVMMemoryManagerAllocateCodeSectionCallback AllocateCodeSection, + LLVMMemoryManagerAllocateDataSectionCallback AllocateDataSection, + LLVMMemoryManagerFinalizeMemoryCallback FinalizeMemory, + LLVMMemoryManagerDestroyCallback Destroy); + +void LLVMDisposeMCJITMemoryManager(LLVMMCJITMemoryManagerRef MM); + /** * @} */ #ifdef __cplusplus -} +} #endif /* defined(__cplusplus) */ #endif diff --git a/contrib/llvm/include/llvm-c/IRReader.h b/contrib/llvm/include/llvm-c/IRReader.h new file mode 100644 index 000000000..d0a23be0a --- /dev/null +++ b/contrib/llvm/include/llvm-c/IRReader.h @@ -0,0 +1,40 @@ +/*===-- llvm-c/IRReader.h - IR Reader C Interface -----------------*- C -*-===*\ +|* *| +|* The LLVM Compiler Infrastructure *| +|* *| +|* This file is distributed under the University of Illinois Open Source *| +|* License. See LICENSE.TXT for details. *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This file defines the C interface to the IR Reader. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_C_IRREADER_H +#define LLVM_C_IRREADER_H + +#include "llvm-c/Core.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Read LLVM IR from a memory buffer and convert it into an in-memory Module + * object. Returns 0 on success. + * Optionally returns a human-readable description of any errors that + * occured during parsing IR. OutMessage must be disposed with + * LLVMDisposeMessage. + * + * @see llvm::ParseIR() + */ +LLVMBool LLVMParseIRInContext(LLVMContextRef ContextRef, + LLVMMemoryBufferRef MemBuf, LLVMModuleRef *OutM, + char **OutMessage); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/contrib/llvm/include/llvm-c/LinkTimeOptimizer.h b/contrib/llvm/include/llvm-c/LinkTimeOptimizer.h index 7a0fbf65b..8bcf59969 100644 --- a/contrib/llvm/include/llvm-c/LinkTimeOptimizer.h +++ b/contrib/llvm/include/llvm-c/LinkTimeOptimizer.h @@ -4,7 +4,7 @@ // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. -// +// //===----------------------------------------------------------------------===// // // This header provides a C API to use the LLVM link time optimization @@ -46,7 +46,7 @@ extern "C" { // Added C-specific error codes LLVM_LTO_NULL_OBJECT } llvm_lto_status_t; - + /// This provides C interface to initialize link time optimizer. This allows /// linker to use dlopen() interface to dynamically load LinkTimeOptimizer. /// extern "C" helps, because dlopen() interface uses name to find the symbol. diff --git a/contrib/llvm/include/llvm-c/Object.h b/contrib/llvm/include/llvm-c/Object.h index ecccfeed7..c27155248 100644 --- a/contrib/llvm/include/llvm-c/Object.h +++ b/contrib/llvm/include/llvm-c/Object.h @@ -100,4 +100,3 @@ const char *LLVMGetRelocationValueString(LLVMRelocationIteratorRef RI); #endif /* defined(__cplusplus) */ #endif - diff --git a/contrib/llvm/include/llvm-c/Support.h b/contrib/llvm/include/llvm-c/Support.h new file mode 100644 index 000000000..7f03ede60 --- /dev/null +++ b/contrib/llvm/include/llvm-c/Support.h @@ -0,0 +1,35 @@ +/*===-- llvm-c/Support.h - Support C Interface --------------------*- C -*-===*\ +|* *| +|* The LLVM Compiler Infrastructure *| +|* *| +|* This file is distributed under the University of Illinois Open Source *| +|* License. See LICENSE.TXT for details. *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This file defines the C interface to the LLVM support library. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_C_SUPPORT_H +#define LLVM_C_SUPPORT_H + +#include "llvm-c/Core.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * This function permanently loads the dynamic library at the given path. + * It is safe to call this function multiple times for the same library. + * + * @see sys::DynamicLibrary::LoadLibraryPermanently() + */ +LLVMBool LLVMLoadLibraryPermanently(const char* Filename); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/contrib/llvm/include/llvm-c/Target.h b/contrib/llvm/include/llvm-c/Target.h index 80fc3e5ad..b465b4b88 100644 --- a/contrib/llvm/include/llvm-c/Target.h +++ b/contrib/llvm/include/llvm-c/Target.h @@ -22,6 +22,10 @@ #include "llvm-c/Core.h" #include "llvm/Config/llvm-config.h" +#if defined(_MSC_VER) && !defined(inline) +#define inline __inline +#endif + #ifdef __cplusplus extern "C" { #endif @@ -37,14 +41,13 @@ enum LLVMByteOrdering { LLVMBigEndian, LLVMLittleEndian }; typedef struct LLVMOpaqueTargetData *LLVMTargetDataRef; typedef struct LLVMOpaqueTargetLibraryInfotData *LLVMTargetLibraryInfoRef; -typedef struct LLVMStructLayout *LLVMStructLayoutRef; /* Declare all of the target-initialization functions that are available. */ #define LLVM_TARGET(TargetName) \ void LLVMInitialize##TargetName##TargetInfo(void); #include "llvm/Config/Targets.def" #undef LLVM_TARGET /* Explicit undef to make SWIG happier */ - + #define LLVM_TARGET(TargetName) void LLVMInitialize##TargetName##Target(void); #include "llvm/Config/Targets.def" #undef LLVM_TARGET /* Explicit undef to make SWIG happier */ @@ -53,7 +56,7 @@ typedef struct LLVMStructLayout *LLVMStructLayoutRef; void LLVMInitialize##TargetName##TargetMC(void); #include "llvm/Config/Targets.def" #undef LLVM_TARGET /* Explicit undef to make SWIG happier */ - + /* Declare all of the available assembly printer initialization functions. */ #define LLVM_ASM_PRINTER(TargetName) \ void LLVMInitialize##TargetName##AsmPrinter(void); @@ -71,7 +74,7 @@ typedef struct LLVMStructLayout *LLVMStructLayoutRef; void LLVMInitialize##TargetName##Disassembler(void); #include "llvm/Config/Disassemblers.def" #undef LLVM_DISASSEMBLER /* Explicit undef to make SWIG happier */ - + /** LLVMInitializeAllTargetInfos - The main program should call this function if it wants access to all available targets that LLVM is configured to support. */ @@ -98,7 +101,7 @@ static inline void LLVMInitializeAllTargetMCs(void) { #include "llvm/Config/Targets.def" #undef LLVM_TARGET /* Explicit undef to make SWIG happier */ } - + /** LLVMInitializeAllAsmPrinters - The main program should call this function if it wants all asm printers that LLVM is configured to support, to make them available via the TargetRegistry. */ @@ -107,7 +110,7 @@ static inline void LLVMInitializeAllAsmPrinters(void) { #include "llvm/Config/AsmPrinters.def" #undef LLVM_ASM_PRINTER /* Explicit undef to make SWIG happier */ } - + /** LLVMInitializeAllAsmParsers - The main program should call this function if it wants all asm parsers that LLVM is configured to support, to make them available via the TargetRegistry. */ @@ -116,7 +119,7 @@ static inline void LLVMInitializeAllAsmParsers(void) { #include "llvm/Config/AsmParsers.def" #undef LLVM_ASM_PARSER /* Explicit undef to make SWIG happier */ } - + /** LLVMInitializeAllDisassemblers - The main program should call this function if it wants all disassemblers that LLVM is configured to support, to make them available via the TargetRegistry. */ @@ -126,9 +129,9 @@ static inline void LLVMInitializeAllDisassemblers(void) { #include "llvm/Config/Disassemblers.def" #undef LLVM_DISASSEMBLER /* Explicit undef to make SWIG happier */ } - + /** LLVMInitializeNativeTarget - The main program should call this function to - initialize the native target corresponding to the host. This is useful + initialize the native target corresponding to the host. This is useful for JIT applications to ensure that the target gets linked in correctly. */ static inline LLVMBool LLVMInitializeNativeTarget(void) { /* If we have a native target, initialize it to ensure it is linked in. */ @@ -140,7 +143,43 @@ static inline LLVMBool LLVMInitializeNativeTarget(void) { #else return 1; #endif -} +} + +/** LLVMInitializeNativeTargetAsmParser - The main program should call this + function to initialize the parser for the native target corresponding to the + host. */ +static inline LLVMBool LLVMInitializeNativeAsmParser(void) { +#ifdef LLVM_NATIVE_ASMPARSER + LLVM_NATIVE_ASMPARSER(); + return 0; +#else + return 1; +#endif +} + +/** LLVMInitializeNativeTargetAsmPrinter - The main program should call this + function to initialize the printer for the native target corresponding to + the host. */ +static inline LLVMBool LLVMInitializeNativeAsmPrinter(void) { +#ifdef LLVM_NATIVE_ASMPRINTER + LLVM_NATIVE_ASMPRINTER(); + return 0; +#else + return 1; +#endif +} + +/** LLVMInitializeNativeTargetDisassembler - The main program should call this + function to initialize the disassembler for the native target corresponding + to the host. */ +static inline LLVMBool LLVMInitializeNativeDisassembler(void) { +#ifdef LLVM_NATIVE_DISASSEMBLER + LLVM_NATIVE_DISASSEMBLER(); + return 0; +#else + return 1; +#endif +} /*===-- Target Data -------------------------------------------------------===*/ @@ -151,83 +190,94 @@ LLVMTargetDataRef LLVMCreateTargetData(const char *StringRep); /** Adds target data information to a pass manager. This does not take ownership of the target data. See the method llvm::PassManagerBase::add. */ -void LLVMAddTargetData(LLVMTargetDataRef, LLVMPassManagerRef); +void LLVMAddTargetData(LLVMTargetDataRef TD, LLVMPassManagerRef PM); /** Adds target library information to a pass manager. This does not take ownership of the target library info. See the method llvm::PassManagerBase::add. */ -void LLVMAddTargetLibraryInfo(LLVMTargetLibraryInfoRef, LLVMPassManagerRef); +void LLVMAddTargetLibraryInfo(LLVMTargetLibraryInfoRef TLI, + LLVMPassManagerRef PM); /** Converts target data to a target layout string. The string must be disposed with LLVMDisposeMessage. See the constructor llvm::DataLayout::DataLayout. */ -char *LLVMCopyStringRepOfTargetData(LLVMTargetDataRef); +char *LLVMCopyStringRepOfTargetData(LLVMTargetDataRef TD); /** Returns the byte order of a target, either LLVMBigEndian or LLVMLittleEndian. See the method llvm::DataLayout::isLittleEndian. */ -enum LLVMByteOrdering LLVMByteOrder(LLVMTargetDataRef); +enum LLVMByteOrdering LLVMByteOrder(LLVMTargetDataRef TD); /** Returns the pointer size in bytes for a target. See the method llvm::DataLayout::getPointerSize. */ -unsigned LLVMPointerSize(LLVMTargetDataRef); +unsigned LLVMPointerSize(LLVMTargetDataRef TD); /** Returns the pointer size in bytes for a target for a specified address space. See the method llvm::DataLayout::getPointerSize. */ -unsigned LLVMPointerSizeForAS(LLVMTargetDataRef, unsigned AS); +unsigned LLVMPointerSizeForAS(LLVMTargetDataRef TD, unsigned AS); + +/** Returns the integer type that is the same size as a pointer on a target. + See the method llvm::DataLayout::getIntPtrType. */ +LLVMTypeRef LLVMIntPtrType(LLVMTargetDataRef TD); + +/** Returns the integer type that is the same size as a pointer on a target. + This version allows the address space to be specified. + See the method llvm::DataLayout::getIntPtrType. */ +LLVMTypeRef LLVMIntPtrTypeForAS(LLVMTargetDataRef TD, unsigned AS); /** Returns the integer type that is the same size as a pointer on a target. See the method llvm::DataLayout::getIntPtrType. */ -LLVMTypeRef LLVMIntPtrType(LLVMTargetDataRef); +LLVMTypeRef LLVMIntPtrTypeInContext(LLVMContextRef C, LLVMTargetDataRef TD); /** Returns the integer type that is the same size as a pointer on a target. This version allows the address space to be specified. See the method llvm::DataLayout::getIntPtrType. */ -LLVMTypeRef LLVMIntPtrTypeForAS(LLVMTargetDataRef, unsigned AS); +LLVMTypeRef LLVMIntPtrTypeForASInContext(LLVMContextRef C, LLVMTargetDataRef TD, + unsigned AS); /** Computes the size of a type in bytes for a target. See the method llvm::DataLayout::getTypeSizeInBits. */ -unsigned long long LLVMSizeOfTypeInBits(LLVMTargetDataRef, LLVMTypeRef); +unsigned long long LLVMSizeOfTypeInBits(LLVMTargetDataRef TD, LLVMTypeRef Ty); /** Computes the storage size of a type in bytes for a target. See the method llvm::DataLayout::getTypeStoreSize. */ -unsigned long long LLVMStoreSizeOfType(LLVMTargetDataRef, LLVMTypeRef); +unsigned long long LLVMStoreSizeOfType(LLVMTargetDataRef TD, LLVMTypeRef Ty); /** Computes the ABI size of a type in bytes for a target. See the method llvm::DataLayout::getTypeAllocSize. */ -unsigned long long LLVMABISizeOfType(LLVMTargetDataRef, LLVMTypeRef); +unsigned long long LLVMABISizeOfType(LLVMTargetDataRef TD, LLVMTypeRef Ty); /** Computes the ABI alignment of a type in bytes for a target. See the method llvm::DataLayout::getTypeABISize. */ -unsigned LLVMABIAlignmentOfType(LLVMTargetDataRef, LLVMTypeRef); +unsigned LLVMABIAlignmentOfType(LLVMTargetDataRef TD, LLVMTypeRef Ty); /** Computes the call frame alignment of a type in bytes for a target. See the method llvm::DataLayout::getTypeABISize. */ -unsigned LLVMCallFrameAlignmentOfType(LLVMTargetDataRef, LLVMTypeRef); +unsigned LLVMCallFrameAlignmentOfType(LLVMTargetDataRef TD, LLVMTypeRef Ty); /** Computes the preferred alignment of a type in bytes for a target. See the method llvm::DataLayout::getTypeABISize. */ -unsigned LLVMPreferredAlignmentOfType(LLVMTargetDataRef, LLVMTypeRef); +unsigned LLVMPreferredAlignmentOfType(LLVMTargetDataRef TD, LLVMTypeRef Ty); /** Computes the preferred alignment of a global variable in bytes for a target. See the method llvm::DataLayout::getPreferredAlignment. */ -unsigned LLVMPreferredAlignmentOfGlobal(LLVMTargetDataRef, +unsigned LLVMPreferredAlignmentOfGlobal(LLVMTargetDataRef TD, LLVMValueRef GlobalVar); /** Computes the structure element that contains the byte offset for a target. See the method llvm::StructLayout::getElementContainingOffset. */ -unsigned LLVMElementAtOffset(LLVMTargetDataRef, LLVMTypeRef StructTy, +unsigned LLVMElementAtOffset(LLVMTargetDataRef TD, LLVMTypeRef StructTy, unsigned long long Offset); /** Computes the byte offset of the indexed struct element for a target. See the method llvm::StructLayout::getElementContainingOffset. */ -unsigned long long LLVMOffsetOfElement(LLVMTargetDataRef, LLVMTypeRef StructTy, - unsigned Element); +unsigned long long LLVMOffsetOfElement(LLVMTargetDataRef TD, + LLVMTypeRef StructTy, unsigned Element); /** Deallocates a TargetData. See the destructor llvm::DataLayout::~DataLayout. */ -void LLVMDisposeTargetData(LLVMTargetDataRef); +void LLVMDisposeTargetData(LLVMTargetDataRef TD); /** * @} diff --git a/contrib/llvm/include/llvm-c/TargetMachine.h b/contrib/llvm/include/llvm-c/TargetMachine.h index 5e355959f..e15941139 100644 --- a/contrib/llvm/include/llvm-c/TargetMachine.h +++ b/contrib/llvm/include/llvm-c/TargetMachine.h @@ -57,11 +57,21 @@ typedef enum { } LLVMCodeGenFileType; /** Returns the first llvm::Target in the registered targets list. */ -LLVMTargetRef LLVMGetFirstTarget(); +LLVMTargetRef LLVMGetFirstTarget(void); /** Returns the next llvm::Target given a previous one (or null if there's none) */ LLVMTargetRef LLVMGetNextTarget(LLVMTargetRef T); /*===-- Target ------------------------------------------------------------===*/ +/** Finds the target corresponding to the given name and stores it in \p T. + Returns 0 on success. */ +LLVMTargetRef LLVMGetTargetFromName(const char *Name); + +/** Finds the target corresponding to the given triple and stores it in \p T. + Returns 0 on success. Optionally returns any error in ErrorMessage. + Use LLVMDisposeMessage to dispose the message. */ +LLVMBool LLVMGetTargetFromTriple(const char* Triple, LLVMTargetRef *T, + char **ErrorMessage); + /** Returns the name of a target. See llvm::Target::getName */ const char *LLVMGetTargetName(LLVMTargetRef T); @@ -79,9 +89,9 @@ LLVMBool LLVMTargetHasAsmBackend(LLVMTargetRef T); /*===-- Target Machine ----------------------------------------------------===*/ /** Creates a new llvm::TargetMachine. See llvm::Target::createTargetMachine */ -LLVMTargetMachineRef LLVMCreateTargetMachine(LLVMTargetRef T, char *Triple, - char *CPU, char *Features, LLVMCodeGenOptLevel Level, LLVMRelocMode Reloc, - LLVMCodeModel CodeModel); +LLVMTargetMachineRef LLVMCreateTargetMachine(LLVMTargetRef T, + const char *Triple, const char *CPU, const char *Features, + LLVMCodeGenOptLevel Level, LLVMRelocMode Reloc, LLVMCodeModel CodeModel); /** Dispose the LLVMTargetMachineRef instance generated by LLVMCreateTargetMachine. */ @@ -108,6 +118,10 @@ char *LLVMGetTargetMachineFeatureString(LLVMTargetMachineRef T); /** Returns the llvm::DataLayout used for this llvm:TargetMachine. */ LLVMTargetDataRef LLVMGetTargetMachineData(LLVMTargetMachineRef T); +/** Set the target machine's ASM verbosity. */ +void LLVMSetTargetMachineAsmVerbosity(LLVMTargetMachineRef T, + LLVMBool VerboseAsm); + /** Emits an asm or object file for the given module to the filename. This wraps several c++ only classes (among them a file stream). Returns any error in ErrorMessage. Use LLVMDisposeMessage to dispose the message. */ @@ -117,6 +131,12 @@ LLVMBool LLVMTargetMachineEmitToFile(LLVMTargetMachineRef T, LLVMModuleRef M, /** Compile the LLVM IR stored in \p M and store the result in \p OutMemBuf. */ LLVMBool LLVMTargetMachineEmitToMemoryBuffer(LLVMTargetMachineRef T, LLVMModuleRef M, LLVMCodeGenFileType codegen, char** ErrorMessage, LLVMMemoryBufferRef *OutMemBuf); + +/*===-- Triple ------------------------------------------------------------===*/ +/** Get a triple for the host machine as a string. The result needs to be + disposed with LLVMDisposeMessage. */ +char* LLVMGetDefaultTargetTriple(void); + #ifdef __cplusplus } #endif diff --git a/contrib/llvm/include/llvm-c/Transforms/Scalar.h b/contrib/llvm/include/llvm-c/Transforms/Scalar.h index a2c4d6116..355e8dc29 100644 --- a/contrib/llvm/include/llvm-c/Transforms/Scalar.h +++ b/contrib/llvm/include/llvm-c/Transforms/Scalar.h @@ -65,6 +65,9 @@ void LLVMAddLoopIdiomPass(LLVMPassManagerRef PM); /** See llvm::createLoopRotatePass function. */ void LLVMAddLoopRotatePass(LLVMPassManagerRef PM); +/** See llvm::createLoopRerollPass function. */ +void LLVMAddLoopRerollPass(LLVMPassManagerRef PM); + /** See llvm::createLoopUnrollPass function. */ void LLVMAddLoopUnrollPass(LLVMPassManagerRef PM); @@ -74,6 +77,9 @@ void LLVMAddLoopUnswitchPass(LLVMPassManagerRef PM); /** See llvm::createMemCpyOptPass function. */ void LLVMAddMemCpyOptPass(LLVMPassManagerRef PM); +/** See llvm::createPartiallyInlineLibCallsPass function. */ +void LLVMAddPartiallyInlineLibCallsPass(LLVMPassManagerRef PM); + /** See llvm::createPromoteMemoryToRegisterPass function. */ void LLVMAddPromoteMemoryToRegisterPass(LLVMPassManagerRef PM); diff --git a/contrib/llvm/include/llvm-c/lto.h b/contrib/llvm/include/llvm-c/lto.h index 40110fddf..89f54b7a7 100644 --- a/contrib/llvm/include/llvm-c/lto.h +++ b/contrib/llvm/include/llvm-c/lto.h @@ -16,9 +16,22 @@ #ifndef LLVM_C_LTO_H #define LLVM_C_LTO_H -#include #include -#include +#include + +#ifndef __cplusplus +#if !defined(_MSC_VER) +#include +typedef bool lto_bool_t; +#else +/* MSVC in particular does not have anything like _Bool or bool in C, but we can + at least make sure the type is the same size. The implementation side will + use C++ bool. */ +typedef unsigned char lto_bool_t; +#endif +#else +typedef bool lto_bool_t; +#endif /** * @defgroup LLVMCLTO LTO @@ -27,7 +40,7 @@ * @{ */ -#define LTO_API_VERSION 4 +#define LTO_API_VERSION 5 typedef enum { LTO_SYMBOL_ALIGNMENT_MASK = 0x0000001F, /* log2 of alignment */ @@ -87,14 +100,14 @@ lto_get_error_message(void); /** * Checks if a file is a loadable object file. */ -extern bool +extern lto_bool_t lto_module_is_object_file(const char* path); /** * Checks if a file is a loadable object compiled for requested target. */ -extern bool +extern lto_bool_t lto_module_is_object_file_for_target(const char* path, const char* target_triple_prefix); @@ -102,14 +115,14 @@ lto_module_is_object_file_for_target(const char* path, /** * Checks if a buffer is a loadable object file. */ -extern bool +extern lto_bool_t lto_module_is_object_file_in_memory(const void* mem, size_t length); /** * Checks if a buffer is a loadable object compiled for requested target. */ -extern bool +extern lto_bool_t lto_module_is_object_file_in_memory_for_target(const void* mem, size_t length, const char* target_triple_prefix); @@ -208,7 +221,7 @@ lto_codegen_dispose(lto_code_gen_t); * Add an object module to the set of modules for which code will be generated. * Returns true on error (check lto_get_error_message() for details). */ -extern bool +extern lto_bool_t lto_codegen_add_module(lto_code_gen_t cg, lto_module_t mod); @@ -217,7 +230,7 @@ lto_codegen_add_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). */ -extern bool +extern lto_bool_t lto_codegen_set_debug_model(lto_code_gen_t cg, lto_debug_model); @@ -225,7 +238,7 @@ lto_codegen_set_debug_model(lto_code_gen_t cg, lto_debug_model); * Sets which PIC code model to generated. * Returns true on error (check lto_get_error_message() for details). */ -extern bool +extern lto_bool_t lto_codegen_set_pic_model(lto_code_gen_t cg, lto_codegen_model); @@ -251,9 +264,8 @@ lto_codegen_set_assembler_args(lto_code_gen_t cg, const char **args, int nargs); /** - * Adds to a list of all global symbols that must exist in the final - * generated code. If a function is not listed, it might be - * inlined into every usage and optimized away. + * Tells LTO optimization passes that this symbol must be preserved + * because it is referenced by native code or a command line option. */ extern void lto_codegen_add_must_preserve_symbol(lto_code_gen_t cg, const char* symbol); @@ -263,7 +275,7 @@ lto_codegen_add_must_preserve_symbol(lto_code_gen_t cg, const char* symbol); * merged contents of all modules added so far. * Returns true on error (check lto_get_error_message() for details). */ -extern bool +extern lto_bool_t lto_codegen_write_merged_modules(lto_code_gen_t cg, const char* path); /** @@ -281,7 +293,7 @@ lto_codegen_compile(lto_code_gen_t cg, size_t* length); * Generates code for all added modules into one native object file. * The name of the file is written to name. Returns true on error. */ -extern bool +extern lto_bool_t lto_codegen_compile_to_file(lto_code_gen_t cg, const char** name); diff --git a/contrib/llvm/include/llvm/ADT/APFloat.h b/contrib/llvm/include/llvm/ADT/APFloat.h index 14bcaef6d..43a78660b 100644 --- a/contrib/llvm/include/llvm/ADT/APFloat.h +++ b/contrib/llvm/include/llvm/ADT/APFloat.h @@ -6,461 +6,575 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// This file declares a class to represent arbitrary precision floating -// point values and provide a variety of arithmetic operations on them. -// +/// +/// \file +/// \brief +/// This file declares a class to represent arbitrary precision floating point +/// values and provide a variety of arithmetic operations on them. +/// //===----------------------------------------------------------------------===// -/* A self-contained host- and target-independent arbitrary-precision - floating-point software implementation. It uses bignum integer - arithmetic as provided by static functions in the APInt class. - The library will work with bignum integers whose parts are any - unsigned type at least 16 bits wide, but 64 bits is recommended. - - Written for clarity rather than speed, in particular with a view - to use in the front-end of a cross compiler so that target - arithmetic can be correctly performed on the host. Performance - should nonetheless be reasonable, particularly for its intended - use. It may be useful as a base implementation for a run-time - library during development of a faster target-specific one. - - All 5 rounding modes in the IEEE-754R draft are handled correctly - for all implemented operations. Currently implemented operations - are add, subtract, multiply, divide, fused-multiply-add, - conversion-to-float, conversion-to-integer and - conversion-from-integer. New rounding modes (e.g. away from zero) - can be added with three or four lines of code. - - Four formats are built-in: IEEE single precision, double - precision, quadruple precision, and x87 80-bit extended double - (when operating with full extended precision). Adding a new - format that obeys IEEE semantics only requires adding two lines of - code: a declaration and definition of the format. - - All operations return the status of that operation as an exception - bit-mask, so multiple operations can be done consecutively with - their results or-ed together. The returned status can be useful - for compiler diagnostics; e.g., inexact, underflow and overflow - can be easily diagnosed on constant folding, and compiler - optimizers can determine what exceptions would be raised by - folding operations and optimize, or perhaps not optimize, - accordingly. - - At present, underflow tininess is detected after rounding; it - should be straight forward to add support for the before-rounding - case too. - - The library reads hexadecimal floating point numbers as per C99, - and correctly rounds if necessary according to the specified - rounding mode. Syntax is required to have been validated by the - caller. It also converts floating point numbers to hexadecimal - text as per the C99 %a and %A conversions. The output precision - (or alternatively the natural minimal precision) can be specified; - if the requested precision is less than the natural precision the - output is correctly rounded for the specified rounding mode. - - It also reads decimal floating point numbers and correctly rounds - according to the specified rounding mode. - - Conversion to decimal text is not currently implemented. - - Non-zero finite numbers are represented internally as a sign bit, - a 16-bit signed exponent, and the significand as an array of - integer parts. After normalization of a number of precision P the - exponent is within the range of the format, and if the number is - not denormal the P-th bit of the significand is set as an explicit - integer bit. For denormals the most significant bit is shifted - right so that the exponent is maintained at the format's minimum, - so that the smallest denormal has just the least significant bit - of the significand set. The sign of zeroes and infinities is - significant; the exponent and significand of such numbers is not - stored, but has a known implicit (deterministic) value: 0 for the - significands, 0 for zero exponent, all 1 bits for infinity - exponent. For NaNs the sign and significand are deterministic, - although not really meaningful, and preserved in non-conversion - operations. The exponent is implicitly all 1 bits. - - TODO - ==== - - Some features that may or may not be worth adding: - - Binary to decimal conversion (hard). - - Optional ability to detect underflow tininess before rounding. - - New formats: x87 in single and double precision mode (IEEE apart - from extended exponent range) (hard). - - New operations: sqrt, IEEE remainder, C90 fmod, nextafter, - nexttoward. -*/ - #ifndef LLVM_ADT_APFLOAT_H #define LLVM_ADT_APFLOAT_H -// APInt contains static functions implementing bignum arithmetic. #include "llvm/ADT/APInt.h" namespace llvm { - /* Exponents are stored as signed numbers. */ - typedef signed short exponent_t; - - struct fltSemantics; - class APSInt; - class StringRef; - - /* When bits of a floating point number are truncated, this enum is - used to indicate what fraction of the LSB those bits represented. - It essentially combines the roles of guard and sticky bits. */ - enum lostFraction { // Example of truncated bits: - lfExactlyZero, // 000000 - lfLessThanHalf, // 0xxxxx x's not all zero - lfExactlyHalf, // 100000 - lfMoreThanHalf // 1xxxxx x's not all zero +struct fltSemantics; +class APSInt; +class StringRef; + +/// Enum that represents what fraction of the LSB truncated bits of an fp number +/// represent. +/// +/// This essentially combines the roles of guard and sticky bits. +enum lostFraction { // Example of truncated bits: + lfExactlyZero, // 000000 + lfLessThanHalf, // 0xxxxx x's not all zero + lfExactlyHalf, // 100000 + lfMoreThanHalf // 1xxxxx x's not all zero +}; + +/// \brief A self-contained host- and target-independent arbitrary-precision +/// floating-point software implementation. +/// +/// APFloat uses bignum integer arithmetic as provided by static functions in +/// the APInt class. The library will work with bignum integers whose parts are +/// any unsigned type at least 16 bits wide, but 64 bits is recommended. +/// +/// Written for clarity rather than speed, in particular with a view to use in +/// the front-end of a cross compiler so that target arithmetic can be correctly +/// performed on the host. Performance should nonetheless be reasonable, +/// particularly for its intended use. It may be useful as a base +/// implementation for a run-time library during development of a faster +/// target-specific one. +/// +/// All 5 rounding modes in the IEEE-754R draft are handled correctly for all +/// implemented operations. Currently implemented operations are add, subtract, +/// multiply, divide, fused-multiply-add, conversion-to-float, +/// conversion-to-integer and conversion-from-integer. New rounding modes +/// (e.g. away from zero) can be added with three or four lines of code. +/// +/// Four formats are built-in: IEEE single precision, double precision, +/// quadruple precision, and x87 80-bit extended double (when operating with +/// full extended precision). Adding a new format that obeys IEEE semantics +/// only requires adding two lines of code: a declaration and definition of the +/// format. +/// +/// All operations return the status of that operation as an exception bit-mask, +/// so multiple operations can be done consecutively with their results or-ed +/// together. The returned status can be useful for compiler diagnostics; e.g., +/// inexact, underflow and overflow can be easily diagnosed on constant folding, +/// and compiler optimizers can determine what exceptions would be raised by +/// folding operations and optimize, or perhaps not optimize, accordingly. +/// +/// At present, underflow tininess is detected after rounding; it should be +/// straight forward to add support for the before-rounding case too. +/// +/// The library reads hexadecimal floating point numbers as per C99, and +/// correctly rounds if necessary according to the specified rounding mode. +/// Syntax is required to have been validated by the caller. It also converts +/// floating point numbers to hexadecimal text as per the C99 %a and %A +/// conversions. The output precision (or alternatively the natural minimal +/// precision) can be specified; if the requested precision is less than the +/// natural precision the output is correctly rounded for the specified rounding +/// mode. +/// +/// It also reads decimal floating point numbers and correctly rounds according +/// to the specified rounding mode. +/// +/// Conversion to decimal text is not currently implemented. +/// +/// Non-zero finite numbers are represented internally as a sign bit, a 16-bit +/// signed exponent, and the significand as an array of integer parts. After +/// normalization of a number of precision P the exponent is within the range of +/// the format, and if the number is not denormal the P-th bit of the +/// significand is set as an explicit integer bit. For denormals the most +/// significant bit is shifted right so that the exponent is maintained at the +/// format's minimum, so that the smallest denormal has just the least +/// significant bit of the significand set. The sign of zeroes and infinities +/// is significant; the exponent and significand of such numbers is not stored, +/// but has a known implicit (deterministic) value: 0 for the significands, 0 +/// for zero exponent, all 1 bits for infinity exponent. For NaNs the sign and +/// significand are deterministic, although not really meaningful, and preserved +/// in non-conversion operations. The exponent is implicitly all 1 bits. +/// +/// APFloat does not provide any exception handling beyond default exception +/// handling. We represent Signaling NaNs via IEEE-754R 2008 6.2.1 should clause +/// by encoding Signaling NaNs with the first bit of its trailing significand as +/// 0. +/// +/// TODO +/// ==== +/// +/// Some features that may or may not be worth adding: +/// +/// Binary to decimal conversion (hard). +/// +/// Optional ability to detect underflow tininess before rounding. +/// +/// New formats: x87 in single and double precision mode (IEEE apart from +/// extended exponent range) (hard). +/// +/// New operations: sqrt, IEEE remainder, C90 fmod, nexttoward. +/// +class APFloat { +public: + + /// A signed type to represent a floating point numbers unbiased exponent. + typedef signed short ExponentType; + + /// \name Floating Point Semantics. + /// @{ + + static const fltSemantics IEEEhalf; + static const fltSemantics IEEEsingle; + static const fltSemantics IEEEdouble; + static const fltSemantics IEEEquad; + static const fltSemantics PPCDoubleDouble; + static const fltSemantics x87DoubleExtended; + + /// A Pseudo fltsemantic used to construct APFloats that cannot conflict with + /// anything real. + static const fltSemantics Bogus; + + /// @} + + static unsigned int semanticsPrecision(const fltSemantics &); + + /// IEEE-754R 5.11: Floating Point Comparison Relations. + enum cmpResult { + cmpLessThan, + cmpEqual, + cmpGreaterThan, + cmpUnordered }; - class APFloat { - public: - - /* We support the following floating point semantics. */ - static const fltSemantics IEEEhalf; - static const fltSemantics IEEEsingle; - static const fltSemantics IEEEdouble; - static const fltSemantics IEEEquad; - static const fltSemantics PPCDoubleDouble; - static const fltSemantics x87DoubleExtended; - /* And this pseudo, used to construct APFloats that cannot - conflict with anything real. */ - static const fltSemantics Bogus; - - static unsigned int semanticsPrecision(const fltSemantics &); - - /* Floating point numbers have a four-state comparison relation. */ - enum cmpResult { - cmpLessThan, - cmpEqual, - cmpGreaterThan, - cmpUnordered - }; - - /* IEEE-754R gives five rounding modes. */ - enum roundingMode { - rmNearestTiesToEven, - rmTowardPositive, - rmTowardNegative, - rmTowardZero, - rmNearestTiesToAway - }; - - // Operation status. opUnderflow or opOverflow are always returned - // or-ed with opInexact. - enum opStatus { - opOK = 0x00, - opInvalidOp = 0x01, - opDivByZero = 0x02, - opOverflow = 0x04, - opUnderflow = 0x08, - opInexact = 0x10 - }; - - // Category of internally-represented number. - enum fltCategory { - fcInfinity, - fcNaN, - fcNormal, - fcZero - }; - - enum uninitializedTag { - uninitialized - }; - - // Constructors. - APFloat(const fltSemantics &); // Default construct to 0.0 - APFloat(const fltSemantics &, StringRef); - APFloat(const fltSemantics &, integerPart); - APFloat(const fltSemantics &, fltCategory, bool negative); - APFloat(const fltSemantics &, uninitializedTag); - APFloat(const fltSemantics &, const APInt &); - explicit APFloat(double d); - explicit APFloat(float f); - APFloat(const APFloat &); - ~APFloat(); - - // Convenience "constructors" - static APFloat getZero(const fltSemantics &Sem, bool Negative = false) { - return APFloat(Sem, fcZero, Negative); - } - static APFloat getInf(const fltSemantics &Sem, bool Negative = false) { - return APFloat(Sem, fcInfinity, Negative); - } - - /// getNaN - Factory for QNaN values. - /// - /// \param Negative - True iff the NaN generated should be negative. - /// \param type - The unspecified fill bits for creating the NaN, 0 by - /// default. The value is truncated as necessary. - static APFloat getNaN(const fltSemantics &Sem, bool Negative = false, - unsigned type = 0) { - if (type) { - APInt fill(64, type); - return getQNaN(Sem, Negative, &fill); - } else { - return getQNaN(Sem, Negative, 0); - } - } - - /// getQNan - Factory for QNaN values. - static APFloat getQNaN(const fltSemantics &Sem, - bool Negative = false, - const APInt *payload = 0) { - return makeNaN(Sem, false, Negative, payload); - } + /// IEEE-754R 4.3: Rounding-direction attributes. + enum roundingMode { + rmNearestTiesToEven, + rmTowardPositive, + rmTowardNegative, + rmTowardZero, + rmNearestTiesToAway + }; - /// getSNan - Factory for SNaN values. - static APFloat getSNaN(const fltSemantics &Sem, - bool Negative = false, - const APInt *payload = 0) { - return makeNaN(Sem, true, Negative, payload); - } + /// IEEE-754R 7: Default exception handling. + /// + /// opUnderflow or opOverflow are always returned or-ed with opInexact. + enum opStatus { + opOK = 0x00, + opInvalidOp = 0x01, + opDivByZero = 0x02, + opOverflow = 0x04, + opUnderflow = 0x08, + opInexact = 0x10 + }; - /// getLargest - Returns the largest finite number in the given - /// semantics. - /// - /// \param Negative - True iff the number should be negative - static APFloat getLargest(const fltSemantics &Sem, bool Negative = false); - - /// getSmallest - Returns the smallest (by magnitude) finite number - /// in the given semantics. Might be denormalized, which implies a - /// relative loss of precision. - /// - /// \param Negative - True iff the number should be negative - static APFloat getSmallest(const fltSemantics &Sem, bool Negative = false); - - /// getSmallestNormalized - Returns the smallest (by magnitude) - /// normalized finite number in the given semantics. - /// - /// \param Negative - True iff the number should be negative - static APFloat getSmallestNormalized(const fltSemantics &Sem, - bool Negative = false); - - /// getAllOnesValue - Returns a float which is bitcasted from - /// an all one value int. - /// - /// \param BitWidth - Select float type - /// \param isIEEE - If 128 bit number, select between PPC and IEEE - static APFloat getAllOnesValue(unsigned BitWidth, bool isIEEE = false); - - /// Profile - Used to insert APFloat objects, or objects that contain - /// APFloat objects, into FoldingSets. - void Profile(FoldingSetNodeID& NID) const; - - /// @brief Used by the Bitcode serializer to emit APInts to Bitcode. - void Emit(Serializer& S) const; - - /// @brief Used by the Bitcode deserializer to deserialize APInts. - static APFloat ReadVal(Deserializer& D); - - /* Arithmetic. */ - opStatus add(const APFloat &, roundingMode); - opStatus subtract(const APFloat &, roundingMode); - opStatus multiply(const APFloat &, roundingMode); - opStatus divide(const APFloat &, roundingMode); - /* IEEE remainder. */ - opStatus remainder(const APFloat &); - /* C fmod, or llvm frem. */ - opStatus mod(const APFloat &, roundingMode); - opStatus fusedMultiplyAdd(const APFloat &, const APFloat &, roundingMode); - opStatus roundToIntegral(roundingMode); - - /* Sign operations. */ - void changeSign(); - void clearSign(); - void copySign(const APFloat &); - - /* Conversions. */ - opStatus convert(const fltSemantics &, roundingMode, bool *); - opStatus convertToInteger(integerPart *, unsigned int, bool, - roundingMode, bool *) const; - opStatus convertToInteger(APSInt&, roundingMode, bool *) const; - opStatus convertFromAPInt(const APInt &, - bool, roundingMode); - opStatus convertFromSignExtendedInteger(const integerPart *, unsigned int, - bool, roundingMode); - opStatus convertFromZeroExtendedInteger(const integerPart *, unsigned int, - bool, roundingMode); - opStatus convertFromString(StringRef, roundingMode); - APInt bitcastToAPInt() const; - double convertToDouble() const; - float convertToFloat() const; - - /* 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; - - /* IEEE comparison with another floating point number (NaNs - compare unordered, 0==-0). */ - cmpResult compare(const APFloat &) const; - - /* Bitwise comparison for equality (QNaNs compare equal, 0!=-0). */ - bool bitwiseIsEqual(const APFloat &) const; - - /* Write out a hexadecimal representation of the floating point - value to DST, which must be of sufficient size, in the C99 form - [-]0xh.hhhhp[+-]d. Return the number of characters written, - excluding the terminating NUL. */ - unsigned int convertToHexString(char *dst, unsigned int hexDigits, - bool upperCase, roundingMode) const; - - /* Simple queries. */ - fltCategory getCategory() const { return category; } - const fltSemantics &getSemantics() const { return *semantics; } - bool isZero() const { return category == fcZero; } - bool isNonZero() const { return category != fcZero; } - bool isNormal() const { return category == fcNormal; } - bool isNaN() const { return category == fcNaN; } - bool isInfinity() const { return category == fcInfinity; } - bool isNegative() const { return sign; } - bool isPosZero() const { return isZero() && !isNegative(); } - bool isNegZero() const { return isZero() && isNegative(); } - bool isDenormal() const; - - APFloat& operator=(const APFloat &); - - /// \brief Overload to compute a hash code for an APFloat value. - /// - /// Note that the use of hash codes for floating point values is in general - /// frought with peril. Equality is hard to define for these values. For - /// example, should negative and positive zero hash to different codes? Are - /// they equal or not? This hash value implementation specifically - /// emphasizes producing different codes for different inputs in order to - /// be used in canonicalization and memoization. As such, equality is - /// bitwiseIsEqual, and 0 != -0. - friend hash_code hash_value(const APFloat &Arg); - - /// Converts this value into a decimal string. - /// - /// \param FormatPrecision The maximum number of digits of - /// precision to output. If there are fewer digits available, - /// zero padding will not be used unless the value is - /// integral and small enough to be expressed in - /// FormatPrecision digits. 0 means to use the natural - /// precision of the number. - /// \param FormatMaxPadding The maximum number of zeros to - /// consider inserting before falling back to scientific - /// notation. 0 means to always use scientific notation. - /// - /// Number Precision MaxPadding Result - /// ------ --------- ---------- ------ - /// 1.01E+4 5 2 10100 - /// 1.01E+4 4 2 1.01E+4 - /// 1.01E+4 5 1 1.01E+4 - /// 1.01E-2 5 2 0.0101 - /// 1.01E-2 4 2 0.0101 - /// 1.01E-2 4 1 1.01E-2 - void toString(SmallVectorImpl &Str, - unsigned FormatPrecision = 0, - unsigned FormatMaxPadding = 3) const; - - /// getExactInverse - If this value has an exact multiplicative inverse, - /// store it in inv and return true. - bool getExactInverse(APFloat *inv) const; - - private: - - /* Trivial queries. */ - integerPart *significandParts(); - const integerPart *significandParts() const; - unsigned int partCount() const; - - /* Significand operations. */ - integerPart addSignificand(const APFloat &); - integerPart subtractSignificand(const APFloat &, integerPart); - lostFraction addOrSubtractSignificand(const APFloat &, bool subtract); - lostFraction multiplySignificand(const APFloat &, const APFloat *); - lostFraction divideSignificand(const APFloat &); - void incrementSignificand(); - void initialize(const fltSemantics *); - void shiftSignificandLeft(unsigned int); - lostFraction shiftSignificandRight(unsigned int); - unsigned int significandLSB() const; - unsigned int significandMSB() const; - void zeroSignificand(); - - /* Arithmetic on special values. */ - opStatus addOrSubtractSpecials(const APFloat &, bool subtract); - opStatus divideSpecials(const APFloat &); - opStatus multiplySpecials(const APFloat &); - opStatus modSpecials(const APFloat &); - - /* Miscellany. */ - static APFloat makeNaN(const fltSemantics &Sem, bool SNaN, bool Negative, - const APInt *fill); - void makeNaN(bool SNaN = false, bool Neg = false, const APInt *fill = 0); - opStatus normalize(roundingMode, lostFraction); - opStatus addOrSubtract(const APFloat &, roundingMode, bool subtract); - cmpResult compareAbsoluteValue(const APFloat &) const; - opStatus handleOverflow(roundingMode); - bool roundAwayFromZero(roundingMode, lostFraction, unsigned int) const; - opStatus convertToSignExtendedInteger(integerPart *, unsigned int, bool, - roundingMode, bool *) const; - opStatus convertFromUnsignedParts(const integerPart *, unsigned int, - roundingMode); - opStatus convertFromHexadecimalString(StringRef, roundingMode); - opStatus convertFromDecimalString(StringRef, roundingMode); - char *convertNormalToHexString(char *, unsigned int, bool, - roundingMode) const; - opStatus roundSignificandWithExponent(const integerPart *, unsigned int, - int, roundingMode); - - APInt convertHalfAPFloatToAPInt() const; - APInt convertFloatAPFloatToAPInt() const; - APInt convertDoubleAPFloatToAPInt() const; - APInt convertQuadrupleAPFloatToAPInt() const; - APInt convertF80LongDoubleAPFloatToAPInt() const; - APInt convertPPCDoubleDoubleAPFloatToAPInt() const; - void initFromAPInt(const fltSemantics *Sem, const APInt& api); - void initFromHalfAPInt(const APInt& api); - void initFromFloatAPInt(const APInt& api); - void initFromDoubleAPInt(const APInt& api); - void initFromQuadrupleAPInt(const APInt &api); - void initFromF80LongDoubleAPInt(const APInt& api); - void initFromPPCDoubleDoubleAPInt(const APInt& api); - - void assign(const APFloat &); - void copySignificand(const APFloat &); - void freeSignificand(); - - /* What kind of semantics does this value obey? */ - const fltSemantics *semantics; - - /* Significand - the fraction with an explicit integer bit. Must be - at least one bit wider than the target precision. */ - union Significand - { - integerPart part; - integerPart *parts; - } significand; - - /* The exponent - a signed number. */ - exponent_t exponent; - - /* What kind of floating point number this is. */ - /* Only 2 bits are required, but VisualStudio incorrectly sign extends - it. Using the extra bit keeps it from failing under VisualStudio */ - fltCategory category: 3; - - /* The sign bit of this number. */ - unsigned int sign: 1; + /// Category of internally-represented number. + enum fltCategory { + fcInfinity, + fcNaN, + fcNormal, + fcZero }; - // See friend declaration above. This additional declaration is required in - // order to compile LLVM with IBM xlC compiler. - hash_code hash_value(const APFloat &Arg); -} /* namespace llvm */ + /// Convenience enum used to construct an uninitialized APFloat. + enum uninitializedTag { + uninitialized + }; -#endif /* LLVM_ADT_APFLOAT_H */ + /// \name Constructors + /// @{ + + APFloat(const fltSemantics &); // Default construct to 0.0 + APFloat(const fltSemantics &, StringRef); + APFloat(const fltSemantics &, integerPart); + APFloat(const fltSemantics &, uninitializedTag); + APFloat(const fltSemantics &, const APInt &); + explicit APFloat(double d); + explicit APFloat(float f); + APFloat(const APFloat &); + ~APFloat(); + + /// @} + + /// \brief Returns whether this instance allocated memory. + bool needsCleanup() const { return partCount() > 1; } + + /// \name Convenience "constructors" + /// @{ + + /// Factory for Positive and Negative Zero. + /// + /// \param Negative True iff the number should be negative. + static APFloat getZero(const fltSemantics &Sem, bool Negative = false) { + APFloat Val(Sem, uninitialized); + Val.makeZero(Negative); + return Val; + } + + /// Factory for Positive and Negative Infinity. + /// + /// \param Negative True iff the number should be negative. + static APFloat getInf(const fltSemantics &Sem, bool Negative = false) { + APFloat Val(Sem, uninitialized); + Val.makeInf(Negative); + return Val; + } + + /// Factory for QNaN values. + /// + /// \param Negative - True iff the NaN generated should be negative. + /// \param type - The unspecified fill bits for creating the NaN, 0 by + /// default. The value is truncated as necessary. + static APFloat getNaN(const fltSemantics &Sem, bool Negative = false, + unsigned type = 0) { + if (type) { + APInt fill(64, type); + return getQNaN(Sem, Negative, &fill); + } else { + return getQNaN(Sem, Negative, 0); + } + } + + /// Factory for QNaN values. + static APFloat getQNaN(const fltSemantics &Sem, bool Negative = false, + const APInt *payload = 0) { + return makeNaN(Sem, false, Negative, payload); + } + + /// Factory for SNaN values. + static APFloat getSNaN(const fltSemantics &Sem, bool Negative = false, + const APInt *payload = 0) { + return makeNaN(Sem, true, Negative, payload); + } + + /// Returns the largest finite number in the given semantics. + /// + /// \param Negative - True iff the number should be negative + static APFloat getLargest(const fltSemantics &Sem, bool Negative = false); + + /// Returns the smallest (by magnitude) finite number in the given semantics. + /// Might be denormalized, which implies a relative loss of precision. + /// + /// \param Negative - True iff the number should be negative + static APFloat getSmallest(const fltSemantics &Sem, bool Negative = false); + + /// Returns the smallest (by magnitude) normalized finite number in the given + /// semantics. + /// + /// \param Negative - True iff the number should be negative + static APFloat getSmallestNormalized(const fltSemantics &Sem, + bool Negative = false); + + /// Returns a float which is bitcasted from an all one value int. + /// + /// \param BitWidth - Select float type + /// \param isIEEE - If 128 bit number, select between PPC and IEEE + static APFloat getAllOnesValue(unsigned BitWidth, bool isIEEE = false); + + /// @} + + /// Used to insert APFloat objects, or objects that contain APFloat objects, + /// into FoldingSets. + void Profile(FoldingSetNodeID &NID) const; + + /// \brief Used by the Bitcode serializer to emit APInts to Bitcode. + void Emit(Serializer &S) const; + + /// \brief Used by the Bitcode deserializer to deserialize APInts. + static APFloat ReadVal(Deserializer &D); + + /// \name Arithmetic + /// @{ + + opStatus add(const APFloat &, roundingMode); + opStatus subtract(const APFloat &, roundingMode); + opStatus multiply(const APFloat &, roundingMode); + opStatus divide(const APFloat &, roundingMode); + /// IEEE remainder. + opStatus remainder(const APFloat &); + /// C fmod, or llvm frem. + opStatus mod(const APFloat &, roundingMode); + opStatus fusedMultiplyAdd(const APFloat &, const APFloat &, roundingMode); + opStatus roundToIntegral(roundingMode); + /// IEEE-754R 5.3.1: nextUp/nextDown. + opStatus next(bool nextDown); + + /// @} + + /// \name Sign operations. + /// @{ + + void changeSign(); + void clearSign(); + void copySign(const APFloat &); + + /// @} + + /// \name Conversions + /// @{ + + opStatus convert(const fltSemantics &, roundingMode, bool *); + opStatus convertToInteger(integerPart *, unsigned int, bool, roundingMode, + bool *) const; + opStatus convertToInteger(APSInt &, roundingMode, bool *) const; + opStatus convertFromAPInt(const APInt &, bool, roundingMode); + opStatus convertFromSignExtendedInteger(const integerPart *, unsigned int, + bool, roundingMode); + opStatus convertFromZeroExtendedInteger(const integerPart *, unsigned int, + bool, roundingMode); + opStatus convertFromString(StringRef, roundingMode); + APInt bitcastToAPInt() const; + double convertToDouble() const; + float convertToFloat() const; + + /// @} + + /// 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; + + /// IEEE comparison with another floating point number (NaNs compare + /// unordered, 0==-0). + cmpResult compare(const APFloat &) const; + + /// Bitwise comparison for equality (QNaNs compare equal, 0!=-0). + bool bitwiseIsEqual(const APFloat &) const; + + /// Write out a hexadecimal representation of the floating point value to DST, + /// which must be of sufficient size, in the C99 form [-]0xh.hhhhp[+-]d. + /// Return the number of characters written, excluding the terminating NUL. + unsigned int convertToHexString(char *dst, unsigned int hexDigits, + bool upperCase, roundingMode) const; + + /// \name IEEE-754R 5.7.2 General operations. + /// @{ + + /// IEEE-754R isSignMinus: Returns true if and only if the current value is + /// negative. + /// + /// This applies to zeros and NaNs as well. + bool isNegative() const { return sign; } + + /// IEEE-754R isNormal: Returns true if and only if the current value is normal. + /// + /// This implies that the current value of the float is not zero, subnormal, + /// infinite, or NaN following the definition of normality from IEEE-754R. + bool isNormal() const { return !isDenormal() && isFiniteNonZero(); } + + /// Returns true if and only if the current value is zero, subnormal, or + /// normal. + /// + /// This means that the value is not infinite or NaN. + bool isFinite() const { return !isNaN() && !isInfinity(); } + + /// Returns true if and only if the float is plus or minus zero. + bool isZero() const { return category == fcZero; } + + /// IEEE-754R isSubnormal(): Returns true if and only if the float is a + /// denormal. + bool isDenormal() const; + + /// IEEE-754R isInfinite(): Returns true if and only if the float is infinity. + bool isInfinity() const { return category == fcInfinity; } + + /// Returns true if and only if the float is a quiet or signaling NaN. + bool isNaN() const { return category == fcNaN; } + + /// Returns true if and only if the float is a signaling NaN. + bool isSignaling() const; + + /// @} + + /// \name Simple Queries + /// @{ + + fltCategory getCategory() const { return category; } + const fltSemantics &getSemantics() const { return *semantics; } + bool isNonZero() const { return category != fcZero; } + bool isFiniteNonZero() const { return isFinite() && !isZero(); } + bool isPosZero() const { return isZero() && !isNegative(); } + bool isNegZero() const { return isZero() && isNegative(); } + + /// Returns true if and only if the number has the smallest possible non-zero + /// magnitude in the current semantics. + bool isSmallest() const; + + /// Returns true if and only if the number has the largest possible finite + /// magnitude in the current semantics. + bool isLargest() const; + + /// @} + + APFloat &operator=(const APFloat &); + + /// \brief Overload to compute a hash code for an APFloat value. + /// + /// Note that the use of hash codes for floating point values is in general + /// frought with peril. Equality is hard to define for these values. For + /// example, should negative and positive zero hash to different codes? Are + /// they equal or not? This hash value implementation specifically + /// emphasizes producing different codes for different inputs in order to + /// be used in canonicalization and memoization. As such, equality is + /// bitwiseIsEqual, and 0 != -0. + friend hash_code hash_value(const APFloat &Arg); + + /// Converts this value into a decimal string. + /// + /// \param FormatPrecision The maximum number of digits of + /// precision to output. If there are fewer digits available, + /// zero padding will not be used unless the value is + /// integral and small enough to be expressed in + /// FormatPrecision digits. 0 means to use the natural + /// precision of the number. + /// \param FormatMaxPadding The maximum number of zeros to + /// consider inserting before falling back to scientific + /// notation. 0 means to always use scientific notation. + /// + /// Number Precision MaxPadding Result + /// ------ --------- ---------- ------ + /// 1.01E+4 5 2 10100 + /// 1.01E+4 4 2 1.01E+4 + /// 1.01E+4 5 1 1.01E+4 + /// 1.01E-2 5 2 0.0101 + /// 1.01E-2 4 2 0.0101 + /// 1.01E-2 4 1 1.01E-2 + void toString(SmallVectorImpl &Str, unsigned FormatPrecision = 0, + unsigned FormatMaxPadding = 3) const; + + /// If this value has an exact multiplicative inverse, store it in inv and + /// return true. + bool getExactInverse(APFloat *inv) const; + +private: + + /// \name Simple Queries + /// @{ + + integerPart *significandParts(); + const integerPart *significandParts() const; + unsigned int partCount() const; + + /// @} + + /// \name Significand operations. + /// @{ + + integerPart addSignificand(const APFloat &); + integerPart subtractSignificand(const APFloat &, integerPart); + lostFraction addOrSubtractSignificand(const APFloat &, bool subtract); + lostFraction multiplySignificand(const APFloat &, const APFloat *); + lostFraction divideSignificand(const APFloat &); + void incrementSignificand(); + void initialize(const fltSemantics *); + void shiftSignificandLeft(unsigned int); + lostFraction shiftSignificandRight(unsigned int); + unsigned int significandLSB() const; + unsigned int significandMSB() const; + void zeroSignificand(); + /// Return true if the significand excluding the integral bit is all ones. + bool isSignificandAllOnes() const; + /// Return true if the significand excluding the integral bit is all zeros. + bool isSignificandAllZeros() const; + + /// @} + + /// \name Arithmetic on special values. + /// @{ + + opStatus addOrSubtractSpecials(const APFloat &, bool subtract); + opStatus divideSpecials(const APFloat &); + opStatus multiplySpecials(const APFloat &); + opStatus modSpecials(const APFloat &); + + /// @} + + /// \name Special value setters. + /// @{ + + void makeLargest(bool Neg = false); + void makeSmallest(bool Neg = false); + void makeNaN(bool SNaN = false, bool Neg = false, const APInt *fill = 0); + static APFloat makeNaN(const fltSemantics &Sem, bool SNaN, bool Negative, + const APInt *fill); + void makeInf(bool Neg = false); + void makeZero(bool Neg = false); + + /// @} + + /// \name Miscellany + /// @{ + + bool convertFromStringSpecials(StringRef str); + opStatus normalize(roundingMode, lostFraction); + opStatus addOrSubtract(const APFloat &, roundingMode, bool subtract); + cmpResult compareAbsoluteValue(const APFloat &) const; + opStatus handleOverflow(roundingMode); + bool roundAwayFromZero(roundingMode, lostFraction, unsigned int) const; + opStatus convertToSignExtendedInteger(integerPart *, unsigned int, bool, + roundingMode, bool *) const; + opStatus convertFromUnsignedParts(const integerPart *, unsigned int, + roundingMode); + opStatus convertFromHexadecimalString(StringRef, roundingMode); + opStatus convertFromDecimalString(StringRef, roundingMode); + char *convertNormalToHexString(char *, unsigned int, bool, + roundingMode) const; + opStatus roundSignificandWithExponent(const integerPart *, unsigned int, int, + roundingMode); + + /// @} + + APInt convertHalfAPFloatToAPInt() const; + APInt convertFloatAPFloatToAPInt() const; + APInt convertDoubleAPFloatToAPInt() const; + APInt convertQuadrupleAPFloatToAPInt() const; + APInt convertF80LongDoubleAPFloatToAPInt() const; + APInt convertPPCDoubleDoubleAPFloatToAPInt() const; + void initFromAPInt(const fltSemantics *Sem, const APInt &api); + void initFromHalfAPInt(const APInt &api); + void initFromFloatAPInt(const APInt &api); + void initFromDoubleAPInt(const APInt &api); + void initFromQuadrupleAPInt(const APInt &api); + void initFromF80LongDoubleAPInt(const APInt &api); + void initFromPPCDoubleDoubleAPInt(const APInt &api); + + void assign(const APFloat &); + void copySignificand(const APFloat &); + void freeSignificand(); + + /// The semantics that this value obeys. + const fltSemantics *semantics; + + /// A binary fraction with an explicit integer bit. + /// + /// The significand must be at least one bit wider than the target precision. + union Significand { + integerPart part; + integerPart *parts; + } significand; + + /// The signed unbiased exponent of the value. + ExponentType exponent; + + /// What kind of floating point number this is. + /// + /// Only 2 bits are required, but VisualStudio incorrectly sign extends it. + /// Using the extra bit keeps it from failing under VisualStudio. + fltCategory category : 3; + + /// Sign bit of the number. + unsigned int sign : 1; +}; + +/// See friend declaration above. +/// +/// This additional declaration is required in order to compile LLVM with IBM +/// xlC compiler. +hash_code hash_value(const APFloat &Arg); +} // namespace llvm + +#endif // LLVM_ADT_APFLOAT_H diff --git a/contrib/llvm/include/llvm/ADT/APInt.h b/contrib/llvm/include/llvm/ADT/APInt.h index 3d8b72d9a..d494ad253 100644 --- a/contrib/llvm/include/llvm/ADT/APInt.h +++ b/contrib/llvm/include/llvm/ADT/APInt.h @@ -6,10 +6,11 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// This file implements a class to represent arbitrary precision integral -// constant values and operations on them. -// +/// +/// \file +/// \brief This file implements a class to represent arbitrary precision +/// integral constant values and operations on them. +/// //===----------------------------------------------------------------------===// #ifndef LLVM_ADT_APINT_H @@ -24,30 +25,30 @@ #include namespace llvm { - class Deserializer; - class FoldingSetNodeID; - class Serializer; - class StringRef; - class hash_code; - class raw_ostream; +class Deserializer; +class FoldingSetNodeID; +class Serializer; +class StringRef; +class hash_code; +class raw_ostream; - template - class SmallVectorImpl; +template class SmallVectorImpl; - // An unsigned host type used as a single part of a multi-part - // bignum. - typedef uint64_t integerPart; +// An unsigned host type used as a single part of a multi-part +// bignum. +typedef uint64_t integerPart; - const unsigned int host_char_bit = 8; - const unsigned int integerPartWidth = host_char_bit * - static_cast(sizeof(integerPart)); +const unsigned int host_char_bit = 8; +const unsigned int integerPartWidth = + host_char_bit * static_cast(sizeof(integerPart)); //===----------------------------------------------------------------------===// // APInt Class //===----------------------------------------------------------------------===// -/// APInt - This class represents arbitrary precision constant integral values. -/// It is a functional replacement for common case unsigned integer type like +/// \brief Class for arbitrary precision integers. +/// +/// APInt is a functional replacement for common case unsigned integer type like /// "unsigned", "unsigned long" or "uint64_t", but also allows non-byte-width /// integer sizes and large integer value types such as 3-bits, 15-bits, or more /// than 64-bits of precision. APInt provides a variety of arithmetic operators @@ -71,65 +72,68 @@ namespace llvm { /// * In general, the class tries to follow the style of computation that LLVM /// uses in its IR. This simplifies its use for LLVM. /// -/// @brief Class for arbitrary precision integers. class APInt { - unsigned BitWidth; ///< The number of bits in this APInt. + unsigned BitWidth; ///< The number of bits in this APInt. /// This union is used to store the integer value. When the /// integer bit-width <= 64, it uses VAL, otherwise it uses pVal. union { - uint64_t VAL; ///< Used to store the <= 64 bits integer value. - uint64_t *pVal; ///< Used to store the >64 bits integer value. + uint64_t VAL; ///< Used to store the <= 64 bits integer value. + uint64_t *pVal; ///< Used to store the >64 bits integer value. }; /// This enum is used to hold the constants we needed for APInt. enum { /// Bits in a word - APINT_BITS_PER_WORD = static_cast(sizeof(uint64_t)) * - CHAR_BIT, + APINT_BITS_PER_WORD = + static_cast(sizeof(uint64_t)) * CHAR_BIT, /// Byte size of a word APINT_WORD_SIZE = static_cast(sizeof(uint64_t)) }; + /// \brief Fast internal constructor + /// /// This constructor is used only internally for speed of construction of /// temporaries. It is unsafe for general use so it is not public. - /// @brief Fast internal constructor - APInt(uint64_t* val, unsigned bits) : BitWidth(bits), pVal(val) { } + APInt(uint64_t *val, unsigned bits) : BitWidth(bits), pVal(val) {} - /// @returns true if the number of bits <= 64, false otherwise. - /// @brief Determine if this APInt just has one word to store value. - bool isSingleWord() const { - return BitWidth <= APINT_BITS_PER_WORD; - } + /// \brief Determine if this APInt just has one word to store value. + /// + /// \returns true if the number of bits <= 64, false otherwise. + bool isSingleWord() const { return BitWidth <= APINT_BITS_PER_WORD; } - /// @returns the word position for the specified bit position. - /// @brief Determine which word a bit is in. + /// \brief Determine which word a bit is in. + /// + /// \returns the word position for the specified bit position. static unsigned whichWord(unsigned bitPosition) { return bitPosition / APINT_BITS_PER_WORD; } - /// @returns the bit position in a word for the specified bit position + /// \brief Determine which bit in a word a bit is in. + /// + /// \returns the bit position in a word for the specified bit position /// in the APInt. - /// @brief Determine which bit in a word a bit is in. static unsigned whichBit(unsigned bitPosition) { return bitPosition % APINT_BITS_PER_WORD; } + /// \brief Get a single bit mask. + /// + /// \returns a uint64_t with only bit at "whichBit(bitPosition)" set /// This method generates and returns a uint64_t (word) mask for a single /// bit at a specific bit position. This is used to mask the bit in the /// corresponding word. - /// @returns a uint64_t with only bit at "whichBit(bitPosition)" set - /// @brief Get a single bit mask. static uint64_t maskBit(unsigned bitPosition) { return 1ULL << whichBit(bitPosition); } + /// \brief Clear unused high order bits + /// /// This method is used internally to clear the to "N" bits in the high order /// word that are not used by the APInt. This is needed after the most /// significant word is assigned a value to ensure that those bits are /// zero'd out. - /// @brief Clear unused high order bits - APInt& clearUnusedBits() { + APInt &clearUnusedBits() { // Compute how many bits are used in the final word unsigned wordBits = BitWidth % APINT_BITS_PER_WORD; if (wordBits == 0) @@ -147,12 +151,15 @@ class APInt { return *this; } - /// @returns the corresponding word for the specified bit position. - /// @brief Get the word corresponding to a bit position + /// \brief Get the word corresponding to a bit position + /// \returns the corresponding word for the specified bit position. uint64_t getWord(unsigned bitPosition) const { return isSingleWord() ? VAL : pVal[whichWord(bitPosition)]; } + /// \brief Convert a char array into an APInt + /// + /// \param radix 2, 8, 10, 16, or 36 /// Converts a string into a number. The string must be non-empty /// and well-formed as a number of the given base. The bit-width /// must be sufficient to hold the result. @@ -162,19 +169,16 @@ class APInt { /// StringRef::getAsInteger is superficially similar but (1) does /// not assume that the string is well-formed and (2) grows the /// result to hold the input. - /// - /// @param radix 2, 8, 10, 16, or 36 - /// @brief Convert a char array into an APInt void fromString(unsigned numBits, StringRef str, uint8_t radix); + /// \brief An internal division function for dividing APInts. + /// /// This is used by the toString method to divide by the radix. It simply /// provides a more convenient form of divide for internal use since KnuthDiv /// has specific constraints on its inputs. If those constraints are not met /// then it provides a simpler form of divide. - /// @brief An internal division function for dividing APInts. - static void divide(const APInt LHS, unsigned lhsWords, - const APInt &RHS, unsigned rhsWords, - APInt *Quotient, APInt *Remainder); + static void divide(const APInt LHS, unsigned lhsWords, const APInt &RHS, + unsigned rhsWords, APInt *Quotient, APInt *Remainder); /// out-of-line slow case for inline constructor void initSlowCase(unsigned numBits, uint64_t val, bool isSigned); @@ -183,25 +187,25 @@ class APInt { void initFromArray(ArrayRef array); /// out-of-line slow case for inline copy constructor - void initSlowCase(const APInt& that); + void initSlowCase(const APInt &that); /// out-of-line slow case for shl APInt shlSlowCase(unsigned shiftAmt) const; /// out-of-line slow case for operator& - APInt AndSlowCase(const APInt& RHS) const; + APInt AndSlowCase(const APInt &RHS) const; /// out-of-line slow case for operator| - APInt OrSlowCase(const APInt& RHS) const; + APInt OrSlowCase(const APInt &RHS) const; /// out-of-line slow case for operator^ - APInt XorSlowCase(const APInt& RHS) const; + APInt XorSlowCase(const APInt &RHS) const; /// out-of-line slow case for operator= - APInt& AssignSlowCase(const APInt& RHS); + APInt &AssignSlowCase(const APInt &RHS); /// out-of-line slow case for operator== - bool EqualSlowCase(const APInt& RHS) const; + bool EqualSlowCase(const APInt &RHS) const; /// out-of-line slow case for operator== bool EqualSlowCase(uint64_t Val) const; @@ -216,18 +220,21 @@ class APInt { unsigned countPopulationSlowCase() const; public: - /// @name Constructors + /// \name Constructors /// @{ + + /// \brief Create a new APInt of numBits width, initialized as val. + /// /// If isSigned is true then val is treated as if it were a signed value /// (i.e. as an int64_t) and the appropriate sign extension to the bit width /// will be done. Otherwise, no sign extension occurs (high order bits beyond /// the range of val are zero filled). - /// @param numBits the bit width of the constructed APInt - /// @param val the initial value of the APInt - /// @param isSigned how to treat signedness of val - /// @brief Create a new APInt of numBits width, initialized as val. + /// + /// \param numBits the bit width of the constructed APInt + /// \param val the initial value of the APInt + /// \param isSigned how to treat signedness of val APInt(unsigned numBits, uint64_t val, bool isSigned = false) - : BitWidth(numBits), VAL(0) { + : BitWidth(numBits), VAL(0) { assert(BitWidth && "bitwidth too small"); if (isSingleWord()) VAL = val; @@ -236,12 +243,15 @@ public: clearUnusedBits(); } + /// \brief Construct an APInt of numBits width, initialized as bigVal[]. + /// /// Note that bigVal.size() can be smaller or larger than the corresponding /// bit width but any extraneous bits will be dropped. - /// @param numBits the bit width of the constructed APInt - /// @param bigVal a sequence of words to form the initial value of the APInt - /// @brief Construct an APInt of numBits width, initialized as bigVal[]. + /// + /// \param numBits the bit width of the constructed APInt + /// \param bigVal a sequence of words to form the initial value of the APInt APInt(unsigned numBits, ArrayRef bigVal); + /// Equivalent to APInt(numBits, ArrayRef(bigVal, numWords)), but /// deprecated because this constructor is prone to ambiguity with the /// APInt(unsigned, uint64_t, bool) constructor. @@ -251,22 +261,22 @@ public: /// constructor. APInt(unsigned numBits, unsigned numWords, const uint64_t bigVal[]); + /// \brief Construct an APInt from a string representation. + /// /// This constructor interprets the string \p str in the given radix. The /// interpretation stops when the first character that is not suitable for the /// radix is encountered, or the end of the string. Acceptable radix values - /// are 2, 8, 10, 16, and 36. It is an error for the value implied by the + /// are 2, 8, 10, 16, and 36. It is an error for the value implied by the /// string to require more bits than numBits. /// - /// @param numBits the bit width of the constructed APInt - /// @param str the string to be interpreted - /// @param radix the radix to use for the conversion - /// @brief Construct an APInt from a string representation. + /// \param numBits the bit width of the constructed APInt + /// \param str the string to be interpreted + /// \param radix the radix to use for the conversion APInt(unsigned numBits, StringRef str, uint8_t radix); /// Simply makes *this a copy of that. /// @brief Copy Constructor. - APInt(const APInt& that) - : BitWidth(that.BitWidth), VAL(0) { + APInt(const APInt &that) : BitWidth(that.BitWidth), VAL(0) { assert(BitWidth && "bitwidth too small"); if (isSingleWord()) VAL = that.VAL; @@ -275,207 +285,228 @@ public: } #if LLVM_HAS_RVALUE_REFERENCES - /// @brief Move Constructor. - APInt(APInt&& that) : BitWidth(that.BitWidth), VAL(that.VAL) { + /// \brief Move Constructor. + APInt(APInt &&that) : BitWidth(that.BitWidth), VAL(that.VAL) { that.BitWidth = 0; } #endif - /// @brief Destructor. + /// \brief Destructor. ~APInt() { - if (!isSingleWord()) - delete [] pVal; + if (needsCleanup()) + delete[] pVal; } - /// Default constructor that creates an uninitialized APInt. This is useful - /// for object deserialization (pair this with the static method Read). + /// \brief Default constructor that creates an uninitialized APInt. + /// + /// This is useful for object deserialization (pair this with the static + /// method Read). explicit APInt() : BitWidth(1) {} - /// Profile - Used to insert APInt objects, or objects that contain APInt - /// objects, into FoldingSets. - void Profile(FoldingSetNodeID& id) const; + /// \brief Returns whether this instance allocated memory. + bool needsCleanup() const { return !isSingleWord(); } + + /// Used to insert APInt objects, or objects that contain APInt objects, into + /// FoldingSets. + void Profile(FoldingSetNodeID &id) const; /// @} - /// @name Value Tests + /// \name Value Tests /// @{ + + /// \brief Determine sign of this APInt. + /// /// This tests the high bit of this APInt to determine if it is set. - /// @returns true if this APInt is negative, false otherwise - /// @brief Determine sign of this APInt. - bool isNegative() const { - return (*this)[BitWidth - 1]; - } + /// + /// \returns true if this APInt is negative, false otherwise + bool isNegative() const { return (*this)[BitWidth - 1]; } + /// \brief Determine if this APInt Value is non-negative (>= 0) + /// /// This tests the high bit of the APInt to determine if it is unset. - /// @brief Determine if this APInt Value is non-negative (>= 0) - bool isNonNegative() const { - return !isNegative(); - } + bool isNonNegative() const { return !isNegative(); } + /// \brief Determine if this APInt Value is positive. + /// /// This tests if the value of this APInt is positive (> 0). Note /// that 0 is not a positive value. - /// @returns true if this APInt is positive. - /// @brief Determine if this APInt Value is positive. - bool isStrictlyPositive() const { - return isNonNegative() && !!*this; - } + /// + /// \returns true if this APInt is positive. + bool isStrictlyPositive() const { return isNonNegative() && !!*this; } + /// \brief Determine if all bits are set + /// /// This checks to see if the value has all bits of the APInt are set or not. - /// @brief Determine if all bits are set bool isAllOnesValue() const { - return countPopulation() == BitWidth; + if (isSingleWord()) + return VAL == ~integerPart(0) >> (APINT_BITS_PER_WORD - BitWidth); + return countPopulationSlowCase() == BitWidth; } + /// \brief Determine if this is the largest unsigned value. + /// /// This checks to see if the value of this APInt is the maximum unsigned /// value for the APInt's bit width. - /// @brief Determine if this is the largest unsigned value. - bool isMaxValue() const { - return countPopulation() == BitWidth; - } + bool isMaxValue() const { return isAllOnesValue(); } + /// \brief Determine if this is the largest signed value. + /// /// This checks to see if the value of this APInt is the maximum signed /// value for the APInt's bit width. - /// @brief Determine if this is the largest signed value. bool isMaxSignedValue() const { - return BitWidth == 1 ? VAL == 0 : - !isNegative() && countPopulation() == BitWidth - 1; + return BitWidth == 1 ? VAL == 0 + : !isNegative() && countPopulation() == BitWidth - 1; } + /// \brief Determine if this is the smallest unsigned value. + /// /// This checks to see if the value of this APInt is the minimum unsigned /// value for the APInt's bit width. - /// @brief Determine if this is the smallest unsigned value. - bool isMinValue() const { - return !*this; - } + bool isMinValue() const { return !*this; } + /// \brief Determine if this is the smallest signed value. + /// /// This checks to see if the value of this APInt is the minimum signed /// value for the APInt's bit width. - /// @brief Determine if this is the smallest signed value. bool isMinSignedValue() const { return BitWidth == 1 ? VAL == 1 : isNegative() && isPowerOf2(); } - /// @brief Check if this APInt has an N-bits unsigned integer value. + /// \brief Check if this APInt has an N-bits unsigned integer value. bool isIntN(unsigned N) const { assert(N && "N == 0 ???"); return getActiveBits() <= N; } - /// @brief Check if this APInt has an N-bits signed integer value. + /// \brief Check if this APInt has an N-bits signed integer value. bool isSignedIntN(unsigned N) const { assert(N && "N == 0 ???"); return getMinSignedBits() <= N; } - /// @returns true if the argument APInt value is a power of two > 0. + /// \brief Check if this APInt's value is a power of two greater than zero. + /// + /// \returns true if the argument APInt value is a power of two > 0. bool isPowerOf2() const { if (isSingleWord()) return isPowerOf2_64(VAL); return countPopulationSlowCase() == 1; } - /// isSignBit - Return true if this is the value returned by getSignBit. + /// \brief Check if the APInt's value is returned by getSignBit. + /// + /// \returns true if this is the value returned by getSignBit. bool isSignBit() const { return isMinSignedValue(); } + /// \brief Convert APInt to a boolean value. + /// /// This converts the APInt to a boolean value as a test against zero. - /// @brief Boolean conversion function. - bool getBoolValue() const { - return !!*this; - } + bool getBoolValue() const { return !!*this; } - /// getLimitedValue - If this value is smaller than the specified limit, - /// return it, otherwise return the limit value. This causes the value - /// to saturate to the limit. + /// If this value is smaller than the specified limit, return it, otherwise + /// return the limit value. This causes the value to saturate to the limit. uint64_t getLimitedValue(uint64_t Limit = ~0ULL) const { - return (getActiveBits() > 64 || getZExtValue() > Limit) ? - Limit : getZExtValue(); + return (getActiveBits() > 64 || getZExtValue() > Limit) ? Limit + : getZExtValue(); } /// @} - /// @name Value Generators + /// \name Value Generators /// @{ - /// @brief Gets maximum unsigned value of APInt for specific bit width. + + /// \brief Gets maximum unsigned value of APInt for specific bit width. static APInt getMaxValue(unsigned numBits) { return getAllOnesValue(numBits); } - /// @brief Gets maximum signed value of APInt for a specific bit width. + /// \brief Gets maximum signed value of APInt for a specific bit width. static APInt getSignedMaxValue(unsigned numBits) { APInt API = getAllOnesValue(numBits); API.clearBit(numBits - 1); return API; } - /// @brief Gets minimum unsigned value of APInt for a specific bit width. - static APInt getMinValue(unsigned numBits) { - return APInt(numBits, 0); - } + /// \brief Gets minimum unsigned value of APInt for a specific bit width. + static APInt getMinValue(unsigned numBits) { return APInt(numBits, 0); } - /// @brief Gets minimum signed value of APInt for a specific bit width. + /// \brief Gets minimum signed value of APInt for a specific bit width. static APInt getSignedMinValue(unsigned numBits) { APInt API(numBits, 0); API.setBit(numBits - 1); return API; } - /// getSignBit - This is just a wrapper function of getSignedMinValue(), and - /// it helps code readability when we want to get a SignBit. - /// @brief Get the SignBit for a specific bit width. + /// \brief Get the SignBit for a specific bit width. + /// + /// This is just a wrapper function of getSignedMinValue(), and it helps code + /// readability when we want to get a SignBit. static APInt getSignBit(unsigned BitWidth) { return getSignedMinValue(BitWidth); } - /// @returns the all-ones value for an APInt of the specified bit-width. - /// @brief Get the all-ones value. + /// \brief Get the all-ones value. + /// + /// \returns the all-ones value for an APInt of the specified bit-width. static APInt getAllOnesValue(unsigned numBits) { return APInt(numBits, UINT64_MAX, true); } - /// @returns the '0' value for an APInt of the specified bit-width. - /// @brief Get the '0' value. - static APInt getNullValue(unsigned numBits) { - return APInt(numBits, 0); - } + /// \brief Get the '0' value. + /// + /// \returns the '0' value for an APInt of the specified bit-width. + static APInt getNullValue(unsigned numBits) { return APInt(numBits, 0); } + /// \brief Compute an APInt containing numBits highbits from this APInt. + /// /// Get an APInt with the same BitWidth as this APInt, just zero mask /// the low bits and right shift to the least significant bit. - /// @returns the high "numBits" bits of this APInt. + /// + /// \returns the high "numBits" bits of this APInt. APInt getHiBits(unsigned numBits) const; + /// \brief Compute an APInt containing numBits lowbits from this APInt. + /// /// Get an APInt with the same BitWidth as this APInt, just zero mask /// the high bits. - /// @returns the low "numBits" bits of this APInt. + /// + /// \returns the low "numBits" bits of this APInt. APInt getLoBits(unsigned numBits) const; - /// getOneBitSet - Return an APInt with exactly one bit set in the result. + /// \brief Return an APInt with exactly one bit set in the result. static APInt getOneBitSet(unsigned numBits, unsigned BitNo) { APInt Res(numBits, 0); Res.setBit(BitNo); return Res; } - + + /// \brief Get a value with a block of bits set. + /// /// Constructs an APInt value that has a contiguous range of bits set. The /// bits from loBit (inclusive) to hiBit (exclusive) will be set. All other /// bits will be zero. For example, with parameters(32, 0, 16) you would get /// 0x0000FFFF. If hiBit is less than loBit then the set bits "wrap". For /// example, with parameters (32, 28, 4), you would get 0xF000000F. - /// @param numBits the intended bit width of the result - /// @param loBit the index of the lowest bit set. - /// @param hiBit the index of the highest bit set. - /// @returns An APInt value with the requested bits set. - /// @brief Get a value with a block of bits set. + /// + /// \param numBits the intended bit width of the result + /// \param loBit the index of the lowest bit set. + /// \param hiBit the index of the highest bit set. + /// + /// \returns An APInt value with the requested bits set. static APInt getBitsSet(unsigned numBits, unsigned loBit, unsigned hiBit) { assert(hiBit <= numBits && "hiBit out of range"); assert(loBit < numBits && "loBit out of range"); if (hiBit < loBit) return getLowBitsSet(numBits, hiBit) | - getHighBitsSet(numBits, numBits-loBit); - return getLowBitsSet(numBits, hiBit-loBit).shl(loBit); + getHighBitsSet(numBits, numBits - loBit); + return getLowBitsSet(numBits, hiBit - loBit).shl(loBit); } + /// \brief Get a value with high bits set + /// /// Constructs an APInt value that has the top hiBitsSet bits set. - /// @param numBits the bitwidth of the result - /// @param hiBitsSet the number of high-order bits set in the result. - /// @brief Get a value with high bits set + /// + /// \param numBits the bitwidth of the result + /// \param hiBitsSet the number of high-order bits set in the result. static APInt getHighBitsSet(unsigned numBits, unsigned hiBitsSet) { assert(hiBitsSet <= numBits && "Too many bits to set!"); // Handle a degenerate case, to avoid shifting by word size @@ -488,10 +519,12 @@ public: return getAllOnesValue(numBits).shl(shiftAmt); } + /// \brief Get a value with low bits set + /// /// Constructs an APInt value that has the bottom loBitsSet bits set. - /// @param numBits the bitwidth of the result - /// @param loBitsSet the number of low-order bits set in the result. - /// @brief Get a value with low bits set + /// + /// \param numBits the bitwidth of the result + /// \param loBitsSet the number of low-order bits set in the result. static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet) { assert(loBitsSet <= numBits && "Too many bits to set!"); // Handle a degenerate case, to avoid shifting by word size @@ -527,65 +560,74 @@ public: return I1.zext(I2.getBitWidth()) == I2; } - + /// \brief Overload to compute a hash_code for an APInt value. friend hash_code hash_value(const APInt &Arg); /// This function returns a pointer to the internal storage of the APInt. /// This is useful for writing out the APInt in binary form without any /// conversions. - const uint64_t* getRawData() const { + const uint64_t *getRawData() const { if (isSingleWord()) return &VAL; return &pVal[0]; } /// @} - /// @name Unary Operators + /// \name Unary Operators /// @{ - /// @returns a new APInt value representing *this incremented by one - /// @brief Postfix increment operator. + + /// \brief Postfix increment operator. + /// + /// \returns a new APInt value representing *this incremented by one const APInt operator++(int) { APInt API(*this); ++(*this); return API; } - /// @returns *this incremented by one - /// @brief Prefix increment operator. - APInt& operator++(); + /// \brief Prefix increment operator. + /// + /// \returns *this incremented by one + APInt &operator++(); - /// @returns a new APInt representing *this decremented by one. - /// @brief Postfix decrement operator. + /// \brief Postfix decrement operator. + /// + /// \returns a new APInt representing *this decremented by one. const APInt operator--(int) { APInt API(*this); --(*this); return API; } - /// @returns *this decremented by one. - /// @brief Prefix decrement operator. - APInt& operator--(); + /// \brief Prefix decrement operator. + /// + /// \returns *this decremented by one. + APInt &operator--(); + /// \brief Unary bitwise complement operator. + /// /// Performs a bitwise complement operation on this APInt. - /// @returns an APInt that is the bitwise complement of *this - /// @brief Unary bitwise complement operator. + /// + /// \returns an APInt that is the bitwise complement of *this APInt operator~() const { APInt Result(*this); Result.flipAllBits(); return Result; } + /// \brief Unary negation operator + /// /// Negates *this using two's complement logic. - /// @returns An APInt value representing the negation of *this. - /// @brief Unary negation operator - APInt operator-() const { - return APInt(BitWidth, 0) - (*this); - } + /// + /// \returns An APInt value representing the negation of *this. + APInt operator-() const { return APInt(BitWidth, 0) - (*this); } + /// \brief Logical negation operator. + /// /// Performs logical negation operation on this APInt. - /// @returns true if *this is zero, false otherwise. - /// @brief Logical negation operator. + /// + /// \returns true if *this is zero, false otherwise. bool operator!() const { if (isSingleWord()) return !VAL; @@ -597,11 +639,13 @@ public: } /// @} - /// @name Assignment Operators + /// \name Assignment Operators /// @{ - /// @returns *this after assignment of RHS. - /// @brief Copy assignment operator. - APInt& operator=(const APInt& RHS) { + + /// \brief Copy assignment operator. + /// + /// \returns *this after assignment of RHS. + APInt &operator=(const APInt &RHS) { // If the bitwidths are the same, we can avoid mucking with memory if (isSingleWord() && RHS.isSingleWord()) { VAL = RHS.VAL; @@ -614,9 +658,9 @@ public: #if LLVM_HAS_RVALUE_REFERENCES /// @brief Move assignment operator. - APInt& operator=(APInt&& that) { + APInt &operator=(APInt &&that) { if (!isSingleWord()) - delete [] pVal; + delete[] pVal; BitWidth = that.BitWidth; VAL = that.VAL; @@ -627,31 +671,37 @@ public: } #endif + /// \brief Assignment operator. + /// /// The RHS value is assigned to *this. If the significant bits in RHS exceed /// the bit width, the excess bits are truncated. If the bit width is larger /// than 64, the value is zero filled in the unspecified high order bits. - /// @returns *this after assignment of RHS value. - /// @brief Assignment operator. - APInt& operator=(uint64_t RHS); + /// + /// \returns *this after assignment of RHS value. + APInt &operator=(uint64_t RHS); + /// \brief Bitwise AND assignment operator. + /// /// Performs a bitwise AND operation on this APInt and RHS. The result is /// assigned to *this. - /// @returns *this after ANDing with RHS. - /// @brief Bitwise AND assignment operator. - APInt& operator&=(const APInt& RHS); + /// + /// \returns *this after ANDing with RHS. + APInt &operator&=(const APInt &RHS); + /// \brief Bitwise OR assignment operator. + /// /// Performs a bitwise OR operation on this APInt and RHS. The result is /// assigned *this; - /// @returns *this after ORing with RHS. - /// @brief Bitwise OR assignment operator. - APInt& operator|=(const APInt& RHS); + /// + /// \returns *this after ORing with RHS. + APInt &operator|=(const APInt &RHS); + /// \brief Bitwise OR assignment operator. + /// /// Performs a bitwise OR operation on this APInt and RHS. RHS is /// logically zero-extended or truncated to match the bit-width of /// the LHS. - /// - /// @brief Bitwise OR assignment operator. - APInt& operator|=(uint64_t RHS) { + APInt &operator|=(uint64_t RHS) { if (isSingleWord()) { VAL |= RHS; clearUnusedBits(); @@ -661,114 +711,149 @@ public: return *this; } + /// \brief Bitwise XOR assignment operator. + /// /// Performs a bitwise XOR operation on this APInt and RHS. The result is /// assigned to *this. - /// @returns *this after XORing with RHS. - /// @brief Bitwise XOR assignment operator. - APInt& operator^=(const APInt& RHS); + /// + /// \returns *this after XORing with RHS. + APInt &operator^=(const APInt &RHS); + /// \brief Multiplication assignment operator. + /// /// Multiplies this APInt by RHS and assigns the result to *this. - /// @returns *this - /// @brief Multiplication assignment operator. - APInt& operator*=(const APInt& RHS); + /// + /// \returns *this + APInt &operator*=(const APInt &RHS); + /// \brief Addition assignment operator. + /// /// Adds RHS to *this and assigns the result to *this. - /// @returns *this - /// @brief Addition assignment operator. - APInt& operator+=(const APInt& RHS); + /// + /// \returns *this + APInt &operator+=(const APInt &RHS); + /// \brief Subtraction assignment operator. + /// /// Subtracts RHS from *this and assigns the result to *this. - /// @returns *this - /// @brief Subtraction assignment operator. - APInt& operator-=(const APInt& RHS); + /// + /// \returns *this + APInt &operator-=(const APInt &RHS); + /// \brief Left-shift assignment function. + /// /// Shifts *this left by shiftAmt and assigns the result to *this. - /// @returns *this after shifting left by shiftAmt - /// @brief Left-shift assignment function. - APInt& operator<<=(unsigned shiftAmt) { + /// + /// \returns *this after shifting left by shiftAmt + APInt &operator<<=(unsigned shiftAmt) { *this = shl(shiftAmt); return *this; } /// @} - /// @name Binary Operators + /// \name Binary Operators /// @{ + + /// \brief Bitwise AND operator. + /// /// Performs a bitwise AND operation on *this and RHS. - /// @returns An APInt value representing the bitwise AND of *this and RHS. - /// @brief Bitwise AND operator. - APInt operator&(const APInt& RHS) const { + /// + /// \returns An APInt value representing the bitwise AND of *this and RHS. + APInt operator&(const APInt &RHS) const { assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); if (isSingleWord()) return APInt(getBitWidth(), VAL & RHS.VAL); return AndSlowCase(RHS); } - APInt And(const APInt& RHS) const { + APInt LLVM_ATTRIBUTE_UNUSED_RESULT And(const APInt &RHS) const { return this->operator&(RHS); } + /// \brief Bitwise OR operator. + /// /// Performs a bitwise OR operation on *this and RHS. - /// @returns An APInt value representing the bitwise OR of *this and RHS. - /// @brief Bitwise OR operator. - APInt operator|(const APInt& RHS) const { + /// + /// \returns An APInt value representing the bitwise OR of *this and RHS. + APInt operator|(const APInt &RHS) const { assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); if (isSingleWord()) return APInt(getBitWidth(), VAL | RHS.VAL); return OrSlowCase(RHS); } - APInt Or(const APInt& RHS) const { + + /// \brief Bitwise OR function. + /// + /// Performs a bitwise or on *this and RHS. This is implemented bny simply + /// calling operator|. + /// + /// \returns An APInt value representing the bitwise OR of *this and RHS. + APInt LLVM_ATTRIBUTE_UNUSED_RESULT Or(const APInt &RHS) const { return this->operator|(RHS); } + /// \brief Bitwise XOR operator. + /// /// Performs a bitwise XOR operation on *this and RHS. - /// @returns An APInt value representing the bitwise XOR of *this and RHS. - /// @brief Bitwise XOR operator. - APInt operator^(const APInt& RHS) const { + /// + /// \returns An APInt value representing the bitwise XOR of *this and RHS. + APInt operator^(const APInt &RHS) const { assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); if (isSingleWord()) return APInt(BitWidth, VAL ^ RHS.VAL); return XorSlowCase(RHS); } - APInt Xor(const APInt& RHS) const { + + /// \brief Bitwise XOR function. + /// + /// Performs a bitwise XOR operation on *this and RHS. This is implemented + /// through the usage of operator^. + /// + /// \returns An APInt value representing the bitwise XOR of *this and RHS. + APInt LLVM_ATTRIBUTE_UNUSED_RESULT Xor(const APInt &RHS) const { return this->operator^(RHS); } + /// \brief Multiplication operator. + /// /// Multiplies this APInt by RHS and returns the result. - /// @brief Multiplication operator. - APInt operator*(const APInt& RHS) const; + APInt operator*(const APInt &RHS) const; + /// \brief Addition operator. + /// /// Adds RHS to this APInt and returns the result. - /// @brief Addition operator. - APInt operator+(const APInt& RHS) const; - APInt operator+(uint64_t RHS) const { - return (*this) + APInt(BitWidth, RHS); - } + APInt operator+(const APInt &RHS) const; + APInt operator+(uint64_t RHS) const { return (*this) + APInt(BitWidth, RHS); } + /// \brief Subtraction operator. + /// /// Subtracts RHS from this APInt and returns the result. - /// @brief Subtraction operator. - APInt operator-(const APInt& RHS) const; - APInt operator-(uint64_t RHS) const { - return (*this) - APInt(BitWidth, RHS); - } + APInt operator-(const APInt &RHS) const; + APInt operator-(uint64_t RHS) const { return (*this) - APInt(BitWidth, RHS); } - APInt operator<<(unsigned Bits) const { - return shl(Bits); - } + /// \brief Left logical shift operator. + /// + /// Shifts this APInt left by \p Bits and returns the result. + APInt operator<<(unsigned Bits) const { return shl(Bits); } - APInt operator<<(const APInt &Bits) const { - return shl(Bits); - } + /// \brief Left logical shift operator. + /// + /// Shifts this APInt left by \p Bits and returns the result. + APInt operator<<(const APInt &Bits) const { return shl(Bits); } + /// \brief Arithmetic right-shift function. + /// /// Arithmetic right-shift this APInt by shiftAmt. - /// @brief Arithmetic right-shift function. - APInt ashr(unsigned shiftAmt) const; + APInt LLVM_ATTRIBUTE_UNUSED_RESULT ashr(unsigned shiftAmt) const; + /// \brief Logical right-shift function. + /// /// Logical right-shift this APInt by shiftAmt. - /// @brief Logical right-shift function. - APInt lshr(unsigned shiftAmt) const; + APInt LLVM_ATTRIBUTE_UNUSED_RESULT lshr(unsigned shiftAmt) const; + /// \brief Left-shift function. + /// /// Left-shift this APInt by shiftAmt. - /// @brief Left-shift function. - APInt shl(unsigned shiftAmt) const { + APInt LLVM_ATTRIBUTE_UNUSED_RESULT shl(unsigned shiftAmt) const { assert(shiftAmt <= BitWidth && "Invalid shift amount"); if (isSingleWord()) { if (shiftAmt >= BitWidth) @@ -778,65 +863,74 @@ public: return shlSlowCase(shiftAmt); } - /// @brief Rotate left by rotateAmt. - APInt rotl(unsigned rotateAmt) const; + /// \brief Rotate left by rotateAmt. + APInt LLVM_ATTRIBUTE_UNUSED_RESULT rotl(unsigned rotateAmt) const; - /// @brief Rotate right by rotateAmt. - APInt rotr(unsigned rotateAmt) const; + /// \brief Rotate right by rotateAmt. + APInt LLVM_ATTRIBUTE_UNUSED_RESULT rotr(unsigned rotateAmt) const; + /// \brief Arithmetic right-shift function. + /// /// Arithmetic right-shift this APInt by shiftAmt. - /// @brief Arithmetic right-shift function. - APInt ashr(const APInt &shiftAmt) const; + APInt LLVM_ATTRIBUTE_UNUSED_RESULT ashr(const APInt &shiftAmt) const; + /// \brief Logical right-shift function. + /// /// Logical right-shift this APInt by shiftAmt. - /// @brief Logical right-shift function. - APInt lshr(const APInt &shiftAmt) const; + APInt LLVM_ATTRIBUTE_UNUSED_RESULT lshr(const APInt &shiftAmt) const; + /// \brief Left-shift function. + /// /// Left-shift this APInt by shiftAmt. - /// @brief Left-shift function. - APInt shl(const APInt &shiftAmt) const; + APInt LLVM_ATTRIBUTE_UNUSED_RESULT shl(const APInt &shiftAmt) const; - /// @brief Rotate left by rotateAmt. - APInt rotl(const APInt &rotateAmt) const; + /// \brief Rotate left by rotateAmt. + APInt LLVM_ATTRIBUTE_UNUSED_RESULT rotl(const APInt &rotateAmt) const; - /// @brief Rotate right by rotateAmt. - APInt rotr(const APInt &rotateAmt) const; + /// \brief Rotate right by rotateAmt. + APInt LLVM_ATTRIBUTE_UNUSED_RESULT rotr(const APInt &rotateAmt) const; + /// \brief Unsigned division operation. + /// /// Perform an unsigned divide operation on this APInt by RHS. Both this and /// RHS are treated as unsigned quantities for purposes of this division. - /// @returns a new APInt value containing the division result - /// @brief Unsigned division operation. - APInt udiv(const APInt &RHS) const; + /// + /// \returns a new APInt value containing the division result + APInt LLVM_ATTRIBUTE_UNUSED_RESULT udiv(const APInt &RHS) const; + /// \brief Signed division function for APInt. + /// /// Signed divide this APInt by APInt RHS. - /// @brief Signed division function for APInt. - APInt sdiv(const APInt &RHS) const; + APInt LLVM_ATTRIBUTE_UNUSED_RESULT sdiv(const APInt &RHS) const; + /// \brief Unsigned remainder operation. + /// /// Perform an unsigned remainder operation on this APInt with RHS being the /// divisor. Both this and RHS are treated as unsigned quantities for purposes - /// of this operation. Note that this is a true remainder operation and not - /// a modulo operation because the sign follows the sign of the dividend - /// which is *this. - /// @returns a new APInt value containing the remainder result - /// @brief Unsigned remainder operation. - APInt urem(const APInt &RHS) const; + /// of this operation. Note that this is a true remainder operation and not a + /// modulo operation because the sign follows the sign of the dividend which + /// is *this. + /// + /// \returns a new APInt value containing the remainder result + APInt LLVM_ATTRIBUTE_UNUSED_RESULT urem(const APInt &RHS) const; + /// \brief Function for signed remainder operation. + /// /// Signed remainder operation on APInt. - /// @brief Function for signed remainder operation. - APInt srem(const APInt &RHS) const; + APInt LLVM_ATTRIBUTE_UNUSED_RESULT srem(const APInt &RHS) const; + /// \brief Dual division/remainder interface. + /// /// Sometimes it is convenient to divide two APInt values and obtain both the /// quotient and remainder. This function does both operations in the same /// computation making it a little more efficient. The pair of input arguments /// may overlap with the pair of output arguments. It is safe to call /// udivrem(X, Y, X, Y), for example. - /// @brief Dual division/remainder interface. - static void udivrem(const APInt &LHS, const APInt &RHS, - APInt &Quotient, APInt &Remainder); - - static void sdivrem(const APInt &LHS, const APInt &RHS, - APInt &Quotient, APInt &Remainder); + static void udivrem(const APInt &LHS, const APInt &RHS, APInt &Quotient, + APInt &Remainder); + static void sdivrem(const APInt &LHS, const APInt &RHS, APInt &Quotient, + APInt &Remainder); // Operations that return overflow indicators. APInt sadd_ov(const APInt &RHS, bool &Overflow) const; @@ -848,247 +942,261 @@ public: APInt umul_ov(const APInt &RHS, bool &Overflow) const; APInt sshl_ov(unsigned Amt, bool &Overflow) const; - /// @returns the bit value at bitPosition - /// @brief Array-indexing support. + /// \brief Array-indexing support. + /// + /// \returns the bit value at bitPosition bool operator[](unsigned bitPosition) const { assert(bitPosition < getBitWidth() && "Bit position out of bounds!"); return (maskBit(bitPosition) & - (isSingleWord() ? VAL : pVal[whichWord(bitPosition)])) != 0; + (isSingleWord() ? VAL : pVal[whichWord(bitPosition)])) != + 0; } /// @} - /// @name Comparison Operators + /// \name Comparison Operators /// @{ + + /// \brief Equality operator. + /// /// Compares this APInt with RHS for the validity of the equality /// relationship. - /// @brief Equality operator. - bool operator==(const APInt& RHS) const { + bool operator==(const APInt &RHS) const { assert(BitWidth == RHS.BitWidth && "Comparison requires equal bit widths"); if (isSingleWord()) return VAL == RHS.VAL; return EqualSlowCase(RHS); } + /// \brief Equality operator. + /// /// Compares this APInt with a uint64_t for the validity of the equality /// relationship. - /// @returns true if *this == Val - /// @brief Equality operator. + /// + /// \returns true if *this == Val bool operator==(uint64_t Val) const { if (isSingleWord()) return VAL == Val; return EqualSlowCase(Val); } + /// \brief Equality comparison. + /// /// Compares this APInt with RHS for the validity of the equality /// relationship. - /// @returns true if *this == Val - /// @brief Equality comparison. - bool eq(const APInt &RHS) const { - return (*this) == RHS; - } + /// + /// \returns true if *this == Val + bool eq(const APInt &RHS) const { return (*this) == RHS; } + /// \brief Inequality operator. + /// /// Compares this APInt with RHS for the validity of the inequality /// relationship. - /// @returns true if *this != Val - /// @brief Inequality operator. - bool operator!=(const APInt& RHS) const { - return !((*this) == RHS); - } + /// + /// \returns true if *this != Val + bool operator!=(const APInt &RHS) const { return !((*this) == RHS); } + /// \brief Inequality operator. + /// /// Compares this APInt with a uint64_t for the validity of the inequality /// relationship. - /// @returns true if *this != Val - /// @brief Inequality operator. - bool operator!=(uint64_t Val) const { - return !((*this) == Val); - } + /// + /// \returns true if *this != Val + bool operator!=(uint64_t Val) const { return !((*this) == Val); } + /// \brief Inequality comparison + /// /// Compares this APInt with RHS for the validity of the inequality /// relationship. - /// @returns true if *this != Val - /// @brief Inequality comparison - bool ne(const APInt &RHS) const { - return !((*this) == RHS); - } + /// + /// \returns true if *this != Val + bool ne(const APInt &RHS) const { return !((*this) == RHS); } + /// \brief Unsigned less than comparison + /// /// Regards both *this and RHS as unsigned quantities and compares them for /// the validity of the less-than relationship. - /// @returns true if *this < RHS when both are considered unsigned. - /// @brief Unsigned less than comparison + /// + /// \returns true if *this < RHS when both are considered unsigned. bool ult(const APInt &RHS) const; + /// \brief Unsigned less than comparison + /// /// Regards both *this as an unsigned quantity and compares it with RHS for /// the validity of the less-than relationship. - /// @returns true if *this < RHS when considered unsigned. - /// @brief Unsigned less than comparison - bool ult(uint64_t RHS) const { - return ult(APInt(getBitWidth(), RHS)); - } + /// + /// \returns true if *this < RHS when considered unsigned. + bool ult(uint64_t RHS) const { return ult(APInt(getBitWidth(), RHS)); } + /// \brief Signed less than comparison + /// /// Regards both *this and RHS as signed quantities and compares them for /// validity of the less-than relationship. - /// @returns true if *this < RHS when both are considered signed. - /// @brief Signed less than comparison - bool slt(const APInt& RHS) const; + /// + /// \returns true if *this < RHS when both are considered signed. + bool slt(const APInt &RHS) const; + /// \brief Signed less than comparison + /// /// Regards both *this as a signed quantity and compares it with RHS for /// the validity of the less-than relationship. - /// @returns true if *this < RHS when considered signed. - /// @brief Signed less than comparison - bool slt(uint64_t RHS) const { - return slt(APInt(getBitWidth(), RHS)); - } + /// + /// \returns true if *this < RHS when considered signed. + bool slt(uint64_t RHS) const { return slt(APInt(getBitWidth(), RHS)); } + /// \brief Unsigned less or equal comparison + /// /// Regards both *this and RHS as unsigned quantities and compares them for /// validity of the less-or-equal relationship. - /// @returns true if *this <= RHS when both are considered unsigned. - /// @brief Unsigned less or equal comparison - bool ule(const APInt& RHS) const { - return ult(RHS) || eq(RHS); - } + /// + /// \returns true if *this <= RHS when both are considered unsigned. + bool ule(const APInt &RHS) const { return ult(RHS) || eq(RHS); } + /// \brief Unsigned less or equal comparison + /// /// Regards both *this as an unsigned quantity and compares it with RHS for /// the validity of the less-or-equal relationship. - /// @returns true if *this <= RHS when considered unsigned. - /// @brief Unsigned less or equal comparison - bool ule(uint64_t RHS) const { - return ule(APInt(getBitWidth(), RHS)); - } + /// + /// \returns true if *this <= RHS when considered unsigned. + bool ule(uint64_t RHS) const { return ule(APInt(getBitWidth(), RHS)); } + /// \brief Signed less or equal comparison + /// /// Regards both *this and RHS as signed quantities and compares them for /// validity of the less-or-equal relationship. - /// @returns true if *this <= RHS when both are considered signed. - /// @brief Signed less or equal comparison - bool sle(const APInt& RHS) const { - return slt(RHS) || eq(RHS); - } + /// + /// \returns true if *this <= RHS when both are considered signed. + bool sle(const APInt &RHS) const { return slt(RHS) || eq(RHS); } - /// Regards both *this as a signed quantity and compares it with RHS for - /// the validity of the less-or-equal relationship. - /// @returns true if *this <= RHS when considered signed. - /// @brief Signed less or equal comparison - bool sle(uint64_t RHS) const { - return sle(APInt(getBitWidth(), RHS)); - } + /// \brief Signed less or equal comparison + /// + /// Regards both *this as a signed quantity and compares it with RHS for the + /// validity of the less-or-equal relationship. + /// + /// \returns true if *this <= RHS when considered signed. + bool sle(uint64_t RHS) const { return sle(APInt(getBitWidth(), RHS)); } + /// \brief Unsigned greather than comparison + /// /// Regards both *this and RHS as unsigned quantities and compares them for /// the validity of the greater-than relationship. - /// @returns true if *this > RHS when both are considered unsigned. - /// @brief Unsigned greather than comparison - bool ugt(const APInt& RHS) const { - return !ult(RHS) && !eq(RHS); - } + /// + /// \returns true if *this > RHS when both are considered unsigned. + bool ugt(const APInt &RHS) const { return !ult(RHS) && !eq(RHS); } + /// \brief Unsigned greater than comparison + /// /// Regards both *this as an unsigned quantity and compares it with RHS for /// the validity of the greater-than relationship. - /// @returns true if *this > RHS when considered unsigned. - /// @brief Unsigned greater than comparison - bool ugt(uint64_t RHS) const { - return ugt(APInt(getBitWidth(), RHS)); - } + /// + /// \returns true if *this > RHS when considered unsigned. + bool ugt(uint64_t RHS) const { return ugt(APInt(getBitWidth(), RHS)); } - /// Regards both *this and RHS as signed quantities and compares them for - /// the validity of the greater-than relationship. - /// @returns true if *this > RHS when both are considered signed. - /// @brief Signed greather than comparison - bool sgt(const APInt& RHS) const { - return !slt(RHS) && !eq(RHS); - } + /// \brief Signed greather than comparison + /// + /// Regards both *this and RHS as signed quantities and compares them for the + /// validity of the greater-than relationship. + /// + /// \returns true if *this > RHS when both are considered signed. + bool sgt(const APInt &RHS) const { return !slt(RHS) && !eq(RHS); } + /// \brief Signed greater than comparison + /// /// Regards both *this as a signed quantity and compares it with RHS for /// the validity of the greater-than relationship. - /// @returns true if *this > RHS when considered signed. - /// @brief Signed greater than comparison - bool sgt(uint64_t RHS) const { - return sgt(APInt(getBitWidth(), RHS)); - } + /// + /// \returns true if *this > RHS when considered signed. + bool sgt(uint64_t RHS) const { return sgt(APInt(getBitWidth(), RHS)); } + /// \brief Unsigned greater or equal comparison + /// /// Regards both *this and RHS as unsigned quantities and compares them for /// validity of the greater-or-equal relationship. - /// @returns true if *this >= RHS when both are considered unsigned. - /// @brief Unsigned greater or equal comparison - bool uge(const APInt& RHS) const { - return !ult(RHS); - } + /// + /// \returns true if *this >= RHS when both are considered unsigned. + bool uge(const APInt &RHS) const { return !ult(RHS); } + /// \brief Unsigned greater or equal comparison + /// /// Regards both *this as an unsigned quantity and compares it with RHS for /// the validity of the greater-or-equal relationship. - /// @returns true if *this >= RHS when considered unsigned. - /// @brief Unsigned greater or equal comparison - bool uge(uint64_t RHS) const { - return uge(APInt(getBitWidth(), RHS)); - } + /// + /// \returns true if *this >= RHS when considered unsigned. + bool uge(uint64_t RHS) const { return uge(APInt(getBitWidth(), RHS)); } + /// \brief Signed greather or equal comparison + /// /// Regards both *this and RHS as signed quantities and compares them for /// validity of the greater-or-equal relationship. - /// @returns true if *this >= RHS when both are considered signed. - /// @brief Signed greather or equal comparison - bool sge(const APInt& RHS) const { - return !slt(RHS); - } + /// + /// \returns true if *this >= RHS when both are considered signed. + bool sge(const APInt &RHS) const { return !slt(RHS); } + /// \brief Signed greater or equal comparison + /// /// Regards both *this as a signed quantity and compares it with RHS for /// the validity of the greater-or-equal relationship. - /// @returns true if *this >= RHS when considered signed. - /// @brief Signed greater or equal comparison - bool sge(uint64_t RHS) const { - return sge(APInt(getBitWidth(), RHS)); - } + /// + /// \returns true if *this >= RHS when considered signed. + bool sge(uint64_t RHS) const { return sge(APInt(getBitWidth(), RHS)); } - - - /// This operation tests if there are any pairs of corresponding bits /// between this APInt and RHS that are both set. - bool intersects(const APInt &RHS) const { - return (*this & RHS) != 0; - } + bool intersects(const APInt &RHS) const { return (*this & RHS) != 0; } /// @} - /// @name Resizing Operators + /// \name Resizing Operators /// @{ + + /// \brief Truncate to new width. + /// /// Truncate the APInt to a specified width. It is an error to specify a width /// that is greater than or equal to the current width. - /// @brief Truncate to new width. - APInt trunc(unsigned width) const; + APInt LLVM_ATTRIBUTE_UNUSED_RESULT trunc(unsigned width) const; + /// \brief Sign extend to a new width. + /// /// This operation sign extends the APInt to a new width. If the high order /// bit is set, the fill on the left will be done with 1 bits, otherwise zero. /// It is an error to specify a width that is less than or equal to the /// current width. - /// @brief Sign extend to a new width. - APInt sext(unsigned width) const; + APInt LLVM_ATTRIBUTE_UNUSED_RESULT sext(unsigned width) const; + /// \brief Zero extend to a new width. + /// /// This operation zero extends the APInt to a new width. The high order bits /// are filled with 0 bits. It is an error to specify a width that is less /// than or equal to the current width. - /// @brief Zero extend to a new width. - APInt zext(unsigned width) const; + APInt LLVM_ATTRIBUTE_UNUSED_RESULT zext(unsigned width) const; + /// \brief Sign extend or truncate to width + /// /// Make this APInt have the bit width given by \p width. The value is sign /// extended, truncated, or left alone to make it that width. - /// @brief Sign extend or truncate to width - APInt sextOrTrunc(unsigned width) const; + APInt LLVM_ATTRIBUTE_UNUSED_RESULT sextOrTrunc(unsigned width) const; + /// \brief Zero extend or truncate to width + /// /// Make this APInt have the bit width given by \p width. The value is zero /// extended, truncated, or left alone to make it that width. - /// @brief Zero extend or truncate to width - APInt zextOrTrunc(unsigned width) const; + APInt LLVM_ATTRIBUTE_UNUSED_RESULT zextOrTrunc(unsigned width) const; + /// \brief Sign extend or truncate to width + /// /// Make this APInt have the bit width given by \p width. The value is sign /// extended, or left alone to make it that width. - /// @brief Sign extend or truncate to width - APInt sextOrSelf(unsigned width) const; + APInt LLVM_ATTRIBUTE_UNUSED_RESULT sextOrSelf(unsigned width) const; + /// \brief Zero extend or truncate to width + /// /// Make this APInt have the bit width given by \p width. The value is zero /// extended, or left alone to make it that width. - /// @brief Zero extend or truncate to width - APInt zextOrSelf(unsigned width) const; + APInt LLVM_ATTRIBUTE_UNUSED_RESULT zextOrSelf(unsigned width) const; /// @} - /// @name Bit Manipulation Operators + /// \name Bit Manipulation Operators /// @{ - /// @brief Set every bit to 1. + + /// \brief Set every bit to 1. void setAllBits() { if (isSingleWord()) VAL = UINT64_MAX; @@ -1101,11 +1209,12 @@ public: clearUnusedBits(); } + /// \brief Set a given bit to 1. + /// /// Set the given bit to 1 whose position is given as "bitPosition". - /// @brief Set a given bit to 1. void setBit(unsigned bitPosition); - /// @brief Set every bit to 0. + /// \brief Set every bit to 0. void clearAllBits() { if (isSingleWord()) VAL = 0; @@ -1113,11 +1222,12 @@ public: memset(pVal, 0, getNumWords() * APINT_WORD_SIZE); } + /// \brief Set a given bit to 0. + /// /// Set the given bit to 0 whose position is given as "bitPosition". - /// @brief Set a given bit to 0. void clearBit(unsigned bitPosition); - /// @brief Toggle every bit to its opposite value. + /// \brief Toggle every bit to its opposite value. void flipAllBits() { if (isSingleWord()) VAL ^= UINT64_MAX; @@ -1128,68 +1238,71 @@ public: clearUnusedBits(); } + /// \brief Toggles a given bit to its opposite value. + /// /// Toggle a given bit to its opposite value whose position is given /// as "bitPosition". - /// @brief Toggles a given bit to its opposite value. void flipBit(unsigned bitPosition); /// @} - /// @name Value Characterization Functions + /// \name Value Characterization Functions /// @{ - /// @returns the total number of bits. - unsigned getBitWidth() const { - return BitWidth; - } + /// \brief Return the number of bits in the APInt. + unsigned getBitWidth() const { return BitWidth; } + /// \brief Get the number of words. + /// /// Here one word's bitwidth equals to that of uint64_t. - /// @returns the number of words to hold the integer value of this APInt. - /// @brief Get the number of words. - unsigned getNumWords() const { - return getNumWords(BitWidth); - } + /// + /// \returns the number of words to hold the integer value of this APInt. + unsigned getNumWords() const { return getNumWords(BitWidth); } - /// Here one word's bitwidth equals to that of uint64_t. - /// @returns the number of words to hold the integer value with a - /// given bit width. - /// @brief Get the number of words. + /// \brief Get the number of words. + /// + /// *NOTE* Here one word's bitwidth equals to that of uint64_t. + /// + /// \returns the number of words to hold the integer value with a given bit + /// width. static unsigned getNumWords(unsigned BitWidth) { return (BitWidth + APINT_BITS_PER_WORD - 1) / APINT_BITS_PER_WORD; } + /// \brief Compute the number of active bits in the value + /// /// This function returns the number of active bits which is defined as the /// bit width minus the number of leading zeros. This is used in several /// computations to see how "wide" the value is. - /// @brief Compute the number of active bits in the value - unsigned getActiveBits() const { - return BitWidth - countLeadingZeros(); - } + unsigned getActiveBits() const { return BitWidth - countLeadingZeros(); } - /// This function returns the number of active words in the value of this - /// APInt. This is used in conjunction with getActiveData to extract the raw - /// value of the APInt. + /// \brief Compute the number of active words in the value of this APInt. + /// + /// This is used in conjunction with getActiveData to extract the raw value of + /// the APInt. unsigned getActiveWords() const { unsigned numActiveBits = getActiveBits(); return numActiveBits ? whichWord(numActiveBits - 1) + 1 : 1; } - /// Computes the minimum bit width for this APInt while considering it to be - /// a signed (and probably negative) value. If the value is not negative, - /// this function returns the same value as getActiveBits()+1. Otherwise, it + /// \brief Get the minimum bit size for this signed APInt + /// + /// Computes the minimum bit width for this APInt while considering it to be a + /// signed (and probably negative) value. If the value is not negative, this + /// function returns the same value as getActiveBits()+1. Otherwise, it /// returns the smallest bit width that will retain the negative value. For /// example, -1 can be written as 0b1 or 0xFFFFFFFFFF. 0b1 is shorter and so /// for -1, this function will always return 1. - /// @brief Get the minimum bit size for this signed APInt unsigned getMinSignedBits() const { if (isNegative()) return BitWidth - countLeadingOnes() + 1; - return getActiveBits()+1; + return getActiveBits() + 1; } + /// \brief Get zero extended value + /// /// This method attempts to return the value of this APInt as a zero extended /// uint64_t. The bitwidth must be <= 64 or the value must fit within a /// uint64_t. Otherwise an assertion will result. - /// @brief Get zero extended value uint64_t getZExtValue() const { if (isSingleWord()) return VAL; @@ -1197,43 +1310,49 @@ public: return pVal[0]; } + /// \brief Get sign extended value + /// /// This method attempts to return the value of this APInt as a sign extended /// int64_t. The bit width must be <= 64 or the value must fit within an /// int64_t. Otherwise an assertion will result. - /// @brief Get sign extended value int64_t getSExtValue() const { if (isSingleWord()) return int64_t(VAL << (APINT_BITS_PER_WORD - BitWidth)) >> - (APINT_BITS_PER_WORD - BitWidth); + (APINT_BITS_PER_WORD - BitWidth); assert(getMinSignedBits() <= 64 && "Too many bits for int64_t"); return int64_t(pVal[0]); } + /// \brief Get bits required for string value. + /// /// This method determines how many bits are required to hold the APInt /// equivalent of the string given by \p str. - /// @brief Get bits required for string value. static unsigned getBitsNeeded(StringRef str, uint8_t radix); - /// countLeadingZeros - This function is an APInt version of the - /// countLeadingZeros_{32,64} functions in MathExtras.h. It counts the number - /// of zeros from the most significant bit to the first one bit. - /// @returns BitWidth if the value is zero, otherwise - /// returns the number of zeros from the most significant bit to the first - /// one bits. + /// \brief The APInt version of the countLeadingZeros functions in + /// MathExtras.h. + /// + /// It counts the number of zeros from the most significant bit to the first + /// one bit. + /// + /// \returns BitWidth if the value is zero, otherwise returns the number of + /// zeros from the most significant bit to the first one bits. unsigned countLeadingZeros() const { if (isSingleWord()) { unsigned unusedBits = APINT_BITS_PER_WORD - BitWidth; - return CountLeadingZeros_64(VAL) - unusedBits; + return llvm::countLeadingZeros(VAL) - unusedBits; } return countLeadingZerosSlowCase(); } - /// countLeadingOnes - This function is an APInt version of the - /// countLeadingOnes_{32,64} functions in MathExtras.h. It counts the number - /// of ones from the most significant bit to the first zero bit. - /// @returns 0 if the high order bit is not set, otherwise - /// returns the number of 1 bits from the most significant to the least - /// @brief Count the number of leading one bits. + /// \brief Count the number of leading one bits. + /// + /// This function is an APInt version of the countLeadingOnes_{32,64} + /// functions in MathExtras.h. It counts the number of ones from the most + /// significant bit to the first zero bit. + /// + /// \returns 0 if the high order bit is not set, otherwise returns the number + /// of 1 bits from the most significant to the least unsigned countLeadingOnes() const; /// Computes the number of leading bits of this APInt that are equal to its @@ -1242,34 +1361,36 @@ public: return isNegative() ? countLeadingOnes() : countLeadingZeros(); } - /// countTrailingZeros - This function is an APInt version of the - /// countTrailingZeros_{32,64} functions in MathExtras.h. It counts - /// the number of zeros from the least significant bit to the first set bit. - /// @returns BitWidth if the value is zero, otherwise - /// returns the number of zeros from the least significant bit to the first - /// one bit. - /// @brief Count the number of trailing zero bits. + /// \brief Count the number of trailing zero bits. + /// + /// This function is an APInt version of the countTrailingZeros_{32,64} + /// functions in MathExtras.h. It counts the number of zeros from the least + /// significant bit to the first set bit. + /// + /// \returns BitWidth if the value is zero, otherwise returns the number of + /// zeros from the least significant bit to the first one bit. unsigned countTrailingZeros() const; - /// countTrailingOnes - This function is an APInt version of the - /// countTrailingOnes_{32,64} functions in MathExtras.h. It counts - /// the number of ones from the least significant bit to the first zero bit. - /// @returns BitWidth if the value is all ones, otherwise - /// returns the number of ones from the least significant bit to the first - /// zero bit. - /// @brief Count the number of trailing one bits. + /// \brief Count the number of trailing one bits. + /// + /// This function is an APInt version of the countTrailingOnes_{32,64} + /// functions in MathExtras.h. It counts the number of ones from the least + /// significant bit to the first zero bit. + /// + /// \returns BitWidth if the value is all ones, otherwise returns the number + /// of ones from the least significant bit to the first zero bit. unsigned countTrailingOnes() const { if (isSingleWord()) return CountTrailingOnes_64(VAL); return countTrailingOnesSlowCase(); } - /// countPopulation - This function is an APInt version of the - /// countPopulation_{32,64} 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. - /// @brief Count the number of bits set. + /// \brief Count the number of bits set. + /// + /// This function is an APInt version of the countPopulation_{32,64} 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); @@ -1277,12 +1398,12 @@ public: } /// @} - /// @name Conversion Functions + /// \name Conversion Functions /// @{ void print(raw_ostream &OS, bool isSigned) const; - /// toString - Converts an APInt to a string and append it to Str. Str is - /// commonly a SmallString. + /// Converts an APInt to a string and append it to Str. Str is commonly a + /// SmallString. void toString(SmallVectorImpl &Str, unsigned Radix, bool Signed, bool formatAsCLiteral = false) const; @@ -1298,32 +1419,30 @@ public: toString(Str, Radix, true, false); } - /// toString - This returns the APInt as a std::string. Note that this is an - /// inefficient method. It is better to pass in a SmallVector/SmallString - /// to the methods above to avoid thrashing the heap for the string. + /// \brief Return the APInt as a std::string. + /// + /// Note that this is an inefficient method. It is better to pass in a + /// SmallVector/SmallString to the methods above to avoid thrashing the heap + /// for the string. std::string toString(unsigned Radix, bool Signed) const; + /// \returns a byte-swapped representation of this APInt Value. + APInt LLVM_ATTRIBUTE_UNUSED_RESULT byteSwap() const; - /// @returns a byte-swapped representation of this APInt Value. - APInt byteSwap() const; - - /// @brief Converts this APInt to a double value. + /// \brief Converts this APInt to a double value. double roundToDouble(bool isSigned) const; - /// @brief Converts this unsigned APInt to a double value. - double roundToDouble() const { - return roundToDouble(false); - } + /// \brief Converts this unsigned APInt to a double value. + double roundToDouble() const { return roundToDouble(false); } - /// @brief Converts this signed APInt to a double value. - double signedRoundToDouble() const { - return roundToDouble(true); - } + /// \brief Converts this signed APInt to a double value. + double signedRoundToDouble() const { return roundToDouble(true); } + /// \brief Converts APInt bits to a double + /// /// The conversion does not do a translation from integer to double, it just /// re-interprets the bits as a double. Note that it is valid to do this on /// any bit width. Exactly 64 bits will be translated. - /// @brief Converts APInt bits to a double double bitsToDouble() const { union { uint64_t I; @@ -1333,10 +1452,11 @@ public: return T.D; } + /// \brief Converts APInt bits to a double + /// /// The conversion does not do a translation from integer to float, it just /// re-interprets the bits as a float. Note that it is valid to do this on /// any bit width. Exactly 32 bits will be translated. - /// @brief Converts APInt bits to a double float bitsToFloat() const { union { unsigned I; @@ -1346,10 +1466,11 @@ public: return T.F; } + /// \brief Converts a double to APInt bits. + /// /// The conversion does not do a translation from double to integer, it just /// re-interprets the bits of the double. - /// @brief Converts a double to APInt bits. - static APInt doubleToBits(double V) { + static APInt LLVM_ATTRIBUTE_UNUSED_RESULT doubleToBits(double V) { union { uint64_t I; double D; @@ -1358,10 +1479,11 @@ public: return APInt(sizeof T * CHAR_BIT, T.I); } + /// \brief Converts a float to APInt bits. + /// /// The conversion does not do a translation from float to integer, it just /// re-interprets the bits of the float. - /// @brief Converts a float to APInt bits. - static APInt floatToBits(float V) { + static APInt LLVM_ATTRIBUTE_UNUSED_RESULT floatToBits(float V) { union { unsigned I; float F; @@ -1371,20 +1493,18 @@ public: } /// @} - /// @name Mathematics Operations + /// \name Mathematics Operations /// @{ - /// @returns the floor log base 2 of this APInt. - unsigned logBase2() const { - return BitWidth - 1 - countLeadingZeros(); - } + /// \returns the floor log base 2 of this APInt. + unsigned logBase2() const { return BitWidth - 1 - countLeadingZeros(); } - /// @returns the ceil log base 2 of this APInt. + /// \returns the ceil log base 2 of this APInt. unsigned ceilLogBase2() const { return BitWidth - (*this - 1).countLeadingZeros(); } - /// @returns the log base 2 of this APInt if its an exact power of two, -1 + /// \returns the log base 2 of this APInt if its an exact power of two, -1 /// otherwise int32_t exactLogBase2() const { if (!isPowerOf2()) @@ -1392,22 +1512,23 @@ public: return logBase2(); } - /// @brief Compute the square root - APInt sqrt() const; + /// \brief Compute the square root + APInt LLVM_ATTRIBUTE_UNUSED_RESULT sqrt() const; + /// \brief Get the absolute value; + /// /// If *this is < 0 then return -(*this), otherwise *this; - /// @brief Get the absolute value; - APInt abs() const { + APInt LLVM_ATTRIBUTE_UNUSED_RESULT abs() const { if (isNegative()) return -(*this); return *this; } - /// @returns the multiplicative inverse for a given modulo. - APInt multiplicativeInverse(const APInt& modulo) const; + /// \returns the multiplicative inverse for a given modulo. + APInt multiplicativeInverse(const APInt &modulo) const; /// @} - /// @name Support for division by constant + /// \name Support for division by constant /// @{ /// Calculate the magic number for signed division by a constant. @@ -1419,18 +1540,17 @@ public: mu magicu(unsigned LeadingZeros = 0) const; /// @} - /// @name Building-block Operations for APInt and APFloat + /// \name Building-block Operations for APInt and APFloat /// @{ - // These building block operations operate on a representation of - // arbitrary precision, two's-complement, bignum integer values. - // They should be sufficient to implement APInt and APFloat bignum - // requirements. Inputs are generally a pointer to the base of an - // array of integer parts, representing an unsigned bignum, and a - // count of how many parts there are. + // These building block operations operate on a representation of arbitrary + // precision, two's-complement, bignum integer values. They should be + // sufficient to implement APInt and APFloat bignum requirements. Inputs are + // generally a pointer to the base of an array of integer parts, representing + // an unsigned bignum, and a count of how many parts there are. - /// Sets the least significant part of a bignum to the input value, - /// and zeroes out higher parts. */ + /// Sets the least significant part of a bignum to the input value, and zeroes + /// out higher parts. static void tcSet(integerPart *, integerPart, unsigned int); /// Assign one bignum to another. @@ -1442,13 +1562,13 @@ public: /// Extract the given bit of a bignum; returns 0 or 1. Zero-based. static int tcExtractBit(const integerPart *, unsigned int bit); - /// Copy the bit vector of width srcBITS from SRC, starting at bit - /// srcLSB, to DST, of dstCOUNT parts, such that the bit srcLSB - /// becomes the least significant bit of DST. All high bits above - /// srcBITS in DST are zero-filled. + /// Copy the bit vector of width srcBITS from SRC, starting at bit srcLSB, to + /// DST, of dstCOUNT parts, such that the bit srcLSB becomes the least + /// significant bit of DST. All high bits above srcBITS in DST are + /// zero-filled. static void tcExtract(integerPart *, unsigned int dstCount, - const integerPart *, - unsigned int srcBits, unsigned int srcLSB); + const integerPart *, unsigned int srcBits, + unsigned int srcLSB); /// Set the given bit of a bignum. Zero-based. static void tcSetBit(integerPart *, unsigned int bit); @@ -1456,76 +1576,70 @@ public: /// Clear the given bit of a bignum. Zero-based. static void tcClearBit(integerPart *, unsigned int bit); - /// Returns the bit number of the least or most significant set bit - /// of a number. If the input number has no bits set -1U is - /// returned. + /// Returns the bit number of the least or most significant set bit of a + /// number. If the input number has no bits set -1U is returned. static unsigned int tcLSB(const integerPart *, unsigned int); static unsigned int tcMSB(const integerPart *parts, unsigned int n); /// Negate a bignum in-place. static void tcNegate(integerPart *, unsigned int); - /// DST += RHS + CARRY where CARRY is zero or one. Returns the - /// carry flag. + /// DST += RHS + CARRY where CARRY is zero or one. Returns the carry flag. static integerPart tcAdd(integerPart *, const integerPart *, integerPart carry, unsigned); - /// DST -= RHS + CARRY where CARRY is zero or one. Returns the - /// carry flag. + /// DST -= RHS + CARRY where CARRY is zero or one. Returns the carry flag. static integerPart tcSubtract(integerPart *, const integerPart *, integerPart carry, unsigned); - /// DST += SRC * MULTIPLIER + PART if add is true - /// DST = SRC * MULTIPLIER + PART if add is false + /// DST += SRC * MULTIPLIER + PART if add is true + /// DST = SRC * MULTIPLIER + PART if add is false /// - /// Requires 0 <= DSTPARTS <= SRCPARTS + 1. If DST overlaps SRC - /// they must start at the same point, i.e. DST == SRC. + /// Requires 0 <= DSTPARTS <= SRCPARTS + 1. If DST overlaps SRC they must + /// start at the same point, i.e. DST == SRC. /// - /// If DSTPARTS == SRC_PARTS + 1 no overflow occurs and zero is - /// returned. Otherwise DST is filled with the least significant - /// DSTPARTS parts of the result, and if all of the omitted higher - /// parts were zero return zero, otherwise overflow occurred and - /// return one. + /// If DSTPARTS == SRC_PARTS + 1 no overflow occurs and zero is returned. + /// Otherwise DST is filled with the least significant DSTPARTS parts of the + /// result, and if all of the omitted higher parts were zero return zero, + /// otherwise overflow occurred and return one. static int tcMultiplyPart(integerPart *dst, const integerPart *src, integerPart multiplier, integerPart carry, unsigned int srcParts, unsigned int dstParts, bool add); - /// DST = LHS * RHS, where DST has the same width as the operands - /// and is filled with the least significant parts of the result. - /// Returns one if overflow occurred, otherwise zero. DST must be - /// disjoint from both operands. - static int tcMultiply(integerPart *, const integerPart *, - const integerPart *, unsigned); - - /// DST = LHS * RHS, where DST has width the sum of the widths of - /// the operands. No overflow occurs. DST must be disjoint from - /// both operands. Returns the number of parts required to hold the - /// result. + /// DST = LHS * RHS, where DST has the same width as the operands and is + /// filled with the least significant parts of the result. Returns one if + /// overflow occurred, otherwise zero. DST must be disjoint from both + /// operands. + static int tcMultiply(integerPart *, const integerPart *, const integerPart *, + unsigned); + + /// DST = LHS * RHS, where DST has width the sum of the widths of the + /// operands. No overflow occurs. DST must be disjoint from both + /// operands. Returns the number of parts required to hold the result. static unsigned int tcFullMultiply(integerPart *, const integerPart *, const integerPart *, unsigned, unsigned); /// If RHS is zero LHS and REMAINDER are left unchanged, return one. - /// Otherwise set LHS to LHS / RHS with the fractional part - /// discarded, set REMAINDER to the remainder, return zero. i.e. + /// Otherwise set LHS to LHS / RHS with the fractional part discarded, set + /// REMAINDER to the remainder, return zero. i.e. /// /// OLD_LHS = RHS * LHS + REMAINDER /// - /// SCRATCH is a bignum of the same size as the operands and result - /// for use by the routine; its contents need not be initialized - /// and are destroyed. LHS, REMAINDER and SCRATCH must be - /// distinct. + /// SCRATCH is a bignum of the same size as the operands and result for use by + /// the routine; its contents need not be initialized and are destroyed. LHS, + /// REMAINDER and SCRATCH must be distinct. static int tcDivide(integerPart *lhs, const integerPart *rhs, integerPart *remainder, integerPart *scratch, unsigned int parts); - /// Shift a bignum left COUNT bits. Shifted in bits are zero. - /// There are no restrictions on COUNT. + /// Shift a bignum left COUNT bits. Shifted in bits are zero. There are no + /// restrictions on COUNT. static void tcShiftLeft(integerPart *, unsigned int parts, unsigned int count); - /// Shift a bignum right COUNT bits. Shifted in bits are zero. - /// There are no restrictions on COUNT. + /// Shift a bignum right COUNT bits. Shifted in bits are zero. There are no + /// restrictions on COUNT. static void tcShiftRight(integerPart *, unsigned int parts, unsigned int count); @@ -1536,17 +1650,19 @@ public: static void tcComplement(integerPart *, unsigned int); /// Comparison (unsigned) of two bignums. - static int tcCompare(const integerPart *, const integerPart *, - unsigned int); + static int tcCompare(const integerPart *, const integerPart *, unsigned int); /// Increment a bignum in-place. Return the carry flag. static integerPart tcIncrement(integerPart *, unsigned int); + /// Decrement a bignum in-place. Return the borrow flag. + static integerPart tcDecrement(integerPart *, unsigned int); + /// Set the least significant BITS and clear the rest. static void tcSetLeastSignificantBits(integerPart *, unsigned int, unsigned int bits); - /// @brief debug method + /// \brief debug method void dump() const; /// @} @@ -1554,24 +1670,20 @@ public: /// Magic data for optimising signed division by a constant. struct APInt::ms { - APInt m; ///< magic number - unsigned s; ///< shift amount + APInt m; ///< magic number + unsigned s; ///< shift amount }; /// Magic data for optimising unsigned division by a constant. struct APInt::mu { - APInt m; ///< magic number - bool a; ///< add indicator - unsigned s; ///< shift amount + APInt m; ///< magic number + bool a; ///< add indicator + unsigned s; ///< shift amount }; -inline bool operator==(uint64_t V1, const APInt& V2) { - return V2 == V1; -} +inline bool operator==(uint64_t V1, const APInt &V2) { return V2 == V1; } -inline bool operator!=(uint64_t V1, const APInt& V2) { - return V2 != V1; -} +inline bool operator!=(uint64_t V1, const APInt &V2) { return V2 != V1; } inline raw_ostream &operator<<(raw_ostream &OS, const APInt &I) { I.print(OS, true); @@ -1580,188 +1692,173 @@ inline raw_ostream &operator<<(raw_ostream &OS, const APInt &I) { namespace APIntOps { -/// @brief Determine the smaller of two APInts considered to be signed. -inline APInt smin(const APInt &A, const APInt &B) { - return A.slt(B) ? A : B; -} +/// \brief Determine the smaller of two APInts considered to be signed. +inline APInt smin(const APInt &A, const APInt &B) { return A.slt(B) ? A : B; } -/// @brief Determine the larger of two APInts considered to be signed. -inline APInt smax(const APInt &A, const APInt &B) { - return A.sgt(B) ? A : B; -} +/// \brief Determine the larger of two APInts considered to be signed. +inline APInt smax(const APInt &A, const APInt &B) { return A.sgt(B) ? A : B; } -/// @brief Determine the smaller of two APInts considered to be signed. -inline APInt umin(const APInt &A, const APInt &B) { - return A.ult(B) ? A : B; -} +/// \brief Determine the smaller of two APInts considered to be signed. +inline APInt umin(const APInt &A, const APInt &B) { return A.ult(B) ? A : B; } -/// @brief Determine the larger of two APInts considered to be unsigned. -inline APInt umax(const APInt &A, const APInt &B) { - return A.ugt(B) ? A : B; -} +/// \brief Determine the larger of two APInts considered to be unsigned. +inline APInt umax(const APInt &A, const APInt &B) { return A.ugt(B) ? A : B; } -/// @brief Check if the specified APInt has a N-bits unsigned integer value. -inline bool isIntN(unsigned N, const APInt& APIVal) { - return APIVal.isIntN(N); -} +/// \brief Check if the specified APInt has a N-bits unsigned integer value. +inline bool isIntN(unsigned N, const APInt &APIVal) { return APIVal.isIntN(N); } -/// @brief Check if the specified APInt has a N-bits signed integer value. -inline bool isSignedIntN(unsigned N, const APInt& APIVal) { +/// \brief Check if the specified APInt has a N-bits signed integer value. +inline bool isSignedIntN(unsigned N, const APInt &APIVal) { return APIVal.isSignedIntN(N); } -/// @returns true if the argument APInt value is a sequence of ones -/// starting at the least significant bit with the remainder zero. -inline bool isMask(unsigned numBits, const APInt& APIVal) { +/// \returns true if the argument APInt value is a sequence of ones starting at +/// the least significant bit with the remainder zero. +inline bool isMask(unsigned numBits, const APInt &APIVal) { return numBits <= APIVal.getBitWidth() && - APIVal == APInt::getLowBitsSet(APIVal.getBitWidth(), numBits); + APIVal == APInt::getLowBitsSet(APIVal.getBitWidth(), numBits); } -/// @returns true if the argument APInt value contains a sequence of ones +/// \brief Return true if the argument APInt value contains a sequence of ones /// with the remainder zero. -inline bool isShiftedMask(unsigned numBits, const APInt& APIVal) { - return isMask(numBits, (APIVal - APInt(numBits,1)) | APIVal); +inline bool isShiftedMask(unsigned numBits, const APInt &APIVal) { + return isMask(numBits, (APIVal - APInt(numBits, 1)) | APIVal); } -/// @returns a byte-swapped representation of the specified APInt Value. -inline APInt byteSwap(const APInt& APIVal) { - return APIVal.byteSwap(); -} +/// \brief Returns a byte-swapped representation of the specified APInt Value. +inline APInt byteSwap(const APInt &APIVal) { return APIVal.byteSwap(); } -/// @returns the floor log base 2 of the specified APInt value. -inline unsigned logBase2(const APInt& APIVal) { - return APIVal.logBase2(); -} +/// \brief Returns the floor log base 2 of the specified APInt value. +inline unsigned logBase2(const APInt &APIVal) { return APIVal.logBase2(); } -/// GreatestCommonDivisor - This function returns the greatest common -/// divisor of the two APInt values using Euclid's algorithm. -/// @returns the greatest common divisor of Val1 and Val2 -/// @brief Compute GCD of two APInt values. -APInt GreatestCommonDivisor(const APInt& Val1, const APInt& Val2); +/// \brief Compute GCD of two APInt values. +/// +/// This function returns the greatest common divisor of the two APInt values +/// using Euclid's algorithm. +/// +/// \returns the greatest common divisor of Val1 and Val2 +APInt GreatestCommonDivisor(const APInt &Val1, const APInt &Val2); +/// \brief Converts the given APInt to a double value. +/// /// Treats the APInt as an unsigned value for conversion purposes. -/// @brief Converts the given APInt to a double value. -inline double RoundAPIntToDouble(const APInt& APIVal) { +inline double RoundAPIntToDouble(const APInt &APIVal) { return APIVal.roundToDouble(); } +/// \brief Converts the given APInt to a double value. +/// /// Treats the APInt as a signed value for conversion purposes. -/// @brief Converts the given APInt to a double value. -inline double RoundSignedAPIntToDouble(const APInt& APIVal) { +inline double RoundSignedAPIntToDouble(const APInt &APIVal) { return APIVal.signedRoundToDouble(); } -/// @brief Converts the given APInt to a float vlalue. -inline float RoundAPIntToFloat(const APInt& APIVal) { +/// \brief Converts the given APInt to a float vlalue. +inline float RoundAPIntToFloat(const APInt &APIVal) { return float(RoundAPIntToDouble(APIVal)); } +/// \brief Converts the given APInt to a float value. +/// /// Treast the APInt as a signed value for conversion purposes. -/// @brief Converts the given APInt to a float value. -inline float RoundSignedAPIntToFloat(const APInt& APIVal) { +inline float RoundSignedAPIntToFloat(const APInt &APIVal) { return float(APIVal.signedRoundToDouble()); } -/// RoundDoubleToAPInt - This function convert a double value to an APInt value. -/// @brief Converts the given double value into a APInt. +/// \brief Converts the given double value into a APInt. +/// +/// This function convert a double value to an APInt value. APInt RoundDoubleToAPInt(double Double, unsigned width); -/// RoundFloatToAPInt - Converts a float value into an APInt value. -/// @brief Converts a float value into a APInt. +/// \brief Converts a float value into a APInt. +/// +/// Converts a float value into an APInt value. inline APInt RoundFloatToAPInt(float Float, unsigned width) { return RoundDoubleToAPInt(double(Float), width); } +/// \brief Arithmetic right-shift function. +/// /// Arithmetic right-shift the APInt by shiftAmt. -/// @brief Arithmetic right-shift function. -inline APInt ashr(const APInt& LHS, unsigned shiftAmt) { +inline APInt ashr(const APInt &LHS, unsigned shiftAmt) { return LHS.ashr(shiftAmt); } +/// \brief Logical right-shift function. +/// /// Logical right-shift the APInt by shiftAmt. -/// @brief Logical right-shift function. -inline APInt lshr(const APInt& LHS, unsigned shiftAmt) { +inline APInt lshr(const APInt &LHS, unsigned shiftAmt) { return LHS.lshr(shiftAmt); } +/// \brief Left-shift function. +/// /// Left-shift the APInt by shiftAmt. -/// @brief Left-shift function. -inline APInt shl(const APInt& LHS, unsigned shiftAmt) { +inline APInt shl(const APInt &LHS, unsigned shiftAmt) { return LHS.shl(shiftAmt); } +/// \brief Signed division function for APInt. +/// /// Signed divide APInt LHS by APInt RHS. -/// @brief Signed division function for APInt. -inline APInt sdiv(const APInt& LHS, const APInt& RHS) { - return LHS.sdiv(RHS); -} +inline APInt sdiv(const APInt &LHS, const APInt &RHS) { return LHS.sdiv(RHS); } +/// \brief Unsigned division function for APInt. +/// /// Unsigned divide APInt LHS by APInt RHS. -/// @brief Unsigned division function for APInt. -inline APInt udiv(const APInt& LHS, const APInt& RHS) { - return LHS.udiv(RHS); -} +inline APInt udiv(const APInt &LHS, const APInt &RHS) { return LHS.udiv(RHS); } +/// \brief Function for signed remainder operation. +/// /// Signed remainder operation on APInt. -/// @brief Function for signed remainder operation. -inline APInt srem(const APInt& LHS, const APInt& RHS) { - return LHS.srem(RHS); -} +inline APInt srem(const APInt &LHS, const APInt &RHS) { return LHS.srem(RHS); } +/// \brief Function for unsigned remainder operation. +/// /// Unsigned remainder operation on APInt. -/// @brief Function for unsigned remainder operation. -inline APInt urem(const APInt& LHS, const APInt& RHS) { - return LHS.urem(RHS); -} +inline APInt urem(const APInt &LHS, const APInt &RHS) { return LHS.urem(RHS); } +/// \brief Function for multiplication operation. +/// /// Performs multiplication on APInt values. -/// @brief Function for multiplication operation. -inline APInt mul(const APInt& LHS, const APInt& RHS) { - return LHS * RHS; -} +inline APInt mul(const APInt &LHS, const APInt &RHS) { return LHS * RHS; } +/// \brief Function for addition operation. +/// /// Performs addition on APInt values. -/// @brief Function for addition operation. -inline APInt add(const APInt& LHS, const APInt& RHS) { - return LHS + RHS; -} +inline APInt add(const APInt &LHS, const APInt &RHS) { return LHS + RHS; } +/// \brief Function for subtraction operation. +/// /// Performs subtraction on APInt values. -/// @brief Function for subtraction operation. -inline APInt sub(const APInt& LHS, const APInt& RHS) { - return LHS - RHS; -} +inline APInt sub(const APInt &LHS, const APInt &RHS) { return LHS - RHS; } +/// \brief Bitwise AND function for APInt. +/// /// Performs bitwise AND operation on APInt LHS and /// APInt RHS. -/// @brief Bitwise AND function for APInt. -inline APInt And(const APInt& LHS, const APInt& RHS) { - return LHS & RHS; -} +inline APInt And(const APInt &LHS, const APInt &RHS) { return LHS & RHS; } +/// \brief Bitwise OR function for APInt. +/// /// Performs bitwise OR operation on APInt LHS and APInt RHS. -/// @brief Bitwise OR function for APInt. -inline APInt Or(const APInt& LHS, const APInt& RHS) { - return LHS | RHS; -} +inline APInt Or(const APInt &LHS, const APInt &RHS) { return LHS | RHS; } +/// \brief Bitwise XOR function for APInt. +/// /// Performs bitwise XOR operation on APInt. -/// @brief Bitwise XOR function for APInt. -inline APInt Xor(const APInt& LHS, const APInt& RHS) { - return LHS ^ RHS; -} +inline APInt Xor(const APInt &LHS, const APInt &RHS) { return LHS ^ RHS; } +/// \brief Bitwise complement function. +/// /// Performs a bitwise complement operation on APInt. -/// @brief Bitwise complement function. -inline APInt Not(const APInt& APIVal) { - return ~APIVal; -} +inline APInt Not(const APInt &APIVal) { return ~APIVal; } } // End of APIntOps namespace - // See friend declaration above. This additional declaration is required in - // order to compile LLVM with IBM xlC compiler. - hash_code hash_value(const APInt &Arg); +// See friend declaration above. This additional declaration is required in +// order to compile LLVM with IBM xlC compiler. +hash_code hash_value(const APInt &Arg); } // End of llvm namespace #endif diff --git a/contrib/llvm/include/llvm/ADT/APSInt.h b/contrib/llvm/include/llvm/ADT/APSInt.h index 11be4c513..ad035a7c3 100644 --- a/contrib/llvm/include/llvm/ADT/APSInt.h +++ b/contrib/llvm/include/llvm/ADT/APSInt.h @@ -68,18 +68,18 @@ public: } using APInt::toString; - APSInt trunc(uint32_t width) const { + APSInt LLVM_ATTRIBUTE_UNUSED_RESULT trunc(uint32_t width) const { return APSInt(APInt::trunc(width), IsUnsigned); } - APSInt extend(uint32_t width) const { + APSInt LLVM_ATTRIBUTE_UNUSED_RESULT extend(uint32_t width) const { if (IsUnsigned) return APSInt(zext(width), IsUnsigned); else return APSInt(sext(width), IsUnsigned); } - APSInt extOrTrunc(uint32_t width) const { + APSInt LLVM_ATTRIBUTE_UNUSED_RESULT extOrTrunc(uint32_t width) const { if (IsUnsigned) return APSInt(zextOrTrunc(width), IsUnsigned); else @@ -212,7 +212,7 @@ public: assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); return APSInt(static_cast(*this) & RHS, IsUnsigned); } - APSInt And(const APSInt& RHS) const { + APSInt LLVM_ATTRIBUTE_UNUSED_RESULT And(const APSInt& RHS) const { return this->operator&(RHS); } @@ -220,7 +220,7 @@ public: assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); return APSInt(static_cast(*this) | RHS, IsUnsigned); } - APSInt Or(const APSInt& RHS) const { + APSInt LLVM_ATTRIBUTE_UNUSED_RESULT Or(const APSInt& RHS) const { return this->operator|(RHS); } @@ -229,7 +229,7 @@ public: assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); return APSInt(static_cast(*this) ^ RHS, IsUnsigned); } - APSInt Xor(const APSInt& RHS) const { + APSInt LLVM_ATTRIBUTE_UNUSED_RESULT Xor(const APSInt& RHS) const { return this->operator^(RHS); } diff --git a/contrib/llvm/include/llvm/ADT/ArrayRef.h b/contrib/llvm/include/llvm/ADT/ArrayRef.h index d4152ec72..e5562c368 100644 --- a/contrib/llvm/include/llvm/ADT/ArrayRef.h +++ b/contrib/llvm/include/llvm/ADT/ArrayRef.h @@ -80,9 +80,16 @@ namespace llvm { /// Construct an ArrayRef from a C array. template - /*implicit*/ ArrayRef(const T (&Arr)[N]) + /*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 + /// @} /// @name Simple Operations /// @{ @@ -178,6 +185,8 @@ namespace llvm { public: typedef T *iterator; + typedef std::reverse_iterator reverse_iterator; + /// Construct an empty MutableArrayRef. /*implicit*/ MutableArrayRef() : ArrayRef() {} @@ -212,6 +221,9 @@ namespace llvm { iterator begin() const { return data(); } iterator end() const { return data() + this->size(); } + reverse_iterator rbegin() const { return reverse_iterator(end()); } + reverse_iterator rend() const { return reverse_iterator(begin()); } + /// front - Get the first element. T &front() const { assert(!this->empty()); diff --git a/contrib/llvm/include/llvm/ADT/BitVector.h b/contrib/llvm/include/llvm/ADT/BitVector.h index 82cfdf437..8fb538f68 100644 --- a/contrib/llvm/include/llvm/ADT/BitVector.h +++ b/contrib/llvm/include/llvm/ADT/BitVector.h @@ -138,8 +138,15 @@ public: /// all - Returns true if all bits are set. bool all() const { - // TODO: Optimize this. - return count() == size(); + for (unsigned i = 0; i < Size / BITWORD_SIZE; ++i) + if (Bits[i] != ~0UL) + return false; + + // If bits remain check that they are ones. The unused bits are always zero. + if (unsigned Remainder = Size % BITWORD_SIZE) + return Bits[Size / BITWORD_SIZE] == (1UL << Remainder) - 1; + + return true; } /// none - Returns true if none of the bits are set. @@ -153,9 +160,9 @@ public: for (unsigned i = 0; i < NumBitWords(size()); ++i) if (Bits[i] != 0) { if (sizeof(BitWord) == 4) - return i * BITWORD_SIZE + CountTrailingZeros_32((uint32_t)Bits[i]); + return i * BITWORD_SIZE + countTrailingZeros((uint32_t)Bits[i]); if (sizeof(BitWord) == 8) - return i * BITWORD_SIZE + CountTrailingZeros_64(Bits[i]); + return i * BITWORD_SIZE + countTrailingZeros(Bits[i]); llvm_unreachable("Unsupported!"); } return -1; @@ -176,9 +183,9 @@ public: if (Copy != 0) { if (sizeof(BitWord) == 4) - return WordPos * BITWORD_SIZE + CountTrailingZeros_32((uint32_t)Copy); + return WordPos * BITWORD_SIZE + countTrailingZeros((uint32_t)Copy); if (sizeof(BitWord) == 8) - return WordPos * BITWORD_SIZE + CountTrailingZeros_64(Copy); + return WordPos * BITWORD_SIZE + countTrailingZeros(Copy); llvm_unreachable("Unsupported!"); } @@ -186,9 +193,9 @@ public: for (unsigned i = WordPos+1; i < NumBitWords(size()); ++i) if (Bits[i] != 0) { if (sizeof(BitWord) == 4) - return i * BITWORD_SIZE + CountTrailingZeros_32((uint32_t)Bits[i]); + return i * BITWORD_SIZE + countTrailingZeros((uint32_t)Bits[i]); if (sizeof(BitWord) == 8) - return i * BITWORD_SIZE + CountTrailingZeros_64(Bits[i]); + return i * BITWORD_SIZE + countTrailingZeros(Bits[i]); llvm_unreachable("Unsupported!"); } return -1; diff --git a/contrib/llvm/include/llvm/ADT/DenseMap.h b/contrib/llvm/include/llvm/ADT/DenseMap.h index 31fd6d899..ce322cce4 100644 --- a/contrib/llvm/include/llvm/ADT/DenseMap.h +++ b/contrib/llvm/include/llvm/ADT/DenseMap.h @@ -64,7 +64,9 @@ public: return const_iterator(getBucketsEnd(), getBucketsEnd(), true); } - bool empty() const { return getNumEntries() == 0; } + bool LLVM_ATTRIBUTE_UNUSED_RESULT empty() const { + return getNumEntries() == 0; + } unsigned size() const { return getNumEntries(); } /// Grow the densemap so that it has at least Size buckets. Does not shrink @@ -222,11 +224,11 @@ public: if (LookupBucketFor(Key, TheBucket)) return *TheBucket; - return *InsertIntoBucket(Key, ValueT(), TheBucket); + return *InsertIntoBucket(std::move(Key), ValueT(), TheBucket); } ValueT &operator[](KeyT &&Key) { - return FindAndConstruct(Key).second; + return FindAndConstruct(std::move(Key)).second; } #endif @@ -436,9 +438,8 @@ private: this->grow(NumBuckets * 2); LookupBucketFor(Key, TheBucket); NumBuckets = getNumBuckets(); - } - if (NumBuckets-(NewNumEntries+getNumTombstones()) <= NumBuckets/8) { - this->grow(NumBuckets * 2); + } else if (NumBuckets-(NewNumEntries+getNumTombstones()) <= NumBuckets/8) { + this->grow(NumBuckets); LookupBucketFor(Key, TheBucket); } assert(TheBucket); @@ -713,13 +714,13 @@ public: init(NumInitBuckets); } - SmallDenseMap(const SmallDenseMap &other) { + SmallDenseMap(const SmallDenseMap &other) : BaseT() { init(0); copyFrom(other); } #if LLVM_HAS_RVALUE_REFERENCES - SmallDenseMap(SmallDenseMap &&other) { + SmallDenseMap(SmallDenseMap &&other) : BaseT() { init(0); swap(other); } diff --git a/contrib/llvm/include/llvm/ADT/FoldingSet.h b/contrib/llvm/include/llvm/ADT/FoldingSet.h index 91794dea6..1b2c94c35 100644 --- a/contrib/llvm/include/llvm/ADT/FoldingSet.h +++ b/contrib/llvm/include/llvm/ADT/FoldingSet.h @@ -352,7 +352,8 @@ template class FoldingSetBucketIterator; template inline bool DefaultFoldingSetTrait::Equals(T &X, const FoldingSetNodeID &ID, - unsigned IDHash, FoldingSetNodeID &TempID) { + unsigned /*IDHash*/, + FoldingSetNodeID &TempID) { FoldingSetTrait::Profile(X, TempID); return TempID == ID; } @@ -366,7 +367,7 @@ template inline bool DefaultContextualFoldingSetTrait::Equals(T &X, const FoldingSetNodeID &ID, - unsigned IDHash, + unsigned /*IDHash*/, FoldingSetNodeID &TempID, Ctx Context) { ContextualFoldingSetTrait::Profile(X, TempID, Context); diff --git a/contrib/llvm/include/llvm/ADT/ImmutableMap.h b/contrib/llvm/include/llvm/ADT/ImmutableMap.h index a667479a4..8f8fb9877 100644 --- a/contrib/llvm/include/llvm/ADT/ImmutableMap.h +++ b/contrib/llvm/include/llvm/ADT/ImmutableMap.h @@ -211,6 +211,7 @@ public: friend class ImmutableMap; public: + typedef ptrdiff_t difference_type; typedef typename ImmutableMap::value_type value_type; typedef typename ImmutableMap::value_type_ref reference; typedef typename iterator::value_type *pointer; diff --git a/contrib/llvm/include/llvm/ADT/ImmutableSet.h b/contrib/llvm/include/llvm/ADT/ImmutableSet.h index fbdf066e6..ad349699e 100644 --- a/contrib/llvm/include/llvm/ADT/ImmutableSet.h +++ b/contrib/llvm/include/llvm/ADT/ImmutableSet.h @@ -851,6 +851,18 @@ PROFILE_INTEGER_INFO(unsigned long long) #undef PROFILE_INTEGER_INFO +/// Profile traits for booleans. +template <> +struct ImutProfileInfo { + typedef const bool value_type; + typedef const bool& value_type_ref; + + static inline void Profile(FoldingSetNodeID& ID, value_type_ref X) { + ID.AddBoolean(X); + } +}; + + /// Generic profile trait for pointer types. We treat pointers as /// references to unique objects. template @@ -1060,6 +1072,7 @@ public: friend class ImmutableSet; public: + typedef ptrdiff_t difference_type; typedef typename ImmutableSet::value_type value_type; typedef typename ImmutableSet::value_type_ref reference; typedef typename iterator::value_type *pointer; diff --git a/contrib/llvm/include/llvm/ADT/IntervalMap.h b/contrib/llvm/include/llvm/ADT/IntervalMap.h index c4083eed6..1ca3288a3 100644 --- a/contrib/llvm/include/llvm/ADT/IntervalMap.h +++ b/contrib/llvm/include/llvm/ADT/IntervalMap.h @@ -496,7 +496,7 @@ public: NodeRef() {} /// operator bool - Detect a null ref. - operator bool() const { return pip.getOpaqueValue(); } + LLVM_EXPLICIT operator bool() const { return pip.getOpaqueValue(); } /// NodeRef - Create a reference to the node p with n elements. template @@ -612,7 +612,7 @@ public: /// insertFrom - Add mapping of [a;b] to y if possible, coalescing as much as /// possible. This may cause the node to grow by 1, or it may cause the node /// to shrink because of coalescing. -/// @param i Starting index = insertFrom(0, size, a) +/// @param Pos Starting index = insertFrom(0, size, a) /// @param Size Number of elements in node. /// @param a Interval start. /// @param b Interval stop. @@ -1956,7 +1956,7 @@ iterator::eraseNode(unsigned Level) { /// overflow - Distribute entries of the current node evenly among /// its siblings and ensure that the current node is not full. /// This may require allocating a new node. -/// @param NodeT The type of node at Level (Leaf or Branch). +/// @tparam NodeT The type of node at Level (Leaf or Branch). /// @param Level path index of the overflowing node. /// @return True when the tree height was changed. template diff --git a/contrib/llvm/include/llvm/ADT/NullablePtr.h b/contrib/llvm/include/llvm/ADT/NullablePtr.h deleted file mode 100644 index 8ddfd5d20..000000000 --- a/contrib/llvm/include/llvm/ADT/NullablePtr.h +++ /dev/null @@ -1,52 +0,0 @@ -//===- llvm/ADT/NullablePtr.h - A pointer that allows null ------*- 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 and implements the NullablePtr class. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_ADT_NULLABLEPTR_H -#define LLVM_ADT_NULLABLEPTR_H - -#include -#include - -namespace llvm { -/// NullablePtr pointer wrapper - NullablePtr is used for APIs where a -/// potentially-null pointer gets passed around that must be explicitly handled -/// in lots of places. By putting a wrapper around the null pointer, it makes -/// it more likely that the null pointer case will be handled correctly. -template -class NullablePtr { - T *Ptr; -public: - NullablePtr(T *P = 0) : Ptr(P) {} - - bool isNull() const { return Ptr == 0; } - bool isNonNull() const { return Ptr != 0; } - - /// get - Return the pointer if it is non-null. - const T *get() const { - assert(Ptr && "Pointer wasn't checked for null!"); - return Ptr; - } - - /// get - Return the pointer if it is non-null. - T *get() { - assert(Ptr && "Pointer wasn't checked for null!"); - return Ptr; - } - - T *getPtrOrNull() { return Ptr; } - const T *getPtrOrNull() const { return Ptr; } -}; - -} // end namespace llvm - -#endif diff --git a/contrib/llvm/include/llvm/ADT/OwningPtr.h b/contrib/llvm/include/llvm/ADT/OwningPtr.h index 86f9feee2..6b9e42eae 100644 --- a/contrib/llvm/include/llvm/ADT/OwningPtr.h +++ b/contrib/llvm/include/llvm/ADT/OwningPtr.h @@ -70,8 +70,9 @@ public: T *operator->() const { return Ptr; } T *get() const { return Ptr; } - operator bool() const { return Ptr != 0; } + LLVM_EXPLICIT operator bool() const { return Ptr != 0; } bool operator!() const { return Ptr == 0; } + bool isValid() const { return Ptr != 0; } void swap(OwningPtr &RHS) { T *Tmp = RHS.Ptr; @@ -132,7 +133,7 @@ public: } T *get() const { return Ptr; } - operator bool() const { return Ptr != 0; } + LLVM_EXPLICIT operator bool() const { return Ptr != 0; } bool operator!() const { return Ptr == 0; } void swap(OwningArrayPtr &RHS) { diff --git a/contrib/llvm/include/llvm/ADT/PointerIntPair.h b/contrib/llvm/include/llvm/ADT/PointerIntPair.h index 0299a83c4..0cfd47000 100644 --- a/contrib/llvm/include/llvm/ADT/PointerIntPair.h +++ b/contrib/llvm/include/llvm/ADT/PointerIntPair.h @@ -14,6 +14,7 @@ #ifndef LLVM_ADT_POINTERINTPAIR_H #define LLVM_ADT_POINTERINTPAIR_H +#include "llvm/Support/Compiler.h" #include "llvm/Support/PointerLikeTypeTraits.h" #include @@ -40,7 +41,7 @@ template > class PointerIntPair { intptr_t Value; - enum { + enum LLVM_ENUM_INT_TYPE(uintptr_t) { /// PointerBitMask - The bits that come from the pointer. PointerBitMask = ~(uintptr_t)(((intptr_t)1 << PtrTraits::NumLowBitsAvailable)-1), diff --git a/contrib/llvm/include/llvm/ADT/PointerUnion.h b/contrib/llvm/include/llvm/ADT/PointerUnion.h index f42515ac7..05d362fea 100644 --- a/contrib/llvm/include/llvm/ADT/PointerUnion.h +++ b/contrib/llvm/include/llvm/ADT/PointerUnion.h @@ -15,6 +15,7 @@ #ifndef LLVM_ADT_POINTERUNION_H #define LLVM_ADT_POINTERUNION_H +#include "llvm/Support/Compiler.h" #include "llvm/ADT/PointerIntPair.h" namespace llvm { @@ -71,7 +72,7 @@ namespace llvm { /// printf("%d %d", P.is(), P.is()); // prints "1 0" /// X = P.get(); // ok. /// Y = P.get(); // runtime assertion failure. - /// Z = P.get(); // runtime assertion failure (regardless of tag) + /// Z = P.get(); // compile time failure. /// P = (float*)0; /// Y = P.get(); // ok. /// X = P.get(); // runtime assertion failure. @@ -109,7 +110,7 @@ namespace llvm { // we recursively strip off low bits if we have a nested PointerUnion. return !PointerLikeTypeTraits::getFromVoidPointer(Val.getPointer()); } - operator bool() const { return !isNull(); } + LLVM_EXPLICIT operator bool() const { return !isNull(); } /// is() return true if the Union currently holds the type matching T. template @@ -174,7 +175,19 @@ namespace llvm { return V; } }; - + + template + static bool operator==(PointerUnion lhs, + PointerUnion rhs) { + 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 @@ -251,7 +264,7 @@ namespace llvm { /// isNull - Return true if the pointer held in the union is null, /// regardless of which type it is. bool isNull() const { return Val.isNull(); } - operator bool() const { return !isNull(); } + LLVM_EXPLICIT operator bool() const { return !isNull(); } /// is() return true if the Union currently holds the type matching T. template @@ -359,7 +372,7 @@ namespace llvm { /// isNull - Return true if the pointer held in the union is null, /// regardless of which type it is. bool isNull() const { return Val.isNull(); } - operator bool() const { return !isNull(); } + LLVM_EXPLICIT operator bool() const { return !isNull(); } /// is() return true if the Union currently holds the type matching T. template diff --git a/contrib/llvm/include/llvm/ADT/STLExtras.h b/contrib/llvm/include/llvm/ADT/STLExtras.h index dacda3652..3aa818335 100644 --- a/contrib/llvm/include/llvm/ADT/STLExtras.h +++ b/contrib/llvm/include/llvm/ADT/STLExtras.h @@ -217,6 +217,22 @@ inline tier tie(T1& f, T2& s) { return tier(f, s); } +/// \brief Function object to check whether the first component of a std::pair +/// compares less than the first component of another std::pair. +struct less_first { + template bool operator()(const T &lhs, const T &rhs) const { + return lhs.first < rhs.first; + } +}; + +/// \brief Function object to check whether the second component of a std::pair +/// compares less than the second component of another std::pair. +struct less_second { + template bool operator()(const T &lhs, const T &rhs) const { + return lhs.second < rhs.second; + } +}; + //===----------------------------------------------------------------------===// // Extra additions for arrays //===----------------------------------------------------------------------===// @@ -277,12 +293,16 @@ inline void array_pod_sort(IteratorTy Start, IteratorTy End) { get_array_pod_sort_comparator(*Start)); } -template -inline void array_pod_sort(IteratorTy Start, IteratorTy End, - int (*Compare)(const void*, const void*)) { +template +inline void array_pod_sort( + IteratorTy Start, IteratorTy End, + int (*Compare)( + const typename std::iterator_traits::value_type *, + const typename std::iterator_traits::value_type *)) { // Don't dereference start iterator of empty sequence. if (Start == End) return; - qsort(&*Start, End-Start, sizeof(*Start), Compare); + qsort(&*Start, End - Start, sizeof(*Start), + reinterpret_cast(Compare)); } //===----------------------------------------------------------------------===// diff --git a/contrib/llvm/include/llvm/ADT/SetVector.h b/contrib/llvm/include/llvm/ADT/SetVector.h index d2f7286c2..5eda37c67 100644 --- a/contrib/llvm/include/llvm/ADT/SetVector.h +++ b/contrib/llvm/include/llvm/ADT/SetVector.h @@ -170,7 +170,7 @@ public: vector_.pop_back(); } - T pop_back_val() { + T LLVM_ATTRIBUTE_UNUSED_RESULT pop_back_val() { T Ret = back(); pop_back(); return Ret; diff --git a/contrib/llvm/include/llvm/ADT/SmallBitVector.h b/contrib/llvm/include/llvm/ADT/SmallBitVector.h index 652492a15..86949b2ae 100644 --- a/contrib/llvm/include/llvm/ADT/SmallBitVector.h +++ b/contrib/llvm/include/llvm/ADT/SmallBitVector.h @@ -216,9 +216,9 @@ public: if (Bits == 0) return -1; if (NumBaseBits == 32) - return CountTrailingZeros_32(Bits); + return countTrailingZeros(Bits); if (NumBaseBits == 64) - return CountTrailingZeros_64(Bits); + return countTrailingZeros(Bits); llvm_unreachable("Unsupported!"); } return getPointer()->find_first(); @@ -234,9 +234,9 @@ public: if (Bits == 0 || Prev + 1 >= getSmallSize()) return -1; if (NumBaseBits == 32) - return CountTrailingZeros_32(Bits); + return countTrailingZeros(Bits); if (NumBaseBits == 64) - return CountTrailingZeros_64(Bits); + return countTrailingZeros(Bits); llvm_unreachable("Unsupported!"); } return getPointer()->find_next(Prev); @@ -426,6 +426,40 @@ public: return *this; } + /// reset - Reset bits that are set in RHS. Same as *this &= ~RHS. + SmallBitVector &reset(const SmallBitVector &RHS) { + if (isSmall() && RHS.isSmall()) + setSmallBits(getSmallBits() & ~RHS.getSmallBits()); + else if (!isSmall() && !RHS.isSmall()) + getPointer()->reset(*RHS.getPointer()); + else + for (unsigned i = 0, e = std::min(size(), RHS.size()); i != e; ++i) + if (RHS.test(i)) + reset(i); + + return *this; + } + + /// test - Check if (This - RHS) is zero. + /// This is the same as reset(RHS) and any(). + bool test(const SmallBitVector &RHS) const { + if (isSmall() && RHS.isSmall()) + return (getSmallBits() & ~RHS.getSmallBits()) != 0; + if (!isSmall() && !RHS.isSmall()) + return getPointer()->test(*RHS.getPointer()); + + unsigned i, e; + for (i = 0, e = std::min(size(), RHS.size()); i != e; ++i) + if (test(i) && !RHS.test(i)) + return true; + + for (e = size(); i != e; ++i) + if (test(i)) + return true; + + return false; + } + SmallBitVector &operator|=(const SmallBitVector &RHS) { resize(std::max(size(), RHS.size())); if (isSmall()) diff --git a/contrib/llvm/include/llvm/ADT/SmallPtrSet.h b/contrib/llvm/include/llvm/ADT/SmallPtrSet.h index 8c7304197..bd0d8838e 100644 --- a/contrib/llvm/include/llvm/ADT/SmallPtrSet.h +++ b/contrib/llvm/include/llvm/ADT/SmallPtrSet.h @@ -71,7 +71,7 @@ protected: ~SmallPtrSetImpl(); public: - bool empty() const { return size() == 0; } + bool LLVM_ATTRIBUTE_UNUSED_RESULT empty() const { return size() == 0; } unsigned size() const { return NumElements; } void clear() { diff --git a/contrib/llvm/include/llvm/ADT/SmallVector.h b/contrib/llvm/include/llvm/ADT/SmallVector.h index 7ba0a714b..505aa8d8a 100644 --- a/contrib/llvm/include/llvm/ADT/SmallVector.h +++ b/contrib/llvm/include/llvm/ADT/SmallVector.h @@ -53,7 +53,7 @@ public: return size_t((char*)CapacityX - (char*)BeginX); } - bool empty() const { return BeginX == EndX; } + bool LLVM_ATTRIBUTE_UNUSED_RESULT empty() const { return BeginX == EndX; } }; template struct SmallVectorStorage; @@ -427,7 +427,7 @@ public: this->grow(N); } - T pop_back_val() { + T LLVM_ATTRIBUTE_UNUSED_RESULT pop_back_val() { #if LLVM_HAS_RVALUE_REFERENCES T Result = ::std::move(this->back()); #else diff --git a/contrib/llvm/include/llvm/ADT/SparseBitVector.h b/contrib/llvm/include/llvm/ADT/SparseBitVector.h index 306e92832..7a10f8570 100644 --- a/contrib/llvm/include/llvm/ADT/SparseBitVector.h +++ b/contrib/llvm/include/llvm/ADT/SparseBitVector.h @@ -137,9 +137,9 @@ public: for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i) if (Bits[i] != 0) { if (sizeof(BitWord) == 4) - return i * BITWORD_SIZE + CountTrailingZeros_32(Bits[i]); + return i * BITWORD_SIZE + countTrailingZeros(Bits[i]); if (sizeof(BitWord) == 8) - return i * BITWORD_SIZE + CountTrailingZeros_64(Bits[i]); + return i * BITWORD_SIZE + countTrailingZeros(Bits[i]); llvm_unreachable("Unsupported!"); } llvm_unreachable("Illegal empty element"); @@ -162,9 +162,9 @@ public: if (Copy != 0) { if (sizeof(BitWord) == 4) - return WordPos * BITWORD_SIZE + CountTrailingZeros_32(Copy); + return WordPos * BITWORD_SIZE + countTrailingZeros(Copy); if (sizeof(BitWord) == 8) - return WordPos * BITWORD_SIZE + CountTrailingZeros_64(Copy); + return WordPos * BITWORD_SIZE + countTrailingZeros(Copy); llvm_unreachable("Unsupported!"); } @@ -172,9 +172,9 @@ public: for (unsigned i = WordPos+1; i < BITWORDS_PER_ELEMENT; ++i) if (Bits[i] != 0) { if (sizeof(BitWord) == 4) - return i * BITWORD_SIZE + CountTrailingZeros_32(Bits[i]); + return i * BITWORD_SIZE + countTrailingZeros(Bits[i]); if (sizeof(BitWord) == 8) - return i * BITWORD_SIZE + CountTrailingZeros_64(Bits[i]); + return i * BITWORD_SIZE + countTrailingZeros(Bits[i]); llvm_unreachable("Unsupported!"); } return -1; diff --git a/contrib/llvm/include/llvm/ADT/StringExtras.h b/contrib/llvm/include/llvm/ADT/StringExtras.h index d2887c5c2..56dbb5b80 100644 --- a/contrib/llvm/include/llvm/ADT/StringExtras.h +++ b/contrib/llvm/include/llvm/ADT/StringExtras.h @@ -14,6 +14,7 @@ #ifndef LLVM_ADT_STRINGEXTRAS_H #define LLVM_ADT_STRINGEXTRAS_H +#include #include "llvm/ADT/StringRef.h" #include "llvm/Support/DataTypes.h" @@ -159,6 +160,48 @@ static inline StringRef getOrdinalSuffix(unsigned Val) { } } +template +inline std::string join_impl(IteratorT Begin, IteratorT End, + StringRef Separator, std::input_iterator_tag) { + std::string S; + if (Begin == End) + return S; + + S += (*Begin); + while (++Begin != End) { + S += Separator; + S += (*Begin); + } + return S; +} + +template +inline std::string join_impl(IteratorT Begin, IteratorT End, + StringRef Separator, std::forward_iterator_tag) { + std::string S; + if (Begin == End) + return S; + + size_t Len = (std::distance(Begin, End) - 1) * Separator.size(); + for (IteratorT I = Begin; I != End; ++I) + Len += (*Begin).size(); + S.reserve(Len); + S += (*Begin); + while (++Begin != End) { + S += Separator; + S += (*Begin); + } + return S; +} + +/// Joins the strings in the range [Begin, End), adding Separator between +/// the elements. +template +inline std::string join(IteratorT Begin, IteratorT End, StringRef Separator) { + typedef typename std::iterator_traits::iterator_category tag; + return join_impl(Begin, End, Separator, tag()); +} + } // End llvm namespace #endif diff --git a/contrib/llvm/include/llvm/ADT/StringMap.h b/contrib/llvm/include/llvm/ADT/StringMap.h index d01437b61..0838ebe91 100644 --- a/contrib/llvm/include/llvm/ADT/StringMap.h +++ b/contrib/llvm/include/llvm/ADT/StringMap.h @@ -102,6 +102,13 @@ public: bool empty() const { return NumItems == 0; } unsigned size() const { return NumItems; } + + void swap(StringMapImpl &Other) { + std::swap(TheTable, Other.TheTable); + std::swap(NumBuckets, Other.NumBuckets); + std::swap(NumItems, Other.NumItems); + std::swap(NumTombstones, Other.NumTombstones); + } }; /// StringMapEntry - This is used to represent one value that is inserted into @@ -109,6 +116,7 @@ public: /// and data. template class StringMapEntry : public StringMapEntryBase { + StringMapEntry(StringMapEntry &E) LLVM_DELETED_FUNCTION; public: ValueTy second; @@ -409,6 +417,8 @@ protected: public: typedef StringMapEntry value_type; + StringMapConstIterator() : Ptr(0) { } + explicit StringMapConstIterator(StringMapEntryBase **Bucket, bool NoAdvance = false) : Ptr(Bucket) { @@ -448,6 +458,7 @@ private: template class StringMapIterator : public StringMapConstIterator { public: + StringMapIterator() {} explicit StringMapIterator(StringMapEntryBase **Bucket, bool NoAdvance = false) : StringMapConstIterator(Bucket, NoAdvance) { diff --git a/contrib/llvm/include/llvm/ADT/StringRef.h b/contrib/llvm/include/llvm/ADT/StringRef.h index d013d0562..ec0c2849f 100644 --- a/contrib/llvm/include/llvm/ADT/StringRef.h +++ b/contrib/llvm/include/llvm/ADT/StringRef.h @@ -19,7 +19,7 @@ #include namespace llvm { - template + template class SmallVectorImpl; class APInt; class hash_code; @@ -175,7 +175,7 @@ namespace llvm { /// transform one of the given strings into the other. If zero, /// the strings are identical. unsigned edit_distance(StringRef Other, bool AllowReplacements = true, - unsigned MaxEditDistance = 0); + unsigned MaxEditDistance = 0) const; /// str - Get the contents as an std::string. std::string str() const { @@ -210,12 +210,18 @@ namespace llvm { compareMemory(Data, Prefix.Data, Prefix.Length) == 0; } + /// Check if this string starts with the given \p Prefix, ignoring case. + bool startswith_lower(StringRef Prefix) const; + /// Check if this string ends with the given \p Suffix. bool endswith(StringRef Suffix) const { return Length >= Suffix.Length && compareMemory(end() - Suffix.Length, Suffix.Data, Suffix.Length) == 0; } + /// Check if this string ends with the given \p Suffix, ignoring case. + bool endswith_lower(StringRef Suffix) const; + /// @} /// @name String Searching /// @{ @@ -548,6 +554,10 @@ namespace llvm { template struct isPodLike; template <> struct isPodLike { static const bool value = true; }; + /// Construct a string ref from a boolean. + inline StringRef toStringRef(bool B) { + return StringRef(B ? "true" : "false"); + } } #endif diff --git a/contrib/llvm/include/llvm/ADT/Triple.h b/contrib/llvm/include/llvm/ADT/Triple.h index 3a72e8704..84e0b29d1 100644 --- a/contrib/llvm/include/llvm/ADT/Triple.h +++ b/contrib/llvm/include/llvm/ADT/Triple.h @@ -14,30 +14,33 @@ // Some system headers or GCC predefined macros conflict with identifiers in // this file. Undefine them here. +#undef NetBSD #undef mips #undef sparc namespace llvm { -/// Triple - Helper class for working with target triples. +/// Triple - Helper class for working with autoconf configuration names. For +/// historical reasons, we also call these 'triples' (they used to contain +/// exactly three fields). /// -/// Target triples are strings in the canonical form: +/// Configuration names are strings in the canonical form: /// ARCHITECTURE-VENDOR-OPERATING_SYSTEM /// or /// ARCHITECTURE-VENDOR-OPERATING_SYSTEM-ENVIRONMENT /// /// This class is used for clients which want to support arbitrary -/// target triples, but also want to implement certain special -/// behavior for particular targets. This class isolates the mapping -/// from the components of the target triple to well known IDs. +/// configuration names, but also want to implement certain special +/// behavior for particular configurations. This class isolates the mapping +/// from the components of the configuration name to well known IDs. /// /// At its core the Triple class is designed to be a wrapper for a triple /// string; the constructor does not change or normalize the triple string. /// Clients that need to handle the non-canonical triples that users often /// specify should use the normalize method. /// -/// See autoconf/config.guess for a glimpse into what triples look like in -/// practice. +/// See autoconf/config.guess for a glimpse into what configuration names +/// look like in practice. class Triple { public: enum ArchType { @@ -53,6 +56,7 @@ public: msp430, // MSP430: msp430 ppc, // PPC: powerpc ppc64, // PPC64: powerpc64, ppu + ppc64le, // PPC64LE: powerpc64le r600, // R600: AMD GPUs HD2XXX - HD6XXX sparc, // Sparc: sparc sparcv9, // Sparcv9: Sparcv9 @@ -62,7 +66,6 @@ public: x86, // X86: i[3-9]86 x86_64, // X86-64: amd64, x86_64 xcore, // XCore: xcore - mblaze, // MBlaze: mblaze nvptx, // NVPTX: 32-bit nvptx64, // NVPTX: 64-bit le32, // le32: generic little-endian 32-bit CPU (PNaCl / Emscripten) @@ -79,7 +82,8 @@ public: BGP, BGQ, Freescale, - IBM + IBM, + NVIDIA }; enum OSType { UnknownOS, @@ -105,7 +109,9 @@ public: NaCl, // Native Client CNK, // BG/P Compute-Node Kernel Bitrig, - AIX + AIX, + CUDA, // NVIDIA CUDA + NVCL // NVIDIA OpenCL }; enum EnvironmentType { UnknownEnvironment, @@ -313,7 +319,12 @@ public: return getOS() == Triple::Cygwin || getOS() == Triple::MinGW32; } - /// isOSWindows - Is this a "Windows" OS. + /// \brief Is this a "Windows" OS targeting a "MSVCRT.dll" environment. + bool isOSMSVCRT() const { + return getOS() == Triple::Win32 || getOS() == Triple::MinGW32; + } + + /// \brief Tests whether the OS is Windows. bool isOSWindows() const { return getOS() == Triple::Win32 || isOSCygMing(); } @@ -323,6 +334,11 @@ public: return getOS() == Triple::NaCl; } + /// \brief Tests whether the OS is Linux. + bool isOSLinux() const { + return getOS() == Triple::Linux; + } + /// \brief Tests whether the OS uses the ELF binary format. bool isOSBinFormatELF() const { return !isOSDarwin() && !isOSWindows(); diff --git a/contrib/llvm/include/llvm/ADT/ilist.h b/contrib/llvm/include/llvm/ADT/ilist.h index 71dab2ef5..6aeaa91f1 100644 --- a/contrib/llvm/include/llvm/ADT/ilist.h +++ b/contrib/llvm/include/llvm/ADT/ilist.h @@ -382,7 +382,9 @@ public: // Miscellaneous inspection routines. size_type max_size() const { return size_type(-1); } - bool empty() const { return Head == 0 || Head == getTail(); } + bool LLVM_ATTRIBUTE_UNUSED_RESULT empty() const { + return Head == 0 || Head == getTail(); + } // Front and back accessor functions... reference front() { @@ -534,7 +536,7 @@ public: // Functionality derived from other functions defined above... // - size_type size() const { + size_type LLVM_ATTRIBUTE_UNUSED_RESULT size() const { if (Head == 0) return 0; // Don't require construction of sentinel if empty. return std::distance(begin(), end()); } diff --git a/contrib/llvm/include/llvm/ADT/polymorphic_ptr.h b/contrib/llvm/include/llvm/ADT/polymorphic_ptr.h new file mode 100644 index 000000000..b8d8d7123 --- /dev/null +++ b/contrib/llvm/include/llvm/ADT/polymorphic_ptr.h @@ -0,0 +1,117 @@ +//===- llvm/ADT/polymorphic_ptr.h - Smart copyable owned ptr ----*- 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 polymorphic_ptr class template. See the class comments +/// for details about this API, its intended use cases, etc. +/// +/// The primary motivation here is to work around the necessity of copy +/// semantics in C++98. This is typically used where any actual copies are +/// incidental or unnecessary. As a consequence, it is expected to cease to be +/// useful and be removed when we can directly rely on move-only types. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_POLYMORPHIC_PTR_H +#define LLVM_ADT_POLYMORPHIC_PTR_H + +#include "llvm/Support/Compiler.h" + +namespace llvm { + +/// \brief An owning, copyable polymorphic smart pointer. +/// +/// This pointer exists to provide copyable owned smart pointer. Rather than +/// shared ownership semantics, it has unique ownership semantics and deep copy +/// semantics. It is copyable by requiring that the underlying type exposes +/// a method which can produce a (heap allocated) clone. +/// +/// Note that in almost all scenarios use of this could be avoided if we could +/// build move-only containers of a std::unique_ptr, but until then this +/// provides an effective way to place polymorphic objects in a container. +template class polymorphic_ptr { + T *ptr; + +public: + polymorphic_ptr(T *ptr = 0) : ptr(ptr) {} + polymorphic_ptr(const polymorphic_ptr &arg) : ptr(arg ? arg->clone() : 0) {} +#if LLVM_HAS_RVALUE_REFERENCES + polymorphic_ptr(polymorphic_ptr &&arg) : ptr(arg.take()) {} +#endif + ~polymorphic_ptr() { delete ptr; } + + polymorphic_ptr &operator=(polymorphic_ptr arg) { + swap(arg); + return *this; + } + polymorphic_ptr &operator=(T *arg) { + if (arg != ptr) { + delete ptr; + ptr = arg; + } + return *this; + } + + T &operator*() const { return *ptr; } + T *operator->() const { return ptr; } + LLVM_EXPLICIT operator bool() const { return ptr != 0; } + bool operator!() const { return ptr == 0; } + + T *get() const { return ptr; } + + T *take() { + T *tmp = ptr; + ptr = 0; + return tmp; + } + + void swap(polymorphic_ptr &arg) { + T *tmp = ptr; + ptr = arg.ptr; + arg.ptr = tmp; + } +}; + +template +void swap(polymorphic_ptr &lhs, polymorphic_ptr &rhs) { + lhs.swap(rhs); +} + +template +bool operator==(const polymorphic_ptr &lhs, const polymorphic_ptr &rhs) { + return lhs.get() == rhs.get(); +} + +template +bool operator!=(const polymorphic_ptr &lhs, const polymorphic_ptr &rhs) { + return lhs.get() != rhs.get(); +} + +template +bool operator==(const polymorphic_ptr &lhs, U *rhs) { + return lhs.get() == rhs; +} + +template +bool operator!=(const polymorphic_ptr &lhs, U *rhs) { + return lhs.get() != rhs; +} + +template +bool operator==(T *lhs, const polymorphic_ptr &rhs) { + return lhs == rhs.get(); +} + +template +bool operator!=(T *lhs, const polymorphic_ptr &rhs) { + return lhs != rhs.get(); +} + +} + +#endif diff --git a/contrib/llvm/include/llvm/Analysis/AliasAnalysis.h b/contrib/llvm/include/llvm/Analysis/AliasAnalysis.h index d703f21c0..efafbbdb7 100644 --- a/contrib/llvm/include/llvm/Analysis/AliasAnalysis.h +++ b/contrib/llvm/include/llvm/Analysis/AliasAnalysis.h @@ -584,6 +584,10 @@ struct DenseMapInfo { /// function. bool isNoAliasCall(const Value *V); +/// isNoAliasArgument - Return true if this is an argument with the noalias +/// attribute. +bool isNoAliasArgument(const Value *V); + /// isIdentifiedObject - Return true if this pointer refers to a distinct and /// identifiable object. This returns true for: /// Global Variables and Functions (but not Global Aliases) diff --git a/contrib/llvm/include/llvm/Analysis/BlockFrequencyImpl.h b/contrib/llvm/include/llvm/Analysis/BlockFrequencyImpl.h index b3e2d18eb..817a44188 100644 --- a/contrib/llvm/include/llvm/Analysis/BlockFrequencyImpl.h +++ b/contrib/llvm/include/llvm/Analysis/BlockFrequencyImpl.h @@ -1,4 +1,4 @@ -//===---- BlockFrequencyImpl.h - Machine Block Frequency Implementation ---===// +//===-- BlockFrequencyImpl.h - Block Frequency Implementation --*- C++ -*--===// // // The LLVM Compiler Infrastructure // @@ -33,7 +33,7 @@ class BlockFrequencyInfo; class MachineBlockFrequencyInfo; /// BlockFrequencyImpl implements block frequency algorithm for IR and -/// Machine Instructions. Algorithm starts with value 1024 (START_FREQ) +/// Machine Instructions. Algorithm starts with value ENTRY_FREQ /// for the entry block and then propagates frequencies using branch weights /// from (Machine)BranchProbabilityInfo. LoopInfo is not required because /// algorithm can find "backedges" by itself. @@ -85,31 +85,16 @@ class BlockFrequencyImpl { << " --> " << Freqs[BB] << "\n"); } - /// divBlockFreq - Divide BB block frequency by PROB. If Prob = 0 do nothing. - /// - void divBlockFreq(BlockT *BB, BranchProbability Prob) { - uint64_t N = Prob.getNumerator(); - assert(N && "Illegal division by zero!"); - uint64_t D = Prob.getDenominator(); - uint64_t Freq = (Freqs[BB].getFrequency() * D) / N; - - // Should we assert it? - if (Freq > UINT32_MAX) - Freq = UINT32_MAX; - - Freqs[BB] = BlockFrequency(Freq); - DEBUG(dbgs() << "Frequency(" << getBlockName(BB) << ") /= (" << Prob - << ") --> " << Freqs[BB] << "\n"); - } - // All blocks in postorder. std::vector POT; // Map Block -> Position in reverse-postorder list. DenseMap RPO; - // Cycle Probability for each bloch. - DenseMap CycleProb; + // For each loop header, record the per-iteration probability of exiting the + // loop. This is the reciprocal of the expected number of loop iterations. + typedef DenseMap LoopExitProbMap; + LoopExitProbMap LoopExitProb; // (reverse-)postorder traversal iterators. typedef typename std::vector::iterator pot_iterator; @@ -123,7 +108,7 @@ class BlockFrequencyImpl { rpot_iterator rpot_at(BlockT *BB) { rpot_iterator I = rpot_begin(); - unsigned idx = RPO[BB]; + unsigned idx = RPO.lookup(BB); assert(idx); std::advance(I, idx - 1); @@ -131,22 +116,14 @@ class BlockFrequencyImpl { return I; } - - /// isReachable - Returns if BB block is reachable from the entry. - /// - bool isReachable(BlockT *BB) { - return RPO.count(BB); - } - - /// isBackedge - Return if edge Src -> Dst is a backedge. + /// isBackedge - Return if edge Src -> Dst is a reachable backedge. /// - bool isBackedge(BlockT *Src, BlockT *Dst) { - assert(isReachable(Src)); - assert(isReachable(Dst)); - - unsigned a = RPO[Src]; - unsigned b = RPO[Dst]; - + bool isBackedge(BlockT *Src, BlockT *Dst) const { + unsigned a = RPO.lookup(Src); + if (!a) + return false; + unsigned b = RPO.lookup(Dst); + assert(b && "Destination block should be reachable"); return a >= b; } @@ -196,7 +173,7 @@ class BlockFrequencyImpl { PI != PE; ++PI) { BlockT *Pred = *PI; - if (isReachable(Pred) && isBackedge(Pred, BB)) { + if (isBackedge(Pred, BB)) { isLoopHead = true; } else if (BlocksInLoop.count(Pred)) { incBlockFreq(BB, getEdgeFreq(Pred, BB)); @@ -211,10 +188,13 @@ class BlockFrequencyImpl { if (!isLoopHead) return; - assert(EntryFreq >= CycleProb[BB]); - uint32_t CProb = CycleProb[BB]; - uint32_t Numerator = EntryFreq - CProb ? EntryFreq - CProb : 1; - divBlockFreq(BB, BranchProbability(Numerator, EntryFreq)); + // This block is a loop header, so boost its frequency by the expected + // number of loop iterations. The loop blocks will be revisited so they all + // get this boost. + typename LoopExitProbMap::const_iterator I = LoopExitProb.find(BB); + assert(I != LoopExitProb.end() && "Loop header missing from table"); + Freqs[BB] /= I->second; + DEBUG(dbgs() << "Loop header scaled to " << Freqs[BB] << ".\n"); } /// doLoop - Propagate block frequency down through the loop. @@ -234,24 +214,50 @@ class BlockFrequencyImpl { } // Compute loop's cyclic probability using backedges probabilities. + BlockFrequency BackFreq; for (typename GT::ChildIteratorType PI = GraphTraits< Inverse >::child_begin(Head), PE = GraphTraits< Inverse >::child_end(Head); PI != PE; ++PI) { BlockT *Pred = *PI; assert(Pred); - if (isReachable(Pred) && isBackedge(Pred, Head)) { - uint64_t N = getEdgeFreq(Pred, Head).getFrequency(); - uint64_t D = getBlockFreq(Head).getFrequency(); - assert(N <= EntryFreq && "Backedge frequency must be <= EntryFreq!"); - uint64_t Res = (N * EntryFreq) / D; - - assert(Res <= UINT32_MAX); - CycleProb[Head] += (uint32_t) Res; - DEBUG(dbgs() << " CycleProb[" << getBlockName(Head) << "] += " << Res - << " --> " << CycleProb[Head] << "\n"); - } + if (isBackedge(Pred, Head)) + BackFreq += getEdgeFreq(Pred, Head); + } + + // The cyclic probability is freq(BackEdges) / freq(Head), where freq(Head) + // only counts edges entering the loop, not the loop backedges. + // The probability of leaving the loop on each iteration is: + // + // ExitProb = 1 - CyclicProb + // + // The Expected number of loop iterations is: + // + // Iterations = 1 / ExitProb + // + uint64_t D = std::max(getBlockFreq(Head).getFrequency(), UINT64_C(1)); + uint64_t N = std::max(BackFreq.getFrequency(), UINT64_C(1)); + if (N < D) + N = D - N; + else + // We'd expect N < D, but rounding and saturation means that can't be + // guaranteed. + N = 1; + + // Now ExitProb = N / D, make sure it fits in an i32/i32 fraction. + assert(N <= D); + if (D > UINT32_MAX) { + unsigned Shift = 32 - countLeadingZeros(D); + D >>= Shift; + N >>= Shift; + if (N == 0) + N = 1; } + BranchProbability LEP = BranchProbability(N, D); + LoopExitProb.insert(std::make_pair(Head, LEP)); + DEBUG(dbgs() << "LoopExitProb[" << getBlockName(Head) << "] = " << LEP + << " from 1 - " << BackFreq << " / " << getBlockFreq(Head) + << ".\n"); } friend class BlockFrequencyInfo; @@ -266,7 +272,7 @@ class BlockFrequencyImpl { // Clear everything. RPO.clear(); POT.clear(); - CycleProb.clear(); + LoopExitProb.clear(); Freqs.clear(); BlockT *EntryBlock = fn->begin(); @@ -292,8 +298,7 @@ class BlockFrequencyImpl { PI != PE; ++PI) { BlockT *Pred = *PI; - if (isReachable(Pred) && isBackedge(Pred, BB) - && (!LastTail || RPO[Pred] > RPO[LastTail])) + if (isBackedge(Pred, BB) && (!LastTail || RPO[Pred] > RPO[LastTail])) LastTail = Pred; } diff --git a/contrib/llvm/include/llvm/Analysis/BlockFrequencyInfo.h b/contrib/llvm/include/llvm/Analysis/BlockFrequencyInfo.h index fcab90677..a123d0b8c 100644 --- a/contrib/llvm/include/llvm/Analysis/BlockFrequencyInfo.h +++ b/contrib/llvm/include/llvm/Analysis/BlockFrequencyInfo.h @@ -1,4 +1,4 @@ -//========-------- BlockFrequencyInfo.h - Block Frequency Analysis -------========// +//===------- BlockFrequencyInfo.h - Block Frequency Analysis --*- C++ -*---===// // // The LLVM Compiler Infrastructure // @@ -41,12 +41,14 @@ public: bool runOnFunction(Function &F); void print(raw_ostream &O, const Module *M) const; + const Function *getFunction() const; + void view() const; /// getblockFreq - Return block frequency. Return 0 if we don't have the - /// information. Please note that initial frequency is equal to 1024. It means - /// that we should not rely on the value itself, but only on the comparison to - /// the other block frequencies. We do this to avoid using of floating points. - /// + /// information. Please note that initial frequency is equal to ENTRY_FREQ. It + /// means that we should not rely on the value itself, but only on the + /// comparison to the other block frequencies. We do this to avoid using of + /// floating points. BlockFrequency getBlockFreq(const BasicBlock *BB) const; }; diff --git a/contrib/llvm/include/llvm/Analysis/BranchProbabilityInfo.h b/contrib/llvm/include/llvm/Analysis/BranchProbabilityInfo.h index 6c23f7c3a..4ff712172 100644 --- a/contrib/llvm/include/llvm/Analysis/BranchProbabilityInfo.h +++ b/contrib/llvm/include/llvm/Analysis/BranchProbabilityInfo.h @@ -131,11 +131,15 @@ private: /// \brief Track the set of blocks directly succeeded by a returning block. SmallPtrSet PostDominatedByUnreachable; + /// \brief Track the set of blocks that always lead to a cold call. + SmallPtrSet PostDominatedByColdCall; + /// \brief Get sum of the block successors' weights. uint32_t getSumForBlock(const BasicBlock *BB) const; bool calcUnreachableHeuristics(BasicBlock *BB); bool calcMetadataWeights(BasicBlock *BB); + bool calcColdCallHeuristics(BasicBlock *BB); bool calcPointerHeuristics(BasicBlock *BB); bool calcLoopBranchHeuristics(BasicBlock *BB); bool calcZeroHeuristics(BasicBlock *BB); diff --git a/contrib/llvm/include/llvm/Analysis/CFG.h b/contrib/llvm/include/llvm/Analysis/CFG.h new file mode 100644 index 000000000..e5683c8e5 --- /dev/null +++ b/contrib/llvm/include/llvm/Analysis/CFG.h @@ -0,0 +1,83 @@ +//===-- Analysis/CFG.h - BasicBlock Analyses --------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This family of functions performs analyses on basic blocks, and instructions +// contained within basic blocks. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_CFG_H +#define LLVM_ANALYSIS_CFG_H + +#include "llvm/IR/BasicBlock.h" +#include "llvm/Support/CFG.h" + +namespace llvm { + +class BasicBlock; +class DominatorTree; +class Function; +class Instruction; +class LoopInfo; +class TerminatorInst; + +/// Analyze the specified function to find all of the loop backedges in the +/// function and return them. This is a relatively cheap (compared to +/// computing dominators and loop info) analysis. +/// +/// The output is added to Result, as pairs of edge info. +void FindFunctionBackedges( + const Function &F, + SmallVectorImpl > & + Result); + +/// Search for the specified successor of basic block BB and return its position +/// in the terminator instruction's list of successors. It is an error to call +/// this with a block that is not a successor. +unsigned GetSuccessorNumber(BasicBlock *BB, BasicBlock *Succ); + +/// Return true if the specified edge is a critical edge. Critical edges are +/// edges from a block with multiple successors to a block with multiple +/// predecessors. +/// +bool isCriticalEdge(const TerminatorInst *TI, unsigned SuccNum, + bool AllowIdenticalEdges = false); + +/// \brief Determine whether instruction 'To' is reachable from 'From', +/// returning true if uncertain. +/// +/// Determine whether there is a path from From to To within a single function. +/// Returns false only if we can prove that once 'From' has been executed then +/// 'To' can not be executed. Conservatively returns true. +/// +/// This function is linear with respect to the number of blocks in the CFG, +/// walking down successors from From to reach To, with a fixed threshold. +/// Using DT or LI allows us to answer more quickly. LI reduces the cost of +/// an entire loop of any number of blocsk to be the same as the cost of a +/// single block. DT reduces the cost by allowing the search to terminate when +/// we find a block that dominates the block containing 'To'. DT is most useful +/// on branchy code but not loops, and LI is most useful on code with loops but +/// does not help on branchy code outside loops. +bool isPotentiallyReachable(const Instruction *From, const Instruction *To, + const DominatorTree *DT = 0, + const LoopInfo *LI = 0); + +/// \brief Determine whether block 'To' is reachable from 'From', returning +/// true if uncertain. +/// +/// Determine whether there is a path from From to To within a single function. +/// Returns false only if we can prove that once 'From' has been reached then +/// 'To' can not be executed. Conservatively returns true. +bool isPotentiallyReachable(const BasicBlock *From, const BasicBlock *To, + const DominatorTree *DT = 0, + const LoopInfo *LI = 0); + +} // End llvm namespace + +#endif diff --git a/contrib/llvm/include/llvm/Analysis/CFGPrinter.h b/contrib/llvm/include/llvm/Analysis/CFGPrinter.h index fa596c3a3..39e90eb96 100644 --- a/contrib/llvm/include/llvm/Analysis/CFGPrinter.h +++ b/contrib/llvm/include/llvm/Analysis/CFGPrinter.h @@ -44,8 +44,9 @@ struct DOTGraphTraits : public DefaultDOTGraphTraits { return OS.str(); } - static std::string getCompleteNodeLabel(const BasicBlock *Node, + static std::string getCompleteNodeLabel(const BasicBlock *Node, const Function *) { + enum { MaxColumns = 80 }; std::string Str; raw_string_ostream OS(Str); @@ -59,16 +60,32 @@ struct DOTGraphTraits : public DefaultDOTGraphTraits { if (OutStr[0] == '\n') OutStr.erase(OutStr.begin()); // Process string output to make it nicer... - for (unsigned i = 0; i != OutStr.length(); ++i) + unsigned ColNum = 0; + unsigned LastSpace = 0; + for (unsigned i = 0; i != OutStr.length(); ++i) { if (OutStr[i] == '\n') { // Left justify OutStr[i] = '\\'; OutStr.insert(OutStr.begin()+i+1, 'l'); + ColNum = 0; + LastSpace = 0; } else if (OutStr[i] == ';') { // Delete comments! unsigned Idx = OutStr.find('\n', i+1); // Find end of line OutStr.erase(OutStr.begin()+i, OutStr.begin()+Idx); --i; + } else if (ColNum == MaxColumns) { // Wrap lines. + if (LastSpace) { + OutStr.insert(LastSpace, "\\l..."); + ColNum = i - LastSpace; + LastSpace = 0; + i += 3; // The loop will advance 'i' again. + } + // Else keep trying to find a space. } - + else + ++ColNum; + if (OutStr[i] == ' ') + LastSpace = i; + } return OutStr; } @@ -86,20 +103,20 @@ struct DOTGraphTraits : public DefaultDOTGraphTraits { if (const BranchInst *BI = dyn_cast(Node->getTerminator())) if (BI->isConditional()) return (I == succ_begin(Node)) ? "T" : "F"; - + // Label source of switch edges with the associated value. if (const SwitchInst *SI = dyn_cast(Node->getTerminator())) { unsigned SuccNo = I.getSuccessorIndex(); if (SuccNo == 0) return "def"; - + std::string Str; raw_string_ostream OS(Str); SwitchInst::ConstCaseIt Case = - SwitchInst::ConstCaseIt::fromSuccessorIndex(SI, SuccNo); + SwitchInst::ConstCaseIt::fromSuccessorIndex(SI, SuccNo); OS << Case.getCaseValue()->getValue(); return OS.str(); - } + } return ""; } }; diff --git a/contrib/llvm/include/llvm/Analysis/CallGraph.h b/contrib/llvm/include/llvm/Analysis/CallGraph.h index 591484dd2..d00c2ed32 100644 --- a/contrib/llvm/include/llvm/Analysis/CallGraph.h +++ b/contrib/llvm/include/llvm/Analysis/CallGraph.h @@ -69,13 +69,36 @@ class CallGraphNode; //===----------------------------------------------------------------------===// // CallGraph class definition // -class CallGraph { -protected: +class CallGraph : public ModulePass { Module *Mod; // The module this call graph represents typedef std::map FunctionMapTy; FunctionMapTy FunctionMap; // Map from a function to its node + // Root is root of the call graph, or the external node if a 'main' function + // couldn't be found. + // + CallGraphNode *Root; + + // ExternalCallingNode - This node has edges to all external functions and + // those internal functions that have their address taken. + CallGraphNode *ExternalCallingNode; + + // CallsExternalNode - This node has edges to it from all functions making + // indirect calls or calling an external function. + CallGraphNode *CallsExternalNode; + + /// Replace the function represented by this node by another. + /// This does not rescan the body of the function, so it is suitable when + /// splicing the body of one function to another while also updating all + /// callers from the old function to the new. + /// + void spliceFunction(const Function *From, const Function *To); + + // Add a function to the call graph, and link the node to all of the functions + // that it calls. + void addToCallGraph(Function *F); + public: static char ID; // Class identification, replacement for typeinfo //===--------------------------------------------------------------------- @@ -107,15 +130,14 @@ public: } /// Returns the CallGraphNode which is used to represent undetermined calls - /// into the callgraph. Override this if you want behavioral inheritance. - virtual CallGraphNode* getExternalCallingNode() const { return 0; } - virtual CallGraphNode* getCallsExternalNode() const { return 0; } + /// into the callgraph. + CallGraphNode *getExternalCallingNode() const { return ExternalCallingNode; } + CallGraphNode *getCallsExternalNode() const { return CallsExternalNode; } /// Return the root/main method in the module, or some other root node, such - /// as the externalcallingnode. Overload these if you behavioral - /// inheritance. - virtual CallGraphNode* getRoot() { return 0; } - virtual const CallGraphNode* getRoot() const { return 0; } + /// as the externalcallingnode. + CallGraphNode *getRoot() { return Root; } + const CallGraphNode *getRoot() const { return Root; } //===--------------------------------------------------------------------- // Functions to keep a call graph up to date with a function that has been @@ -129,41 +151,20 @@ public: /// do this is to dropAllReferences before calling this. /// Function *removeFunctionFromModule(CallGraphNode *CGN); - Function *removeFunctionFromModule(Function *F) { - return removeFunctionFromModule((*this)[F]); - } /// getOrInsertFunction - This method is identical to calling operator[], but /// it will insert a new CallGraphNode for the specified function if one does /// not already exist. CallGraphNode *getOrInsertFunction(const Function *F); - /// spliceFunction - Replace the function represented by this node by another. - /// This does not rescan the body of the function, so it is suitable when - /// splicing the body of one function to another while also updating all - /// callers from the old function to the new. - /// - void spliceFunction(const Function *From, const Function *To); - - //===--------------------------------------------------------------------- - // Pass infrastructure interface glue code. - // -protected: - CallGraph() {} - -public: - virtual ~CallGraph() { destroy(); } - - /// initialize - Call this method before calling other methods, - /// re/initializes the state of the CallGraph. - /// - void initialize(Module &M); + CallGraph(); + virtual ~CallGraph() { releaseMemory(); } + virtual void getAnalysisUsage(AnalysisUsage &AU) const; + virtual bool runOnModule(Module &M); + virtual void releaseMemory(); - void print(raw_ostream &o, Module *) const; + void print(raw_ostream &o, const Module *) const; void dump() const; -protected: - // destroy - Release memory for the call graph - virtual void destroy(); }; //===----------------------------------------------------------------------===// diff --git a/contrib/llvm/include/llvm/Analysis/ConstantFolding.h b/contrib/llvm/include/llvm/Analysis/ConstantFolding.h index 12e623ea9..0018a5679 100644 --- a/contrib/llvm/include/llvm/Analysis/ConstantFolding.h +++ b/contrib/llvm/include/llvm/Analysis/ConstantFolding.h @@ -1,4 +1,4 @@ -//===-- ConstantFolding.h - Fold instructions into constants --------------===// +//===-- ConstantFolding.h - Fold instructions into constants ----*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -48,8 +48,8 @@ Constant *ConstantFoldConstantExpression(const ConstantExpr *CE, /// ConstantFoldInstOperands - Attempt to constant fold an instruction with the /// specified operands. If successful, the constant result is returned, if not, -/// null is returned. Note that this function can fail when attempting to -/// fold instructions like loads and stores, which have no constant expression +/// null is returned. Note that this function can fail when attempting to +/// fold instructions like loads and stores, which have no constant expression /// form. /// Constant *ConstantFoldInstOperands(unsigned Opcode, Type *DestTy, diff --git a/contrib/llvm/include/llvm/Analysis/DependenceAnalysis.h b/contrib/llvm/include/llvm/Analysis/DependenceAnalysis.h index a78ac5919..ea8cecf97 100644 --- a/contrib/llvm/include/llvm/Analysis/DependenceAnalysis.h +++ b/contrib/llvm/include/llvm/Analysis/DependenceAnalysis.h @@ -61,11 +61,20 @@ namespace llvm { /// cases (for output, flow, and anti dependences), the dependence implies /// an ordering, where the source must precede the destination; in contrast, /// input dependences are unordered. + /// + /// When a dependence graph is built, each Dependence will be a member of + /// the set of predecessor edges for its destination instruction and a set + /// if successor edges for its source instruction. These sets are represented + /// as singly-linked lists, with the "next" fields stored in the dependence + /// itelf. class Dependence { public: Dependence(Instruction *Source, Instruction *Destination) : - Src(Source), Dst(Destination) {} + Src(Source), + Dst(Destination), + NextPredecessor(NULL), + NextSuccessor(NULL) {} virtual ~Dependence() {} /// Dependence::DVEntry - Each level in the distance/direction vector @@ -164,11 +173,36 @@ namespace llvm { /// variable associated with the loop at this level. virtual bool isScalar(unsigned Level) const; + /// getNextPredecessor - Returns the value of the NextPredecessor + /// field. + const Dependence *getNextPredecessor() const { + return NextPredecessor; + } + + /// getNextSuccessor - Returns the value of the NextSuccessor + /// field. + const Dependence *getNextSuccessor() const { + return NextSuccessor; + } + + /// setNextPredecessor - Sets the value of the NextPredecessor + /// field. + void setNextPredecessor(const Dependence *pred) { + NextPredecessor = pred; + } + + /// setNextSuccessor - Sets the value of the NextSuccessor + /// field. + void setNextSuccessor(const Dependence *succ) { + NextSuccessor = succ; + } + /// dump - For debugging purposes, dumps a dependence to OS. /// void dump(raw_ostream &OS) const; private: Instruction *Src, *Dst; + const Dependence *NextPredecessor, *NextSuccessor; friend class DependenceAnalysis; }; @@ -815,7 +849,7 @@ namespace llvm { bool propagate(const SCEV *&Src, const SCEV *&Dst, SmallBitVector &Loops, - SmallVector &Constraints, + SmallVectorImpl &Constraints, bool &Consistent); /// propagateDistance - Attempt to propagate a distance @@ -874,6 +908,10 @@ namespace llvm { /// based on the current constraint. void updateDirection(Dependence::DVEntry &Level, const Constraint &CurConstraint) const; + + bool tryDelinearize(const SCEV *SrcSCEV, const SCEV *DstSCEV, + SmallVectorImpl &Pair) const; + public: static char ID; // Class identification, replacement for typeinfo DependenceAnalysis() : FunctionPass(ID) { diff --git a/contrib/llvm/include/llvm/Analysis/Dominators.h b/contrib/llvm/include/llvm/Analysis/Dominators.h index 81c04bb6b..3aa0beb6b 100644 --- a/contrib/llvm/include/llvm/Analysis/Dominators.h +++ b/contrib/llvm/include/llvm/Analysis/Dominators.h @@ -346,6 +346,20 @@ public: DomTreeNodeBase *getRootNode() { return RootNode; } const DomTreeNodeBase *getRootNode() const { return RootNode; } + /// Get all nodes dominated by R, including R itself. Return true on success. + void getDescendants(NodeT *R, SmallVectorImpl &Result) const { + const DomTreeNodeBase *RN = getNode(R); + SmallVector *, 8> WL; + WL.push_back(RN); + Result.clear(); + + while (!WL.empty()) { + const DomTreeNodeBase *N = WL.pop_back_val(); + Result.push_back(N->getBlock()); + WL.append(N->begin(), N->end()); + } + } + /// properlyDominates - Returns true iff A dominates B and A != B. /// Note that this is not a constant time operation! /// @@ -755,6 +769,12 @@ public: return DT->getRootNode(); } + /// Get all nodes dominated by R, including R itself. Return true on success. + void getDescendants(BasicBlock *R, + SmallVectorImpl &Result) const { + DT->getDescendants(R, Result); + } + /// compare - Return false if the other dominator tree matches this /// dominator tree. Otherwise return true. inline bool compare(DominatorTree &Other) const { diff --git a/contrib/llvm/include/llvm/Analysis/InlineCost.h b/contrib/llvm/include/llvm/Analysis/InlineCost.h index bc7924e10..383f69713 100644 --- a/contrib/llvm/include/llvm/Analysis/InlineCost.h +++ b/contrib/llvm/include/llvm/Analysis/InlineCost.h @@ -14,7 +14,6 @@ #ifndef LLVM_ANALYSIS_INLINECOST_H #define LLVM_ANALYSIS_INLINECOST_H -#include "llvm/Analysis/CodeMetrics.h" #include "llvm/Analysis/CallGraphSCCPass.h" #include #include @@ -77,7 +76,7 @@ public: } /// \brief Test whether the inline cost is low enough for inlining. - operator bool() const { + LLVM_EXPLICIT operator bool() const { return Cost < Threshold; } diff --git a/contrib/llvm/include/llvm/Analysis/InstructionSimplify.h b/contrib/llvm/include/llvm/Analysis/InstructionSimplify.h index d760a4cba..775d0df46 100644 --- a/contrib/llvm/include/llvm/Analysis/InstructionSimplify.h +++ b/contrib/llvm/include/llvm/Analysis/InstructionSimplify.h @@ -1,4 +1,4 @@ -//===-- InstructionSimplify.h - Fold instructions into simpler forms ------===// +//===-- InstructionSimplify.h - Fold instrs into simpler forms --*- C++ -*-===// // // The LLVM Compiler Infrastructure // diff --git a/contrib/llvm/include/llvm/Analysis/LoopInfo.h b/contrib/llvm/include/llvm/Analysis/LoopInfo.h index 783e34752..62f5acad5 100644 --- a/contrib/llvm/include/llvm/Analysis/LoopInfo.h +++ b/contrib/llvm/include/llvm/Analysis/LoopInfo.h @@ -50,6 +50,7 @@ inline void RemoveFromVector(std::vector &V, T *N) { class DominatorTree; class LoopInfo; class Loop; +class MDNode; class PHINode; class raw_ostream; template class LoopInfoBase; @@ -68,6 +69,8 @@ class LoopBase { // Blocks - The list of blocks in this loop. First entry is the header node. std::vector Blocks; + SmallPtrSet DenseBlockSet; + LoopBase(const LoopBase &) LLVM_DELETED_FUNCTION; const LoopBase& operator=(const LoopBase &) LLVM_DELETED_FUNCTION; @@ -107,7 +110,7 @@ public: /// contains - Return true if the specified basic block is in this loop. /// bool contains(const BlockT *BB) const { - return std::find(block_begin(), block_end(), BB) != block_end(); + return DenseBlockSet.count(BB); } /// contains - Return true if the specified instruction is in this loop. @@ -133,7 +136,6 @@ public: /// getBlocks - Get a list of the basic blocks which make up this loop. /// const std::vector &getBlocks() const { return Blocks; } - std::vector &getBlocksVector() { return Blocks; } typedef typename std::vector::const_iterator block_iterator; block_iterator block_begin() const { return Blocks.begin(); } block_iterator block_end() const { return Blocks.end(); } @@ -270,6 +272,17 @@ public: /// transformations should use addBasicBlockToLoop. void addBlockEntry(BlockT *BB) { Blocks.push_back(BB); + DenseBlockSet.insert(BB); + } + + /// reverseBlocks - interface to reverse Blocks[from, end of loop] in this loop + void reverseBlock(unsigned from) { + std::reverse(Blocks.begin() + from, Blocks.end()); + } + + /// reserveBlocks- interface to do reserve() for Blocks + void reserveBlocks(unsigned size) { + Blocks.reserve(size); } /// moveToHeader - This method is used to move BB (which must be part of this @@ -292,6 +305,7 @@ public: /// the mapping in the LoopInfo class. void removeBlockFromLoop(BlockT *BB) { RemoveFromVector(Blocks, BB); + DenseBlockSet.erase(BB); } /// verifyLoop - Verify loop structure @@ -306,6 +320,7 @@ protected: friend class LoopInfoBase; explicit LoopBase(BlockT *BB) : ParentLoop(0) { Blocks.push_back(BB); + DenseBlockSet.insert(BB); } }; @@ -391,6 +406,22 @@ public: /// iterations. bool isAnnotatedParallel() const; + /// Return the llvm.loop loop id metadata node for this loop if it is present. + /// + /// If this loop contains the same llvm.loop metadata on each branch to the + /// header then the node is returned. If any latch instruction does not + /// contain llvm.loop or or if multiple latches contain different nodes then + /// 0 is returned. + MDNode *getLoopID() const; + /// Set the llvm.loop loop id metadata for this loop. + /// + /// The LoopID metadata node will be added to each terminator instruction in + /// the loop that branches to the loop header. + /// + /// The LoopID metadata node should have one or more operands and the first + /// operand should should be the node itself. + void setLoopID(MDNode *LoopID) const; + /// hasDedicatedExits - Return true if no exit block for the loop /// has a predecessor that is outside the loop. bool hasDedicatedExits() const; diff --git a/contrib/llvm/include/llvm/Analysis/LoopInfoImpl.h b/contrib/llvm/include/llvm/Analysis/LoopInfoImpl.h index 5485f3c0c..c98cb5891 100644 --- a/contrib/llvm/include/llvm/Analysis/LoopInfoImpl.h +++ b/contrib/llvm/include/llvm/Analysis/LoopInfoImpl.h @@ -31,17 +31,12 @@ namespace llvm { template void LoopBase:: getExitingBlocks(SmallVectorImpl &ExitingBlocks) const { - // Sort the blocks vector so that we can use binary search to do quick - // lookups. - SmallVector LoopBBs(block_begin(), block_end()); - std::sort(LoopBBs.begin(), LoopBBs.end()); - typedef GraphTraits BlockTraits; for (block_iterator BI = block_begin(), BE = block_end(); BI != BE; ++BI) for (typename BlockTraits::ChildIteratorType I = BlockTraits::child_begin(*BI), E = BlockTraits::child_end(*BI); I != E; ++I) - if (!std::binary_search(LoopBBs.begin(), LoopBBs.end(), *I)) { + if (!contains(*I)) { // Not in current loop? It must be an exit block. ExitingBlocks.push_back(*BI); break; @@ -65,17 +60,12 @@ BlockT *LoopBase::getExitingBlock() const { template void LoopBase:: getExitBlocks(SmallVectorImpl &ExitBlocks) const { - // Sort the blocks vector so that we can use binary search to do quick - // lookups. - SmallVector LoopBBs(block_begin(), block_end()); - std::sort(LoopBBs.begin(), LoopBBs.end()); - typedef GraphTraits BlockTraits; for (block_iterator BI = block_begin(), BE = block_end(); BI != BE; ++BI) for (typename BlockTraits::ChildIteratorType I = BlockTraits::child_begin(*BI), E = BlockTraits::child_end(*BI); I != E; ++I) - if (!std::binary_search(LoopBBs.begin(), LoopBBs.end(), *I)) + if (!contains(*I)) // Not in current loop? It must be an exit block. ExitBlocks.push_back(*I); } @@ -95,17 +85,12 @@ BlockT *LoopBase::getExitBlock() const { template void LoopBase:: getExitEdges(SmallVectorImpl &ExitEdges) const { - // Sort the blocks vector so that we can use binary search to do quick - // lookups. - SmallVector LoopBBs(block_begin(), block_end()); - array_pod_sort(LoopBBs.begin(), LoopBBs.end()); - typedef GraphTraits BlockTraits; for (block_iterator BI = block_begin(), BE = block_end(); BI != BE; ++BI) for (typename BlockTraits::ChildIteratorType I = BlockTraits::child_begin(*BI), E = BlockTraits::child_end(*BI); I != E; ++I) - if (!std::binary_search(LoopBBs.begin(), LoopBBs.end(), *I)) + if (!contains(*I)) // Not in current loop? It must be an exit block. ExitEdges.push_back(Edge(*BI, *I)); } @@ -210,7 +195,7 @@ addBasicBlockToLoop(BlockT *NewBB, LoopInfoBase &LIB) { // Add the basic block to this loop and all parent loops... while (L) { - L->Blocks.push_back(NewBB); + L->addBlockEntry(NewBB); L = L->getParentLoop(); } } @@ -250,11 +235,6 @@ void LoopBase::verifyLoop() const { // Keep track of the number of BBs visited. unsigned NumVisited = 0; - // Sort the blocks vector so that we can use binary search to do quick - // lookups. - SmallVector LoopBBs(block_begin(), block_end()); - std::sort(LoopBBs.begin(), LoopBBs.end()); - // Check the individual blocks. for ( ; BI != BE; ++BI) { BlockT *BB = *BI; @@ -266,7 +246,7 @@ void LoopBase::verifyLoop() const { for (typename BlockTraits::ChildIteratorType SI = BlockTraits::child_begin(BB), SE = BlockTraits::child_end(BB); SI != SE; ++SI) - if (std::binary_search(LoopBBs.begin(), LoopBBs.end(), *SI)) { + if (contains(*SI)) { HasInsideLoopSuccs = true; break; } @@ -275,7 +255,7 @@ void LoopBase::verifyLoop() const { InvBlockTraits::child_begin(BB), PE = InvBlockTraits::child_end(BB); PI != PE; ++PI) { BlockT *N = *PI; - if (std::binary_search(LoopBBs.begin(), LoopBBs.end(), N)) + if (contains(N)) HasInsideLoopPreds = true; else OutsideLoopPreds.push_back(N); @@ -309,7 +289,7 @@ void LoopBase::verifyLoop() const { // Each block in each subloop should be contained within this loop. for (block_iterator BI = (*I)->block_begin(), BE = (*I)->block_end(); BI != BE; ++BI) { - assert(std::binary_search(LoopBBs.begin(), LoopBBs.end(), *BI) && + assert(contains(*BI) && "Loop does not contain all the blocks of a subloop!"); } @@ -418,7 +398,7 @@ static void discoverAndMapSubloop(LoopT *L, ArrayRef Backedges, } } L->getSubLoopsVector().reserve(NumSubloops); - L->getBlocksVector().reserve(NumBlocks); + L->reserveBlocks(NumBlocks); } namespace { @@ -489,15 +469,14 @@ void PopulateLoopsDFS::insertIntoLoop(BlockT *Block) { // For convenience, Blocks and Subloops are inserted in postorder. Reverse // the lists, except for the loop header, which is always at the beginning. - std::reverse(Subloop->getBlocksVector().begin()+1, - Subloop->getBlocksVector().end()); + Subloop->reverseBlock(1); std::reverse(Subloop->getSubLoopsVector().begin(), Subloop->getSubLoopsVector().end()); Subloop = Subloop->getParentLoop(); } for (; Subloop; Subloop = Subloop->getParentLoop()) - Subloop->getBlocksVector().push_back(Block); + Subloop->addBlockEntry(Block); } /// Analyze LoopInfo discovers loops during a postorder DominatorTree traversal diff --git a/contrib/llvm/include/llvm/Analysis/LoopPass.h b/contrib/llvm/include/llvm/Analysis/LoopPass.h index 5767c1916..5926610d1 100644 --- a/contrib/llvm/include/llvm/Analysis/LoopPass.h +++ b/contrib/llvm/include/llvm/Analysis/LoopPass.h @@ -16,8 +16,8 @@ #define LLVM_ANALYSIS_LOOPPASS_H #include "llvm/Analysis/LoopInfo.h" +#include "llvm/IR/LegacyPassManagers.h" #include "llvm/Pass.h" -#include "llvm/PassManagers.h" #include namespace llvm { diff --git a/contrib/llvm/include/llvm/Analysis/MemoryBuiltins.h b/contrib/llvm/include/llvm/Analysis/MemoryBuiltins.h index 488338302..91224ad94 100644 --- a/contrib/llvm/include/llvm/Analysis/MemoryBuiltins.h +++ b/contrib/llvm/include/llvm/Analysis/MemoryBuiltins.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// // // This family of functions identifies calls to builtin functions that allocate -// or free memory. +// or free memory. // //===----------------------------------------------------------------------===// @@ -64,6 +64,10 @@ bool isAllocLikeFn(const Value *V, const TargetLibraryInfo *TLI, bool isReallocLikeFn(const Value *V, const TargetLibraryInfo *TLI, bool LookThroughBitCast = false); +/// \brief Tests if a value is a call or invoke to a library function that +/// allocates memory and never returns null (such as operator new). +bool isOperatorNewLikeFn(const Value *V, const TargetLibraryInfo *TLI, + bool LookThroughBitCast = false); //===----------------------------------------------------------------------===// // malloc Call Utility Functions. @@ -78,10 +82,10 @@ static inline CallInst *extractMallocCall(Value *I, return const_cast(extractMallocCall((const Value*)I, TLI)); } -/// isArrayMalloc - Returns the corresponding CallInst if the instruction +/// isArrayMalloc - Returns the corresponding CallInst if the instruction /// is a call to malloc whose array size can be determined and the array size /// is not constant 1. Otherwise, return NULL. -const CallInst *isArrayMalloc(const Value *I, const DataLayout *TD, +const CallInst *isArrayMalloc(const Value *I, const DataLayout *DL, const TargetLibraryInfo *TLI); /// getMallocType - Returns the PointerType resulting from the malloc call. @@ -98,12 +102,12 @@ PointerType *getMallocType(const CallInst *CI, const TargetLibraryInfo *TLI); /// >1: Unique PointerType cannot be determined, return NULL. Type *getMallocAllocatedType(const CallInst *CI, const TargetLibraryInfo *TLI); -/// getMallocArraySize - Returns the array size of a malloc call. If the +/// getMallocArraySize - Returns the array size of a malloc call. If the /// argument passed to malloc is a multiple of the size of the malloced type, /// then return that multiple. For non-array mallocs, the multiple is /// constant 1. Otherwise, return NULL for mallocs whose array size cannot be /// determined. -Value *getMallocArraySize(CallInst *CI, const DataLayout *TD, +Value *getMallocArraySize(CallInst *CI, const DataLayout *DL, const TargetLibraryInfo *TLI, bool LookThroughSExt = false); @@ -127,12 +131,12 @@ static inline CallInst *extractCallocCall(Value *I, /// isFreeCall - Returns non-null if the value is a call to the builtin free() const CallInst *isFreeCall(const Value *I, const TargetLibraryInfo *TLI); - + static inline CallInst *isFreeCall(Value *I, const TargetLibraryInfo *TLI) { return const_cast(isFreeCall((const Value*)I, TLI)); } - + //===----------------------------------------------------------------------===// // Utility functions to compute size of objects. // @@ -143,19 +147,19 @@ static inline CallInst *isFreeCall(Value *I, const TargetLibraryInfo *TLI) { /// underlying object pointed to by Ptr. /// If RoundToAlign is true, then Size is rounded up to the aligment of allocas, /// byval arguments, and global variables. -bool getObjectSize(const Value *Ptr, uint64_t &Size, const DataLayout *TD, +bool getObjectSize(const Value *Ptr, uint64_t &Size, const DataLayout *DL, const TargetLibraryInfo *TLI, bool RoundToAlign = false); typedef std::pair SizeOffsetType; -/// \brief Evaluate the size and offset of an object ponted by a Value* +/// \brief Evaluate the size and offset of an object pointed to by a Value* /// statically. Fails if size or offset are not known at compile time. class ObjectSizeOffsetVisitor : public InstVisitor { - const DataLayout *TD; + const DataLayout *DL; const TargetLibraryInfo *TLI; bool RoundToAlign; unsigned IntTyBits; @@ -169,7 +173,7 @@ class ObjectSizeOffsetVisitor } public: - ObjectSizeOffsetVisitor(const DataLayout *TD, const TargetLibraryInfo *TLI, + ObjectSizeOffsetVisitor(const DataLayout *DL, const TargetLibraryInfo *TLI, LLVMContext &Context, bool RoundToAlign = false); SizeOffsetType compute(Value *V); @@ -206,7 +210,7 @@ public: typedef std::pair SizeOffsetEvalType; -/// \brief Evaluate the size and offset of an object ponted by a Value*. +/// \brief Evaluate the size and offset of an object pointed to by a Value*. /// May create code to compute the result at run-time. class ObjectSizeOffsetEvaluator : public InstVisitor { @@ -216,7 +220,7 @@ class ObjectSizeOffsetEvaluator typedef DenseMap CacheMapTy; typedef SmallPtrSet PtrSetTy; - const DataLayout *TD; + const DataLayout *DL; const TargetLibraryInfo *TLI; LLVMContext &Context; BuilderTy Builder; @@ -224,6 +228,7 @@ class ObjectSizeOffsetEvaluator Value *Zero; CacheMapTy CacheMap; PtrSetTy SeenVals; + bool RoundToAlign; SizeOffsetEvalType unknown() { return std::make_pair((Value*)0, (Value*)0); @@ -231,8 +236,8 @@ class ObjectSizeOffsetEvaluator SizeOffsetEvalType compute_(Value *V); public: - ObjectSizeOffsetEvaluator(const DataLayout *TD, const TargetLibraryInfo *TLI, - LLVMContext &Context); + ObjectSizeOffsetEvaluator(const DataLayout *DL, const TargetLibraryInfo *TLI, + LLVMContext &Context, bool RoundToAlign = false); SizeOffsetEvalType compute(Value *V); bool knownSize(SizeOffsetEvalType SizeOffset) { diff --git a/contrib/llvm/include/llvm/Analysis/Passes.h b/contrib/llvm/include/llvm/Analysis/Passes.h index ae117135d..a5d098eb0 100644 --- a/contrib/llvm/include/llvm/Analysis/Passes.h +++ b/contrib/llvm/include/llvm/Analysis/Passes.h @@ -93,64 +93,6 @@ namespace llvm { // ImmutablePass *createObjCARCAliasAnalysisPass(); - //===--------------------------------------------------------------------===// - // - // createProfileLoaderPass - This pass loads information from a profile dump - // file. - // - ModulePass *createProfileLoaderPass(); - extern char &ProfileLoaderPassID; - - //===--------------------------------------------------------------------===// - // - // createProfileMetadataLoaderPass - This pass loads information from a - // profile dump file and sets branch weight metadata. - // - ModulePass *createProfileMetadataLoaderPass(); - extern char &ProfileMetadataLoaderPassID; - - //===--------------------------------------------------------------------===// - // - // createNoProfileInfoPass - This pass implements the default "no profile". - // - ImmutablePass *createNoProfileInfoPass(); - - //===--------------------------------------------------------------------===// - // - // createProfileEstimatorPass - This pass estimates profiling information - // instead of loading it from a previous run. - // - FunctionPass *createProfileEstimatorPass(); - extern char &ProfileEstimatorPassID; - - //===--------------------------------------------------------------------===// - // - // createProfileVerifierPass - This pass verifies profiling information. - // - FunctionPass *createProfileVerifierPass(); - - //===--------------------------------------------------------------------===// - // - // createPathProfileLoaderPass - This pass loads information from a path - // profile dump file. - // - ModulePass *createPathProfileLoaderPass(); - extern char &PathProfileLoaderPassID; - - //===--------------------------------------------------------------------===// - // - // createNoPathProfileInfoPass - This pass implements the default - // "no path profile". - // - ImmutablePass *createNoPathProfileInfoPass(); - - //===--------------------------------------------------------------------===// - // - // createPathProfileVerifierPass - This pass verifies path profiling - // information. - // - ModulePass *createPathProfileVerifierPass(); - //===--------------------------------------------------------------------===// // // createDSAAPass - This pass implements simple context sensitive alias @@ -192,6 +134,13 @@ namespace llvm { // FunctionPass *createCostModelAnalysisPass(); + //===--------------------------------------------------------------------===// + // + // createDelinearizationPass - This pass implements attempts to restore + // multidimensional array indices from linearized expressions. + // + FunctionPass *createDelinearizationPass(); + //===--------------------------------------------------------------------===// // // Minor pass prototypes, allowing us to expose them through bugpoint and diff --git a/contrib/llvm/include/llvm/Analysis/PathNumbering.h b/contrib/llvm/include/llvm/Analysis/PathNumbering.h deleted file mode 100644 index 400a37d82..000000000 --- a/contrib/llvm/include/llvm/Analysis/PathNumbering.h +++ /dev/null @@ -1,304 +0,0 @@ -//===- PathNumbering.h ----------------------------------------*- C++ -*---===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Ball-Larus path numbers uniquely identify paths through a directed acyclic -// graph (DAG) [Ball96]. For a CFG backedges are removed and replaced by phony -// edges to obtain a DAG, and thus the unique path numbers [Ball96]. -// -// The purpose of this analysis is to enumerate the edges in a CFG in order -// to obtain paths from path numbers in a convenient manner. As described in -// [Ball96] edges can be enumerated such that given a path number by following -// the CFG and updating the path number, the path is obtained. -// -// [Ball96] -// T. Ball and J. R. Larus. "Efficient Path Profiling." -// International Symposium on Microarchitecture, pages 46-57, 1996. -// http://portal.acm.org/citation.cfm?id=243857 -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_ANALYSIS_PATHNUMBERING_H -#define LLVM_ANALYSIS_PATHNUMBERING_H - -#include "llvm/Analysis/ProfileInfoTypes.h" -#include "llvm/IR/BasicBlock.h" -#include "llvm/IR/Instructions.h" -#include "llvm/Pass.h" -#include "llvm/Support/CFG.h" -#include -#include -#include - -namespace llvm { -class BallLarusNode; -class BallLarusEdge; -class BallLarusDag; - -// typedefs for storage/ interators of various DAG components -typedef std::vector BLNodeVector; -typedef std::vector::iterator BLNodeIterator; -typedef std::vector BLEdgeVector; -typedef std::vector::iterator BLEdgeIterator; -typedef std::map BLBlockNodeMap; -typedef std::stack BLNodeStack; - -// Represents a basic block with information necessary for the BallLarus -// algorithms. -class BallLarusNode { -public: - enum NodeColor { WHITE, GRAY, BLACK }; - - // Constructor: Initializes a new Node for the given BasicBlock - BallLarusNode(BasicBlock* BB) : - _basicBlock(BB), _numberPaths(0), _color(WHITE) { - static unsigned nextUID = 0; - _uid = nextUID++; - } - - // Returns the basic block for the BallLarusNode - BasicBlock* getBlock(); - - // Get/set the number of paths to the exit starting at the node. - unsigned getNumberPaths(); - void setNumberPaths(unsigned numberPaths); - - // Get/set the NodeColor used in graph algorithms. - NodeColor getColor(); - void setColor(NodeColor color); - - // Iterator information for predecessor edges. Includes phony and - // backedges. - BLEdgeIterator predBegin(); - BLEdgeIterator predEnd(); - unsigned getNumberPredEdges(); - - // Iterator information for successor edges. Includes phony and - // backedges. - BLEdgeIterator succBegin(); - BLEdgeIterator succEnd(); - unsigned getNumberSuccEdges(); - - // Add an edge to the predecessor list. - void addPredEdge(BallLarusEdge* edge); - - // Remove an edge from the predecessor list. - void removePredEdge(BallLarusEdge* edge); - - // Add an edge to the successor list. - void addSuccEdge(BallLarusEdge* edge); - - // Remove an edge from the successor list. - void removeSuccEdge(BallLarusEdge* edge); - - // Returns the name of the BasicBlock being represented. If BasicBlock - // is null then returns "". If BasicBlock has no name, then - // "" is returned. Intended for use with debug output. - std::string getName(); - -private: - // The corresponding underlying BB. - BasicBlock* _basicBlock; - - // Holds the predecessor edges of this node. - BLEdgeVector _predEdges; - - // Holds the successor edges of this node. - BLEdgeVector _succEdges; - - // The number of paths from the node to the exit. - unsigned _numberPaths; - - // 'Color' used by graph algorithms to mark the node. - NodeColor _color; - - // Unique ID to ensure naming difference with dotgraphs - unsigned _uid; - - // Removes an edge from an edgeVector. Used by removePredEdge and - // removeSuccEdge. - void removeEdge(BLEdgeVector& v, BallLarusEdge* e); -}; - -// Represents an edge in the Dag. For an edge, v -> w, v is the source, and -// w is the target. -class BallLarusEdge { -public: - enum EdgeType { NORMAL, BACKEDGE, SPLITEDGE, - BACKEDGE_PHONY, SPLITEDGE_PHONY, CALLEDGE_PHONY }; - - // Constructor: Initializes an BallLarusEdge with a source and target. - BallLarusEdge(BallLarusNode* source, BallLarusNode* target, - unsigned duplicateNumber) - : _source(source), _target(target), _weight(0), _edgeType(NORMAL), - _realEdge(NULL), _duplicateNumber(duplicateNumber) {} - - // Returns the source/ target node of this edge. - BallLarusNode* getSource() const; - BallLarusNode* getTarget() const; - - // Sets the type of the edge. - EdgeType getType() const; - - // Gets the type of the edge. - void setType(EdgeType type); - - // Returns the weight of this edge. Used to decode path numbers to - // sequences of basic blocks. - unsigned getWeight(); - - // Sets the weight of the edge. Used during path numbering. - void setWeight(unsigned weight); - - // Gets/sets the phony edge originating at the root. - BallLarusEdge* getPhonyRoot(); - void setPhonyRoot(BallLarusEdge* phonyRoot); - - // Gets/sets the phony edge terminating at the exit. - BallLarusEdge* getPhonyExit(); - void setPhonyExit(BallLarusEdge* phonyExit); - - // Gets/sets the associated real edge if this is a phony edge. - BallLarusEdge* getRealEdge(); - void setRealEdge(BallLarusEdge* realEdge); - - // Returns the duplicate number of the edge. - unsigned getDuplicateNumber(); - -protected: - // Source node for this edge. - BallLarusNode* _source; - - // Target node for this edge. - BallLarusNode* _target; - -private: - // Edge weight cooresponding to path number increments before removing - // increments along a spanning tree. The sum over the edge weights gives - // the path number. - unsigned _weight; - - // Type to represent for what this edge is intended - EdgeType _edgeType; - - // For backedges and split-edges, the phony edge which is linked to the - // root node of the DAG. This contains a path number initialization. - BallLarusEdge* _phonyRoot; - - // For backedges and split-edges, the phony edge which is linked to the - // exit node of the DAG. This contains a path counter increment, and - // potentially a path number increment. - BallLarusEdge* _phonyExit; - - // If this is a phony edge, _realEdge is a link to the back or split - // edge. Otherwise, this is null. - BallLarusEdge* _realEdge; - - // An ID to differentiate between those edges which have the same source - // and destination blocks. - unsigned _duplicateNumber; -}; - -// Represents the Ball Larus DAG for a given Function. Can calculate -// various properties required for instrumentation or analysis. E.g. the -// edge weights that determine the path number. -class BallLarusDag { -public: - // Initializes a BallLarusDag from the CFG of a given function. Must - // call init() after creation, since some initialization requires - // virtual functions. - BallLarusDag(Function &F) - : _root(NULL), _exit(NULL), _function(F) {} - - // Initialization that requires virtual functions which are not fully - // functional in the constructor. - void init(); - - // Frees all memory associated with the DAG. - virtual ~BallLarusDag(); - - // Calculate the path numbers by assigning edge increments as prescribed - // in Ball-Larus path profiling. - void calculatePathNumbers(); - - // Returns the number of paths for the DAG. - unsigned getNumberOfPaths(); - - // Returns the root (i.e. entry) node for the DAG. - BallLarusNode* getRoot(); - - // Returns the exit node for the DAG. - BallLarusNode* getExit(); - - // Returns the function for the DAG. - Function& getFunction(); - - // Clears the node colors. - void clearColors(BallLarusNode::NodeColor color); - -protected: - // All nodes in the DAG. - BLNodeVector _nodes; - - // All edges in the DAG. - BLEdgeVector _edges; - - // All backedges in the DAG. - BLEdgeVector _backEdges; - - // Allows subclasses to determine which type of Node is created. - // Override this method to produce subclasses of BallLarusNode if - // necessary. The destructor of BallLarusDag will call free on each pointer - // created. - virtual BallLarusNode* createNode(BasicBlock* BB); - - // Allows subclasses to determine which type of Edge is created. - // Override this method to produce subclasses of BallLarusEdge if - // necessary. Parameters source and target will have been created by - // createNode and can be cast to the subclass of BallLarusNode* - // returned by createNode. The destructor of BallLarusDag will call free - // on each pointer created. - virtual BallLarusEdge* createEdge(BallLarusNode* source, BallLarusNode* - target, unsigned duplicateNumber); - - // Proxy to node's constructor. Updates the DAG state. - BallLarusNode* addNode(BasicBlock* BB); - - // Proxy to edge's constructor. Updates the DAG state. - BallLarusEdge* addEdge(BallLarusNode* source, BallLarusNode* target, - unsigned duplicateNumber); - -private: - // The root (i.e. entry) node for this DAG. - BallLarusNode* _root; - - // The exit node for this DAG. - BallLarusNode* _exit; - - // The function represented by this DAG. - Function& _function; - - // Processes one node and its imediate edges for building the DAG. - void buildNode(BLBlockNodeMap& inDag, std::stack& dfsStack); - - // Process an edge in the CFG for DAG building. - void buildEdge(BLBlockNodeMap& inDag, std::stack& dfsStack, - BallLarusNode* currentNode, BasicBlock* succBB, - unsigned duplicateNumber); - - // The weight on each edge is the increment required along any path that - // contains that edge. - void calculatePathNumbersFrom(BallLarusNode* node); - - // Adds a backedge with its phony edges. Updates the DAG state. - void addBackedge(BallLarusNode* source, BallLarusNode* target, - unsigned duplicateCount); -}; -} // end namespace llvm - -#endif diff --git a/contrib/llvm/include/llvm/Analysis/PathProfileInfo.h b/contrib/llvm/include/llvm/Analysis/PathProfileInfo.h deleted file mode 100644 index 4fce16ef0..000000000 --- a/contrib/llvm/include/llvm/Analysis/PathProfileInfo.h +++ /dev/null @@ -1,112 +0,0 @@ -//===- PathProfileInfo.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 outlines the interface used by optimizers to load path profiles. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_ANALYSIS_PATHPROFILEINFO_H -#define LLVM_ANALYSIS_PATHPROFILEINFO_H - -#include "llvm/Analysis/PathNumbering.h" -#include "llvm/IR/BasicBlock.h" - -namespace llvm { - -class ProfilePath; -class ProfilePathEdge; -class PathProfileInfo; - -typedef std::vector ProfilePathEdgeVector; -typedef std::vector::iterator ProfilePathEdgeIterator; - -typedef std::vector ProfilePathBlockVector; -typedef std::vector::iterator ProfilePathBlockIterator; - -typedef std::map ProfilePathMap; -typedef std::map::iterator ProfilePathIterator; - -typedef std::map FunctionPathCountMap; -typedef std::map FunctionPathMap; -typedef std::map::iterator FunctionPathIterator; - -class ProfilePathEdge { -public: - ProfilePathEdge(BasicBlock* source, BasicBlock* target, - unsigned duplicateNumber); - - inline unsigned getDuplicateNumber() { return _duplicateNumber; } - inline BasicBlock* getSource() { return _source; } - inline BasicBlock* getTarget() { return _target; } - -protected: - BasicBlock* _source; - BasicBlock* _target; - unsigned _duplicateNumber; -}; - -class ProfilePath { -public: - ProfilePath(unsigned int number, unsigned int count, - double countStdDev, PathProfileInfo* ppi); - - double getFrequency() const; - - inline unsigned int getNumber() const { return _number; } - inline unsigned int getCount() const { return _count; } - inline double getCountStdDev() const { return _countStdDev; } - - ProfilePathEdgeVector* getPathEdges() const; - ProfilePathBlockVector* getPathBlocks() const; - - BasicBlock* getFirstBlockInPath() const; - -private: - unsigned int _number; - unsigned int _count; - double _countStdDev; - - // double pointer back to the profiling info - PathProfileInfo* _ppi; -}; - -// TODO: overload [] operator for getting path -// Add: getFunctionCallCount() -class PathProfileInfo { - public: - PathProfileInfo(); - ~PathProfileInfo(); - - void setCurrentFunction(Function* F); - Function* getCurrentFunction() const; - BasicBlock* getCurrentFunctionEntry(); - - ProfilePath* getPath(unsigned int number); - unsigned int getPotentialPathCount(); - - ProfilePathIterator pathBegin(); - ProfilePathIterator pathEnd(); - unsigned int pathsRun(); - - static char ID; // Pass identification - std::string argList; - -protected: - FunctionPathMap _functionPaths; - FunctionPathCountMap _functionPathCounts; - -private: - BallLarusDag* _currentDag; - Function* _currentFunction; - - friend class ProfilePath; -}; -} // end namespace llvm - -#endif diff --git a/contrib/llvm/include/llvm/Analysis/PostDominators.h b/contrib/llvm/include/llvm/Analysis/PostDominators.h index d08229745..88ebab4ed 100644 --- a/contrib/llvm/include/llvm/Analysis/PostDominators.h +++ b/contrib/llvm/include/llvm/Analysis/PostDominators.h @@ -74,6 +74,11 @@ struct PostDominatorTree : public FunctionPass { return DT->findNearestCommonDominator(A, B); } + inline const BasicBlock *findNearestCommonDominator(const BasicBlock *A, + const BasicBlock *B) { + return DT->findNearestCommonDominator(A, B); + } + virtual void releaseMemory() { DT->releaseMemory(); } diff --git a/contrib/llvm/include/llvm/Analysis/ProfileDataLoader.h b/contrib/llvm/include/llvm/Analysis/ProfileDataLoader.h deleted file mode 100644 index 90097f799..000000000 --- a/contrib/llvm/include/llvm/Analysis/ProfileDataLoader.h +++ /dev/null @@ -1,140 +0,0 @@ -//===- ProfileDataLoader.h - Load & convert profile info ----*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// The ProfileDataLoader class is used to load profiling data from a dump file. -// The ProfileDataT class is used to store the mapping of this -// data to control flow edges. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_ANALYSIS_PROFILEDATALOADER_H -#define LLVM_ANALYSIS_PROFILEDATALOADER_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/ErrorHandling.h" -#include - -namespace llvm { - -class ModulePass; -class Function; -class BasicBlock; - -// Helper for dumping edges to dbgs(). -raw_ostream& operator<<(raw_ostream &O, std::pair E); - -/// \brief The ProfileDataT class is used to store the mapping of -/// profiling data to control flow edges. -/// -/// An edge is defined by its source and sink basic blocks. -template -class ProfileDataT { -public: - // The profiling information defines an Edge by its source and sink basic - // blocks. - typedef std::pair Edge; - -private: - typedef DenseMap EdgeWeights; - - /// \brief Count the number of times a transition between two blocks is - /// executed. - /// - /// As a special case, we also hold an edge from the null BasicBlock to the - /// entry block to indicate how many times the function was entered. - DenseMap EdgeInformation; - -public: - /// getFunction() - Returns the Function for an Edge. - static const FType *getFunction(Edge e) { - // e.first may be NULL - assert(((!e.first) || (e.first->getParent() == e.second->getParent())) - && "A ProfileData::Edge can not be between two functions"); - assert(e.second && "A ProfileData::Edge must have a real sink"); - return e.second->getParent(); - } - - /// getEdge() - Creates an Edge between two BasicBlocks. - static Edge getEdge(const BType *Src, const BType *Dest) { - return Edge(Src, Dest); - } - - /// getEdgeWeight - Return the number of times that a given edge was - /// executed. - unsigned getEdgeWeight(Edge e) const { - const FType *f = getFunction(e); - assert((EdgeInformation.find(f) != EdgeInformation.end()) - && "No profiling information for function"); - EdgeWeights weights = EdgeInformation.find(f)->second; - - assert((weights.find(e) != weights.end()) - && "No profiling information for edge"); - return weights.find(e)->second; - } - - /// addEdgeWeight - Add 'weight' to the already stored execution count for - /// this edge. - void addEdgeWeight(Edge e, unsigned weight) { - EdgeInformation[getFunction(e)][e] += weight; - } -}; - -typedef ProfileDataT ProfileData; -//typedef ProfileDataT MachineProfileData; - -/// The ProfileDataLoader class is used to load raw profiling data from the -/// dump file. -class ProfileDataLoader { -private: - /// The name of the file where the raw profiling data is stored. - const std::string &Filename; - - /// A vector of the command line arguments used when the target program was - /// run to generate profiling data. One entry per program run. - SmallVector CommandLines; - - /// The raw values for how many times each edge was traversed, values from - /// multiple program runs are accumulated. - SmallVector EdgeCounts; - -public: - /// ProfileDataLoader ctor - Read the specified profiling data file, exiting - /// the program if the file is invalid or broken. - ProfileDataLoader(const char *ToolName, const std::string &Filename); - - /// A special value used to represent the weight of an edge which has not - /// been counted yet. - static const unsigned Uncounted; - - /// getNumExecutions - Return the number of times the target program was run - /// to generate this profiling data. - unsigned getNumExecutions() const { return CommandLines.size(); } - - /// getExecution - Return the command line parameters used to generate the - /// i'th set of profiling data. - const std::string &getExecution(unsigned i) const { return CommandLines[i]; } - - const std::string &getFileName() const { return Filename; } - - /// getRawEdgeCounts - Return the raw profiling data, this is just a list of - /// numbers with no mappings to edges. - ArrayRef getRawEdgeCounts() const { return EdgeCounts; } -}; - -/// createProfileMetadataLoaderPass - This function returns a Pass that loads -/// the profiling information for the module from the specified filename. -ModulePass *createProfileMetadataLoaderPass(const std::string &Filename); - -} // End llvm namespace - -#endif diff --git a/contrib/llvm/include/llvm/Analysis/ProfileDataTypes.h b/contrib/llvm/include/llvm/Analysis/ProfileDataTypes.h deleted file mode 100644 index 1be15e025..000000000 --- a/contrib/llvm/include/llvm/Analysis/ProfileDataTypes.h +++ /dev/null @@ -1,39 +0,0 @@ -/*===-- ProfileDataTypes.h - Profiling info shared constants --------------===*\ -|* -|* The LLVM Compiler Infrastructure -|* -|* This file is distributed under the University of Illinois Open Source -|* License. See LICENSE.TXT for details. -|* -|*===----------------------------------------------------------------------===*| -|* -|* This file defines constants shared by the various different profiling -|* runtime libraries and the LLVM C++ profile metadata loader. It must be a -|* C header because, at present, the profiling runtimes are written in C. -|* -\*===----------------------------------------------------------------------===*/ - -#ifndef LLVM_ANALYSIS_PROFILEDATATYPES_H -#define LLVM_ANALYSIS_PROFILEDATATYPES_H - -/* Included by libprofile. */ -#if defined(__cplusplus) -extern "C" { -#endif - -/* TODO: Strip out unused entries once ProfileInfo etc has been removed. */ -enum ProfilingType { - ArgumentInfo = 1, /* The command line argument block */ - FunctionInfo = 2, /* Function profiling information */ - BlockInfo = 3, /* Block profiling information */ - EdgeInfo = 4, /* Edge profiling information */ - PathInfo = 5, /* Path profiling information */ - BBTraceInfo = 6, /* Basic block trace information */ - OptEdgeInfo = 7 /* Edge profiling information, optimal version */ -}; - -#if defined(__cplusplus) -} -#endif - -#endif /* LLVM_ANALYSIS_PROFILEDATATYPES_H */ diff --git a/contrib/llvm/include/llvm/Analysis/ProfileInfo.h b/contrib/llvm/include/llvm/Analysis/ProfileInfo.h deleted file mode 100644 index 5d17fa122..000000000 --- a/contrib/llvm/include/llvm/Analysis/ProfileInfo.h +++ /dev/null @@ -1,247 +0,0 @@ -//===- llvm/Analysis/ProfileInfo.h - Profile Info Interface -----*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the generic ProfileInfo interface, which is used as the -// common interface used by all clients of profiling information, and -// implemented either by making static guestimations, or by actually reading in -// profiling information gathered by running the program. -// -// Note that to be useful, all profile-based optimizations should preserve -// ProfileInfo, which requires that they notify it when changes to the CFG are -// made. (This is not implemented yet.) -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_ANALYSIS_PROFILEINFO_H -#define LLVM_ANALYSIS_PROFILEINFO_H - -#include "llvm/Support/Debug.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/Format.h" -#include "llvm/Support/raw_ostream.h" -#include -#include -#include -#include - -namespace llvm { - class Pass; - class raw_ostream; - - class BasicBlock; - class Function; - class MachineBasicBlock; - class MachineFunction; - - // Helper for dumping edges to dbgs(). - raw_ostream& operator<<(raw_ostream &O, std::pair E); - raw_ostream& operator<<(raw_ostream &O, std::pair E); - - raw_ostream& operator<<(raw_ostream &O, const BasicBlock *BB); - raw_ostream& operator<<(raw_ostream &O, const MachineBasicBlock *MBB); - - raw_ostream& operator<<(raw_ostream &O, const Function *F); - raw_ostream& operator<<(raw_ostream &O, const MachineFunction *MF); - - /// ProfileInfo Class - This class holds and maintains profiling - /// information for some unit of code. - template - class ProfileInfoT { - public: - // Types for handling profiling information. - typedef std::pair Edge; - typedef std::pair EdgeWeight; - typedef std::map EdgeWeights; - typedef std::map BlockCounts; - typedef std::map Path; - - protected: - // EdgeInformation - Count the number of times a transition between two - // blocks is executed. As a special case, we also hold an edge from the - // null BasicBlock to the entry block to indicate how many times the - // function was entered. - std::map EdgeInformation; - - // BlockInformation - Count the number of times a block is executed. - std::map BlockInformation; - - // FunctionInformation - Count the number of times a function is executed. - std::map FunctionInformation; - - ProfileInfoT *MachineProfile; - public: - static char ID; // Class identification, replacement for typeinfo - ProfileInfoT(); - ~ProfileInfoT(); // We want to be subclassed - - // MissingValue - The value that is returned for execution counts in case - // no value is available. - static const double MissingValue; - - // getFunction() - Returns the Function for an Edge, checking for validity. - static const FType* getFunction(Edge e) { - if (e.first) - return e.first->getParent(); - if (e.second) - return e.second->getParent(); - llvm_unreachable("Invalid ProfileInfo::Edge"); - } - - // getEdge() - Creates an Edge from two BasicBlocks. - static Edge getEdge(const BType *Src, const BType *Dest) { - return std::make_pair(Src, Dest); - } - - //===------------------------------------------------------------------===// - /// Profile Information Queries - /// - double getExecutionCount(const FType *F); - - double getExecutionCount(const BType *BB); - - void setExecutionCount(const BType *BB, double w); - - void addExecutionCount(const BType *BB, double w); - - double getEdgeWeight(Edge e) const { - typename std::map::const_iterator J = - EdgeInformation.find(getFunction(e)); - if (J == EdgeInformation.end()) return MissingValue; - - typename EdgeWeights::const_iterator I = J->second.find(e); - if (I == J->second.end()) return MissingValue; - - return I->second; - } - - void setEdgeWeight(Edge e, double w) { - DEBUG_WITH_TYPE("profile-info", - dbgs() << "Creating Edge " << e - << " (weight: " << format("%.20g",w) << ")\n"); - EdgeInformation[getFunction(e)][e] = w; - } - - void addEdgeWeight(Edge e, double w); - - EdgeWeights &getEdgeWeights (const FType *F) { - return EdgeInformation[F]; - } - - //===------------------------------------------------------------------===// - /// Analysis Update Methods - /// - void removeBlock(const BType *BB); - - void removeEdge(Edge e); - - void replaceEdge(const Edge &, const Edge &); - - enum GetPathMode { - GetPathToExit = 1, - GetPathToValue = 2, - GetPathToDest = 4, - GetPathWithNewEdges = 8 - }; - - const BType *GetPath(const BType *Src, const BType *Dest, - Path &P, unsigned Mode); - - void divertFlow(const Edge &, const Edge &); - - void splitEdge(const BType *FirstBB, const BType *SecondBB, - const BType *NewBB, bool MergeIdenticalEdges = false); - - void splitBlock(const BType *Old, const BType* New); - - void splitBlock(const BType *BB, const BType* NewBB, - BType *const *Preds, unsigned NumPreds); - - void replaceAllUses(const BType *RmBB, const BType *DestBB); - - void transfer(const FType *Old, const FType *New); - - void repair(const FType *F); - - void dump(FType *F = 0, bool real = true) { - dbgs() << "**** This is ProfileInfo " << this << " speaking:\n"; - if (!real) { - typename std::set Functions; - - dbgs() << "Functions: \n"; - if (F) { - dbgs() << F << "@" << format("%p", F) << ": " << format("%.20g",getExecutionCount(F)) << "\n"; - Functions.insert(F); - } else { - for (typename std::map::iterator fi = FunctionInformation.begin(), - fe = FunctionInformation.end(); fi != fe; ++fi) { - dbgs() << fi->first << "@" << format("%p",fi->first) << ": " << format("%.20g",fi->second) << "\n"; - Functions.insert(fi->first); - } - } - - for (typename std::set::iterator FI = Functions.begin(), FE = Functions.end(); - FI != FE; ++FI) { - const FType *F = *FI; - typename std::map::iterator bwi = BlockInformation.find(F); - dbgs() << "BasicBlocks for Function " << F << ":\n"; - for (typename BlockCounts::const_iterator bi = bwi->second.begin(), be = bwi->second.end(); bi != be; ++bi) { - dbgs() << bi->first << "@" << format("%p", bi->first) << ": " << format("%.20g",bi->second) << "\n"; - } - } - - for (typename std::set::iterator FI = Functions.begin(), FE = Functions.end(); - FI != FE; ++FI) { - typename std::map::iterator ei = EdgeInformation.find(*FI); - dbgs() << "Edges for Function " << ei->first << ":\n"; - for (typename EdgeWeights::iterator ewi = ei->second.begin(), ewe = ei->second.end(); - ewi != ewe; ++ewi) { - dbgs() << ewi->first << ": " << format("%.20g",ewi->second) << "\n"; - } - } - } else { - assert(F && "No function given, this is not supported!"); - dbgs() << "Functions: \n"; - dbgs() << F << "@" << format("%p", F) << ": " << format("%.20g",getExecutionCount(F)) << "\n"; - - dbgs() << "BasicBlocks for Function " << F << ":\n"; - for (typename FType::const_iterator BI = F->begin(), BE = F->end(); - BI != BE; ++BI) { - const BType *BB = &(*BI); - dbgs() << BB << "@" << format("%p", BB) << ": " << format("%.20g",getExecutionCount(BB)) << "\n"; - } - } - dbgs() << "**** ProfileInfo " << this << ", over and out.\n"; - } - - bool CalculateMissingEdge(const BType *BB, Edge &removed, bool assumeEmptyExit = false); - - bool EstimateMissingEdges(const BType *BB); - - ProfileInfoT *MI() { - if (MachineProfile == 0) - MachineProfile = new ProfileInfoT(); - return MachineProfile; - } - - bool hasMI() const { - return (MachineProfile != 0); - } - }; - - typedef ProfileInfoT ProfileInfo; - typedef ProfileInfoT MachineProfileInfo; - - /// createProfileLoaderPass - This function returns a Pass that loads the - /// profiling information for the module from the specified filename, making - /// it available to the optimizers. - Pass *createProfileLoaderPass(const std::string &Filename); - -} // End llvm namespace - -#endif diff --git a/contrib/llvm/include/llvm/Analysis/ProfileInfoLoader.h b/contrib/llvm/include/llvm/Analysis/ProfileInfoLoader.h deleted file mode 100644 index e0f49f317..000000000 --- a/contrib/llvm/include/llvm/Analysis/ProfileInfoLoader.h +++ /dev/null @@ -1,81 +0,0 @@ -//===- ProfileInfoLoader.h - Load & convert profile information -*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// The ProfileInfoLoader class is used to load and represent profiling -// information read in from the dump file. If conversions between formats are -// needed, it can also do this. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_ANALYSIS_PROFILEINFOLOADER_H -#define LLVM_ANALYSIS_PROFILEINFOLOADER_H - -#include -#include -#include - -namespace llvm { - -class Module; -class Function; -class BasicBlock; - -class ProfileInfoLoader { - const std::string &Filename; - std::vector CommandLines; - std::vector FunctionCounts; - std::vector BlockCounts; - std::vector EdgeCounts; - std::vector OptimalEdgeCounts; - std::vector BBTrace; -public: - // ProfileInfoLoader ctor - Read the specified profiling data file, exiting - // the program if the file is invalid or broken. - ProfileInfoLoader(const char *ToolName, const std::string &Filename); - - static const unsigned Uncounted; - - unsigned getNumExecutions() const { return CommandLines.size(); } - const std::string &getExecution(unsigned i) const { return CommandLines[i]; } - - const std::string &getFileName() const { return Filename; } - - // getRawFunctionCounts - This method is used by consumers of function - // counting information. - // - const std::vector &getRawFunctionCounts() const { - return FunctionCounts; - } - - // getRawBlockCounts - This method is used by consumers of block counting - // information. - // - const std::vector &getRawBlockCounts() const { - return BlockCounts; - } - - // getEdgeCounts - This method is used by consumers of edge counting - // information. - // - const std::vector &getRawEdgeCounts() const { - return EdgeCounts; - } - - // getEdgeOptimalCounts - This method is used by consumers of optimal edge - // counting information. - // - const std::vector &getRawOptimalEdgeCounts() const { - return OptimalEdgeCounts; - } - -}; - -} // End llvm namespace - -#endif diff --git a/contrib/llvm/include/llvm/Analysis/ProfileInfoTypes.h b/contrib/llvm/include/llvm/Analysis/ProfileInfoTypes.h deleted file mode 100644 index 45aab5b70..000000000 --- a/contrib/llvm/include/llvm/Analysis/ProfileInfoTypes.h +++ /dev/null @@ -1,52 +0,0 @@ -/*===-- ProfileInfoTypes.h - Profiling info shared constants --------------===*\ -|* -|* The LLVM Compiler Infrastructure -|* -|* This file is distributed under the University of Illinois Open Source -|* License. See LICENSE.TXT for details. -|* -|*===----------------------------------------------------------------------===*| -|* -|* This file defines constants shared by the various different profiling -|* runtime libraries and the LLVM C++ profile info loader. It must be a -|* C header because, at present, the profiling runtimes are written in C. -|* -\*===----------------------------------------------------------------------===*/ - -#ifndef LLVM_ANALYSIS_PROFILEINFOTYPES_H -#define LLVM_ANALYSIS_PROFILEINFOTYPES_H - -/* Included by libprofile. */ -#if defined(__cplusplus) -extern "C" { -#endif - -/* IDs to distinguish between those path counters stored in hashses vs arrays */ -enum ProfilingStorageType { - ProfilingArray = 1, - ProfilingHash = 2 -}; - -#include "llvm/Analysis/ProfileDataTypes.h" - -/* - * The header for tables that map path numbers to path counters. - */ -typedef struct { - unsigned fnNumber; /* function number for these counters */ - unsigned numEntries; /* number of entries stored */ -} PathProfileHeader; - -/* - * Describes an entry in a tagged table for path counters. - */ -typedef struct { - unsigned pathNumber; - unsigned pathCounter; -} PathProfileTableEntry; - -#if defined(__cplusplus) -} -#endif - -#endif /* LLVM_ANALYSIS_PROFILEINFOTYPES_H */ diff --git a/contrib/llvm/include/llvm/Analysis/RegionPass.h b/contrib/llvm/include/llvm/Analysis/RegionPass.h index 0690ac5e3..3907ad9c7 100644 --- a/contrib/llvm/include/llvm/Analysis/RegionPass.h +++ b/contrib/llvm/include/llvm/Analysis/RegionPass.h @@ -18,8 +18,8 @@ #include "llvm/Analysis/RegionInfo.h" #include "llvm/IR/Function.h" +#include "llvm/IR/LegacyPassManagers.h" #include "llvm/Pass.h" -#include "llvm/PassManagers.h" #include namespace llvm { @@ -51,7 +51,7 @@ public: /// @brief Get a pass to print the LLVM IR in the region. /// - /// @param O The ouput stream to print the Region. + /// @param O The output stream to print the Region. /// @param Banner The banner to separate different printed passes. /// /// @return The pass to print the LLVM IR in the region. diff --git a/contrib/llvm/include/llvm/Analysis/ScalarEvolution.h b/contrib/llvm/include/llvm/Analysis/ScalarEvolution.h index 349447fbb..d7f617817 100644 --- a/contrib/llvm/include/llvm/Analysis/ScalarEvolution.h +++ b/contrib/llvm/include/llvm/Analysis/ScalarEvolution.h @@ -189,15 +189,16 @@ namespace llvm { /// Convenient NoWrapFlags manipulation that hides enum casts and is /// visible in the ScalarEvolution name space. - static SCEV::NoWrapFlags maskFlags(SCEV::NoWrapFlags Flags, int Mask) { + static SCEV::NoWrapFlags LLVM_ATTRIBUTE_UNUSED_RESULT + maskFlags(SCEV::NoWrapFlags Flags, int Mask) { return (SCEV::NoWrapFlags)(Flags & Mask); } - static SCEV::NoWrapFlags setFlags(SCEV::NoWrapFlags Flags, - SCEV::NoWrapFlags OnFlags) { + static SCEV::NoWrapFlags LLVM_ATTRIBUTE_UNUSED_RESULT + setFlags(SCEV::NoWrapFlags Flags, SCEV::NoWrapFlags OnFlags) { return (SCEV::NoWrapFlags)(Flags | OnFlags); } - static SCEV::NoWrapFlags clearFlags(SCEV::NoWrapFlags Flags, - SCEV::NoWrapFlags OffFlags) { + static SCEV::NoWrapFlags LLVM_ATTRIBUTE_UNUSED_RESULT + clearFlags(SCEV::NoWrapFlags Flags, SCEV::NoWrapFlags OffFlags) { return (SCEV::NoWrapFlags)(Flags & ~OffFlags); } @@ -361,18 +362,18 @@ namespace llvm { /// that we attempt to compute getSCEVAtScope information for, which can /// be expensive in extreme cases. DenseMap > ValuesAtScopes; + SmallVector, 2> > ValuesAtScopes; /// LoopDispositions - Memoized computeLoopDisposition results. DenseMap > LoopDispositions; + SmallVector, 2> > LoopDispositions; /// computeLoopDisposition - Compute a LoopDisposition value. LoopDisposition computeLoopDisposition(const SCEV *S, const Loop *L); /// BlockDispositions - Memoized computeBlockDisposition results. DenseMap > BlockDispositions; + SmallVector, 2> > BlockDispositions; /// computeBlockDisposition - Compute a BlockDisposition value. BlockDisposition computeBlockDisposition(const SCEV *S, const BasicBlock *BB); @@ -426,14 +427,6 @@ namespace llvm { /// resolution. void ForgetSymbolicName(Instruction *I, const SCEV *SymName); - /// getBECount - Subtract the end and start values and divide by the step, - /// rounding up, to get the number of times the backedge is executed. Return - /// CouldNotCompute if an intermediate computation overflows. - const SCEV *getBECount(const SCEV *Start, - const SCEV *End, - const SCEV *Step, - bool NoWrap); - /// getBackedgeTakenInfo - Return the BackedgeTakenInfo for the given /// loop, lazily computing new values if the loop hasn't been analyzed /// yet. @@ -498,6 +491,8 @@ namespace llvm { /// less-than is signed. ExitLimit HowManyLessThans(const SCEV *LHS, const SCEV *RHS, const Loop *L, bool isSigned, bool IsSubExpr); + ExitLimit HowManyGreaterThans(const SCEV *LHS, const SCEV *RHS, + const Loop *L, bool isSigned, bool IsSubExpr); /// getPredecessorWithUniqueSuccessorForBB - Return a predecessor of BB /// (which may not be an immediate predecessor) which has exactly one @@ -545,6 +540,10 @@ namespace llvm { /// forgetMemoizedResults - Drop memoized information computed for S. void forgetMemoizedResults(const SCEV *S); + /// Return false iff given SCEV contains a SCEVUnknown with NULL value- + /// pointer. + bool checkValidity(const SCEV *S) const; + public: static char ID; // Pass identification, replacement for typeid ScalarEvolution(); @@ -632,21 +631,15 @@ namespace llvm { const SCEV *getUnknown(Value *V); const SCEV *getCouldNotCompute(); - /// getSizeOfExpr - Return an expression for sizeof on the given type. - /// - const SCEV *getSizeOfExpr(Type *AllocTy); - - /// getAlignOfExpr - Return an expression for alignof on the given type. + /// getSizeOfExpr - Return an expression for sizeof AllocTy that is type + /// IntTy /// - const SCEV *getAlignOfExpr(Type *AllocTy); + const SCEV *getSizeOfExpr(Type *IntTy, Type *AllocTy); - /// getOffsetOfExpr - Return an expression for offsetof on the given field. + /// getOffsetOfExpr - Return an expression for offsetof on the given field + /// with type IntTy /// - const SCEV *getOffsetOfExpr(StructType *STy, unsigned FieldNo); - - /// getOffsetOfExpr - Return an expression for offsetof on the given field. - /// - const SCEV *getOffsetOfExpr(Type *CTy, Constant *FieldNo); + const SCEV *getOffsetOfExpr(Type *IntTy, StructType *STy, unsigned FieldNo); /// getNegativeSCEV - Return the SCEV object corresponding to -V. /// @@ -881,6 +874,24 @@ namespace llvm { virtual void print(raw_ostream &OS, const Module* = 0) const; virtual void verifyAnalysis() const; + private: + /// Compute the backedge taken count knowing the interval difference, the + /// stride and presence of the equality in the comparison. + const SCEV *computeBECount(const SCEV *Delta, const SCEV *Stride, + bool Equality); + + /// Verify if an linear IV with positive stride can overflow when in a + /// less-than comparison, knowing the invariant term of the comparison, + /// the stride and the knowledge of NSW/NUW flags on the recurrence. + bool doesIVOverflowOnLT(const SCEV *RHS, const SCEV *Stride, + bool IsSigned, bool NoWrap); + + /// Verify if an linear IV with negative stride can overflow when in a + /// greater-than comparison, knowing the invariant term of the comparison, + /// the stride and the knowledge of NSW/NUW flags on the recurrence. + bool doesIVOverflowOnGT(const SCEV *RHS, const SCEV *Stride, + bool IsSigned, bool NoWrap); + private: FoldingSet UniqueSCEVs; BumpPtrAllocator SCEVAllocator; diff --git a/contrib/llvm/include/llvm/Analysis/ScalarEvolutionExpander.h b/contrib/llvm/include/llvm/Analysis/ScalarEvolutionExpander.h index 00779fc32..4433be000 100644 --- a/contrib/llvm/include/llvm/Analysis/ScalarEvolutionExpander.h +++ b/contrib/llvm/include/llvm/Analysis/ScalarEvolutionExpander.h @@ -26,7 +26,7 @@ namespace llvm { /// Return true if the given expression is safe to expand in the sense that /// all materialized values are safe to speculate. - bool isSafeToExpand(const SCEV *S); + bool isSafeToExpand(const SCEV *S, ScalarEvolution &SE); /// SCEVExpander - This class uses information about analyze scalars to /// rewrite expressions in canonical form. @@ -252,8 +252,6 @@ namespace llvm { void rememberInstruction(Value *I); - void restoreInsertPoint(BasicBlock *BB, BasicBlock::iterator I); - bool isNormalAddRecExprPHI(PHINode *PN, Instruction *IncV, const Loop *L); bool isExpandedAddRecExprPHI(PHINode *PN, Instruction *IncV, const Loop *L); diff --git a/contrib/llvm/include/llvm/Analysis/ScalarEvolutionExpressions.h b/contrib/llvm/include/llvm/Analysis/ScalarEvolutionExpressions.h index eac91131a..9cd902a12 100644 --- a/contrib/llvm/include/llvm/Analysis/ScalarEvolutionExpressions.h +++ b/contrib/llvm/include/llvm/Analysis/ScalarEvolutionExpressions.h @@ -351,8 +351,14 @@ namespace llvm { static inline bool classof(const SCEV *S) { return S->getSCEVType() == scAddRecExpr; } - }; + /// Splits the SCEV into two vectors of SCEVs representing the subscripts + /// and sizes of an array access. Returns the remainder of the + /// delinearization that is the offset start of the array. + const SCEV *delinearize(ScalarEvolution &SE, + SmallVectorImpl &Subscripts, + SmallVectorImpl &Sizes) const; + }; //===--------------------------------------------------------------------===// /// SCEVSMaxExpr - This class represents a signed maximum selection. @@ -549,53 +555,60 @@ namespace llvm { T.visitAll(Root); } - /// The SCEVRewriter takes a scalar evolution expression and copies all its - /// components. The result after a rewrite is an identical SCEV. - struct SCEVRewriter - : public SCEVVisitor { + typedef DenseMap ValueToValueMap; + + /// The SCEVParameterRewriter takes a scalar evolution expression and updates + /// the SCEVUnknown components following the Map (Value -> Value). + struct SCEVParameterRewriter + : public SCEVVisitor { public: - SCEVRewriter(ScalarEvolution &S) : SE(S) {} + static const SCEV *rewrite(const SCEV *Scev, ScalarEvolution &SE, + ValueToValueMap &Map) { + SCEVParameterRewriter Rewriter(SE, Map); + return Rewriter.visit(Scev); + } - virtual ~SCEVRewriter() {} + SCEVParameterRewriter(ScalarEvolution &S, ValueToValueMap &M) + : SE(S), Map(M) {} - virtual const SCEV *visitConstant(const SCEVConstant *Constant) { + const SCEV *visitConstant(const SCEVConstant *Constant) { return Constant; } - virtual const SCEV *visitTruncateExpr(const SCEVTruncateExpr *Expr) { + const SCEV *visitTruncateExpr(const SCEVTruncateExpr *Expr) { const SCEV *Operand = visit(Expr->getOperand()); return SE.getTruncateExpr(Operand, Expr->getType()); } - virtual const SCEV *visitZeroExtendExpr(const SCEVZeroExtendExpr *Expr) { + const SCEV *visitZeroExtendExpr(const SCEVZeroExtendExpr *Expr) { const SCEV *Operand = visit(Expr->getOperand()); return SE.getZeroExtendExpr(Operand, Expr->getType()); } - virtual const SCEV *visitSignExtendExpr(const SCEVSignExtendExpr *Expr) { + const SCEV *visitSignExtendExpr(const SCEVSignExtendExpr *Expr) { const SCEV *Operand = visit(Expr->getOperand()); return SE.getSignExtendExpr(Operand, Expr->getType()); } - virtual const SCEV *visitAddExpr(const SCEVAddExpr *Expr) { + const SCEV *visitAddExpr(const SCEVAddExpr *Expr) { SmallVector Operands; for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) Operands.push_back(visit(Expr->getOperand(i))); return SE.getAddExpr(Operands); } - virtual const SCEV *visitMulExpr(const SCEVMulExpr *Expr) { + const SCEV *visitMulExpr(const SCEVMulExpr *Expr) { SmallVector Operands; for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) Operands.push_back(visit(Expr->getOperand(i))); return SE.getMulExpr(Operands); } - virtual const SCEV *visitUDivExpr(const SCEVUDivExpr *Expr) { + const SCEV *visitUDivExpr(const SCEVUDivExpr *Expr) { return SE.getUDivExpr(visit(Expr->getLHS()), visit(Expr->getRHS())); } - virtual const SCEV *visitAddRecExpr(const SCEVAddRecExpr *Expr) { + const SCEV *visitAddRecExpr(const SCEVAddRecExpr *Expr) { SmallVector Operands; for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) Operands.push_back(visit(Expr->getOperand(i))); @@ -603,54 +616,33 @@ namespace llvm { Expr->getNoWrapFlags()); } - virtual const SCEV *visitSMaxExpr(const SCEVSMaxExpr *Expr) { + const SCEV *visitSMaxExpr(const SCEVSMaxExpr *Expr) { SmallVector Operands; for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) Operands.push_back(visit(Expr->getOperand(i))); return SE.getSMaxExpr(Operands); } - virtual const SCEV *visitUMaxExpr(const SCEVUMaxExpr *Expr) { + const SCEV *visitUMaxExpr(const SCEVUMaxExpr *Expr) { SmallVector Operands; for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) Operands.push_back(visit(Expr->getOperand(i))); return SE.getUMaxExpr(Operands); } - virtual const SCEV *visitUnknown(const SCEVUnknown *Expr) { - return Expr; - } - - virtual const SCEV *visitCouldNotCompute(const SCEVCouldNotCompute *Expr) { - return Expr; - } - - protected: - ScalarEvolution &SE; - }; - - typedef DenseMap ValueToValueMap; - - /// The SCEVParameterRewriter takes a scalar evolution expression and updates - /// the SCEVUnknown components following the Map (Value -> Value). - struct SCEVParameterRewriter: public SCEVRewriter { - public: - static const SCEV *rewrite(const SCEV *Scev, ScalarEvolution &SE, - ValueToValueMap &Map) { - SCEVParameterRewriter Rewriter(SE, Map); - return Rewriter.visit(Scev); - } - SCEVParameterRewriter(ScalarEvolution &S, ValueToValueMap &M) - : SCEVRewriter(S), Map(M) {} - - virtual const SCEV *visitUnknown(const SCEVUnknown *Expr) { + const SCEV *visitUnknown(const SCEVUnknown *Expr) { Value *V = Expr->getValue(); if (Map.count(V)) return SE.getUnknown(Map[V]); return Expr; } + const SCEV *visitCouldNotCompute(const SCEVCouldNotCompute *Expr) { + return Expr; + } + private: + ScalarEvolution &SE; ValueToValueMap ⤅ }; @@ -658,17 +650,56 @@ namespace llvm { /// The SCEVApplyRewriter takes a scalar evolution expression and applies /// the Map (Loop -> SCEV) to all AddRecExprs. - struct SCEVApplyRewriter: public SCEVRewriter { + struct SCEVApplyRewriter + : public SCEVVisitor { public: static const SCEV *rewrite(const SCEV *Scev, LoopToScevMapT &Map, ScalarEvolution &SE) { SCEVApplyRewriter Rewriter(SE, Map); return Rewriter.visit(Scev); } + SCEVApplyRewriter(ScalarEvolution &S, LoopToScevMapT &M) - : SCEVRewriter(S), Map(M) {} + : SE(S), Map(M) {} + + const SCEV *visitConstant(const SCEVConstant *Constant) { + return Constant; + } + + const SCEV *visitTruncateExpr(const SCEVTruncateExpr *Expr) { + const SCEV *Operand = visit(Expr->getOperand()); + return SE.getTruncateExpr(Operand, Expr->getType()); + } + + const SCEV *visitZeroExtendExpr(const SCEVZeroExtendExpr *Expr) { + const SCEV *Operand = visit(Expr->getOperand()); + return SE.getZeroExtendExpr(Operand, Expr->getType()); + } + + const SCEV *visitSignExtendExpr(const SCEVSignExtendExpr *Expr) { + const SCEV *Operand = visit(Expr->getOperand()); + return SE.getSignExtendExpr(Operand, Expr->getType()); + } + + const SCEV *visitAddExpr(const SCEVAddExpr *Expr) { + SmallVector Operands; + for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) + Operands.push_back(visit(Expr->getOperand(i))); + return SE.getAddExpr(Operands); + } + + const SCEV *visitMulExpr(const SCEVMulExpr *Expr) { + SmallVector Operands; + for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) + Operands.push_back(visit(Expr->getOperand(i))); + return SE.getMulExpr(Operands); + } - virtual const SCEV *visitAddRecExpr(const SCEVAddRecExpr *Expr) { + const SCEV *visitUDivExpr(const SCEVUDivExpr *Expr) { + return SE.getUDivExpr(visit(Expr->getLHS()), visit(Expr->getRHS())); + } + + const SCEV *visitAddRecExpr(const SCEVAddRecExpr *Expr) { SmallVector Operands; for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) Operands.push_back(visit(Expr->getOperand(i))); @@ -683,7 +714,30 @@ namespace llvm { return Rec->evaluateAtIteration(Map[L], SE); } + const SCEV *visitSMaxExpr(const SCEVSMaxExpr *Expr) { + SmallVector Operands; + for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) + Operands.push_back(visit(Expr->getOperand(i))); + return SE.getSMaxExpr(Operands); + } + + const SCEV *visitUMaxExpr(const SCEVUMaxExpr *Expr) { + SmallVector Operands; + for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) + Operands.push_back(visit(Expr->getOperand(i))); + return SE.getUMaxExpr(Operands); + } + + const SCEV *visitUnknown(const SCEVUnknown *Expr) { + return Expr; + } + + const SCEV *visitCouldNotCompute(const SCEVCouldNotCompute *Expr) { + return Expr; + } + private: + ScalarEvolution &SE; LoopToScevMapT ⤅ }; diff --git a/contrib/llvm/include/llvm/Analysis/TargetTransformInfo.h b/contrib/llvm/include/llvm/Analysis/TargetTransformInfo.h index a9d6725d8..4f4756238 100644 --- a/contrib/llvm/include/llvm/Analysis/TargetTransformInfo.h +++ b/contrib/llvm/include/llvm/Analysis/TargetTransformInfo.h @@ -29,6 +29,7 @@ namespace llvm { class GlobalValue; +class Loop; class Type; class User; class Value; @@ -171,6 +172,12 @@ public: /// comments for a detailed explanation of the cost values. virtual 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; + /// \brief Test whether calls to a function lower to actual program function /// calls. /// @@ -185,6 +192,36 @@ public: /// incurs significant execution cost. virtual bool isLoweredToCall(const Function *F) const; + /// Parameters that control the generic loop unrolling transformation. + struct UnrollingPreferences { + /// The cost threshold for the unrolled loop, compared to + /// CodeMetrics.NumInsts aggregated over all basic blocks in the loop body. + /// The unrolling factor is set such that the unrolled loop body does not + /// exceed this cost. Set this to UINT_MAX to disable the loop body cost + /// restriction. + unsigned Threshold; + /// The cost threshold for the unrolled loop when optimizing for size (set + /// to UINT_MAX to disable). + unsigned OptSizeThreshold; + /// A forced unrolling factor (the number of concatenated bodies of the + /// original loop in the unrolled loop body). When set to 0, the unrolling + /// transformation will select an unrolling factor based on the current cost + /// threshold and other factors. + unsigned Count; + /// 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; + /// 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; + }; + + /// \brief Get target-customized preferences for the generic loop unrolling + /// transformation. The caller will initialize UP with the current + /// target-independent defaults. + virtual void getUnrollingPreferences(Loop *L, UnrollingPreferences &UP) const; + /// @} /// \name Scalar Target Information @@ -225,6 +262,16 @@ public: int64_t BaseOffset, bool HasBaseReg, int64_t Scale) const; + /// \brief Return the cost of the scaling factor used in the addressing + /// mode represented by AM for this target, for a load/store + /// of the specified type. + /// 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; + /// isTruncateFree - 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. @@ -246,6 +293,10 @@ public: /// getPopcntSupport - Return hardware support for population count. virtual PopcntSupportKind getPopcntSupport(unsigned IntTyWidthInBit) const; + /// haveFastSqrt -- Return true if the hardware has a fast square-root + /// instruction. + virtual bool haveFastSqrt(Type *Ty) const; + /// getIntImmCost - Return the expected cost of materializing the given /// integer immediate of the specified type. virtual unsigned getIntImmCost(const APInt &Imm, Type *Ty) const; @@ -263,7 +314,7 @@ public: SK_ExtractSubvector ///< ExtractSubvector Index indicates start offset. }; - /// \brief Additonal information about an operand's possible values. + /// \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). @@ -317,6 +368,22 @@ public: unsigned Alignment, unsigned AddressSpace) const; + /// \brief Calculate the cost of performing a vector reduction. + /// + /// This is the cost of reducing the vector value of type \p Ty to a scalar + /// value using the operation denoted by \p Opcode. The form of the reduction + /// can either be a pairwise reduction or a reduction that splits the vector + /// at every reduction level. + /// + /// Pairwise: + /// (v0, v1, v2, v3) + /// ((v0+v1), (v2, v3), undef, undef) + /// Split: + /// (v0, v1, v2, v3) + /// ((v0+v2), (v1+v3), undef, undef) + virtual 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; @@ -329,7 +396,11 @@ public: /// merged into the instruction indexing mode. Some targets might want to /// distinguish between address computation for memory operations on vector /// types and scalar types. Such targets should override this function. - virtual unsigned getAddressComputationCost(Type *Ty) const; + /// 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; /// @} diff --git a/contrib/llvm/include/llvm/Analysis/ValueTracking.h b/contrib/llvm/include/llvm/Analysis/ValueTracking.h index 3775ec9f0..0392f98f0 100644 --- a/contrib/llvm/include/llvm/Analysis/ValueTracking.h +++ b/contrib/llvm/include/llvm/Analysis/ValueTracking.h @@ -25,6 +25,7 @@ namespace llvm { class DataLayout; class StringRef; class MDNode; + class TargetLibraryInfo; /// ComputeMaskedBits - Determine which of the bits specified in Mask are /// known to be either zero or one and return them in the KnownZero/KnownOne @@ -186,7 +187,7 @@ namespace llvm { /// isKnownNonNull - Return true if this pointer couldn't possibly be null by /// its definition. This returns true for allocas, non-extern-weak globals /// and byval arguments. - bool isKnownNonNull(const Value *V); + bool isKnownNonNull(const Value *V, const TargetLibraryInfo *TLI = 0); } // end namespace llvm diff --git a/contrib/llvm/include/llvm/AutoUpgrade.h b/contrib/llvm/include/llvm/AutoUpgrade.h index e13c4c12b..c774782f1 100644 --- a/contrib/llvm/include/llvm/AutoUpgrade.h +++ b/contrib/llvm/include/llvm/AutoUpgrade.h @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// // -// These functions are implemented by lib/VMCore/AutoUpgrade.cpp. +// These functions are implemented by lib/IR/AutoUpgrade.cpp. // //===----------------------------------------------------------------------===// @@ -15,30 +15,52 @@ #define LLVM_AUTOUPGRADE_H namespace llvm { + class CallInst; + class Constant; + class Function; + class Instruction; class Module; class GlobalVariable; - class Function; - class CallInst; + class Type; + class Value; - /// This is a more granular function that simply checks an intrinsic function + /// This is a more granular function that simply checks an intrinsic function /// for upgrading, and returns true if it requires upgrading. It may return /// null in NewFn if the all calls to the original intrinsic function /// should be transformed to non-function-call instructions. bool UpgradeIntrinsicFunction(Function *F, Function *&NewFn); - /// This is the complement to the above, replacing a specific call to an + /// This is the complement to the above, replacing a specific call to an /// intrinsic function with a call to the specified new function. void UpgradeIntrinsicCall(CallInst *CI, Function *NewFn); - - /// This is an auto-upgrade hook for any old intrinsic function syntaxes - /// which need to have both the function updated as well as all calls updated - /// to the new function. This should only be run in a post-processing fashion + + /// This is an auto-upgrade hook for any old intrinsic function syntaxes + /// which need to have both the function updated as well as all calls updated + /// to the new function. This should only be run in a post-processing fashion /// so that it can update all calls to the old function. void UpgradeCallsToIntrinsic(Function* F); /// This checks for global variables which should be upgraded. It returns true /// if it requires upgrading. bool UpgradeGlobalVariable(GlobalVariable *GV); + + /// If the TBAA tag for the given instruction uses the scalar TBAA format, + /// we upgrade it to the struct-path aware TBAA format. + void UpgradeInstWithTBAATag(Instruction *I); + + /// This is an auto-upgrade for bitcast between pointers with different + /// address spaces: the instruction is replaced by a pair ptrtoint+inttoptr. + Instruction *UpgradeBitCastInst(unsigned Opc, Value *V, Type *DestTy, + Instruction *&Temp); + + /// This is an auto-upgrade for bitcast constant expression between pointers + /// with different address spaces: the instruction is replaced by a pair + /// ptrtoint+inttoptr. + Value *UpgradeBitCastExpr(unsigned Opc, Constant *C, Type *DestTy); + + /// Check the debug info version number, if it is out-dated, drop the debug + /// info. Return true if module is modified. + bool UpgradeDebugInfo(Module &M); } // End llvm namespace #endif diff --git a/contrib/llvm/include/llvm/Bitcode/Archive.h b/contrib/llvm/include/llvm/Bitcode/Archive.h deleted file mode 100644 index 7b30c7e45..000000000 --- a/contrib/llvm/include/llvm/Bitcode/Archive.h +++ /dev/null @@ -1,538 +0,0 @@ -//===-- llvm/Bitcode/Archive.h - LLVM Bitcode Archive -----------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This header file declares the Archive and ArchiveMember classes that provide -// manipulation of LLVM Archive files. The implementation is provided by the -// lib/Bitcode/Archive library. This library is used to read and write -// archive (*.a) files that contain LLVM bitcode files (or others). -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_BITCODE_ARCHIVE_H -#define LLVM_BITCODE_ARCHIVE_H - -#include "llvm/ADT/ilist.h" -#include "llvm/ADT/ilist_node.h" -#include "llvm/Support/Path.h" -#include -#include - -namespace llvm { - class MemoryBuffer; - -// Forward declare classes -class Module; // From VMCore -class Archive; // Declared below -class ArchiveMemberHeader; // Internal implementation class -class LLVMContext; // Global data - -/// This class is the main class manipulated by users of the Archive class. It -/// holds information about one member of the Archive. It is also the element -/// stored by the Archive's ilist, the Archive's main abstraction. Because of -/// the special requirements of archive files, users are not permitted to -/// construct ArchiveMember instances. You should obtain them from the methods -/// of the Archive class instead. -/// @brief This class represents a single archive member. -class ArchiveMember : public ilist_node { - /// @name Types - /// @{ - public: - /// These flags are used internally by the archive member to specify various - /// characteristics of the member. The various "is" methods below provide - /// access to the flags. The flags are not user settable. - enum Flags { - SVR4SymbolTableFlag = 1, ///< Member is a SVR4 symbol table - BSD4SymbolTableFlag = 2, ///< Member is a BSD4 symbol table - LLVMSymbolTableFlag = 4, ///< Member is an LLVM symbol table - BitcodeFlag = 8, ///< Member is bitcode - HasPathFlag = 16, ///< Member has a full or partial path - HasLongFilenameFlag = 32, ///< Member uses the long filename syntax - StringTableFlag = 64 ///< Member is an ar(1) format string table - }; - - /// @} - /// @name Accessors - /// @{ - public: - /// @returns the parent Archive instance - /// @brief Get the archive associated with this member - Archive* getArchive() const { return parent; } - - /// @returns the path to the Archive's file - /// @brief Get the path to the archive member - const sys::Path& getPath() const { return path; } - - /// The "user" is the owner of the file per Unix security. This may not - /// have any applicability on non-Unix systems but is a required component - /// of the "ar" file format. - /// @brief Get the user associated with this archive member. - unsigned getUser() const { return info.getUser(); } - - /// The "group" is the owning group of the file per Unix security. This - /// may not have any applicability on non-Unix systems but is a required - /// component of the "ar" file format. - /// @brief Get the group associated with this archive member. - unsigned getGroup() const { return info.getGroup(); } - - /// The "mode" specifies the access permissions for the file per Unix - /// security. This may not have any applicability on non-Unix systems but is - /// a required component of the "ar" file format. - /// @brief Get the permission mode associated with this archive member. - unsigned getMode() const { return info.getMode(); } - - /// This method returns the time at which the archive member was last - /// modified when it was not in the archive. - /// @brief Get the time of last modification of the archive member. - sys::TimeValue getModTime() const { return info.getTimestamp(); } - - /// @returns the size of the archive member in bytes. - /// @brief Get the size of the archive member. - uint64_t getSize() const { return info.getSize(); } - - /// This method returns the total size of the archive member as it - /// appears on disk. This includes the file content, the header, the - /// long file name if any, and the padding. - /// @brief Get total on-disk member size. - unsigned getMemberSize() const; - - /// This method will return a pointer to the in-memory content of the - /// archive member, if it is available. If the data has not been loaded - /// into memory, the return value will be null. - /// @returns a pointer to the member's data. - /// @brief Get the data content of the archive member - const char* getData() const { return data; } - - /// @returns true iff the member is a SVR4 (non-LLVM) symbol table - /// @brief Determine if this member is a SVR4 symbol table. - bool isSVR4SymbolTable() const { return flags&SVR4SymbolTableFlag; } - - /// @returns true iff the member is a BSD4.4 (non-LLVM) symbol table - /// @brief Determine if this member is a BSD4.4 symbol table. - bool isBSD4SymbolTable() const { return flags&BSD4SymbolTableFlag; } - - /// @returns true iff the archive member is the LLVM symbol table - /// @brief Determine if this member is the LLVM symbol table. - bool isLLVMSymbolTable() const { return flags&LLVMSymbolTableFlag; } - - /// @returns true iff the archive member is the ar(1) string table - /// @brief Determine if this member is the ar(1) string table. - bool isStringTable() const { return flags&StringTableFlag; } - - /// @returns true iff the archive member is a bitcode file. - /// @brief Determine if this member is a bitcode file. - bool isBitcode() const { return flags&BitcodeFlag; } - - /// @returns true iff the file name contains a path (directory) component. - /// @brief Determine if the member has a path - bool hasPath() const { return flags&HasPathFlag; } - - /// Long filenames are an artifact of the ar(1) file format which allows - /// up to sixteen characters in its header and doesn't allow a path - /// separator character (/). To avoid this, a "long format" member name is - /// allowed that doesn't have this restriction. This method determines if - /// that "long format" is used for this member. - /// @returns true iff the file name uses the long form - /// @brief Determine if the member has a long file name - bool hasLongFilename() const { return flags&HasLongFilenameFlag; } - - /// This method returns the status info (like Unix stat(2)) for the archive - /// member. The status info provides the file's size, permissions, and - /// modification time. The contents of the Path::StatusInfo structure, other - /// than the size and modification time, may not have utility on non-Unix - /// systems. - /// @returns the status info for the archive member - /// @brief Obtain the status info for the archive member - const sys::FileStatus &getFileStatus() const { return info; } - - /// This method causes the archive member to be replaced with the contents - /// of the file specified by \p File. The contents of \p this will be - /// updated to reflect the new data from \p File. The \p File must exist and - /// be readable on entry to this method. - /// @returns true if an error occurred, false otherwise - /// @brief Replace contents of archive member with a new file. - bool replaceWith(const sys::Path &aFile, std::string* ErrMsg); - - /// @} - /// @name Data - /// @{ - private: - Archive* parent; ///< Pointer to parent archive - sys::PathWithStatus path; ///< Path of file containing the member - sys::FileStatus info; ///< Status info (size,mode,date) - unsigned flags; ///< Flags about the archive member - const char* data; ///< Data for the member - - /// @} - /// @name Constructors - /// @{ - public: - /// The default constructor is only used by the Archive's iplist when it - /// constructs the list's sentry node. - ArchiveMember(); - - private: - /// Used internally by the Archive class to construct an ArchiveMember. - /// The contents of the ArchiveMember are filled out by the Archive class. - explicit ArchiveMember(Archive *PAR); - - // So Archive can construct an ArchiveMember - friend class llvm::Archive; - /// @} -}; - -/// This class defines the interface to LLVM Archive files. The Archive class -/// presents the archive file as an ilist of ArchiveMember objects. The members -/// can be rearranged in any fashion either by directly editing the ilist or by -/// using editing methods on the Archive class (recommended). The Archive -/// class also provides several ways of accessing the archive file for various -/// purposes such as editing and linking. Full symbol table support is provided -/// for loading only those files that resolve symbols. Note that read -/// performance of this library is _crucial_ for performance of JIT type -/// applications and the linkers. Consequently, the implementation of the class -/// is optimized for reading. -class Archive { - - /// @name Types - /// @{ - public: - /// This is the ilist type over which users may iterate to examine - /// the contents of the archive - /// @brief The ilist type of ArchiveMembers that Archive contains. - typedef iplist MembersList; - - /// @brief Forward mutable iterator over ArchiveMember - typedef MembersList::iterator iterator; - - /// @brief Forward immutable iterator over ArchiveMember - typedef MembersList::const_iterator const_iterator; - - /// @brief Reverse mutable iterator over ArchiveMember - typedef std::reverse_iterator reverse_iterator; - - /// @brief Reverse immutable iterator over ArchiveMember - typedef std::reverse_iterator const_reverse_iterator; - - /// @brief The in-memory version of the symbol table - typedef std::map SymTabType; - - /// @} - /// @name ilist accessor methods - /// @{ - public: - inline iterator begin() { return members.begin(); } - inline const_iterator begin() const { return members.begin(); } - inline iterator end () { return members.end(); } - inline const_iterator end () const { return members.end(); } - - inline reverse_iterator rbegin() { return members.rbegin(); } - inline const_reverse_iterator rbegin() const { return members.rbegin(); } - inline reverse_iterator rend () { return members.rend(); } - inline const_reverse_iterator rend () const { return members.rend(); } - - inline size_t size() const { return members.size(); } - inline bool empty() const { return members.empty(); } - inline const ArchiveMember& front() const { return members.front(); } - inline ArchiveMember& front() { return members.front(); } - inline const ArchiveMember& back() const { return members.back(); } - inline ArchiveMember& back() { return members.back(); } - - /// @} - /// @name ilist mutator methods - /// @{ - public: - /// This method splices a \p src member from an archive (possibly \p this), - /// to a position just before the member given by \p dest in \p this. When - /// the archive is written, \p src will be written in its new location. - /// @brief Move a member to a new location - inline void splice(iterator dest, Archive& arch, iterator src) - { return members.splice(dest,arch.members,src); } - - /// This method erases a \p target member from the archive. When the - /// archive is written, it will no longer contain \p target. The associated - /// ArchiveMember is deleted. - /// @brief Erase a member. - inline iterator erase(iterator target) { return members.erase(target); } - - /// @} - /// @name Constructors - /// @{ - public: - /// Create an empty archive file and associate it with the \p Filename. This - /// method does not actually create the archive disk file. It creates an - /// empty Archive object. If the writeToDisk method is called, the archive - /// file \p Filename will be created at that point, with whatever content - /// the returned Archive object has at that time. - /// @returns An Archive* that represents the new archive file. - /// @brief Create an empty Archive. - static Archive* CreateEmpty( - const sys::Path& Filename,///< Name of the archive to (eventually) create. - LLVMContext& C ///< Context to use for global information - ); - - /// Open an existing archive and load its contents in preparation for - /// editing. After this call, the member ilist is completely populated based - /// on the contents of the archive file. You should use this form of open if - /// you intend to modify the archive or traverse its contents (e.g. for - /// printing). - /// @brief Open and load an archive file - static Archive* OpenAndLoad( - const sys::Path& filePath, ///< The file path to open and load - LLVMContext& C, ///< The context to use for global information - std::string* ErrorMessage ///< An optional error string - ); - - /// This method opens an existing archive file from \p Filename and reads in - /// its symbol table without reading in any of the archive's members. This - /// reduces both I/O and cpu time in opening the archive if it is to be used - /// solely for symbol lookup (e.g. during linking). The \p Filename must - /// exist and be an archive file or an error will be returned. This form - /// of opening the archive is intended for read-only operations that need to - /// locate members via the symbol table for link editing. Since the archve - /// members are not read by this method, the archive will appear empty upon - /// return. If editing operations are performed on the archive, they will - /// completely replace the contents of the archive! It is recommended that - /// if this form of opening the archive is used that only the symbol table - /// lookup methods (getSymbolTable, findModuleDefiningSymbol, and - /// findModulesDefiningSymbols) be used. - /// @returns an Archive* that represents the archive file, or null on error. - /// @brief Open an existing archive and load its symbols. - static Archive* OpenAndLoadSymbols( - const sys::Path& Filename, ///< Name of the archive file to open - LLVMContext& C, ///< The context to use for global info - std::string* ErrorMessage=0 ///< An optional error string - ); - - /// This destructor cleans up the Archive object, releases all memory, and - /// closes files. It does nothing with the archive file on disk. If you - /// haven't used the writeToDisk method by the time the destructor is - /// called, all changes to the archive will be lost. - /// @brief Destruct in-memory archive - ~Archive(); - - /// @} - /// @name Accessors - /// @{ - public: - /// @returns the path to the archive file. - /// @brief Get the archive path. - const sys::Path& getPath() { return archPath; } - - /// This method is provided so that editing methods can be invoked directly - /// on the Archive's iplist of ArchiveMember. However, it is recommended - /// that the usual STL style iterator interface be used instead. - /// @returns the iplist of ArchiveMember - /// @brief Get the iplist of the members - MembersList& getMembers() { return members; } - - /// This method allows direct query of the Archive's symbol table. The - /// symbol table is a std::map of std::string (the symbol) to unsigned (the - /// file offset). Note that for efficiency reasons, the offset stored in - /// the symbol table is not the actual offset. It is the offset from the - /// beginning of the first "real" file member (after the symbol table). Use - /// the getFirstFileOffset() to obtain that offset and add this value to the - /// offset in the symbol table to obtain the real file offset. Note that - /// there is purposefully no interface provided by Archive to look up - /// members by their offset. Use the findModulesDefiningSymbols and - /// findModuleDefiningSymbol methods instead. - /// @returns the Archive's symbol table. - /// @brief Get the archive's symbol table - const SymTabType& getSymbolTable() { return symTab; } - - /// This method returns the offset in the archive file to the first "real" - /// file member. Archive files, on disk, have a signature and might have a - /// symbol table that precedes the first actual file member. This method - /// allows you to determine what the size of those fields are. - /// @returns the offset to the first "real" file member in the archive. - /// @brief Get the offset to the first "real" file member in the archive. - unsigned getFirstFileOffset() { return firstFileOffset; } - - /// This method will scan the archive for bitcode modules, interpret them - /// and return a vector of the instantiated modules in \p Modules. If an - /// error occurs, this method will return true. If \p ErrMessage is not null - /// and an error occurs, \p *ErrMessage will be set to a string explaining - /// the error that occurred. - /// @returns true if an error occurred - /// @brief Instantiate all the bitcode modules located in the archive - bool getAllModules(std::vector& Modules, std::string* ErrMessage); - - /// This accessor looks up the \p symbol in the archive's symbol table and - /// returns the associated module that defines that symbol. This method can - /// be called as many times as necessary. This is handy for linking the - /// archive into another module based on unresolved symbols. Note that the - /// Module returned by this accessor should not be deleted by the caller. It - /// is managed internally by the Archive class. It is possible that multiple - /// calls to this accessor will return the same Module instance because the - /// associated module defines multiple symbols. - /// @returns The Module* found or null if the archive does not contain a - /// module that defines the \p symbol. - /// @brief Look up a module by symbol name. - Module* findModuleDefiningSymbol( - const std::string& symbol, ///< Symbol to be sought - std::string* ErrMessage ///< Error message storage, if non-zero - ); - - /// This method is similar to findModuleDefiningSymbol but allows lookup of - /// more than one symbol at a time. If \p symbols contains a list of - /// undefined symbols in some module, then calling this method is like - /// making one complete pass through the archive to resolve symbols but is - /// more efficient than looking at the individual members. Note that on - /// exit, the symbols resolved by this method will be removed from \p - /// symbols to ensure they are not re-searched on a subsequent call. If - /// you need to retain the list of symbols, make a copy. - /// @brief Look up multiple symbols in the archive. - bool findModulesDefiningSymbols( - std::set& symbols, ///< Symbols to be sought - SmallVectorImpl& modules, ///< The modules matching \p symbols - std::string* ErrMessage ///< Error msg storage, if non-zero - ); - - /// This method determines whether the archive is a properly formed llvm - /// bitcode archive. It first makes sure the symbol table has been loaded - /// and has a non-zero size. If it does, then it is an archive. If not, - /// then it tries to load all the bitcode modules of the archive. Finally, - /// it returns whether it was successful. - /// @returns true if the archive is a proper llvm bitcode archive - /// @brief Determine whether the archive is a proper llvm bitcode archive. - bool isBitcodeArchive(); - - /// @} - /// @name Mutators - /// @{ - public: - /// This method is the only way to get the archive written to disk. It - /// creates or overwrites the file specified when \p this was created - /// or opened. The arguments provide options for writing the archive. If - /// \p CreateSymbolTable is true, the archive is scanned for bitcode files - /// and a symbol table of the externally visible function and global - /// variable names is created. If \p TruncateNames is true, the names of the - /// archive members will have their path component stripped and the file - /// name will be truncated at 15 characters. If \p Compress is specified, - /// all archive members will be compressed before being written. If - /// \p PrintSymTab is true, the symbol table will be printed to std::cout. - /// @returns true if an error occurred, \p error set to error message; - /// returns false if the writing succeeded. - /// @brief Write (possibly modified) archive contents to disk - bool writeToDisk( - bool CreateSymbolTable=false, ///< Create Symbol table - bool TruncateNames=false, ///< Truncate the filename to 15 chars - std::string* ErrMessage=0 ///< If non-null, where error msg is set - ); - - /// This method adds a new file to the archive. The \p filename is examined - /// to determine just enough information to create an ArchiveMember object - /// which is then inserted into the Archive object's ilist at the location - /// given by \p where. - /// @returns true if an error occurred, false otherwise - /// @brief Add a file to the archive. - bool addFileBefore( - const sys::Path& filename, ///< The file to be added - iterator where, ///< Insertion point - std::string* ErrMsg ///< Optional error message location - ); - - /// @} - /// @name Implementation - /// @{ - protected: - /// @brief Construct an Archive for \p filename and optionally map it - /// into memory. - explicit Archive(const sys::Path& filename, LLVMContext& C); - - /// @param data The symbol table data to be parsed - /// @param len The length of the symbol table data - /// @param error Set to address of a std::string to get error messages - /// @returns false on error - /// @brief Parse the symbol table at \p data. - bool parseSymbolTable(const void* data,unsigned len,std::string* error); - - /// @returns A fully populated ArchiveMember or 0 if an error occurred. - /// @brief Parse the header of a member starting at \p At - ArchiveMember* parseMemberHeader( - const char*&At, ///< The pointer to the location we're parsing - const char*End, ///< The pointer to the end of the archive - std::string* error ///< Optional error message catcher - ); - - /// @param ErrMessage Set to address of a std::string to get error messages - /// @returns false on error - /// @brief Check that the archive signature is correct - bool checkSignature(std::string* ErrMessage); - - /// @param ErrMessage Set to address of a std::string to get error messages - /// @returns false on error - /// @brief Load the entire archive. - bool loadArchive(std::string* ErrMessage); - - /// @param ErrMessage Set to address of a std::string to get error messages - /// @returns false on error - /// @brief Load just the symbol table. - bool loadSymbolTable(std::string* ErrMessage); - - /// @brief Write the symbol table to an ofstream. - void writeSymbolTable(std::ofstream& ARFile); - - /// Writes one ArchiveMember to an ofstream. If an error occurs, returns - /// false, otherwise true. If an error occurs and error is non-null then - /// it will be set to an error message. - /// @returns false if writing member succeeded, - /// returns true if writing member failed, \p error set to error message. - bool writeMember( - const ArchiveMember& member, ///< The member to be written - std::ofstream& ARFile, ///< The file to write member onto - bool CreateSymbolTable, ///< Should symbol table be created? - bool TruncateNames, ///< Should names be truncated to 11 chars? - std::string* ErrMessage ///< If non-null, place were error msg is set - ); - - /// @brief Fill in an ArchiveMemberHeader from ArchiveMember. - bool fillHeader(const ArchiveMember&mbr, - ArchiveMemberHeader& hdr,int sz, bool TruncateNames) const; - - /// @brief Maps archive into memory - bool mapToMemory(std::string* ErrMsg); - - /// @brief Frees all the members and unmaps the archive file. - void cleanUpMemory(); - - /// This type is used to keep track of bitcode modules loaded from the - /// symbol table. It maps the file offset to a pair that consists of the - /// associated ArchiveMember and the Module. - /// @brief Module mapping type - typedef std::map > - ModuleMap; - - - /// @} - /// @name Data - /// @{ - protected: - sys::Path archPath; ///< Path to the archive file we read/write - MembersList members; ///< The ilist of ArchiveMember - MemoryBuffer *mapfile; ///< Raw Archive contents mapped into memory - const char* base; ///< Base of the memory mapped file data - SymTabType symTab; ///< The symbol table - std::string strtab; ///< The string table for long file names - unsigned symTabSize; ///< Size in bytes of symbol table - unsigned firstFileOffset; ///< Offset to first normal file. - ModuleMap modules; ///< The modules loaded via symbol lookup. - ArchiveMember* foreignST; ///< This holds the foreign symbol table. - LLVMContext& Context; ///< This holds global data. - /// @} - /// @name Hidden - /// @{ - private: - Archive() LLVM_DELETED_FUNCTION; - Archive(const Archive&) LLVM_DELETED_FUNCTION; - Archive& operator=(const Archive&) LLVM_DELETED_FUNCTION; - /// @} -}; - -} // End llvm namespace - -#endif diff --git a/contrib/llvm/include/llvm/Bitcode/BitstreamReader.h b/contrib/llvm/include/llvm/Bitcode/BitstreamReader.h index f3139739c..dc5e09515 100644 --- a/contrib/llvm/include/llvm/Bitcode/BitstreamReader.h +++ b/contrib/llvm/include/llvm/Bitcode/BitstreamReader.h @@ -244,7 +244,7 @@ public: uint32_t getWord(size_t pos) { uint8_t buf[4] = { 0xFF, 0xFF, 0xFF, 0xFF }; - BitStream->getBitcodeBytes().readBytes(pos, sizeof(buf), buf, NULL); + BitStream->getBitcodeBytes().readBytes(pos, sizeof(buf), buf); return *reinterpret_cast(buf); } @@ -366,8 +366,7 @@ public: // Read the next word from the stream. uint8_t Array[sizeof(word_t)] = {0}; - BitStream->getBitcodeBytes().readBytes(NextChar, sizeof(Array), - Array, NULL); + BitStream->getBitcodeBytes().readBytes(NextChar, sizeof(Array), Array); // Handle big-endian byte-swapping if necessary. support::detail::packed_endian_specific_integral diff --git a/contrib/llvm/include/llvm/Bitcode/BitstreamWriter.h b/contrib/llvm/include/llvm/Bitcode/BitstreamWriter.h index a83721187..f40a0d1d2 100644 --- a/contrib/llvm/include/llvm/Bitcode/BitstreamWriter.h +++ b/contrib/llvm/include/llvm/Bitcode/BitstreamWriter.h @@ -381,7 +381,8 @@ private: BlobData = 0; } else { for (unsigned e = Vals.size(); RecordIdx != e; ++RecordIdx) { - assert(Vals[RecordIdx] < 256 && "Value too large to emit as blob"); + assert(isUInt<8>(Vals[RecordIdx]) && + "Value too large to emit as blob"); WriteByte((unsigned char)Vals[RecordIdx]); } } diff --git a/contrib/llvm/include/llvm/Bitcode/LLVMBitCodes.h b/contrib/llvm/include/llvm/Bitcode/LLVMBitCodes.h index f9690d5b7..b3d24661d 100644 --- a/contrib/llvm/include/llvm/Bitcode/LLVMBitCodes.h +++ b/contrib/llvm/include/llvm/Bitcode/LLVMBitCodes.h @@ -194,7 +194,8 @@ namespace bitc { CAST_FPEXT = 8, CAST_PTRTOINT = 9, CAST_INTTOPTR = 10, - CAST_BITCAST = 11 + CAST_BITCAST = 11, + CAST_ADDRSPACECAST = 12 }; /// BinaryOpcodes - These are values used in the bitcode files to encode which @@ -330,6 +331,48 @@ namespace bitc { enum UseListCodes { USELIST_CODE_ENTRY = 1 // USELIST_CODE_ENTRY: TBD. }; + + enum AttributeKindCodes { + // = 0 is unused + ATTR_KIND_ALIGNMENT = 1, + ATTR_KIND_ALWAYS_INLINE = 2, + ATTR_KIND_BY_VAL = 3, + ATTR_KIND_INLINE_HINT = 4, + ATTR_KIND_IN_REG = 5, + ATTR_KIND_MIN_SIZE = 6, + ATTR_KIND_NAKED = 7, + ATTR_KIND_NEST = 8, + ATTR_KIND_NO_ALIAS = 9, + ATTR_KIND_NO_BUILTIN = 10, + ATTR_KIND_NO_CAPTURE = 11, + ATTR_KIND_NO_DUPLICATE = 12, + ATTR_KIND_NO_IMPLICIT_FLOAT = 13, + ATTR_KIND_NO_INLINE = 14, + ATTR_KIND_NON_LAZY_BIND = 15, + ATTR_KIND_NO_RED_ZONE = 16, + ATTR_KIND_NO_RETURN = 17, + ATTR_KIND_NO_UNWIND = 18, + ATTR_KIND_OPTIMIZE_FOR_SIZE = 19, + ATTR_KIND_READ_NONE = 20, + ATTR_KIND_READ_ONLY = 21, + ATTR_KIND_RETURNED = 22, + ATTR_KIND_RETURNS_TWICE = 23, + ATTR_KIND_S_EXT = 24, + ATTR_KIND_STACK_ALIGNMENT = 25, + ATTR_KIND_STACK_PROTECT = 26, + ATTR_KIND_STACK_PROTECT_REQ = 27, + ATTR_KIND_STACK_PROTECT_STRONG = 28, + ATTR_KIND_STRUCT_RET = 29, + ATTR_KIND_SANITIZE_ADDRESS = 30, + ATTR_KIND_SANITIZE_THREAD = 31, + ATTR_KIND_SANITIZE_MEMORY = 32, + ATTR_KIND_UW_TABLE = 33, + ATTR_KIND_Z_EXT = 34, + ATTR_KIND_BUILTIN = 35, + ATTR_KIND_COLD = 36, + ATTR_KIND_OPTIMIZE_NONE = 37 + }; + } // End bitc namespace } // End llvm namespace diff --git a/contrib/llvm/include/llvm/CodeGen/Analysis.h b/contrib/llvm/include/llvm/CodeGen/Analysis.h index ce9ca0a05..b2cc7047b 100644 --- a/contrib/llvm/include/llvm/CodeGen/Analysis.h +++ b/contrib/llvm/include/llvm/CodeGen/Analysis.h @@ -26,6 +26,7 @@ namespace llvm { class GlobalVariable; class TargetLowering; +class TargetLoweringBase; class SDNode; class SDValue; class SelectionDAG; @@ -88,6 +89,14 @@ ISD::CondCode getICmpCondCode(ICmpInst::Predicate Pred); /// This function only tests target-independent requirements. bool isInTailCallPosition(ImmutableCallSite CS, const TargetLowering &TLI); +/// Test if given that the input instruction is in the tail call position if the +/// return type or any attributes of the function will inhibit tail call +/// optimization. +bool returnTypeIsEligibleForTailCall(const Function *F, + const Instruction *I, + const ReturnInst *Ret, + const TargetLoweringBase &TLI); + } // End llvm namespace #endif diff --git a/contrib/llvm/include/llvm/CodeGen/AsmPrinter.h b/contrib/llvm/include/llvm/CodeGen/AsmPrinter.h index c2fd6ce36..4bda0f160 100644 --- a/contrib/llvm/include/llvm/CodeGen/AsmPrinter.h +++ b/contrib/llvm/include/llvm/CodeGen/AsmPrinter.h @@ -38,9 +38,10 @@ namespace llvm { class MachineConstantPoolValue; class MachineJumpTableInfo; class MachineModuleInfo; - class MachineMove; class MCAsmInfo; + class MCCFIInstruction; class MCContext; + class MCInstrInfo; class MCSection; class MCStreamer; class MCSymbol; @@ -64,6 +65,7 @@ namespace llvm { /// const MCAsmInfo *MAI; + const MCInstrInfo *MII; /// OutContext - 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. @@ -121,6 +123,8 @@ namespace llvm { public: virtual ~AsmPrinter(); + const DwarfDebug *getDwarfDebug() const { return DD; } + /// isVerbose - Return true if assembly output should contain comments. /// bool isVerbose() const { return VerboseAsm; } @@ -141,6 +145,7 @@ namespace llvm { /// getCurrentSection() - Return the current section we are emitting to. const MCSection *getCurrentSection() const; + MCSymbol *getSymbol(const GlobalValue *GV) const; //===------------------------------------------------------------------===// // MachineFunctionPass Implementation. @@ -233,8 +238,8 @@ namespace llvm { /// it if appropriate. void EmitBasicBlockStart(const MachineBasicBlock *MBB) const; - /// EmitGlobalConstant - Print a general LLVM constant to the .s file. - void EmitGlobalConstant(const Constant *CV, unsigned AddrSpace = 0); + /// \brief Print a general LLVM constant to the .s file. + void EmitGlobalConstant(const Constant *CV); //===------------------------------------------------------------------===// @@ -282,6 +287,10 @@ namespace llvm { virtual bool isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) const; + /// emitImplicitDef - Targets can override this to customize the output of + /// IMPLICIT_DEF instructions in verbose mode. + virtual void emitImplicitDef(const MachineInstr *MI) const; + //===------------------------------------------------------------------===// // Symbol Lowering Routines. //===------------------------------------------------------------------===// @@ -357,13 +366,15 @@ namespace llvm { /// where the size in bytes of the directive is specified by Size and Label /// specifies the label. This implicitly uses .set if it is available. void EmitLabelPlusOffset(const MCSymbol *Label, uint64_t Offset, - unsigned Size) const; + unsigned Size, + bool IsSectionRelative = false) const; /// EmitLabelReference - Emit something like ".long Label" /// where the size in bytes of the directive is specified by Size and Label /// specifies the label. - void EmitLabelReference(const MCSymbol *Label, unsigned Size) const { - EmitLabelPlusOffset(Label, 0, Size); + void EmitLabelReference(const MCSymbol *Label, unsigned Size, + bool IsSectionRelative = false) const { + EmitLabelPlusOffset(Label, 0, Size, IsSectionRelative); } //===------------------------------------------------------------------===// @@ -371,10 +382,10 @@ namespace llvm { //===------------------------------------------------------------------===// /// EmitSLEB128 - emit the specified signed leb128 value. - void EmitSLEB128(int Value, const char *Desc = 0) const; + void EmitSLEB128(int64_t Value, const char *Desc = 0) const; /// EmitULEB128 - emit the specified unsigned leb128 value. - void EmitULEB128(unsigned Value, const char *Desc = 0, + void EmitULEB128(uint64_t Value, const char *Desc = 0, unsigned PadTo = 0) const; /// EmitCFAByte - Emit a .byte 42 directive for a DW_CFA_xxx value. @@ -402,24 +413,20 @@ namespace llvm { void EmitSectionOffset(const MCSymbol *Label, const MCSymbol *SectionLabel) const; - /// getDebugValueLocation - Get location information encoded by DBG_VALUE - /// operands. - virtual MachineLocation getDebugValueLocation(const MachineInstr *MI) const; - /// getISAEncoding - Get the value for DW_AT_APPLE_isa. Zero if no isa /// encoding specified. virtual unsigned getISAEncoding() { return 0; } /// EmitDwarfRegOp - Emit dwarf register operation. - virtual void EmitDwarfRegOp(const MachineLocation &MLoc) const; + virtual void EmitDwarfRegOp(const MachineLocation &MLoc, + bool Indirect) const; //===------------------------------------------------------------------===// // Dwarf Lowering Routines //===------------------------------------------------------------------===// - /// EmitCFIFrameMove - Emit frame instruction to describe the layout of the - /// frame. - void EmitCFIFrameMove(const MachineMove &Move) const; + /// \brief Emit frame instruction to describe the layout of the frame. + void emitCFIInstruction(const MCCFIInstruction &Inst) const; //===------------------------------------------------------------------===// // Inline Asm Support @@ -451,8 +458,7 @@ namespace llvm { /// return true if the operand is erroneous. virtual bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, unsigned AsmVariant, - const char *ExtraCode, - raw_ostream &OS); + const char *ExtraCode, raw_ostream &OS); private: /// Private state for PrintSpecial() @@ -464,7 +470,8 @@ namespace llvm { /// EmitInlineAsm - Emit a blob of inline asm to the output streamer. void EmitInlineAsm(StringRef Str, const MDNode *LocMDNode = 0, - InlineAsm::AsmDialect AsmDialect = InlineAsm::AD_ATT) const; + InlineAsm::AsmDialect AsmDialect = + InlineAsm::AD_ATT) const; /// EmitInlineAsm - This method formats and emits the specified machine /// instruction that is an inline asm. @@ -479,12 +486,13 @@ namespace llvm { void EmitVisibility(MCSymbol *Sym, unsigned Visibility, bool IsDefinition = true) const; - void EmitLinkage(unsigned Linkage, MCSymbol *GVSym) const; + void EmitLinkage(const GlobalValue *GV, MCSymbol *GVSym) const; void EmitJumpTableEntry(const MachineJumpTableInfo *MJTI, - const MachineBasicBlock *MBB, - unsigned uid) const; + const MachineBasicBlock *MBB, unsigned uid) const; void EmitLLVMUsedList(const ConstantArray *InitList); + /// Emit llvm.ident metadata in an '.ident' directive. + void EmitModuleIdents(Module &M); void EmitXXStructorList(const Constant *List, bool isCtor); GCMetadataPrinter *GetOrCreateGCPrinter(GCStrategy *C); }; diff --git a/contrib/llvm/include/llvm/CodeGen/CalcSpillWeights.h b/contrib/llvm/include/llvm/CodeGen/CalcSpillWeights.h index 9cd2decfa..0d79b1d41 100644 --- a/contrib/llvm/include/llvm/CodeGen/CalcSpillWeights.h +++ b/contrib/llvm/include/llvm/CodeGen/CalcSpillWeights.h @@ -18,9 +18,12 @@ namespace llvm { class LiveInterval; class LiveIntervals; + class MachineBlockFrequencyInfo; class MachineLoopInfo; - /// normalizeSpillWeight - The spill weight of a live interval is computed as: + /// \brief Normalize the spill weight of a live interval + /// + /// The spill weight of a live interval is computed as: /// /// (sum(use freq) + sum(def freq)) / (K + size) /// @@ -37,42 +40,38 @@ namespace llvm { return UseDefFreq / (Size + 25*SlotIndex::InstrDist); } - /// VirtRegAuxInfo - Calculate auxiliary information for a virtual - /// register such as its spill weight and allocation hint. + /// \brief Calculate auxiliary information for a virtual register such as its + /// spill weight and allocation hint. class VirtRegAuxInfo { + public: + typedef float (*NormalizingFn)(float, unsigned); + + private: MachineFunction &MF; LiveIntervals &LIS; const MachineLoopInfo &Loops; + const MachineBlockFrequencyInfo &MBFI; DenseMap Hint; + NormalizingFn normalize; + public: VirtRegAuxInfo(MachineFunction &mf, LiveIntervals &lis, - const MachineLoopInfo &loops) : - MF(mf), LIS(lis), Loops(loops) {} + const MachineLoopInfo &loops, + const MachineBlockFrequencyInfo &mbfi, + NormalizingFn norm = normalizeSpillWeight) + : MF(mf), LIS(lis), Loops(loops), MBFI(mbfi), normalize(norm) {} - /// CalculateWeightAndHint - (re)compute li's spill weight and allocation - /// hint. - void CalculateWeightAndHint(LiveInterval &li); + /// \brief (re)compute li's spill weight and allocation hint. + void calculateSpillWeightAndHint(LiveInterval &li); }; - /// CalculateSpillWeights - Compute spill weights for all virtual register + /// \brief Compute spill weights and allocation hints for all virtual register /// live intervals. - class CalculateSpillWeights : public MachineFunctionPass { - public: - static char ID; - - CalculateSpillWeights() : MachineFunctionPass(ID) { - initializeCalculateSpillWeightsPass(*PassRegistry::getPassRegistry()); - } - - virtual void getAnalysisUsage(AnalysisUsage &au) const; - - virtual bool runOnMachineFunction(MachineFunction &fn); - - private: - /// Returns true if the given live interval is zero length. - bool isZeroLengthInterval(LiveInterval *li) const; - }; - + void calculateSpillWeightsAndHints(LiveIntervals &LIS, MachineFunction &MF, + const MachineLoopInfo &MLI, + const MachineBlockFrequencyInfo &MBFI, + VirtRegAuxInfo::NormalizingFn norm = + normalizeSpillWeight); } #endif // LLVM_CODEGEN_CALCSPILLWEIGHTS_H diff --git a/contrib/llvm/include/llvm/CodeGen/CallingConvLower.h b/contrib/llvm/include/llvm/CodeGen/CallingConvLower.h index fa9d60f0d..a18f433bd 100644 --- a/contrib/llvm/include/llvm/CodeGen/CallingConvLower.h +++ b/contrib/llvm/include/llvm/CodeGen/CallingConvLower.h @@ -158,7 +158,7 @@ private: MachineFunction &MF; const TargetMachine &TM; const TargetRegisterInfo &TRI; - SmallVector &Locs; + SmallVectorImpl &Locs; LLVMContext &Context; unsigned StackOffset; @@ -219,7 +219,7 @@ protected: public: CCState(CallingConv::ID CC, bool isVarArg, MachineFunction &MF, - const TargetMachine &TM, SmallVector &locs, + const TargetMachine &TM, SmallVectorImpl &locs, LLVMContext &C); void addLoc(const CCValAssign &V) { diff --git a/contrib/llvm/include/llvm/CodeGen/CommandFlags.h b/contrib/llvm/include/llvm/CodeGen/CommandFlags.h index 9a27661b5..bc8dce333 100644 --- a/contrib/llvm/include/llvm/CodeGen/CommandFlags.h +++ b/contrib/llvm/include/llvm/CodeGen/CommandFlags.h @@ -109,11 +109,6 @@ DisableFPElim("disable-fp-elim", cl::desc("Disable frame pointer elimination optimization"), cl::init(false)); -cl::opt -DisableFPElimNonLeaf("disable-non-leaf-fp-elim", - cl::desc("Disable frame pointer elimination optimization for non-leaf funcs"), - cl::init(false)); - cl::opt EnableUnsafeFPMath("enable-unsafe-fp-math", cl::desc("Enable optimizations that may decrease FP precision"), @@ -155,7 +150,7 @@ FloatABIForCalls("float-abi", cl::opt FuseFPOps("fp-contract", - cl::desc("Enable aggresive formation of fused FP ops"), + cl::desc("Enable aggressive formation of fused FP ops"), cl::init(FPOpFusion::Standard), cl::values( clEnumValN(FPOpFusion::Fast, "fast", @@ -186,11 +181,6 @@ OverrideStackAlignment("stack-alignment", cl::desc("Override default stack alignment"), cl::init(0)); -cl::opt -EnableRealignStack("realign-stack", - cl::desc("Realign stack if needed"), - cl::init(true)); - cl::opt TrapFuncName("trap-func", cl::Hidden, cl::desc("Emit a call to trap function rather than a trap instruction"), @@ -220,8 +210,4 @@ cl::opt StartAfter("start-after", cl::value_desc("pass-name"), cl::init("")); -cl::opt -SSPBufferSize("stack-protector-buffer-size", cl::init(8), - cl::desc("Lower bound for a buffer to be considered for " - "stack protection")); #endif diff --git a/contrib/llvm/include/llvm/CodeGen/FastISel.h b/contrib/llvm/include/llvm/CodeGen/FastISel.h index 471e9bfc4..1e0ef6b54 100644 --- a/contrib/llvm/include/llvm/CodeGen/FastISel.h +++ b/contrib/llvm/include/llvm/CodeGen/FastISel.h @@ -1,4 +1,4 @@ -//===-- FastISel.h - Definition of the FastISel class ---------------------===// +//===-- FastISel.h - Definition of the FastISel class ---*- C++ -*---------===// // // The LLVM Compiler Infrastructure // @@ -6,9 +6,10 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// This file defines the FastISel class. -// +/// +/// \file +/// This file defines the FastISel class. +/// //===----------------------------------------------------------------------===// #ifndef LLVM_CODEGEN_FASTISEL_H @@ -26,7 +27,6 @@ class ConstantFP; class FunctionLoweringInfo; class Instruction; class LoadInst; -class MachineBasicBlock; class MachineConstantPool; class MachineFunction; class MachineInstr; @@ -42,9 +42,8 @@ class TargetRegisterInfo; class User; class Value; -/// FastISel - This is a fast-path instruction selection class that -/// generates poor code and doesn't support illegal types or non-trivial -/// lowering, but runs quickly. +/// This is a fast-path instruction selection class that generates poor code and +/// doesn't support illegal types or non-trivial lowering, but runs quickly. class FastISel { protected: DenseMap LocalValueMap; @@ -60,99 +59,92 @@ protected: const TargetRegisterInfo &TRI; const TargetLibraryInfo *LibInfo; - /// The position of the last instruction for materializing constants - /// for use in the current block. It resets to EmitStartPt when it - /// makes sense (for example, it's usually profitable to avoid function - /// calls between the definition and the use) + /// The position of the last instruction for materializing constants for use + /// in the current block. It resets to EmitStartPt when it makes sense (for + /// example, it's usually profitable to avoid function calls between the + /// definition and the use) MachineInstr *LastLocalValue; - /// The top most instruction in the current block that is allowed for - /// emitting local variables. LastLocalValue resets to EmitStartPt when - /// it makes sense (for example, on function calls) + /// The top most instruction in the current block that is allowed for emitting + /// local variables. LastLocalValue resets to EmitStartPt when it makes sense + /// (for example, on function calls) MachineInstr *EmitStartPt; public: - /// getLastLocalValue - Return the position of the last instruction - /// emitted for materializing constants for use in the current block. + /// Return the position of the last instruction emitted for materializing + /// constants for use in the current block. MachineInstr *getLastLocalValue() { return LastLocalValue; } - /// setLastLocalValue - Update the position of the last instruction - /// emitted for materializing constants for use in the current block. + /// Update the position of the last instruction emitted for materializing + /// constants for use in the current block. void setLastLocalValue(MachineInstr *I) { EmitStartPt = I; LastLocalValue = I; } - /// startNewBlock - Set the current block to which generated machine - /// instructions will be appended, and clear the local CSE map. - /// + /// Set the current block to which generated machine instructions will be + /// appended, and clear the local CSE map. void startNewBlock(); - /// getCurDebugLoc() - Return current debug location information. + /// Return current debug location information. DebugLoc getCurDebugLoc() const { return DL; } - /// LowerArguments - Do "fast" instruction selection for function arguments - /// and append machine instructions to the current block. Return true if - /// it is successful. + /// Do "fast" instruction selection for function arguments and append machine + /// instructions to the current block. Return true if it is successful. bool LowerArguments(); - /// SelectInstruction - Do "fast" instruction selection for the given - /// LLVM IR instruction, and append generated machine instructions to - /// the current block. Return true if selection was successful. - /// + /// Do "fast" instruction selection for the given LLVM IR instruction, and + /// append generated machine instructions to the current block. Return true if + /// selection was successful. bool SelectInstruction(const Instruction *I); - /// SelectOperator - Do "fast" instruction selection for the given - /// LLVM IR operator (Instruction or ConstantExpr), and append - /// generated machine instructions to the current block. Return true - /// if selection was successful. - /// + /// Do "fast" instruction selection for the given LLVM IR operator + /// (Instruction or ConstantExpr), and append generated machine instructions + /// to the current block. Return true if selection was successful. bool SelectOperator(const User *I, unsigned Opcode); - /// getRegForValue - Create a virtual register and arrange for it to - /// be assigned the value for the given LLVM value. + /// Create a virtual register and arrange for it to be assigned the value for + /// the given LLVM value. unsigned getRegForValue(const Value *V); - /// lookUpRegForValue - Look up the value to see if its value is already - /// cached in a register. It may be defined by instructions across blocks or - /// defined locally. + /// Look up the value to see if its value is already cached in a register. It + /// may be defined by instructions across blocks or defined locally. unsigned lookUpRegForValue(const Value *V); - /// getRegForGEPIndex - This is a wrapper around getRegForValue that also - /// takes care of truncating or sign-extending the given getelementptr - /// index value. + /// This is a wrapper around getRegForValue that also takes care of truncating + /// or sign-extending the given getelementptr index value. std::pair getRegForGEPIndex(const Value *V); - /// \brief We're checking to see if we can fold \p LI into \p FoldInst. - /// Note that we could have a sequence where multiple LLVM IR instructions - /// are folded into the same machineinstr. For example we could have: + /// \brief We're checking to see if we can fold \p LI into \p FoldInst. Note + /// that we could have a sequence where multiple LLVM IR instructions are + /// folded into the same machineinstr. For example we could have: + /// /// A: x = load i32 *P /// B: y = icmp A, 42 /// C: br y, ... /// - /// In this scenario, \p LI is "A", and \p FoldInst is "C". We know - /// about "B" (and any other folded instructions) because it is between - /// A and C. + /// In this scenario, \p LI is "A", and \p FoldInst is "C". We know about "B" + /// (and any other folded instructions) because it is between A and C. /// /// If we succeed folding, return true. - /// bool tryToFoldLoad(const LoadInst *LI, const Instruction *FoldInst); - /// \brief The specified machine instr operand is a vreg, and that - /// vreg is being provided by the specified load instruction. If possible, - /// try to fold the load as an operand to the instruction, returning true if + /// \brief The specified machine instr operand is a vreg, and that vreg is + /// being provided by the specified load instruction. If possible, try to + /// fold the load as an operand to the instruction, returning true if /// possible. + /// /// This method should be implemented by targets. virtual bool tryToFoldLoadIntoMI(MachineInstr * /*MI*/, unsigned /*OpNo*/, const LoadInst * /*LI*/) { return false; } - /// recomputeInsertPt - Reset InsertPt to prepare for inserting instructions - /// into the current block. + /// Reset InsertPt to prepare for inserting instructions into the current + /// block. void recomputeInsertPt(); - /// removeDeadCode - Remove all dead instructions between the I and E. + /// Remove all dead instructions between the I and E. void removeDeadCode(MachineBasicBlock::iterator I, MachineBasicBlock::iterator E); @@ -161,11 +153,11 @@ public: DebugLoc DL; }; - /// enterLocalValueArea - Prepare InsertPt to begin inserting instructions - /// into the local value area and return the old insert position. + /// Prepare InsertPt to begin inserting instructions into the local value area + /// and return the old insert position. SavePoint enterLocalValueArea(); - /// leaveLocalValueArea - Reset InsertPt to the given old insert position. + /// Reset InsertPt to the given old insert position. void leaveLocalValueArea(SavePoint Old); virtual ~FastISel(); @@ -174,69 +166,59 @@ protected: explicit FastISel(FunctionLoweringInfo &funcInfo, const TargetLibraryInfo *libInfo); - /// TargetSelectInstruction - This method is called by target-independent - /// code when the normal FastISel process fails to select an instruction. - /// This gives targets a chance to emit code for anything that doesn't - /// fit into FastISel's framework. It returns true if it was successful. - /// + /// This method is called by target-independent code when the normal FastISel + /// process fails to select an instruction. This gives targets a chance to + /// emit code for anything that doesn't fit into FastISel's framework. It + /// returns true if it was successful. virtual bool TargetSelectInstruction(const Instruction *I) = 0; - /// FastLowerArguments - This method is called by target-independent code to - /// do target specific argument lowering. It returns true if it was - /// successful. + /// This method is called by target-independent code to do target specific + /// argument lowering. It returns true if it was successful. virtual bool FastLowerArguments(); - /// FastEmit_r - This method is called by target-independent code - /// to request that an instruction with the given type and opcode - /// be emitted. + /// This method is called by target-independent code to request that an + /// instruction with the given type and opcode be emitted. virtual unsigned FastEmit_(MVT VT, MVT RetVT, unsigned Opcode); - /// FastEmit_r - This method is called by target-independent code - /// to request that an instruction with the given type, opcode, and - /// register operand be emitted. - /// + /// This method is called by target-independent code to request that an + /// instruction with the given type, opcode, and register operand be emitted. virtual unsigned FastEmit_r(MVT VT, MVT RetVT, unsigned Opcode, unsigned Op0, bool Op0IsKill); - /// FastEmit_rr - This method is called by target-independent code - /// to request that an instruction with the given type, opcode, and - /// register operands be emitted. - /// + /// This method is called by target-independent code to request that an + /// instruction with the given type, opcode, and register operands be emitted. virtual unsigned FastEmit_rr(MVT VT, MVT RetVT, unsigned Opcode, unsigned Op0, bool Op0IsKill, unsigned Op1, bool Op1IsKill); - /// FastEmit_ri - This method is called by target-independent code - /// to request that an instruction with the given type, opcode, and - /// register and immediate operands be emitted. - /// + /// This method is called by target-independent code to request that an + /// instruction with the given type, opcode, and register and immediate + /// operands be emitted. virtual unsigned FastEmit_ri(MVT VT, MVT RetVT, unsigned Opcode, unsigned Op0, bool Op0IsKill, uint64_t Imm); - /// FastEmit_rf - This method is called by target-independent code - /// to request that an instruction with the given type, opcode, and - /// register and floating-point immediate operands be emitted. - /// + /// This method is called by target-independent code to request that an + /// instruction with the given type, opcode, and register and floating-point + /// immediate operands be emitted. virtual unsigned FastEmit_rf(MVT VT, MVT RetVT, unsigned Opcode, unsigned Op0, bool Op0IsKill, const ConstantFP *FPImm); - /// FastEmit_rri - This method is called by target-independent code - /// to request that an instruction with the given type, opcode, and - /// register and immediate operands be emitted. - /// + /// This method is called by target-independent code to request that an + /// instruction with the given type, opcode, and register and immediate + /// operands be emitted. virtual unsigned FastEmit_rri(MVT VT, MVT RetVT, unsigned Opcode, @@ -244,142 +226,130 @@ protected: unsigned Op1, bool Op1IsKill, uint64_t Imm); - /// FastEmit_ri_ - This method is a wrapper of FastEmit_ri. It first tries - /// to emit an instruction with an immediate operand using FastEmit_ri. - /// If that fails, it materializes the immediate into a register and try - /// FastEmit_rr instead. + /// \brief This method is a wrapper of FastEmit_ri. + /// + /// It first tries to emit an instruction with an immediate operand using + /// FastEmit_ri. If that fails, it materializes the immediate into a register + /// and try FastEmit_rr instead. unsigned FastEmit_ri_(MVT VT, unsigned Opcode, unsigned Op0, bool Op0IsKill, uint64_t Imm, MVT ImmType); - /// FastEmit_i - This method is called by target-independent code - /// to request that an instruction with the given type, opcode, and - /// immediate operand be emitted. + /// This method is called by target-independent code to request that an + /// instruction with the given type, opcode, and immediate operand be emitted. virtual unsigned FastEmit_i(MVT VT, MVT RetVT, unsigned Opcode, uint64_t Imm); - /// FastEmit_f - This method is called by target-independent code - /// to request that an instruction with the given type, opcode, and - /// floating-point immediate operand be emitted. + /// This method is called by target-independent code to request that an + /// instruction with the given type, opcode, and floating-point immediate + /// operand be emitted. virtual unsigned FastEmit_f(MVT VT, MVT RetVT, unsigned Opcode, const ConstantFP *FPImm); - /// FastEmitInst_ - Emit a MachineInstr with no operands and a - /// result register in the given register class. - /// + /// Emit a MachineInstr with no operands and a result register in the given + /// register class. unsigned FastEmitInst_(unsigned MachineInstOpcode, const TargetRegisterClass *RC); - /// FastEmitInst_r - Emit a MachineInstr with one register operand - /// and a result register in the given register class. - /// + /// Emit a MachineInstr with one register operand and a result register in the + /// given register class. unsigned FastEmitInst_r(unsigned MachineInstOpcode, const TargetRegisterClass *RC, unsigned Op0, bool Op0IsKill); - /// FastEmitInst_rr - Emit a MachineInstr with two register operands - /// and a result register in the given register class. - /// + /// Emit a MachineInstr with two register operands and a result register in + /// the given register class. unsigned FastEmitInst_rr(unsigned MachineInstOpcode, const TargetRegisterClass *RC, unsigned Op0, bool Op0IsKill, unsigned Op1, bool Op1IsKill); - /// FastEmitInst_rrr - Emit a MachineInstr with three register operands - /// and a result register in the given register class. - /// + /// Emit a MachineInstr with three register operands and a result register in + /// the given register class. unsigned FastEmitInst_rrr(unsigned MachineInstOpcode, const TargetRegisterClass *RC, unsigned Op0, bool Op0IsKill, unsigned Op1, bool Op1IsKill, unsigned Op2, bool Op2IsKill); - /// FastEmitInst_ri - Emit a MachineInstr with a register operand, - /// an immediate, and a result register in the given register class. - /// + /// Emit a MachineInstr with a register operand, an immediate, and a result + /// register in the given register class. unsigned FastEmitInst_ri(unsigned MachineInstOpcode, const TargetRegisterClass *RC, unsigned Op0, bool Op0IsKill, uint64_t Imm); - /// FastEmitInst_rii - Emit a MachineInstr with one register operand - /// and two immediate operands. - /// + /// Emit a MachineInstr with one register operand and two immediate operands. unsigned FastEmitInst_rii(unsigned MachineInstOpcode, const TargetRegisterClass *RC, unsigned Op0, bool Op0IsKill, uint64_t Imm1, uint64_t Imm2); - /// FastEmitInst_rf - Emit a MachineInstr with two register operands - /// and a result register in the given register class. - /// + /// Emit a MachineInstr with two register operands and a result register in + /// the given register class. unsigned FastEmitInst_rf(unsigned MachineInstOpcode, const TargetRegisterClass *RC, unsigned Op0, bool Op0IsKill, const ConstantFP *FPImm); - /// FastEmitInst_rri - Emit a MachineInstr with two register operands, - /// an immediate, and a result register in the given register class. - /// + /// Emit a MachineInstr with two register operands, an immediate, and a result + /// register in the given register class. unsigned FastEmitInst_rri(unsigned MachineInstOpcode, const TargetRegisterClass *RC, unsigned Op0, bool Op0IsKill, unsigned Op1, bool Op1IsKill, uint64_t Imm); - /// FastEmitInst_rrii - Emit a MachineInstr with two register operands, - /// two immediates operands, and a result register in the given register - /// class. + /// Emit a MachineInstr with two register operands, two immediates operands, + /// and a result register in the given register class. unsigned FastEmitInst_rrii(unsigned MachineInstOpcode, const TargetRegisterClass *RC, unsigned Op0, bool Op0IsKill, unsigned Op1, bool Op1IsKill, uint64_t Imm1, uint64_t Imm2); - /// FastEmitInst_i - Emit a MachineInstr with a single immediate - /// operand, and a result register in the given register class. + /// Emit a MachineInstr with a single immediate operand, and a result register + /// in the given register class. unsigned FastEmitInst_i(unsigned MachineInstrOpcode, const TargetRegisterClass *RC, uint64_t Imm); - /// FastEmitInst_ii - Emit a MachineInstr with a two immediate operands. + /// Emit a MachineInstr with a two immediate operands. unsigned FastEmitInst_ii(unsigned MachineInstrOpcode, const TargetRegisterClass *RC, uint64_t Imm1, uint64_t Imm2); - /// FastEmitInst_extractsubreg - Emit a MachineInstr for an extract_subreg - /// from a specified index of a superregister to a specified type. + /// Emit a MachineInstr for an extract_subreg from a specified index of a + /// superregister to a specified type. unsigned FastEmitInst_extractsubreg(MVT RetVT, unsigned Op0, bool Op0IsKill, uint32_t Idx); - /// FastEmitZExtFromI1 - Emit MachineInstrs to compute the value of Op - /// with all but the least significant bit set to zero. + /// Emit MachineInstrs to compute the value of Op with all but the least + /// significant bit set to zero. unsigned FastEmitZExtFromI1(MVT VT, unsigned Op0, bool Op0IsKill); - /// FastEmitBranch - Emit an unconditional branch to the given block, - /// unless it is the immediate (fall-through) successor, and update - /// the CFG. + /// Emit an unconditional branch to the given block, unless it is the + /// immediate (fall-through) successor, and update the CFG. void FastEmitBranch(MachineBasicBlock *MBB, DebugLoc DL); void UpdateValueMap(const Value* I, unsigned Reg, unsigned NumRegs = 1); unsigned createResultReg(const TargetRegisterClass *RC); - /// TargetMaterializeConstant - Emit a constant in a register using - /// target-specific logic, such as constant pool loads. + /// Emit a constant in a register using target-specific logic, such as + /// constant pool loads. virtual unsigned TargetMaterializeConstant(const Constant* C) { return 0; } - /// TargetMaterializeAlloca - Emit an alloca address in a register using - /// target-specific logic. + /// Emit an alloca address in a register using target-specific logic. virtual unsigned TargetMaterializeAlloca(const AllocaInst* C) { return 0; } @@ -388,6 +358,15 @@ protected: return 0; } + /// \brief Check if \c Add is an add that can be safely folded into \c GEP. + /// + /// \c Add can be folded into \c GEP if: + /// - \c Add is an add, + /// - \c Add's size matches \c GEP's, + /// - \c Add is in the same basic block as \c GEP, and + /// - \c Add has a constant operand. + bool canFoldAddIntoGEP(const User *GEP, const Value *Add); + private: bool SelectBinaryOp(const User *I, unsigned ISDOpcode); @@ -405,25 +384,26 @@ private: bool SelectInsertValue(const User *I); - /// HandlePHINodesInSuccessorBlocks - Handle PHI nodes in successor blocks. + /// \brief Handle PHI nodes in successor blocks. + /// /// Emit code to ensure constants are copied into registers when needed. /// Remember the virtual registers that need to be added to the Machine PHI - /// nodes as input. We cannot just directly add them, because expansion - /// might result in multiple MBB's for one BB. As such, the start of the - /// BB might correspond to a different MBB than the end. + /// nodes as input. We cannot just directly add them, because expansion might + /// result in multiple MBB's for one BB. As such, the start of the BB might + /// correspond to a different MBB than the end. bool HandlePHINodesInSuccessorBlocks(const BasicBlock *LLVMBB); - /// materializeRegForValue - Helper for getRegForVale. This function is - /// called when the value isn't already available in a register and must - /// be materialized with new instructions. + /// Helper for getRegForVale. This function is called when the value isn't + /// already available in a register and must be materialized with new + /// instructions. unsigned materializeRegForValue(const Value *V, MVT VT); - /// flushLocalValueMap - clears LocalValueMap and moves the area for the - /// new local variables to the beginning of the block. It helps to avoid - /// spilling cached variables across heavy instructions like calls. + /// Clears LocalValueMap and moves the area for the new local variables to the + /// beginning of the block. It helps to avoid spilling cached variables across + /// heavy instructions like calls. void flushLocalValueMap(); - /// hasTrivialKill - Test whether the given value has exactly one use. + /// Test whether the given value has exactly one use. bool hasTrivialKill(const Value *V) const; }; diff --git a/contrib/llvm/include/llvm/CodeGen/FunctionLoweringInfo.h b/contrib/llvm/include/llvm/CodeGen/FunctionLoweringInfo.h index e6f30a2ce..50d320f8e 100644 --- a/contrib/llvm/include/llvm/CodeGen/FunctionLoweringInfo.h +++ b/contrib/llvm/include/llvm/CodeGen/FunctionLoweringInfo.h @@ -49,8 +49,8 @@ class Value; /// function that is used when lowering a region of the function. /// class FunctionLoweringInfo { + const TargetMachine &TM; public: - const TargetLowering &TLI; const Function *Fn; MachineFunction *MF; MachineRegisterInfo *RegInfo; @@ -120,7 +120,7 @@ public: /// SelectionDAGISel::PrepareEHLandingPad(). unsigned ExceptionPointerVirtReg, ExceptionSelectorVirtReg; - explicit FunctionLoweringInfo(const TargetLowering &TLI); + explicit FunctionLoweringInfo(const TargetMachine &TM) : TM(TM) {} /// set - Initialize this FunctionLoweringInfo with the given Function /// and its associated MachineFunction. diff --git a/contrib/llvm/include/llvm/CodeGen/ISDOpcodes.h b/contrib/llvm/include/llvm/CodeGen/ISDOpcodes.h index 0fd211b4a..48a0523dc 100644 --- a/contrib/llvm/include/llvm/CodeGen/ISDOpcodes.h +++ b/contrib/llvm/include/llvm/CodeGen/ISDOpcodes.h @@ -77,18 +77,6 @@ namespace ISD { /// adjustment during unwind. FRAME_TO_ARGS_OFFSET, - /// RESULT, OUTCHAIN = EXCEPTIONADDR(INCHAIN) - This node represents the - /// address of the exception block on entry to an landing pad block. - EXCEPTIONADDR, - - /// RESULT, OUTCHAIN = LSDAADDR(INCHAIN) - This node represents the - /// address of the Language Specific Data Area for the enclosing function. - LSDAADDR, - - /// RESULT, OUTCHAIN = EHSELECTION(INCHAIN, EXCEPTION) - This node - /// represents the selection index of the exception thrown. - EHSELECTION, - /// OUTCHAIN = EH_RETURN(INCHAIN, OFFSET, HANDLER) - This node represents /// 'eh_return' gcc dwarf builtin, which is used to return from /// exception. The general meaning is: adjust stack by OFFSET and pass @@ -431,6 +419,10 @@ namespace ISD { /// getNode(). BITCAST, + /// ADDRSPACECAST - This operator converts between pointers of different + /// address spaces. + ADDRSPACECAST, + /// CONVERT_RNDSAT - This operator is used to support various conversions /// between various types (float, signed, unsigned and vectors of those /// types) with rounding and saturation. NOTE: Avoid using this operator as @@ -452,11 +444,11 @@ namespace ISD { /// FNEG, FABS, FSQRT, FSIN, FCOS, FPOWI, FPOW, /// FLOG, FLOG2, FLOG10, FEXP, FEXP2, - /// FCEIL, FTRUNC, FRINT, FNEARBYINT, FFLOOR - Perform various unary + /// FCEIL, FTRUNC, FRINT, FNEARBYINT, FROUND, FFLOOR - Perform various unary /// floating point operations. These are inspired by libm. FNEG, FABS, FSQRT, FSIN, FCOS, FPOWI, FPOW, FLOG, FLOG2, FLOG10, FEXP, FEXP2, - FCEIL, FTRUNC, FRINT, FNEARBYINT, FFLOOR, + FCEIL, FTRUNC, FRINT, FNEARBYINT, FROUND, FFLOOR, /// FSINCOS - Compute both fsin and fcos as a single operation. FSINCOS, @@ -616,11 +608,17 @@ namespace ISD { ATOMIC_STORE, /// Val, OUTCHAIN = ATOMIC_CMP_SWAP(INCHAIN, ptr, cmp, swap) + /// For double-word atomic operations: + /// ValLo, ValHi, OUTCHAIN = ATOMIC_CMP_SWAP(INCHAIN, ptr, cmpLo, cmpHi, + /// swapLo, swapHi) /// This corresponds to the cmpxchg instruction. ATOMIC_CMP_SWAP, /// Val, OUTCHAIN = ATOMIC_SWAP(INCHAIN, ptr, amt) /// Val, OUTCHAIN = ATOMIC_LOAD_[OpName](INCHAIN, ptr, amt) + /// For double-word atomic operations: + /// ValLo, ValHi, OUTCHAIN = ATOMIC_SWAP(INCHAIN, ptr, amtLo, amtHi) + /// ValLo, ValHi, OUTCHAIN = ATOMIC_LOAD_[OpName](INCHAIN, ptr, amtLo, amtHi) /// These correspond to the atomicrmw instruction. ATOMIC_SWAP, ATOMIC_LOAD_ADD, @@ -647,7 +645,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+150; + static const int FIRST_TARGET_MEMORY_OPCODE = BUILTIN_OP_END+180; //===--------------------------------------------------------------------===// /// MemIndexedMode enum - This enum defines the load / store indexed diff --git a/contrib/llvm/include/llvm/CodeGen/LexicalScopes.h b/contrib/llvm/include/llvm/CodeGen/LexicalScopes.h index ff65db4ee..26563a605 100644 --- a/contrib/llvm/include/llvm/CodeGen/LexicalScopes.h +++ b/contrib/llvm/include/llvm/CodeGen/LexicalScopes.h @@ -141,8 +141,8 @@ private: DenseMap AbstractScopeMap; /// AbstractScopesList - Tracks abstract scopes constructed while processing - /// a function. - SmallVectorAbstractScopesList; + /// a function. + SmallVector AbstractScopesList; /// CurrentFnLexicalScope - Top level scope for the current function. /// @@ -166,13 +166,13 @@ public: virtual ~LexicalScope() {} // Accessors. - LexicalScope *getParent() const { return Parent; } - const MDNode *getDesc() const { return Desc; } - const MDNode *getInlinedAt() const { return InlinedAtLocation; } - const MDNode *getScopeNode() const { return Desc; } - bool isAbstractScope() const { return AbstractScope; } - SmallVector &getChildren() { return Children; } - SmallVector &getRanges() { return Ranges; } + LexicalScope *getParent() const { return Parent; } + const MDNode *getDesc() const { return Desc; } + const MDNode *getInlinedAt() const { return InlinedAtLocation; } + const MDNode *getScopeNode() const { return Desc; } + bool isAbstractScope() const { return AbstractScope; } + SmallVectorImpl &getChildren() { return Children; } + SmallVectorImpl &getRanges() { return Ranges; } /// addChild - Add a child scope. void addChild(LexicalScope *S) { Children.push_back(S); } diff --git a/contrib/llvm/include/llvm/CodeGen/LiveInterval.h b/contrib/llvm/include/llvm/CodeGen/LiveInterval.h index cb09a4966..3a9fef6fb 100644 --- a/contrib/llvm/include/llvm/CodeGen/LiveInterval.h +++ b/contrib/llvm/include/llvm/CodeGen/LiveInterval.h @@ -9,12 +9,12 @@ // // This file implements the LiveRange and LiveInterval classes. Given some // numbering of each the machine instructions an interval [i, j) is said to be a -// live interval for register v if there is no instruction with number j' >= j +// live range for register v if there is no instruction with number j' >= j // such that v is live at j' and there is no instruction with number i' < i such -// that v is live at i'. In this implementation intervals can have holes, -// i.e. an interval might look like [1,20), [50,65), [1000,1001). Each -// individual range is represented as an instance of LiveRange, and the whole -// interval is represented as an instance of LiveInterval. +// that v is live at i'. In this implementation ranges can have holes, +// i.e. a range might look like [1,20), [50,65), [1000,1001). Each +// individual segment is represented as an instance of LiveRange::Segment, +// and the whole range is represented as an instance of LiveRange. // //===----------------------------------------------------------------------===// @@ -35,6 +35,7 @@ namespace llvm { class MachineRegisterInfo; class TargetRegisterInfo; class raw_ostream; + template class SmallPtrSet; /// VNInfo - Value Number Information. /// This class holds information about a machine level values, including @@ -66,7 +67,7 @@ namespace llvm { } /// Returns true if this value is defined by a PHI instruction (or was, - /// PHI instrucions may have been eliminated). + /// PHI instructions may have been eliminated). /// PHI-defs begin at a block boundary, all other defs begin at register or /// EC slots. bool isPHIDef() const { return def.isBlock(); } @@ -78,107 +79,136 @@ namespace llvm { void markUnused() { def = SlotIndex(); } }; - /// LiveRange structure - This represents a simple register range in the - /// program, with an inclusive start point and an exclusive end point. - /// These ranges are rendered as [start,end). - struct LiveRange { - SlotIndex start; // Start point of the interval (inclusive) - SlotIndex end; // End point of the interval (exclusive) - VNInfo *valno; // identifier for the value contained in this interval. + /// Result of a LiveRange query. This class hides the implementation details + /// of live ranges, and it should be used as the primary interface for + /// examining live ranges around instructions. + class LiveQueryResult { + VNInfo *const EarlyVal; + VNInfo *const LateVal; + const SlotIndex EndPoint; + const bool Kill; - LiveRange() : valno(0) {} + public: + LiveQueryResult(VNInfo *EarlyVal, VNInfo *LateVal, SlotIndex EndPoint, + bool Kill) + : EarlyVal(EarlyVal), LateVal(LateVal), EndPoint(EndPoint), Kill(Kill) + {} - LiveRange(SlotIndex S, SlotIndex E, VNInfo *V) - : start(S), end(E), valno(V) { - assert(S < E && "Cannot create empty or backwards range"); + /// Return the value that is live-in to the instruction. This is the value + /// that will be read by the instruction's use operands. Return NULL if no + /// value is live-in. + VNInfo *valueIn() const { + return EarlyVal; } - /// contains - Return true if the index is covered by this range. - /// - bool contains(SlotIndex I) const { - return start <= I && I < end; + /// Return true if the live-in value is killed by this instruction. This + /// means that either the live range ends at the instruction, or it changes + /// value. + bool isKill() const { + return Kill; } - /// containsRange - Return true if the given range, [S, E), is covered by - /// this range. - bool containsRange(SlotIndex S, SlotIndex E) const { - assert((S < E) && "Backwards interval?"); - return (start <= S && S < end) && (start < E && E <= end); + /// Return true if this instruction has a dead def. + bool isDeadDef() const { + return EndPoint.isDead(); } - bool operator<(const LiveRange &LR) const { - return start < LR.start || (start == LR.start && end < LR.end); + /// Return the value leaving the instruction, if any. This can be a + /// live-through value, or a live def. A dead def returns NULL. + VNInfo *valueOut() const { + return isDeadDef() ? 0 : LateVal; } - bool operator==(const LiveRange &LR) const { - return start == LR.start && end == LR.end; + + /// 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 { + return EarlyVal == LateVal ? 0 : LateVal; } - void dump() const; - void print(raw_ostream &os) const; + /// Return the end point of the last live range segment to interact with + /// the instruction, if any. + /// + /// The end point is an invalid SlotIndex only if the live range doesn't + /// intersect the instruction at all. + /// + /// The end point may be at or past the end of the instruction's basic + /// block. That means the value was live out of the block. + SlotIndex endPoint() const { + return EndPoint; + } }; - template <> struct isPodLike { static const bool value = true; }; - - raw_ostream& operator<<(raw_ostream& os, const LiveRange &LR); - + /// This class represents the liveness of a register, stack slot, etc. + /// It manages an ordered list of Segment objects. + /// The Segments are organized in a static single assignment form: At places + /// where a new value is defined or different values reach a CFG join a new + /// segment with a new value number is used. + class LiveRange { + public: - inline bool operator<(SlotIndex V, const LiveRange &LR) { - return V < LR.start; - } + /// This represents a simple continuous liveness interval for a value. + /// The start point is inclusive, the end point exclusive. These intervals + /// are rendered as [start,end). + struct Segment { + SlotIndex start; // Start point of the interval (inclusive) + SlotIndex end; // End point of the interval (exclusive) + VNInfo *valno; // identifier for the value contained in this segment. - inline bool operator<(const LiveRange &LR, SlotIndex V) { - return LR.start < V; - } + Segment() : valno(0) {} - /// LiveInterval - This class represents some number of live ranges for a - /// register or value. This class also contains a bit of register allocator - /// state. - class LiveInterval { - public: + Segment(SlotIndex S, SlotIndex E, VNInfo *V) + : start(S), end(E), valno(V) { + assert(S < E && "Cannot create empty or backwards segment"); + } - typedef SmallVector Ranges; - typedef SmallVector VNInfoList; + /// Return true if the index is covered by this segment. + bool contains(SlotIndex I) const { + return start <= I && I < end; + } - const unsigned reg; // the register or stack slot of this interval. - float weight; // weight of this interval - Ranges ranges; // the ranges in which this register is live - VNInfoList valnos; // value#'s + /// Return true if the given interval, [S, E), is covered by this segment. + bool containsInterval(SlotIndex S, SlotIndex E) const { + assert((S < E) && "Backwards interval?"); + return (start <= S && S < end) && (start < E && E <= end); + } - struct InstrSlots { - enum { - LOAD = 0, - USE = 1, - DEF = 2, - STORE = 3, - NUM = 4 - }; + bool operator<(const Segment &Other) const { + return start < Other.start || (start == Other.start && end < Other.end); + } + bool operator==(const Segment &Other) const { + return start == Other.start && end == Other.end; + } + void dump() const; }; - LiveInterval(unsigned Reg, float Weight) - : reg(Reg), weight(Weight) {} + typedef SmallVector Segments; + typedef SmallVector VNInfoList; + + Segments segments; // the liveness segments + VNInfoList valnos; // value#'s - typedef Ranges::iterator iterator; - iterator begin() { return ranges.begin(); } - iterator end() { return ranges.end(); } + typedef Segments::iterator iterator; + iterator begin() { return segments.begin(); } + iterator end() { return segments.end(); } - typedef Ranges::const_iterator const_iterator; - const_iterator begin() const { return ranges.begin(); } - const_iterator end() const { return ranges.end(); } + typedef Segments::const_iterator const_iterator; + const_iterator begin() const { return segments.begin(); } + const_iterator end() const { return segments.end(); } typedef VNInfoList::iterator vni_iterator; vni_iterator vni_begin() { return valnos.begin(); } - vni_iterator vni_end() { return valnos.end(); } + vni_iterator vni_end() { return valnos.end(); } typedef VNInfoList::const_iterator const_vni_iterator; const_vni_iterator vni_begin() const { return valnos.begin(); } - const_vni_iterator vni_end() const { return valnos.end(); } + const_vni_iterator vni_end() const { return valnos.end(); } - /// advanceTo - Advance the specified iterator to point to the LiveRange + /// 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 interval. If no LiveRange contains this position, but the + /// end of the range. If no Segment contains this position, but the /// position is in a hole, this method returns an iterator pointing to the - /// LiveRange immediately after the hole. + /// Segment immediately after the hole. iterator advanceTo(iterator I, SlotIndex Pos) { assert(I != end()); if (Pos >= endIndex()) @@ -187,22 +217,26 @@ namespace llvm { return I; } - /// find - Return an iterator pointing to the first range that ends after + /// 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 intervals. + /// when searching large ranges. /// - /// If Pos is contained in a LiveRange, that range is returned. - /// If Pos is in a hole, the following LiveRange is returned. + /// If Pos is contained in a Segment, that segment is returned. + /// If Pos is in a hole, the following Segment is returned. /// If Pos is beyond endIndex, end() is returned. iterator find(SlotIndex Pos); const_iterator find(SlotIndex Pos) const { - return const_cast(this)->find(Pos); + return const_cast(this)->find(Pos); } void clear() { valnos.clear(); - ranges.clear(); + segments.clear(); + } + + size_t size() const { + return segments.size(); } bool hasAtLeastOneValue() const { return !valnos.empty(); } @@ -220,7 +254,7 @@ namespace llvm { return valnos[ValNo]; } - /// containsValue - Returns true if VNI belongs to this interval. + /// containsValue - Returns true if VNI belongs to this range. bool containsValue(const VNInfo *VNI) const { return VNI && VNI->id < getNumValNums() && VNI == getValNumInfo(VNI->id); } @@ -234,7 +268,7 @@ namespace llvm { return VNI; } - /// createDeadDef - Make sure the interval has a value defined at Def. + /// createDeadDef - Make sure the range has a value defined at Def. /// If one already exists, return it. Otherwise allocate a new value and /// add liveness for a dead def. VNInfo *createDeadDef(SlotIndex Def, VNInfo::Allocator &VNInfoAllocator); @@ -251,42 +285,42 @@ namespace llvm { /// RenumberValues - Renumber all values in order of appearance and remove /// unused values. - void RenumberValues(LiveIntervals &lis); + void RenumberValues(); - /// MergeValueNumberInto - This method is called when two value nubmers + /// MergeValueNumberInto - This method is called when two value numbers /// are found to be equivalent. This eliminates V1, replacing all - /// LiveRanges with the V1 value number with the V2 value number. This can + /// segments with the V1 value number with the V2 value number. This can /// cause merging of V1/V2 values numbers and compaction of the value space. VNInfo* MergeValueNumberInto(VNInfo *V1, VNInfo *V2); - /// MergeValueInAsValue - Merge all of the live ranges of a specific val# - /// in RHS into this live interval as the specified value number. - /// The LiveRanges in RHS are allowed to overlap with LiveRanges in the - /// current interval, it will replace the value numbers of the overlaped - /// live ranges with the specified value number. - void MergeRangesInAsValue(const LiveInterval &RHS, VNInfo *LHSValNo); - - /// MergeValueInAsValue - Merge all of the live ranges of a specific val# - /// in RHS into this live interval as the specified value number. - /// The LiveRanges in RHS are allowed to overlap with LiveRanges in the - /// current interval, but only if the overlapping LiveRanges have the + /// Merge all of the live segments of a specific val# in RHS into this live + /// range as the specified value number. The segments in RHS are allowed + /// to overlap with segments in the current range, it will replace the + /// value numbers of the overlaped live segments with the specified value + /// number. + void MergeSegmentsInAsValue(const LiveRange &RHS, VNInfo *LHSValNo); + + /// MergeValueInAsValue - Merge all of the segments of a specific val# + /// in RHS into this live range as the specified value number. + /// The segments in RHS are allowed to overlap with segments in the + /// current range, but only if the overlapping segments have the /// specified value number. - void MergeValueInAsValue(const LiveInterval &RHS, + void MergeValueInAsValue(const LiveRange &RHS, const VNInfo *RHSValNo, VNInfo *LHSValNo); - bool empty() const { return ranges.empty(); } + bool empty() const { return segments.empty(); } - /// beginIndex - Return the lowest numbered slot covered by interval. + /// beginIndex - Return the lowest numbered slot covered. SlotIndex beginIndex() const { - assert(!empty() && "Call to beginIndex() on empty interval."); - return ranges.front().start; + assert(!empty() && "Call to beginIndex() on empty range."); + return segments.front().start; } - /// endNumber - return the maximum point of the interval of the whole, + /// endNumber - return the maximum point of the range of the whole, /// exclusive. SlotIndex endIndex() const { - assert(!empty() && "Call to endIndex() on empty interval."); - return ranges.back().end; + assert(!empty() && "Call to endIndex() on empty range."); + return segments.back().end; } bool expiredAt(SlotIndex index) const { @@ -298,31 +332,23 @@ namespace llvm { return r != end() && r->start <= index; } - /// killedAt - Return true if a live range ends at index. Note that the kill - /// point is not contained in the half-open live range. It is usually the - /// getDefIndex() slot following its last use. - bool killedAt(SlotIndex index) const { - const_iterator r = find(index.getRegSlot(true)); - return r != end() && r->end == index; - } - - /// getLiveRangeContaining - Return the live range that contains the - /// specified index, or null if there is none. - const LiveRange *getLiveRangeContaining(SlotIndex Idx) const { - const_iterator I = FindLiveRangeContaining(Idx); + /// Return the segment that contains the specified index, or null if there + /// is none. + const Segment *getSegmentContaining(SlotIndex Idx) const { + const_iterator I = FindSegmentContaining(Idx); return I == end() ? 0 : &*I; } - /// getLiveRangeContaining - Return the live range that contains the - /// specified index, or null if there is none. - LiveRange *getLiveRangeContaining(SlotIndex Idx) { - iterator I = FindLiveRangeContaining(Idx); + /// Return the live segment that contains the specified index, or null if + /// there is none. + Segment *getSegmentContaining(SlotIndex Idx) { + iterator I = FindSegmentContaining(Idx); return I == end() ? 0 : &*I; } /// getVNInfoAt - Return the VNInfo that is live at Idx, or NULL. VNInfo *getVNInfoAt(SlotIndex Idx) const { - const_iterator I = FindLiveRangeContaining(Idx); + const_iterator I = FindSegmentContaining(Idx); return I == end() ? 0 : I->valno; } @@ -330,76 +356,68 @@ namespace llvm { /// necessarilly including Idx, or NULL. Use this to find the reaching def /// used by an instruction at this SlotIndex position. VNInfo *getVNInfoBefore(SlotIndex Idx) const { - const_iterator I = FindLiveRangeContaining(Idx.getPrevSlot()); + const_iterator I = FindSegmentContaining(Idx.getPrevSlot()); return I == end() ? 0 : I->valno; } - /// FindLiveRangeContaining - Return an iterator to the live range that - /// contains the specified index, or end() if there is none. - iterator FindLiveRangeContaining(SlotIndex Idx) { + /// Return an iterator to the segment that contains the specified index, or + /// end() if there is none. + iterator FindSegmentContaining(SlotIndex Idx) { iterator I = find(Idx); return I != end() && I->start <= Idx ? I : end(); } - const_iterator FindLiveRangeContaining(SlotIndex Idx) const { + const_iterator FindSegmentContaining(SlotIndex Idx) const { const_iterator I = find(Idx); return I != end() && I->start <= Idx ? I : end(); } - /// overlaps - Return true if the intersection of the two live intervals is + /// overlaps - Return true if the intersection of the two live ranges is /// not empty. - bool overlaps(const LiveInterval& other) const { + bool overlaps(const LiveRange &other) const { if (other.empty()) return false; return overlapsFrom(other, other.begin()); } - /// overlaps - Return true if the two intervals have overlapping segments + /// overlaps - Return true if the two ranges have overlapping segments /// that are not coalescable according to CP. /// - /// Overlapping segments where one interval is defined by a coalescable + /// Overlapping segments where one range is defined by a coalescable /// copy are allowed. - bool overlaps(const LiveInterval &Other, const CoalescerPair &CP, + bool overlaps(const LiveRange &Other, const CoalescerPair &CP, const SlotIndexes&) const; - /// overlaps - Return true if the live interval overlaps a range specified + /// overlaps - Return true if the live range overlaps an interval specified /// by [Start, End). bool overlaps(SlotIndex Start, SlotIndex End) const; - /// overlapsFrom - Return true if the intersection of the two live intervals + /// overlapsFrom - Return true if the intersection of the two live ranges /// is not empty. The specified iterator is a hint that we can begin - /// scanning the Other interval starting at I. - bool overlapsFrom(const LiveInterval& other, const_iterator I) const; + /// scanning the Other range starting at I. + bool overlapsFrom(const LiveRange &Other, const_iterator I) const; - /// addRange - Add the specified LiveRange to this interval, merging - /// intervals as appropriate. This returns an iterator to the inserted live - /// range (which may have grown since it was inserted. - iterator addRange(LiveRange LR) { - return addRangeFrom(LR, ranges.begin()); + /// 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()); } - /// extendInBlock - If this interval is live before Kill in the basic block + /// 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 live range before Kill, return NULL. + /// the value. If there is no segment before Kill, return NULL. VNInfo *extendInBlock(SlotIndex StartIdx, SlotIndex Kill); - /// join - Join two live intervals (this, and other) together. This applies - /// mappings to the value numbers in the LHS/RHS intervals as specified. If - /// the intervals are not joinable, this aborts. - void join(LiveInterval &Other, + /// join - Join two live ranges (this, and other) together. This applies + /// mappings to the value numbers in the LHS/RHS ranges as specified. If + /// the ranges are not joinable, this aborts. + void join(LiveRange &Other, const int *ValNoAssignments, const int *RHSValNoAssignments, - SmallVector &NewVNInfo, - MachineRegisterInfo *MRI); + SmallVectorImpl &NewVNInfo); - /// isInOneLiveRange - Return true if the range specified is entirely in the - /// a single LiveRange of the live interval. - bool isInOneLiveRange(SlotIndex Start, SlotIndex End) const { - const_iterator r = find(Start); - return r != end() && r->containsRange(Start, End); - } - - /// True iff this live range is a single segment that lies between the + /// True iff this segment is a single segment that lies between the /// specified boundaries, exclusively. Vregs live across a backedge are not /// considered local. The boundaries are expected to lie within an extended /// basic block, so vregs that are not live out should contain no holes. @@ -408,25 +426,63 @@ namespace llvm { endIndex() < End.getBoundaryIndex(); } - /// removeRange - Remove the specified range from this interval. Note that - /// the range must be a single LiveRange in its entirety. - void removeRange(SlotIndex Start, SlotIndex End, - bool RemoveDeadValNo = false); + /// Remove the specified segment from this range. Note that the segment + /// must be a single Segment in its entirety. + void removeSegment(SlotIndex Start, SlotIndex End, + bool RemoveDeadValNo = false); - void removeRange(LiveRange LR, bool RemoveDeadValNo = false) { - removeRange(LR.start, LR.end, RemoveDeadValNo); + void removeSegment(Segment S, bool RemoveDeadValNo = false) { + removeSegment(S.start, S.end, RemoveDeadValNo); } - /// removeValNo - Remove all the ranges defined by the specified value#. + /// Query Liveness at Idx. + /// The sub-instruction slot of Idx doesn't matter, only the instruction + /// it refers to is considered. + LiveQueryResult Query(SlotIndex Idx) const { + // Find the segment that enters the instruction. + const_iterator I = find(Idx.getBaseIndex()); + const_iterator E = end(); + if (I == E) + return LiveQueryResult(0, 0, SlotIndex(), false); + + // Is this an instruction live-in segment? + // If Idx is the start index of a basic block, include live-in segments + // that start at Idx.getBaseIndex(). + VNInfo *EarlyVal = 0; + VNInfo *LateVal = 0; + SlotIndex EndPoint; + bool Kill = false; + if (I->start <= Idx.getBaseIndex()) { + EarlyVal = I->valno; + EndPoint = I->end; + // Move to the potentially live-out segment. + if (SlotIndex::isSameInstr(Idx, I->end)) { + Kill = true; + if (++I == E) + return LiveQueryResult(EarlyVal, LateVal, EndPoint, Kill); + } + // Special case: A PHIDef value can have its def in the middle of a + // segment if the value happens to be live out of the layout + // predecessor. + // Such a value is not live-in. + if (EarlyVal->def == Idx.getBaseIndex()) + EarlyVal = 0; + } + // I now points to the segment that may be live-through, or defined by + // this instr. Ignore segments starting after the current instr. + if (!SlotIndex::isEarlierInstr(Idx, I->start)) { + LateVal = I->valno; + EndPoint = I->end; + } + return LiveQueryResult(EarlyVal, LateVal, EndPoint, Kill); + } + + /// removeValNo - Remove all the segments defined by the specified value#. /// Also remove the value# from value# list. void removeValNo(VNInfo *ValNo); - /// getSize - Returns the sum of sizes of all the LiveRange's. - /// - unsigned getSize() const; - - /// Returns true if the live interval is zero length, i.e. no live ranges - /// span instructions. It doesn't pay to spill such an interval. + /// 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() < @@ -435,27 +491,16 @@ namespace llvm { return true; } - /// isSpillable - Can this interval be spilled? - bool isSpillable() const { - return weight != HUGE_VALF; - } - - /// markNotSpillable - Mark interval as not spillable - void markNotSpillable() { - weight = HUGE_VALF; - } - - bool operator<(const LiveInterval& other) const { + bool operator<(const LiveRange& other) const { const SlotIndex &thisIndex = beginIndex(); const SlotIndex &otherIndex = other.beginIndex(); - return (thisIndex < otherIndex || - (thisIndex == otherIndex && reg < other.reg)); + return thisIndex < otherIndex; } void print(raw_ostream &OS) const; void dump() const; - /// \brief Walk the interval and assert if any invariants fail to hold. + /// \brief Walk the range and assert if any invariants fail to hold. /// /// Note that this is a no-op when asserts are disabled. #ifdef NDEBUG @@ -466,11 +511,55 @@ namespace llvm { private: - Ranges::iterator addRangeFrom(LiveRange LR, Ranges::iterator From); - void extendIntervalEndTo(Ranges::iterator I, SlotIndex NewEnd); - Ranges::iterator extendIntervalStartTo(Ranges::iterator I, SlotIndex NewStr); + iterator addSegmentFrom(Segment S, iterator From); + void extendSegmentEndTo(iterator I, SlotIndex NewEnd); + iterator extendSegmentStartTo(iterator I, SlotIndex NewStr); void markValNoForDeletion(VNInfo *V); + }; + + inline raw_ostream &operator<<(raw_ostream &OS, const LiveRange &LR) { + LR.print(OS); + return OS; + } + + /// LiveInterval - This class represents the liveness of a register, + /// or stack slot. + class LiveInterval : public LiveRange { + public: + typedef LiveRange super; + + 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) {} + + /// getSize - Returns the sum of sizes of all the LiveRange's. + /// + unsigned getSize() const; + + /// isSpillable - Can this interval be spilled? + bool isSpillable() const { + return weight != llvm::huge_valf; + } + + /// markNotSpillable - Mark interval as not spillable + void markNotSpillable() { + weight = llvm::huge_valf; + } + + bool operator<(const LiveInterval& other) const { + const SlotIndex &thisIndex = beginIndex(); + const SlotIndex &otherIndex = other.beginIndex(); + return thisIndex < otherIndex || + (thisIndex == otherIndex && reg < other.reg); + } + + void print(raw_ostream &OS) const; + void dump() const; + + private: LiveInterval& operator=(const LiveInterval& rhs) LLVM_DELETED_FUNCTION; }; @@ -480,54 +569,65 @@ namespace llvm { return OS; } - /// Helper class for performant LiveInterval bulk updates. + raw_ostream &operator<<(raw_ostream &OS, const LiveRange::Segment &S); + + inline bool operator<(SlotIndex V, const LiveRange::Segment &S) { + return V < S.start; + } + + inline bool operator<(const LiveRange::Segment &S, SlotIndex V) { + return S.start < V; + } + + /// Helper class for performant LiveRange bulk updates. /// - /// Calling LiveInterval::addRange() repeatedly can be expensive on large + /// Calling LiveRange::addSegment() repeatedly can be expensive on large /// live ranges because segments after the insertion point may need to be /// shifted. The LiveRangeUpdater class can defer the shifting when adding /// many segments in order. /// - /// The LiveInterval will be in an invalid state until flush() is called. + /// The LiveRange will be in an invalid state until flush() is called. class LiveRangeUpdater { - LiveInterval *LI; + LiveRange *LR; SlotIndex LastStart; - LiveInterval::iterator WriteI; - LiveInterval::iterator ReadI; - SmallVector Spills; + LiveRange::iterator WriteI; + LiveRange::iterator ReadI; + SmallVector Spills; void mergeSpills(); public: - /// Create a LiveRangeUpdater for adding segments to LI. - /// LI will temporarily be in an invalid state until flush() is called. - LiveRangeUpdater(LiveInterval *li = 0) : LI(li) {} + /// Create a LiveRangeUpdater for adding segments to LR. + /// LR will temporarily be in an invalid state until flush() is called. + LiveRangeUpdater(LiveRange *lr = 0) : LR(lr) {} ~LiveRangeUpdater() { flush(); } - /// Add a segment to LI and coalesce when possible, just like LI.addRange(). - /// Segments should be added in increasing start order for best performance. - void add(LiveRange); + /// Add a segment to LR and coalesce when possible, just like + /// LR.addSegment(). Segments should be added in increasing start order for + /// best performance. + void add(LiveRange::Segment); void add(SlotIndex Start, SlotIndex End, VNInfo *VNI) { - add(LiveRange(Start, End, VNI)); + add(LiveRange::Segment(Start, End, VNI)); } - /// Return true if the LI is currently in an invalid state, and flush() + /// Return true if the LR is currently in an invalid state, and flush() /// needs to be called. bool isDirty() const { return LastStart.isValid(); } - /// Flush the updater state to LI so it is valid and contains all added + /// Flush the updater state to LR so it is valid and contains all added /// segments. void flush(); /// Select a different destination live range. - void setDest(LiveInterval *li) { - if (LI != li && isDirty()) + void setDest(LiveRange *lr) { + if (LR != lr && isDirty()) flush(); - LI = li; + LR = lr; } /// Get the current destination live range. - LiveInterval *getDest() const { return LI; } + LiveRange *getDest() const { return LR; } void dump() const; void print(raw_ostream&) const; @@ -538,99 +638,6 @@ namespace llvm { return OS; } - /// LiveRangeQuery - Query information about a live range around a given - /// instruction. This class hides the implementation details of live ranges, - /// and it should be used as the primary interface for examining live ranges - /// around instructions. - /// - class LiveRangeQuery { - VNInfo *EarlyVal; - VNInfo *LateVal; - SlotIndex EndPoint; - bool Kill; - - public: - /// Create a LiveRangeQuery for the given live range and instruction index. - /// The sub-instruction slot of Idx doesn't matter, only the instruction it - /// refers to is considered. - LiveRangeQuery(const LiveInterval &LI, SlotIndex Idx) - : EarlyVal(0), LateVal(0), Kill(false) { - // Find the segment that enters the instruction. - LiveInterval::const_iterator I = LI.find(Idx.getBaseIndex()); - LiveInterval::const_iterator E = LI.end(); - if (I == E) - return; - // Is this an instruction live-in segment? - // If Idx is the start index of a basic block, include live-in segments - // that start at Idx.getBaseIndex(). - if (I->start <= Idx.getBaseIndex()) { - EarlyVal = I->valno; - EndPoint = I->end; - // Move to the potentially live-out segment. - if (SlotIndex::isSameInstr(Idx, I->end)) { - Kill = true; - if (++I == E) - return; - } - // Special case: A PHIDef value can have its def in the middle of a - // segment if the value happens to be live out of the layout - // predecessor. - // Such a value is not live-in. - if (EarlyVal->def == Idx.getBaseIndex()) - EarlyVal = 0; - } - // I now points to the segment that may be live-through, or defined by - // this instr. Ignore segments starting after the current instr. - if (SlotIndex::isEarlierInstr(Idx, I->start)) - return; - LateVal = I->valno; - EndPoint = I->end; - } - - /// Return the value that is live-in to the instruction. This is the value - /// that will be read by the instruction's use operands. Return NULL if no - /// value is live-in. - VNInfo *valueIn() const { - return EarlyVal; - } - - /// Return true if the live-in value is killed by this instruction. This - /// means that either the live range ends at the instruction, or it changes - /// value. - bool isKill() const { - return Kill; - } - - /// Return true if this instruction has a dead def. - bool isDeadDef() const { - return EndPoint.isDead(); - } - - /// Return the value leaving the instruction, if any. This can be a - /// live-through value, or a live def. A dead def returns NULL. - VNInfo *valueOut() const { - return isDeadDef() ? 0 : 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 { - return EarlyVal == LateVal ? 0 : LateVal; - } - - /// Return the end point of the last live range segment to interact with - /// the instruction, if any. - /// - /// The end point is an invalid SlotIndex only if the live range doesn't - /// intersect the instruction at all. - /// - /// The end point may be at or past the end of the instruction's basic - /// block. That means the value was live out of the block. - SlotIndex endPoint() const { - return EndPoint; - } - }; - /// ConnectedVNInfoEqClasses - Helper class that can divide VNInfos in a /// LiveInterval into equivalence clases of connected components. A /// LiveInterval that has multiple connected components can be broken into diff --git a/contrib/llvm/include/llvm/CodeGen/LiveIntervalAnalysis.h b/contrib/llvm/include/llvm/CodeGen/LiveIntervalAnalysis.h index 7d72f3725..d8437f09a 100644 --- a/contrib/llvm/include/llvm/CodeGen/LiveIntervalAnalysis.h +++ b/contrib/llvm/include/llvm/CodeGen/LiveIntervalAnalysis.h @@ -35,6 +35,7 @@ namespace llvm { class AliasAnalysis; class BitVector; + class BlockFrequency; class LiveRangeCalc; class LiveVariables; class MachineDominatorTree; @@ -89,9 +90,9 @@ namespace llvm { /// block. SmallVector, 8> RegMaskBlocks; - /// RegUnitIntervals - Keep a live interval for each register unit as a way - /// of tracking fixed physreg interference. - SmallVector RegUnitIntervals; + /// Keeps a live range set for each register unit to track fixed physreg + /// interference. + SmallVector RegUnitRanges; public: static char ID; // Pass identification, replacement for typeid @@ -99,12 +100,13 @@ namespace llvm { virtual ~LiveIntervals(); // Calculate the spill weight to assign to a single instruction. - static float getSpillWeight(bool isDef, bool isUse, unsigned loopDepth); + static float getSpillWeight(bool isDef, bool isUse, BlockFrequency freq); LiveInterval &getInterval(unsigned Reg) { - LiveInterval *LI = VirtRegIntervals[Reg]; - assert(LI && "Interval does not exist for virtual register"); - return *LI; + if (hasInterval(Reg)) + return *VirtRegIntervals[Reg]; + else + return createAndComputeVirtRegInterval(Reg); } const LiveInterval &getInterval(unsigned Reg) const { @@ -116,12 +118,17 @@ namespace llvm { } // Interval creation. - LiveInterval &getOrCreateInterval(unsigned Reg) { - if (!hasInterval(Reg)) { - VirtRegIntervals.grow(Reg); - VirtRegIntervals[Reg] = createInterval(Reg); - } - return getInterval(Reg); + LiveInterval &createEmptyInterval(unsigned Reg) { + assert(!hasInterval(Reg) && "Interval already exists!"); + VirtRegIntervals.grow(Reg); + VirtRegIntervals[Reg] = createInterval(Reg); + return *VirtRegIntervals[Reg]; + } + + LiveInterval &createAndComputeVirtRegInterval(unsigned Reg) { + LiveInterval &LI = createEmptyInterval(Reg); + computeVirtRegInterval(LI); + return LI; } // Interval removal. @@ -130,10 +137,10 @@ namespace llvm { VirtRegIntervals[Reg] = 0; } - /// addLiveRangeToEndOfBlock - Given a register and an instruction, - /// adds a live range from that instruction to the end of its MBB. - LiveRange addLiveRangeToEndOfBlock(unsigned reg, - MachineInstr* startInst); + /// Given a register and an instruction, adds a live segment from that + /// instruction to the end of its MBB. + LiveInterval::Segment addSegmentToEndOfBlock(unsigned reg, + MachineInstr* startInst); /// shrinkToUses - After removing some uses of a register, shrink its live /// range to just the remaining uses. This method does not compute reaching @@ -153,7 +160,7 @@ namespace llvm { /// extended to be live out of the basic block. /// /// See also LiveRangeCalc::extend(). - void extendToIndices(LiveInterval *LI, ArrayRef Indices); + 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 @@ -199,14 +206,14 @@ namespace llvm { return Indexes->getMBBEndIdx(mbb); } - bool isLiveInToMBB(const LiveInterval &li, + bool isLiveInToMBB(const LiveRange &LR, const MachineBasicBlock *mbb) const { - return li.liveAt(getMBBStartIdx(mbb)); + return LR.liveAt(getMBBStartIdx(mbb)); } - bool isLiveOutOfMBB(const LiveInterval &li, + bool isLiveOutOfMBB(const LiveRange &LR, const MachineBasicBlock *mbb) const { - return li.liveAt(getMBBEndIdx(mbb).getPrevSlot()); + return LR.liveAt(getMBBEndIdx(mbb).getPrevSlot()); } MachineBasicBlock* getMBBFromIndex(SlotIndex index) const { @@ -224,6 +231,12 @@ namespace llvm { return Indexes->insertMachineInstrInMaps(MI); } + void InsertMachineInstrRangeInMaps(MachineBasicBlock::iterator B, + MachineBasicBlock::iterator E) { + for (MachineBasicBlock::iterator I = B; I != E; ++I) + Indexes->insertMachineInstrInMaps(I); + } + void RemoveMachineInstrFromMaps(MachineInstr *MI) { Indexes->removeMachineInstrFromMaps(MI); } @@ -351,24 +364,24 @@ namespace llvm { /// getRegUnit - Return the live range for Unit. /// It will be computed if it doesn't exist. - LiveInterval &getRegUnit(unsigned Unit) { - LiveInterval *LI = RegUnitIntervals[Unit]; - if (!LI) { + LiveRange &getRegUnit(unsigned Unit) { + LiveRange *LR = RegUnitRanges[Unit]; + if (!LR) { // Compute missing ranges on demand. - RegUnitIntervals[Unit] = LI = new LiveInterval(Unit, HUGE_VALF); - computeRegUnitInterval(LI); + RegUnitRanges[Unit] = LR = new LiveRange(); + computeRegUnitRange(*LR, Unit); } - return *LI; + return *LR; } /// getCachedRegUnit - Return the live range for Unit if it has already /// been computed, or NULL if it hasn't been computed yet. - LiveInterval *getCachedRegUnit(unsigned Unit) { - return RegUnitIntervals[Unit]; + LiveRange *getCachedRegUnit(unsigned Unit) { + return RegUnitRanges[Unit]; } - const LiveInterval *getCachedRegUnit(unsigned Unit) const { - return RegUnitIntervals[Unit]; + const LiveRange *getCachedRegUnit(unsigned Unit) const { + return RegUnitRanges[Unit]; } private: @@ -384,8 +397,8 @@ namespace llvm { void dumpInstrs() const; void computeLiveInRegUnits(); - void computeRegUnitInterval(LiveInterval*); - void computeVirtRegInterval(LiveInterval*); + void computeRegUnitRange(LiveRange&, unsigned Unit); + void computeVirtRegInterval(LiveInterval&); class HMEditor; }; diff --git a/contrib/llvm/include/llvm/CodeGen/LiveIntervalUnion.h b/contrib/llvm/include/llvm/CodeGen/LiveIntervalUnion.h index 615b339bd..95933d11d 100644 --- a/contrib/llvm/include/llvm/CodeGen/LiveIntervalUnion.h +++ b/contrib/llvm/include/llvm/CodeGen/LiveIntervalUnion.h @@ -32,7 +32,7 @@ typedef SparseBitVector<128> LiveVirtRegBitSet; /// Compare a live virtual register segment to a LiveIntervalUnion segment. inline bool -overlap(const LiveRange &VRSeg, +overlap(const LiveInterval::Segment &VRSeg, const IntervalMap::const_iterator &LUSeg) { return VRSeg.start < LUSeg.stop() && LUSeg.start() < VRSeg.end; } diff --git a/contrib/llvm/include/llvm/CodeGen/LiveRangeEdit.h b/contrib/llvm/include/llvm/CodeGen/LiveRangeEdit.h index e59276fd6..7edf67cc2 100644 --- a/contrib/llvm/include/llvm/CodeGen/LiveRangeEdit.h +++ b/contrib/llvm/include/llvm/CodeGen/LiveRangeEdit.h @@ -19,19 +19,21 @@ #define LLVM_CODEGEN_LIVERANGEEDIT_H #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/SetVector.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/CodeGen/LiveInterval.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/Target/TargetMachine.h" namespace llvm { class AliasAnalysis; class LiveIntervals; +class MachineBlockFrequencyInfo; class MachineLoopInfo; -class MachineRegisterInfo; class VirtRegMap; -class LiveRangeEdit { +class LiveRangeEdit : private MachineRegisterInfo::Delegate { public: /// Callback methods for LiveRangeEdit owners. class Delegate { @@ -56,7 +58,7 @@ public: private: LiveInterval *Parent; - SmallVectorImpl &NewRegs; + SmallVectorImpl &NewRegs; MachineRegisterInfo &MRI; LiveIntervals &LIS; VirtRegMap *VRM; @@ -89,6 +91,16 @@ private: /// a load, eliminate the register by folding the def into the use. bool foldAsLoad(LiveInterval *LI, SmallVectorImpl &Dead); + typedef SetVector, + SmallPtrSet > ToShrinkSet; + /// Helper for eliminateDeadDefs. + void eliminateDeadDef(MachineInstr *MI, ToShrinkSet &ToShrink); + + /// MachineRegisterInfo callback to notify when new virtual + /// registers are created. + void MRI_NoteNewVirtualRegister(unsigned VReg); + public: /// Create a LiveRangeEdit for breaking down parent into smaller pieces. /// @param parent The register being spilled or split. @@ -100,7 +112,7 @@ public: /// function. If NULL, no virtual register map updates will /// be done. This could be the case if called before Regalloc. LiveRangeEdit(LiveInterval *parent, - SmallVectorImpl &newRegs, + SmallVectorImpl &newRegs, MachineFunction &MF, LiveIntervals &lis, VirtRegMap *vrm, @@ -110,7 +122,9 @@ public: TII(*MF.getTarget().getInstrInfo()), TheDelegate(delegate), FirstNew(newRegs.size()), - ScannedRemattable(false) {} + ScannedRemattable(false) { MRI.setDelegate(this); } + + ~LiveRangeEdit() { MRI.resetDelegate(this); } LiveInterval &getParent() const { assert(Parent && "No parent LiveInterval"); @@ -119,23 +133,30 @@ public: unsigned getReg() const { return getParent().reg; } /// Iterator for accessing the new registers added by this edit. - typedef SmallVectorImpl::const_iterator iterator; + typedef SmallVectorImpl::const_iterator iterator; iterator begin() const { return NewRegs.begin()+FirstNew; } iterator end() const { return NewRegs.end(); } unsigned size() const { return NewRegs.size()-FirstNew; } bool empty() const { return size() == 0; } - LiveInterval *get(unsigned idx) const { return NewRegs[idx+FirstNew]; } + unsigned get(unsigned idx) const { return NewRegs[idx+FirstNew]; } - ArrayRef regs() const { + ArrayRef regs() const { return makeArrayRef(NewRegs).slice(FirstNew); } + /// createEmptyIntervalFrom - Create a new empty interval based on OldReg. + LiveInterval &createEmptyIntervalFrom(unsigned OldReg); + /// createFrom - Create a new virtual register based on OldReg. - LiveInterval &createFrom(unsigned OldReg); + unsigned createFrom(unsigned OldReg); /// create - Create a new register with the same class and original slot as /// parent. - LiveInterval &create() { + LiveInterval &createEmptyInterval() { + return createEmptyIntervalFrom(getReg()); + } + + unsigned create() { return createFrom(getReg()); } @@ -201,7 +222,8 @@ public: /// calculateRegClassAndHint - Recompute register class and hint for each new /// register. void calculateRegClassAndHint(MachineFunction&, - const MachineLoopInfo&); + const MachineLoopInfo&, + const MachineBlockFrequencyInfo&); }; } diff --git a/contrib/llvm/include/llvm/CodeGen/LiveRegUnits.h b/contrib/llvm/include/llvm/CodeGen/LiveRegUnits.h new file mode 100644 index 000000000..02b9c55cc --- /dev/null +++ b/contrib/llvm/include/llvm/CodeGen/LiveRegUnits.h @@ -0,0 +1,88 @@ +//===-- llvm/CodeGen/LiveRegUnits.h - Live register unit set ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements a Set of live register units. This can be used for ad +// hoc liveness tracking after register allocation. You can start with the +// live-ins/live-outs at the beginning/end of a block and update the information +// while walking the instructions inside the block. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_LIVEREGUNITS_H +#define LLVM_CODEGEN_LIVEREGUNITS_H + +#include "llvm/ADT/SparseSet.h" +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include + +namespace llvm { + +class MachineInstr; + +/// A set of live register units with functions to track liveness when walking +/// backward/forward through a basic block. +class LiveRegUnits { + SparseSet LiveUnits; + + LiveRegUnits(const LiveRegUnits&) LLVM_DELETED_FUNCTION; + LiveRegUnits &operator=(const LiveRegUnits&) LLVM_DELETED_FUNCTION; +public: + /// \brief Constructs a new empty LiveRegUnits set. + LiveRegUnits() {} + + void init(const TargetRegisterInfo *TRI) { + LiveUnits.clear(); + LiveUnits.setUniverse(TRI->getNumRegs()); + } + + void clear() { LiveUnits.clear(); } + + bool empty() const { return LiveUnits.empty(); } + + /// \brief Adds a register to the set. + void addReg(unsigned Reg, const MCRegisterInfo &MCRI) { + for (MCRegUnitIterator RUnits(Reg, &MCRI); RUnits.isValid(); ++RUnits) + LiveUnits.insert(*RUnits); + } + + /// \brief Removes a register from the set. + void removeReg(unsigned Reg, const MCRegisterInfo &MCRI) { + for (MCRegUnitIterator RUnits(Reg, &MCRI); RUnits.isValid(); ++RUnits) + LiveUnits.erase(*RUnits); + } + + /// \brief Removes registers clobbered by the regmask operand @p Op. + void removeRegsInMask(const MachineOperand &Op, const MCRegisterInfo &MCRI); + + /// \brief Returns true if register @p Reg (or one of its super register) is + /// contained in the set. + bool contains(unsigned Reg, const MCRegisterInfo &MCRI) const { + for (MCRegUnitIterator RUnits(Reg, &MCRI); RUnits.isValid(); ++RUnits) { + if (LiveUnits.count(*RUnits)) + return true; + } + return false; + } + + /// \brief Simulates liveness when stepping backwards over an + /// instruction(bundle): Remove Defs, add uses. + void stepBackward(const MachineInstr &MI, const MCRegisterInfo &MCRI); + + /// \brief Simulates liveness when stepping forward over an + /// instruction(bundle): Remove killed-uses, add defs. + void stepForward(const MachineInstr &MI, const MCRegisterInfo &MCRI); + + /// \brief Adds all registers in the live-in list of block @p BB. + void addLiveIns(const MachineBasicBlock *MBB, const MCRegisterInfo &MCRI); +}; + +} // namespace llvm + +#endif diff --git a/contrib/llvm/include/llvm/CodeGen/LiveVariables.h b/contrib/llvm/include/llvm/CodeGen/LiveVariables.h index 6628fd278..dc735f7b5 100644 --- a/contrib/llvm/include/llvm/CodeGen/LiveVariables.h +++ b/contrib/llvm/include/llvm/CodeGen/LiveVariables.h @@ -157,8 +157,8 @@ private: // Intermediate data structures void HandlePhysRegUse(unsigned Reg, MachineInstr *MI); void HandlePhysRegDef(unsigned Reg, MachineInstr *MI, - SmallVector &Defs); - void UpdatePhysRegDefs(MachineInstr *MI, SmallVector &Defs); + SmallVectorImpl &Defs); + void UpdatePhysRegDefs(MachineInstr *MI, SmallVectorImpl &Defs); /// FindLastRefOrPartRef - Return the last reference or partial reference of /// the specified register. diff --git a/contrib/llvm/include/llvm/CodeGen/MachineBasicBlock.h b/contrib/llvm/include/llvm/CodeGen/MachineBasicBlock.h index d6f588304..7717809e0 100644 --- a/contrib/llvm/include/llvm/CodeGen/MachineBasicBlock.h +++ b/contrib/llvm/include/llvm/CodeGen/MachineBasicBlock.h @@ -410,8 +410,8 @@ public: /// branch to do so (e.g., a table jump). True is a conservative answer. bool canFallThrough(); - /// Returns a pointer to the first instructon in this block that is not a - /// PHINode instruction. When adding instruction to the beginning of the + /// Returns a pointer to the first instruction in this block that is not a + /// PHINode instruction. When adding instructions to the beginning of the /// basic block, they should be added before the returned value, not before /// the first instruction, which might be PHI. /// Returns end() is there's no non-PHI instruction. @@ -733,6 +733,31 @@ template <> struct GraphTraits > { } }; + + +/// MachineInstrSpan provides an interface to get an iteration range +/// containing the instruction it was initialized with, along with all +/// those instructions inserted prior to or following that instruction +/// at some point after the MachineInstrSpan is constructed. +class MachineInstrSpan { + MachineBasicBlock &MBB; + MachineBasicBlock::iterator I, B, E; +public: + MachineInstrSpan(MachineBasicBlock::iterator I) + : MBB(*I->getParent()), + I(I), + B(I == MBB.begin() ? MBB.end() : llvm::prior(I)), + E(llvm::next(I)) {} + + MachineBasicBlock::iterator begin() { + return B == MBB.end() ? MBB.begin() : llvm::next(B); + } + MachineBasicBlock::iterator end() { return E; } + bool empty() { return begin() == end(); } + + MachineBasicBlock::iterator getInitial() { return I; } +}; + } // End llvm namespace #endif diff --git a/contrib/llvm/include/llvm/CodeGen/MachineBranchProbabilityInfo.h b/contrib/llvm/include/llvm/CodeGen/MachineBranchProbabilityInfo.h index 98dd03b45..c59948fd6 100644 --- a/contrib/llvm/include/llvm/CodeGen/MachineBranchProbabilityInfo.h +++ b/contrib/llvm/include/llvm/CodeGen/MachineBranchProbabilityInfo.h @@ -1,4 +1,4 @@ -//==- MachineBranchProbabilityInfo.h - Machine Branch Probability Analysis -==// +//=- MachineBranchProbabilityInfo.h - Branch Probability Analysis -*- C++ -*-=// // // The LLVM Compiler Infrastructure // diff --git a/contrib/llvm/include/llvm/CodeGen/MachineConstantPool.h b/contrib/llvm/include/llvm/CodeGen/MachineConstantPool.h index 8ed215d75..912ce8966 100644 --- a/contrib/llvm/include/llvm/CodeGen/MachineConstantPool.h +++ b/contrib/llvm/include/llvm/CodeGen/MachineConstantPool.h @@ -132,15 +132,17 @@ public: /// address of the function constant pool values. /// @brief The machine constant pool. class MachineConstantPool { - const DataLayout *TD; ///< The machine's DataLayout. - unsigned PoolAlignment; ///< The alignment for the pool. + const TargetMachine &TM; ///< The target machine. + unsigned PoolAlignment; ///< The alignment for the pool. std::vector Constants; ///< The pool of constants. /// MachineConstantPoolValues that use an existing MachineConstantPoolEntry. DenseSet MachineCPVsSharingEntries; + + const DataLayout *getDataLayout() const; public: /// @brief The only constructor. - explicit MachineConstantPool(const DataLayout *td) - : TD(td), PoolAlignment(1) {} + explicit MachineConstantPool(const TargetMachine &TM) + : TM(TM), PoolAlignment(1) {} ~MachineConstantPool(); /// getConstantPoolAlignment - Return the alignment required by diff --git a/contrib/llvm/include/llvm/CodeGen/MachineFrameInfo.h b/contrib/llvm/include/llvm/CodeGen/MachineFrameInfo.h index cdec7e663..022634df8 100644 --- a/contrib/llvm/include/llvm/CodeGen/MachineFrameInfo.h +++ b/contrib/llvm/include/llvm/CodeGen/MachineFrameInfo.h @@ -27,6 +27,7 @@ class Type; class MachineFunction; class MachineBasicBlock; class TargetFrameLowering; +class TargetMachine; class BitVector; class Value; class AllocaInst; @@ -119,6 +120,8 @@ class MachineFrameInfo { isSpillSlot(isSS), MayNeedSP(NSP), Alloca(Val), PreAllocated(false) {} }; + const TargetMachine &TM; + /// Objects - The list of stack objects allocated... /// std::vector Objects; @@ -201,10 +204,6 @@ class MachineFrameInfo { /// CSIValid - Has CSInfo been set yet? bool CSIValid; - /// TargetFrameLowering - Target information about frame layout. - /// - const TargetFrameLowering &TFI; - /// LocalFrameObjects - References to frame indices which are mapped /// into the local frame allocation block. SmallVector, 32> LocalFrameObjects; @@ -223,9 +222,11 @@ class MachineFrameInfo { /// Whether the "realign-stack" option is on. bool RealignOption; + + const TargetFrameLowering *getFrameLowering() const; public: - explicit MachineFrameInfo(const TargetFrameLowering &tfi, bool RealignOpt) - : TFI(tfi), RealignOption(RealignOpt) { + explicit MachineFrameInfo(const TargetMachine &TM, bool RealignOpt) + : TM(TM), RealignOption(RealignOpt) { StackSize = NumFixedObjects = OffsetAdjustment = MaxAlignment = 0; HasVarSizedObjects = false; FrameAddressTaken = false; diff --git a/contrib/llvm/include/llvm/CodeGen/MachineInstr.h b/contrib/llvm/include/llvm/CodeGen/MachineInstr.h index 195cce7a6..cccab81ef 100644 --- a/contrib/llvm/include/llvm/CodeGen/MachineInstr.h +++ b/contrib/llvm/include/llvm/CodeGen/MachineInstr.h @@ -397,8 +397,8 @@ public: return isBranch(Type) & isBarrier(Type) & !isIndirectBranch(Type); } - // isPredicable - Return true if this instruction has a predicate operand that - // controls execution. It may be set to 'always', or may be set to other + /// Return true if this instruction has a predicate operand that + /// controls execution. It may be set to 'always', or may be set to other /// values. There are various methods in TargetInstrInfo that can be used to /// control and modify the predicate in this instruction. bool isPredicable(QueryType Type = AllInBundle) const { @@ -637,6 +637,13 @@ public: bool isEHLabel() const { return getOpcode() == TargetOpcode::EH_LABEL; } bool isGCLabel() const { return getOpcode() == TargetOpcode::GC_LABEL; } bool isDebugValue() const { return getOpcode() == TargetOpcode::DBG_VALUE; } + /// A DBG_VALUE is indirect iff the first operand is a register and + /// the second operand is an immediate. + bool isIndirectDebugValue() const { + return isDebugValue() + && getOperand(0).isReg() + && getOperand(1).isImm(); + } bool isPHI() const { return getOpcode() == TargetOpcode::PHI; } bool isKill() const { return getOpcode() == TargetOpcode::KILL; } @@ -886,13 +893,12 @@ public: /// Look for the operand that defines it and mark it as IsDead. If /// AddIfNotFound is true, add a implicit operand if it's not found. Returns /// true if the operand exists / is added. - bool addRegisterDead(unsigned IncomingReg, const TargetRegisterInfo *RegInfo, + bool addRegisterDead(unsigned Reg, const TargetRegisterInfo *RegInfo, bool AddIfNotFound = false); /// addRegisterDefined - We have determined MI defines a register. Make sure /// there is an operand defining Reg. - void addRegisterDefined(unsigned IncomingReg, - const TargetRegisterInfo *RegInfo = 0); + void addRegisterDefined(unsigned Reg, const TargetRegisterInfo *RegInfo = 0); /// setPhysRegsDeadExcept - Mark every physreg used by this instruction as /// dead except those in the UsedRegs list. @@ -908,11 +914,6 @@ public: bool isSafeToMove(const TargetInstrInfo *TII, AliasAnalysis *AA, bool &SawStore) const; - /// isSafeToReMat - Return true if it's safe to rematerialize the specified - /// instruction which defined the specified register instead of copying it. - bool isSafeToReMat(const TargetInstrInfo *TII, AliasAnalysis *AA, - unsigned DstReg) const; - /// hasOrderedMemoryRef - Return true if this instruction may have an ordered /// or volatile memory reference, or if the information describing the memory /// reference is not available. Return false if it is known to have no diff --git a/contrib/llvm/include/llvm/CodeGen/MachineInstrBuilder.h b/contrib/llvm/include/llvm/CodeGen/MachineInstrBuilder.h index 92c8da991..df01371a4 100644 --- a/contrib/llvm/include/llvm/CodeGen/MachineInstrBuilder.h +++ b/contrib/llvm/include/llvm/CodeGen/MachineInstrBuilder.h @@ -335,6 +335,51 @@ inline MachineInstrBuilder BuildMI(MachineBasicBlock *BB, return BuildMI(*BB, BB->end(), DL, MCID, DestReg); } +/// BuildMI - This version of the builder builds a DBG_VALUE intrinsic +/// for either a value in a register or a register-indirect+offset +/// address. The convention is that a DBG_VALUE is indirect iff the +/// second operand is an immediate. +/// +inline MachineInstrBuilder BuildMI(MachineFunction &MF, + DebugLoc DL, + const MCInstrDesc &MCID, + bool IsIndirect, + unsigned Reg, + unsigned Offset, + const MDNode *MD) { + if (IsIndirect) + return BuildMI(MF, DL, MCID) + .addReg(Reg, RegState::Debug) + .addImm(Offset) + .addMetadata(MD); + else { + assert(Offset == 0 && "A direct address cannot have an offset."); + return BuildMI(MF, DL, MCID) + .addReg(Reg, RegState::Debug) + .addReg(0U, RegState::Debug) + .addMetadata(MD); + } +} + +/// BuildMI - This version of the builder builds a DBG_VALUE intrinsic +/// for either a value in a register or a register-indirect+offset +/// address and inserts it at position I. +/// +inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB, + MachineBasicBlock::iterator I, + DebugLoc DL, + const MCInstrDesc &MCID, + bool IsIndirect, + unsigned Reg, + unsigned Offset, + const MDNode *MD) { + MachineFunction &MF = *BB.getParent(); + MachineInstr *MI = BuildMI(MF, DL, MCID, IsIndirect, Reg, Offset, MD); + BB.insert(I, MI); + return MachineInstrBuilder(MF, MI); +} + + inline unsigned getDefRegState(bool B) { return B ? RegState::Define : 0; } diff --git a/contrib/llvm/include/llvm/CodeGen/MachineModuleInfo.h b/contrib/llvm/include/llvm/CodeGen/MachineModuleInfo.h index a3acec809..460c08c8c 100644 --- a/contrib/llvm/include/llvm/CodeGen/MachineModuleInfo.h +++ b/contrib/llvm/include/llvm/CodeGen/MachineModuleInfo.h @@ -106,9 +106,9 @@ class MachineModuleInfo : public ImmutablePass { /// want. MachineModuleInfoImpl *ObjFileMMI; - /// FrameMoves - List of moves done by a function's prolog. Used to construct - /// frame maps by debug and exception handling consumers. - std::vector FrameMoves; + /// List of moves done by a function's prolog. Used to construct frame maps + /// by debug and exception handling consumers. + std::vector FrameInstructions; /// CompactUnwindEncoding - If the target supports it, this is the compact /// unwind encoding. It replaces a function's CIE and FDE. @@ -231,10 +231,16 @@ public: UsesVAFloatArgument = b; } - /// getFrameMoves - Returns a reference to a list of moves done in the current + /// \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. - std::vector &getFrameMoves() { return FrameMoves; } + const std::vector &getFrameInstructions() const { + return FrameInstructions; + } + + void addFrameInst(const MCCFIInstruction &Inst) { + FrameInstructions.push_back(Inst); + } /// getCompactUnwindEncoding - Returns the compact unwind encoding for a /// function if the target supports the encoding. This encoding replaces a diff --git a/contrib/llvm/include/llvm/CodeGen/MachineOperand.h b/contrib/llvm/include/llvm/CodeGen/MachineOperand.h index 414770b9e..40f3580bf 100644 --- a/contrib/llvm/include/llvm/CodeGen/MachineOperand.h +++ b/contrib/llvm/include/llvm/CodeGen/MachineOperand.h @@ -391,7 +391,7 @@ public: } void setIsDebug(bool Val = true) { - assert(isReg() && IsDef && "Wrong MachineOperand accessor"); + assert(isReg() && !IsDef && "Wrong MachineOperand accessor"); IsDebug = Val; } @@ -564,6 +564,8 @@ public: unsigned SubReg = 0, bool isDebug = false, bool isInternalRead = false) { + assert(!(isDead && !isDef) && "Dead flag on non-def"); + assert(!(isKill && isDef) && "Kill flag on def"); MachineOperand Op(MachineOperand::MO_Register); Op.IsDef = isDef; Op.IsImp = isImp; diff --git a/contrib/llvm/include/llvm/CodeGen/MachineRegisterInfo.h b/contrib/llvm/include/llvm/CodeGen/MachineRegisterInfo.h index 24ba7bb1a..58ca90731 100644 --- a/contrib/llvm/include/llvm/CodeGen/MachineRegisterInfo.h +++ b/contrib/llvm/include/llvm/CodeGen/MachineRegisterInfo.h @@ -17,16 +17,29 @@ #include "llvm/ADT/BitVector.h" #include "llvm/ADT/IndexedMap.h" #include "llvm/CodeGen/MachineInstrBundle.h" +#include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetRegisterInfo.h" #include namespace llvm { +class PSetIterator; /// MachineRegisterInfo - Keep track of information for virtual and physical /// registers, including vreg register classes, use/def chains for registers, /// etc. class MachineRegisterInfo { - const TargetRegisterInfo *const TRI; +public: + class Delegate { + virtual void anchor(); + public: + virtual void MRI_NoteNewVirtualRegister(unsigned Reg) = 0; + + virtual ~Delegate() {} + }; + +private: + const TargetMachine &TM; + Delegate *TheDelegate; /// IsSSA - True when the machine function is in SSA form and virtual /// registers have a single def. @@ -108,9 +121,30 @@ class MachineRegisterInfo { MachineRegisterInfo(const MachineRegisterInfo&) LLVM_DELETED_FUNCTION; void operator=(const MachineRegisterInfo&) LLVM_DELETED_FUNCTION; public: - explicit MachineRegisterInfo(const TargetRegisterInfo &TRI); + explicit MachineRegisterInfo(const TargetMachine &TM); ~MachineRegisterInfo(); + const TargetRegisterInfo *getTargetRegisterInfo() const { + return TM.getRegisterInfo(); + } + + void resetDelegate(Delegate *delegate) { + // Ensure another delegate does not take over unless the current + // delegate first unattaches itself. If we ever need to multicast + // notifications, we will need to change to using a list. + assert(TheDelegate == delegate && + "Only the current delegate can perform reset!"); + TheDelegate = 0; + } + + void setDelegate(Delegate *delegate) { + assert(delegate && !TheDelegate && + "Attempted to set delegate to null, or to change it without " + "first resetting it!"); + + TheDelegate = delegate; + } + //===--------------------------------------------------------------------===// // Function State //===--------------------------------------------------------------------===// @@ -294,6 +328,11 @@ public: /// a physreg. bool isConstantPhysReg(unsigned PhysReg, const MachineFunction &MF) const; + /// Get an iterator over the pressure sets affected by the given physical or + /// virtual register. If RegUnit is physical, it must be a register unit (from + /// MCRegUnitIterator). + PSetIterator getPressureSets(unsigned RegUnit) const; + //===--------------------------------------------------------------------===// // Virtual Register Info //===--------------------------------------------------------------------===// @@ -377,7 +416,8 @@ public: bool isPhysRegUsed(unsigned Reg) const { if (UsedPhysRegMask.test(Reg)) return true; - for (MCRegUnitIterator Units(Reg, TRI); Units.isValid(); ++Units) + for (MCRegUnitIterator Units(Reg, getTargetRegisterInfo()); + Units.isValid(); ++Units) if (UsedRegUnits.test(*Units)) return true; return false; @@ -392,7 +432,8 @@ public: /// setPhysRegUsed - Mark the specified register used in this function. /// This should only be called during and after register allocation. void setPhysRegUsed(unsigned Reg) { - for (MCRegUnitIterator Units(Reg, TRI); Units.isValid(); ++Units) + for (MCRegUnitIterator Units(Reg, getTargetRegisterInfo()); + Units.isValid(); ++Units) UsedRegUnits.set(*Units); } @@ -406,7 +447,8 @@ public: /// This should only be called during and after register allocation. void setPhysRegUnused(unsigned Reg) { UsedPhysRegMask.reset(Reg); - for (MCRegUnitIterator Units(Reg, TRI); Units.isValid(); ++Units) + for (MCRegUnitIterator Units(Reg, getTargetRegisterInfo()); + Units.isValid(); ++Units) UsedRegUnits.reset(*Units); } @@ -466,7 +508,8 @@ public: /// register, so a register allocator needs to track its liveness and /// availability. bool isAllocatable(unsigned PhysReg) const { - return TRI->isInAllocatableClass(PhysReg) && !isReserved(PhysReg); + return getTargetRegisterInfo()->isInAllocatableClass(PhysReg) && + !isReserved(PhysReg); } //===--------------------------------------------------------------------===// @@ -611,9 +654,49 @@ public: return Op->getParent(); } }; +}; +/// Iterate over the pressure sets affected by the given physical or virtual +/// register. If Reg is physical, it must be a register unit (from +/// MCRegUnitIterator). +class PSetIterator { + const int *PSet; + unsigned Weight; +public: + PSetIterator(): PSet(0), Weight(0) {} + PSetIterator(unsigned RegUnit, const MachineRegisterInfo *MRI) { + const TargetRegisterInfo *TRI = MRI->getTargetRegisterInfo(); + if (TargetRegisterInfo::isVirtualRegister(RegUnit)) { + const TargetRegisterClass *RC = MRI->getRegClass(RegUnit); + PSet = TRI->getRegClassPressureSets(RC); + Weight = TRI->getRegClassWeight(RC).RegWeight; + } + else { + PSet = TRI->getRegUnitPressureSets(RegUnit); + Weight = TRI->getRegUnitWeight(RegUnit); + } + if (*PSet == -1) + PSet = 0; + } + bool isValid() const { return PSet; } + + unsigned getWeight() const { return Weight; } + + unsigned operator*() const { return *PSet; } + + void operator++() { + assert(isValid() && "Invalid PSetIterator."); + ++PSet; + if (*PSet == -1) + PSet = 0; + } }; +inline PSetIterator MachineRegisterInfo:: +getPressureSets(unsigned RegUnit) const { + return PSetIterator(RegUnit, this); +} + } // End llvm namespace #endif diff --git a/contrib/llvm/include/llvm/CodeGen/MachineRelocation.h b/contrib/llvm/include/llvm/CodeGen/MachineRelocation.h index 244b466e1..e77845745 100644 --- a/contrib/llvm/include/llvm/CodeGen/MachineRelocation.h +++ b/contrib/llvm/include/llvm/CodeGen/MachineRelocation.h @@ -57,7 +57,7 @@ class MachineRelocation { union { void *Result; // If this has been resolved to a resolved pointer GlobalValue *GV; // If this is a pointer to a GV or an indirect ref. - MachineBasicBlock *MBB; // If this is a pointer to a LLVM BB + MachineBasicBlock *MBB; // If this is a pointer to an LLVM BB const char *ExtSym; // If this is a pointer to a named symbol unsigned Index; // Constant pool / jump table index unsigned GOTIndex; // Index in the GOT of this symbol/global diff --git a/contrib/llvm/include/llvm/CodeGen/MachineScheduler.h b/contrib/llvm/include/llvm/CodeGen/MachineScheduler.h index 769e4b42a..778289533 100644 --- a/contrib/llvm/include/llvm/CodeGen/MachineScheduler.h +++ b/contrib/llvm/include/llvm/CodeGen/MachineScheduler.h @@ -7,8 +7,48 @@ // //===----------------------------------------------------------------------===// // -// This file provides a MachineSchedRegistry for registering alternative machine -// schedulers. A Target may provide an alternative scheduler implementation by +// This file provides an interface for customizing the standard MachineScheduler +// pass. Note that the entire pass may be replaced as follows: +// +// TargetMachine::createPassConfig(PassManagerBase &PM) { +// PM.substitutePass(&MachineSchedulerID, &CustomSchedulerPassID); +// ...} +// +// The MachineScheduler pass is only responsible for choosing the regions to be +// scheduled. Targets can override the DAG builder and scheduler without +// replacing the pass as follows: +// +// ScheduleDAGInstrs *PassConfig:: +// createMachineScheduler(MachineSchedContext *C) { +// return new CustomMachineScheduler(C); +// } +// +// The default scheduler, ScheduleDAGMI, builds the DAG and drives list +// scheduling while updating the instruction stream, register pressure, and live +// intervals. Most targets don't need to override the DAG builder and list +// schedulier, but subtargets that require custom scheduling heuristics may +// plugin an alternate MachineSchedStrategy. The strategy is responsible for +// selecting the highest priority node from the list: +// +// ScheduleDAGInstrs *PassConfig:: +// createMachineScheduler(MachineSchedContext *C) { +// return new ScheduleDAGMI(C, CustomStrategy(C)); +// } +// +// The DAG builder can also be customized in a sense by adding DAG mutations +// that will run after DAG building and before list scheduling. DAG mutations +// can adjust dependencies based on target-specific knowledge or add weak edges +// to aid heuristics: +// +// ScheduleDAGInstrs *PassConfig:: +// createMachineScheduler(MachineSchedContext *C) { +// ScheduleDAGMI *DAG = new ScheduleDAGMI(C, CustomStrategy(C)); +// DAG->addMutation(new CustomDependencies(DAG->TII, DAG->TRI)); +// return DAG; +// } +// +// A target that supports alternative schedulers can use the +// MachineSchedRegistry to allow command line selection. This can be done by // implementing the following boilerplate: // // static ScheduleDAGInstrs *createCustomMachineSched(MachineSchedContext *C) { @@ -18,9 +58,19 @@ // SchedCustomRegistry("custom", "Run my target's custom scheduler", // createCustomMachineSched); // -// Inside PassConfig: -// enablePass(&MachineSchedulerID); -// MachineSchedRegistry::setDefault(createCustomMachineSched); +// +// Finally, subtargets that don't need to implement custom heuristics but would +// like to configure the GenericScheduler's policy for a given scheduler region, +// including scheduling direction and register pressure tracking policy, can do +// this: +// +// void Subtarget:: +// overrideSchedPolicy(MachineSchedPolicy &Policy, +// MachineInstr *begin, +// MachineInstr *end, +// unsigned NumRegionInstrs) const { +// Policy. = true; +// } // //===----------------------------------------------------------------------===// @@ -30,7 +80,6 @@ #include "llvm/CodeGen/MachinePassRegistry.h" #include "llvm/CodeGen/RegisterPressure.h" #include "llvm/CodeGen/ScheduleDAGInstrs.h" -#include "llvm/Target/TargetInstrInfo.h" namespace llvm { @@ -86,15 +135,6 @@ public: static MachineSchedRegistry *getList() { return (MachineSchedRegistry *)Registry.getList(); } - static ScheduleDAGCtor getDefault() { - return (ScheduleDAGCtor)Registry.getDefault(); - } - static void setDefault(ScheduleDAGCtor C) { - Registry.setDefault((MachinePassCtor)C); - } - static void setDefault(StringRef Name) { - Registry.setDefault(Name); - } static void setListener(MachinePassRegistryListener *L) { Registry.setListener(L); } @@ -102,12 +142,41 @@ public: class ScheduleDAGMI; +/// Define a generic scheduling policy for targets that don't provide their own +/// MachineSchedStrategy. This can be overriden for each scheduling region +/// before building the DAG. +struct MachineSchedPolicy { + // Allow the scheduler to disable register pressure tracking. + bool ShouldTrackPressure; + + // Allow the scheduler to force top-down or bottom-up scheduling. If neither + // is true, the scheduler runs in both directions and converges. + bool OnlyTopDown; + bool OnlyBottomUp; + + MachineSchedPolicy(): + ShouldTrackPressure(false), OnlyTopDown(false), OnlyBottomUp(false) {} +}; + /// MachineSchedStrategy - Interface to the scheduling algorithm used by /// ScheduleDAGMI. +/// +/// Initialization sequence: +/// initPolicy -> shouldTrackPressure -> initialize(DAG) -> registerRoots class MachineSchedStrategy { + virtual void anchor(); public: virtual ~MachineSchedStrategy() {} + /// Optionally override the per-region scheduling policy. + virtual void initPolicy(MachineBasicBlock::iterator Begin, + MachineBasicBlock::iterator End, + unsigned NumRegionInstrs) {} + + /// Check if pressure tracking is needed before building the DAG and + /// initializing this strategy. Called after initPolicy. + virtual bool shouldTrackPressure() const { return true; } + /// Initialize the strategy after building the DAG for a new region. virtual void initialize(ScheduleDAGMI *DAG) = 0; @@ -194,6 +263,7 @@ public: /// Mutate the DAG as a postpass after normal DAG building. class ScheduleDAGMutation { + virtual void anchor(); public: virtual ~ScheduleDAGMutation() {} @@ -222,14 +292,20 @@ protected: MachineBasicBlock::iterator LiveRegionEnd; - /// Register pressure in this region computed by buildSchedGraph. + // Map each SU to its summary of pressure changes. This array is updated for + // liveness during bottom-up scheduling. Top-down scheduling may proceed but + // has no affect on the pressure diffs. + PressureDiffs SUPressureDiffs; + + /// Register pressure in this region computed by initRegPressure. + bool ShouldTrackPressure; IntervalPressure RegPressure; RegPressureTracker RPTracker; /// List of pressure sets that exceed the target's pressure limit before /// scheduling, listed in increasing set ID order. Each pressure set is paired /// with its max pressure in the currently scheduled regions. - std::vector RegionCriticalPSets; + std::vector RegionCriticalPSets; /// The top of the unscheduled zone. MachineBasicBlock::iterator CurrentTop; @@ -255,8 +331,9 @@ public: ScheduleDAGMI(MachineSchedContext *C, MachineSchedStrategy *S): ScheduleDAGInstrs(*C->MF, *C->MLI, *C->MDT, /*IsPostRA=*/false, C->LIS), AA(C->AA), RegClassInfo(C->RegClassInfo), SchedImpl(S), DFSResult(0), - Topo(SUnits, &ExitSU), RPTracker(RegPressure), CurrentTop(), - TopRPTracker(TopPressure), CurrentBottom(), BotRPTracker(BotPressure), + Topo(SUnits, &ExitSU), ShouldTrackPressure(false), + RPTracker(RegPressure), CurrentTop(), TopRPTracker(TopPressure), + CurrentBottom(), BotRPTracker(BotPressure), NextClusterPred(NULL), NextClusterSucc(NULL) { #ifndef NDEBUG NumInstrsScheduled = 0; @@ -265,6 +342,9 @@ public: virtual ~ScheduleDAGMI(); + /// \brief Return true if register pressure tracking is enabled. + bool isTrackingPressure() const { return ShouldTrackPressure; } + /// Add a postprocessing step to the DAG builder. /// Mutations are applied in the order that they are added after normal DAG /// building and before MachineSchedStrategy initialization. @@ -294,8 +374,7 @@ public: void enterRegion(MachineBasicBlock *bb, MachineBasicBlock::iterator begin, MachineBasicBlock::iterator end, - unsigned endcount); - + unsigned regioninstrs) LLVM_OVERRIDE; /// Implement ScheduleDAGInstrs interface for scheduling a sequence of /// reorderable instructions. @@ -316,10 +395,14 @@ public: /// Get register pressure for the entire scheduling region before scheduling. const IntervalPressure &getRegPressure() const { return RegPressure; } - const std::vector &getRegionCriticalPSets() const { + const std::vector &getRegionCriticalPSets() const { return RegionCriticalPSets; } + PressureDiff &getPressureDiff(const SUnit *SU) { + return SUPressureDiffs[SU->NodeNum]; + } + const SUnit *getNextClusterPred() const { return NextClusterPred; } const SUnit *getNextClusterSucc() const { return NextClusterSucc; } @@ -333,6 +416,9 @@ public: BitVector &getScheduledTrees() { return ScheduledTrees; } + /// Compute the cyclic critical path through the DAG. + unsigned computeCyclicCriticalPath(); + void viewGraph(const Twine &Name, const Twine &Title) LLVM_OVERRIDE; void viewGraph() LLVM_OVERRIDE; @@ -368,7 +454,10 @@ protected: void initRegPressure(); - void updateScheduledPressure(const std::vector &NewMaxPressure); + void updatePressureDiffs(ArrayRef LiveUses); + + void updateScheduledPressure(const SUnit *SU, + const std::vector &NewMaxPressure); bool checkSchedLimit(); diff --git a/contrib/llvm/include/llvm/CodeGen/PBQP/Graph.h b/contrib/llvm/include/llvm/CodeGen/PBQP/Graph.h index 85bf511d6..aca0a9130 100644 --- a/contrib/llvm/include/llvm/CodeGen/PBQP/Graph.h +++ b/contrib/llvm/include/llvm/CodeGen/PBQP/Graph.h @@ -20,79 +20,63 @@ #include "llvm/ADT/ilist_node.h" #include #include +#include namespace PBQP { /// PBQP Graph class. /// Instances of this class describe PBQP problems. class Graph { - private: - - // ----- TYPEDEFS ----- - class NodeEntry; - class EdgeEntry; - - typedef llvm::ilist NodeList; - typedef llvm::ilist EdgeList; - public: - typedef NodeEntry* NodeItr; - typedef const NodeEntry* ConstNodeItr; - - typedef EdgeEntry* EdgeItr; - typedef const EdgeEntry* ConstEdgeItr; + typedef unsigned NodeId; + typedef unsigned EdgeId; private: - typedef std::list AdjEdgeList; - + typedef std::set AdjEdgeList; + public: typedef AdjEdgeList::iterator AdjEdgeItr; private: - class NodeEntry : public llvm::ilist_node { - friend struct llvm::ilist_sentinel_traits; + class NodeEntry { private: - Vector costs; + Vector costs; AdjEdgeList adjEdges; - unsigned degree; void *data; NodeEntry() : costs(0, 0) {} public: - NodeEntry(const Vector &costs) : costs(costs), degree(0) {} + NodeEntry(const Vector &costs) : costs(costs), data(0) {} Vector& getCosts() { return costs; } const Vector& getCosts() const { return costs; } - unsigned getDegree() const { return degree; } + unsigned getDegree() const { return adjEdges.size(); } AdjEdgeItr edgesBegin() { return adjEdges.begin(); } AdjEdgeItr edgesEnd() { return adjEdges.end(); } - AdjEdgeItr addEdge(EdgeItr e) { - ++degree; + AdjEdgeItr addEdge(EdgeId e) { return adjEdges.insert(adjEdges.end(), e); } void removeEdge(AdjEdgeItr ae) { - --degree; adjEdges.erase(ae); } void setData(void *data) { this->data = data; } void* getData() { return data; } }; - class EdgeEntry : public llvm::ilist_node { - friend struct llvm::ilist_sentinel_traits; + class EdgeEntry { private: - NodeItr node1, node2; + NodeId node1, node2; Matrix costs; AdjEdgeItr node1AEItr, node2AEItr; void *data; - EdgeEntry() : costs(0, 0, 0) {} + EdgeEntry() : costs(0, 0, 0), data(0) {} public: - EdgeEntry(NodeItr node1, NodeItr node2, const Matrix &costs) + EdgeEntry(NodeId node1, NodeId node2, const Matrix &costs) : node1(node1), node2(node2), costs(costs) {} - NodeItr getNode1() const { return node1; } - NodeItr getNode2() const { return node2; } + NodeId getNode1() const { return node1; } + NodeId getNode2() const { return node2; } Matrix& getCosts() { return costs; } const Matrix& getCosts() const { return costs; } void setNode1AEItr(AdjEdgeItr ae) { node1AEItr = ae; } @@ -105,254 +89,305 @@ namespace PBQP { // ----- MEMBERS ----- - NodeList nodes; - unsigned numNodes; + typedef std::vector NodeVector; + typedef std::vector FreeNodeVector; + NodeVector nodes; + FreeNodeVector freeNodes; - EdgeList edges; - unsigned numEdges; + typedef std::vector EdgeVector; + typedef std::vector FreeEdgeVector; + EdgeVector edges; + FreeEdgeVector freeEdges; // ----- INTERNAL METHODS ----- - NodeEntry& getNode(NodeItr nItr) { return *nItr; } - const NodeEntry& getNode(ConstNodeItr nItr) const { return *nItr; } - - EdgeEntry& getEdge(EdgeItr eItr) { return *eItr; } - const EdgeEntry& getEdge(ConstEdgeItr eItr) const { return *eItr; } - - NodeItr addConstructedNode(const NodeEntry &n) { - ++numNodes; - return nodes.insert(nodes.end(), n); + NodeEntry& getNode(NodeId nId) { return nodes[nId]; } + const NodeEntry& getNode(NodeId nId) const { return nodes[nId]; } + + EdgeEntry& getEdge(EdgeId eId) { return edges[eId]; } + const EdgeEntry& getEdge(EdgeId eId) const { return edges[eId]; } + + NodeId addConstructedNode(const NodeEntry &n) { + NodeId nodeId = 0; + if (!freeNodes.empty()) { + nodeId = freeNodes.back(); + freeNodes.pop_back(); + nodes[nodeId] = n; + } else { + nodeId = nodes.size(); + nodes.push_back(n); + } + return nodeId; } - EdgeItr addConstructedEdge(const EdgeEntry &e) { - assert(findEdge(e.getNode1(), e.getNode2()) == edges.end() && + EdgeId addConstructedEdge(const EdgeEntry &e) { + assert(findEdge(e.getNode1(), e.getNode2()) == invalidEdgeId() && "Attempt to add duplicate edge."); - ++numEdges; - EdgeItr edgeItr = edges.insert(edges.end(), e); - EdgeEntry &ne = getEdge(edgeItr); + EdgeId edgeId = 0; + if (!freeEdges.empty()) { + edgeId = freeEdges.back(); + freeEdges.pop_back(); + edges[edgeId] = e; + } else { + edgeId = edges.size(); + edges.push_back(e); + } + + EdgeEntry &ne = getEdge(edgeId); NodeEntry &n1 = getNode(ne.getNode1()); NodeEntry &n2 = getNode(ne.getNode2()); + // Sanity check on matrix dimensions: assert((n1.getCosts().getLength() == ne.getCosts().getRows()) && (n2.getCosts().getLength() == ne.getCosts().getCols()) && "Edge cost dimensions do not match node costs dimensions."); - ne.setNode1AEItr(n1.addEdge(edgeItr)); - ne.setNode2AEItr(n2.addEdge(edgeItr)); - return edgeItr; + + ne.setNode1AEItr(n1.addEdge(edgeId)); + ne.setNode2AEItr(n2.addEdge(edgeId)); + return edgeId; } - inline void copyFrom(const Graph &other); + Graph(const Graph &other) {} + void operator=(const Graph &other) {} + public: - /// \brief Construct an empty PBQP graph. - Graph() : numNodes(0), numEdges(0) {} + class NodeItr { + public: + NodeItr(NodeId nodeId, const Graph &g) + : nodeId(nodeId), endNodeId(g.nodes.size()), freeNodes(g.freeNodes) { + this->nodeId = findNextInUse(nodeId); // Move to the first in-use nodeId + } - /// \brief Copy construct this graph from "other". Note: Does not copy node - /// and edge data, only graph structure and costs. - /// @param other Source graph to copy from. - Graph(const Graph &other) : numNodes(0), numEdges(0) { - copyFrom(other); - } + bool operator==(const NodeItr& n) const { return nodeId == n.nodeId; } + bool operator!=(const NodeItr& n) const { return !(*this == n); } + NodeItr& operator++() { nodeId = findNextInUse(++nodeId); return *this; } + NodeId operator*() const { return nodeId; } - /// \brief Make this graph a copy of "other". Note: Does not copy node and - /// edge data, only graph structure and costs. - /// @param other The graph to copy from. - /// @return A reference to this graph. - /// - /// This will clear the current graph, erasing any nodes and edges added, - /// before copying from other. - Graph& operator=(const Graph &other) { - clear(); - copyFrom(other); - return *this; - } + private: + NodeId findNextInUse(NodeId n) const { + while (n < endNodeId && + std::find(freeNodes.begin(), freeNodes.end(), n) != + freeNodes.end()) { + ++n; + } + return n; + } + + NodeId nodeId, endNodeId; + const FreeNodeVector& freeNodes; + }; + + class EdgeItr { + public: + EdgeItr(EdgeId edgeId, const Graph &g) + : edgeId(edgeId), endEdgeId(g.edges.size()), freeEdges(g.freeEdges) { + this->edgeId = findNextInUse(edgeId); // Move to the first in-use edgeId + } + + bool operator==(const EdgeItr& n) const { return edgeId == n.edgeId; } + bool operator!=(const EdgeItr& n) const { return !(*this == n); } + EdgeItr& operator++() { edgeId = findNextInUse(++edgeId); return *this; } + EdgeId operator*() const { return edgeId; } + + private: + EdgeId findNextInUse(EdgeId n) const { + while (n < endEdgeId && + std::find(freeEdges.begin(), freeEdges.end(), n) != + freeEdges.end()) { + ++n; + } + return n; + } + + EdgeId edgeId, endEdgeId; + const FreeEdgeVector& freeEdges; + }; + + /// \brief Construct an empty PBQP graph. + Graph() {} /// \brief Add a node with the given costs. /// @param costs Cost vector for the new node. /// @return Node iterator for the added node. - NodeItr addNode(const Vector &costs) { + NodeId addNode(const Vector &costs) { return addConstructedNode(NodeEntry(costs)); } /// \brief Add an edge between the given nodes with the given costs. - /// @param n1Itr First node. - /// @param n2Itr Second node. + /// @param n1Id First node. + /// @param n2Id Second node. /// @return Edge iterator for the added edge. - EdgeItr addEdge(Graph::NodeItr n1Itr, Graph::NodeItr n2Itr, - const Matrix &costs) { - assert(getNodeCosts(n1Itr).getLength() == costs.getRows() && - getNodeCosts(n2Itr).getLength() == costs.getCols() && + EdgeId addEdge(NodeId n1Id, NodeId n2Id, const Matrix &costs) { + assert(getNodeCosts(n1Id).getLength() == costs.getRows() && + getNodeCosts(n2Id).getLength() == costs.getCols() && "Matrix dimensions mismatch."); - return addConstructedEdge(EdgeEntry(n1Itr, n2Itr, costs)); + return addConstructedEdge(EdgeEntry(n1Id, n2Id, costs)); } /// \brief Get the number of nodes in the graph. /// @return Number of nodes in the graph. - unsigned getNumNodes() const { return numNodes; } + unsigned getNumNodes() const { return nodes.size() - freeNodes.size(); } /// \brief Get the number of edges in the graph. /// @return Number of edges in the graph. - unsigned getNumEdges() const { return numEdges; } + unsigned getNumEdges() const { return edges.size() - freeEdges.size(); } /// \brief Get a node's cost vector. - /// @param nItr Node iterator. + /// @param nId Node id. /// @return Node cost vector. - Vector& getNodeCosts(NodeItr nItr) { return getNode(nItr).getCosts(); } + Vector& getNodeCosts(NodeId nId) { return getNode(nId).getCosts(); } /// \brief Get a node's cost vector (const version). - /// @param nItr Node iterator. + /// @param nId Node id. /// @return Node cost vector. - const Vector& getNodeCosts(ConstNodeItr nItr) const { - return getNode(nItr).getCosts(); + const Vector& getNodeCosts(NodeId nId) const { + return getNode(nId).getCosts(); } /// \brief Set a node's data pointer. - /// @param nItr Node iterator. + /// @param nId Node id. /// @param data Pointer to node data. /// /// Typically used by a PBQP solver to attach data to aid in solution. - void setNodeData(NodeItr nItr, void *data) { getNode(nItr).setData(data); } + void setNodeData(NodeId nId, void *data) { getNode(nId).setData(data); } /// \brief Get the node's data pointer. - /// @param nItr Node iterator. + /// @param nId Node id. /// @return Pointer to node data. - void* getNodeData(NodeItr nItr) { return getNode(nItr).getData(); } - + void* getNodeData(NodeId nId) { return getNode(nId).getData(); } + /// \brief Get an edge's cost matrix. - /// @param eItr Edge iterator. + /// @param eId Edge id. /// @return Edge cost matrix. - Matrix& getEdgeCosts(EdgeItr eItr) { return getEdge(eItr).getCosts(); } + Matrix& getEdgeCosts(EdgeId eId) { return getEdge(eId).getCosts(); } /// \brief Get an edge's cost matrix (const version). - /// @param eItr Edge iterator. + /// @param eId Edge id. /// @return Edge cost matrix. - const Matrix& getEdgeCosts(ConstEdgeItr eItr) const { - return getEdge(eItr).getCosts(); + const Matrix& getEdgeCosts(EdgeId eId) const { + return getEdge(eId).getCosts(); } /// \brief Set an edge's data pointer. - /// @param eItr Edge iterator. + /// @param eId Edge id. /// @param data Pointer to edge data. /// /// Typically used by a PBQP solver to attach data to aid in solution. - void setEdgeData(EdgeItr eItr, void *data) { getEdge(eItr).setData(data); } + void setEdgeData(EdgeId eId, void *data) { getEdge(eId).setData(data); } /// \brief Get an edge's data pointer. - /// @param eItr Edge iterator. - /// @return Pointer to edge data. - void* getEdgeData(EdgeItr eItr) { return getEdge(eItr).getData(); } + /// @param eId Edge id. + /// @return Pointer to edge data. + void* getEdgeData(EdgeId eId) { return getEdge(eId).getData(); } /// \brief Get a node's degree. - /// @param nItr Node iterator. + /// @param nId Node id. /// @return The degree of the node. - unsigned getNodeDegree(NodeItr nItr) const { - return getNode(nItr).getDegree(); + unsigned getNodeDegree(NodeId nId) const { + return getNode(nId).getDegree(); } /// \brief Begin iterator for node set. - NodeItr nodesBegin() { return nodes.begin(); } - - /// \brief Begin const iterator for node set. - ConstNodeItr nodesBegin() const { return nodes.begin(); } + NodeItr nodesBegin() const { return NodeItr(0, *this); } /// \brief End iterator for node set. - NodeItr nodesEnd() { return nodes.end(); } - - /// \brief End const iterator for node set. - ConstNodeItr nodesEnd() const { return nodes.end(); } + NodeItr nodesEnd() const { return NodeItr(nodes.size(), *this); } /// \brief Begin iterator for edge set. - EdgeItr edgesBegin() { return edges.begin(); } + EdgeItr edgesBegin() const { return EdgeItr(0, *this); } /// \brief End iterator for edge set. - EdgeItr edgesEnd() { return edges.end(); } + EdgeItr edgesEnd() const { return EdgeItr(edges.size(), *this); } /// \brief Get begin iterator for adjacent edge set. - /// @param nItr Node iterator. + /// @param nId Node id. /// @return Begin iterator for the set of edges connected to the given node. - AdjEdgeItr adjEdgesBegin(NodeItr nItr) { - return getNode(nItr).edgesBegin(); + AdjEdgeItr adjEdgesBegin(NodeId nId) { + return getNode(nId).edgesBegin(); } /// \brief Get end iterator for adjacent edge set. - /// @param nItr Node iterator. + /// @param nId Node id. /// @return End iterator for the set of edges connected to the given node. - AdjEdgeItr adjEdgesEnd(NodeItr nItr) { - return getNode(nItr).edgesEnd(); + AdjEdgeItr adjEdgesEnd(NodeId nId) { + return getNode(nId).edgesEnd(); } /// \brief Get the first node connected to this edge. - /// @param eItr Edge iterator. - /// @return The first node connected to the given edge. - NodeItr getEdgeNode1(EdgeItr eItr) { - return getEdge(eItr).getNode1(); + /// @param eId Edge id. + /// @return The first node connected to the given edge. + NodeId getEdgeNode1(EdgeId eId) { + return getEdge(eId).getNode1(); } /// \brief Get the second node connected to this edge. - /// @param eItr Edge iterator. - /// @return The second node connected to the given edge. - NodeItr getEdgeNode2(EdgeItr eItr) { - return getEdge(eItr).getNode2(); - } + /// @param eId Edge id. + /// @return The second node connected to the given edge. + NodeId getEdgeNode2(EdgeId eId) { + return getEdge(eId).getNode2(); + } /// \brief Get the "other" node connected to this edge. - /// @param eItr Edge iterator. - /// @param nItr Node iterator for the "given" node. - /// @return The iterator for the "other" node connected to this edge. - NodeItr getEdgeOtherNode(EdgeItr eItr, NodeItr nItr) { - EdgeEntry &e = getEdge(eItr); - if (e.getNode1() == nItr) { + /// @param eId Edge id. + /// @param nId Node id for the "given" node. + /// @return The iterator for the "other" node connected to this edge. + NodeId getEdgeOtherNode(EdgeId eId, NodeId nId) { + EdgeEntry &e = getEdge(eId); + if (e.getNode1() == nId) { return e.getNode2(); } // else return e.getNode1(); } + EdgeId invalidEdgeId() const { + return std::numeric_limits::max(); + } + /// \brief Get the edge connecting two nodes. - /// @param n1Itr First node iterator. - /// @param n2Itr Second node iterator. - /// @return An iterator for edge (n1Itr, n2Itr) if such an edge exists, - /// otherwise returns edgesEnd(). - EdgeItr findEdge(NodeItr n1Itr, NodeItr n2Itr) { - for (AdjEdgeItr aeItr = adjEdgesBegin(n1Itr), aeEnd = adjEdgesEnd(n1Itr); + /// @param n1Id First node id. + /// @param n2Id Second node id. + /// @return An id for edge (n1Id, n2Id) if such an edge exists, + /// otherwise returns an invalid edge id. + EdgeId findEdge(NodeId n1Id, NodeId n2Id) { + for (AdjEdgeItr aeItr = adjEdgesBegin(n1Id), aeEnd = adjEdgesEnd(n1Id); aeItr != aeEnd; ++aeItr) { - if ((getEdgeNode1(*aeItr) == n2Itr) || - (getEdgeNode2(*aeItr) == n2Itr)) { + if ((getEdgeNode1(*aeItr) == n2Id) || + (getEdgeNode2(*aeItr) == n2Id)) { return *aeItr; } } - return edges.end(); + return invalidEdgeId(); } /// \brief Remove a node from the graph. - /// @param nItr Node iterator. - void removeNode(NodeItr nItr) { - NodeEntry &n = getNode(nItr); - for (AdjEdgeItr itr = n.edgesBegin(), end = n.edgesEnd(); itr != end;) { - EdgeItr eItr = *itr; - ++itr; - removeEdge(eItr); + /// @param nId Node id. + void removeNode(NodeId nId) { + NodeEntry &n = getNode(nId); + for (AdjEdgeItr itr = n.edgesBegin(), end = n.edgesEnd(); itr != end; ++itr) { + EdgeId eId = *itr; + removeEdge(eId); } - nodes.erase(nItr); - --numNodes; + freeNodes.push_back(nId); } /// \brief Remove an edge from the graph. - /// @param eItr Edge iterator. - void removeEdge(EdgeItr eItr) { - EdgeEntry &e = getEdge(eItr); + /// @param eId Edge id. + void removeEdge(EdgeId eId) { + EdgeEntry &e = getEdge(eId); NodeEntry &n1 = getNode(e.getNode1()); NodeEntry &n2 = getNode(e.getNode2()); n1.removeEdge(e.getNode1AEItr()); n2.removeEdge(e.getNode2AEItr()); - edges.erase(eItr); - --numEdges; + freeEdges.push_back(eId); } /// \brief Remove all nodes and edges from the graph. void clear() { nodes.clear(); + freeNodes.clear(); edges.clear(); - numNodes = numEdges = 0; + freeEdges.clear(); } /// \brief Dump a graph to an output stream. @@ -362,7 +397,7 @@ namespace PBQP { for (NodeItr nodeItr = nodesBegin(), nodeEnd = nodesEnd(); nodeItr != nodeEnd; ++nodeItr) { - const Vector& v = getNodeCosts(nodeItr); + const Vector& v = getNodeCosts(*nodeItr); os << "\n" << v.getLength() << "\n"; assert(v.getLength() != 0 && "Empty vector in graph."); os << v[0]; @@ -374,10 +409,10 @@ namespace PBQP { for (EdgeItr edgeItr = edgesBegin(), edgeEnd = edgesEnd(); edgeItr != edgeEnd; ++edgeItr) { - unsigned n1 = std::distance(nodesBegin(), getEdgeNode1(edgeItr)); - unsigned n2 = std::distance(nodesBegin(), getEdgeNode2(edgeItr)); + NodeId n1 = getEdgeNode1(*edgeItr); + NodeId n2 = getEdgeNode2(*edgeItr); assert(n1 != n2 && "PBQP graphs shound not have self-edges."); - const Matrix& m = getEdgeCosts(edgeItr); + const Matrix& m = getEdgeCosts(*edgeItr); os << "\n" << n1 << " " << n2 << "\n" << m.getRows() << " " << m.getCols() << "\n"; assert(m.getRows() != 0 && "No rows in matrix."); @@ -396,14 +431,14 @@ namespace PBQP { /// @param os Output stream to print on. template void printDot(OStream &os) { - + os << "graph {\n"; for (NodeItr nodeItr = nodesBegin(), nodeEnd = nodesEnd(); nodeItr != nodeEnd; ++nodeItr) { os << " node" << nodeItr << " [ label=\"" - << nodeItr << ": " << getNodeCosts(nodeItr) << "\" ]\n"; + << nodeItr << ": " << getNodeCosts(*nodeItr) << "\" ]\n"; } os << " edge [ len=" << getNumNodes() << " ]\n"; @@ -411,11 +446,11 @@ namespace PBQP { for (EdgeItr edgeItr = edgesBegin(), edgeEnd = edgesEnd(); edgeItr != edgeEnd; ++edgeItr) { - os << " node" << getEdgeNode1(edgeItr) - << " -- node" << getEdgeNode2(edgeItr) + os << " node" << getEdgeNode1(*edgeItr) + << " -- node" << getEdgeNode2(*edgeItr) << " [ label=\""; - const Matrix &edgeCosts = getEdgeCosts(edgeItr); + const Matrix &edgeCosts = getEdgeCosts(*edgeItr); for (unsigned i = 0; i < edgeCosts.getRows(); ++i) { os << edgeCosts.getRowAsVector(i) << "\\n"; @@ -427,39 +462,16 @@ namespace PBQP { }; - class NodeItrComparator { - public: - bool operator()(Graph::NodeItr n1, Graph::NodeItr n2) const { - return &*n1 < &*n2; - } - - bool operator()(Graph::ConstNodeItr n1, Graph::ConstNodeItr n2) const { - return &*n1 < &*n2; - } - }; - - class EdgeItrCompartor { - public: - bool operator()(Graph::EdgeItr e1, Graph::EdgeItr e2) const { - return &*e1 < &*e2; - } - - bool operator()(Graph::ConstEdgeItr e1, Graph::ConstEdgeItr e2) const { - return &*e1 < &*e2; - } - }; - - void Graph::copyFrom(const Graph &other) { - std::map nodeMap; +// void Graph::copyFrom(const Graph &other) { +// std::map nodeMap; - for (Graph::ConstNodeItr nItr = other.nodesBegin(), - nEnd = other.nodesEnd(); - nItr != nEnd; ++nItr) { - nodeMap[nItr] = addNode(other.getNodeCosts(nItr)); - } - - } +// for (Graph::ConstNodeItr nItr = other.nodesBegin(), +// nEnd = other.nodesEnd(); +// nItr != nEnd; ++nItr) { +// nodeMap[nItr] = addNode(other.getNodeCosts(nItr)); +// } +// } } diff --git a/contrib/llvm/include/llvm/CodeGen/PBQP/HeuristicBase.h b/contrib/llvm/include/llvm/CodeGen/PBQP/HeuristicBase.h index 0c1fcb7ea..8bcbb9ed1 100644 --- a/contrib/llvm/include/llvm/CodeGen/PBQP/HeuristicBase.h +++ b/contrib/llvm/include/llvm/CodeGen/PBQP/HeuristicBase.h @@ -27,7 +27,7 @@ namespace PBQP { ///
  • void heuristicReduce() : Perform a single heuristic reduction. ///
  • void preUpdateEdgeCosts(Graph::EdgeItr) : Handle the (imminent) /// change to the cost matrix on the given edge (by R2). - ///
  • void postUpdateEdgeCostts(Graph::EdgeItr) : Handle the new + ///
  • void postUpdateEdgeCostts(Graph::EdgeItr) : Handle the new /// costs on the given edge. ///
  • void handleAddEdge(Graph::EdgeItr) : Handle the addition of a new /// edge into the PBQP graph (by R2). @@ -39,7 +39,7 @@ namespace PBQP { /// /// These methods are implemented in this class for documentation purposes, /// but will assert if called. - /// + /// /// Note that this class uses the curiously recursive template idiom to /// forward calls to the derived class. These methods need not be made /// virtual, and indeed probably shouldn't for performance reasons. @@ -52,7 +52,7 @@ namespace PBQP { class HeuristicBase { private: - typedef std::list OptimalList; + typedef std::list OptimalList; HeuristicSolverImpl &s; Graph &g; @@ -62,9 +62,9 @@ namespace PBQP { HImpl& impl() { return static_cast(*this); } // Add the given node to the optimal reductions list. Keep an iterator to - // its location for fast removal. - void addToOptimalReductionList(Graph::NodeItr nItr) { - optimalList.insert(optimalList.end(), nItr); + // its location for fast removal. + void addToOptimalReductionList(Graph::NodeId nId) { + optimalList.insert(optimalList.end(), nId); } public: @@ -94,7 +94,7 @@ namespace PBQP { /// behaviour. bool solverRunSimplify() const { return true; } - /// \brief Decide whether a node should be optimally or heuristically + /// \brief Decide whether a node should be optimally or heuristically /// reduced. /// @return Whether or not the given node should be listed for optimal /// reduction (via R0, R1 or R2). @@ -105,21 +105,21 @@ namespace PBQP { /// criteria. Note however that your criteria for selecting optimal nodes /// should be at least as strong as this. I.e. Nodes of degree 3 or /// higher should not be selected under any circumstances. - bool shouldOptimallyReduce(Graph::NodeItr nItr) { - if (g.getNodeDegree(nItr) < 3) + bool shouldOptimallyReduce(Graph::NodeId nId) { + if (g.getNodeDegree(nId) < 3) return true; // else return false; } /// \brief Add the given node to the list of nodes to be optimally reduced. - /// @param nItr Node iterator to be added. + /// @param nId Node id to be added. /// /// You probably don't want to over-ride this, except perhaps to record /// statistics before calling this implementation. HeuristicBase relies on /// its behaviour. - void addToOptimalReduceList(Graph::NodeItr nItr) { - optimalList.push_back(nItr); + void addToOptimalReduceList(Graph::NodeId nId) { + optimalList.push_back(nId); } /// \brief Initialise the heuristic. @@ -132,10 +132,10 @@ namespace PBQP { void setup() { for (Graph::NodeItr nItr = g.nodesBegin(), nEnd = g.nodesEnd(); nItr != nEnd; ++nItr) { - if (impl().shouldOptimallyReduce(nItr)) { - addToOptimalReduceList(nItr); + if (impl().shouldOptimallyReduce(*nItr)) { + addToOptimalReduceList(*nItr); } else { - impl().addToHeuristicReduceList(nItr); + impl().addToHeuristicReduceList(*nItr); } } } @@ -150,13 +150,13 @@ namespace PBQP { if (optimalList.empty()) return false; - Graph::NodeItr nItr = optimalList.front(); + Graph::NodeId nId = optimalList.front(); optimalList.pop_front(); - switch (s.getSolverDegree(nItr)) { - case 0: s.applyR0(nItr); break; - case 1: s.applyR1(nItr); break; - case 2: s.applyR2(nItr); break; + switch (s.getSolverDegree(nId)) { + case 0: s.applyR0(nId); break; + case 1: s.applyR1(nId); break; + case 2: s.applyR2(nId); break; default: llvm_unreachable( "Optimal reductions of degree > 2 nodes is invalid."); } @@ -184,8 +184,8 @@ namespace PBQP { } /// \brief Add a node to the heuristic reduce list. - /// @param nItr Node iterator to add to the heuristic reduce list. - void addToHeuristicList(Graph::NodeItr nItr) { + /// @param nId Node id to add to the heuristic reduce list. + void addToHeuristicList(Graph::NodeId nId) { llvm_unreachable("Must be implemented in derived class."); } @@ -199,31 +199,31 @@ namespace PBQP { } /// \brief Prepare a change in the costs on the given edge. - /// @param eItr Edge iterator. - void preUpdateEdgeCosts(Graph::EdgeItr eItr) { + /// @param eId Edge id. + void preUpdateEdgeCosts(Graph::EdgeId eId) { llvm_unreachable("Must be implemented in derived class."); } /// \brief Handle the change in the costs on the given edge. - /// @param eItr Edge iterator. - void postUpdateEdgeCostts(Graph::EdgeItr eItr) { + /// @param eId Edge id. + void postUpdateEdgeCostts(Graph::EdgeId eId) { llvm_unreachable("Must be implemented in derived class."); } /// \brief Handle the addition of a new edge into the PBQP graph. - /// @param eItr Edge iterator for the added edge. - void handleAddEdge(Graph::EdgeItr eItr) { + /// @param eId Edge id for the added edge. + void handleAddEdge(Graph::EdgeId eId) { llvm_unreachable("Must be implemented in derived class."); } /// \brief Handle disconnection of an edge from a node. - /// @param eItr Edge iterator for edge being disconnected. - /// @param nItr Node iterator for the node being disconnected from. + /// @param eId Edge id for edge being disconnected. + /// @param nId Node id for the node being disconnected from. /// /// Edges are frequently removed due to the removal of a node. This /// method allows for the effect to be computed only for the remaining /// node in the graph. - void handleRemoveEdge(Graph::EdgeItr eItr, Graph::NodeItr nItr) { + void handleRemoveEdge(Graph::EdgeId eId, Graph::NodeId nId) { llvm_unreachable("Must be implemented in derived class."); } diff --git a/contrib/llvm/include/llvm/CodeGen/PBQP/HeuristicSolver.h b/contrib/llvm/include/llvm/CodeGen/PBQP/HeuristicSolver.h index 47e15b27e..e26ca02ff 100644 --- a/contrib/llvm/include/llvm/CodeGen/PBQP/HeuristicSolver.h +++ b/contrib/llvm/include/llvm/CodeGen/PBQP/HeuristicSolver.h @@ -9,7 +9,7 @@ // // Heuristic PBQP solver. This solver is able to perform optimal reductions for // nodes of degree 0, 1 or 2. For nodes of degree >2 a plugable heuristic is -// used to select a node for reduction. +// used to select a node for reduction. // //===----------------------------------------------------------------------===// @@ -40,10 +40,10 @@ namespace PBQP { typedef typename HImpl::NodeData HeuristicNodeData; typedef typename HImpl::EdgeData HeuristicEdgeData; - typedef std::list SolverEdges; + typedef std::list SolverEdges; public: - + /// \brief Iterator type for edges in the solver graph. typedef SolverEdges::iterator SolverEdgeItr; @@ -55,9 +55,9 @@ namespace PBQP { HeuristicNodeData& getHeuristicData() { return hData; } - SolverEdgeItr addSolverEdge(Graph::EdgeItr eItr) { + SolverEdgeItr addSolverEdge(Graph::EdgeId eId) { ++solverDegree; - return solverEdges.insert(solverEdges.end(), eItr); + return solverEdges.insert(solverEdges.end(), eId); } void removeSolverEdge(SolverEdgeItr seItr) { @@ -70,15 +70,15 @@ namespace PBQP { unsigned getSolverDegree() const { return solverDegree; } void clearSolverEdges() { solverDegree = 0; - solverEdges.clear(); + solverEdges.clear(); } - + private: HeuristicNodeData hData; unsigned solverDegree; SolverEdges solverEdges; }; - + class EdgeData { public: HeuristicEdgeData& getHeuristicData() { return hData; } @@ -104,7 +104,7 @@ namespace PBQP { Graph &g; HImpl h; Solution s; - std::vector stack; + std::vector stack; typedef std::list NodeDataList; NodeDataList nodeDataList; @@ -117,7 +117,7 @@ namespace PBQP { /// \brief Construct a heuristic solver implementation to solve the given /// graph. /// @param g The graph representing the problem instance to be solved. - HeuristicSolverImpl(Graph &g) : g(g), h(*this) {} + HeuristicSolverImpl(Graph &g) : g(g), h(*this) {} /// \brief Get the graph being solved by this solver. /// @return The graph representing the problem instance being solved by this @@ -125,46 +125,46 @@ namespace PBQP { Graph& getGraph() { return g; } /// \brief Get the heuristic data attached to the given node. - /// @param nItr Node iterator. + /// @param nId Node id. /// @return The heuristic data attached to the given node. - HeuristicNodeData& getHeuristicNodeData(Graph::NodeItr nItr) { - return getSolverNodeData(nItr).getHeuristicData(); + HeuristicNodeData& getHeuristicNodeData(Graph::NodeId nId) { + return getSolverNodeData(nId).getHeuristicData(); } /// \brief Get the heuristic data attached to the given edge. - /// @param eItr Edge iterator. + /// @param eId Edge id. /// @return The heuristic data attached to the given node. - HeuristicEdgeData& getHeuristicEdgeData(Graph::EdgeItr eItr) { - return getSolverEdgeData(eItr).getHeuristicData(); + HeuristicEdgeData& getHeuristicEdgeData(Graph::EdgeId eId) { + return getSolverEdgeData(eId).getHeuristicData(); } /// \brief Begin iterator for the set of edges adjacent to the given node in /// the solver graph. - /// @param nItr Node iterator. + /// @param nId Node id. /// @return Begin iterator for the set of edges adjacent to the given node - /// in the solver graph. - SolverEdgeItr solverEdgesBegin(Graph::NodeItr nItr) { - return getSolverNodeData(nItr).solverEdgesBegin(); + /// in the solver graph. + SolverEdgeItr solverEdgesBegin(Graph::NodeId nId) { + return getSolverNodeData(nId).solverEdgesBegin(); } /// \brief End iterator for the set of edges adjacent to the given node in /// the solver graph. - /// @param nItr Node iterator. + /// @param nId Node id. /// @return End iterator for the set of edges adjacent to the given node in - /// the solver graph. - SolverEdgeItr solverEdgesEnd(Graph::NodeItr nItr) { - return getSolverNodeData(nItr).solverEdgesEnd(); + /// the solver graph. + SolverEdgeItr solverEdgesEnd(Graph::NodeId nId) { + return getSolverNodeData(nId).solverEdgesEnd(); } /// \brief Remove a node from the solver graph. - /// @param eItr Edge iterator for edge to be removed. + /// @param eId Edge id for edge to be removed. /// /// Does not notify the heuristic of the removal. That should be /// done manually if necessary. - void removeSolverEdge(Graph::EdgeItr eItr) { - EdgeData &eData = getSolverEdgeData(eItr); - NodeData &n1Data = getSolverNodeData(g.getEdgeNode1(eItr)), - &n2Data = getSolverNodeData(g.getEdgeNode2(eItr)); + void removeSolverEdge(Graph::EdgeId eId) { + EdgeData &eData = getSolverEdgeData(eId); + NodeData &n1Data = getSolverNodeData(g.getEdgeNode1(eId)), + &n2Data = getSolverNodeData(g.getEdgeNode2(eId)); n1Data.removeSolverEdge(eData.getN1SolverEdgeItr()); n2Data.removeSolverEdge(eData.getN2SolverEdgeItr()); @@ -188,66 +188,66 @@ namespace PBQP { } /// \brief Add to the end of the stack. - /// @param nItr Node iterator to add to the reduction stack. - void pushToStack(Graph::NodeItr nItr) { - getSolverNodeData(nItr).clearSolverEdges(); - stack.push_back(nItr); + /// @param nId Node id to add to the reduction stack. + void pushToStack(Graph::NodeId nId) { + getSolverNodeData(nId).clearSolverEdges(); + stack.push_back(nId); } /// \brief Returns the solver degree of the given node. - /// @param nItr Node iterator for which degree is requested. + /// @param nId Node id for which degree is requested. /// @return Node degree in the solver graph (not the original graph). - unsigned getSolverDegree(Graph::NodeItr nItr) { - return getSolverNodeData(nItr).getSolverDegree(); + unsigned getSolverDegree(Graph::NodeId nId) { + return getSolverNodeData(nId).getSolverDegree(); } /// \brief Set the solution of the given node. - /// @param nItr Node iterator to set solution for. + /// @param nId Node id to set solution for. /// @param selection Selection for node. - void setSolution(const Graph::NodeItr &nItr, unsigned selection) { - s.setSelection(nItr, selection); + void setSolution(const Graph::NodeId &nId, unsigned selection) { + s.setSelection(nId, selection); - for (Graph::AdjEdgeItr aeItr = g.adjEdgesBegin(nItr), - aeEnd = g.adjEdgesEnd(nItr); + for (Graph::AdjEdgeItr aeItr = g.adjEdgesBegin(nId), + aeEnd = g.adjEdgesEnd(nId); aeItr != aeEnd; ++aeItr) { - Graph::EdgeItr eItr(*aeItr); - Graph::NodeItr anItr(g.getEdgeOtherNode(eItr, nItr)); - getSolverNodeData(anItr).addSolverEdge(eItr); + Graph::EdgeId eId(*aeItr); + Graph::NodeId anId(g.getEdgeOtherNode(eId, nId)); + getSolverNodeData(anId).addSolverEdge(eId); } } /// \brief Apply rule R0. - /// @param nItr Node iterator for node to apply R0 to. + /// @param nId Node id for node to apply R0 to. /// /// Node will be automatically pushed to the solver stack. - void applyR0(Graph::NodeItr nItr) { - assert(getSolverNodeData(nItr).getSolverDegree() == 0 && + void applyR0(Graph::NodeId nId) { + assert(getSolverNodeData(nId).getSolverDegree() == 0 && "R0 applied to node with degree != 0."); // Nothing to do. Just push the node onto the reduction stack. - pushToStack(nItr); + pushToStack(nId); s.recordR0(); } /// \brief Apply rule R1. - /// @param xnItr Node iterator for node to apply R1 to. + /// @param xnId Node id for node to apply R1 to. /// /// Node will be automatically pushed to the solver stack. - void applyR1(Graph::NodeItr xnItr) { - NodeData &nd = getSolverNodeData(xnItr); + void applyR1(Graph::NodeId xnId) { + NodeData &nd = getSolverNodeData(xnId); assert(nd.getSolverDegree() == 1 && "R1 applied to node with degree != 1."); - Graph::EdgeItr eItr = *nd.solverEdgesBegin(); + Graph::EdgeId eId = *nd.solverEdgesBegin(); + + const Matrix &eCosts = g.getEdgeCosts(eId); + const Vector &xCosts = g.getNodeCosts(xnId); - const Matrix &eCosts = g.getEdgeCosts(eItr); - const Vector &xCosts = g.getNodeCosts(xnItr); - // Duplicate a little to avoid transposing matrices. - if (xnItr == g.getEdgeNode1(eItr)) { - Graph::NodeItr ynItr = g.getEdgeNode2(eItr); - Vector &yCosts = g.getNodeCosts(ynItr); + if (xnId == g.getEdgeNode1(eId)) { + Graph::NodeId ynId = g.getEdgeNode2(eId); + Vector &yCosts = g.getNodeCosts(ynId); for (unsigned j = 0; j < yCosts.getLength(); ++j) { PBQPNum min = eCosts[0][j] + xCosts[0]; for (unsigned i = 1; i < xCosts.getLength(); ++i) { @@ -257,10 +257,10 @@ namespace PBQP { } yCosts[j] += min; } - h.handleRemoveEdge(eItr, ynItr); + h.handleRemoveEdge(eId, ynId); } else { - Graph::NodeItr ynItr = g.getEdgeNode1(eItr); - Vector &yCosts = g.getNodeCosts(ynItr); + Graph::NodeId ynId = g.getEdgeNode1(eId); + Vector &yCosts = g.getNodeCosts(ynId); for (unsigned i = 0; i < yCosts.getLength(); ++i) { PBQPNum min = eCosts[i][0] + xCosts[0]; for (unsigned j = 1; j < xCosts.getLength(); ++j) { @@ -270,48 +270,48 @@ namespace PBQP { } yCosts[i] += min; } - h.handleRemoveEdge(eItr, ynItr); + h.handleRemoveEdge(eId, ynId); } - removeSolverEdge(eItr); + removeSolverEdge(eId); assert(nd.getSolverDegree() == 0 && "Degree 1 with edge removed should be 0."); - pushToStack(xnItr); + pushToStack(xnId); s.recordR1(); } /// \brief Apply rule R2. - /// @param xnItr Node iterator for node to apply R2 to. + /// @param xnId Node id for node to apply R2 to. /// /// Node will be automatically pushed to the solver stack. - void applyR2(Graph::NodeItr xnItr) { - assert(getSolverNodeData(xnItr).getSolverDegree() == 2 && + void applyR2(Graph::NodeId xnId) { + assert(getSolverNodeData(xnId).getSolverDegree() == 2 && "R2 applied to node with degree != 2."); - NodeData &nd = getSolverNodeData(xnItr); - const Vector &xCosts = g.getNodeCosts(xnItr); + NodeData &nd = getSolverNodeData(xnId); + const Vector &xCosts = g.getNodeCosts(xnId); SolverEdgeItr aeItr = nd.solverEdgesBegin(); - Graph::EdgeItr yxeItr = *aeItr, - zxeItr = *(++aeItr); + Graph::EdgeId yxeId = *aeItr, + zxeId = *(++aeItr); - Graph::NodeItr ynItr = g.getEdgeOtherNode(yxeItr, xnItr), - znItr = g.getEdgeOtherNode(zxeItr, xnItr); + Graph::NodeId ynId = g.getEdgeOtherNode(yxeId, xnId), + znId = g.getEdgeOtherNode(zxeId, xnId); - bool flipEdge1 = (g.getEdgeNode1(yxeItr) == xnItr), - flipEdge2 = (g.getEdgeNode1(zxeItr) == xnItr); + bool flipEdge1 = (g.getEdgeNode1(yxeId) == xnId), + flipEdge2 = (g.getEdgeNode1(zxeId) == xnId); const Matrix *yxeCosts = flipEdge1 ? - new Matrix(g.getEdgeCosts(yxeItr).transpose()) : - &g.getEdgeCosts(yxeItr); + new Matrix(g.getEdgeCosts(yxeId).transpose()) : + &g.getEdgeCosts(yxeId); const Matrix *zxeCosts = flipEdge2 ? - new Matrix(g.getEdgeCosts(zxeItr).transpose()) : - &g.getEdgeCosts(zxeItr); + new Matrix(g.getEdgeCosts(zxeId).transpose()) : + &g.getEdgeCosts(zxeId); unsigned xLen = xCosts.getLength(), yLen = yxeCosts->getRows(), zLen = zxeCosts->getRows(); - + Matrix delta(yLen, zLen); for (unsigned i = 0; i < yLen; ++i) { @@ -333,79 +333,79 @@ namespace PBQP { if (flipEdge2) delete zxeCosts; - Graph::EdgeItr yzeItr = g.findEdge(ynItr, znItr); + Graph::EdgeId yzeId = g.findEdge(ynId, znId); bool addedEdge = false; - if (yzeItr == g.edgesEnd()) { - yzeItr = g.addEdge(ynItr, znItr, delta); + if (yzeId == g.invalidEdgeId()) { + yzeId = g.addEdge(ynId, znId, delta); addedEdge = true; } else { - Matrix &yzeCosts = g.getEdgeCosts(yzeItr); - h.preUpdateEdgeCosts(yzeItr); - if (ynItr == g.getEdgeNode1(yzeItr)) { + Matrix &yzeCosts = g.getEdgeCosts(yzeId); + h.preUpdateEdgeCosts(yzeId); + if (ynId == g.getEdgeNode1(yzeId)) { yzeCosts += delta; } else { yzeCosts += delta.transpose(); } } - bool nullCostEdge = tryNormaliseEdgeMatrix(yzeItr); + bool nullCostEdge = tryNormaliseEdgeMatrix(yzeId); if (!addedEdge) { // If we modified the edge costs let the heuristic know. - h.postUpdateEdgeCosts(yzeItr); + h.postUpdateEdgeCosts(yzeId); } - + if (nullCostEdge) { // If this edge ended up null remove it. if (!addedEdge) { // We didn't just add it, so we need to notify the heuristic // and remove it from the solver. - h.handleRemoveEdge(yzeItr, ynItr); - h.handleRemoveEdge(yzeItr, znItr); - removeSolverEdge(yzeItr); + h.handleRemoveEdge(yzeId, ynId); + h.handleRemoveEdge(yzeId, znId); + removeSolverEdge(yzeId); } - g.removeEdge(yzeItr); + g.removeEdge(yzeId); } else if (addedEdge) { // If the edge was added, and non-null, finish setting it up, add it to // the solver & notify heuristic. edgeDataList.push_back(EdgeData()); - g.setEdgeData(yzeItr, &edgeDataList.back()); - addSolverEdge(yzeItr); - h.handleAddEdge(yzeItr); + g.setEdgeData(yzeId, &edgeDataList.back()); + addSolverEdge(yzeId); + h.handleAddEdge(yzeId); } - h.handleRemoveEdge(yxeItr, ynItr); - removeSolverEdge(yxeItr); - h.handleRemoveEdge(zxeItr, znItr); - removeSolverEdge(zxeItr); + h.handleRemoveEdge(yxeId, ynId); + removeSolverEdge(yxeId); + h.handleRemoveEdge(zxeId, znId); + removeSolverEdge(zxeId); - pushToStack(xnItr); + pushToStack(xnId); s.recordR2(); } /// \brief Record an application of the RN rule. /// /// For use by the HeuristicBase. - void recordRN() { s.recordRN(); } + void recordRN() { s.recordRN(); } private: - NodeData& getSolverNodeData(Graph::NodeItr nItr) { - return *static_cast(g.getNodeData(nItr)); + NodeData& getSolverNodeData(Graph::NodeId nId) { + return *static_cast(g.getNodeData(nId)); } - EdgeData& getSolverEdgeData(Graph::EdgeItr eItr) { - return *static_cast(g.getEdgeData(eItr)); + EdgeData& getSolverEdgeData(Graph::EdgeId eId) { + return *static_cast(g.getEdgeData(eId)); } - void addSolverEdge(Graph::EdgeItr eItr) { - EdgeData &eData = getSolverEdgeData(eItr); - NodeData &n1Data = getSolverNodeData(g.getEdgeNode1(eItr)), - &n2Data = getSolverNodeData(g.getEdgeNode2(eItr)); + void addSolverEdge(Graph::EdgeId eId) { + EdgeData &eData = getSolverEdgeData(eId); + NodeData &n1Data = getSolverNodeData(g.getEdgeNode1(eId)), + &n2Data = getSolverNodeData(g.getEdgeNode2(eId)); - eData.setN1SolverEdgeItr(n1Data.addSolverEdge(eItr)); - eData.setN2SolverEdgeItr(n2Data.addSolverEdge(eItr)); + eData.setN1SolverEdgeItr(n1Data.addSolverEdge(eId)); + eData.setN2SolverEdgeItr(n2Data.addSolverEdge(eId)); } void setup() { @@ -417,15 +417,15 @@ namespace PBQP { for (Graph::NodeItr nItr = g.nodesBegin(), nEnd = g.nodesEnd(); nItr != nEnd; ++nItr) { nodeDataList.push_back(NodeData()); - g.setNodeData(nItr, &nodeDataList.back()); + g.setNodeData(*nItr, &nodeDataList.back()); } // Create edge data objects. for (Graph::EdgeItr eItr = g.edgesBegin(), eEnd = g.edgesEnd(); eItr != eEnd; ++eItr) { edgeDataList.push_back(EdgeData()); - g.setEdgeData(eItr, &edgeDataList.back()); - addSolverEdge(eItr); + g.setEdgeData(*eItr, &edgeDataList.back()); + addSolverEdge(*eItr); } } @@ -441,28 +441,30 @@ namespace PBQP { for (Graph::NodeItr nItr = g.nodesBegin(), nEnd = g.nodesEnd(); nItr != nEnd; ++nItr) { - if (g.getNodeCosts(nItr).getLength() == 1) { + Graph::NodeId nId = *nItr; + + if (g.getNodeCosts(nId).getLength() == 1) { - std::vector edgesToRemove; + std::vector edgesToRemove; - for (Graph::AdjEdgeItr aeItr = g.adjEdgesBegin(nItr), - aeEnd = g.adjEdgesEnd(nItr); + for (Graph::AdjEdgeItr aeItr = g.adjEdgesBegin(nId), + aeEnd = g.adjEdgesEnd(nId); aeItr != aeEnd; ++aeItr) { - Graph::EdgeItr eItr = *aeItr; + Graph::EdgeId eId = *aeItr; - if (g.getEdgeNode1(eItr) == nItr) { - Graph::NodeItr otherNodeItr = g.getEdgeNode2(eItr); - g.getNodeCosts(otherNodeItr) += - g.getEdgeCosts(eItr).getRowAsVector(0); + if (g.getEdgeNode1(eId) == nId) { + Graph::NodeId otherNodeId = g.getEdgeNode2(eId); + g.getNodeCosts(otherNodeId) += + g.getEdgeCosts(eId).getRowAsVector(0); } else { - Graph::NodeItr otherNodeItr = g.getEdgeNode1(eItr); - g.getNodeCosts(otherNodeItr) += - g.getEdgeCosts(eItr).getColAsVector(0); + Graph::NodeId otherNodeId = g.getEdgeNode1(eId); + g.getNodeCosts(otherNodeId) += + g.getEdgeCosts(eId).getColAsVector(0); } - edgesToRemove.push_back(eItr); + edgesToRemove.push_back(eId); } if (!edgesToRemove.empty()) @@ -477,12 +479,12 @@ namespace PBQP { } void eliminateIndependentEdges() { - std::vector edgesToProcess; + std::vector edgesToProcess; unsigned numEliminated = 0; for (Graph::EdgeItr eItr = g.edgesBegin(), eEnd = g.edgesEnd(); eItr != eEnd; ++eItr) { - edgesToProcess.push_back(eItr); + edgesToProcess.push_back(*eItr); } while (!edgesToProcess.empty()) { @@ -492,21 +494,21 @@ namespace PBQP { } } - bool tryToEliminateEdge(Graph::EdgeItr eItr) { - if (tryNormaliseEdgeMatrix(eItr)) { - g.removeEdge(eItr); - return true; + bool tryToEliminateEdge(Graph::EdgeId eId) { + if (tryNormaliseEdgeMatrix(eId)) { + g.removeEdge(eId); + return true; } return false; } - bool tryNormaliseEdgeMatrix(Graph::EdgeItr &eItr) { + bool tryNormaliseEdgeMatrix(Graph::EdgeId &eId) { const PBQPNum infinity = std::numeric_limits::infinity(); - Matrix &edgeCosts = g.getEdgeCosts(eItr); - Vector &uCosts = g.getNodeCosts(g.getEdgeNode1(eItr)), - &vCosts = g.getNodeCosts(g.getEdgeNode2(eItr)); + Matrix &edgeCosts = g.getEdgeCosts(eId); + Vector &uCosts = g.getNodeCosts(g.getEdgeNode1(eId)), + &vCosts = g.getNodeCosts(g.getEdgeNode2(eId)); for (unsigned r = 0; r < edgeCosts.getRows(); ++r) { PBQPNum rowMin = infinity; @@ -554,34 +556,34 @@ namespace PBQP { } } - void computeSolution(Graph::NodeItr nItr) { + void computeSolution(Graph::NodeId nId) { - NodeData &nodeData = getSolverNodeData(nItr); + NodeData &nodeData = getSolverNodeData(nId); - Vector v(g.getNodeCosts(nItr)); + Vector v(g.getNodeCosts(nId)); // Solve based on existing solved edges. for (SolverEdgeItr solvedEdgeItr = nodeData.solverEdgesBegin(), solvedEdgeEnd = nodeData.solverEdgesEnd(); solvedEdgeItr != solvedEdgeEnd; ++solvedEdgeItr) { - Graph::EdgeItr eItr(*solvedEdgeItr); - Matrix &edgeCosts = g.getEdgeCosts(eItr); + Graph::EdgeId eId(*solvedEdgeItr); + Matrix &edgeCosts = g.getEdgeCosts(eId); - if (nItr == g.getEdgeNode1(eItr)) { - Graph::NodeItr adjNode(g.getEdgeNode2(eItr)); + if (nId == g.getEdgeNode1(eId)) { + Graph::NodeId adjNode(g.getEdgeNode2(eId)); unsigned adjSolution = s.getSelection(adjNode); v += edgeCosts.getColAsVector(adjSolution); } else { - Graph::NodeItr adjNode(g.getEdgeNode1(eItr)); + Graph::NodeId adjNode(g.getEdgeNode1(eId)); unsigned adjSolution = s.getSelection(adjNode); v += edgeCosts.getRowAsVector(adjSolution); } } - setSolution(nItr, v.minIndex()); + setSolution(nId, v.minIndex()); } void cleanup() { diff --git a/contrib/llvm/include/llvm/CodeGen/PBQP/Heuristics/Briggs.h b/contrib/llvm/include/llvm/CodeGen/PBQP/Heuristics/Briggs.h index 307d81e1d..c355c2c2f 100644 --- a/contrib/llvm/include/llvm/CodeGen/PBQP/Heuristics/Briggs.h +++ b/contrib/llvm/include/llvm/CodeGen/PBQP/Heuristics/Briggs.h @@ -27,7 +27,7 @@ namespace PBQP { /// \brief PBQP Heuristic which applies an allocability test based on /// Briggs. - /// + /// /// This heuristic assumes that the elements of cost vectors in the PBQP /// problem represent storage options, with the first being the spill /// option and subsequent elements representing legal registers for the @@ -39,16 +39,16 @@ namespace PBQP { /// solver stack. If no nodes can be proven allocable then the node with /// the lowest estimated spill cost is selected and push to the solver stack /// instead. - /// - /// This implementation is built on top of HeuristicBase. + /// + /// This implementation is built on top of HeuristicBase. class Briggs : public HeuristicBase { private: class LinkDegreeComparator { public: LinkDegreeComparator(HeuristicSolverImpl &s) : s(&s) {} - bool operator()(Graph::NodeItr n1Itr, Graph::NodeItr n2Itr) const { - if (s->getSolverDegree(n1Itr) > s->getSolverDegree(n2Itr)) + bool operator()(Graph::NodeId n1Id, Graph::NodeId n2Id) const { + if (s->getSolverDegree(n1Id) > s->getSolverDegree(n2Id)) return true; return false; } @@ -60,12 +60,12 @@ namespace PBQP { public: SpillCostComparator(HeuristicSolverImpl &s) : s(&s), g(&s.getGraph()) {} - bool operator()(Graph::NodeItr n1Itr, Graph::NodeItr n2Itr) const { - const PBQP::Vector &cv1 = g->getNodeCosts(n1Itr); - const PBQP::Vector &cv2 = g->getNodeCosts(n2Itr); + bool operator()(Graph::NodeId n1Id, Graph::NodeId n2Id) const { + const PBQP::Vector &cv1 = g->getNodeCosts(n1Id); + const PBQP::Vector &cv2 = g->getNodeCosts(n2Id); - PBQPNum cost1 = cv1[0] / s->getSolverDegree(n1Itr); - PBQPNum cost2 = cv2[0] / s->getSolverDegree(n2Itr); + PBQPNum cost1 = cv1[0] / s->getSolverDegree(n1Id); + PBQPNum cost2 = cv2[0] / s->getSolverDegree(n2Id); if (cost1 < cost2) return true; @@ -77,10 +77,10 @@ namespace PBQP { Graph *g; }; - typedef std::list RNAllocableList; + typedef std::list RNAllocableList; typedef RNAllocableList::iterator RNAllocableListItr; - typedef std::list RNUnallocableList; + typedef std::list RNUnallocableList; typedef RNUnallocableList::iterator RNUnallocableListItr; public: @@ -114,7 +114,7 @@ namespace PBQP { /// \brief Determine whether a node should be reduced using optimal /// reduction. - /// @param nItr Node iterator to be considered. + /// @param nId Node id to be considered. /// @return True if the given node should be optimally reduced, false /// otherwise. /// @@ -123,8 +123,8 @@ namespace PBQP { /// infinite are checked for allocability first. Allocable nodes may be /// optimally reduced, but nodes whose allocability cannot be proven are /// selected for heuristic reduction instead. - bool shouldOptimallyReduce(Graph::NodeItr nItr) { - if (getSolver().getSolverDegree(nItr) < 3) { + bool shouldOptimallyReduce(Graph::NodeId nId) { + if (getSolver().getSolverDegree(nId) < 3) { return true; } // else @@ -132,15 +132,15 @@ namespace PBQP { } /// \brief Add a node to the heuristic reduce list. - /// @param nItr Node iterator to add to the heuristic reduce list. - void addToHeuristicReduceList(Graph::NodeItr nItr) { - NodeData &nd = getHeuristicNodeData(nItr); - initializeNode(nItr); + /// @param nId Node id to add to the heuristic reduce list. + void addToHeuristicReduceList(Graph::NodeId nId) { + NodeData &nd = getHeuristicNodeData(nId); + initializeNode(nId); nd.isHeuristic = true; if (nd.isAllocable) { - nd.rnaItr = rnAllocableList.insert(rnAllocableList.end(), nItr); + nd.rnaItr = rnAllocableList.insert(rnAllocableList.end(), nId); } else { - nd.rnuItr = rnUnallocableList.insert(rnUnallocableList.end(), nItr); + nd.rnuItr = rnUnallocableList.insert(rnUnallocableList.end(), nId); } } @@ -159,19 +159,19 @@ namespace PBQP { RNAllocableListItr rnaItr = min_element(rnAllocableList.begin(), rnAllocableList.end(), LinkDegreeComparator(getSolver())); - Graph::NodeItr nItr = *rnaItr; + Graph::NodeId nId = *rnaItr; rnAllocableList.erase(rnaItr); - handleRemoveNode(nItr); - getSolver().pushToStack(nItr); + handleRemoveNode(nId); + getSolver().pushToStack(nId); return true; } else if (!rnUnallocableList.empty()) { RNUnallocableListItr rnuItr = min_element(rnUnallocableList.begin(), rnUnallocableList.end(), SpillCostComparator(getSolver())); - Graph::NodeItr nItr = *rnuItr; + Graph::NodeId nId = *rnuItr; rnUnallocableList.erase(rnuItr); - handleRemoveNode(nItr); - getSolver().pushToStack(nItr); + handleRemoveNode(nId); + getSolver().pushToStack(nId); return true; } // else @@ -179,43 +179,43 @@ namespace PBQP { } /// \brief Prepare a change in the costs on the given edge. - /// @param eItr Edge iterator. - void preUpdateEdgeCosts(Graph::EdgeItr eItr) { + /// @param eId Edge id. + void preUpdateEdgeCosts(Graph::EdgeId eId) { Graph &g = getGraph(); - Graph::NodeItr n1Itr = g.getEdgeNode1(eItr), - n2Itr = g.getEdgeNode2(eItr); - NodeData &n1 = getHeuristicNodeData(n1Itr), - &n2 = getHeuristicNodeData(n2Itr); + Graph::NodeId n1Id = g.getEdgeNode1(eId), + n2Id = g.getEdgeNode2(eId); + NodeData &n1 = getHeuristicNodeData(n1Id), + &n2 = getHeuristicNodeData(n2Id); if (n1.isHeuristic) - subtractEdgeContributions(eItr, getGraph().getEdgeNode1(eItr)); + subtractEdgeContributions(eId, getGraph().getEdgeNode1(eId)); if (n2.isHeuristic) - subtractEdgeContributions(eItr, getGraph().getEdgeNode2(eItr)); + subtractEdgeContributions(eId, getGraph().getEdgeNode2(eId)); - EdgeData &ed = getHeuristicEdgeData(eItr); + EdgeData &ed = getHeuristicEdgeData(eId); ed.isUpToDate = false; } /// \brief Handle the change in the costs on the given edge. - /// @param eItr Edge iterator. - void postUpdateEdgeCosts(Graph::EdgeItr eItr) { + /// @param eId Edge id. + void postUpdateEdgeCosts(Graph::EdgeId eId) { // This is effectively the same as adding a new edge now, since // we've factored out the costs of the old one. - handleAddEdge(eItr); + handleAddEdge(eId); } /// \brief Handle the addition of a new edge into the PBQP graph. - /// @param eItr Edge iterator for the added edge. + /// @param eId Edge id for the added edge. /// /// Updates allocability of any nodes connected by this edge which are /// being managed by the heuristic. If allocability changes they are /// moved to the appropriate list. - void handleAddEdge(Graph::EdgeItr eItr) { + void handleAddEdge(Graph::EdgeId eId) { Graph &g = getGraph(); - Graph::NodeItr n1Itr = g.getEdgeNode1(eItr), - n2Itr = g.getEdgeNode2(eItr); - NodeData &n1 = getHeuristicNodeData(n1Itr), - &n2 = getHeuristicNodeData(n2Itr); + Graph::NodeId n1Id = g.getEdgeNode1(eId), + n2Id = g.getEdgeNode2(eId); + NodeData &n1 = getHeuristicNodeData(n1Id), + &n2 = getHeuristicNodeData(n2Id); // If neither node is managed by the heuristic there's nothing to be // done. @@ -223,60 +223,60 @@ namespace PBQP { return; // Ok - we need to update at least one node. - computeEdgeContributions(eItr); + computeEdgeContributions(eId); // Update node 1 if it's managed by the heuristic. if (n1.isHeuristic) { bool n1WasAllocable = n1.isAllocable; - addEdgeContributions(eItr, n1Itr); - updateAllocability(n1Itr); + addEdgeContributions(eId, n1Id); + updateAllocability(n1Id); if (n1WasAllocable && !n1.isAllocable) { rnAllocableList.erase(n1.rnaItr); n1.rnuItr = - rnUnallocableList.insert(rnUnallocableList.end(), n1Itr); + rnUnallocableList.insert(rnUnallocableList.end(), n1Id); } } // Likewise for node 2. if (n2.isHeuristic) { bool n2WasAllocable = n2.isAllocable; - addEdgeContributions(eItr, n2Itr); - updateAllocability(n2Itr); + addEdgeContributions(eId, n2Id); + updateAllocability(n2Id); if (n2WasAllocable && !n2.isAllocable) { rnAllocableList.erase(n2.rnaItr); n2.rnuItr = - rnUnallocableList.insert(rnUnallocableList.end(), n2Itr); + rnUnallocableList.insert(rnUnallocableList.end(), n2Id); } } } /// \brief Handle disconnection of an edge from a node. - /// @param eItr Edge iterator for edge being disconnected. - /// @param nItr Node iterator for the node being disconnected from. + /// @param eId Edge id for edge being disconnected. + /// @param nId Node id for the node being disconnected from. /// /// Updates allocability of the given node and, if appropriate, moves the /// node to a new list. - void handleRemoveEdge(Graph::EdgeItr eItr, Graph::NodeItr nItr) { - NodeData &nd = getHeuristicNodeData(nItr); + void handleRemoveEdge(Graph::EdgeId eId, Graph::NodeId nId) { + NodeData &nd =getHeuristicNodeData(nId); // If the node is not managed by the heuristic there's nothing to be // done. if (!nd.isHeuristic) return; - EdgeData &ed = getHeuristicEdgeData(eItr); + EdgeData &ed = getHeuristicEdgeData(eId); (void)ed; assert(ed.isUpToDate && "Edge data is not up to date."); // Update node. bool ndWasAllocable = nd.isAllocable; - subtractEdgeContributions(eItr, nItr); - updateAllocability(nItr); + subtractEdgeContributions(eId, nId); + updateAllocability(nId); // If the node has gone optimal... - if (shouldOptimallyReduce(nItr)) { + if (shouldOptimallyReduce(nId)) { nd.isHeuristic = false; - addToOptimalReduceList(nItr); + addToOptimalReduceList(nId); if (ndWasAllocable) { rnAllocableList.erase(nd.rnaItr); } else { @@ -287,36 +287,36 @@ namespace PBQP { // from "unallocable" to "allocable". if (!ndWasAllocable && nd.isAllocable) { rnUnallocableList.erase(nd.rnuItr); - nd.rnaItr = rnAllocableList.insert(rnAllocableList.end(), nItr); + nd.rnaItr = rnAllocableList.insert(rnAllocableList.end(), nId); } } } private: - NodeData& getHeuristicNodeData(Graph::NodeItr nItr) { - return getSolver().getHeuristicNodeData(nItr); + NodeData& getHeuristicNodeData(Graph::NodeId nId) { + return getSolver().getHeuristicNodeData(nId); } - EdgeData& getHeuristicEdgeData(Graph::EdgeItr eItr) { - return getSolver().getHeuristicEdgeData(eItr); + EdgeData& getHeuristicEdgeData(Graph::EdgeId eId) { + return getSolver().getHeuristicEdgeData(eId); } // Work out what this edge will contribute to the allocability of the // nodes connected to it. - void computeEdgeContributions(Graph::EdgeItr eItr) { - EdgeData &ed = getHeuristicEdgeData(eItr); + void computeEdgeContributions(Graph::EdgeId eId) { + EdgeData &ed = getHeuristicEdgeData(eId); if (ed.isUpToDate) return; // Edge data is already up to date. - Matrix &eCosts = getGraph().getEdgeCosts(eItr); + Matrix &eCosts = getGraph().getEdgeCosts(eId); unsigned numRegs = eCosts.getRows() - 1, numReverseRegs = eCosts.getCols() - 1; std::vector rowInfCounts(numRegs, 0), - colInfCounts(numReverseRegs, 0); + colInfCounts(numReverseRegs, 0); ed.worst = 0; ed.reverseWorst = 0; @@ -348,19 +348,19 @@ namespace PBQP { ed.isUpToDate = true; } - // Add the contributions of the given edge to the given node's + // Add the contributions of the given edge to the given node's // numDenied and safe members. No action is taken other than to update // these member values. Once updated these numbers can be used by clients // to update the node's allocability. - void addEdgeContributions(Graph::EdgeItr eItr, Graph::NodeItr nItr) { - EdgeData &ed = getHeuristicEdgeData(eItr); + void addEdgeContributions(Graph::EdgeId eId, Graph::NodeId nId) { + EdgeData &ed = getHeuristicEdgeData(eId); assert(ed.isUpToDate && "Using out-of-date edge numbers."); - NodeData &nd = getHeuristicNodeData(nItr); - unsigned numRegs = getGraph().getNodeCosts(nItr).getLength() - 1; - - bool nIsNode1 = nItr == getGraph().getEdgeNode1(eItr); + NodeData &nd = getHeuristicNodeData(nId); + unsigned numRegs = getGraph().getNodeCosts(nId).getLength() - 1; + + bool nIsNode1 = nId == getGraph().getEdgeNode1(eId); EdgeData::UnsafeArray &unsafe = nIsNode1 ? ed.unsafe : ed.reverseUnsafe; nd.numDenied += nIsNode1 ? ed.worst : ed.reverseWorst; @@ -375,25 +375,25 @@ namespace PBQP { } } - // Subtract the contributions of the given edge to the given node's + // Subtract the contributions of the given edge to the given node's // numDenied and safe members. No action is taken other than to update // these member values. Once updated these numbers can be used by clients // to update the node's allocability. - void subtractEdgeContributions(Graph::EdgeItr eItr, Graph::NodeItr nItr) { - EdgeData &ed = getHeuristicEdgeData(eItr); + void subtractEdgeContributions(Graph::EdgeId eId, Graph::NodeId nId) { + EdgeData &ed = getHeuristicEdgeData(eId); assert(ed.isUpToDate && "Using out-of-date edge numbers."); - NodeData &nd = getHeuristicNodeData(nItr); - unsigned numRegs = getGraph().getNodeCosts(nItr).getLength() - 1; - - bool nIsNode1 = nItr == getGraph().getEdgeNode1(eItr); + NodeData &nd = getHeuristicNodeData(nId); + unsigned numRegs = getGraph().getNodeCosts(nId).getLength() - 1; + + bool nIsNode1 = nId == getGraph().getEdgeNode1(eId); EdgeData::UnsafeArray &unsafe = nIsNode1 ? ed.unsafe : ed.reverseUnsafe; nd.numDenied -= nIsNode1 ? ed.worst : ed.reverseWorst; for (unsigned r = 0; r < numRegs; ++r) { - if (unsafe[r]) { + if (unsafe[r]) { if (nd.unsafeDegrees[r] == 1) { ++nd.numSafe; } @@ -402,22 +402,22 @@ namespace PBQP { } } - void updateAllocability(Graph::NodeItr nItr) { - NodeData &nd = getHeuristicNodeData(nItr); - unsigned numRegs = getGraph().getNodeCosts(nItr).getLength() - 1; + void updateAllocability(Graph::NodeId nId) { + NodeData &nd = getHeuristicNodeData(nId); + unsigned numRegs = getGraph().getNodeCosts(nId).getLength() - 1; nd.isAllocable = nd.numDenied < numRegs || nd.numSafe > 0; } - void initializeNode(Graph::NodeItr nItr) { - NodeData &nd = getHeuristicNodeData(nItr); + void initializeNode(Graph::NodeId nId) { + NodeData &nd = getHeuristicNodeData(nId); if (nd.isInitialized) return; // Node data is already up to date. - unsigned numRegs = getGraph().getNodeCosts(nItr).getLength() - 1; + unsigned numRegs = getGraph().getNodeCosts(nId).getLength() - 1; nd.numDenied = 0; - const Vector& nCosts = getGraph().getNodeCosts(nItr); + const Vector& nCosts = getGraph().getNodeCosts(nId); for (unsigned i = 1; i < nCosts.getLength(); ++i) { if (nCosts[i] == std::numeric_limits::infinity()) ++nd.numDenied; @@ -428,27 +428,27 @@ namespace PBQP { typedef HeuristicSolverImpl::SolverEdgeItr SolverEdgeItr; - for (SolverEdgeItr aeItr = getSolver().solverEdgesBegin(nItr), - aeEnd = getSolver().solverEdgesEnd(nItr); + for (SolverEdgeItr aeItr = getSolver().solverEdgesBegin(nId), + aeEnd = getSolver().solverEdgesEnd(nId); aeItr != aeEnd; ++aeItr) { - - Graph::EdgeItr eItr = *aeItr; - computeEdgeContributions(eItr); - addEdgeContributions(eItr, nItr); + + Graph::EdgeId eId = *aeItr; + computeEdgeContributions(eId); + addEdgeContributions(eId, nId); } - updateAllocability(nItr); + updateAllocability(nId); nd.isInitialized = true; } - void handleRemoveNode(Graph::NodeItr xnItr) { + void handleRemoveNode(Graph::NodeId xnId) { typedef HeuristicSolverImpl::SolverEdgeItr SolverEdgeItr; - std::vector edgesToRemove; - for (SolverEdgeItr aeItr = getSolver().solverEdgesBegin(xnItr), - aeEnd = getSolver().solverEdgesEnd(xnItr); + std::vector edgesToRemove; + for (SolverEdgeItr aeItr = getSolver().solverEdgesBegin(xnId), + aeEnd = getSolver().solverEdgesEnd(xnId); aeItr != aeEnd; ++aeItr) { - Graph::NodeItr ynItr = getGraph().getEdgeOtherNode(*aeItr, xnItr); - handleRemoveEdge(*aeItr, ynItr); + Graph::NodeId ynId = getGraph().getEdgeOtherNode(*aeItr, xnId); + handleRemoveEdge(*aeItr, ynId); edgesToRemove.push_back(*aeItr); } while (!edgesToRemove.empty()) { diff --git a/contrib/llvm/include/llvm/CodeGen/PBQP/Solution.h b/contrib/llvm/include/llvm/CodeGen/PBQP/Solution.h index b9f288bbe..091805d00 100644 --- a/contrib/llvm/include/llvm/CodeGen/PBQP/Solution.h +++ b/contrib/llvm/include/llvm/CodeGen/PBQP/Solution.h @@ -26,8 +26,7 @@ namespace PBQP { class Solution { private: - typedef std::map SelectionsMap; + typedef std::map SelectionsMap; SelectionsMap selections; unsigned r0Reductions, r1Reductions, r2Reductions, rNReductions; @@ -71,17 +70,17 @@ namespace PBQP { unsigned numRNReductions() const { return rNReductions; } /// \brief Set the selection for a given node. - /// @param nItr Node iterator. - /// @param selection Selection for nItr. - void setSelection(Graph::NodeItr nItr, unsigned selection) { - selections[nItr] = selection; + /// @param nodeId Node id. + /// @param selection Selection for nodeId. + void setSelection(Graph::NodeId nodeId, unsigned selection) { + selections[nodeId] = selection; } /// \brief Get a node's selection. - /// @param nItr Node iterator. - /// @return The selection for nItr; - unsigned getSelection(Graph::ConstNodeItr nItr) const { - SelectionsMap::const_iterator sItr = selections.find(nItr); + /// @param nodeId Node id. + /// @return The selection for nodeId; + unsigned getSelection(Graph::NodeId nodeId) const { + SelectionsMap::const_iterator sItr = selections.find(nodeId); assert(sItr != selections.end() && "No selection for node."); return sItr->second; } diff --git a/contrib/llvm/include/llvm/CodeGen/Passes.h b/contrib/llvm/include/llvm/CodeGen/Passes.h index b02f63e70..ae4a2fa0b 100644 --- a/contrib/llvm/include/llvm/CodeGen/Passes.h +++ b/contrib/llvm/include/llvm/CodeGen/Passes.h @@ -21,19 +21,22 @@ namespace llvm { - class FunctionPass; - class MachineFunctionPass; - class PassInfo; - class PassManagerBase; - class TargetLoweringBase; - class TargetLowering; - class TargetRegisterClass; - class raw_ostream; -} - -namespace llvm { - +class FunctionPass; +class MachineFunctionPass; class PassConfigImpl; +class PassInfo; +class ScheduleDAGInstrs; +class TargetLowering; +class TargetLoweringBase; +class TargetRegisterClass; +class raw_ostream; +struct MachineSchedContext; + +// The old pass manager infrastructure is hidden in a legacy namespace now. +namespace legacy { +class PassManagerBase; +} +using legacy::PassManagerBase; /// Discriminated union of Pass ID types. /// @@ -204,6 +207,20 @@ public: /// Fully developed targets will not generally override this. virtual void addMachinePasses(); + /// createTargetScheduler - Create an instance of ScheduleDAGInstrs to be run + /// within the standard MachineScheduler pass for this function and target at + /// the current optimization level. + /// + /// 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 NULL to select the default (generic) machine scheduler. + virtual ScheduleDAGInstrs * + createMachineScheduler(MachineSchedContext *C) const { + return 0; + } + protected: // Helper to verify the analysis is really immutable. void setOpt(bool &Opt, bool Val); @@ -308,7 +325,8 @@ protected: AnalysisID addPass(AnalysisID PassID); /// Add a pass to the PassManager if that pass is supposed to be run, as - /// determined by the StartAfter and StopAfter options. + /// determined by the StartAfter and StopAfter options. Takes ownership of the + /// pass. void addPass(Pass *P); /// addMachinePasses helper to create the target-selected or overriden @@ -329,7 +347,7 @@ namespace llvm { /// This pass implements the target transform info analysis using the target /// independent information available to the LLVM code generator. ImmutablePass * - createBasicTargetTransformInfoPass(const TargetLoweringBase *TLI); + createBasicTargetTransformInfoPass(const TargetMachine *TM); /// createUnreachableBlockEliminationPass - The LLVM code generator does not /// work well with unreachable basic blocks (what live ranges make sense for a @@ -364,14 +382,6 @@ namespace llvm { /// these register allocator like this: AU.addRequiredID(PHIEliminationID); extern char &PHIEliminationID; - /// StrongPHIElimination - This pass eliminates machine instruction PHI - /// nodes by inserting copy instructions. This destroys SSA information, but - /// is the desired input for some register allocators. This pass is - /// "required" by these register allocator like this: - /// AU.addRequiredID(PHIEliminationID); - /// This pass is still in development - extern char &StrongPHIEliminationID; - /// LiveIntervals - This analysis keeps track of the live ranges of virtual /// and physical registers. extern char &LiveIntervalsID; @@ -518,7 +528,7 @@ namespace llvm { /// createStackProtectorPass - This pass adds stack protectors to functions. /// - FunctionPass *createStackProtectorPass(const TargetLoweringBase *tli); + FunctionPass *createStackProtectorPass(const TargetMachine *TM); /// createMachineVerifierPass - This pass verifies cenerated machine code /// instructions for correctness. @@ -527,12 +537,12 @@ namespace llvm { /// 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); + FunctionPass *createDwarfEHPass(const TargetMachine *TM); /// createSjLjEHPreparePass - This pass adapts exception handling code to use /// the GCC-style builtin setjmp/longjmp (sjlj) to handling EH control flow. /// - FunctionPass *createSjLjEHPreparePass(const TargetLoweringBase *tli); + FunctionPass *createSjLjEHPreparePass(const TargetMachine *TM); /// LocalStackSlotAllocation - This pass assigns local frame indices to stack /// slots relative to one another and allocates base registers to access them diff --git a/contrib/llvm/include/llvm/CodeGen/PseudoSourceValue.h b/contrib/llvm/include/llvm/CodeGen/PseudoSourceValue.h index df74d0888..705086c22 100644 --- a/contrib/llvm/include/llvm/CodeGen/PseudoSourceValue.h +++ b/contrib/llvm/include/llvm/CodeGen/PseudoSourceValue.h @@ -44,7 +44,7 @@ namespace llvm { virtual bool isAliased(const MachineFrameInfo *) const; /// mayAlias - Return true if the memory pointed to by this - /// PseudoSourceValue can ever alias a LLVM IR Value. + /// PseudoSourceValue can ever alias an LLVM IR Value. virtual bool mayAlias(const MachineFrameInfo *) const; /// classof - Methods for support type inquiry through isa, cast, and diff --git a/contrib/llvm/include/llvm/CodeGen/RegAllocPBQP.h b/contrib/llvm/include/llvm/CodeGen/RegAllocPBQP.h index 8b8e3d90f..7472e5a62 100644 --- a/contrib/llvm/include/llvm/CodeGen/RegAllocPBQP.h +++ b/contrib/llvm/include/llvm/CodeGen/RegAllocPBQP.h @@ -26,8 +26,8 @@ namespace llvm { class LiveIntervals; + class MachineBlockFrequencyInfo; class MachineFunction; - class MachineLoopInfo; class TargetRegisterInfo; template class OwningPtr; @@ -52,22 +52,22 @@ namespace llvm { /// PBQPBuilder you are unlikely to need this: Nodes and options for all /// vregs will already have been set up for you by the base class. template - void recordVReg(unsigned vreg, PBQP::Graph::NodeItr node, + void recordVReg(unsigned vreg, PBQP::Graph::NodeId nodeId, AllowedRegsItr arBegin, AllowedRegsItr arEnd) { - assert(node2VReg.find(node) == node2VReg.end() && "Re-mapping node."); + assert(node2VReg.find(nodeId) == node2VReg.end() && "Re-mapping node."); assert(vreg2Node.find(vreg) == vreg2Node.end() && "Re-mapping vreg."); assert(allowedSets[vreg].empty() && "vreg already has pregs."); - node2VReg[node] = vreg; - vreg2Node[vreg] = node; + node2VReg[nodeId] = vreg; + vreg2Node[vreg] = nodeId; std::copy(arBegin, arEnd, std::back_inserter(allowedSets[vreg])); } /// Get the virtual register corresponding to the given PBQP node. - unsigned getVRegForNode(PBQP::Graph::ConstNodeItr node) const; + unsigned getVRegForNode(PBQP::Graph::NodeId nodeId) const; /// Get the PBQP node corresponding to the given virtual register. - PBQP::Graph::NodeItr getNodeForVReg(unsigned vreg) const; + PBQP::Graph::NodeId getNodeForVReg(unsigned vreg) const; /// Returns true if the given PBQP option represents a physical register, /// false otherwise. @@ -92,9 +92,8 @@ namespace llvm { private: - typedef std::map Node2VReg; - typedef DenseMap VReg2Node; + typedef std::map Node2VReg; + typedef DenseMap VReg2Node; typedef DenseMap AllowedSetMap; PBQP::Graph graph; @@ -125,7 +124,7 @@ namespace llvm { /// Build a PBQP instance to represent the register allocation problem for /// the given MachineFunction. virtual PBQPRAProblem *build(MachineFunction *mf, const LiveIntervals *lis, - const MachineLoopInfo *loopInfo, + const MachineBlockFrequencyInfo *mbfi, const RegSet &vregs); private: @@ -144,7 +143,7 @@ namespace llvm { /// Build a PBQP instance to represent the register allocation problem for /// the given MachineFunction. virtual PBQPRAProblem *build(MachineFunction *mf, const LiveIntervals *lis, - const MachineLoopInfo *loopInfo, + const MachineBlockFrequencyInfo *mbfi, const RegSet &vregs); private: diff --git a/contrib/llvm/include/llvm/CodeGen/RegisterClassInfo.h b/contrib/llvm/include/llvm/CodeGen/RegisterClassInfo.h index 3ad22e65c..9ec12bdea 100644 --- a/contrib/llvm/include/llvm/CodeGen/RegisterClassInfo.h +++ b/contrib/llvm/include/llvm/CodeGen/RegisterClassInfo.h @@ -62,6 +62,8 @@ class RegisterClassInfo { // Reserved registers in the current MF. BitVector Reserved; + OwningArrayPtr PSetLimits; + // Compute all information about RC. void compute(const TargetRegisterClass *RC) const; @@ -126,8 +128,19 @@ public: unsigned getLastCostChange(const TargetRegisterClass *RC) { return get(RC).LastCostChange; } + + /// Get the register unit limit for the given pressure set index. + /// + /// RegisterClassInfo adjusts this limit for reserved registers. + unsigned getRegPressureSetLimit(unsigned Idx) const { + if (!PSetLimits[Idx]) + PSetLimits[Idx] = computePSetLimit(Idx); + return PSetLimits[Idx]; + } + +protected: + unsigned computePSetLimit(unsigned Idx) const; }; } // end namespace llvm #endif - diff --git a/contrib/llvm/include/llvm/CodeGen/RegisterPressure.h b/contrib/llvm/include/llvm/CodeGen/RegisterPressure.h index 267018074..a801d1d1e 100644 --- a/contrib/llvm/include/llvm/CodeGen/RegisterPressure.h +++ b/contrib/llvm/include/llvm/CodeGen/RegisterPressure.h @@ -22,7 +22,7 @@ namespace llvm { class LiveIntervals; -class LiveInterval; +class LiveRange; class RegisterClassInfo; class MachineInstr; @@ -89,16 +89,89 @@ struct RegionPressure : RegisterPressure { void openBottom(MachineBasicBlock::const_iterator PrevBottom); }; -/// An element of pressure difference that identifies the pressure set and -/// amount of increase or decrease in units of pressure. -struct PressureElement { - unsigned PSetID; - int UnitIncrease; +/// Capture a change in pressure for a single pressure set. UnitInc may be +/// expressed in terms of upward or downward pressure depending on the client +/// and will be dynamically adjusted for current liveness. +/// +/// Pressure increments are tiny, typically 1-2 units, and this is only for +/// heuristics, so we don't check UnitInc overflow. Instead, we may have a +/// higher level assert that pressure is consistent within a region. We also +/// effectively ignore dead defs which don't affect heuristics much. +class PressureChange { + uint16_t PSetID; // ID+1. 0=Invalid. + int16_t UnitInc; +public: + PressureChange(): PSetID(0), UnitInc(0) {} + PressureChange(unsigned id): PSetID(id+1), UnitInc(0) { + assert(id < UINT16_MAX && "PSetID overflow."); + } + + bool isValid() const { return PSetID > 0; } + + unsigned getPSet() const { + assert(isValid() && "invalid PressureChange"); + return PSetID - 1; + } + // If PSetID is invalid, return UINT16_MAX to give it lowest priority. + unsigned getPSetOrMax() const { return (PSetID - 1) & UINT16_MAX; } + + int getUnitInc() const { return UnitInc; } + + void setUnitInc(int Inc) { UnitInc = Inc; } + + bool operator==(const PressureChange &RHS) const { + return PSetID == RHS.PSetID && UnitInc == RHS.UnitInc; + } +}; + +template <> struct isPodLike { + static const bool value = true; +}; + +/// List of PressureChanges in order of increasing, unique PSetID. +/// +/// Use a small fixed number, because we can fit more PressureChanges in an +/// empty SmallVector than ever need to be tracked per register class. If more +/// PSets are affected, then we only track the most constrained. +class PressureDiff { + // The initial design was for MaxPSets=4, but that requires PSet partitions, + // which are not yet implemented. (PSet partitions are equivalent PSets given + // the register classes actually in use within the scheduling region.) + enum { MaxPSets = 16 }; + + PressureChange PressureChanges[MaxPSets]; +public: + typedef PressureChange* iterator; + typedef const PressureChange* const_iterator; + iterator begin() { return &PressureChanges[0]; } + iterator end() { return &PressureChanges[MaxPSets]; } + const_iterator begin() const { return &PressureChanges[0]; } + const_iterator end() const { return &PressureChanges[MaxPSets]; } + + void addPressureChange(unsigned RegUnit, bool IsDec, + const MachineRegisterInfo *MRI); +}; + +/// Array of PressureDiffs. +class PressureDiffs { + PressureDiff *PDiffArray; + unsigned Size; + unsigned Max; +public: + PressureDiffs(): PDiffArray(0), Size(0), Max(0) {} + ~PressureDiffs() { free(PDiffArray); } - PressureElement(): PSetID(~0U), UnitIncrease(0) {} - PressureElement(unsigned id, int inc): PSetID(id), UnitIncrease(inc) {} + void clear() { Size = 0; } - bool isValid() const { return PSetID != ~0U; } + void init(unsigned N); + + PressureDiff &operator[](unsigned Idx) { + assert(Idx < Size && "PressureDiff index out of bounds"); + return PDiffArray[Idx]; + } + const PressureDiff &operator[](unsigned Idx) const { + return const_cast(this)->operator[](Idx); + } }; /// Store the effects of a change in pressure on things that MI scheduler cares @@ -116,11 +189,19 @@ struct PressureElement { /// CurrentMax records the largest increase in the tracker's max pressure that /// exceeds the current limit for some pressure set determined by the client. struct RegPressureDelta { - PressureElement Excess; - PressureElement CriticalMax; - PressureElement CurrentMax; + PressureChange Excess; + PressureChange CriticalMax; + PressureChange CurrentMax; RegPressureDelta() {} + + bool operator==(const RegPressureDelta &RHS) const { + return Excess == RHS.Excess && CriticalMax == RHS.CriticalMax + && CurrentMax == RHS.CurrentMax; + } + bool operator!=(const RegPressureDelta &RHS) const { + return !operator==(RHS); + } }; /// \brief A set of live virtual registers and physical register units. @@ -131,7 +212,7 @@ struct LiveRegSet { SparseSet PhysRegs; SparseSet VirtRegs; - bool contains(unsigned Reg) { + bool contains(unsigned Reg) const { if (TargetRegisterInfo::isVirtualRegister(Reg)) return VirtRegs.count(Reg); return PhysRegs.count(Reg); @@ -183,6 +264,9 @@ class RegPressureTracker { /// or RegisterPressure. If requireIntervals is false, LIS are ignored. bool RequireIntervals; + /// True if UntiedDefs will be populated. + bool TrackUntiedDefs; + /// Register pressure corresponds to liveness before this instruction /// iterator. It may point to the end of the block or a DebugValue rather than /// an instruction. @@ -194,16 +278,26 @@ class RegPressureTracker { /// Set of live registers. LiveRegSet LiveRegs; + /// Set of vreg defs that start a live range. + SparseSet UntiedDefs; + /// Live-through pressure. + std::vector LiveThruPressure; + public: RegPressureTracker(IntervalPressure &rp) : - MF(0), TRI(0), RCI(0), LIS(0), MBB(0), P(rp), RequireIntervals(true) {} + MF(0), TRI(0), RCI(0), LIS(0), MBB(0), P(rp), RequireIntervals(true), + TrackUntiedDefs(false) {} RegPressureTracker(RegionPressure &rp) : - MF(0), TRI(0), RCI(0), LIS(0), MBB(0), P(rp), RequireIntervals(false) {} + MF(0), TRI(0), RCI(0), LIS(0), MBB(0), P(rp), RequireIntervals(false), + TrackUntiedDefs(false) {} + + void reset(); void init(const MachineFunction *mf, const RegisterClassInfo *rci, const LiveIntervals *lis, const MachineBasicBlock *mbb, - MachineBasicBlock::const_iterator pos); + MachineBasicBlock::const_iterator pos, + bool ShouldTrackUntiedDefs = false); /// Force liveness of virtual registers or physical register /// units. Particularly useful to initialize the livein/out state of the @@ -224,7 +318,7 @@ public: SlotIndex getCurrSlot() const; /// Recede across the previous instruction. - bool recede(); + bool recede(SmallVectorImpl *LiveUses = 0, PressureDiff *PDiff = 0); /// Advance across the current instruction. bool advance(); @@ -232,6 +326,17 @@ public: /// Finalize the region boundaries and recored live ins and live outs. void closeRegion(); + /// Initialize the LiveThru pressure set based on the untied defs found in + /// RPTracker. + void initLiveThru(const RegPressureTracker &RPTracker); + + /// Copy an existing live thru pressure result. + void initLiveThru(ArrayRef PressureSet) { + LiveThruPressure.assign(PressureSet.begin(), PressureSet.end()); + } + + ArrayRef getLiveThru() const { return LiveThruPressure; } + /// Get the resulting register pressure over the traversed region. /// This result is complete if either advance() or recede() has returned true, /// or if closeRegion() was explicitly invoked. @@ -256,31 +361,39 @@ public: /// limit based on the tracker's current pressure, and record the number of /// excess register units of that pressure set introduced by this instruction. void getMaxUpwardPressureDelta(const MachineInstr *MI, + PressureDiff *PDiff, RegPressureDelta &Delta, - ArrayRef CriticalPSets, + ArrayRef CriticalPSets, ArrayRef MaxPressureLimit); + void getUpwardPressureDelta(const MachineInstr *MI, + /*const*/ PressureDiff &PDiff, + RegPressureDelta &Delta, + ArrayRef CriticalPSets, + ArrayRef MaxPressureLimit) const; + /// Consider the pressure increase caused by traversing this instruction /// top-down. Find the pressure set with the most change beyond its pressure /// limit based on the tracker's current pressure, and record the number of /// excess register units of that pressure set introduced by this instruction. void getMaxDownwardPressureDelta(const MachineInstr *MI, RegPressureDelta &Delta, - ArrayRef CriticalPSets, + ArrayRef CriticalPSets, ArrayRef MaxPressureLimit); /// Find the pressure set with the most change beyond its pressure limit after /// traversing this instruction either upward or downward depending on the /// closed end of the current region. - void getMaxPressureDelta(const MachineInstr *MI, RegPressureDelta &Delta, - ArrayRef CriticalPSets, + void getMaxPressureDelta(const MachineInstr *MI, + RegPressureDelta &Delta, + ArrayRef CriticalPSets, ArrayRef MaxPressureLimit) { if (isTopClosed()) return getMaxDownwardPressureDelta(MI, Delta, CriticalPSets, MaxPressureLimit); assert(isBottomClosed() && "Uninitialized pressure tracker"); - return getMaxUpwardPressureDelta(MI, Delta, CriticalPSets, + return getMaxUpwardPressureDelta(MI, 0, Delta, CriticalPSets, MaxPressureLimit); } @@ -304,10 +417,14 @@ public: return getDownwardPressure(MI, PressureResult, MaxPressureResult); } + bool hasUntiedDef(unsigned VirtReg) const { + return UntiedDefs.count(VirtReg); + } + void dump() const; protected: - const LiveInterval *getInterval(unsigned Reg) const; + const LiveRange *getLiveRange(unsigned Reg) const; void increaseRegPressure(ArrayRef Regs); void decreaseRegPressure(ArrayRef Regs); @@ -315,6 +432,11 @@ protected: void bumpUpwardPressure(const MachineInstr *MI); void bumpDownwardPressure(const MachineInstr *MI); }; + +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) +void dumpRegSetPressure(ArrayRef SetPressure, + const TargetRegisterInfo *TRI); +#endif } // end namespace llvm #endif diff --git a/contrib/llvm/include/llvm/CodeGen/RegisterScavenging.h b/contrib/llvm/include/llvm/CodeGen/RegisterScavenging.h index 95bf29167..28ebe5361 100644 --- a/contrib/llvm/include/llvm/CodeGen/RegisterScavenging.h +++ b/contrib/llvm/include/llvm/CodeGen/RegisterScavenging.h @@ -131,7 +131,7 @@ public: /// Query whether a frame index is a scavenging frame index. bool isScavengingFrameIndex(int FI) const { - for (SmallVector::const_iterator I = Scavenged.begin(), + for (SmallVectorImpl::const_iterator I = Scavenged.begin(), IE = Scavenged.end(); I != IE; ++I) if (I->FrameIndex == FI) return true; @@ -141,7 +141,7 @@ public: /// Get an array of scavenging frame indices. void getScavengingFrameIndices(SmallVectorImpl &A) const { - for (SmallVector::const_iterator I = Scavenged.begin(), + for (SmallVectorImpl::const_iterator I = Scavenged.begin(), IE = Scavenged.end(); I != IE; ++I) if (I->FrameIndex >= 0) A.push_back(I->FrameIndex); diff --git a/contrib/llvm/include/llvm/CodeGen/RuntimeLibcalls.h b/contrib/llvm/include/llvm/CodeGen/RuntimeLibcalls.h index 41289a42c..009b8a0f6 100644 --- a/contrib/llvm/include/llvm/CodeGen/RuntimeLibcalls.h +++ b/contrib/llvm/include/llvm/CodeGen/RuntimeLibcalls.h @@ -1,4 +1,4 @@ -//===-- CodeGen/RuntimeLibcall.h - Runtime Library Calls --------*- C++ -*-===// +//===-- CodeGen/RuntimeLibcalls.h - Runtime Library Calls -------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -188,6 +188,11 @@ namespace RTLIB { NEARBYINT_F80, NEARBYINT_F128, NEARBYINT_PPCF128, + ROUND_F32, + ROUND_F64, + ROUND_F80, + ROUND_F128, + ROUND_PPCF128, FLOOR_F32, FLOOR_F64, FLOOR_F80, @@ -320,34 +325,65 @@ namespace RTLIB { SYNC_VAL_COMPARE_AND_SWAP_2, SYNC_VAL_COMPARE_AND_SWAP_4, SYNC_VAL_COMPARE_AND_SWAP_8, + SYNC_VAL_COMPARE_AND_SWAP_16, SYNC_LOCK_TEST_AND_SET_1, SYNC_LOCK_TEST_AND_SET_2, SYNC_LOCK_TEST_AND_SET_4, SYNC_LOCK_TEST_AND_SET_8, + SYNC_LOCK_TEST_AND_SET_16, SYNC_FETCH_AND_ADD_1, SYNC_FETCH_AND_ADD_2, SYNC_FETCH_AND_ADD_4, SYNC_FETCH_AND_ADD_8, + SYNC_FETCH_AND_ADD_16, SYNC_FETCH_AND_SUB_1, SYNC_FETCH_AND_SUB_2, SYNC_FETCH_AND_SUB_4, SYNC_FETCH_AND_SUB_8, + SYNC_FETCH_AND_SUB_16, SYNC_FETCH_AND_AND_1, SYNC_FETCH_AND_AND_2, SYNC_FETCH_AND_AND_4, SYNC_FETCH_AND_AND_8, + SYNC_FETCH_AND_AND_16, SYNC_FETCH_AND_OR_1, SYNC_FETCH_AND_OR_2, SYNC_FETCH_AND_OR_4, SYNC_FETCH_AND_OR_8, + SYNC_FETCH_AND_OR_16, SYNC_FETCH_AND_XOR_1, SYNC_FETCH_AND_XOR_2, SYNC_FETCH_AND_XOR_4, SYNC_FETCH_AND_XOR_8, + SYNC_FETCH_AND_XOR_16, SYNC_FETCH_AND_NAND_1, SYNC_FETCH_AND_NAND_2, SYNC_FETCH_AND_NAND_4, SYNC_FETCH_AND_NAND_8, + SYNC_FETCH_AND_NAND_16, + SYNC_FETCH_AND_MAX_1, + SYNC_FETCH_AND_MAX_2, + SYNC_FETCH_AND_MAX_4, + SYNC_FETCH_AND_MAX_8, + SYNC_FETCH_AND_MAX_16, + SYNC_FETCH_AND_UMAX_1, + SYNC_FETCH_AND_UMAX_2, + SYNC_FETCH_AND_UMAX_4, + SYNC_FETCH_AND_UMAX_8, + SYNC_FETCH_AND_UMAX_16, + SYNC_FETCH_AND_MIN_1, + SYNC_FETCH_AND_MIN_2, + SYNC_FETCH_AND_MIN_4, + SYNC_FETCH_AND_MIN_8, + SYNC_FETCH_AND_MIN_16, + SYNC_FETCH_AND_UMIN_1, + SYNC_FETCH_AND_UMIN_2, + SYNC_FETCH_AND_UMIN_4, + SYNC_FETCH_AND_UMIN_8, + SYNC_FETCH_AND_UMIN_16, + + // Stack Protector Fail. + STACKPROTECTOR_CHECK_FAIL, UNKNOWN_LIBCALL }; diff --git a/contrib/llvm/include/llvm/CodeGen/ScheduleDAG.h b/contrib/llvm/include/llvm/CodeGen/ScheduleDAG.h index 7cff27e17..ccba1b036 100644 --- a/contrib/llvm/include/llvm/CodeGen/ScheduleDAG.h +++ b/contrib/llvm/include/llvm/CodeGen/ScheduleDAG.h @@ -90,11 +90,6 @@ namespace llvm { /// the value of the Latency field of the predecessor, however advanced /// models may provide additional information about specific edges. unsigned Latency; - /// Record MinLatency seperately from "expected" Latency. - /// - /// FIXME: this field is not packed on LP64. Convert to 16-bit DAG edge - /// latency after introducing saturating truncation. - unsigned MinLatency; public: /// SDep - Construct a null SDep. This is only for use by container @@ -120,10 +115,9 @@ namespace llvm { Latency = 1; break; } - MinLatency = Latency; } SDep(SUnit *S, OrderKind kind) - : Dep(S, Order), Contents(), Latency(0), MinLatency(0) { + : Dep(S, Order), Contents(), Latency(0) { Contents.OrdKind = kind; } @@ -142,8 +136,7 @@ namespace llvm { } bool operator==(const SDep &Other) const { - return overlaps(Other) - && Latency == Other.Latency && MinLatency == Other.MinLatency; + return overlaps(Other) && Latency == Other.Latency; } bool operator!=(const SDep &Other) const { @@ -163,18 +156,6 @@ namespace llvm { Latency = Lat; } - /// getMinLatency - Return the minimum latency for this edge. Minimum - /// latency is used for scheduling groups, while normal (expected) latency - /// is for instruction cost and critical path. - unsigned getMinLatency() const { - return MinLatency; - } - - /// setMinLatency - Set the minimum latency for this edge. - void setMinLatency(unsigned Lat) { - MinLatency = Lat; - } - //// getSUnit - Return the SUnit to which this edge points. SUnit *getSUnit() const { return Dep.getPointer(); @@ -267,7 +248,7 @@ namespace llvm { /// SUnit - Scheduling unit. This is a node in the scheduling DAG. class SUnit { private: - enum { BoundaryID = ~0u }; + enum LLVM_ENUM_INT_TYPE(unsigned) { BoundaryID = ~0u }; SDNode *Node; // Representative node. MachineInstr *Instr; // Alternatively, a MachineInstr. @@ -282,10 +263,10 @@ namespace llvm { SmallVector Preds; // All sunit predecessors. SmallVector Succs; // All sunit successors. - typedef SmallVector::iterator pred_iterator; - typedef SmallVector::iterator succ_iterator; - typedef SmallVector::const_iterator const_pred_iterator; - typedef SmallVector::const_iterator const_succ_iterator; + typedef SmallVectorImpl::iterator pred_iterator; + typedef SmallVectorImpl::iterator succ_iterator; + typedef SmallVectorImpl::const_iterator const_pred_iterator; + typedef SmallVectorImpl::const_iterator const_succ_iterator; unsigned NodeNum; // Entry # of node in the node vector. unsigned NodeQueueId; // Queue id of node. diff --git a/contrib/llvm/include/llvm/CodeGen/ScheduleDAGInstrs.h b/contrib/llvm/include/llvm/CodeGen/ScheduleDAGInstrs.h index 990cac634..fe4f3c2de 100644 --- a/contrib/llvm/include/llvm/CodeGen/ScheduleDAGInstrs.h +++ b/contrib/llvm/include/llvm/CodeGen/ScheduleDAGInstrs.h @@ -28,6 +28,7 @@ namespace llvm { class MachineDominatorTree; class LiveIntervals; class RegPressureTracker; + class PressureDiffs; /// An individual mapping from virtual register number to SUnit. struct VReg2SUnit { @@ -56,7 +57,8 @@ namespace llvm { /// Use a SparseMultiSet to track physical registers. Storage is only /// allocated once for the pass. It can be cleared in constant time and reused /// without any frees. - typedef SparseMultiSet, uint16_t> Reg2SUnitsMap; + typedef SparseMultiSet, uint16_t> + Reg2SUnitsMap; /// Use SparseSet as a SparseMap by relying on the fact that it never /// compares ValueT's, only unsigned keys. This allows the set to be cleared @@ -64,6 +66,11 @@ namespace llvm { /// require a destructor. typedef SparseSet VReg2SUnitMap; + /// Track local uses of virtual registers. These uses are gathered by the DAG + /// builder and may be consulted by the scheduler to avoid iterating an entire + /// vreg use list. + typedef SparseMultiSet VReg2UseMap; + /// ScheduleDAGInstrs - A ScheduleDAG subclass for scheduling lists of /// MachineInstrs. class ScheduleDAGInstrs : public ScheduleDAG { @@ -81,10 +88,6 @@ namespace llvm { /// isPostRA flag indicates vregs cannot be present. bool IsPostRA; - /// UnitLatencies (misnamed) flag avoids computing def-use latencies, using - /// the def-side latency only. - bool UnitLatencies; - /// The standard DAG builder does not normally include terminators as DAG /// nodes because it does not create the necessary dependencies to prevent /// reordering. A specialized scheduler can overide @@ -104,17 +107,18 @@ namespace llvm { /// The end of the range to be scheduled. MachineBasicBlock::iterator RegionEnd; - /// The index in BB of RegionEnd. - /// - /// This is the instruction number from the top of the current block, not - /// the SlotIndex. It is only used by the AntiDepBreaker and should be - /// removed once that client is obsolete. - unsigned EndIndex; + /// Instructions in this region (distance(RegionBegin, RegionEnd)). + unsigned NumRegionInstrs; /// After calling BuildSchedGraph, each machine instruction in the current /// scheduling region is mapped to an SUnit. DenseMap MISUnitMap; + /// After calling BuildSchedGraph, each vreg used in the scheduling region + /// is mapped to a set of SUnits. These include all local vreg uses, not + /// just the uses for a singly defined vreg. + VReg2UseMap VRegUses; + /// State internal to DAG building. /// ------------------------------- @@ -125,7 +129,7 @@ namespace llvm { Reg2SUnitsMap Defs; Reg2SUnitsMap Uses; - /// Track the last instructon in this region defining each virtual register. + /// Track the last instruction in this region defining each virtual register. VReg2SUnitMap VRegDefs; /// PendingLoads - Remember where unknown loads are after the most recent @@ -158,7 +162,7 @@ namespace llvm { /// \brief Resolve and cache a resolved scheduling class for an SUnit. const MCSchedClassDesc *getSchedClass(SUnit *SU) const { - if (!SU->SchedClass) + if (!SU->SchedClass && SchedModel.hasInstrSchedModel()) SU->SchedClass = SchedModel.resolveSchedClass(SU->getInstr()); return SU->SchedClass; } @@ -185,14 +189,15 @@ namespace llvm { virtual void enterRegion(MachineBasicBlock *bb, MachineBasicBlock::iterator begin, MachineBasicBlock::iterator end, - unsigned endcount); + unsigned regioninstrs); /// Notify that the scheduler has finished scheduling the current region. virtual void exitRegion(); /// buildSchedGraph - Build SUnits from the MachineBasicBlock that we are /// input. - void buildSchedGraph(AliasAnalysis *AA, RegPressureTracker *RPTracker = 0); + void buildSchedGraph(AliasAnalysis *AA, RegPressureTracker *RPTracker = 0, + PressureDiffs *PDiffs = 0); /// addSchedBarrierDeps - Add dependencies from instructions in the current /// list of instructions being scheduled to scheduling barrier. We want to diff --git a/contrib/llvm/include/llvm/CodeGen/SelectionDAG.h b/contrib/llvm/include/llvm/CodeGen/SelectionDAG.h index 8c064bf2d..82becca31 100644 --- a/contrib/llvm/include/llvm/CodeGen/SelectionDAG.h +++ b/contrib/llvm/include/llvm/CodeGen/SelectionDAG.h @@ -33,12 +33,50 @@ class AliasAnalysis; class MachineConstantPoolValue; class MachineFunction; class MDNode; -class SDNodeOrdering; class SDDbgValue; class TargetLowering; class TargetSelectionDAGInfo; class TargetTransformInfo; +class SDVTListNode : public FoldingSetNode { + friend struct FoldingSetTrait; + /// FastID - A reference to an Interned FoldingSetNodeID for this node. + /// The Allocator in SelectionDAG holds the data. + /// SDVTList contains all types which are frequently accessed in SelectionDAG. + /// The size of this list is not expected big so it won't introduce memory penalty. + FoldingSetNodeIDRef FastID; + const EVT *VTs; + unsigned int NumVTs; + /// The hash value for SDVTList is fixed so cache it to avoid hash calculation + unsigned HashValue; +public: + SDVTListNode(const FoldingSetNodeIDRef ID, const EVT *VT, unsigned int Num) : + FastID(ID), VTs(VT), NumVTs(Num) { + HashValue = ID.ComputeHash(); + } + SDVTList getSDVTList() { + SDVTList result = {VTs, NumVTs}; + return result; + } +}; + +// Specialize FoldingSetTrait for SDVTListNode +// To avoid computing temp FoldingSetNodeID and hash value. +template<> struct FoldingSetTrait : DefaultFoldingSetTrait { + static void Profile(const SDVTListNode &X, FoldingSetNodeID& ID) { + ID = X.FastID; + } + static bool Equals(const SDVTListNode &X, const FoldingSetNodeID &ID, + unsigned IDHash, FoldingSetNodeID &TempID) { + if (X.HashValue != IDHash) + return false; + return ID == X.FastID; + } + static unsigned ComputeHash(const SDVTListNode &X, FoldingSetNodeID &TempID) { + return X.HashValue; + } +}; + template<> struct ilist_traits : public ilist_default_traits { private: mutable ilist_half_node Sentinel; @@ -73,7 +111,8 @@ private: class SDDbgInfo { SmallVector DbgValues; SmallVector ByvalParmDbgValues; - DenseMap > DbgValMap; + typedef DenseMap > DbgValMapType; + DbgValMapType DbgValMap; void operator=(const SDDbgInfo&) LLVM_DELETED_FUNCTION; SDDbgInfo(const SDDbgInfo&) LLVM_DELETED_FUNCTION; @@ -99,14 +138,13 @@ public: } ArrayRef getSDDbgValues(const SDNode *Node) { - DenseMap >::iterator I = - DbgValMap.find(Node); + DbgValMapType::iterator I = DbgValMap.find(Node); if (I != DbgValMap.end()) return I->second; return ArrayRef(); } - typedef SmallVector::iterator DbgIterator; + typedef SmallVectorImpl::iterator DbgIterator; DbgIterator DbgBegin() { return DbgValues.begin(); } DbgIterator DbgEnd() { return DbgValues.end(); } DbgIterator ByvalParmDbgBegin() { return ByvalParmDbgValues.begin(); } @@ -130,9 +168,9 @@ void checkForCycles(const SelectionDAG *DAG); /// class SelectionDAG { const TargetMachine &TM; - const TargetLowering &TLI; const TargetSelectionDAGInfo &TSI; const TargetTransformInfo *TTI; + const TargetLowering *TLI; MachineFunction *MF; LLVMContext *Context; CodeGenOpt::Level OptLevel; @@ -166,10 +204,6 @@ class SelectionDAG { /// SelectionDAG. BumpPtrAllocator Allocator; - /// SDNodeOrdering - The ordering of the SDNodes. It roughly corresponds to - /// the ordering of the original LLVM instructions. - SDNodeOrdering *Ordering; - /// DbgInfo - Tracks dbg_value information through SDISel. SDDbgInfo *DbgInfo; @@ -203,6 +237,13 @@ public: virtual void NodeUpdated(SDNode *N); }; + /// NewNodesMustHaveLegalTypes - When true, additional steps are taken to + /// ensure that getConstant() and similar functions return DAG nodes that + /// have legal types. This is important after type legalization since + /// any illegally typed nodes generated after this point will not experience + /// type legalization. + bool NewNodesMustHaveLegalTypes; + private: /// DAGUpdateListener is a friend so it can manipulate the listener stack. friend struct DAGUpdateListener; @@ -228,7 +269,8 @@ public: /// init - Prepare this SelectionDAG to process code in the given /// MachineFunction. /// - void init(MachineFunction &mf, const TargetTransformInfo *TTI); + void init(MachineFunction &mf, const TargetTransformInfo *TTI, + const TargetLowering *TLI); /// clear - Clear state and free memory necessary to make this /// SelectionDAG ready to process a new block. @@ -237,7 +279,7 @@ public: MachineFunction &getMachineFunction() const { return *MF; } const TargetMachine &getTarget() const { return TM; } - const TargetLowering &getTargetLoweringInfo() const { return TLI; } + const TargetLowering &getTargetLoweringInfo() const { return *TLI; } const TargetSelectionDAGInfo &getSelectionDAGInfo() const { return TSI; } const TargetTransformInfo *getTargetTransformInfo() const { return TTI; } LLVMContext *getContext() const {return Context; } @@ -386,10 +428,10 @@ public: SDValue getTargetConstantFP(const ConstantFP &Val, EVT VT) { return getConstantFP(Val, VT, true); } - SDValue getGlobalAddress(const GlobalValue *GV, DebugLoc DL, EVT VT, + SDValue getGlobalAddress(const GlobalValue *GV, SDLoc DL, EVT VT, int64_t offset = 0, bool isTargetGA = false, unsigned char TargetFlags = 0); - SDValue getTargetGlobalAddress(const GlobalValue *GV, DebugLoc DL, EVT VT, + SDValue getTargetGlobalAddress(const GlobalValue *GV, SDLoc DL, EVT VT, int64_t offset = 0, unsigned char TargetFlags = 0) { return getGlobalAddress(GV, DL, VT, offset, true, TargetFlags); @@ -424,15 +466,15 @@ public: // When generating a branch to a BB, we don't in general know enough // to provide debug info for the BB at that time, so keep this one around. SDValue getBasicBlock(MachineBasicBlock *MBB); - SDValue getBasicBlock(MachineBasicBlock *MBB, DebugLoc dl); + SDValue getBasicBlock(MachineBasicBlock *MBB, SDLoc dl); SDValue getExternalSymbol(const char *Sym, EVT VT); - SDValue getExternalSymbol(const char *Sym, DebugLoc dl, EVT VT); + SDValue getExternalSymbol(const char *Sym, SDLoc dl, EVT VT); SDValue getTargetExternalSymbol(const char *Sym, EVT VT, unsigned char TargetFlags = 0); SDValue getValueType(EVT); SDValue getRegister(unsigned Reg, EVT VT); SDValue getRegisterMask(const uint32_t *RegMask); - SDValue getEHLabel(DebugLoc dl, SDValue Root, MCSymbol *Label); + SDValue getEHLabel(SDLoc dl, SDValue Root, MCSymbol *Label); SDValue getBlockAddress(const BlockAddress *BA, EVT VT, int64_t Offset = 0, bool isTarget = false, unsigned char TargetFlags = 0); @@ -442,7 +484,7 @@ public: return getBlockAddress(BA, VT, Offset, true, TargetFlags); } - SDValue getCopyToReg(SDValue Chain, DebugLoc dl, unsigned Reg, SDValue N) { + SDValue getCopyToReg(SDValue Chain, SDLoc dl, unsigned Reg, SDValue N) { return getNode(ISD::CopyToReg, dl, MVT::Other, Chain, getRegister(Reg, N.getValueType()), N); } @@ -450,7 +492,7 @@ public: // This version of the getCopyToReg method takes an extra operand, which // indicates that there is potentially an incoming glue value (if Glue is not // null) and that there should be a glue result. - SDValue getCopyToReg(SDValue Chain, DebugLoc dl, unsigned Reg, SDValue N, + SDValue getCopyToReg(SDValue Chain, SDLoc dl, unsigned Reg, SDValue N, SDValue Glue) { SDVTList VTs = getVTList(MVT::Other, MVT::Glue); SDValue Ops[] = { Chain, getRegister(Reg, N.getValueType()), N, Glue }; @@ -458,14 +500,14 @@ public: } // Similar to last getCopyToReg() except parameter Reg is a SDValue - SDValue getCopyToReg(SDValue Chain, DebugLoc dl, SDValue Reg, SDValue N, + SDValue getCopyToReg(SDValue Chain, SDLoc dl, SDValue Reg, SDValue N, SDValue Glue) { SDVTList VTs = getVTList(MVT::Other, MVT::Glue); SDValue Ops[] = { Chain, Reg, N, Glue }; return getNode(ISD::CopyToReg, dl, VTs, Ops, Glue.getNode() ? 4 : 3); } - SDValue getCopyFromReg(SDValue Chain, DebugLoc dl, unsigned Reg, EVT VT) { + SDValue getCopyFromReg(SDValue Chain, SDLoc dl, unsigned Reg, EVT VT) { SDVTList VTs = getVTList(VT, MVT::Other); SDValue Ops[] = { Chain, getRegister(Reg, VT) }; return getNode(ISD::CopyFromReg, dl, VTs, Ops, 2); @@ -474,7 +516,7 @@ public: // This version of the getCopyFromReg method takes an extra operand, which // indicates that there is potentially an incoming glue value (if Glue is not // null) and that there should be a glue result. - SDValue getCopyFromReg(SDValue Chain, DebugLoc dl, unsigned Reg, EVT VT, + SDValue getCopyFromReg(SDValue Chain, SDLoc dl, unsigned Reg, EVT VT, SDValue Glue) { SDVTList VTs = getVTList(VT, MVT::Other, MVT::Glue); SDValue Ops[] = { Chain, getRegister(Reg, VT), Glue }; @@ -485,7 +527,7 @@ public: /// Returns the ConvertRndSat Note: Avoid using this node because it may /// disappear in the future and most targets don't support it. - SDValue getConvertRndSat(EVT VT, DebugLoc dl, SDValue Val, SDValue DTy, + SDValue getConvertRndSat(EVT VT, SDLoc dl, SDValue Val, SDValue DTy, SDValue STy, SDValue Rnd, SDValue Sat, ISD::CvtCode Code); @@ -493,95 +535,95 @@ public: /// elements in VT, which must be a vector type, must match the number of /// mask elements NumElts. A integer mask element equal to -1 is treated as /// undefined. - SDValue getVectorShuffle(EVT VT, DebugLoc dl, SDValue N1, SDValue N2, + SDValue getVectorShuffle(EVT VT, SDLoc dl, SDValue N1, SDValue N2, const int *MaskElts); /// getAnyExtOrTrunc - Convert Op, which must be of integer type, to the /// integer type VT, by either any-extending or truncating it. - SDValue getAnyExtOrTrunc(SDValue Op, DebugLoc DL, EVT VT); + SDValue getAnyExtOrTrunc(SDValue Op, SDLoc DL, EVT VT); /// getSExtOrTrunc - Convert Op, which must be of integer type, to the /// integer type VT, by either sign-extending or truncating it. - SDValue getSExtOrTrunc(SDValue Op, DebugLoc DL, EVT VT); + SDValue getSExtOrTrunc(SDValue Op, SDLoc DL, EVT VT); /// getZExtOrTrunc - Convert Op, which must be of integer type, to the /// integer type VT, by either zero-extending or truncating it. - SDValue getZExtOrTrunc(SDValue Op, DebugLoc DL, EVT VT); + SDValue getZExtOrTrunc(SDValue Op, SDLoc DL, EVT VT); /// getZeroExtendInReg - Return the expression required to zero extend the Op /// value assuming it was the smaller SrcTy value. - SDValue getZeroExtendInReg(SDValue Op, DebugLoc DL, EVT SrcTy); + SDValue getZeroExtendInReg(SDValue Op, SDLoc DL, EVT SrcTy); /// getNOT - Create a bitwise NOT operation as (XOR Val, -1). - SDValue getNOT(DebugLoc DL, SDValue Val, EVT VT); + SDValue getNOT(SDLoc DL, SDValue Val, EVT VT); /// getCALLSEQ_START - Return a new CALLSEQ_START node, which always must have /// a glue result (to ensure it's not CSE'd). CALLSEQ_START does not have a - /// useful DebugLoc. - SDValue getCALLSEQ_START(SDValue Chain, SDValue Op) { + /// useful SDLoc. + SDValue getCALLSEQ_START(SDValue Chain, SDValue Op, SDLoc DL) { SDVTList VTs = getVTList(MVT::Other, MVT::Glue); SDValue Ops[] = { Chain, Op }; - return getNode(ISD::CALLSEQ_START, DebugLoc(), VTs, Ops, 2); + return getNode(ISD::CALLSEQ_START, DL, VTs, Ops, 2); } /// getCALLSEQ_END - Return a new CALLSEQ_END node, which always must have a /// glue result (to ensure it's not CSE'd). CALLSEQ_END does not have - /// a useful DebugLoc. + /// a useful SDLoc. SDValue getCALLSEQ_END(SDValue Chain, SDValue Op1, SDValue Op2, - SDValue InGlue) { + SDValue InGlue, SDLoc DL) { SDVTList NodeTys = getVTList(MVT::Other, MVT::Glue); SmallVector Ops; Ops.push_back(Chain); Ops.push_back(Op1); Ops.push_back(Op2); Ops.push_back(InGlue); - return getNode(ISD::CALLSEQ_END, DebugLoc(), NodeTys, &Ops[0], + return getNode(ISD::CALLSEQ_END, DL, NodeTys, &Ops[0], (unsigned)Ops.size() - (InGlue.getNode() == 0 ? 1 : 0)); } - /// getUNDEF - Return an UNDEF node. UNDEF does not have a useful DebugLoc. + /// getUNDEF - Return an UNDEF node. UNDEF does not have a useful SDLoc. SDValue getUNDEF(EVT VT) { - return getNode(ISD::UNDEF, DebugLoc(), VT); + return getNode(ISD::UNDEF, SDLoc(), VT); } /// getGLOBAL_OFFSET_TABLE - Return a GLOBAL_OFFSET_TABLE node. This does - /// not have a useful DebugLoc. + /// not have a useful SDLoc. SDValue getGLOBAL_OFFSET_TABLE(EVT VT) { - return getNode(ISD::GLOBAL_OFFSET_TABLE, DebugLoc(), VT); + return getNode(ISD::GLOBAL_OFFSET_TABLE, SDLoc(), VT); } /// getNode - Gets or creates the specified node. /// - SDValue getNode(unsigned Opcode, DebugLoc DL, EVT VT); - SDValue getNode(unsigned Opcode, DebugLoc DL, EVT VT, SDValue N); - SDValue getNode(unsigned Opcode, DebugLoc DL, EVT VT, SDValue N1, SDValue N2); - SDValue getNode(unsigned Opcode, DebugLoc DL, EVT VT, + SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT); + SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT, SDValue N); + SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT, SDValue N1, SDValue N2); + SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT, SDValue N1, SDValue N2, SDValue N3); - SDValue getNode(unsigned Opcode, DebugLoc DL, EVT VT, + SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT, SDValue N1, SDValue N2, SDValue N3, SDValue N4); - SDValue getNode(unsigned Opcode, DebugLoc DL, EVT VT, + SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT, SDValue N1, SDValue N2, SDValue N3, SDValue N4, SDValue N5); - SDValue getNode(unsigned Opcode, DebugLoc DL, EVT VT, + SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT, const SDUse *Ops, unsigned NumOps); - SDValue getNode(unsigned Opcode, DebugLoc DL, EVT VT, + SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT, const SDValue *Ops, unsigned NumOps); - SDValue getNode(unsigned Opcode, DebugLoc DL, + SDValue getNode(unsigned Opcode, SDLoc DL, ArrayRef ResultTys, const SDValue *Ops, unsigned NumOps); - SDValue getNode(unsigned Opcode, DebugLoc DL, const EVT *VTs, unsigned NumVTs, + SDValue getNode(unsigned Opcode, SDLoc DL, const EVT *VTs, unsigned NumVTs, const SDValue *Ops, unsigned NumOps); - SDValue getNode(unsigned Opcode, DebugLoc DL, SDVTList VTs, + SDValue getNode(unsigned Opcode, SDLoc DL, SDVTList VTs, const SDValue *Ops, unsigned NumOps); - SDValue getNode(unsigned Opcode, DebugLoc DL, SDVTList VTs); - SDValue getNode(unsigned Opcode, DebugLoc DL, SDVTList VTs, SDValue N); - SDValue getNode(unsigned Opcode, DebugLoc DL, SDVTList VTs, + SDValue getNode(unsigned Opcode, SDLoc DL, SDVTList VTs); + SDValue getNode(unsigned Opcode, SDLoc DL, SDVTList VTs, SDValue N); + SDValue getNode(unsigned Opcode, SDLoc DL, SDVTList VTs, SDValue N1, SDValue N2); - SDValue getNode(unsigned Opcode, DebugLoc DL, SDVTList VTs, + SDValue getNode(unsigned Opcode, SDLoc DL, SDVTList VTs, SDValue N1, SDValue N2, SDValue N3); - SDValue getNode(unsigned Opcode, DebugLoc DL, SDVTList VTs, + SDValue getNode(unsigned Opcode, SDLoc DL, SDVTList VTs, SDValue N1, SDValue N2, SDValue N3, SDValue N4); - SDValue getNode(unsigned Opcode, DebugLoc DL, SDVTList VTs, + SDValue getNode(unsigned Opcode, SDLoc DL, SDVTList VTs, SDValue N1, SDValue N2, SDValue N3, SDValue N4, SDValue N5); @@ -591,36 +633,50 @@ public: /// clobbered. SDValue getStackArgumentTokenFactor(SDValue Chain); - SDValue getMemcpy(SDValue Chain, DebugLoc dl, SDValue Dst, SDValue Src, + SDValue getMemcpy(SDValue Chain, SDLoc dl, SDValue Dst, SDValue Src, SDValue Size, unsigned Align, bool isVol, bool AlwaysInline, MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo); - SDValue getMemmove(SDValue Chain, DebugLoc dl, SDValue Dst, SDValue Src, + SDValue getMemmove(SDValue Chain, SDLoc dl, SDValue Dst, SDValue Src, SDValue Size, unsigned Align, bool isVol, MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo); - SDValue getMemset(SDValue Chain, DebugLoc dl, SDValue Dst, SDValue Src, + SDValue getMemset(SDValue Chain, SDLoc dl, SDValue Dst, SDValue Src, SDValue Size, unsigned Align, bool isVol, MachinePointerInfo DstPtrInfo); /// getSetCC - Helper function to make it easier to build SetCC's if you just /// have an ISD::CondCode instead of an SDValue. /// - SDValue getSetCC(DebugLoc DL, EVT VT, SDValue LHS, SDValue RHS, + SDValue getSetCC(SDLoc DL, EVT VT, SDValue LHS, SDValue RHS, ISD::CondCode Cond) { assert(LHS.getValueType().isVector() == RHS.getValueType().isVector() && "Cannot compare scalars to vectors"); assert(LHS.getValueType().isVector() == VT.isVector() && "Cannot compare scalars to vectors"); + assert(Cond != ISD::SETCC_INVALID && + "Cannot create a setCC of an invalid node."); return getNode(ISD::SETCC, DL, VT, LHS, RHS, getCondCode(Cond)); } + // getSelect - Helper function to make it easier to build Select's if you just + // have operands and don't want to check for vector. + SDValue getSelect(SDLoc DL, EVT VT, SDValue Cond, + SDValue LHS, SDValue RHS) { + assert(LHS.getValueType() == RHS.getValueType() && + "Cannot use select on differing types"); + assert(VT.isVector() == LHS.getValueType().isVector() && + "Cannot mix vectors and scalars"); + return getNode(Cond.getValueType().isVector() ? ISD::VSELECT : ISD::SELECT, DL, VT, + Cond, LHS, RHS); + } + /// getSelectCC - Helper function to make it easier to build SelectCC's if you /// just have an ISD::CondCode instead of an SDValue. /// - SDValue getSelectCC(DebugLoc DL, SDValue LHS, SDValue RHS, + SDValue getSelectCC(SDLoc DL, SDValue LHS, SDValue RHS, SDValue True, SDValue False, ISD::CondCode Cond) { return getNode(ISD::SELECT_CC, DL, True.getValueType(), LHS, RHS, True, False, getCondCode(Cond)); @@ -628,17 +684,17 @@ public: /// getVAArg - VAArg produces a result and token chain, and takes a pointer /// and a source value as input. - SDValue getVAArg(EVT VT, DebugLoc dl, SDValue Chain, SDValue Ptr, + SDValue getVAArg(EVT VT, SDLoc dl, SDValue Chain, SDValue Ptr, SDValue SV, unsigned Align); /// getAtomic - Gets a node for an atomic op, produces result and chain and /// takes 3 operands - SDValue getAtomic(unsigned Opcode, DebugLoc dl, EVT MemVT, SDValue Chain, + SDValue getAtomic(unsigned Opcode, SDLoc dl, EVT MemVT, SDValue Chain, SDValue Ptr, SDValue Cmp, SDValue Swp, MachinePointerInfo PtrInfo, unsigned Alignment, AtomicOrdering Ordering, SynchronizationScope SynchScope); - SDValue getAtomic(unsigned Opcode, DebugLoc dl, EVT MemVT, SDValue Chain, + SDValue getAtomic(unsigned Opcode, SDLoc dl, EVT MemVT, SDValue Chain, SDValue Ptr, SDValue Cmp, SDValue Swp, MachineMemOperand *MMO, AtomicOrdering Ordering, @@ -646,93 +702,105 @@ public: /// getAtomic - Gets a node for an atomic op, produces result (if relevant) /// and chain and takes 2 operands. - SDValue getAtomic(unsigned Opcode, DebugLoc dl, EVT MemVT, SDValue Chain, + SDValue getAtomic(unsigned Opcode, SDLoc dl, EVT MemVT, SDValue Chain, SDValue Ptr, SDValue Val, const Value* PtrVal, unsigned Alignment, AtomicOrdering Ordering, SynchronizationScope SynchScope); - SDValue getAtomic(unsigned Opcode, DebugLoc dl, EVT MemVT, SDValue Chain, + SDValue getAtomic(unsigned Opcode, SDLoc dl, EVT MemVT, SDValue Chain, SDValue Ptr, SDValue Val, MachineMemOperand *MMO, AtomicOrdering Ordering, SynchronizationScope SynchScope); /// getAtomic - Gets a node for an atomic op, produces result and chain and /// takes 1 operand. - SDValue getAtomic(unsigned Opcode, DebugLoc dl, EVT MemVT, EVT VT, + SDValue getAtomic(unsigned Opcode, SDLoc dl, EVT MemVT, EVT VT, SDValue Chain, SDValue Ptr, const Value* PtrVal, unsigned Alignment, AtomicOrdering Ordering, SynchronizationScope SynchScope); - SDValue getAtomic(unsigned Opcode, DebugLoc dl, EVT MemVT, EVT VT, + SDValue getAtomic(unsigned Opcode, SDLoc dl, EVT MemVT, EVT VT, SDValue Chain, SDValue Ptr, MachineMemOperand *MMO, AtomicOrdering Ordering, SynchronizationScope SynchScope); + /// getAtomic - Gets a node for an atomic op, produces result and chain and + /// takes N operands. + SDValue getAtomic(unsigned Opcode, SDLoc dl, EVT MemVT, SDVTList VTList, + SDValue* Ops, unsigned NumOps, MachineMemOperand *MMO, + AtomicOrdering Ordering, + SynchronizationScope SynchScope); + /// getMemIntrinsicNode - Creates a MemIntrinsicNode that may produce a /// result and takes a list of operands. Opcode may be INTRINSIC_VOID, /// INTRINSIC_W_CHAIN, or a target-specific opcode with a value not /// less than FIRST_TARGET_MEMORY_OPCODE. - SDValue getMemIntrinsicNode(unsigned Opcode, DebugLoc dl, + SDValue getMemIntrinsicNode(unsigned Opcode, SDLoc dl, const EVT *VTs, unsigned NumVTs, const SDValue *Ops, unsigned NumOps, EVT MemVT, MachinePointerInfo PtrInfo, unsigned Align = 0, bool Vol = false, bool ReadMem = true, bool WriteMem = true); - SDValue getMemIntrinsicNode(unsigned Opcode, DebugLoc dl, SDVTList VTList, + SDValue getMemIntrinsicNode(unsigned Opcode, SDLoc dl, SDVTList VTList, const SDValue *Ops, unsigned NumOps, EVT MemVT, MachinePointerInfo PtrInfo, unsigned Align = 0, bool Vol = false, bool ReadMem = true, bool WriteMem = true); - SDValue getMemIntrinsicNode(unsigned Opcode, DebugLoc dl, SDVTList VTList, + SDValue getMemIntrinsicNode(unsigned Opcode, SDLoc dl, SDVTList VTList, const SDValue *Ops, unsigned NumOps, EVT MemVT, MachineMemOperand *MMO); /// getMergeValues - Create a MERGE_VALUES node from the given operands. - SDValue getMergeValues(const SDValue *Ops, unsigned NumOps, DebugLoc dl); + SDValue getMergeValues(const SDValue *Ops, unsigned NumOps, SDLoc dl); /// getLoad - Loads are not normal binary operators: their result type is not /// determined by their operands, and they produce a value AND a token chain. /// - SDValue getLoad(EVT VT, DebugLoc dl, SDValue Chain, SDValue Ptr, + SDValue getLoad(EVT VT, SDLoc dl, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, bool isVolatile, bool isNonTemporal, bool isInvariant, unsigned Alignment, const MDNode *TBAAInfo = 0, const MDNode *Ranges = 0); - SDValue getExtLoad(ISD::LoadExtType ExtType, DebugLoc dl, EVT VT, + SDValue getLoad(EVT VT, SDLoc dl, SDValue Chain, SDValue Ptr, + MachineMemOperand *MMO); + SDValue getExtLoad(ISD::LoadExtType ExtType, SDLoc dl, EVT VT, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, EVT MemVT, bool isVolatile, bool isNonTemporal, unsigned Alignment, const MDNode *TBAAInfo = 0); - SDValue getIndexedLoad(SDValue OrigLoad, DebugLoc dl, SDValue Base, + SDValue getExtLoad(ISD::LoadExtType ExtType, SDLoc dl, EVT VT, + SDValue Chain, SDValue Ptr, EVT MemVT, + MachineMemOperand *MMO); + SDValue getIndexedLoad(SDValue OrigLoad, SDLoc dl, SDValue Base, SDValue Offset, ISD::MemIndexedMode AM); SDValue getLoad(ISD::MemIndexedMode AM, ISD::LoadExtType ExtType, - EVT VT, DebugLoc dl, + EVT VT, SDLoc dl, SDValue Chain, SDValue Ptr, SDValue Offset, MachinePointerInfo PtrInfo, EVT MemVT, bool isVolatile, bool isNonTemporal, bool isInvariant, unsigned Alignment, const MDNode *TBAAInfo = 0, const MDNode *Ranges = 0); SDValue getLoad(ISD::MemIndexedMode AM, ISD::LoadExtType ExtType, - EVT VT, DebugLoc dl, + EVT VT, SDLoc dl, SDValue Chain, SDValue Ptr, SDValue Offset, EVT MemVT, MachineMemOperand *MMO); /// getStore - Helper function to build ISD::STORE nodes. /// - SDValue getStore(SDValue Chain, DebugLoc dl, SDValue Val, SDValue Ptr, + SDValue getStore(SDValue Chain, SDLoc dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, bool isVolatile, bool isNonTemporal, unsigned Alignment, const MDNode *TBAAInfo = 0); - SDValue getStore(SDValue Chain, DebugLoc dl, SDValue Val, SDValue Ptr, + SDValue getStore(SDValue Chain, SDLoc dl, SDValue Val, SDValue Ptr, MachineMemOperand *MMO); - SDValue getTruncStore(SDValue Chain, DebugLoc dl, SDValue Val, SDValue Ptr, + SDValue getTruncStore(SDValue Chain, SDLoc dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, EVT TVT, bool isNonTemporal, bool isVolatile, unsigned Alignment, const MDNode *TBAAInfo = 0); - SDValue getTruncStore(SDValue Chain, DebugLoc dl, SDValue Val, SDValue Ptr, + SDValue getTruncStore(SDValue Chain, SDLoc dl, SDValue Val, SDValue Ptr, EVT TVT, MachineMemOperand *MMO); - SDValue getIndexedStore(SDValue OrigStoe, DebugLoc dl, SDValue Base, + SDValue getIndexedStore(SDValue OrigStoe, SDLoc dl, SDValue Base, SDValue Offset, ISD::MemIndexedMode AM); /// getSrcValue - Construct a node to track a Value* through the backend. @@ -741,6 +809,10 @@ public: /// getMDNode - Return an MDNodeSDNode which holds an MDNode. SDValue getMDNode(const MDNode *MD); + /// getAddrSpaceCast - Return an AddrSpaceCastSDNode. + SDValue getAddrSpaceCast(SDLoc dl, EVT VT, SDValue Ptr, + unsigned SrcAS, unsigned DestAS); + /// getShiftAmountOperand - Return the specified value casted to /// the target's desired shift amount type. SDValue getShiftAmountOperand(EVT LHSTy, SDValue Op); @@ -804,47 +876,47 @@ public: /// Note that getMachineNode returns the resultant node. If there is already /// a node of the specified opcode and operands, it returns that node instead /// of the current one. - MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT); - MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT, + MachineSDNode *getMachineNode(unsigned Opcode, SDLoc dl, EVT VT); + MachineSDNode *getMachineNode(unsigned Opcode, SDLoc dl, EVT VT, SDValue Op1); - MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT, + MachineSDNode *getMachineNode(unsigned Opcode, SDLoc dl, EVT VT, SDValue Op1, SDValue Op2); - MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT, + MachineSDNode *getMachineNode(unsigned Opcode, SDLoc dl, EVT VT, SDValue Op1, SDValue Op2, SDValue Op3); - MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT, + MachineSDNode *getMachineNode(unsigned Opcode, SDLoc dl, EVT VT, ArrayRef Ops); - MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT1, EVT VT2); - MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT1, EVT VT2, + MachineSDNode *getMachineNode(unsigned Opcode, SDLoc dl, EVT VT1, EVT VT2); + MachineSDNode *getMachineNode(unsigned Opcode, SDLoc dl, EVT VT1, EVT VT2, SDValue Op1); - MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT1, EVT VT2, + MachineSDNode *getMachineNode(unsigned Opcode, SDLoc dl, EVT VT1, EVT VT2, SDValue Op1, SDValue Op2); - MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT1, EVT VT2, + MachineSDNode *getMachineNode(unsigned Opcode, SDLoc dl, EVT VT1, EVT VT2, SDValue Op1, SDValue Op2, SDValue Op3); - MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT1, EVT VT2, + MachineSDNode *getMachineNode(unsigned Opcode, SDLoc dl, EVT VT1, EVT VT2, ArrayRef Ops); - MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT1, EVT VT2, + MachineSDNode *getMachineNode(unsigned Opcode, SDLoc dl, EVT VT1, EVT VT2, EVT VT3, SDValue Op1, SDValue Op2); - MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT1, EVT VT2, + MachineSDNode *getMachineNode(unsigned Opcode, SDLoc dl, EVT VT1, EVT VT2, EVT VT3, SDValue Op1, SDValue Op2, SDValue Op3); - MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT1, EVT VT2, + MachineSDNode *getMachineNode(unsigned Opcode, SDLoc dl, EVT VT1, EVT VT2, EVT VT3, ArrayRef Ops); - MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT1, EVT VT2, + MachineSDNode *getMachineNode(unsigned Opcode, SDLoc dl, EVT VT1, EVT VT2, EVT VT3, EVT VT4, ArrayRef Ops); - MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, + MachineSDNode *getMachineNode(unsigned Opcode, SDLoc dl, ArrayRef ResultTys, ArrayRef Ops); - MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, SDVTList VTs, + MachineSDNode *getMachineNode(unsigned Opcode, SDLoc dl, SDVTList VTs, ArrayRef Ops); /// getTargetExtractSubreg - A convenience function for creating /// TargetInstrInfo::EXTRACT_SUBREG nodes. - SDValue getTargetExtractSubreg(int SRIdx, DebugLoc DL, EVT VT, + SDValue getTargetExtractSubreg(int SRIdx, SDLoc DL, EVT VT, SDValue Operand); /// getTargetInsertSubreg - A convenience function for creating /// TargetInstrInfo::INSERT_SUBREG nodes. - SDValue getTargetInsertSubreg(int SRIdx, DebugLoc DL, EVT VT, + SDValue getTargetInsertSubreg(int SRIdx, SDLoc DL, EVT VT, SDValue Operand, SDValue Subreg); /// getNodeIfExists - Get the specified node if it's already available, or @@ -950,12 +1022,6 @@ public: } } - /// AssignOrdering - Assign an order to the SDNode. - void AssignOrdering(const SDNode *SD, unsigned Order); - - /// GetOrdering - Get the order for the SDNode. - unsigned GetOrdering(const SDNode *SD) const; - /// AddDbgValue - Add a dbg_value SDNode. If SD is non-null that means the /// value is produced by SD. void AddDbgValue(SDDbgValue *DB, SDNode *SD, bool isParameter); @@ -998,7 +1064,7 @@ public: /// FoldSetCC - Constant fold a setcc to true or false. SDValue FoldSetCC(EVT VT, SDValue N1, - SDValue N2, ISD::CondCode Cond, DebugLoc dl); + SDValue N2, ISD::CondCode Cond, SDLoc dl); /// SignBitIsZero - Return true if the sign bit of Op is known to be zero. We /// use this predicate to simplify operations downstream. @@ -1064,6 +1130,30 @@ public: /// it cannot be inferred. unsigned InferPtrAlignment(SDValue Ptr) const; + /// GetSplitDestVTs - Compute the VTs needed for the low/hi parts of a type + /// which is split (or expanded) into two not necessarily identical pieces. + std::pair GetSplitDestVTs(const EVT &VT) const; + + /// SplitVector - Split the vector with EXTRACT_SUBVECTOR using the provides + /// VTs and return the low/high part. + std::pair SplitVector(const SDValue &N, const SDLoc &DL, + const EVT &LoVT, const EVT &HiVT); + + /// SplitVector - Split the vector with EXTRACT_SUBVECTOR and return the + /// low/high part. + std::pair SplitVector(const SDValue &N, const SDLoc &DL) { + EVT LoVT, HiVT; + llvm::tie(LoVT, HiVT) = GetSplitDestVTs(N.getValueType()); + return SplitVector(N, DL, LoVT, HiVT); + } + + /// SplitVectorOperand - Split the node's operand with EXTRACT_SUBVECTOR and + /// return the low/high part. + std::pair SplitVectorOperand(const SDNode *N, unsigned OpNo) + { + return SplitVector(N->getOperand(OpNo), SDLoc(N)); + } + private: bool RemoveNodeFromCSEMaps(SDNode *N); void AddModifiedNodeToCSEMaps(SDNode *N); @@ -1072,7 +1162,7 @@ private: void *&InsertPos); SDNode *FindModifiedNodeSlot(SDNode *N, const SDValue *Ops, unsigned NumOps, void *&InsertPos); - SDNode *UpdadeDebugLocOnMergedSDNode(SDNode *N, DebugLoc loc); + SDNode *UpdadeSDLocOnMergedSDNode(SDNode *N, SDLoc loc); void DeleteNodeNotInCSEMaps(SDNode *N); void DeallocateNode(SDNode *N); @@ -1082,7 +1172,7 @@ private: void allnodes_clear(); /// VTList - List of non-single value types. - std::vector VTList; + FoldingSet VTListMap; /// CondCodeNodes - Maps to auto-CSE operations. std::vector CondCodeNodes; diff --git a/contrib/llvm/include/llvm/CodeGen/SelectionDAGISel.h b/contrib/llvm/include/llvm/CodeGen/SelectionDAGISel.h index a4721db68..b5ec8cb07 100644 --- a/contrib/llvm/include/llvm/CodeGen/SelectionDAGISel.h +++ b/contrib/llvm/include/llvm/CodeGen/SelectionDAGISel.h @@ -30,7 +30,6 @@ namespace llvm { class MachineInstr; class TargetLowering; class TargetLibraryInfo; - class TargetInstrInfo; class TargetTransformInfo; class FunctionLoweringInfo; class ScheduleHazardRecognizer; @@ -42,8 +41,7 @@ namespace llvm { /// pattern-matching instruction selectors. class SelectionDAGISel : public MachineFunctionPass { public: - const TargetMachine &TM; - const TargetLowering &TLI; + TargetMachine &TM; const TargetLibraryInfo *LibInfo; const TargetTransformInfo *TTI; FunctionLoweringInfo *FuncInfo; @@ -56,11 +54,13 @@ public: CodeGenOpt::Level OptLevel; static char ID; - explicit SelectionDAGISel(const TargetMachine &tm, + explicit SelectionDAGISel(TargetMachine &tm, CodeGenOpt::Level OL = CodeGenOpt::Default); virtual ~SelectionDAGISel(); - const TargetLowering &getTargetLowering() { return TLI; } + const TargetLowering *getTargetLowering() const { + return TM.getTargetLowering(); + } virtual void getAnalysisUsage(AnalysisUsage &AU) const; @@ -113,6 +113,8 @@ public: OPC_MoveChild, OPC_MoveParent, OPC_CheckSame, + OPC_CheckChild0Same, OPC_CheckChild1Same, + OPC_CheckChild2Same, OPC_CheckChild3Same, OPC_CheckPatternPredicate, OPC_CheckPredicate, OPC_CheckOpcode, diff --git a/contrib/llvm/include/llvm/CodeGen/SelectionDAGNodes.h b/contrib/llvm/include/llvm/CodeGen/SelectionDAGNodes.h index fef567f56..70c15e6c6 100644 --- a/contrib/llvm/include/llvm/CodeGen/SelectionDAGNodes.h +++ b/contrib/llvm/include/llvm/CodeGen/SelectionDAGNodes.h @@ -344,6 +344,13 @@ private: /// debugLoc - source line information. DebugLoc debugLoc; + // The ordering of the SDNodes. It roughly corresponds to the ordering of the + // original LLVM instructions. + // This is used for turning off scheduling, because we'll forgo + // the normal scheduling algorithms and output the instructions according to + // this ordering. + unsigned IROrder; + /// getValueTypeList - Return a pointer to the specified value type. static const EVT *getValueTypeList(EVT VT); @@ -365,7 +372,7 @@ public: /// \ISD namespace). bool isTargetOpcode() const { return NodeType >= ISD::BUILTIN_OP_END; } - /// isTargetMemoryOpcode - Test if this node has a target-specific + /// isTargetMemoryOpcode - Test if this node has a target-specific /// memory-referencing opcode (in the \ISD namespace and /// greater than FIRST_TARGET_MEMORY_OPCODE). bool isTargetMemoryOpcode() const { @@ -412,6 +419,14 @@ public: /// setNodeId - Set unique node id. void setNodeId(int Id) { NodeId = Id; } + /// getIROrder - Return the node ordering. + /// + unsigned getIROrder() const { return IROrder; } + + /// setIROrder - Set the node ordering. + /// + void setIROrder(unsigned Order) { IROrder = Order; } + /// getDebugLoc - Return the source location info. const DebugLoc getDebugLoc() const { return debugLoc; } @@ -505,7 +520,9 @@ public: /// isPredecessorOf - Return true if this node is a predecessor of N. /// NOTE: Implemented on top of hasPredecessor and every bit as /// expensive. Use carefully. - bool isPredecessorOf(const SDNode *N) const { return N->hasPredecessor(this); } + bool isPredecessorOf(const SDNode *N) const { + return N->hasPredecessor(this); + } /// hasPredecessor - Return true if N is a predecessor of this node. /// N is either an operand of this node, or can be reached by recursively @@ -524,7 +541,7 @@ public: /// NOTE: This is still very expensive. Use carefully. bool hasPredecessorHelper(const SDNode *N, SmallPtrSet &Visited, - SmallVector &Worklist) const; + SmallVectorImpl &Worklist) const; /// getNumOperands - Return the number of values used by this operation. /// @@ -681,14 +698,14 @@ protected: return Ret; } - SDNode(unsigned Opc, const DebugLoc dl, SDVTList VTs, const SDValue *Ops, - unsigned NumOps) + SDNode(unsigned Opc, unsigned Order, const DebugLoc dl, SDVTList VTs, + const SDValue *Ops, unsigned NumOps) : NodeType(Opc), OperandsNeedDelete(true), HasDebugValue(false), SubclassData(0), NodeId(-1), OperandList(NumOps ? new SDUse[NumOps] : 0), ValueList(VTs.VTs), UseList(NULL), NumOperands(NumOps), NumValues(VTs.NumVTs), - debugLoc(dl) { + debugLoc(dl), IROrder(Order) { for (unsigned i = 0; i != NumOps; ++i) { OperandList[i].setUser(this); OperandList[i].setInitial(Ops[i]); @@ -698,11 +715,11 @@ protected: /// This constructor adds no operands itself; operands can be /// set later with InitOperands. - SDNode(unsigned Opc, const DebugLoc dl, SDVTList VTs) + SDNode(unsigned Opc, unsigned Order, const DebugLoc dl, SDVTList VTs) : NodeType(Opc), OperandsNeedDelete(false), HasDebugValue(false), - SubclassData(0), NodeId(-1), OperandList(0), ValueList(VTs.VTs), - UseList(NULL), NumOperands(0), NumValues(VTs.NumVTs), - debugLoc(dl) {} + SubclassData(0), NodeId(-1), OperandList(0), + ValueList(VTs.VTs), UseList(NULL), NumOperands(0), NumValues(VTs.NumVTs), + debugLoc(dl), IROrder(Order) {} /// InitOperands - Initialize the operands list of this with 1 operand. void InitOperands(SDUse *Ops, const SDValue &Op0) { @@ -770,6 +787,53 @@ protected: void DropOperands(); }; +/// Wrapper class for IR location info (IR ordering and DebugLoc) to be passed +/// into SDNode creation functions. +/// When an SDNode is created from the DAGBuilder, the DebugLoc is extracted +/// from the original Instruction, and IROrder is the ordinal position of +/// the instruction. +/// When an SDNode is created after the DAG is being built, both DebugLoc and +/// the IROrder are propagated from the original SDNode. +/// So SDLoc class provides two constructors besides the default one, one to +/// be used by the DAGBuilder, the other to be used by others. +class SDLoc { +private: + // Ptr could be used for either Instruction* or SDNode*. It is used for + // Instruction* if IROrder is not -1. + const void *Ptr; + int IROrder; + +public: + SDLoc() : Ptr(NULL), IROrder(0) {} + SDLoc(const SDNode *N) : Ptr(N), IROrder(-1) { + assert(N && "null SDNode"); + } + SDLoc(const SDValue V) : Ptr(V.getNode()), IROrder(-1) { + assert(Ptr && "null SDNode"); + } + SDLoc(const Instruction *I, int Order) : Ptr(I), IROrder(Order) { + assert(Order >= 0 && "bad IROrder"); + } + unsigned getIROrder() { + if (IROrder >= 0 || Ptr == NULL) { + return (unsigned)IROrder; + } + const SDNode *N = (const SDNode*)(Ptr); + return N->getIROrder(); + } + DebugLoc getDebugLoc() { + if (Ptr == NULL) { + return DebugLoc(); + } + if (IROrder >= 0) { + const Instruction *I = (const Instruction*)(Ptr); + return I->getDebugLoc(); + } + const SDNode *N = (const SDNode*)(Ptr); + return N->getDebugLoc(); + } +}; + // Define inline functions from the SDValue class. @@ -839,8 +903,9 @@ inline void SDUse::setNode(SDNode *N) { class UnarySDNode : public SDNode { SDUse Op; public: - UnarySDNode(unsigned Opc, DebugLoc dl, SDVTList VTs, SDValue X) - : SDNode(Opc, dl, VTs) { + UnarySDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTs, + SDValue X) + : SDNode(Opc, Order, dl, VTs) { InitOperands(&Op, X); } }; @@ -850,8 +915,9 @@ public: class BinarySDNode : public SDNode { SDUse Ops[2]; public: - BinarySDNode(unsigned Opc, DebugLoc dl, SDVTList VTs, SDValue X, SDValue Y) - : SDNode(Opc, dl, VTs) { + BinarySDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTs, + SDValue X, SDValue Y) + : SDNode(Opc, Order, dl, VTs) { InitOperands(Ops, X, Y); } }; @@ -861,9 +927,9 @@ public: class TernarySDNode : public SDNode { SDUse Ops[3]; public: - TernarySDNode(unsigned Opc, DebugLoc dl, SDVTList VTs, SDValue X, SDValue Y, - SDValue Z) - : SDNode(Opc, dl, VTs) { + TernarySDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTs, + SDValue X, SDValue Y, SDValue Z) + : SDNode(Opc, Order, dl, VTs) { InitOperands(Ops, X, Y, Z); } }; @@ -876,20 +942,31 @@ public: class HandleSDNode : public SDNode { SDUse Op; public: - // FIXME: Remove the "noinline" attribute once is - // fixed. -#if __GNUC__==4 && __GNUC_MINOR__==2 && defined(__APPLE__) && !defined(__llvm__) - explicit __attribute__((__noinline__)) HandleSDNode(SDValue X) -#else explicit HandleSDNode(SDValue X) -#endif - : SDNode(ISD::HANDLENODE, DebugLoc(), getSDVTList(MVT::Other)) { + : SDNode(ISD::HANDLENODE, 0, DebugLoc(), getSDVTList(MVT::Other)) { InitOperands(&Op, X); } ~HandleSDNode(); const SDValue &getValue() const { return Op; } }; +class AddrSpaceCastSDNode : public UnarySDNode { +private: + unsigned SrcAddrSpace; + unsigned DestAddrSpace; + +public: + AddrSpaceCastSDNode(unsigned Order, DebugLoc dl, EVT VT, SDValue X, + unsigned SrcAS, unsigned DestAS); + + unsigned getSrcAddressSpace() const { return SrcAddrSpace; } + unsigned getDestAddressSpace() const { return DestAddrSpace; } + + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::ADDRSPACECAST; + } +}; + /// Abstact virtual class for operations for memory operations class MemSDNode : public SDNode { private: @@ -901,17 +978,18 @@ protected: MachineMemOperand *MMO; public: - MemSDNode(unsigned Opc, DebugLoc dl, SDVTList VTs, EVT MemoryVT, - MachineMemOperand *MMO); + MemSDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTs, + EVT MemoryVT, MachineMemOperand *MMO); - MemSDNode(unsigned Opc, DebugLoc dl, SDVTList VTs, const SDValue *Ops, + MemSDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTs, + const SDValue *Ops, unsigned NumOps, EVT MemoryVT, MachineMemOperand *MMO); bool readMem() const { return MMO->isLoad(); } bool writeMem() const { return MMO->isStore(); } /// Returns alignment and volatility of the memory access - unsigned getOriginalAlignment() const { + unsigned getOriginalAlignment() const { return MMO->getBaseAlignment(); } unsigned getAlignment() const { @@ -1028,30 +1106,43 @@ public: // Swp: swap value // SrcVal: address to update as a Value (used for MemOperand) // Align: alignment of memory - AtomicSDNode(unsigned Opc, DebugLoc dl, SDVTList VTL, EVT MemVT, + AtomicSDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTL, + EVT MemVT, SDValue Chain, SDValue Ptr, SDValue Cmp, SDValue Swp, MachineMemOperand *MMO, AtomicOrdering Ordering, SynchronizationScope SynchScope) - : MemSDNode(Opc, dl, VTL, MemVT, MMO) { + : MemSDNode(Opc, Order, dl, VTL, MemVT, MMO) { InitAtomic(Ordering, SynchScope); InitOperands(Ops, Chain, Ptr, Cmp, Swp); } - AtomicSDNode(unsigned Opc, DebugLoc dl, SDVTList VTL, EVT MemVT, + AtomicSDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTL, + EVT MemVT, SDValue Chain, SDValue Ptr, SDValue Val, MachineMemOperand *MMO, AtomicOrdering Ordering, SynchronizationScope SynchScope) - : MemSDNode(Opc, dl, VTL, MemVT, MMO) { + : MemSDNode(Opc, Order, dl, VTL, MemVT, MMO) { InitAtomic(Ordering, SynchScope); InitOperands(Ops, Chain, Ptr, Val); } - AtomicSDNode(unsigned Opc, DebugLoc dl, SDVTList VTL, EVT MemVT, + AtomicSDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTL, + EVT MemVT, SDValue Chain, SDValue Ptr, MachineMemOperand *MMO, AtomicOrdering Ordering, SynchronizationScope SynchScope) - : MemSDNode(Opc, dl, VTL, MemVT, MMO) { + : MemSDNode(Opc, Order, dl, VTL, MemVT, MMO) { InitAtomic(Ordering, SynchScope); InitOperands(Ops, Chain, Ptr); } + AtomicSDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTL, EVT MemVT, + SDValue* AllOps, SDUse *DynOps, unsigned NumOps, + MachineMemOperand *MMO, + AtomicOrdering Ordering, SynchronizationScope SynchScope) + : MemSDNode(Opc, Order, dl, VTL, MemVT, MMO) { + InitAtomic(Ordering, SynchScope); + assert((DynOps || NumOps <= array_lengthof(Ops)) && + "Too many ops for internal storage!"); + InitOperands(DynOps ? DynOps : Ops, AllOps, NumOps); + } const SDValue &getBasePtr() const { return getOperand(1); } const SDValue &getVal() const { return getOperand(2); } @@ -1086,10 +1177,10 @@ public: /// with a value not less than FIRST_TARGET_MEMORY_OPCODE. class MemIntrinsicSDNode : public MemSDNode { public: - MemIntrinsicSDNode(unsigned Opc, DebugLoc dl, SDVTList VTs, + MemIntrinsicSDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTs, const SDValue *Ops, unsigned NumOps, EVT MemoryVT, MachineMemOperand *MMO) - : MemSDNode(Opc, dl, VTs, Ops, NumOps, MemoryVT, MMO) { + : MemSDNode(Opc, Order, dl, VTs, Ops, NumOps, MemoryVT, MMO) { } // Methods to support isa and dyn_cast @@ -1119,9 +1210,9 @@ class ShuffleVectorSDNode : public SDNode { const int *Mask; protected: friend class SelectionDAG; - ShuffleVectorSDNode(EVT VT, DebugLoc dl, SDValue N1, SDValue N2, - const int *M) - : SDNode(ISD::VECTOR_SHUFFLE, dl, getSDVTList(VT)), Mask(M) { + ShuffleVectorSDNode(EVT VT, unsigned Order, DebugLoc dl, SDValue N1, + SDValue N2, const int *M) + : SDNode(ISD::VECTOR_SHUFFLE, Order, dl, getSDVTList(VT)), Mask(M) { InitOperands(Ops, N1, N2); } public: @@ -1134,16 +1225,16 @@ public: assert(Idx < getValueType(0).getVectorNumElements() && "Idx out of range!"); return Mask[Idx]; } - + bool isSplat() const { return isSplatMask(Mask, getValueType(0)); } - int getSplatIndex() const { + int getSplatIndex() const { assert(isSplat() && "Cannot get splat index for non-splat!"); EVT VT = getValueType(0); for (unsigned i = 0, e = VT.getVectorNumElements(); i != e; ++i) { - if (Mask[i] != -1) + if (Mask[i] >= 0) return Mask[i]; } - return -1; + llvm_unreachable("Splat with all undef indices?"); } static bool isSplatMask(const int *Mask, EVT VT); @@ -1151,13 +1242,13 @@ public: return N->getOpcode() == ISD::VECTOR_SHUFFLE; } }; - + class ConstantSDNode : public SDNode { const ConstantInt *Value; friend class SelectionDAG; ConstantSDNode(bool isTarget, const ConstantInt *val, EVT VT) : SDNode(isTarget ? ISD::TargetConstant : ISD::Constant, - DebugLoc(), getSDVTList(VT)), Value(val) { + 0, DebugLoc(), getSDVTList(VT)), Value(val) { } public: @@ -1181,7 +1272,7 @@ class ConstantFPSDNode : public SDNode { friend class SelectionDAG; ConstantFPSDNode(bool isTarget, const ConstantFP *val, EVT VT) : SDNode(isTarget ? ISD::TargetConstantFP : ISD::ConstantFP, - DebugLoc(), getSDVTList(VT)), Value(val) { + 0, DebugLoc(), getSDVTList(VT)), Value(val) { } public: @@ -1224,8 +1315,9 @@ class GlobalAddressSDNode : public SDNode { int64_t Offset; unsigned char TargetFlags; friend class SelectionDAG; - GlobalAddressSDNode(unsigned Opc, DebugLoc DL, const GlobalValue *GA, EVT VT, - int64_t o, unsigned char TargetFlags); + GlobalAddressSDNode(unsigned Opc, unsigned Order, DebugLoc DL, + const GlobalValue *GA, EVT VT, int64_t o, + unsigned char TargetFlags); public: const GlobalValue *getGlobal() const { return TheGlobal; } @@ -1247,7 +1339,7 @@ class FrameIndexSDNode : public SDNode { friend class SelectionDAG; FrameIndexSDNode(int fi, EVT VT, bool isTarg) : SDNode(isTarg ? ISD::TargetFrameIndex : ISD::FrameIndex, - DebugLoc(), getSDVTList(VT)), FI(fi) { + 0, DebugLoc(), getSDVTList(VT)), FI(fi) { } public: @@ -1265,7 +1357,7 @@ class JumpTableSDNode : public SDNode { friend class SelectionDAG; JumpTableSDNode(int jti, EVT VT, bool isTarg, unsigned char TF) : SDNode(isTarg ? ISD::TargetJumpTable : ISD::JumpTable, - DebugLoc(), getSDVTList(VT)), JTI(jti), TargetFlags(TF) { + 0, DebugLoc(), getSDVTList(VT)), JTI(jti), TargetFlags(TF) { } public: @@ -1289,23 +1381,22 @@ class ConstantPoolSDNode : public SDNode { friend class SelectionDAG; ConstantPoolSDNode(bool isTarget, const Constant *c, EVT VT, int o, unsigned Align, unsigned char TF) - : SDNode(isTarget ? ISD::TargetConstantPool : ISD::ConstantPool, - DebugLoc(), - getSDVTList(VT)), Offset(o), Alignment(Align), TargetFlags(TF) { + : SDNode(isTarget ? ISD::TargetConstantPool : ISD::ConstantPool, 0, + DebugLoc(), getSDVTList(VT)), Offset(o), Alignment(Align), + TargetFlags(TF) { assert(Offset >= 0 && "Offset is too large"); Val.ConstVal = c; } ConstantPoolSDNode(bool isTarget, MachineConstantPoolValue *v, EVT VT, int o, unsigned Align, unsigned char TF) - : SDNode(isTarget ? ISD::TargetConstantPool : ISD::ConstantPool, - DebugLoc(), - getSDVTList(VT)), Offset(o), Alignment(Align), TargetFlags(TF) { + : SDNode(isTarget ? ISD::TargetConstantPool : ISD::ConstantPool, 0, + DebugLoc(), getSDVTList(VT)), Offset(o), Alignment(Align), + TargetFlags(TF) { assert(Offset >= 0 && "Offset is too large"); Val.MachineCPVal = v; Offset |= 1 << (sizeof(unsigned)*CHAR_BIT-1); } public: - bool isMachineConstantPoolEntry() const { return Offset < 0; @@ -1347,7 +1438,7 @@ class TargetIndexSDNode : public SDNode { public: TargetIndexSDNode(int Idx, EVT VT, int64_t Ofs, unsigned char TF) - : SDNode(ISD::TargetIndex, DebugLoc(), getSDVTList(VT)), + : SDNode(ISD::TargetIndex, 0, DebugLoc(), getSDVTList(VT)), TargetFlags(TF), Index(Idx), Offset(Ofs) {} public: @@ -1367,8 +1458,8 @@ class BasicBlockSDNode : public SDNode { /// blocks out of order when they're jumped to, which makes it a bit /// harder. Let's see if we need it first. explicit BasicBlockSDNode(MachineBasicBlock *mbb) - : SDNode(ISD::BasicBlock, DebugLoc(), getSDVTList(MVT::Other)), MBB(mbb) { - } + : SDNode(ISD::BasicBlock, 0, DebugLoc(), getSDVTList(MVT::Other)), MBB(mbb) + {} public: MachineBasicBlock *getBasicBlock() const { return MBB; } @@ -1411,7 +1502,7 @@ class SrcValueSDNode : public SDNode { friend class SelectionDAG; /// Create a SrcValue for a general value. explicit SrcValueSDNode(const Value *v) - : SDNode(ISD::SRCVALUE, DebugLoc(), getSDVTList(MVT::Other)), V(v) {} + : SDNode(ISD::SRCVALUE, 0, DebugLoc(), getSDVTList(MVT::Other)), V(v) {} public: /// getValue - return the contained Value. @@ -1421,27 +1512,27 @@ public: return N->getOpcode() == ISD::SRCVALUE; } }; - + class MDNodeSDNode : public SDNode { const MDNode *MD; friend class SelectionDAG; explicit MDNodeSDNode(const MDNode *md) - : SDNode(ISD::MDNODE_SDNODE, DebugLoc(), getSDVTList(MVT::Other)), MD(md) {} + : SDNode(ISD::MDNODE_SDNODE, 0, DebugLoc(), getSDVTList(MVT::Other)), MD(md) + {} public: - + const MDNode *getMD() const { return MD; } - + static bool classof(const SDNode *N) { return N->getOpcode() == ISD::MDNODE_SDNODE; } }; - class RegisterSDNode : public SDNode { unsigned Reg; friend class SelectionDAG; RegisterSDNode(unsigned reg, EVT VT) - : SDNode(ISD::Register, DebugLoc(), getSDVTList(VT)), Reg(reg) { + : SDNode(ISD::Register, 0, DebugLoc(), getSDVTList(VT)), Reg(reg) { } public: @@ -1457,7 +1548,7 @@ class RegisterMaskSDNode : public SDNode { const uint32_t *RegMask; friend class SelectionDAG; RegisterMaskSDNode(const uint32_t *mask) - : SDNode(ISD::RegisterMask, DebugLoc(), getSDVTList(MVT::Untyped)), + : SDNode(ISD::RegisterMask, 0, DebugLoc(), getSDVTList(MVT::Untyped)), RegMask(mask) {} public: @@ -1475,7 +1566,7 @@ class BlockAddressSDNode : public SDNode { friend class SelectionDAG; BlockAddressSDNode(unsigned NodeTy, EVT VT, const BlockAddress *ba, int64_t o, unsigned char Flags) - : SDNode(NodeTy, DebugLoc(), getSDVTList(VT)), + : SDNode(NodeTy, 0, DebugLoc(), getSDVTList(VT)), BA(ba), Offset(o), TargetFlags(Flags) { } public: @@ -1493,8 +1584,8 @@ class EHLabelSDNode : public SDNode { SDUse Chain; MCSymbol *Label; friend class SelectionDAG; - EHLabelSDNode(DebugLoc dl, SDValue ch, MCSymbol *L) - : SDNode(ISD::EH_LABEL, dl, getSDVTList(MVT::Other)), Label(L) { + EHLabelSDNode(unsigned Order, DebugLoc dl, SDValue ch, MCSymbol *L) + : SDNode(ISD::EH_LABEL, Order, dl, getSDVTList(MVT::Other)), Label(L) { InitOperands(&Chain, ch); } public: @@ -1508,11 +1599,11 @@ public: class ExternalSymbolSDNode : public SDNode { const char *Symbol; unsigned char TargetFlags; - + friend class SelectionDAG; ExternalSymbolSDNode(bool isTarget, const char *Sym, unsigned char TF, EVT VT) : SDNode(isTarget ? ISD::TargetExternalSymbol : ISD::ExternalSymbol, - DebugLoc(), getSDVTList(VT)), Symbol(Sym), TargetFlags(TF) { + 0, DebugLoc(), getSDVTList(VT)), Symbol(Sym), TargetFlags(TF) { } public: @@ -1529,7 +1620,7 @@ class CondCodeSDNode : public SDNode { ISD::CondCode Condition; friend class SelectionDAG; explicit CondCodeSDNode(ISD::CondCode Cond) - : SDNode(ISD::CONDCODE, DebugLoc(), getSDVTList(MVT::Other)), + : SDNode(ISD::CONDCODE, 0, DebugLoc(), getSDVTList(MVT::Other)), Condition(Cond) { } public: @@ -1540,15 +1631,16 @@ public: return N->getOpcode() == ISD::CONDCODE; } }; - + /// CvtRndSatSDNode - NOTE: avoid using this node as this may disappear in the /// future and most targets don't support it. class CvtRndSatSDNode : public SDNode { ISD::CvtCode CvtCode; friend class SelectionDAG; - explicit CvtRndSatSDNode(EVT VT, DebugLoc dl, const SDValue *Ops, - unsigned NumOps, ISD::CvtCode Code) - : SDNode(ISD::CONVERT_RNDSAT, dl, getSDVTList(VT), Ops, NumOps), + explicit CvtRndSatSDNode(EVT VT, unsigned Order, DebugLoc dl, + const SDValue *Ops, unsigned NumOps, + ISD::CvtCode Code) + : SDNode(ISD::CONVERT_RNDSAT, Order, dl, getSDVTList(VT), Ops, NumOps), CvtCode(Code) { assert(NumOps == 5 && "wrong number of operations"); } @@ -1566,7 +1658,7 @@ class VTSDNode : public SDNode { EVT ValueType; friend class SelectionDAG; explicit VTSDNode(EVT VT) - : SDNode(ISD::VALUETYPE, DebugLoc(), getSDVTList(MVT::Other)), + : SDNode(ISD::VALUETYPE, 0, DebugLoc(), getSDVTList(MVT::Other)), ValueType(VT) { } public: @@ -1589,10 +1681,11 @@ class LSBaseSDNode : public MemSDNode { */ SDUse Ops[4]; public: - LSBaseSDNode(ISD::NodeType NodeTy, DebugLoc dl, SDValue *Operands, - unsigned numOperands, SDVTList VTs, ISD::MemIndexedMode AM, - EVT MemVT, MachineMemOperand *MMO) - : MemSDNode(NodeTy, dl, VTs, MemVT, MMO) { + LSBaseSDNode(ISD::NodeType NodeTy, unsigned Order, DebugLoc dl, + SDValue *Operands, unsigned numOperands, + SDVTList VTs, ISD::MemIndexedMode AM, EVT MemVT, + MachineMemOperand *MMO) + : MemSDNode(NodeTy, Order, dl, VTs, MemVT, MMO) { SubclassData |= AM << 2; assert(getAddressingMode() == AM && "MemIndexedMode encoding error!"); InitOperands(Ops, Operands, numOperands); @@ -1626,11 +1719,10 @@ public: /// class LoadSDNode : public LSBaseSDNode { friend class SelectionDAG; - LoadSDNode(SDValue *ChainPtrOff, DebugLoc dl, SDVTList VTs, + LoadSDNode(SDValue *ChainPtrOff, unsigned Order, DebugLoc dl, SDVTList VTs, ISD::MemIndexedMode AM, ISD::LoadExtType ETy, EVT MemVT, MachineMemOperand *MMO) - : LSBaseSDNode(ISD::LOAD, dl, ChainPtrOff, 3, - VTs, AM, MemVT, MMO) { + : LSBaseSDNode(ISD::LOAD, Order, dl, ChainPtrOff, 3, VTs, AM, MemVT, MMO) { SubclassData |= (unsigned short)ETy; assert(getExtensionType() == ETy && "LoadExtType encoding error!"); assert(readMem() && "Load MachineMemOperand is not a load!"); @@ -1656,10 +1748,10 @@ public: /// class StoreSDNode : public LSBaseSDNode { friend class SelectionDAG; - StoreSDNode(SDValue *ChainValuePtrOff, DebugLoc dl, SDVTList VTs, - ISD::MemIndexedMode AM, bool isTrunc, EVT MemVT, + StoreSDNode(SDValue *ChainValuePtrOff, unsigned Order, DebugLoc dl, + SDVTList VTs, ISD::MemIndexedMode AM, bool isTrunc, EVT MemVT, MachineMemOperand *MMO) - : LSBaseSDNode(ISD::STORE, dl, ChainValuePtrOff, 4, + : LSBaseSDNode(ISD::STORE, Order, dl, ChainValuePtrOff, 4, VTs, AM, MemVT, MMO) { SubclassData |= (unsigned short)isTrunc; assert(isTruncatingStore() == isTrunc && "isTrunc encoding error!"); @@ -1692,8 +1784,8 @@ public: private: friend class SelectionDAG; - MachineSDNode(unsigned Opc, const DebugLoc DL, SDVTList VTs) - : SDNode(Opc, DL, VTs), MemRefs(0), MemRefsEnd(0) {} + MachineSDNode(unsigned Opc, unsigned Order, const DebugLoc DL, SDVTList VTs) + : SDNode(Opc, Order, DL, VTs), MemRefs(0), MemRefsEnd(0) {} /// LocalOperands - Operands for this instruction, if they fit here. If /// they don't, this field is unused. @@ -1781,7 +1873,7 @@ template <> struct GraphTraits { /// LargestSDNode - The largest SDNode class. /// -typedef LoadSDNode LargestSDNode; +typedef AtomicSDNode LargestSDNode; /// MostAlignedSDNode - The SDNode class with the greatest alignment /// requirement. diff --git a/contrib/llvm/include/llvm/CodeGen/SlotIndexes.h b/contrib/llvm/include/llvm/CodeGen/SlotIndexes.h index 26d0433f3..984796af8 100644 --- a/contrib/llvm/include/llvm/CodeGen/SlotIndexes.h +++ b/contrib/llvm/include/llvm/CodeGen/SlotIndexes.h @@ -59,7 +59,7 @@ namespace llvm { // poisoned, so that dangling SlotIndex access can be reliably detected. void setPoison() { intptr_t tmp = reinterpret_cast(mi); - assert(((tmp & 0x1) == 0x0) && "Pointer already poisoned?"); + assert(((tmp & 0x1) == 0x0) && "Pointer already poisoned?"); tmp |= 0x1; mi = reinterpret_cast(tmp); } @@ -162,7 +162,7 @@ namespace llvm { } /// Return true for a valid index. - operator bool() const { return isValid(); } + LLVM_EXPLICIT operator bool() const { return isValid(); } /// Print this index to the given raw_ostream. void print(raw_ostream &os) const; @@ -218,6 +218,13 @@ namespace llvm { return other.getIndex() - getIndex(); } + /// Return the scaled distance from this index to the given one, where all + /// slots on the same instruction have zero distance. + int getInstrDistance(SlotIndex other) const { + return (other.listEntry()->getIndex() - listEntry()->getIndex()) + / Slot_Count; + } + /// isBlock - Returns true if this is a block boundary slot. bool isBlock() const { return getSlot() == Slot_Block; } @@ -672,7 +679,7 @@ namespace llvm { /// performance. Any remaining SlotIndex objects that point to the same /// index are left 'dangling' (much the same as a dangling pointer to a /// freed object) and should not be accessed, except to destruct them. - /// + /// /// Like dangling pointers, access to dangling SlotIndexes can cause /// painful-to-track-down bugs, especially if the memory for the index /// previously pointed to has been re-used. To detect dangling SlotIndex diff --git a/contrib/llvm/include/llvm/CodeGen/StackMaps.h b/contrib/llvm/include/llvm/CodeGen/StackMaps.h new file mode 100644 index 000000000..e90f22e5b --- /dev/null +++ b/contrib/llvm/include/llvm/CodeGen/StackMaps.h @@ -0,0 +1,175 @@ +//===------------------- StackMaps.h - StackMaps ----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_STACKMAPS +#define LLVM_STACKMAPS + +#include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/MachineInstr.h" +#include +#include + +namespace llvm { + +class AsmPrinter; +class MCExpr; + +/// \brief MI-level patchpoint operands. +/// +/// MI patchpoint operations take the form: +/// [], , , , , , ... +/// +/// IR patchpoint intrinsics do not have the operand because calling +/// convention is part of the subclass data. +/// +/// SD patchpoint nodes do not have a def operand because it is part of the +/// SDValue. +/// +/// Patchpoints following the anyregcc convention are handled specially. For +/// these, the stack map also records the location of the return value and +/// arguments. +class PatchPointOpers { +public: + /// Enumerate the meta operands. + enum { IDPos, NBytesPos, TargetPos, NArgPos, CCPos, MetaEnd }; +private: + const MachineInstr *MI; + bool HasDef; + bool IsAnyReg; +public: + explicit PatchPointOpers(const MachineInstr *MI); + + bool isAnyReg() const { return IsAnyReg; } + bool hasDef() const { return HasDef; } + + unsigned getMetaIdx(unsigned Pos = 0) const { + assert(Pos < MetaEnd && "Meta operand index out of range."); + return (HasDef ? 1 : 0) + Pos; + } + + const MachineOperand &getMetaOper(unsigned Pos) { + return MI->getOperand(getMetaIdx(Pos)); + } + + unsigned getArgIdx() const { return getMetaIdx() + MetaEnd; } + + /// Get the operand index of the variable list of non-argument operands. + /// These hold the "live state". + unsigned getVarIdx() const { + return getMetaIdx() + MetaEnd + + MI->getOperand(getMetaIdx(NArgPos)).getImm(); + } + + /// Get the index at which stack map locations will be recorded. + /// Arguments are not recorded unless the anyregcc convention is used. + unsigned getStackMapStartIdx() const { + if (IsAnyReg) + return getArgIdx(); + return getVarIdx(); + } + + /// \brief Get the next scratch register operand index. + unsigned getNextScratchIdx(unsigned StartIdx = 0) const; +}; + +class StackMaps { +public: + struct Location { + enum LocationType { Unprocessed, Register, Direct, Indirect, Constant, + ConstantIndex }; + LocationType LocType; + unsigned Size; + unsigned Reg; + int64_t Offset; + Location() : LocType(Unprocessed), Size(0), Reg(0), Offset(0) {} + Location(LocationType LocType, unsigned Size, unsigned Reg, int64_t Offset) + : LocType(LocType), Size(Size), Reg(Reg), Offset(Offset) {} + }; + + // Typedef a function pointer for functions that parse sequences of operands + // and return a Location, plus a new "next" operand iterator. + typedef std::pair + (*OperandParser)(MachineInstr::const_mop_iterator, + MachineInstr::const_mop_iterator, const TargetMachine&); + + // OpTypes are used to encode information about the following logical + // operand (which may consist of several MachineOperands) for the + // OpParser. + typedef enum { DirectMemRefOp, IndirectMemRefOp, ConstantOp } OpType; + + StackMaps(AsmPrinter &AP, OperandParser OpParser) + : AP(AP), OpParser(OpParser) {} + + /// \brief Generate a stackmap record for a stackmap instruction. + /// + /// MI must be a raw STACKMAP, not a PATCHPOINT. + void recordStackMap(const MachineInstr &MI); + + /// \brief Generate a stackmap record for a patchpoint instruction. + void recordPatchPoint(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. + void serializeToStackMapSection(); + +private: + typedef SmallVector LocationVec; + + struct CallsiteInfo { + const MCExpr *CSOffsetExpr; + unsigned ID; + LocationVec Locations; + CallsiteInfo() : CSOffsetExpr(0), ID(0) {} + CallsiteInfo(const MCExpr *CSOffsetExpr, unsigned ID, + LocationVec Locations) + : CSOffsetExpr(CSOffsetExpr), ID(ID), Locations(Locations) {} + }; + + typedef std::vector CallsiteInfoList; + + struct ConstantPool { + private: + typedef std::map ConstantsMap; + std::vector ConstantsList; + ConstantsMap ConstantIndexes; + + public: + size_t getNumConstants() const { return ConstantsList.size(); } + int64_t getConstant(size_t Idx) const { return ConstantsList[Idx]; } + size_t getConstantIndex(int64_t ConstVal) { + size_t NextIdx = ConstantsList.size(); + ConstantsMap::const_iterator I = + ConstantIndexes.insert(ConstantIndexes.end(), + std::make_pair(ConstVal, NextIdx)); + if (I->second == NextIdx) + ConstantsList.push_back(ConstVal); + return I->second; + } + }; + + AsmPrinter &AP; + OperandParser OpParser; + CallsiteInfoList CSInfos; + ConstantPool ConstPool; + + /// This should be called by the MC lowering code _immediately_ before + /// lowering the MI to an MCInst. It records where the operands for the + /// instruction are stored, and outputs a label to record the offset of + /// the call from the start of the text section. In special cases (e.g. AnyReg + /// calling convention) the return register is also recorded if requested. + void recordStackMapOpers(const MachineInstr &MI, uint32_t ID, + MachineInstr::const_mop_iterator MOI, + MachineInstr::const_mop_iterator MOE, + bool recordResult = false); +}; + +} + +#endif // LLVM_STACKMAPS diff --git a/contrib/llvm/include/llvm/CodeGen/StackProtector.h b/contrib/llvm/include/llvm/CodeGen/StackProtector.h new file mode 100644 index 000000000..d09a933a6 --- /dev/null +++ b/contrib/llvm/include/llvm/CodeGen/StackProtector.h @@ -0,0 +1,127 @@ +//===-- StackProtector.h - Stack Protector Insertion ----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass inserts stack protectors into functions which need them. A variable +// with a random value in it is stored onto the stack before the local variables +// are allocated. Upon exiting the block, the stored value is checked. If it's +// changed, then there was some sort of violation and the program aborts. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_STACKPROTECTOR_H +#define LLVM_CODEGEN_STACKPROTECTOR_H + +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/Triple.h" +#include "llvm/ADT/ValueMap.h" +#include "llvm/Pass.h" +#include "llvm/Target/TargetLowering.h" + +namespace llvm { +class DominatorTree; +class Function; +class Module; +class PHINode; + +class StackProtector : public FunctionPass { +public: + /// SSPLayoutKind. Stack Smashing Protection (SSP) rules require that + /// vulnerable stack allocations are located close the stack protector. + enum SSPLayoutKind { + SSPLK_None, ///< Did not trigger a stack protector. No effect on data + ///< layout. + SSPLK_LargeArray, ///< Array or nested array >= SSP-buffer-size. Closest + ///< to the stack protector. + SSPLK_SmallArray, ///< Array or nested array < SSP-buffer-size. 2nd closest + ///< to the stack protector. + SSPLK_AddrOf ///< The address of this allocation is exposed and + ///< triggered protection. 3rd closest to the protector. + }; + + /// A mapping of AllocaInsts to their required SSP layout. + typedef ValueMap SSPLayoutMap; + +private: + const TargetMachine *TM; + + /// TLI - Keep a pointer of a TargetLowering to consult for determining + /// target type sizes. + const TargetLoweringBase *TLI; + const Triple Trip; + + Function *F; + Module *M; + + DominatorTree *DT; + + /// Layout - Mapping of allocations to the required SSPLayoutKind. + /// StackProtector analysis will update this map when determining if an + /// AllocaInst triggers a stack protector. + SSPLayoutMap Layout; + + /// \brief The minimum size of buffers that will receive stack smashing + /// protection when -fstack-protection is used. + unsigned SSPBufferSize; + + /// VisitedPHIs - The set of PHI nodes visited when determining + /// if a variable's reference has been taken. This set + /// is maintained to ensure we don't visit the same PHI node multiple + /// times. + SmallPtrSet VisitedPHIs; + + /// InsertStackProtectors - Insert code into the prologue and epilogue of + /// the function. + /// + /// - The prologue code loads and stores the stack guard onto the stack. + /// - The epilogue checks the value stored in the prologue against the + /// original value. It calls __stack_chk_fail if they differ. + bool InsertStackProtectors(); + + /// CreateFailBB - Create a basic block to jump to when the stack protector + /// check fails. + BasicBlock *CreateFailBB(); + + /// ContainsProtectableArray - Check whether the type either is an array or + /// contains an array of sufficient size so that we need stack protectors + /// for it. + /// \param [out] IsLarge is set to true if a protectable array is found and + /// it is "large" ( >= ssp-buffer-size). In the case of a structure with + /// multiple arrays, this gets set if any of them is large. + bool ContainsProtectableArray(Type *Ty, bool &IsLarge, bool Strong = false, + bool InStruct = false) const; + + /// \brief Check whether a stack allocation has its address taken. + bool HasAddressTaken(const Instruction *AI); + + /// RequiresStackProtector - Check whether or not this function needs a + /// stack protector based upon the stack protector level. + bool RequiresStackProtector(); + +public: + static char ID; // Pass identification, replacement for typeid. + StackProtector() : FunctionPass(ID), TM(0), TLI(0), SSPBufferSize(0) { + initializeStackProtectorPass(*PassRegistry::getPassRegistry()); + } + StackProtector(const TargetMachine *TM) + : FunctionPass(ID), TM(TM), TLI(0), Trip(TM->getTargetTriple()), + SSPBufferSize(8) { + initializeStackProtectorPass(*PassRegistry::getPassRegistry()); + } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.addPreserved(); + } + + SSPLayoutKind getSSPLayout(const AllocaInst *AI) const; + + virtual bool runOnFunction(Function &Fn); +}; +} // end namespace llvm + +#endif // LLVM_CODEGEN_STACKPROTECTOR_H diff --git a/contrib/llvm/include/llvm/CodeGen/TargetSchedule.h b/contrib/llvm/include/llvm/CodeGen/TargetSchedule.h index 3e22252ee..8ef26b7ca 100644 --- a/contrib/llvm/include/llvm/CodeGen/TargetSchedule.h +++ b/contrib/llvm/include/llvm/CodeGen/TargetSchedule.h @@ -84,9 +84,6 @@ public: /// \brief Maximum number of micro-ops that may be scheduled per cycle. unsigned getIssueWidth() const { return SchedModel.IssueWidth; } - /// \brief Number of cycles the OOO processor is expected to hide. - unsigned getILPWindow() const { return SchedModel.ILPWindow; } - /// \brief Return the number of issue slots required for this MI. unsigned getNumMicroOps(const MachineInstr *MI, const MCSchedClassDesc *SC = 0) const; @@ -131,18 +128,23 @@ public: return ResourceLCM; } + /// \brief Number of micro-ops that may be buffered for OOO execution. + unsigned getMicroOpBufferSize() const { return SchedModel.MicroOpBufferSize; } + + /// \brief Number of resource units that may be buffered for OOO execution. + /// \return The buffer size in resource units or -1 for unlimited. + int getResourceBufferSize(unsigned PIdx) const { + return SchedModel.getProcResource(PIdx)->BufferSize; + } + /// \brief Compute operand latency based on the available machine model. /// - /// Computes and return the latency of the given data dependent def and use + /// Compute and return the latency of the given data dependent def and use /// when the operand indices are already known. UseMI may be NULL for an /// unknown user. - /// - /// FindMin may be set to get the minimum vs. expected latency. Minimum - /// latency is used for scheduling groups, while expected latency is for - /// instruction cost and critical path. unsigned computeOperandLatency(const MachineInstr *DefMI, unsigned DefOperIdx, - const MachineInstr *UseMI, unsigned UseOperIdx, - bool FindMin) const; + const MachineInstr *UseMI, unsigned UseOperIdx) + const; /// \brief Compute the instruction latency based on the available machine /// model. @@ -150,19 +152,19 @@ public: /// Compute and return the expected latency of this instruction independent of /// a particular use. computeOperandLatency is the prefered API, but this is /// occasionally useful to help estimate instruction cost. - unsigned computeInstrLatency(const MachineInstr *MI) const; + /// + /// If UseDefaultDefLatency is false and no new machine sched model is + /// present this method falls back to TII->getInstrLatency with an empty + /// instruction itinerary (this is so we preserve the previous behavior of the + /// if converter after moving it to TargetSchedModel). + unsigned computeInstrLatency(const MachineInstr *MI, + bool UseDefaultDefLatency = true) const; /// \brief Output dependency latency of a pair of defs of the same register. /// /// This is typically one cycle. unsigned computeOutputLatency(const MachineInstr *DefMI, unsigned DefIdx, const MachineInstr *DepMI) const; - -private: - /// getDefLatency is a helper for computeOperandLatency. Return the - /// instruction's latency if operand lookup is not required. - /// Otherwise return -1. - int getDefLatency(const MachineInstr *DefMI, bool FindMin) const; }; } // namespace llvm diff --git a/contrib/llvm/include/llvm/CodeGen/ValueTypes.h b/contrib/llvm/include/llvm/CodeGen/ValueTypes.h index ec48b67b9..79f323341 100644 --- a/contrib/llvm/include/llvm/CodeGen/ValueTypes.h +++ b/contrib/llvm/include/llvm/CodeGen/ValueTypes.h @@ -27,9 +27,9 @@ namespace llvm { class LLVMContext; struct EVT; - /// MVT - Machine Value Type. Every type that is supported natively by some - /// processor targeted by LLVM occurs here. This means that any legal value - /// type can be represented by a MVT. + /// MVT - Machine Value Type. Every type that is supported natively by some + /// processor targeted by LLVM occurs here. This means that any legal value + /// type can be represented by an MVT. class MVT { public: enum SimpleValueType { @@ -67,40 +67,45 @@ namespace llvm { v32i1 = 17, // 32 x i1 v64i1 = 18, // 64 x i1 - v2i8 = 19, // 2 x i8 - v4i8 = 20, // 4 x i8 - v8i8 = 21, // 8 x i8 - v16i8 = 22, // 16 x i8 - v32i8 = 23, // 32 x i8 - v64i8 = 24, // 64 x i8 - v1i16 = 25, // 1 x i16 - v2i16 = 26, // 2 x i16 - v4i16 = 27, // 4 x i16 - v8i16 = 28, // 8 x i16 - v16i16 = 29, // 16 x i16 - v32i16 = 30, // 32 x i16 - v1i32 = 31, // 1 x i32 - v2i32 = 32, // 2 x i32 - v4i32 = 33, // 4 x i32 - v8i32 = 34, // 8 x i32 - v16i32 = 35, // 16 x i32 - v1i64 = 36, // 1 x i64 - v2i64 = 37, // 2 x i64 - v4i64 = 38, // 4 x i64 - v8i64 = 39, // 8 x i64 - v16i64 = 40, // 16 x i64 + v1i8 = 19, // 1 x i8 + v2i8 = 20, // 2 x i8 + v4i8 = 21, // 4 x i8 + v8i8 = 22, // 8 x i8 + v16i8 = 23, // 16 x i8 + v32i8 = 24, // 32 x i8 + v64i8 = 25, // 64 x i8 + v1i16 = 26, // 1 x i16 + v2i16 = 27, // 2 x i16 + v4i16 = 28, // 4 x i16 + v8i16 = 29, // 8 x i16 + v16i16 = 30, // 16 x i16 + v32i16 = 31, // 32 x i16 + v1i32 = 32, // 1 x i32 + v2i32 = 33, // 2 x i32 + v4i32 = 34, // 4 x i32 + v8i32 = 35, // 8 x i32 + v16i32 = 36, // 16 x i32 + v1i64 = 37, // 1 x i64 + v2i64 = 38, // 2 x i64 + v4i64 = 39, // 4 x i64 + v8i64 = 40, // 8 x i64 + v16i64 = 41, // 16 x i64 FIRST_INTEGER_VECTOR_VALUETYPE = v2i1, LAST_INTEGER_VECTOR_VALUETYPE = v16i64, - v2f16 = 41, // 2 x f16 - v2f32 = 42, // 2 x f32 - v4f32 = 43, // 4 x f32 - v8f32 = 44, // 8 x f32 - v16f32 = 45, // 16 x f32 - v2f64 = 46, // 2 x f64 - v4f64 = 47, // 4 x f64 - v8f64 = 48, // 8 x f64 + v2f16 = 42, // 2 x f16 + v4f16 = 43, // 4 x f16 + v8f16 = 44, // 8 x f16 + v1f32 = 45, // 1 x f32 + v2f32 = 46, // 2 x f32 + v4f32 = 47, // 4 x f32 + v8f32 = 48, // 8 x f32 + v16f32 = 49, // 16 x f32 + v1f64 = 50, // 1 x f64 + v2f64 = 51, // 2 x f64 + v4f64 = 52, // 4 x f64 + v8f64 = 53, // 8 x f64 FIRST_FP_VECTOR_VALUETYPE = v2f16, LAST_FP_VECTOR_VALUETYPE = v8f64, @@ -108,17 +113,17 @@ namespace llvm { FIRST_VECTOR_VALUETYPE = v2i1, LAST_VECTOR_VALUETYPE = v8f64, - x86mmx = 49, // This is an X86 MMX value + x86mmx = 54, // This is an X86 MMX value - Glue = 50, // This glues nodes together during pre-RA sched + Glue = 55, // This glues nodes together during pre-RA sched - isVoid = 51, // This has no value + isVoid = 56, // This has no value - Untyped = 52, // This value takes a register, but has + Untyped = 57, // This value takes a register, but has // unspecified type. The register class // will be determined by the opcode. - LAST_VALUETYPE = 53, // This always remains at the end of the list. + LAST_VALUETYPE = 58, // This always remains at the end of the list. // This is the current maximum for LAST_VALUETYPE. // MVT::MAX_ALLOWED_VALUETYPE is used for asserts and to size bit vectors @@ -203,7 +208,7 @@ namespace llvm { bool is64BitVector() const { return (SimpleTy == MVT::v8i8 || SimpleTy == MVT::v4i16 || SimpleTy == MVT::v2i32 || SimpleTy == MVT::v1i64 || - SimpleTy == MVT::v2f32); + SimpleTy == MVT::v1f64 || SimpleTy == MVT::v2f32); } /// is128BitVector - Return true if this is a 128-bit vector type. @@ -265,6 +270,7 @@ namespace llvm { case v16i1 : case v32i1 : case v64i1: return i1; + case v1i8 : case v2i8 : case v4i8 : case v8i8 : @@ -287,11 +293,15 @@ namespace llvm { case v4i64: case v8i64: case v16i64: return i64; - case v2f16: return f16; + case v2f16: + case v4f16: + case v8f16: return f16; + case v1f32: case v2f32: case v4f32: case v8f32: case v16f32: return f32; + case v1f64: case v2f64: case v4f64: case v8f64: return f64; @@ -318,6 +328,7 @@ namespace llvm { case v8i16: case v8i32: case v8i64: + case v8f16: case v8f32: case v8f64: return 8; case v4i1: @@ -325,6 +336,7 @@ namespace llvm { case v4i16: case v4i32: case v4i64: + case v4f16: case v4f32: case v4f64: return 4; case v2i1: @@ -335,14 +347,21 @@ namespace llvm { case v2f16: case v2f32: case v2f64: return 2; + case v1i8: case v1i16: case v1i32: - case v1i64: return 1; + case v1i64: + case v1f32: + case v1f64: return 1; } } unsigned getSizeInBits() const { switch (SimpleTy) { + default: + llvm_unreachable("getSizeInBits called on extended MVT."); + case Other: + llvm_unreachable("Value type is non-standard value, Other."); case iPTR: llvm_unreachable("Value type size is target-dependent. Ask TLI."); case iPTRAny: @@ -352,12 +371,11 @@ namespace llvm { llvm_unreachable("Value type is overloaded."); case Metadata: llvm_unreachable("Value type is metadata."); - default: - llvm_unreachable("getSizeInBits called on extended MVT."); case i1 : return 1; case v2i1: return 2; case v4i1: return 4; case i8 : + case v1i8: case v8i1: return 8; case i16 : case f16: @@ -370,6 +388,7 @@ namespace llvm { case v4i8: case v2i16: case v2f16: + case v1f32: case v1i32: return 32; case x86mmx: case f64 : @@ -379,7 +398,9 @@ namespace llvm { case v4i16: case v2i32: case v1i64: - case v2f32: return 64; + case v4f16: + case v2f32: + case v1f64: return 64; case f80 : return 80; case f128: case ppcf128: @@ -388,6 +409,7 @@ namespace llvm { case v8i16: case v4i32: case v2i64: + case v8f16: case v4f32: case v2f64: return 128; case v32i8: @@ -488,6 +510,7 @@ namespace llvm { if (NumElements == 64) return MVT::v64i1; break; case MVT::i8: + if (NumElements == 1) return MVT::v1i8; if (NumElements == 2) return MVT::v2i8; if (NumElements == 4) return MVT::v4i8; if (NumElements == 8) return MVT::v8i8; @@ -519,14 +542,18 @@ namespace llvm { break; case MVT::f16: if (NumElements == 2) return MVT::v2f16; + if (NumElements == 4) return MVT::v4f16; + if (NumElements == 8) return MVT::v8f16; break; case MVT::f32: + if (NumElements == 1) return MVT::v1f32; if (NumElements == 2) return MVT::v2f32; if (NumElements == 4) return MVT::v4f32; if (NumElements == 8) return MVT::v8f32; if (NumElements == 16) return MVT::v16f32; break; case MVT::f64: + if (NumElements == 1) return MVT::v1f64; if (NumElements == 2) return MVT::v2f64; if (NumElements == 4) return MVT::v4f64; if (NumElements == 8) return MVT::v8f64; diff --git a/contrib/llvm/include/llvm/CodeGen/ValueTypes.td b/contrib/llvm/include/llvm/CodeGen/ValueTypes.td index da2698594..b5fa0e8c6 100644 --- a/contrib/llvm/include/llvm/CodeGen/ValueTypes.td +++ b/contrib/llvm/include/llvm/CodeGen/ValueTypes.td @@ -26,7 +26,7 @@ def i16 : ValueType<16 , 3>; // 16-bit integer value def i32 : ValueType<32 , 4>; // 32-bit integer value def i64 : ValueType<64 , 5>; // 64-bit integer value def i128 : ValueType<128, 6>; // 128-bit integer value -def f16 : ValueType<16 , 7>; // 32-bit floating point value +def f16 : ValueType<16 , 7>; // 16-bit floating point value def f32 : ValueType<32 , 8>; // 32-bit floating point value def f64 : ValueType<64 , 9>; // 64-bit floating point value def f80 : ValueType<80 , 10>; // 80-bit floating point value @@ -39,43 +39,48 @@ def v8i1 : ValueType<8 , 15>; // 8 x i1 vector value def v16i1 : ValueType<16, 16>; // 16 x i1 vector value def v32i1 : ValueType<32 , 17>; // 32 x i1 vector value def v64i1 : ValueType<64 , 18>; // 64 x i1 vector value -def v2i8 : ValueType<16 , 19>; // 2 x i8 vector value -def v4i8 : ValueType<32 , 20>; // 4 x i8 vector value -def v8i8 : ValueType<64 , 21>; // 8 x i8 vector value -def v16i8 : ValueType<128, 22>; // 16 x i8 vector value -def v32i8 : ValueType<256, 23>; // 32 x i8 vector value -def v64i8 : ValueType<512, 24>; // 64 x i8 vector value -def v1i16 : ValueType<16 , 25>; // 1 x i16 vector value -def v2i16 : ValueType<32 , 26>; // 2 x i16 vector value -def v4i16 : ValueType<64 , 27>; // 4 x i16 vector value -def v8i16 : ValueType<128, 28>; // 8 x i16 vector value -def v16i16 : ValueType<256, 29>; // 16 x i16 vector value -def v32i16 : ValueType<512, 30>; // 32 x i16 vector value -def v1i32 : ValueType<32 , 31>; // 1 x i32 vector value -def v2i32 : ValueType<64 , 32>; // 2 x i32 vector value -def v4i32 : ValueType<128, 33>; // 4 x i32 vector value -def v8i32 : ValueType<256, 34>; // 8 x i32 vector value -def v16i32 : ValueType<512, 35>; // 16 x i32 vector value -def v1i64 : ValueType<64 , 36>; // 1 x i64 vector value -def v2i64 : ValueType<128, 37>; // 2 x i64 vector value -def v4i64 : ValueType<256, 38>; // 4 x i64 vector value -def v8i64 : ValueType<512, 39>; // 8 x i64 vector value -def v16i64 : ValueType<1024,40>; // 16 x i64 vector value +def v1i8 : ValueType<16, 19>; // 1 x i8 vector value +def v2i8 : ValueType<16 , 20>; // 2 x i8 vector value +def v4i8 : ValueType<32 , 21>; // 4 x i8 vector value +def v8i8 : ValueType<64 , 22>; // 8 x i8 vector value +def v16i8 : ValueType<128, 23>; // 16 x i8 vector value +def v32i8 : ValueType<256, 24>; // 32 x i8 vector value +def v64i8 : ValueType<512, 25>; // 64 x i8 vector value +def v1i16 : ValueType<16 , 26>; // 1 x i16 vector value +def v2i16 : ValueType<32 , 27>; // 2 x i16 vector value +def v4i16 : ValueType<64 , 28>; // 4 x i16 vector value +def v8i16 : ValueType<128, 29>; // 8 x i16 vector value +def v16i16 : ValueType<256, 30>; // 16 x i16 vector value +def v32i16 : ValueType<512, 31>; // 32 x i16 vector value +def v1i32 : ValueType<32 , 32>; // 1 x i32 vector value +def v2i32 : ValueType<64 , 33>; // 2 x i32 vector value +def v4i32 : ValueType<128, 34>; // 4 x i32 vector value +def v8i32 : ValueType<256, 35>; // 8 x i32 vector value +def v16i32 : ValueType<512, 36>; // 16 x i32 vector value +def v1i64 : ValueType<64 , 37>; // 1 x i64 vector value +def v2i64 : ValueType<128, 38>; // 2 x i64 vector value +def v4i64 : ValueType<256, 39>; // 4 x i64 vector value +def v8i64 : ValueType<512, 40>; // 8 x i64 vector value +def v16i64 : ValueType<1024,41>; // 16 x i64 vector value -def v2f16 : ValueType<32 , 41>; // 2 x f16 vector value -def v2f32 : ValueType<64 , 42>; // 2 x f32 vector value -def v4f32 : ValueType<128, 43>; // 4 x f32 vector value -def v8f32 : ValueType<256, 44>; // 8 x f32 vector value -def v16f32 : ValueType<512, 45>; // 16 x f32 vector value -def v2f64 : ValueType<128, 46>; // 2 x f64 vector value -def v4f64 : ValueType<256, 47>; // 4 x f64 vector value -def v8f64 : ValueType<512, 48>; // 8 x f64 vector value +def v2f16 : ValueType<32 , 42>; // 2 x f16 vector value +def v4f16 : ValueType<64 , 43>; // 4 x f16 vector value +def v8f16 : ValueType<128, 44>; // 8 x f16 vector value +def v1f32 : ValueType<32 , 45>; // 1 x f32 vector value +def v2f32 : ValueType<64 , 46>; // 2 x f32 vector value +def v4f32 : ValueType<128, 47>; // 4 x f32 vector value +def v8f32 : ValueType<256, 48>; // 8 x f32 vector value +def v16f32 : ValueType<512, 49>; // 16 x f32 vector value +def v1f64 : ValueType<64, 50>; // 1 x f64 vector value +def v2f64 : ValueType<128, 51>; // 2 x f64 vector value +def v4f64 : ValueType<256, 52>; // 4 x f64 vector value +def v8f64 : ValueType<512, 53>; // 8 x f64 vector value -def x86mmx : ValueType<64 , 49>; // X86 MMX value -def FlagVT : ValueType<0 , 50>; // Pre-RA sched glue -def isVoid : ValueType<0 , 51>; // Produces no value -def untyped: ValueType<8 , 52>; // Produces an untyped value +def x86mmx : ValueType<64 , 54>; // X86 MMX value +def FlagVT : ValueType<0 , 55>; // Pre-RA sched glue +def isVoid : ValueType<0 , 56>; // Produces no value +def untyped: ValueType<8 , 57>; // Produces an untyped value def MetadataVT: ValueType<0, 250>; // Metadata // Pseudo valuetype mapped to the current pointer size to any address space. diff --git a/contrib/llvm/include/llvm/DIBuilder.h b/contrib/llvm/include/llvm/DIBuilder.h index 2c0f712a9..bac16795f 100644 --- a/contrib/llvm/include/llvm/DIBuilder.h +++ b/contrib/llvm/include/llvm/DIBuilder.h @@ -17,7 +17,9 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" +#include "llvm/DebugInfo.h" #include "llvm/Support/DataTypes.h" +#include "llvm/Support/ValueHandle.h" namespace llvm { class BasicBlock; @@ -29,6 +31,7 @@ namespace llvm { class MDNode; class StringRef; class DIBasicType; + class DICompileUnit; class DICompositeType; class DIDerivedType; class DIDescriptor; @@ -37,7 +40,7 @@ namespace llvm { class DIType; class DIArray; class DIGlobalVariable; - class DIImportedModule; + class DIImportedEntity; class DINameSpace; class DIVariable; class DISubrange; @@ -53,7 +56,6 @@ namespace llvm { private: Module &M; LLVMContext & VMContext; - MDNode *TheCU; MDNode *TempEnumTypes; MDNode *TempRetainTypes; @@ -65,17 +67,24 @@ namespace llvm { Function *ValueFn; // llvm.dbg.value SmallVector AllEnumTypes; - SmallVector AllRetainTypes; + /// Use TrackingVH to collect RetainTypes, since they can be updated + /// later on. + SmallVector, 4> AllRetainTypes; SmallVector AllSubprograms; SmallVector AllGVs; SmallVector AllImportedModules; + DITemplateValueParameter + createTemplateValueParameter(unsigned Tag, DIDescriptor Scope, + StringRef Name, DIType Ty, Value *Val, + MDNode *File = 0, unsigned LineNo = 0, + unsigned ColumnNo = 0); + DIBuilder(const DIBuilder &) LLVM_DELETED_FUNCTION; void operator=(const DIBuilder &) LLVM_DELETED_FUNCTION; public: explicit DIBuilder(Module &M); - const MDNode *getCU() { return TheCU; } enum ComplexAddrKind { OpPlus=1, OpDeref }; /// finalize - Construct any deferred debug info descriptors. @@ -97,20 +106,24 @@ namespace llvm { /// Objective-C. /// @param SplitName The name of the file that we'll split debug info out /// into. - void createCompileUnit(unsigned Lang, StringRef File, StringRef Dir, - StringRef Producer, bool isOptimized, - StringRef Flags, unsigned RV, - StringRef SplitName = StringRef()); + DICompileUnit createCompileUnit(unsigned Lang, StringRef File, + StringRef Dir, StringRef Producer, + bool isOptimized, StringRef Flags, + unsigned RV, + StringRef SplitName = StringRef()); /// createFile - Create a file descriptor to hold debugging information /// for a file. DIFile createFile(StringRef Filename, StringRef Directory); /// createEnumerator - Create a single enumerator value. - DIEnumerator createEnumerator(StringRef Name, uint64_t Val); + DIEnumerator createEnumerator(StringRef Name, int64_t Val); + + /// \brief Create a DWARF unspecified type. + DIBasicType createUnspecifiedType(StringRef Name); - /// createNullPtrType - Create C++0x nullptr type. - DIType createNullPtrType(StringRef Name); + /// \brief Create C++11 nullptr type. + DIBasicType createNullPtrType(); /// createBasicType - Create debugging information entry for a basic /// type. @@ -155,7 +168,7 @@ namespace llvm { unsigned LineNo, DIDescriptor Context); /// createFriend - Create debugging information entry for a 'friend'. - DIType createFriend(DIType Ty, DIType FriendTy); + DIDerivedType createFriend(DIType Ty, DIType FriendTy); /// createInheritance - Create debugging information entry to establish /// inheritance relationship between two types. @@ -191,9 +204,10 @@ namespace llvm { /// @param Ty Type of the static member. /// @param Flags Flags to encode member attribute, e.g. private. /// @param Val Const initializer of the member. - DIType createStaticMemberType(DIDescriptor Scope, StringRef Name, - DIFile File, unsigned LineNo, DIType Ty, - unsigned Flags, llvm::Value *Val); + DIDerivedType + createStaticMemberType(DIDescriptor Scope, StringRef Name, + DIFile File, unsigned LineNo, DIType Ty, + unsigned Flags, llvm::Value *Val); /// createObjCIVar - Create debugging information entry for Objective-C /// instance variable. @@ -212,14 +226,14 @@ namespace llvm { /// @param PropertySetterName Name of the Objective C property setter /// selector. /// @param PropertyAttributes Objective C property attributes. - DIType createObjCIVar(StringRef Name, DIFile File, - unsigned LineNo, uint64_t SizeInBits, - uint64_t AlignInBits, uint64_t OffsetInBits, - unsigned Flags, DIType Ty, - StringRef PropertyName = StringRef(), - StringRef PropertyGetterName = StringRef(), - StringRef PropertySetterName = StringRef(), - unsigned PropertyAttributes = 0); + DIDerivedType createObjCIVar(StringRef Name, DIFile File, + unsigned LineNo, uint64_t SizeInBits, + uint64_t AlignInBits, uint64_t OffsetInBits, + unsigned Flags, DIType Ty, + StringRef PropertyName = StringRef(), + StringRef PropertyGetterName = StringRef(), + StringRef PropertySetterName = StringRef(), + unsigned PropertyAttributes = 0); /// createObjCIVar - Create debugging information entry for Objective-C /// instance variable. @@ -232,11 +246,11 @@ namespace llvm { /// @param Flags Flags to encode member attribute, e.g. private /// @param Ty Parent type. /// @param PropertyNode Property associated with this ivar. - DIType createObjCIVar(StringRef Name, DIFile File, - unsigned LineNo, uint64_t SizeInBits, - uint64_t AlignInBits, uint64_t OffsetInBits, - unsigned Flags, DIType Ty, - MDNode *PropertyNode); + DIDerivedType createObjCIVar(StringRef Name, DIFile File, + unsigned LineNo, uint64_t SizeInBits, + uint64_t AlignInBits, uint64_t OffsetInBits, + unsigned Flags, DIType Ty, + MDNode *PropertyNode); /// createObjCProperty - Create debugging information entry for Objective-C /// property. @@ -269,13 +283,15 @@ namespace llvm { /// DW_AT_containing_type. See DWARF documentation /// for more info. /// @param TemplateParms Template type parameters. + /// @param UniqueIdentifier A unique identifier for the class. DICompositeType createClassType(DIDescriptor Scope, StringRef Name, DIFile File, unsigned LineNumber, uint64_t SizeInBits, uint64_t AlignInBits, uint64_t OffsetInBits, unsigned Flags, DIType DerivedFrom, DIArray Elements, - MDNode *VTableHolder = 0, - MDNode *TemplateParms = 0); + DIType VTableHolder = DIType(), + MDNode *TemplateParms = 0, + StringRef UniqueIdentifier = StringRef()); /// createStructType - Create debugging information entry for a struct. /// @param Scope Scope in which this struct is defined. @@ -287,12 +303,14 @@ namespace llvm { /// @param Flags Flags to encode member attribute, e.g. private /// @param Elements Struct elements. /// @param RunTimeLang Optional parameter, Objective-C runtime version. + /// @param UniqueIdentifier A unique identifier for the struct. DICompositeType createStructType(DIDescriptor Scope, StringRef Name, DIFile File, unsigned LineNumber, uint64_t SizeInBits, uint64_t AlignInBits, unsigned Flags, DIType DerivedFrom, DIArray Elements, unsigned RunTimeLang = 0, - MDNode *VTableHolder = 0); + DIType VTableHolder = DIType(), + StringRef UniqueIdentifier = StringRef()); /// createUnionType - Create debugging information entry for an union. /// @param Scope Scope in which this union is defined. @@ -304,10 +322,12 @@ namespace llvm { /// @param Flags Flags to encode member attribute, e.g. private /// @param Elements Union elements. /// @param RunTimeLang Optional parameter, Objective-C runtime version. + /// @param UniqueIdentifier A unique identifier for the union. DICompositeType createUnionType( DIDescriptor Scope, StringRef Name, DIFile File, unsigned LineNumber, uint64_t SizeInBits, uint64_t AlignInBits, unsigned Flags, - DIArray Elements, unsigned RunTimeLang = 0); + DIArray Elements, unsigned RunTimeLang = 0, + StringRef UniqueIdentifier = StringRef()); /// createTemplateTypeParameter - Create debugging information for template /// type parameter. @@ -327,15 +347,40 @@ namespace llvm { /// @param Scope Scope in which this type is defined. /// @param Name Value parameter name. /// @param Ty Parameter type. - /// @param Value Constant parameter value. + /// @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, - uint64_t Value, - MDNode *File = 0, unsigned LineNo = 0, - unsigned ColumnNo = 0); + createTemplateValueParameter(DIDescriptor Scope, StringRef Name, + DIType Ty, Value *Val, MDNode *File = 0, + unsigned LineNo = 0, unsigned ColumnNo = 0); + + /// \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 = 0, + unsigned LineNo = 0, unsigned ColumnNo = 0); + + /// \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 = 0, + unsigned LineNo = 0, unsigned ColumnNo = 0); /// createArrayType - Create debugging information entry for an array. /// @param Size Array size. @@ -350,8 +395,8 @@ namespace llvm { /// @param AlignInBits Alignment. /// @param Ty Element type. /// @param Subscripts Subscripts. - DIType createVectorType(uint64_t Size, uint64_t AlignInBits, - DIType Ty, DIArray Subscripts); + DICompositeType createVectorType(uint64_t Size, uint64_t AlignInBits, + DIType Ty, DIArray Subscripts); /// createEnumerationType - Create debugging information entry for an /// enumeration. @@ -363,12 +408,11 @@ namespace llvm { /// @param AlignInBits Member alignment. /// @param Elements Enumeration elements. /// @param UnderlyingType Underlying type of a C++11/ObjC fixed enum. + /// @param UniqueIdentifier A unique identifier for the enum. DICompositeType createEnumerationType(DIDescriptor Scope, StringRef Name, - DIFile File, unsigned LineNumber, - uint64_t SizeInBits, - uint64_t AlignInBits, - DIArray Elements, - DIType UnderlyingType); + DIFile File, unsigned LineNumber, uint64_t SizeInBits, + uint64_t AlignInBits, DIArray Elements, DIType UnderlyingType, + StringRef UniqueIdentifier = StringRef()); /// createSubroutineType - Create subroutine type. /// @param File File in which this subroutine is defined. @@ -384,9 +428,12 @@ namespace llvm { DIType createObjectPointerType(DIType Ty); /// createForwardDecl - Create a temporary forward-declared type. - DIType createForwardDecl(unsigned Tag, StringRef Name, DIDescriptor Scope, - DIFile F, unsigned Line, unsigned RuntimeLang = 0, - uint64_t SizeInBits = 0, uint64_t AlignInBits = 0); + DICompositeType createForwardDecl(unsigned Tag, StringRef Name, + DIDescriptor Scope, DIFile F, + unsigned Line, unsigned RuntimeLang = 0, + uint64_t SizeInBits = 0, + uint64_t AlignInBits = 0, + StringRef UniqueIdentifier = StringRef()); /// retainType - Retain DIType in a module even if it is not referenced /// through debug info anchors. @@ -460,7 +507,7 @@ namespace llvm { /// @param AlwaysPreserve Boolean. Set to true if debug info for this /// variable should be preserved in optimized build. /// @param Flags Flags, e.g. artificial variable. - /// @param ArgNo If this variable is an arugment then this argument's + /// @param ArgNo If this variable is an argument then this argument's /// number. 1 indicates 1st argument. DIVariable createLocalVariable(unsigned Tag, DIDescriptor Scope, StringRef Name, @@ -480,7 +527,7 @@ namespace llvm { /// @param LineNo Line number. /// @param Ty Variable Type /// @param Addr An array of complex address operations. - /// @param ArgNo If this variable is an arugment then this argument's + /// @param ArgNo If this variable is an argument then this argument's /// number. 1 indicates 1st argument. DIVariable createComplexVariable(unsigned Tag, DIDescriptor Scope, StringRef Name, DIFile F, unsigned LineNo, @@ -506,7 +553,21 @@ namespace llvm { DISubprogram createFunction(DIDescriptor Scope, StringRef Name, StringRef LinkageName, DIFile File, unsigned LineNo, - DIType Ty, bool isLocalToUnit, + DICompositeType Ty, bool isLocalToUnit, + bool isDefinition, + unsigned ScopeLine, + unsigned Flags = 0, + bool isOptimized = false, + Function *Fn = 0, + MDNode *TParam = 0, + MDNode *Decl = 0); + + /// FIXME: this is added for dragonegg. Once we update dragonegg + /// to call resolve function, this will be removed. + DISubprogram createFunction(DIScopeRef Scope, StringRef Name, + StringRef LinkageName, + DIFile File, unsigned LineNo, + DICompositeType Ty, bool isLocalToUnit, bool isDefinition, unsigned ScopeLine, unsigned Flags = 0, @@ -537,10 +598,10 @@ namespace llvm { DISubprogram createMethod(DIDescriptor Scope, StringRef Name, StringRef LinkageName, DIFile File, unsigned LineNo, - DIType Ty, bool isLocalToUnit, + DICompositeType Ty, bool isLocalToUnit, bool isDefinition, unsigned Virtuality = 0, unsigned VTableIndex = 0, - MDNode *VTableHolder = 0, + DIType VTableHolder = DIType(), unsigned Flags = 0, bool isOptimized = false, Function *Fn = 0, @@ -577,8 +638,25 @@ namespace llvm { /// @param Context The scope this module is imported into /// @param NS The namespace being imported here /// @param Line Line number - DIImportedModule createImportedModule(DIScope Context, DINameSpace NS, - unsigned Line); + DIImportedEntity createImportedModule(DIScope Context, DINameSpace NS, + unsigned Line, + StringRef Name = StringRef()); + + /// \brief Create a descriptor for an imported module. + /// @param Context The scope this module is imported into + /// @param NS An aliased namespace + /// @param Line Line number + DIImportedEntity createImportedModule(DIScope Context, DIImportedEntity NS, + unsigned Line, StringRef Name); + + /// \brief Create a descriptor for an imported function. + /// @param Context The scope this module is imported into + /// @param Decl The declaration (or definition) of a function, type, or + /// variable + /// @param Line Line number + DIImportedEntity createImportedDeclaration(DIScope Context, + DIDescriptor Decl, + unsigned Line); /// insertDeclare - Insert a new llvm.dbg.declare intrinsic call. /// @param Storage llvm::Value of the variable diff --git a/contrib/llvm/include/llvm/DebugInfo.h b/contrib/llvm/include/llvm/DebugInfo.h index f9b58f477..768cf4ea1 100644 --- a/contrib/llvm/include/llvm/DebugInfo.h +++ b/contrib/llvm/include/llvm/DebugInfo.h @@ -17,769 +17,834 @@ #ifndef LLVM_DEBUGINFO_H #define LLVM_DEBUGINFO_H +#include "llvm/Support/Casting.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" +#include "llvm/IR/Metadata.h" #include "llvm/Support/Dwarf.h" namespace llvm { - class BasicBlock; - class Constant; - class Function; - class GlobalVariable; - class Module; - class Type; - class Value; - class DbgDeclareInst; - class Instruction; - class MDNode; - class NamedMDNode; - class LLVMContext; - class raw_ostream; - - class DIFile; - class DISubprogram; - class DILexicalBlock; - class DILexicalBlockFile; - class DIVariable; - class DIType; - class DIObjCProperty; - - /// DIDescriptor - A thin wraper around MDNode to access encoded debug info. - /// This should not be stored in a container, because the underlying MDNode - /// may change in certain situations. - class DIDescriptor { - public: - enum { - FlagPrivate = 1 << 0, - FlagProtected = 1 << 1, - 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 - }; - protected: - const MDNode *DbgNode; - - StringRef getStringField(unsigned Elt) const; - unsigned getUnsignedField(unsigned Elt) const { - return (unsigned)getUInt64Field(Elt); - } - uint64_t getUInt64Field(unsigned Elt) const; - int64_t getInt64Field(unsigned Elt) const; - DIDescriptor getDescriptorField(unsigned Elt) const; - - template - DescTy getFieldAs(unsigned Elt) const { - return DescTy(getDescriptorField(Elt)); - } - - GlobalVariable *getGlobalVariableField(unsigned Elt) const; - Constant *getConstantField(unsigned Elt) const; - Function *getFunctionField(unsigned Elt) const; - void replaceFunctionField(unsigned Elt, Function *F); - - public: - explicit DIDescriptor() : DbgNode(0) {} - explicit DIDescriptor(const MDNode *N) : DbgNode(N) {} - explicit DIDescriptor(const DIFile F); - explicit DIDescriptor(const DISubprogram F); - explicit DIDescriptor(const DILexicalBlockFile F); - explicit DIDescriptor(const DILexicalBlock F); - explicit DIDescriptor(const DIVariable F); - explicit DIDescriptor(const DIType F); - - bool Verify() const; - - operator MDNode *() const { return const_cast(DbgNode); } - MDNode *operator ->() const { return const_cast(DbgNode); } - - unsigned getTag() const { - return getUnsignedField(0) & ~LLVMDebugVersionMask; - } - - bool isDerivedType() const; - bool isCompositeType() const; - bool isBasicType() const; - bool isVariable() const; - bool isSubprogram() const; - bool isGlobalVariable() const; - bool isScope() const; - bool isFile() const; - bool isCompileUnit() const; - bool isNameSpace() const; - bool isLexicalBlockFile() const; - bool isLexicalBlock() const; - bool isSubrange() const; - bool isEnumerator() const; - bool isType() const; - bool isGlobal() const; - bool isUnspecifiedParameter() const; - bool isTemplateTypeParameter() const; - bool isTemplateValueParameter() const; - bool isObjCProperty() const; - bool isImportedModule() const; - - /// print - print descriptor. - void print(raw_ostream &OS) const; - - /// dump - print descriptor to dbgs() with a newline. - void dump() const; +class BasicBlock; +class Constant; +class Function; +class GlobalVariable; +class Module; +class Type; +class Value; +class DbgDeclareInst; +class DbgValueInst; +class Instruction; +class MDNode; +class MDString; +class NamedMDNode; +class LLVMContext; +class raw_ostream; + +class DIFile; +class DISubprogram; +class DILexicalBlock; +class DILexicalBlockFile; +class DIVariable; +class DIType; +class DIScope; +class DIObjCProperty; + +/// Maps from type identifier to the actual MDNode. +typedef DenseMap DITypeIdentifierMap; + +/// DIDescriptor - A thin wraper around MDNode to access encoded debug info. +/// This should not be stored in a container, because the underlying MDNode +/// may change in certain situations. +class DIDescriptor { + // Befriends DIRef so DIRef can befriend the protected member + // function: getFieldAs. + template friend class DIRef; + +public: + enum { + FlagPrivate = 1 << 0, + FlagProtected = 1 << 1, + 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 }; - /// DISubrange - This is used to represent ranges, for array bounds. - class DISubrange : public DIDescriptor { - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - public: - explicit DISubrange(const MDNode *N = 0) : DIDescriptor(N) {} - - int64_t getLo() const { return getInt64Field(1); } - int64_t getCount() const { return getInt64Field(2); } - bool Verify() const; - }; - - /// DIArray - This descriptor holds an array of descriptors. - class DIArray : public DIDescriptor { - public: - explicit DIArray(const MDNode *N = 0) - : DIDescriptor(N) {} - - unsigned getNumElements() const; - DIDescriptor getElement(unsigned Idx) const { - return getDescriptorField(Idx); - } - }; - - /// DIScope - A base class for various scopes. - class DIScope : public DIDescriptor { - protected: - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - public: - explicit DIScope(const MDNode *N = 0) : DIDescriptor (N) {} - - StringRef getFilename() const; - StringRef getDirectory() const; - }; - - /// DIFile - This is a wrapper for a file. - class DIFile : public DIScope { - friend class DIDescriptor; - public: - explicit DIFile(const MDNode *N = 0) : DIScope(N) { - if (DbgNode && !isFile()) - DbgNode = 0; - } - MDNode *getFileNode() const; - bool Verify() const; - }; - - /// DICompileUnit - A wrapper for a compile unit. - class DICompileUnit : public DIScope { - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - public: - explicit DICompileUnit(const MDNode *N = 0) : DIScope(N) {} - - unsigned getLanguage() const { return getUnsignedField(2); } - StringRef getProducer() const { return getStringField(3); } - - bool isOptimized() const { return getUnsignedField(4) != 0; } - StringRef getFlags() const { return getStringField(5); } - unsigned getRunTimeVersion() const { return getUnsignedField(6); } - - DIArray getEnumTypes() const; - DIArray getRetainedTypes() const; - DIArray getSubprograms() const; - DIArray getGlobalVariables() const; - DIArray getImportedModules() const; - - StringRef getSplitDebugFilename() const { return getStringField(12); } - - /// Verify - Verify that a compile unit is well formed. - bool Verify() const; - }; - - /// DIEnumerator - A wrapper for an enumerator (e.g. X and Y in 'enum {X,Y}'). - /// FIXME: it seems strange that this doesn't have either a reference to the - /// type/precision or a file/line pair for location info. - class DIEnumerator : public DIDescriptor { - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - public: - explicit DIEnumerator(const MDNode *N = 0) : DIDescriptor(N) {} - - StringRef getName() const { return getStringField(1); } - uint64_t getEnumValue() const { return getUInt64Field(2); } - bool Verify() const; - }; - - /// DIType - 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. - class DIType : public DIScope { - protected: - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - // This ctor is used when the Tag has already been validated by a derived - // ctor. - DIType(const MDNode *N, bool, bool) : DIScope(N) {} - public: - /// Verify - Verify that a type descriptor is well formed. - bool Verify() const; - explicit DIType(const MDNode *N); - explicit DIType() {} - - DIScope getContext() const { return getFieldAs(2); } - StringRef getName() const { return getStringField(3); } - unsigned getLineNumber() const { return getUnsignedField(4); } - uint64_t getSizeInBits() const { return getUInt64Field(5); } - uint64_t getAlignInBits() const { return getUInt64Field(6); } - // FIXME: Offset is only used for DW_TAG_member nodes. Making every type - // carry this is just plain insane. - uint64_t getOffsetInBits() const { return getUInt64Field(7); } - unsigned getFlags() const { return getUnsignedField(8); } - bool isPrivate() const { - return (getFlags() & FlagPrivate) != 0; - } - bool isProtected() const { - return (getFlags() & FlagProtected) != 0; - } - bool isForwardDecl() const { - return (getFlags() & FlagFwdDecl) != 0; - } - // isAppleBlock - Return true if this is the Apple Blocks extension. - bool isAppleBlockExtension() const { - return (getFlags() & FlagAppleBlock) != 0; - } - bool isBlockByrefStruct() const { - return (getFlags() & FlagBlockByrefStruct) != 0; - } - bool isVirtual() const { - return (getFlags() & FlagVirtual) != 0; - } - bool isArtificial() const { - return (getFlags() & FlagArtificial) != 0; - } - bool isObjectPointer() const { - return (getFlags() & FlagObjectPointer) != 0; - } - bool isObjcClassComplete() const { - return (getFlags() & FlagObjcClassComplete) != 0; - } - bool isVector() const { - return (getFlags() & FlagVector) != 0; - } - bool isStaticMember() const { - return (getFlags() & FlagStaticMember) != 0; - } - bool isValid() const { - return DbgNode && (isBasicType() || isDerivedType() || isCompositeType()); - } - - /// isUnsignedDIType - Return true if type encoding is unsigned. - bool isUnsignedDIType(); - - /// replaceAllUsesWith - Replace all uses of debug info referenced by - /// this descriptor. - void replaceAllUsesWith(DIDescriptor &D); - void replaceAllUsesWith(MDNode *D); - }; - - /// DIBasicType - A basic type, like 'int' or 'float'. - class DIBasicType : public DIType { - public: - explicit DIBasicType(const MDNode *N = 0) : DIType(N) {} - - unsigned getEncoding() const { return getUnsignedField(9); } - - /// Verify - Verify that a basic type descriptor is well formed. - bool Verify() const; - }; - - /// DIDerivedType - A simple derived type, like a const qualified type, - /// a typedef, a pointer or reference, et cetera. Or, a data member of - /// a class/struct/union. - class DIDerivedType : public DIType { - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - protected: - explicit DIDerivedType(const MDNode *N, bool, bool) - : DIType(N, true, true) {} - public: - explicit DIDerivedType(const MDNode *N = 0) - : DIType(N, true, true) {} - - DIType getTypeDerivedFrom() const { return getFieldAs(9); } - - /// getOriginalTypeSize - If this type is derived from a base type then - /// return base type size. - uint64_t getOriginalTypeSize() const; - - /// getObjCProperty - Return property node, if this ivar is - /// associated with one. - MDNode *getObjCProperty() const; - - DIType getClassType() const { - assert(getTag() == dwarf::DW_TAG_ptr_to_member_type); - return getFieldAs(10); - } - - Constant *getConstant() const { - assert((getTag() == dwarf::DW_TAG_member) && isStaticMember()); - return getConstantField(10); - } - - /// Verify - Verify that a derived type descriptor is well formed. - bool Verify() const; - }; - - /// DICompositeType - This descriptor holds a type that can refer to multiple - /// other types, like a function or struct. - /// DICompositeType is derived from DIDerivedType because some - /// composite types (such as enums) can be derived from basic types - // FIXME: Make this derive from DIType directly & just store the - // base type in a single DIType field. - class DICompositeType : public DIDerivedType { - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - public: - explicit DICompositeType(const MDNode *N = 0) - : DIDerivedType(N, true, true) { - if (N && !isCompositeType()) - DbgNode = 0; - } - - DIArray getTypeArray() const { return getFieldAs(10); } - void setTypeArray(DIArray Elements, DIArray TParams = DIArray()); - unsigned getRunTimeLang() const { return getUnsignedField(11); } - DICompositeType getContainingType() const { - return getFieldAs(12); - } - void setContainingType(DICompositeType ContainingType); - DIArray getTemplateParams() const { return getFieldAs(13); } - - /// Verify - Verify that a composite type descriptor is well formed. - bool Verify() const; - }; - - /// DITemplateTypeParameter - This is a wrapper for template type parameter. - class DITemplateTypeParameter : public DIDescriptor { - public: - explicit DITemplateTypeParameter(const MDNode *N = 0) : DIDescriptor(N) {} - - DIScope getContext() const { return getFieldAs(1); } - StringRef getName() const { return getStringField(2); } - DIType getType() const { return getFieldAs(3); } - StringRef getFilename() const { - return getFieldAs(4).getFilename(); - } - StringRef getDirectory() const { - return getFieldAs(4).getDirectory(); - } - unsigned getLineNumber() const { return getUnsignedField(5); } - unsigned getColumnNumber() const { return getUnsignedField(6); } - bool Verify() const; - }; - - /// DITemplateValueParameter - This is a wrapper for template value parameter. - class DITemplateValueParameter : public DIDescriptor { - public: - explicit DITemplateValueParameter(const MDNode *N = 0) : DIDescriptor(N) {} - - DIScope getContext() const { return getFieldAs(1); } - StringRef getName() const { return getStringField(2); } - DIType getType() const { return getFieldAs(3); } - uint64_t getValue() const { return getUInt64Field(4); } - StringRef getFilename() const { - return getFieldAs(5).getFilename(); - } - StringRef getDirectory() const { - return getFieldAs(5).getDirectory(); - } - unsigned getLineNumber() const { return getUnsignedField(6); } - unsigned getColumnNumber() const { return getUnsignedField(7); } - bool Verify() const; - }; - - /// DISubprogram - This is a wrapper for a subprogram (e.g. a function). - class DISubprogram : public DIScope { - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - public: - explicit DISubprogram(const MDNode *N = 0) : DIScope(N) {} - - DIScope getContext() const { return getFieldAs(2); } - StringRef getName() const { return getStringField(3); } - StringRef getDisplayName() const { return getStringField(4); } - StringRef getLinkageName() const { return getStringField(5); } - unsigned getLineNumber() const { return getUnsignedField(6); } - DICompositeType getType() const { return getFieldAs(7); } - - /// getReturnTypeName - Subprogram return types are encoded either as - /// DIType or as DICompositeType. - StringRef getReturnTypeName() const { - DICompositeType DCT(getFieldAs(7)); - if (DCT.Verify()) { - DIArray A = DCT.getTypeArray(); - DIType T(A.getElement(0)); - return T.getName(); - } - DIType T(getFieldAs(7)); - return T.getName(); - } - - /// isLocalToUnit - Return true if this subprogram is local to the current - /// compile unit, like 'static' in C. - unsigned isLocalToUnit() const { return getUnsignedField(8); } - unsigned isDefinition() const { return getUnsignedField(9); } - - unsigned getVirtuality() const { return getUnsignedField(10); } - unsigned getVirtualIndex() const { return getUnsignedField(11); } - - DICompositeType getContainingType() const { - return getFieldAs(12); - } - - unsigned getFlags() const { - return getUnsignedField(13); - } - - unsigned isArtificial() const { - return (getUnsignedField(13) & FlagArtificial) != 0; - } - /// isPrivate - Return true if this subprogram has "private" - /// access specifier. - bool isPrivate() const { - return (getUnsignedField(13) & FlagPrivate) != 0; - } - /// isProtected - Return true if this subprogram has "protected" - /// access specifier. - bool isProtected() const { - return (getUnsignedField(13) & FlagProtected) != 0; - } - /// isExplicit - Return true if this subprogram is marked as explicit. - bool isExplicit() const { - return (getUnsignedField(13) & FlagExplicit) != 0; - } - /// isPrototyped - Return true if this subprogram is prototyped. - bool isPrototyped() const { - return (getUnsignedField(13) & FlagPrototyped) != 0; - } - - unsigned isOptimized() const; - - /// getScopeLineNumber - Get the beginning of the scope of the - /// function, not necessarily where the name of the program - /// starts. - unsigned getScopeLineNumber() const { return getUnsignedField(19); } - - /// Verify - Verify that a subprogram descriptor is well formed. - bool Verify() const; - - /// describes - Return true if this subprogram provides debugging - /// information for the function F. - bool describes(const Function *F); - - Function *getFunction() const { return getFunctionField(15); } - void replaceFunction(Function *F) { replaceFunctionField(15, F); } - DIArray getTemplateParams() const { return getFieldAs(16); } - DISubprogram getFunctionDeclaration() const { - return getFieldAs(17); - } - MDNode *getVariablesNodes() const; - DIArray getVariables() const; - }; - - /// DIGlobalVariable - This is a wrapper for a global variable. - class DIGlobalVariable : public DIDescriptor { - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - public: - explicit DIGlobalVariable(const MDNode *N = 0) : DIDescriptor(N) {} - - DIScope getContext() const { return getFieldAs(2); } - StringRef getName() const { return getStringField(3); } - StringRef getDisplayName() const { return getStringField(4); } - StringRef getLinkageName() const { return getStringField(5); } - StringRef getFilename() const { - return getFieldAs(6).getFilename(); - } - StringRef getDirectory() const { - return getFieldAs(6).getDirectory(); - - } - - unsigned getLineNumber() const { return getUnsignedField(7); } - DIType getType() const { return getFieldAs(8); } - unsigned isLocalToUnit() const { return getUnsignedField(9); } - unsigned isDefinition() const { return getUnsignedField(10); } - - GlobalVariable *getGlobal() const { return getGlobalVariableField(11); } - Constant *getConstant() const { return getConstantField(11); } - DIDerivedType getStaticDataMemberDeclaration() const { - return getFieldAs(12); - } - - /// Verify - Verify that a global variable descriptor is well formed. - bool Verify() const; - }; - - /// DIVariable - This is a wrapper for a variable (e.g. parameter, local, - /// global etc). - class DIVariable : public DIDescriptor { - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - public: - explicit DIVariable(const MDNode *N = 0) - : DIDescriptor(N) {} - - DIScope getContext() const { return getFieldAs(1); } - StringRef getName() const { return getStringField(2); } - DIFile getFile() const { return getFieldAs(3); } - unsigned getLineNumber() const { - return (getUnsignedField(4) << 8) >> 8; - } - unsigned getArgNumber() const { - unsigned L = getUnsignedField(4); - return L >> 24; - } - DIType getType() const { return getFieldAs(5); } - - /// isArtificial - Return true if this variable is marked as "artificial". - bool isArtificial() const { - return (getUnsignedField(6) & FlagArtificial) != 0; - } - - bool isObjectPointer() const { - return (getUnsignedField(6) & FlagObjectPointer) != 0; - } - - /// getInlinedAt - If this variable is inlined then return inline location. - MDNode *getInlinedAt() const; - - /// Verify - Verify that a variable descriptor is well formed. - bool Verify() const; - - /// HasComplexAddr - Return true if the variable has a complex address. - bool hasComplexAddress() const { - return getNumAddrElements() > 0; - } - - unsigned getNumAddrElements() const; - - uint64_t getAddrElement(unsigned Idx) const { - return getUInt64Field(Idx+8); - } - - /// isBlockByrefVariable - Return true if the variable was declared as - /// a "__block" variable (Apple Blocks). - bool isBlockByrefVariable() const { - return getType().isBlockByrefStruct(); - } - - /// isInlinedFnArgument - Return true if this variable provides debugging - /// information for an inlined function arguments. - bool isInlinedFnArgument(const Function *CurFn); - - void printExtendedName(raw_ostream &OS) const; - }; - - /// DILexicalBlock - This is a wrapper for a lexical block. - class DILexicalBlock : public DIScope { - public: - explicit DILexicalBlock(const MDNode *N = 0) : DIScope(N) {} - DIScope getContext() const { return getFieldAs(2); } - unsigned getLineNumber() const { return getUnsignedField(3); } - unsigned getColumnNumber() const { return getUnsignedField(4); } - bool Verify() const; - }; - - /// DILexicalBlockFile - This is a wrapper for a lexical block with - /// a filename change. - class DILexicalBlockFile : public DIScope { - public: - explicit DILexicalBlockFile(const MDNode *N = 0) : DIScope(N) {} - DIScope getContext() const { if (getScope().isSubprogram()) return getScope(); return getScope().getContext(); } - unsigned getLineNumber() const { return getScope().getLineNumber(); } - unsigned getColumnNumber() const { return getScope().getColumnNumber(); } - DILexicalBlock getScope() const { return getFieldAs(2); } - bool Verify() const; - }; - - /// DINameSpace - A wrapper for a C++ style name space. - class DINameSpace : public DIScope { - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - public: - explicit DINameSpace(const MDNode *N = 0) : DIScope(N) {} - DIScope getContext() const { return getFieldAs(2); } - StringRef getName() const { return getStringField(3); } - unsigned getLineNumber() const { return getUnsignedField(4); } - bool Verify() const; - }; - - /// DILocation - This object holds location information. This object - /// is not associated with any DWARF tag. - class DILocation : public DIDescriptor { - public: - explicit DILocation(const MDNode *N) : DIDescriptor(N) { } - - unsigned getLineNumber() const { return getUnsignedField(0); } - unsigned getColumnNumber() const { return getUnsignedField(1); } - DIScope getScope() const { return getFieldAs(2); } - DILocation getOrigLocation() const { return getFieldAs(3); } - StringRef getFilename() const { return getScope().getFilename(); } - StringRef getDirectory() const { return getScope().getDirectory(); } - bool Verify() const; - }; - - class DIObjCProperty : public DIDescriptor { - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - public: - explicit DIObjCProperty(const MDNode *N) : DIDescriptor(N) { } - - StringRef getObjCPropertyName() const { return getStringField(1); } - DIFile getFile() const { return getFieldAs(2); } - unsigned getLineNumber() const { return getUnsignedField(3); } - - StringRef getObjCPropertyGetterName() const { - return getStringField(4); - } - StringRef getObjCPropertySetterName() const { - return getStringField(5); - } - bool isReadOnlyObjCProperty() { - return (getUnsignedField(6) & dwarf::DW_APPLE_PROPERTY_readonly) != 0; - } - bool isReadWriteObjCProperty() { - return (getUnsignedField(6) & dwarf::DW_APPLE_PROPERTY_readwrite) != 0; - } - bool isAssignObjCProperty() { - return (getUnsignedField(6) & dwarf::DW_APPLE_PROPERTY_assign) != 0; - } - bool isRetainObjCProperty() { - return (getUnsignedField(6) & dwarf::DW_APPLE_PROPERTY_retain) != 0; - } - bool isCopyObjCProperty() { - return (getUnsignedField(6) & dwarf::DW_APPLE_PROPERTY_copy) != 0; - } - bool isNonAtomicObjCProperty() { - return (getUnsignedField(6) & dwarf::DW_APPLE_PROPERTY_nonatomic) != 0; - } - - DIType getType() const { return getFieldAs(7); } - - /// Verify - Verify that a derived type descriptor is well formed. - bool Verify() const; - }; - - /// \brief An imported module (C++ using directive or similar). - class DIImportedModule : public DIDescriptor { - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - public: - explicit DIImportedModule(const MDNode *N) : DIDescriptor(N) { } - DIScope getContext() const { return getFieldAs(1); } - DINameSpace getNameSpace() const { return getFieldAs(2); } - unsigned getLineNumber() const { return getUnsignedField(3); } - bool Verify() const; - }; - - /// getDISubprogram - Find subprogram that is enclosing this scope. - DISubprogram getDISubprogram(const MDNode *Scope); - - /// getDICompositeType - Find underlying composite type. - DICompositeType getDICompositeType(DIType T); - - /// isSubprogramContext - Return true if Context is either a subprogram - /// or another context nested inside a subprogram. - bool isSubprogramContext(const MDNode *Context); - - /// getOrInsertFnSpecificMDNode - Return a NameMDNode that is suitable - /// to hold function specific information. - NamedMDNode *getOrInsertFnSpecificMDNode(Module &M, DISubprogram SP); - - /// getFnSpecificMDNode - Return a NameMDNode, if available, that is - /// suitable to hold function specific information. - NamedMDNode *getFnSpecificMDNode(const Module &M, DISubprogram SP); - - /// createInlinedVariable - Create a new inlined variable based on current - /// variable. - /// @param DV Current Variable. - /// @param InlinedScope Location at current variable is inlined. - DIVariable createInlinedVariable(MDNode *DV, MDNode *InlinedScope, - LLVMContext &VMContext); - - /// cleanseInlinedVariable - Remove inlined scope from the variable. - DIVariable cleanseInlinedVariable(MDNode *DV, LLVMContext &VMContext); - - class DebugInfoFinder { - public: - /// processModule - Process entire module and collect debug info - /// anchors. - void processModule(const Module &M); - - private: - /// processType - Process DIType. - void processType(DIType DT); - - /// processLexicalBlock - Process DILexicalBlock. - void processLexicalBlock(DILexicalBlock LB); - - /// processSubprogram - Process DISubprogram. - void processSubprogram(DISubprogram SP); - - /// processDeclare - Process DbgDeclareInst. - void processDeclare(const DbgDeclareInst *DDI); - - /// processLocation - Process DILocation. - void processLocation(DILocation Loc); - - /// addCompileUnit - Add compile unit into CUs. - bool addCompileUnit(DICompileUnit CU); - - /// addGlobalVariable - Add global variable into GVs. - bool addGlobalVariable(DIGlobalVariable DIG); - - // addSubprogram - Add subprogram into SPs. - bool addSubprogram(DISubprogram SP); - - /// addType - Add type into Tys. - bool addType(DIType DT); - - public: - typedef SmallVector::const_iterator iterator; - iterator compile_unit_begin() const { return CUs.begin(); } - iterator compile_unit_end() const { return CUs.end(); } - iterator subprogram_begin() const { return SPs.begin(); } - iterator subprogram_end() const { return SPs.end(); } - iterator global_variable_begin() const { return GVs.begin(); } - iterator global_variable_end() const { return GVs.end(); } - iterator type_begin() const { return TYs.begin(); } - iterator type_end() const { return TYs.end(); } - - unsigned compile_unit_count() const { return CUs.size(); } - unsigned global_variable_count() const { return GVs.size(); } - unsigned subprogram_count() const { return SPs.size(); } - unsigned type_count() const { return TYs.size(); } - - private: - SmallVector CUs; // Compile Units - SmallVector SPs; // Subprograms - SmallVector GVs; // Global Variables; - SmallVector TYs; // Types - SmallPtrSet NodesSeen; - }; +protected: + const MDNode *DbgNode; + + StringRef getStringField(unsigned Elt) const; + unsigned getUnsignedField(unsigned Elt) const { + return (unsigned)getUInt64Field(Elt); + } + uint64_t getUInt64Field(unsigned Elt) const; + int64_t getInt64Field(unsigned Elt) const; + DIDescriptor getDescriptorField(unsigned Elt) const; + + template DescTy getFieldAs(unsigned Elt) const { + return DescTy(getDescriptorField(Elt)); + } + + GlobalVariable *getGlobalVariableField(unsigned Elt) const; + Constant *getConstantField(unsigned Elt) const; + Function *getFunctionField(unsigned Elt) const; + void replaceFunctionField(unsigned Elt, Function *F); + +public: + explicit DIDescriptor(const MDNode *N = 0) : DbgNode(N) {} + + bool Verify() const; + + operator MDNode *() const { return const_cast(DbgNode); } + MDNode *operator->() const { return const_cast(DbgNode); } + + // 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 != 0; } + + bool operator==(DIDescriptor Other) const { return DbgNode == Other.DbgNode; } + bool operator!=(DIDescriptor Other) const { return !operator==(Other); } + + uint16_t getTag() const { + return getUnsignedField(0) & ~LLVMDebugVersionMask; + } + + bool isDerivedType() const; + bool isCompositeType() const; + bool isBasicType() const; + bool isVariable() const; + bool isSubprogram() const; + bool isGlobalVariable() const; + bool isScope() const; + bool isFile() const; + bool isCompileUnit() const; + bool isNameSpace() const; + bool isLexicalBlockFile() const; + bool isLexicalBlock() const; + bool isSubrange() const; + bool isEnumerator() const; + bool isType() const; + bool isUnspecifiedParameter() const; + bool isTemplateTypeParameter() const; + bool isTemplateValueParameter() const; + bool isObjCProperty() const; + bool isImportedEntity() const; + + /// print - print descriptor. + void print(raw_ostream &OS) const; + + /// dump - print descriptor to dbgs() with a newline. + void dump() const; +}; + +/// DISubrange - This is used to represent ranges, for array bounds. +class DISubrange : public DIDescriptor { + friend class DIDescriptor; + void printInternal(raw_ostream &OS) const; + +public: + explicit DISubrange(const MDNode *N = 0) : DIDescriptor(N) {} + + int64_t getLo() const { return getInt64Field(1); } + int64_t getCount() const { return getInt64Field(2); } + bool Verify() const; +}; + +/// DIArray - This descriptor holds an array of descriptors. +class DIArray : public DIDescriptor { +public: + explicit DIArray(const MDNode *N = 0) : DIDescriptor(N) {} + + unsigned getNumElements() const; + DIDescriptor getElement(unsigned Idx) const { + return getDescriptorField(Idx); + } +}; + +/// DIEnumerator - A wrapper for an enumerator (e.g. X and Y in 'enum {X,Y}'). +/// FIXME: it seems strange that this doesn't have either a reference to the +/// type/precision or a file/line pair for location info. +class DIEnumerator : public DIDescriptor { + friend class DIDescriptor; + void printInternal(raw_ostream &OS) const; + +public: + explicit DIEnumerator(const MDNode *N = 0) : DIDescriptor(N) {} + + StringRef getName() const { return getStringField(1); } + int64_t getEnumValue() const { return getInt64Field(2); } + bool Verify() const; +}; + +template class DIRef; +typedef DIRef DIScopeRef; +typedef DIRef DITypeRef; + +/// DIScope - A base class for various scopes. +class DIScope : public DIDescriptor { +protected: + friend class DIDescriptor; + void printInternal(raw_ostream &OS) const; + +public: + explicit DIScope(const MDNode *N = 0) : DIDescriptor(N) {} + + /// Gets the parent scope for this scope node or returns a + /// default constructed scope. + DIScopeRef getContext() const; + /// If the scope node has a name, return that, else return an empty string. + StringRef getName() const; + StringRef getFilename() const; + StringRef getDirectory() const; + + /// Generate a reference to this DIScope. Uses the type identifier instead + /// of the actual MDNode if possible, to help type uniquing. + DIScopeRef getRef() const; +}; + +/// Represents reference to a DIDescriptor, abstracts over direct and +/// identifier-based metadata references. +template class DIRef { + template + friend DescTy DIDescriptor::getFieldAs(unsigned Elt) const; + friend DIScopeRef DIScope::getContext() const; + friend DIScopeRef DIScope::getRef() const; + + /// Val can be either a MDNode or a MDString, in the latter, + /// MDString specifies the type identifier. + const Value *Val; + explicit DIRef(const Value *V); + +public: + T resolve(const DITypeIdentifierMap &Map) const; + StringRef getName() const; + operator Value *() const { return const_cast(Val); } +}; + +template +T DIRef::resolve(const DITypeIdentifierMap &Map) const { + if (!Val) + return T(); + + if (const MDNode *MD = dyn_cast(Val)) + return T(MD); + + const MDString *MS = cast(Val); + // Find the corresponding MDNode. + DITypeIdentifierMap::const_iterator Iter = Map.find(MS); + assert(Iter != Map.end() && "Identifier not in the type map?"); + assert(DIDescriptor(Iter->second).isType() && + "MDNode in DITypeIdentifierMap should be a DIType."); + return T(Iter->second); +} + +template StringRef DIRef::getName() const { + if (!Val) + return StringRef(); + + if (const MDNode *MD = dyn_cast(Val)) + return T(MD).getName(); + + const MDString *MS = cast(Val); + return MS->getString(); +} + +/// Specialize getFieldAs to handle fields that are references to DIScopes. +template <> DIScopeRef DIDescriptor::getFieldAs(unsigned Elt) const; +/// Specialize DIRef constructor for DIScopeRef. +template <> DIRef::DIRef(const Value *V); + +/// Specialize getFieldAs to handle fields that are references to DITypes. +template <> DITypeRef DIDescriptor::getFieldAs(unsigned Elt) const; +/// Specialize DIRef constructor for DITypeRef. +template <> DIRef::DIRef(const Value *V); + +/// DIType - 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. +class DIType : public DIScope { +protected: + friend class DIDescriptor; + void printInternal(raw_ostream &OS) const; + +public: + explicit DIType(const MDNode *N = 0) : DIScope(N) {} + + /// Verify - Verify that a type descriptor is well formed. + bool Verify() const; + + DIScopeRef getContext() const { return getFieldAs(2); } + StringRef getName() const { return getStringField(3); } + unsigned getLineNumber() const { return getUnsignedField(4); } + uint64_t getSizeInBits() const { return getUInt64Field(5); } + uint64_t getAlignInBits() const { return getUInt64Field(6); } + // FIXME: Offset is only used for DW_TAG_member nodes. Making every type + // carry this is just plain insane. + uint64_t getOffsetInBits() const { return getUInt64Field(7); } + unsigned getFlags() const { return getUnsignedField(8); } + bool isPrivate() const { return (getFlags() & FlagPrivate) != 0; } + bool isProtected() const { return (getFlags() & FlagProtected) != 0; } + bool isForwardDecl() const { return (getFlags() & FlagFwdDecl) != 0; } + // isAppleBlock - Return true if this is the Apple Blocks extension. + bool isAppleBlockExtension() const { + return (getFlags() & FlagAppleBlock) != 0; + } + bool isBlockByrefStruct() const { + return (getFlags() & FlagBlockByrefStruct) != 0; + } + bool isVirtual() const { return (getFlags() & FlagVirtual) != 0; } + bool isArtificial() const { return (getFlags() & FlagArtificial) != 0; } + bool isObjectPointer() const { return (getFlags() & FlagObjectPointer) != 0; } + bool isObjcClassComplete() const { + return (getFlags() & FlagObjcClassComplete) != 0; + } + bool isVector() const { return (getFlags() & FlagVector) != 0; } + bool isStaticMember() const { return (getFlags() & FlagStaticMember) != 0; } + bool isValid() const { return DbgNode && isType(); } + + /// replaceAllUsesWith - Replace all uses of debug info referenced by + /// this descriptor. + void replaceAllUsesWith(DIDescriptor &D); + void replaceAllUsesWith(MDNode *D); +}; + +/// DIBasicType - A basic type, like 'int' or 'float'. +class DIBasicType : public DIType { +public: + explicit DIBasicType(const MDNode *N = 0) : DIType(N) {} + + unsigned getEncoding() const { return getUnsignedField(9); } + + /// Verify - Verify that a basic type descriptor is well formed. + bool Verify() const; +}; + +/// DIDerivedType - A simple derived type, like a const qualified type, +/// a typedef, a pointer or reference, et cetera. Or, a data member of +/// a class/struct/union. +class DIDerivedType : public DIType { + friend class DIDescriptor; + void printInternal(raw_ostream &OS) const; + +public: + explicit DIDerivedType(const MDNode *N = 0) : DIType(N) {} + + DITypeRef getTypeDerivedFrom() const { return getFieldAs(9); } + + /// getObjCProperty - Return property node, if this ivar is + /// associated with one. + MDNode *getObjCProperty() const; + + DITypeRef getClassType() const { + assert(getTag() == dwarf::DW_TAG_ptr_to_member_type); + return getFieldAs(10); + } + + Constant *getConstant() const { + assert((getTag() == dwarf::DW_TAG_member) && isStaticMember()); + return getConstantField(10); + } + + /// Verify - Verify that a derived type descriptor is well formed. + bool Verify() const; +}; + +/// DICompositeType - This descriptor holds a type that can refer to multiple +/// other types, like a function or struct. +/// DICompositeType is derived from DIDerivedType because some +/// composite types (such as enums) can be derived from basic types +// FIXME: Make this derive from DIType directly & just store the +// base type in a single DIType field. +class DICompositeType : public DIDerivedType { + friend class DIDescriptor; + void printInternal(raw_ostream &OS) const; + +public: + explicit DICompositeType(const MDNode *N = 0) : DIDerivedType(N) {} + + DIArray getTypeArray() const { return getFieldAs(10); } + void setTypeArray(DIArray Elements, DIArray TParams = DIArray()); + void addMember(DIDescriptor D); + unsigned getRunTimeLang() const { return getUnsignedField(11); } + DITypeRef getContainingType() const { return getFieldAs(12); } + void setContainingType(DICompositeType ContainingType); + DIArray getTemplateParams() const { return getFieldAs(13); } + MDString *getIdentifier() const; + + /// Verify - Verify that a composite type descriptor is well formed. + bool Verify() const; +}; + +/// DIFile - This is a wrapper for a file. +class DIFile : public DIScope { + friend class DIDescriptor; + +public: + explicit DIFile(const MDNode *N = 0) : DIScope(N) {} + MDNode *getFileNode() const; + bool Verify() const; +}; + +/// DICompileUnit - A wrapper for a compile unit. +class DICompileUnit : public DIScope { + friend class DIDescriptor; + void printInternal(raw_ostream &OS) const; + +public: + explicit DICompileUnit(const MDNode *N = 0) : DIScope(N) {} + + unsigned getLanguage() const { return getUnsignedField(2); } + StringRef getProducer() const { return getStringField(3); } + + bool isOptimized() const { return getUnsignedField(4) != 0; } + StringRef getFlags() const { return getStringField(5); } + unsigned getRunTimeVersion() const { return getUnsignedField(6); } + + DIArray getEnumTypes() const; + DIArray getRetainedTypes() const; + DIArray getSubprograms() const; + DIArray getGlobalVariables() const; + DIArray getImportedEntities() const; + + StringRef getSplitDebugFilename() const { return getStringField(12); } + + /// Verify - Verify that a compile unit is well formed. + bool Verify() const; +}; + +/// DISubprogram - This is a wrapper for a subprogram (e.g. a function). +class DISubprogram : public DIScope { + friend class DIDescriptor; + void printInternal(raw_ostream &OS) const; + +public: + explicit DISubprogram(const MDNode *N = 0) : DIScope(N) {} + + DIScopeRef getContext() const { return getFieldAs(2); } + StringRef getName() const { return getStringField(3); } + StringRef getDisplayName() const { return getStringField(4); } + StringRef getLinkageName() const { return getStringField(5); } + unsigned getLineNumber() const { return getUnsignedField(6); } + DICompositeType getType() const { return getFieldAs(7); } + + /// isLocalToUnit - Return true if this subprogram is local to the current + /// compile unit, like 'static' in C. + unsigned isLocalToUnit() const { return getUnsignedField(8); } + unsigned isDefinition() const { return getUnsignedField(9); } + + unsigned getVirtuality() const { return getUnsignedField(10); } + unsigned getVirtualIndex() const { return getUnsignedField(11); } + + DITypeRef getContainingType() const { return getFieldAs(12); } + + unsigned getFlags() const { return getUnsignedField(13); } + + unsigned isArtificial() const { + return (getUnsignedField(13) & FlagArtificial) != 0; + } + /// isPrivate - Return true if this subprogram has "private" + /// access specifier. + bool isPrivate() const { return (getUnsignedField(13) & FlagPrivate) != 0; } + /// isProtected - Return true if this subprogram has "protected" + /// access specifier. + bool isProtected() const { + return (getUnsignedField(13) & FlagProtected) != 0; + } + /// isExplicit - Return true if this subprogram is marked as explicit. + bool isExplicit() const { return (getUnsignedField(13) & FlagExplicit) != 0; } + /// isPrototyped - Return true if this subprogram is prototyped. + bool isPrototyped() const { + return (getUnsignedField(13) & FlagPrototyped) != 0; + } + + unsigned isOptimized() const; + + /// Verify - Verify that a subprogram descriptor is well formed. + bool Verify() const; + + /// describes - Return true if this subprogram provides debugging + /// information for the function F. + bool describes(const Function *F); + + Function *getFunction() const { return getFunctionField(15); } + void replaceFunction(Function *F) { replaceFunctionField(15, F); } + DIArray getTemplateParams() const { return getFieldAs(16); } + DISubprogram getFunctionDeclaration() const { + return getFieldAs(17); + } + MDNode *getVariablesNodes() const; + DIArray getVariables() const; + + /// getScopeLineNumber - Get the beginning of the scope of the + /// function, not necessarily where the name of the program + /// starts. + unsigned getScopeLineNumber() const { return getUnsignedField(19); } +}; + +/// DILexicalBlock - This is a wrapper for a lexical block. +class DILexicalBlock : public DIScope { +public: + explicit DILexicalBlock(const MDNode *N = 0) : DIScope(N) {} + DIScope getContext() const { return getFieldAs(2); } + unsigned getLineNumber() const { return getUnsignedField(3); } + unsigned getColumnNumber() const { return getUnsignedField(4); } + bool Verify() const; +}; + +/// DILexicalBlockFile - This is a wrapper for a lexical block with +/// a filename change. +class DILexicalBlockFile : public DIScope { +public: + explicit DILexicalBlockFile(const MDNode *N = 0) : DIScope(N) {} + DIScope getContext() const { + if (getScope().isSubprogram()) + return getScope(); + return getScope().getContext(); + } + unsigned getLineNumber() const { return getScope().getLineNumber(); } + unsigned getColumnNumber() const { return getScope().getColumnNumber(); } + DILexicalBlock getScope() const { return getFieldAs(2); } + bool Verify() const; +}; + +/// DINameSpace - A wrapper for a C++ style name space. +class DINameSpace : public DIScope { + friend class DIDescriptor; + void printInternal(raw_ostream &OS) const; + +public: + explicit DINameSpace(const MDNode *N = 0) : DIScope(N) {} + DIScope getContext() const { return getFieldAs(2); } + StringRef getName() const { return getStringField(3); } + unsigned getLineNumber() const { return getUnsignedField(4); } + bool Verify() const; +}; + +/// DITemplateTypeParameter - This is a wrapper for template type parameter. +class DITemplateTypeParameter : public DIDescriptor { +public: + explicit DITemplateTypeParameter(const MDNode *N = 0) : DIDescriptor(N) {} + + DIScopeRef getContext() const { return getFieldAs(1); } + StringRef getName() const { return getStringField(2); } + DITypeRef getType() const { return getFieldAs(3); } + StringRef getFilename() const { return getFieldAs(4).getFilename(); } + StringRef getDirectory() const { + return getFieldAs(4).getDirectory(); + } + unsigned getLineNumber() const { return getUnsignedField(5); } + unsigned getColumnNumber() const { return getUnsignedField(6); } + bool Verify() const; +}; + +/// DITemplateValueParameter - This is a wrapper for template value parameter. +class DITemplateValueParameter : public DIDescriptor { +public: + explicit DITemplateValueParameter(const MDNode *N = 0) : DIDescriptor(N) {} + + DIScopeRef getContext() const { return getFieldAs(1); } + StringRef getName() const { return getStringField(2); } + DITypeRef getType() const { return getFieldAs(3); } + Value *getValue() const; + StringRef getFilename() const { return getFieldAs(5).getFilename(); } + StringRef getDirectory() const { + return getFieldAs(5).getDirectory(); + } + unsigned getLineNumber() const { return getUnsignedField(6); } + unsigned getColumnNumber() const { return getUnsignedField(7); } + bool Verify() const; +}; + +/// DIGlobalVariable - This is a wrapper for a global variable. +class DIGlobalVariable : public DIDescriptor { + friend class DIDescriptor; + void printInternal(raw_ostream &OS) const; + +public: + explicit DIGlobalVariable(const MDNode *N = 0) : DIDescriptor(N) {} + + DIScope getContext() const { return getFieldAs(2); } + StringRef getName() const { return getStringField(3); } + StringRef getDisplayName() const { return getStringField(4); } + StringRef getLinkageName() const { return getStringField(5); } + StringRef getFilename() const { return getFieldAs(6).getFilename(); } + StringRef getDirectory() const { + return getFieldAs(6).getDirectory(); + } + + unsigned getLineNumber() const { return getUnsignedField(7); } + DIType getType() const { return getFieldAs(8); } + unsigned isLocalToUnit() const { return getUnsignedField(9); } + unsigned isDefinition() const { return getUnsignedField(10); } + + GlobalVariable *getGlobal() const { return getGlobalVariableField(11); } + Constant *getConstant() const { return getConstantField(11); } + DIDerivedType getStaticDataMemberDeclaration() const { + return getFieldAs(12); + } + + /// Verify - Verify that a global variable descriptor is well formed. + bool Verify() const; +}; + +/// DIVariable - This is a wrapper for a variable (e.g. parameter, local, +/// global etc). +class DIVariable : public DIDescriptor { + friend class DIDescriptor; + void printInternal(raw_ostream &OS) const; + +public: + explicit DIVariable(const MDNode *N = 0) : DIDescriptor(N) {} + + DIScope getContext() const { return getFieldAs(1); } + StringRef getName() const { return getStringField(2); } + DIFile getFile() const { return getFieldAs(3); } + unsigned getLineNumber() const { return (getUnsignedField(4) << 8) >> 8; } + unsigned getArgNumber() const { + unsigned L = getUnsignedField(4); + return L >> 24; + } + DIType getType() const { return getFieldAs(5); } + + /// isArtificial - Return true if this variable is marked as "artificial". + bool isArtificial() const { + return (getUnsignedField(6) & FlagArtificial) != 0; + } + + bool isObjectPointer() const { + return (getUnsignedField(6) & FlagObjectPointer) != 0; + } + + /// \brief Return true if this variable is represented as a pointer. + bool isIndirect() const { + return (getUnsignedField(6) & FlagIndirectVariable) != 0; + } + + /// getInlinedAt - If this variable is inlined then return inline location. + MDNode *getInlinedAt() const; + + /// Verify - Verify that a variable descriptor is well formed. + bool Verify() const; + + /// HasComplexAddr - Return true if the variable has a complex address. + bool hasComplexAddress() const { return getNumAddrElements() > 0; } + + unsigned getNumAddrElements() const; + + uint64_t getAddrElement(unsigned Idx) const { + return getUInt64Field(Idx + 8); + } + + /// isBlockByrefVariable - Return true if the variable was declared as + /// a "__block" variable (Apple Blocks). + bool isBlockByrefVariable() const { return getType().isBlockByrefStruct(); } + + /// isInlinedFnArgument - Return true if this variable provides debugging + /// information for an inlined function arguments. + bool isInlinedFnArgument(const Function *CurFn); + + void printExtendedName(raw_ostream &OS) const; +}; + +/// DILocation - This object holds location information. This object +/// is not associated with any DWARF tag. +class DILocation : public DIDescriptor { +public: + explicit DILocation(const MDNode *N) : DIDescriptor(N) {} + + unsigned getLineNumber() const { return getUnsignedField(0); } + unsigned getColumnNumber() const { return getUnsignedField(1); } + DIScope getScope() const { return getFieldAs(2); } + DILocation getOrigLocation() const { return getFieldAs(3); } + StringRef getFilename() const { return getScope().getFilename(); } + StringRef getDirectory() const { return getScope().getDirectory(); } + bool Verify() const; +}; + +class DIObjCProperty : public DIDescriptor { + friend class DIDescriptor; + void printInternal(raw_ostream &OS) const; + +public: + explicit DIObjCProperty(const MDNode *N) : DIDescriptor(N) {} + + StringRef getObjCPropertyName() const { return getStringField(1); } + DIFile getFile() const { return getFieldAs(2); } + unsigned getLineNumber() const { return getUnsignedField(3); } + + StringRef getObjCPropertyGetterName() const { return getStringField(4); } + StringRef getObjCPropertySetterName() const { return getStringField(5); } + bool isReadOnlyObjCProperty() const { + return (getUnsignedField(6) & dwarf::DW_APPLE_PROPERTY_readonly) != 0; + } + bool isReadWriteObjCProperty() const { + return (getUnsignedField(6) & dwarf::DW_APPLE_PROPERTY_readwrite) != 0; + } + bool isAssignObjCProperty() const { + return (getUnsignedField(6) & dwarf::DW_APPLE_PROPERTY_assign) != 0; + } + bool isRetainObjCProperty() const { + return (getUnsignedField(6) & dwarf::DW_APPLE_PROPERTY_retain) != 0; + } + bool isCopyObjCProperty() const { + return (getUnsignedField(6) & dwarf::DW_APPLE_PROPERTY_copy) != 0; + } + bool isNonAtomicObjCProperty() const { + return (getUnsignedField(6) & dwarf::DW_APPLE_PROPERTY_nonatomic) != 0; + } + + DIType getType() const { return getFieldAs(7); } + + /// Verify - Verify that a derived type descriptor is well formed. + bool Verify() const; +}; + +/// \brief An imported module (C++ using directive or similar). +class DIImportedEntity : public DIDescriptor { + friend class DIDescriptor; + void printInternal(raw_ostream &OS) const; + +public: + explicit DIImportedEntity(const MDNode *N) : DIDescriptor(N) {} + DIScope getContext() const { return getFieldAs(1); } + DIDescriptor getEntity() const { return getFieldAs(2); } + unsigned getLineNumber() const { return getUnsignedField(3); } + StringRef getName() const { return getStringField(4); } + bool Verify() const; +}; + +/// getDISubprogram - Find subprogram that is enclosing this scope. +DISubprogram getDISubprogram(const MDNode *Scope); + +/// getDICompositeType - Find underlying composite type. +DICompositeType getDICompositeType(DIType T); + +/// getOrInsertFnSpecificMDNode - Return a NameMDNode that is suitable +/// to hold function specific information. +NamedMDNode *getOrInsertFnSpecificMDNode(Module &M, DISubprogram SP); + +/// getFnSpecificMDNode - Return a NameMDNode, if available, that is +/// suitable to hold function specific information. +NamedMDNode *getFnSpecificMDNode(const Module &M, DISubprogram SP); + +/// createInlinedVariable - Create a new inlined variable based on current +/// variable. +/// @param DV Current Variable. +/// @param InlinedScope Location at current variable is inlined. +DIVariable createInlinedVariable(MDNode *DV, MDNode *InlinedScope, + LLVMContext &VMContext); + +/// cleanseInlinedVariable - Remove inlined scope from the variable. +DIVariable cleanseInlinedVariable(MDNode *DV, LLVMContext &VMContext); + +/// Construct DITypeIdentifierMap by going through retained types of each CU. +DITypeIdentifierMap generateDITypeIdentifierMap(const NamedMDNode *CU_Nodes); + +/// Strip debug info in the module if it exists. +/// To do this, we remove all calls to the debugger intrinsics and any named +/// metadata for debugging. We also remove debug locations for instructions. +/// Return true if module is modified. +bool StripDebugInfo(Module &M); + +/// Return Debug Info Metadata Version by checking module flags. +unsigned getDebugMetadataVersionFromModule(const Module &M); + +/// DebugInfoFinder tries to list all debug info MDNodes used in a module. To +/// list debug info MDNodes used by an instruction, DebugInfoFinder uses +/// processDeclare, processValue and processLocation to handle DbgDeclareInst, +/// DbgValueInst and DbgLoc attached to instructions. processModule will go +/// through all DICompileUnits in llvm.dbg.cu and list debug info MDNodes +/// used by the CUs. +class DebugInfoFinder { +public: + DebugInfoFinder() : TypeMapInitialized(false) {} + + /// processModule - Process entire module and collect debug info + /// anchors. + void processModule(const Module &M); + + /// processDeclare - Process DbgDeclareInst. + void processDeclare(const Module &M, const DbgDeclareInst *DDI); + /// Process DbgValueInst. + void processValue(const Module &M, const DbgValueInst *DVI); + /// processLocation - Process DILocation. + void processLocation(const Module &M, DILocation Loc); + + /// Clear all lists. + void reset(); + +private: + /// Initialize TypeIdentifierMap. + void InitializeTypeMap(const Module &M); + + /// processType - Process DIType. + void processType(DIType DT); + + /// processLexicalBlock - Process DILexicalBlock. + void processLexicalBlock(DILexicalBlock LB); + + /// processSubprogram - Process DISubprogram. + void processSubprogram(DISubprogram SP); + + void processScope(DIScope Scope); + + /// addCompileUnit - Add compile unit into CUs. + bool addCompileUnit(DICompileUnit CU); + + /// addGlobalVariable - Add global variable into GVs. + bool addGlobalVariable(DIGlobalVariable DIG); + + // addSubprogram - Add subprogram into SPs. + bool addSubprogram(DISubprogram SP); + + /// addType - Add type into Tys. + bool addType(DIType DT); + + bool addScope(DIScope Scope); + +public: + typedef SmallVectorImpl::const_iterator iterator; + iterator compile_unit_begin() const { return CUs.begin(); } + iterator compile_unit_end() const { return CUs.end(); } + iterator subprogram_begin() const { return SPs.begin(); } + iterator subprogram_end() const { return SPs.end(); } + iterator global_variable_begin() const { return GVs.begin(); } + iterator global_variable_end() const { return GVs.end(); } + iterator type_begin() const { return TYs.begin(); } + iterator type_end() const { return TYs.end(); } + iterator scope_begin() const { return Scopes.begin(); } + iterator scope_end() const { return Scopes.end(); } + + unsigned compile_unit_count() const { return CUs.size(); } + unsigned global_variable_count() const { return GVs.size(); } + unsigned subprogram_count() const { return SPs.size(); } + unsigned type_count() const { return TYs.size(); } + unsigned scope_count() const { return Scopes.size(); } + +private: + SmallVector CUs; // Compile Units + SmallVector SPs; // Subprograms + SmallVector GVs; // Global Variables; + SmallVector TYs; // Types + SmallVector Scopes; // Scopes + SmallPtrSet NodesSeen; + DITypeIdentifierMap TypeIdentifierMap; + /// Specify if TypeIdentifierMap is initialized. + bool TypeMapInitialized; +}; } // end namespace llvm #endif diff --git a/contrib/llvm/include/llvm/DebugInfo/DIContext.h b/contrib/llvm/include/llvm/DebugInfo/DIContext.h index 8fcd9e0b8..a1a464210 100644 --- a/contrib/llvm/include/llvm/DebugInfo/DIContext.h +++ b/contrib/llvm/include/llvm/DebugInfo/DIContext.h @@ -21,6 +21,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Object/RelocVisitor.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/DataTypes.h" namespace llvm { @@ -37,11 +38,10 @@ public: DILineInfo() : FileName(""), FunctionName(""), Line(0), Column(0) {} - DILineInfo(const SmallString<16> &fileName, - const SmallString<16> &functionName, - uint32_t line, uint32_t column) - : FileName(fileName), FunctionName(functionName), - Line(line), Column(column) {} + DILineInfo(StringRef fileName, StringRef functionName, uint32_t line, + uint32_t column) + : FileName(fileName), FunctionName(functionName), Line(line), + Column(column) {} const char *getFileName() { return FileName.c_str(); } const char *getFunctionName() { return FunctionName.c_str(); } @@ -104,9 +104,14 @@ enum DIDumpType { DIDT_Frames, DIDT_Info, DIDT_InfoDwo, + DIDT_Types, DIDT_Line, + DIDT_Loc, DIDT_Ranges, DIDT_Pubnames, + DIDT_Pubtypes, + DIDT_GnuPubnames, + DIDT_GnuPubtypes, DIDT_Str, DIDT_StrDwo, DIDT_StrOffsetsDwo @@ -121,6 +126,12 @@ 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. @@ -134,6 +145,8 @@ public: uint64_t Size, DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0; virtual DIInliningInfo getInliningInfoForAddress(uint64_t Address, DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0; +private: + const DIContextKind Kind; }; } diff --git a/contrib/llvm/include/llvm/DebugInfo/DWARFFormValue.h b/contrib/llvm/include/llvm/DebugInfo/DWARFFormValue.h index eaaccfb4f..533d2593b 100644 --- a/contrib/llvm/include/llvm/DebugInfo/DWARFFormValue.h +++ b/contrib/llvm/include/llvm/DebugInfo/DWARFFormValue.h @@ -10,15 +10,31 @@ #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 DWARFCompileUnit; +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(NULL) { uval = 0; @@ -32,49 +48,36 @@ public: const uint8_t* data; }; - enum { - eValueTypeInvalid = 0, - eValueTypeUnsigned, - eValueTypeSigned, - eValueTypeCStr, - eValueTypeBlock - }; - -private: uint16_t Form; // Form for this value. ValueType Value; // Contains all data for the form. public: - DWARFFormValue(uint16_t form = 0) : Form(form) {} + DWARFFormValue(uint16_t Form = 0) : Form(Form) {} uint16_t getForm() const { return Form; } - const ValueType& value() const { return Value; } - void dump(raw_ostream &OS, const DWARFCompileUnit* cu) const; + bool isFormClass(FormClass FC) const; + + void dump(raw_ostream &OS, const DWARFUnit *U) const; bool extractValue(DataExtractor data, uint32_t *offset_ptr, - const DWARFCompileUnit *cu); + const DWARFUnit *u); bool isInlinedCStr() const { return Value.data != NULL && Value.data == (const uint8_t*)Value.cstr; } - const uint8_t *BlockData() const; - uint64_t getReference(const DWARFCompileUnit* cu) const; - /// Resolve any compile unit specific references so that we don't need - /// the compile unit at a later time in order to work with the form - /// value. - bool resolveCompileUnitReferences(const DWARFCompileUnit* cu); - uint64_t getUnsigned() const { return Value.uval; } - int64_t getSigned() const { return Value.sval; } - const char *getAsCString(const DataExtractor *debug_str_data_ptr) const; - const char *getIndirectCString(const DataExtractor *, - const DataExtractor *) const; - uint64_t getIndirectAddress(const DataExtractor *, - const DWARFCompileUnit *) const; + /// 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; + bool skipValue(DataExtractor debug_info_data, uint32_t *offset_ptr, - const DWARFCompileUnit *cu) const; + const DWARFUnit *u) const; static bool skipValue(uint16_t form, DataExtractor debug_info_data, - uint32_t *offset_ptr, const DWARFCompileUnit *cu); - static bool isBlockForm(uint16_t form); - static bool isDataForm(uint16_t form); - static const uint8_t *getFixedFormSizes(uint8_t AddrSize, uint16_t Version); + uint32_t *offset_ptr, const DWARFUnit *u); + + static ArrayRef getFixedFormSizes(uint8_t AddrSize, + uint16_t Version); }; } diff --git a/contrib/llvm/include/llvm/ExecutionEngine/ExecutionEngine.h b/contrib/llvm/include/llvm/ExecutionEngine/ExecutionEngine.h index bbaebc6f9..233084dd5 100644 --- a/contrib/llvm/include/llvm/ExecutionEngine/ExecutionEngine.h +++ b/contrib/llvm/include/llvm/ExecutionEngine/ExecutionEngine.h @@ -16,7 +16,6 @@ #define LLVM_EXECUTIONENGINE_EXECUTIONENGINE_H #include "llvm-c/ExecutionEngine.h" -#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/ValueMap.h" @@ -34,6 +33,7 @@ namespace llvm { struct GenericValue; class Constant; +class DataLayout; class ExecutionEngine; class Function; class GlobalVariable; @@ -44,7 +44,7 @@ class MachineCodeInfo; class Module; class MutexGuard; class ObjectCache; -class DataLayout; +class RTDyldMemoryManager; class Triple; class Type; @@ -142,7 +142,7 @@ protected: static ExecutionEngine *(*MCJITCtor)( Module *M, std::string *ErrorStr, - JITMemoryManager *JMM, + RTDyldMemoryManager *MCJMM, bool GVsWithCode, TargetMachine *TM); static ExecutionEngine *(*InterpCtor)(Module *M, std::string *ErrorStr); @@ -152,17 +152,8 @@ protected: /// abort. void *(*LazyFunctionCreator)(const std::string &); - /// ExceptionTableRegister - If Exception Handling is set, the JIT will - /// register dwarf tables with this function. - typedef void (*EERegisterFn)(void*); - EERegisterFn ExceptionTableRegister; - EERegisterFn ExceptionTableDeregister; - /// This maps functions to their exception tables frames. - DenseMap AllExceptionTables; - - public: - /// lock - This lock protects the ExecutionEngine, JIT, JITResolver and + /// lock - This lock protects the ExecutionEngine, MCJIT, JIT, JITResolver and /// JITEmitter classes. It must be held while changing the internal state of /// any of those classes. sys::Mutex lock; @@ -224,7 +215,7 @@ public: /// FindFunctionNamed - Search all of the active modules to find the one that /// defines FnName. This is very slow operation and shouldn't be used for /// general code. - Function *FindFunctionNamed(const char *FnName); + virtual Function *FindFunctionNamed(const char *FnName); /// runFunction - Execute the specified function with the specified arguments, /// and return the result. @@ -239,6 +230,11 @@ public: /// found, this function silently returns a null pointer. Otherwise, /// it prints a message to stderr and aborts. /// + /// This function is deprecated for the MCJIT execution engine. + /// + /// FIXME: the JIT and MCJIT interfaces should be disentangled or united + /// again, if possible. + /// virtual void *getPointerToNamedFunction(const std::string &Name, bool AbortOnFailure = true) = 0; @@ -251,18 +247,38 @@ public: "EE!"); } - // finalizeObject - This method should be called after sections within an - // object have been relocated using mapSectionAddress. When this method is - // called the MCJIT execution engine will reapply relocations for a loaded - // object. This method has no effect for the legacy JIT engine or the - // interpeter. + /// generateCodeForModule - Run code generationen for the specified module and + /// load it into memory. + /// + /// When this function has completed, all code and data for the specified + /// module, and any module on which this module depends, will be generated + /// and loaded into memory, but relocations will not yet have been applied + /// and all memory will be readable and writable but not executable. + /// + /// This function is primarily useful when generating code for an external + /// target, allowing the client an opportunity to remap section addresses + /// before relocations are applied. Clients that intend to execute code + /// locally can use the getFunctionAddress call, which will generate code + /// and apply final preparations all in one step. + /// + /// This method has no effect for the legacy JIT engine or the interpeter. + virtual void generateCodeForModule(Module *M) {} + + /// finalizeObject - ensure the module is fully processed and is usable. + /// + /// It is the user-level function for completing the process of making the + /// object usable for execution. It should be called after sections within an + /// object have been relocated using mapSectionAddress. When this method is + /// called the MCJIT execution engine will reapply relocations for a loaded + /// object. This method has no effect for the legacy JIT engine or the + /// interpeter. virtual void finalizeObject() {} /// runStaticConstructorsDestructors - This method is used to execute all of /// the static constructors or destructors for a program. /// /// \param isDtors - Run the destructors instead of constructors. - void runStaticConstructorsDestructors(bool isDtors); + virtual void runStaticConstructorsDestructors(bool isDtors); /// runStaticConstructorsDestructors - This method is used to execute all of /// the static constructors or destructors for a particular module. @@ -303,10 +319,16 @@ public: /// getPointerToGlobalIfAvailable - This returns the address of the specified /// global value if it is has already been codegen'd, otherwise it returns /// null. + /// + /// This function is deprecated for the MCJIT execution engine. It doesn't + /// seem to be needed in that case, but an equivalent can be added if it is. void *getPointerToGlobalIfAvailable(const GlobalValue *GV); /// getPointerToGlobal - This returns the address of the specified global /// value. This may involve code generation if it's a function. + /// + /// This function is deprecated for the MCJIT execution engine. Use + /// getGlobalValueAddress instead. void *getPointerToGlobal(const GlobalValue *GV); /// getPointerToFunction - The different EE's represent function bodies in @@ -314,22 +336,48 @@ public: /// pointer should look like. When F is destroyed, the ExecutionEngine will /// remove its global mapping and free any machine code. Be sure no threads /// are running inside F when that happens. + /// + /// This function is deprecated for the MCJIT execution engine. Use + /// getFunctionAddress instead. virtual void *getPointerToFunction(Function *F) = 0; /// getPointerToBasicBlock - The different EE's represent basic blocks in /// different ways. Return the representation for a blockaddress of the /// specified block. + /// + /// This function will not be implemented for the MCJIT execution engine. virtual void *getPointerToBasicBlock(BasicBlock *BB) = 0; /// getPointerToFunctionOrStub - If the specified function has been /// code-gen'd, return a pointer to the function. If not, compile it, or use /// a stub to implement lazy compilation if available. See /// getPointerToFunction for the requirements on destroying F. + /// + /// This function is deprecated for the MCJIT execution engine. Use + /// getFunctionAddress instead. virtual void *getPointerToFunctionOrStub(Function *F) { // Default implementation, just codegen the function. return getPointerToFunction(F); } + /// getGlobalValueAddress - Return the address of the specified global + /// value. This may involve code generation. + /// + /// This function should not be called with the JIT or interpreter engines. + virtual uint64_t getGlobalValueAddress(const std::string &Name) { + // Default implementation for JIT and interpreter. MCJIT will override this. + // JIT and interpreter clients should use getPointerToGlobal instead. + return 0; + } + + /// getFunctionAddress - Return the address of the specified function. + /// This may involve code generation. + virtual uint64_t getFunctionAddress(const std::string &Name) { + // Default implementation for JIT and interpreter. MCJIT will override this. + // JIT and interpreter clients should use getPointerToFunction instead. + return 0; + } + // The JIT overrides a version that actually does this. virtual void runJITOnFunction(Function *, MachineCodeInfo * = 0) { } @@ -362,6 +410,9 @@ public: /// getOrEmitGlobalVariable - Return the address of the specified global /// variable, possibly emitting it to memory if needed. This is used by the /// Emitter. + /// + /// This function is deprecated for the MCJIT execution engine. Use + /// getGlobalValueAddress instead. virtual void *getOrEmitGlobalVariable(const GlobalVariable *GV) { return getPointerToGlobal((const GlobalValue *)GV); } @@ -431,41 +482,6 @@ public: LazyFunctionCreator = P; } - /// InstallExceptionTableRegister - The JIT will use the given function - /// to register the exception tables it generates. - void InstallExceptionTableRegister(EERegisterFn F) { - ExceptionTableRegister = F; - } - void InstallExceptionTableDeregister(EERegisterFn F) { - ExceptionTableDeregister = F; - } - - /// RegisterTable - Registers the given pointer as an exception table. It - /// uses the ExceptionTableRegister function. - void RegisterTable(const Function *fn, void* res) { - if (ExceptionTableRegister) { - ExceptionTableRegister(res); - AllExceptionTables[fn] = res; - } - } - - /// DeregisterTable - Deregisters the exception frame previously registered - /// for the given function. - void DeregisterTable(const Function *Fn) { - if (ExceptionTableDeregister) { - DenseMap::iterator frame = - AllExceptionTables.find(Fn); - if(frame != AllExceptionTables.end()) { - ExceptionTableDeregister(frame->second); - AllExceptionTables.erase(frame); - } - } - } - - /// DeregisterAllTables - Deregisters all previously registered pointers to an - /// exception tables. It uses the ExceptionTableoDeregister function. - void DeregisterAllTables(); - protected: explicit ExecutionEngine(Module *M); @@ -496,6 +512,7 @@ private: EngineKind::Kind WhichEngine; std::string *ErrorStr; CodeGenOpt::Level OptLevel; + RTDyldMemoryManager *MCJMM; JITMemoryManager *JMM; bool AllocateGVsWithCode; TargetOptions Options; @@ -511,6 +528,7 @@ private: WhichEngine = EngineKind::Either; ErrorStr = NULL; OptLevel = CodeGenOpt::Default; + MCJMM = NULL; JMM = NULL; Options = TargetOptions(); AllocateGVsWithCode = false; @@ -532,12 +550,29 @@ public: WhichEngine = w; return *this; } + + /// setMCJITMemoryManager - Sets the MCJIT memory manager to use. This allows + /// clients to customize their memory allocation policies for the MCJIT. This + /// is only appropriate for the MCJIT; setting this and configuring the builder + /// to create anything other than MCJIT will cause a runtime error. If create() + /// is called and is successful, the created engine takes ownership of the + /// memory manager. This option defaults to NULL. Using this option nullifies + /// the setJITMemoryManager() option. + EngineBuilder &setMCJITMemoryManager(RTDyldMemoryManager *mcjmm) { + MCJMM = mcjmm; + JMM = NULL; + return *this; + } - /// setJITMemoryManager - Sets the memory manager to use. This allows - /// clients to customize their memory allocation policies. If create() is - /// called and is successful, the created engine takes ownership of the - /// memory manager. This option defaults to NULL. + /// setJITMemoryManager - Sets the JIT memory manager to use. This allows + /// clients to customize their memory allocation policies. This is only + /// appropriate for either JIT or MCJIT; setting this and configuring the + /// builder to create an interpreter will cause a runtime error. If create() + /// is called and is successful, the created engine takes ownership of the + /// memory manager. This option defaults to NULL. This option overrides + /// setMCJITMemoryManager() as well. EngineBuilder &setJITMemoryManager(JITMemoryManager *jmm) { + MCJMM = NULL; JMM = jmm; return *this; } diff --git a/contrib/llvm/include/llvm/ExecutionEngine/JITMemoryManager.h b/contrib/llvm/include/llvm/ExecutionEngine/JITMemoryManager.h index 714a98055..b22d899c9 100644 --- a/contrib/llvm/include/llvm/ExecutionEngine/JITMemoryManager.h +++ b/contrib/llvm/include/llvm/ExecutionEngine/JITMemoryManager.h @@ -115,22 +115,6 @@ public: /// emitting a function. virtual void deallocateFunctionBody(void *Body) = 0; - /// startExceptionTable - When we finished JITing the function, if exception - /// handling is set, we emit the exception table. - virtual uint8_t* startExceptionTable(const Function* F, - uintptr_t &ActualSize) = 0; - - /// endExceptionTable - This method is called when the JIT is done emitting - /// the exception table. - virtual void endExceptionTable(const Function *F, uint8_t *TableStart, - uint8_t *TableEnd, uint8_t* FrameRegister) = 0; - - /// deallocateExceptionTable - Free the specified exception table's memory. - /// The argument must be the return value from a call to startExceptionTable() - /// that hasn't been deallocated yet. This is never called when the JIT is - /// currently emitting an exception table. - virtual void deallocateExceptionTable(void *ET) = 0; - /// CheckInvariants - For testing only. Return true if all internal /// invariants are preserved, or return false and set ErrorStr to a helpful /// error message. diff --git a/contrib/llvm/include/llvm/ExecutionEngine/ObjectBuffer.h b/contrib/llvm/include/llvm/ExecutionEngine/ObjectBuffer.h index 96a48b28b..af2a9263f 100644 --- a/contrib/llvm/include/llvm/ExecutionEngine/ObjectBuffer.h +++ b/contrib/llvm/include/llvm/ExecutionEngine/ObjectBuffer.h @@ -30,6 +30,7 @@ namespace llvm { /// ObjectFile) as needed, but the MemoryBuffer instance returned does not own the /// actual memory it points to. class ObjectBuffer { + virtual void anchor(); public: ObjectBuffer() {} ObjectBuffer(MemoryBuffer* Buf) : Buffer(Buf) {} @@ -44,6 +45,7 @@ public: const char *getBufferStart() const { return Buffer->getBufferStart(); } size_t getBufferSize() const { return Buffer->getBufferSize(); } + StringRef getBuffer() const { return Buffer->getBuffer(); } protected: // The memory contained in an ObjectBuffer @@ -55,6 +57,7 @@ protected: /// while providing a common ObjectBuffer interface for access to the /// memory once the object has been generated. class ObjectBufferStream : public ObjectBuffer { + virtual void anchor(); public: ObjectBufferStream() : OS(SV) {} virtual ~ObjectBufferStream() {} diff --git a/contrib/llvm/include/llvm/ExecutionEngine/ObjectCache.h b/contrib/llvm/include/llvm/ExecutionEngine/ObjectCache.h index 0bee86161..d1849dfc3 100644 --- a/contrib/llvm/include/llvm/ExecutionEngine/ObjectCache.h +++ b/contrib/llvm/include/llvm/ExecutionEngine/ObjectCache.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_LIB_EXECUTIONENGINE_OBJECTCACHE_H -#define LLVM_LIB_EXECUTIONENGINE_OBJECTCACHE_H +#ifndef LLVM_EXECUTIONENGINE_OBJECTCACHE_H +#define LLVM_EXECUTIONENGINE_OBJECTCACHE_H #include "llvm/Support/MemoryBuffer.h" @@ -20,6 +20,7 @@ class Module; /// ExecutionEngine for the purpose of avoiding compilation for Modules that /// have already been compiled and an object file is available. class ObjectCache { + virtual void anchor(); public: ObjectCache() { } @@ -30,23 +31,9 @@ public: /// getObjectCopy - Returns a pointer to a newly allocated MemoryBuffer that /// contains the object which corresponds with Module M, or 0 if an object is - /// not available. The caller owns the MemoryBuffer returned by this function. - MemoryBuffer* getObjectCopy(const Module* M) { - const MemoryBuffer* Obj = getObject(M); - if (Obj) - return MemoryBuffer::getMemBufferCopy(Obj->getBuffer()); - else - return 0; - } - -protected: - /// getObject - Returns a pointer to a MemoryBuffer that contains an object - /// that corresponds with Module M, or 0 if an object is not available. - /// The pointer returned by this function is not suitable for loading because - /// the memory is read-only and owned by the ObjectCache. To retrieve an - /// owning pointer to a MemoryBuffer (which is suitable for calling - /// RuntimeDyld::loadObject() with) use getObjectCopy() instead. - virtual const MemoryBuffer* getObject(const Module* M) = 0; + /// not available. The caller owns both the MemoryBuffer returned by this + /// and the memory it references. + virtual MemoryBuffer* getObject(const Module* M) = 0; }; } diff --git a/contrib/llvm/include/llvm/ExecutionEngine/ObjectImage.h b/contrib/llvm/include/llvm/ExecutionEngine/ObjectImage.h index 9fddca7e3..076f4b114 100644 --- a/contrib/llvm/include/llvm/ExecutionEngine/ObjectImage.h +++ b/contrib/llvm/include/llvm/ExecutionEngine/ObjectImage.h @@ -25,6 +25,7 @@ namespace llvm { class ObjectImage { ObjectImage() LLVM_DELETED_FUNCTION; ObjectImage(const ObjectImage &other) LLVM_DELETED_FUNCTION; + virtual void anchor(); protected: OwningPtr Buffer; diff --git a/contrib/llvm/include/llvm/ExecutionEngine/RTDyldMemoryManager.h b/contrib/llvm/include/llvm/ExecutionEngine/RTDyldMemoryManager.h new file mode 100644 index 000000000..3ad2e5022 --- /dev/null +++ b/contrib/llvm/include/llvm/ExecutionEngine/RTDyldMemoryManager.h @@ -0,0 +1,112 @@ +//===-- RTDyldMemoryManager.cpp - Memory manager for MC-JIT -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Interface of the runtime dynamic memory manager base class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_RT_DYLD_MEMORY_MANAGER_H +#define LLVM_EXECUTIONENGINE_RT_DYLD_MEMORY_MANAGER_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/CBindingWrapping.h" +#include "llvm/Support/Memory.h" +#include "llvm-c/ExecutionEngine.h" + +namespace llvm { + +class ExecutionEngine; +class ObjectImage; + +// RuntimeDyld clients often want to handle the memory management of +// what gets placed where. For JIT clients, this is the subset of +// JITMemoryManager required for dynamic loading of binaries. +// +// FIXME: As the RuntimeDyld fills out, additional routines will be needed +// for the varying types of objects to be allocated. +class RTDyldMemoryManager { + RTDyldMemoryManager(const RTDyldMemoryManager&) LLVM_DELETED_FUNCTION; + void operator=(const RTDyldMemoryManager&) LLVM_DELETED_FUNCTION; +public: + RTDyldMemoryManager() {} + virtual ~RTDyldMemoryManager(); + + /// Allocate a memory block of (at least) the given size suitable for + /// executable code. The SectionID is a unique identifier assigned by the JIT + /// engine, and optionally recorded by the memory manager to access a loaded + /// section. + virtual uint8_t *allocateCodeSection( + uintptr_t Size, unsigned Alignment, unsigned SectionID, + StringRef SectionName) = 0; + + /// Allocate a memory block of (at least) the given size suitable for data. + /// The SectionID is a unique identifier assigned by the JIT engine, and + /// optionally recorded by the memory manager to access a loaded section. + virtual uint8_t *allocateDataSection( + uintptr_t Size, unsigned Alignment, unsigned SectionID, + StringRef SectionName, bool IsReadOnly) = 0; + + /// Register the EH frames with the runtime so that c++ exceptions work. + /// + /// \p Addr parameter provides the local address of the EH frame section + /// data, while \p LoadAddr provides the address of the data in the target + /// address space. If the section has not been remapped (which will usually + /// be the case for local execution) these two values will be the same. + virtual void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size); + + virtual void deregisterEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size); + + /// This method returns the address of the specified function or variable. + /// It is used to resolve symbols during module linking. + virtual uint64_t getSymbolAddress(const std::string &Name); + + /// This method returns the address of the specified function. As such it is + /// only useful for resolving library symbols, not code generated symbols. + /// + /// If \p AbortOnFailure is false and no function with the given name is + /// found, this function returns a null pointer. Otherwise, it prints a + /// message to stderr and aborts. + /// + /// This function is deprecated for memory managers to be used with + /// MCJIT or RuntimeDyld. Use getSymbolAddress instead. + virtual void *getPointerToNamedFunction(const std::string &Name, + bool AbortOnFailure = true); + + /// This method is called after an object has been loaded into memory but + /// before relocations are applied to the loaded sections. The object load + /// may have been initiated by MCJIT to resolve an external symbol for another + /// object that is being finalized. In that case, the object about which + /// the memory manager is being notified will be finalized immediately after + /// the memory manager returns from this call. + /// + /// Memory managers which are preparing code for execution in an external + /// address space can use this call to remap the section addresses for the + /// newly loaded object. + virtual void notifyObjectLoaded(ExecutionEngine *EE, + const ObjectImage *) {} + + /// This method is called when object loading is complete and section page + /// permissions can be applied. It is up to the memory manager implementation + /// to decide whether or not to act on this method. The memory manager will + /// typically allocate all sections as read-write and then apply specific + /// permissions when this method is called. Code sections cannot be executed + /// until this function has been called. In addition, any cache coherency + /// operations needed to reliably use the memory are also performed. + /// + /// Returns true if an error occurred, false otherwise. + virtual bool finalizeMemory(std::string *ErrMsg = 0) = 0; +}; + +// Create wrappers for C Binding types (see CBindingWrapping.h). +DEFINE_SIMPLE_CONVERSION_FUNCTIONS( + RTDyldMemoryManager, LLVMMCJITMemoryManagerRef) + +} // namespace llvm + +#endif // LLVM_EXECUTIONENGINE_RT_DYLD_MEMORY_MANAGER_H diff --git a/contrib/llvm/include/llvm/ExecutionEngine/RuntimeDyld.h b/contrib/llvm/include/llvm/ExecutionEngine/RuntimeDyld.h index c6c126c6e..b8324387b 100644 --- a/contrib/llvm/include/llvm/ExecutionEngine/RuntimeDyld.h +++ b/contrib/llvm/include/llvm/ExecutionEngine/RuntimeDyld.h @@ -16,6 +16,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/ExecutionEngine/ObjectBuffer.h" +#include "llvm/ExecutionEngine/RTDyldMemoryManager.h" #include "llvm/Support/Memory.h" namespace llvm { @@ -23,56 +24,6 @@ namespace llvm { class RuntimeDyldImpl; class ObjectImage; -// RuntimeDyld clients often want to handle the memory management of -// what gets placed where. For JIT clients, this is the subset of -// JITMemoryManager required for dynamic loading of binaries. -// -// FIXME: As the RuntimeDyld fills out, additional routines will be needed -// for the varying types of objects to be allocated. -class RTDyldMemoryManager { - RTDyldMemoryManager(const RTDyldMemoryManager&) LLVM_DELETED_FUNCTION; - void operator=(const RTDyldMemoryManager&) LLVM_DELETED_FUNCTION; -public: - RTDyldMemoryManager() {} - virtual ~RTDyldMemoryManager(); - - /// Allocate a memory block of (at least) the given size suitable for - /// executable code. The SectionID is a unique identifier assigned by the JIT - /// engine, and optionally recorded by the memory manager to access a loaded - /// section. - virtual uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, - unsigned SectionID) = 0; - - /// Allocate a memory block of (at least) the given size suitable for data. - /// The SectionID is a unique identifier assigned by the JIT engine, and - /// optionally recorded by the memory manager to access a loaded section. - virtual uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, - unsigned SectionID, bool IsReadOnly) = 0; - - /// This method returns the address of the specified function. As such it is - /// only useful for resolving library symbols, not code generated symbols. - /// - /// If AbortOnFailure is false and no function with the given name is - /// found, this function returns a null pointer. Otherwise, it prints a - /// message to stderr and aborts. - virtual void *getPointerToNamedFunction(const std::string &Name, - bool AbortOnFailure = true) = 0; - - /// This method is called when object loading is complete and section page - /// permissions can be applied. It is up to the memory manager implementation - /// to decide whether or not to act on this method. The memory manager will - /// typically allocate all sections as read-write and then apply specific - /// permissions when this method is called. - /// - /// Returns true if an error occurred, false otherwise. - virtual bool applyPermissions(std::string *ErrMsg = 0) = 0; - - /// Register the EH frames with the runtime so that c++ exceptions work. The - /// default implementation does nothing. Look at SectionMemoryManager for one - /// that uses __register_frame. - virtual void registerEHFrames(StringRef SectionData); -}; - class RuntimeDyld { RuntimeDyld(const RuntimeDyld &) LLVM_DELETED_FUNCTION; void operator=(const RuntimeDyld &) LLVM_DELETED_FUNCTION; @@ -113,9 +64,16 @@ public: /// This is the address which will be used for relocation resolution. void mapSectionAddress(const void *LocalAddress, uint64_t TargetAddress); - StringRef getErrorString(); + /// Register any EH frame sections that have been loaded but not previously + /// registered with the memory manager. Note, RuntimeDyld is responsible + /// for identifying the EH frame and calling the memory manager with the + /// EH frame section data. However, the memory manager itself will handle + /// the actual target-specific EH frame registration. + void registerEHFrames(); + + void deregisterEHFrames(); - StringRef getEHFrameSection(); + StringRef getErrorString(); }; } // end namespace llvm diff --git a/contrib/llvm/include/llvm/ExecutionEngine/SectionMemoryManager.h b/contrib/llvm/include/llvm/ExecutionEngine/SectionMemoryManager.h index 84a4e08cb..fd6e41f91 100644 --- a/contrib/llvm/include/llvm/ExecutionEngine/SectionMemoryManager.h +++ b/contrib/llvm/include/llvm/ExecutionEngine/SectionMemoryManager.h @@ -16,7 +16,7 @@ #define LLVM_EXECUTIONENGINE_SECTIONMEMORYMANAGER_H #include "llvm/ADT/SmallVector.h" -#include "llvm/ExecutionEngine/JITMemoryManager.h" +#include "llvm/ExecutionEngine/RuntimeDyld.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Memory.h" @@ -33,9 +33,9 @@ namespace llvm { /// Any client using this memory manager MUST ensure that section-specific /// page permissions have been applied before attempting to execute functions /// in the JITed object. Permissions can be applied either by calling -/// MCJIT::finalizeObject or by calling SectionMemoryManager::applyPermissions +/// MCJIT::finalizeObject or by calling SectionMemoryManager::finalizeMemory /// directly. Clients of MCJIT should call MCJIT::finalizeObject. -class SectionMemoryManager : public JITMemoryManager { +class SectionMemoryManager : public RTDyldMemoryManager { SectionMemoryManager(const SectionMemoryManager&) LLVM_DELETED_FUNCTION; void operator=(const SectionMemoryManager&) LLVM_DELETED_FUNCTION; @@ -49,7 +49,8 @@ public: /// The value of \p Alignment must be a power of two. If \p Alignment is zero /// a default alignment of 16 will be used. virtual uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, - unsigned SectionID); + unsigned SectionID, + StringRef SectionName); /// \brief Allocates a memory block of (at least) the given size suitable for /// executable code. @@ -58,30 +59,21 @@ public: /// a default alignment of 16 will be used. virtual uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, unsigned SectionID, + StringRef SectionName, bool isReadOnly); - /// \brief Applies section-specific memory permissions. + /// \brief Update section-specific memory permissions and other attributes. /// /// This method is called when object loading is complete and section page /// permissions can be applied. It is up to the memory manager implementation /// to decide whether or not to act on this method. The memory manager will /// typically allocate all sections as read-write and then apply specific /// permissions when this method is called. Code sections cannot be executed - /// until this function has been called. + /// until this function has been called. In addition, any cache coherency + /// operations needed to reliably use the memory are also performed. /// /// \returns true if an error occurred, false otherwise. - virtual bool applyPermissions(std::string *ErrMsg = 0); - - void registerEHFrames(StringRef SectionData); - - /// This method returns the address of the specified function. As such it is - /// only useful for resolving library symbols, not code generated symbols. - /// - /// If \p AbortOnFailure is false and no function with the given name is - /// found, this function returns a null pointer. Otherwise, it prints a - /// message to stderr and aborts. - virtual void *getPointerToNamedFunction(const std::string &Name, - bool AbortOnFailure = true); + virtual bool finalizeMemory(std::string *ErrMsg = 0); /// \brief Invalidate instruction cache for code sections. /// @@ -89,7 +81,7 @@ public: /// explicit cache flush, otherwise JIT code manipulations (like resolved /// relocations) will get to the data cache but not to the instruction cache. /// - /// This method is called from applyPermissions. + /// This method is called from finalizeMemory. virtual void invalidateInstructionCache(); private: @@ -108,66 +100,6 @@ private: MemoryGroup CodeMem; MemoryGroup RWDataMem; MemoryGroup RODataMem; - -public: - /// - /// Functions below are not used by MCJIT or RuntimeDyld, but must be - /// implemented because they are declared as pure virtuals in the base class. - /// - - virtual void setMemoryWritable() { - llvm_unreachable("Unexpected call!"); - } - virtual void setMemoryExecutable() { - llvm_unreachable("Unexpected call!"); - } - virtual void setPoisonMemory(bool poison) { - llvm_unreachable("Unexpected call!"); - } - virtual void AllocateGOT() { - llvm_unreachable("Unexpected call!"); - } - virtual uint8_t *getGOTBase() const { - llvm_unreachable("Unexpected call!"); - return 0; - } - virtual uint8_t *startFunctionBody(const Function *F, - uintptr_t &ActualSize){ - llvm_unreachable("Unexpected call!"); - return 0; - } - virtual uint8_t *allocateStub(const GlobalValue *F, unsigned StubSize, - unsigned Alignment) { - llvm_unreachable("Unexpected call!"); - return 0; - } - virtual void endFunctionBody(const Function *F, uint8_t *FunctionStart, - uint8_t *FunctionEnd) { - llvm_unreachable("Unexpected call!"); - } - virtual uint8_t *allocateSpace(intptr_t Size, unsigned Alignment) { - llvm_unreachable("Unexpected call!"); - return 0; - } - virtual uint8_t *allocateGlobal(uintptr_t Size, unsigned Alignment) { - llvm_unreachable("Unexpected call!"); - return 0; - } - virtual void deallocateFunctionBody(void *Body) { - llvm_unreachable("Unexpected call!"); - } - virtual uint8_t *startExceptionTable(const Function *F, - uintptr_t &ActualSize) { - llvm_unreachable("Unexpected call!"); - return 0; - } - virtual void endExceptionTable(const Function *F, uint8_t *TableStart, - uint8_t *TableEnd, uint8_t *FrameRegister) { - llvm_unreachable("Unexpected call!"); - } - virtual void deallocateExceptionTable(void *ET) { - llvm_unreachable("Unexpected call!"); - } }; } diff --git a/contrib/llvm/include/llvm/GVMaterializer.h b/contrib/llvm/include/llvm/GVMaterializer.h index 1e5c4263d..8efe50ae9 100644 --- a/contrib/llvm/include/llvm/GVMaterializer.h +++ b/contrib/llvm/include/llvm/GVMaterializer.h @@ -18,7 +18,7 @@ #ifndef LLVM_GVMATERIALIZER_H #define LLVM_GVMATERIALIZER_H -#include +#include "llvm/Support/system_error.h" namespace llvm { @@ -41,11 +41,9 @@ public: /// dematerialized back to whatever backing store this GVMaterializer uses. virtual bool isDematerializable(const GlobalValue *GV) const = 0; - /// Materialize - make sure the given GlobalValue is fully read. If the - /// module is corrupt, this returns true and fills in the optional string with - /// information about the problem. If successful, this returns false. + /// Materialize - make sure the given GlobalValue is fully read. /// - virtual bool Materialize(GlobalValue *GV, std::string *ErrInfo = 0) = 0; + virtual error_code Materialize(GlobalValue *GV) = 0; /// Dematerialize - If the given GlobalValue is read in, and if the /// GVMaterializer supports it, release the memory for the GV, and set it up @@ -55,10 +53,8 @@ public: virtual void Dematerialize(GlobalValue *) {} /// MaterializeModule - make sure the entire Module has been completely read. - /// On error, this returns true and fills in the optional string with - /// information about the problem. If successful, this returns false. /// - virtual bool MaterializeModule(Module *M, std::string *ErrInfo = 0) = 0; + virtual error_code MaterializeModule(Module *M) = 0; }; } // End llvm namespace diff --git a/contrib/llvm/include/llvm/IR/Argument.h b/contrib/llvm/include/llvm/IR/Argument.h index 40d61ff68..eb6ed46b4 100644 --- a/contrib/llvm/include/llvm/IR/Argument.h +++ b/contrib/llvm/include/llvm/IR/Argument.h @@ -82,6 +82,11 @@ public: /// its containing function. bool hasReturnedAttr() const; + /// \brief Return true if this argument has the readonly or readnone attribute + /// on it in its containing function. + bool onlyReadsMemory() const; + + /// \brief Add a Attribute to an argument. void addAttr(AttributeSet AS); diff --git a/contrib/llvm/include/llvm/IR/Attributes.h b/contrib/llvm/include/llvm/IR/Attributes.h index 2c7da6485..c23ba0f73 100644 --- a/contrib/llvm/include/llvm/IR/Attributes.h +++ b/contrib/llvm/include/llvm/IR/Attributes.h @@ -18,6 +18,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/FoldingSet.h" +#include "llvm/Support/Compiler.h" #include "llvm/Support/PointerLikeTypeTraits.h" #include #include @@ -67,7 +68,10 @@ public: ///< stored as log2 of alignment with +1 bias ///< 0 means unaligned (different from align(1)) AlwaysInline, ///< inline=always + Builtin, ///< Callee is recognized as a builtin, despite + ///< nobuiltin attribute on its declaration. ByVal, ///< Pass structure by value + Cold, ///< Marks function as being in a cold path. InlineHint, ///< Source said inlining was desirable InReg, ///< Force argument to be passed in register MinSize, ///< Function must be optimized for size first @@ -85,6 +89,7 @@ public: NoReturn, ///< Mark the function as not returning NoUnwind, ///< Function doesn't unwind stack OptimizeForSize, ///< opt_size + OptimizeNone, ///< Function must not be optimized. ReadNone, ///< Function does not access memory ReadOnly, ///< Function only reads from memory Returned, ///< Return value is always equal to this argument @@ -196,7 +201,7 @@ public: /// index `1'. class AttributeSet { public: - enum AttrIndex { + enum AttrIndex LLVM_ENUM_INT_TYPE(unsigned) { ReturnIndex = 0U, FunctionIndex = ~0U }; @@ -247,6 +252,8 @@ public: /// attribute sets are immutable, this returns a new set. AttributeSet addAttribute(LLVMContext &C, unsigned Index, StringRef Kind) const; + AttributeSet addAttribute(LLVMContext &C, unsigned Index, + StringRef Kind, StringRef Value) const; /// \brief Add attributes to the attribute set at the given index. Since /// attribute sets are immutable, this returns a new set. diff --git a/contrib/llvm/include/llvm/IR/CallingConv.h b/contrib/llvm/include/llvm/IR/CallingConv.h index 413f93abf..4437af255 100644 --- a/contrib/llvm/include/llvm/IR/CallingConv.h +++ b/contrib/llvm/include/llvm/IR/CallingConv.h @@ -51,6 +51,13 @@ namespace CallingConv { // (HiPE). HiPE = 11, + // WebKit JS - Calling convention for stack based JavaScript calls + WebKit_JS = 12, + + // AnyReg - Calling convention for dynamic register based calls (e.g. + // stackmap and patchpoint intrinsics). + AnyReg = 13, + // Target - This is the start of the target-specific calling conventions, // e.g. fastcall and thiscall on X86. FirstTargetCC = 64, @@ -93,13 +100,6 @@ namespace CallingConv { /// Passes all arguments in register or parameter space. PTX_Device = 72, - /// MBLAZE_INTR - Calling convention used for MBlaze interrupt routines. - MBLAZE_INTR = 73, - - /// MBLAZE_INTR - Calling convention used for MBlaze interrupt support - /// routines (i.e. GCC's save_volatiles attribute). - MBLAZE_SVOL = 74, - /// SPIR_FUNC - Calling convention for SPIR non-kernel device functions. /// No lowering or expansion of arguments. /// Structures are passed as a pointer to a struct with the byval attribute. diff --git a/contrib/llvm/include/llvm/IR/Constants.h b/contrib/llvm/include/llvm/IR/Constants.h index 2f29f5459..dac20c9ec 100644 --- a/contrib/llvm/include/llvm/IR/Constants.h +++ b/contrib/llvm/include/llvm/IR/Constants.h @@ -112,7 +112,6 @@ public: /// Return the constant as a 64-bit unsigned integer value after it /// has been zero extended as appropriate for the type of this constant. Note /// that this method can assert if the value does not fit in 64 bits. - /// @deprecated /// @brief Return the zero extended value. inline uint64_t getZExtValue() const { return Val.getZExtValue(); @@ -121,7 +120,6 @@ public: /// Return the constant as a 64-bit integer value after it has been sign /// extended as appropriate for the type of this constant. Note that /// this method can assert if the value does not fit in 64 bits. - /// @deprecated /// @brief Return the sign extended value. inline int64_t getSExtValue() const { return Val.getSExtValue(); @@ -864,6 +862,7 @@ public: static Constant *getPtrToInt(Constant *C, Type *Ty); static Constant *getIntToPtr(Constant *C, Type *Ty); static Constant *getBitCast (Constant *C, Type *Ty); + static Constant *getAddrSpaceCast(Constant *C, Type *Ty); static Constant *getNSWNeg(Constant *C) { return getNeg(C, false, true); } static Constant *getNUWNeg(Constant *C) { return getNeg(C, true, false); } @@ -944,12 +943,20 @@ public: Type *Ty ///< The type to trunc or bitcast C to ); - /// @brief Create a BitCast or a PtrToInt cast constant expression + /// @brief Create a BitCast, AddrSpaceCast, or a PtrToInt cast constant + /// expression. static Constant *getPointerCast( Constant *C, ///< The pointer value to be casted (operand 0) Type *Ty ///< The type to which cast should be made ); + /// @brief Create a BitCast or AddrSpaceCast for a pointer type depending on + /// the address space. + static Constant *getPointerBitCastOrAddrSpaceCast( + Constant *C, ///< The constant to addrspacecast or bitcast + Type *Ty ///< The type to bitcast or addrspacecast C to + ); + /// @brief Create a ZExt, Bitcast or Trunc for integer -> integer casts static Constant *getIntegerCast( Constant *C, ///< The integer constant to be casted @@ -1081,8 +1088,8 @@ public: /// as this ConstantExpr. The instruction is not linked to any basic block. /// /// A better approach to this could be to have a constructor for Instruction - /// which would take a ConstantExpr parameter, but that would have spread - /// implementation details of ConstantExpr outside of Constants.cpp, which + /// which would take a ConstantExpr parameter, but that would have spread + /// implementation details of ConstantExpr outside of Constants.cpp, which /// would make it harder to remove ConstantExprs altogether. Instruction *getAsInstruction(); diff --git a/contrib/llvm/include/llvm/IR/DataLayout.h b/contrib/llvm/include/llvm/IR/DataLayout.h index b0def6be3..10630a262 100644 --- a/contrib/llvm/include/llvm/IR/DataLayout.h +++ b/contrib/llvm/include/llvm/IR/DataLayout.h @@ -237,13 +237,14 @@ public: /// Layout pointer alignment /// FIXME: The defaults need to be removed once all of /// the backends/clients are updated. - unsigned getPointerABIAlignment(unsigned AS = 0) const { + unsigned getPointerABIAlignment(unsigned AS = 0) const { DenseMap::const_iterator val = Pointers.find(AS); if (val == Pointers.end()) { val = Pointers.find(0); } return val->second.ABIAlign; } + /// Return target's alignment for stack-based pointers /// FIXME: The defaults need to be removed once all of /// the backends/clients are updated. @@ -257,7 +258,7 @@ public: /// Layout pointer size /// FIXME: The defaults need to be removed once all of /// the backends/clients are updated. - unsigned getPointerSize(unsigned AS = 0) const { + unsigned getPointerSize(unsigned AS = 0) const { DenseMap::const_iterator val = Pointers.find(AS); if (val == Pointers.end()) { val = Pointers.find(0); @@ -267,9 +268,21 @@ public: /// Layout pointer size, in bits /// FIXME: The defaults need to be removed once all of /// the backends/clients are updated. - unsigned getPointerSizeInBits(unsigned AS = 0) const { + unsigned getPointerSizeInBits(unsigned AS = 0) const { return getPointerSize(AS) * 8; } + + /// Layout pointer size, in bits, based on the type. If this function is + /// called with a pointer type, then the type size of the pointer is returned. + /// If this function is called with a vector of pointers, then the type size + /// of the pointer is returned. This should only be called with a pointer or + /// vector of pointers. + unsigned getPointerTypeSizeInBits(Type *) const; + + unsigned getPointerTypeSize(Type *Ty) const { + return getPointerTypeSizeInBits(Ty) / 8; + } + /// Size examples: /// /// Type SizeInBits StoreSizeInBits AllocSizeInBits[*] @@ -356,6 +369,17 @@ public: /// least as big as Width bits. Type *getSmallestLegalIntType(LLVMContext &C, unsigned Width = 0) const; + /// getLargestLegalIntType - Return the largest legal integer type, or null if + /// none are set. + Type *getLargestLegalIntType(LLVMContext &C) const { + unsigned LargestSize = getLargestLegalIntTypeSize(); + return (LargestSize == 0) ? 0 : Type::getIntNTy(C, LargestSize); + } + + /// getLargestLegalIntType - Return the size of largest legal integer type + /// size, or 0 if none are set. + unsigned getLargestLegalIntTypeSize() const; + /// getIndexedOffset - return the offset from the beginning of the type for /// the specified indices. This is used to implement getelementptr. uint64_t getIndexedOffset(Type *Ty, ArrayRef Indices) const; @@ -438,7 +462,7 @@ inline uint64_t DataLayout::getTypeSizeInBits(Type *Ty) const { case Type::LabelTyID: return getPointerSizeInBits(0); case Type::PointerTyID: - return getPointerSizeInBits(cast(Ty)->getAddressSpace()); + return getPointerSizeInBits(Ty->getPointerAddressSpace()); case Type::ArrayTyID: { ArrayType *ATy = cast(Ty); return ATy->getNumElements() * @@ -448,7 +472,7 @@ inline uint64_t DataLayout::getTypeSizeInBits(Type *Ty) const { // Get the layout annotation... which is lazily created on demand. return getStructLayout(cast(Ty))->getSizeInBits(); case Type::IntegerTyID: - return cast(Ty)->getBitWidth(); + return Ty->getIntegerBitWidth(); case Type::HalfTyID: return 16; case Type::FloatTyID: diff --git a/contrib/llvm/include/llvm/IR/Function.h b/contrib/llvm/include/llvm/IR/Function.h index f97929f65..bba7ecdd2 100644 --- a/contrib/llvm/include/llvm/IR/Function.h +++ b/contrib/llvm/include/llvm/IR/Function.h @@ -159,37 +159,44 @@ 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() >> 1); + return static_cast(getSubclassDataFromValue() >> 2); } void setCallingConv(CallingConv::ID CC) { - setValueSubclassData((getSubclassDataFromValue() & 1) | - (static_cast(CC) << 1)); + setValueSubclassData((getSubclassDataFromValue() & 3) | + (static_cast(CC) << 2)); } - /// getAttributes - Return the attribute list for this Function. - /// + /// @brief Return the attribute list for this Function. AttributeSet getAttributes() const { return AttributeSets; } - /// setAttributes - Set the attribute list for this Function. - /// + /// @brief Set the attribute list for this Function. void setAttributes(AttributeSet attrs) { AttributeSets = attrs; } - /// addFnAttr - Add function attributes to this function. - /// + /// @brief Add function attributes to this function. void addFnAttr(Attribute::AttrKind N) { setAttributes(AttributeSets.addAttribute(getContext(), AttributeSet::FunctionIndex, N)); } - /// addFnAttr - Add function attributes to this function. - /// + /// @brief Remove function attributes from this function. + void removeFnAttr(Attribute::AttrKind N) { + setAttributes(AttributeSets.removeAttribute( + getContext(), AttributeSet::FunctionIndex, N)); + } + + /// @brief Add function attributes to this function. void addFnAttr(StringRef Kind) { setAttributes( AttributeSets.addAttribute(getContext(), AttributeSet::FunctionIndex, Kind)); } + void addFnAttr(StringRef Kind, StringRef Value) { + setAttributes( + AttributeSets.addAttribute(getContext(), + AttributeSet::FunctionIndex, Kind, Value)); + } - /// \brief Return true if the function has the attribute. + /// @brief Return true if the function has the attribute. bool hasFnAttribute(Attribute::AttrKind Kind) const { return AttributeSets.hasAttribute(AttributeSet::FunctionIndex, Kind); } @@ -197,6 +204,14 @@ public: return AttributeSets.hasAttribute(AttributeSet::FunctionIndex, Kind); } + /// @brief Return the attribute for the given attribute kind. + Attribute getFnAttribute(Attribute::AttrKind Kind) const { + return AttributeSets.getAttribute(AttributeSet::FunctionIndex, Kind); + } + Attribute getFnAttribute(StringRef Kind) const { + return AttributeSets.getAttribute(AttributeSet::FunctionIndex, Kind); + } + /// hasGC/getGC/setGC/clearGC - The name of the garbage collection algorithm /// to use during code generation. bool hasGC() const; @@ -303,6 +318,21 @@ public: addAttribute(n, Attribute::NoCapture); } + bool doesNotAccessMemory(unsigned n) const { + return AttributeSets.hasAttribute(n, Attribute::ReadNone); + } + void setDoesNotAccessMemory(unsigned n) { + addAttribute(n, Attribute::ReadNone); + } + + bool onlyReadsMemory(unsigned n) const { + return doesNotAccessMemory(n) || + AttributeSets.hasAttribute(n, Attribute::ReadOnly); + } + void setOnlyReadsMemory(unsigned n) { + addAttribute(n, Attribute::ReadOnly); + } + /// copyAttributesFrom - copy all additional attributes (those not needed to /// create a Function) from the Function Src to this one. void copyAttributesFrom(const GlobalValue *Src); @@ -397,6 +427,13 @@ public: size_t arg_size() const; bool arg_empty() const; + bool hasPrefixData() const { + return getSubclassDataFromValue() & 2; + } + + Constant *getPrefixData() const; + void setPrefixData(Constant *PrefixData); + /// 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/contrib/llvm/include/llvm/IR/GlobalAlias.h b/contrib/llvm/include/llvm/IR/GlobalAlias.h index 883814a32..fec61a7ce 100644 --- a/contrib/llvm/include/llvm/IR/GlobalAlias.h +++ b/contrib/llvm/include/llvm/IR/GlobalAlias.h @@ -66,14 +66,25 @@ public: } /// getAliasedGlobal() - Aliasee can be either global or bitcast of /// global. This method retrives the global for both aliasee flavours. - const GlobalValue *getAliasedGlobal() const; + GlobalValue *getAliasedGlobal(); + const GlobalValue *getAliasedGlobal() const { + return const_cast(this)->getAliasedGlobal(); + } /// resolveAliasedGlobal() - This method tries to ultimately resolve the alias /// by going through the aliasing chain and trying to find the very last /// global. Returns NULL if a cycle was found. If stopOnWeak is false, then /// the whole chain aliasing chain is traversed, otherwise - only strong /// aliases. - const GlobalValue *resolveAliasedGlobal(bool stopOnWeak = true) const; + GlobalValue *resolveAliasedGlobal(bool stopOnWeak = true); + const GlobalValue *resolveAliasedGlobal(bool stopOnWeak = true) const { + return const_cast(this)->resolveAliasedGlobal(stopOnWeak); + } + + static bool isValidLinkage(LinkageTypes L) { + return isExternalLinkage(L) || isLocalLinkage(L) || + isWeakLinkage(L) || isLinkOnceLinkage(L); + } // Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const Value *V) { diff --git a/contrib/llvm/include/llvm/IR/GlobalValue.h b/contrib/llvm/include/llvm/IR/GlobalValue.h index 260302a59..4f20a31a2 100644 --- a/contrib/llvm/include/llvm/IR/GlobalValue.h +++ b/contrib/llvm/include/llvm/IR/GlobalValue.h @@ -35,7 +35,6 @@ public: AvailableExternallyLinkage, ///< Available for inspection, not emission. LinkOnceAnyLinkage, ///< Keep one copy of function when linking (inline) LinkOnceODRLinkage, ///< Same, but only replaced by something equivalent. - LinkOnceODRAutoHideLinkage, ///< Like LinkOnceODRLinkage but addr not taken. WeakAnyLinkage, ///< Keep one copy of named function when linking (weak) WeakODRLinkage, ///< Same, but only replaced by something equivalent. AppendingLinkage, ///< Special purpose, only applies to global arrays @@ -123,12 +122,7 @@ public: return Linkage == AvailableExternallyLinkage; } static bool isLinkOnceLinkage(LinkageTypes Linkage) { - return Linkage == LinkOnceAnyLinkage || - Linkage == LinkOnceODRLinkage || - Linkage == LinkOnceODRAutoHideLinkage; - } - static bool isLinkOnceODRAutoHideLinkage(LinkageTypes Linkage) { - return Linkage == LinkOnceODRAutoHideLinkage; + return Linkage == LinkOnceAnyLinkage || Linkage == LinkOnceODRLinkage; } static bool isWeakLinkage(LinkageTypes Linkage) { return Linkage == WeakAnyLinkage || Linkage == WeakODRLinkage; @@ -192,7 +186,6 @@ public: Linkage == WeakODRLinkage || Linkage == LinkOnceAnyLinkage || Linkage == LinkOnceODRLinkage || - Linkage == LinkOnceODRAutoHideLinkage || Linkage == CommonLinkage || Linkage == ExternalWeakLinkage || Linkage == LinkerPrivateWeakLinkage; @@ -205,9 +198,6 @@ public: bool hasLinkOnceLinkage() const { return isLinkOnceLinkage(Linkage); } - bool hasLinkOnceODRAutoHideLinkage() const { - return isLinkOnceODRAutoHideLinkage(Linkage); - } bool hasWeakLinkage() const { return isWeakLinkage(Linkage); } @@ -239,6 +229,15 @@ public: /// create a GlobalValue) from the GlobalValue Src to this one. virtual void copyAttributesFrom(const GlobalValue *Src); + /// getRealLinkageName - If special LLVM prefix that is used to inform the asm + /// printer to not emit usual symbol prefix before the symbol name is used + /// then return linkage name after skipping this special LLVM prefix. + static StringRef getRealLinkageName(StringRef Name) { + if (!Name.empty() && Name[0] == '\1') + return Name.substr(1); + return Name; + } + /// @name Materialization /// Materialization is used to construct functions only as they're needed. This /// is useful to reduce memory usage in LLVM or parsing work done by the diff --git a/contrib/llvm/include/llvm/IR/GlobalVariable.h b/contrib/llvm/include/llvm/IR/GlobalVariable.h index bfed50786..660092df3 100644 --- a/contrib/llvm/include/llvm/IR/GlobalVariable.h +++ b/contrib/llvm/include/llvm/IR/GlobalVariable.h @@ -84,9 +84,7 @@ public: /// Provide fast operand accessors DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); - /// hasInitializer - Unless a global variable isExternal(), it has an - /// initializer. The initializer for the global variable/constant is held by - /// Initializer if an initializer is specified. + /// Definitions have initializers, declarations don't. /// inline bool hasInitializer() const { return !isDeclaration(); } diff --git a/contrib/llvm/include/llvm/IR/IRBuilder.h b/contrib/llvm/include/llvm/IR/IRBuilder.h index f11d3b4e0..8d1432d6c 100644 --- a/contrib/llvm/include/llvm/IR/IRBuilder.h +++ b/contrib/llvm/include/llvm/IR/IRBuilder.h @@ -25,6 +25,7 @@ #include "llvm/IR/Operator.h" #include "llvm/Support/CBindingWrapping.h" #include "llvm/Support/ConstantFolder.h" +#include "llvm/Support/ValueHandle.h" namespace llvm { class MDNode; @@ -49,17 +50,16 @@ protected: class IRBuilderBase { DebugLoc CurDbgLocation; protected: - /// Save the current debug location here while we are suppressing - /// line table entries. - llvm::DebugLoc SavedDbgLocation; - BasicBlock *BB; BasicBlock::iterator InsertPt; LLVMContext &Context; + + MDNode *DefaultFPMathTag; + FastMathFlags FMF; public: - IRBuilderBase(LLVMContext &context) - : Context(context) { + IRBuilderBase(LLVMContext &context, MDNode *FPMathTag = 0) + : Context(context), DefaultFPMathTag(FPMathTag), FMF() { ClearInsertionPoint(); } @@ -71,6 +71,7 @@ public: /// inserted into a block. void ClearInsertionPoint() { BB = 0; + InsertPt = 0; } BasicBlock *GetInsertBlock() const { return BB; } @@ -89,6 +90,7 @@ public: void SetInsertPoint(Instruction *I) { BB = I->getParent(); InsertPt = I; + assert(I != BB->end() && "Can't read debug loc from end()"); SetCurrentDebugLocation(I->getDebugLoc()); } @@ -117,23 +119,6 @@ public: CurDbgLocation = L; } - /// \brief Temporarily suppress DebugLocations from being attached - /// to emitted instructions, until the next call to - /// SetCurrentDebugLocation() or EnableDebugLocations(). Use this - /// if you want an instruction to be counted towards the prologue or - /// if there is no useful source location. - void DisableDebugLocations() { - llvm::DebugLoc Empty; - SavedDbgLocation = getCurrentDebugLocation(); - SetCurrentDebugLocation(Empty); - } - - /// \brief Restore the previously saved DebugLocation. - void EnableDebugLocations() { - assert(CurDbgLocation.isUnknown()); - SetCurrentDebugLocation(SavedDbgLocation); - } - /// \brief Get location information used by debugging information. DebugLoc getCurrentDebugLocation() const { return CurDbgLocation; } @@ -188,6 +173,68 @@ public: ClearInsertionPoint(); } + /// \brief Get the floating point math metadata being used. + MDNode *getDefaultFPMathTag() const { return DefaultFPMathTag; } + + /// \brief Get the flags to be applied to created floating point ops + FastMathFlags getFastMathFlags() const { return FMF; } + + /// \brief Clear the fast-math flags. + void clearFastMathFlags() { FMF.clear(); } + + /// \brief Set the floating point math metadata to be used. + void SetDefaultFPMathTag(MDNode *FPMathTag) { DefaultFPMathTag = FPMathTag; } + + /// \brief Set the fast-math flags to be used with generated fp-math operators + void SetFastMathFlags(FastMathFlags NewFMF) { FMF = NewFMF; } + + //===--------------------------------------------------------------------===// + // RAII helpers. + //===--------------------------------------------------------------------===// + + // \brief RAII object that stores the current insertion point and restores it + // when the object is destroyed. This includes the debug location. + class InsertPointGuard { + IRBuilderBase &Builder; + AssertingVH Block; + BasicBlock::iterator Point; + DebugLoc DbgLoc; + + InsertPointGuard(const InsertPointGuard &) LLVM_DELETED_FUNCTION; + InsertPointGuard &operator=(const InsertPointGuard &) LLVM_DELETED_FUNCTION; + + public: + InsertPointGuard(IRBuilderBase &B) + : Builder(B), Block(B.GetInsertBlock()), Point(B.GetInsertPoint()), + DbgLoc(B.getCurrentDebugLocation()) {} + + ~InsertPointGuard() { + Builder.restoreIP(InsertPoint(Block, Point)); + Builder.SetCurrentDebugLocation(DbgLoc); + } + }; + + // \brief RAII object that stores the current fast math settings and restores + // them when the object is destroyed. + class FastMathFlagGuard { + IRBuilderBase &Builder; + FastMathFlags FMF; + MDNode *FPMathTag; + + FastMathFlagGuard(const FastMathFlagGuard &) LLVM_DELETED_FUNCTION; + FastMathFlagGuard &operator=( + const FastMathFlagGuard &) LLVM_DELETED_FUNCTION; + + public: + FastMathFlagGuard(IRBuilderBase &B) + : Builder(B), FMF(B.FMF), FPMathTag(B.DefaultFPMathTag) {} + + ~FastMathFlagGuard() { + Builder.FMF = FMF; + Builder.DefaultFPMathTag = FPMathTag; + } + }; + //===--------------------------------------------------------------------===// // Miscellaneous creation methods. //===--------------------------------------------------------------------===// @@ -290,7 +337,7 @@ public: } /// \brief Fetch the type representing a pointer to an integer value. - IntegerType* getIntPtrTy(DataLayout *DL, unsigned AddrSpace = 0) { + IntegerType* getIntPtrTy(const DataLayout *DL, unsigned AddrSpace = 0) { return DL->getIntPtrType(Context, AddrSpace); } @@ -373,76 +420,52 @@ template > class IRBuilder : public IRBuilderBase, public Inserter { T Folder; - MDNode *DefaultFPMathTag; - FastMathFlags FMF; public: IRBuilder(LLVMContext &C, const T &F, const Inserter &I = Inserter(), MDNode *FPMathTag = 0) - : IRBuilderBase(C), Inserter(I), Folder(F), DefaultFPMathTag(FPMathTag), - FMF() { + : IRBuilderBase(C, FPMathTag), Inserter(I), Folder(F) { } explicit IRBuilder(LLVMContext &C, MDNode *FPMathTag = 0) - : IRBuilderBase(C), Folder(), DefaultFPMathTag(FPMathTag), FMF() { + : IRBuilderBase(C, FPMathTag), Folder() { } explicit IRBuilder(BasicBlock *TheBB, const T &F, MDNode *FPMathTag = 0) - : IRBuilderBase(TheBB->getContext()), Folder(F), - DefaultFPMathTag(FPMathTag), FMF() { + : IRBuilderBase(TheBB->getContext(), FPMathTag), Folder(F) { SetInsertPoint(TheBB); } explicit IRBuilder(BasicBlock *TheBB, MDNode *FPMathTag = 0) - : IRBuilderBase(TheBB->getContext()), Folder(), - DefaultFPMathTag(FPMathTag), FMF() { + : IRBuilderBase(TheBB->getContext(), FPMathTag), Folder() { SetInsertPoint(TheBB); } explicit IRBuilder(Instruction *IP, MDNode *FPMathTag = 0) - : IRBuilderBase(IP->getContext()), Folder(), DefaultFPMathTag(FPMathTag), - FMF() { + : IRBuilderBase(IP->getContext(), FPMathTag), Folder() { SetInsertPoint(IP); SetCurrentDebugLocation(IP->getDebugLoc()); } explicit IRBuilder(Use &U, MDNode *FPMathTag = 0) - : IRBuilderBase(U->getContext()), Folder(), DefaultFPMathTag(FPMathTag), - FMF() { + : IRBuilderBase(U->getContext(), FPMathTag), Folder() { SetInsertPoint(U); SetCurrentDebugLocation(cast(U.getUser())->getDebugLoc()); } IRBuilder(BasicBlock *TheBB, BasicBlock::iterator IP, const T& F, MDNode *FPMathTag = 0) - : IRBuilderBase(TheBB->getContext()), Folder(F), - DefaultFPMathTag(FPMathTag), FMF() { + : IRBuilderBase(TheBB->getContext(), FPMathTag), Folder(F) { SetInsertPoint(TheBB, IP); } IRBuilder(BasicBlock *TheBB, BasicBlock::iterator IP, MDNode *FPMathTag = 0) - : IRBuilderBase(TheBB->getContext()), Folder(), - DefaultFPMathTag(FPMathTag), FMF() { + : IRBuilderBase(TheBB->getContext(), FPMathTag), Folder() { SetInsertPoint(TheBB, IP); } /// \brief Get the constant folder being used. const T &getFolder() { return Folder; } - /// \brief Get the floating point math metadata being used. - MDNode *getDefaultFPMathTag() const { return DefaultFPMathTag; } - - /// \brief Get the flags to be applied to created floating point ops - FastMathFlags getFastMathFlags() const { return FMF; } - - /// \brief Clear the fast-math flags. - void clearFastMathFlags() { FMF.clear(); } - - /// \brief SetDefaultFPMathTag - Set the floating point math metadata to be used. - void SetDefaultFPMathTag(MDNode *FPMathTag) { DefaultFPMathTag = FPMathTag; } - - /// \brief Set the fast-math flags to be used with generated fp-math operators - void SetFastMathFlags(FastMathFlags NewFMF) { FMF = NewFMF; } - /// \brief Return true if this builder is configured to actually add the /// requested names to IR created through it. bool isNamePreserving() const { return preserveNames; } @@ -1110,6 +1133,10 @@ public: const Twine &Name = "") { return CreateCast(Instruction::BitCast, V, DestTy, Name); } + Value *CreateAddrSpaceCast(Value *V, Type *DestTy, + const Twine &Name = "") { + return CreateCast(Instruction::AddrSpaceCast, V, DestTy, Name); + } Value *CreateZExtOrBitCast(Value *V, Type *DestTy, const Twine &Name = "") { if (V->getType() == DestTy) diff --git a/contrib/llvm/include/llvm/IR/InlineAsm.h b/contrib/llvm/include/llvm/IR/InlineAsm.h index 33e4ab852..3398a83e3 100644 --- a/contrib/llvm/include/llvm/IR/InlineAsm.h +++ b/contrib/llvm/include/llvm/IR/InlineAsm.h @@ -197,7 +197,7 @@ public: // These are helper methods for dealing with flags in the INLINEASM SDNode // in the backend. - enum { + enum LLVM_ENUM_INT_TYPE(uint32_t) { // Fixed operands on an INLINEASM SDNode. Op_InputChain = 0, Op_AsmString = 1, diff --git a/contrib/llvm/include/llvm/IR/InstrTypes.h b/contrib/llvm/include/llvm/IR/InstrTypes.h index 3e6903cb5..e12bb03a4 100644 --- a/contrib/llvm/include/llvm/IR/InstrTypes.h +++ b/contrib/llvm/include/llvm/IR/InstrTypes.h @@ -531,6 +531,12 @@ public: Type *DestTy ///< The Type to which the value should be cast. ); + /// @brief Check whether a bitcast between these types is valid + static bool isBitCastable( + Type *SrcTy, ///< The Type from which the value should be cast. + Type *DestTy ///< The Type to which the value should be cast. + ); + /// Returns the opcode necessary to cast Val into Ty using usual casting /// rules. /// @brief Infer the opcode for cast operand and type @@ -568,7 +574,7 @@ public: Instruction::CastOps Opcode, ///< Opcode of cast Type *SrcTy, ///< SrcTy of cast Type *DstTy, ///< DstTy of cast - Type *IntPtrTy ///< Integer type corresponding to Ptr types, or null + Type *IntPtrTy ///< Integer type corresponding to Ptr types ); /// @brief Determine if this cast is a no-op cast. @@ -698,7 +704,7 @@ public: /// @brief Create a CmpInst static CmpInst *Create(OtherOps Op, unsigned short predicate, Value *S1, Value *S2, const Twine &Name, BasicBlock *InsertAtEnd); - + /// @brief Get the opcode casted to the right type OtherOps getOpcode() const { return static_cast(Instruction::getOpcode()); @@ -715,15 +721,15 @@ public: static bool isFPPredicate(Predicate P) { return P >= FIRST_FCMP_PREDICATE && P <= LAST_FCMP_PREDICATE; } - + static bool isIntPredicate(Predicate P) { return P >= FIRST_ICMP_PREDICATE && P <= LAST_ICMP_PREDICATE; } - + bool isFPPredicate() const { return isFPPredicate(getPredicate()); } bool isIntPredicate() const { return isIntPredicate(getPredicate()); } - - + + /// For example, EQ -> NE, UGT -> ULE, SLT -> SGE, /// OEQ -> UNE, UGT -> OLE, OLT -> UGE, etc. /// @returns the inverse predicate for the instruction's current predicate. @@ -821,7 +827,7 @@ public: static inline bool classof(const Value *V) { return isa(V) && classof(cast(V)); } - + /// @brief Create a result type for fcmp/icmp static Type* makeCmpResultType(Type* opnd_type) { if (VectorType* vt = dyn_cast(opnd_type)) { diff --git a/contrib/llvm/include/llvm/IR/Instruction.def b/contrib/llvm/include/llvm/IR/Instruction.def index e59a0528e..d46314cc7 100644 --- a/contrib/llvm/include/llvm/IR/Instruction.def +++ b/contrib/llvm/include/llvm/IR/Instruction.def @@ -154,25 +154,26 @@ HANDLE_CAST_INST(41, FPExt , FPExtInst ) // Extend floating point HANDLE_CAST_INST(42, PtrToInt, PtrToIntInst) // Pointer -> Integer HANDLE_CAST_INST(43, IntToPtr, IntToPtrInst) // Integer -> Pointer HANDLE_CAST_INST(44, BitCast , BitCastInst ) // Type cast - LAST_CAST_INST(44) +HANDLE_CAST_INST(45, AddrSpaceCast, AddrSpaceCastInst) // addrspace cast + LAST_CAST_INST(45) // Other operators... - FIRST_OTHER_INST(45) -HANDLE_OTHER_INST(45, ICmp , ICmpInst ) // Integer comparison instruction -HANDLE_OTHER_INST(46, FCmp , FCmpInst ) // Floating point comparison instr. -HANDLE_OTHER_INST(47, PHI , PHINode ) // PHI node instruction -HANDLE_OTHER_INST(48, Call , CallInst ) // Call a function -HANDLE_OTHER_INST(49, Select , SelectInst ) // select instruction -HANDLE_OTHER_INST(50, UserOp1, Instruction) // May be used internally in a pass -HANDLE_OTHER_INST(51, UserOp2, Instruction) // Internal to passes only -HANDLE_OTHER_INST(52, VAArg , VAArgInst ) // vaarg instruction -HANDLE_OTHER_INST(53, ExtractElement, ExtractElementInst)// extract from vector -HANDLE_OTHER_INST(54, InsertElement, InsertElementInst) // insert into vector -HANDLE_OTHER_INST(55, ShuffleVector, ShuffleVectorInst) // shuffle two vectors. -HANDLE_OTHER_INST(56, ExtractValue, ExtractValueInst)// extract from aggregate -HANDLE_OTHER_INST(57, InsertValue, InsertValueInst) // insert into aggregate -HANDLE_OTHER_INST(58, LandingPad, LandingPadInst) // Landing pad instruction. - LAST_OTHER_INST(58) + FIRST_OTHER_INST(46) +HANDLE_OTHER_INST(46, ICmp , ICmpInst ) // Integer comparison instruction +HANDLE_OTHER_INST(47, FCmp , FCmpInst ) // Floating point comparison instr. +HANDLE_OTHER_INST(48, PHI , PHINode ) // PHI node instruction +HANDLE_OTHER_INST(49, Call , CallInst ) // Call a function +HANDLE_OTHER_INST(50, Select , SelectInst ) // select instruction +HANDLE_OTHER_INST(51, UserOp1, Instruction) // May be used internally in a pass +HANDLE_OTHER_INST(52, UserOp2, Instruction) // Internal to passes only +HANDLE_OTHER_INST(53, VAArg , VAArgInst ) // vaarg instruction +HANDLE_OTHER_INST(54, ExtractElement, ExtractElementInst)// extract from vector +HANDLE_OTHER_INST(55, InsertElement, InsertElementInst) // insert into vector +HANDLE_OTHER_INST(56, ShuffleVector, ShuffleVectorInst) // shuffle two vectors. +HANDLE_OTHER_INST(57, ExtractValue, ExtractValueInst)// extract from aggregate +HANDLE_OTHER_INST(58, InsertValue, InsertValueInst) // insert into aggregate +HANDLE_OTHER_INST(59, LandingPad, LandingPadInst) // Landing pad instruction. + LAST_OTHER_INST(59) #undef FIRST_TERM_INST #undef HANDLE_TERM_INST diff --git a/contrib/llvm/include/llvm/IR/Instructions.h b/contrib/llvm/include/llvm/IR/Instructions.h index 7e29699f7..0843d8fca 100644 --- a/contrib/llvm/include/llvm/IR/Instructions.h +++ b/contrib/llvm/include/llvm/IR/Instructions.h @@ -23,8 +23,6 @@ #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/InstrTypes.h" #include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/IntegersSubset.h" -#include "llvm/Support/IntegersSubsetMapping.h" #include namespace llvm { @@ -911,6 +909,18 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(GetElementPtrInst, Value) /// must be identical types. /// \brief Represent an integer comparison operator. class ICmpInst: public CmpInst { + void AssertOK() { + assert(getPredicate() >= CmpInst::FIRST_ICMP_PREDICATE && + getPredicate() <= CmpInst::LAST_ICMP_PREDICATE && + "Invalid ICmp predicate value"); + assert(getOperand(0)->getType() == getOperand(1)->getType() && + "Both operands to ICmp instruction are not of the same type!"); + // Check that the operands are the right type + assert((getOperand(0)->getType()->isIntOrIntVectorTy() || + getOperand(0)->getType()->isPtrOrPtrVectorTy()) && + "Invalid operand types for ICmp instruction"); + } + protected: /// \brief Clone an identical ICmpInst virtual ICmpInst *clone_impl() const; @@ -925,15 +935,9 @@ public: ) : CmpInst(makeCmpResultType(LHS->getType()), Instruction::ICmp, pred, LHS, RHS, NameStr, InsertBefore) { - assert(pred >= CmpInst::FIRST_ICMP_PREDICATE && - pred <= CmpInst::LAST_ICMP_PREDICATE && - "Invalid ICmp predicate value"); - assert(getOperand(0)->getType() == getOperand(1)->getType() && - "Both operands to ICmp instruction are not of the same type!"); - // Check that the operands are the right type - assert((getOperand(0)->getType()->isIntOrIntVectorTy() || - getOperand(0)->getType()->getScalarType()->isPointerTy()) && - "Invalid operand types for ICmp instruction"); +#ifndef NDEBUG + AssertOK(); +#endif } /// \brief Constructor with insert-at-end semantics. @@ -946,15 +950,9 @@ public: ) : CmpInst(makeCmpResultType(LHS->getType()), Instruction::ICmp, pred, LHS, RHS, NameStr, &InsertAtEnd) { - assert(pred >= CmpInst::FIRST_ICMP_PREDICATE && - pred <= CmpInst::LAST_ICMP_PREDICATE && - "Invalid ICmp predicate value"); - assert(getOperand(0)->getType() == getOperand(1)->getType() && - "Both operands to ICmp instruction are not of the same type!"); - // Check that the operands are the right type - assert((getOperand(0)->getType()->isIntOrIntVectorTy() || - getOperand(0)->getType()->getScalarType()->isPointerTy()) && - "Invalid operand types for ICmp instruction"); +#ifndef NDEBUG + AssertOK(); +#endif } /// \brief Constructor with no-insertion semantics @@ -965,15 +963,9 @@ public: const Twine &NameStr = "" ///< Name of the instruction ) : CmpInst(makeCmpResultType(LHS->getType()), Instruction::ICmp, pred, LHS, RHS, NameStr) { - assert(pred >= CmpInst::FIRST_ICMP_PREDICATE && - pred <= CmpInst::LAST_ICMP_PREDICATE && - "Invalid ICmp predicate value"); - assert(getOperand(0)->getType() == getOperand(1)->getType() && - "Both operands to ICmp instruction are not of the same type!"); - // Check that the operands are the right type - assert((getOperand(0)->getType()->isIntOrIntVectorTy() || - getOperand(0)->getType()->getScalarType()->isPointerTy()) && - "Invalid operand types for ICmp instruction"); +#ifndef NDEBUG + AssertOK(); +#endif } /// For example, EQ->EQ, SLE->SLE, UGT->SGT, etc. @@ -1278,7 +1270,11 @@ public: void removeAttribute(unsigned i, Attribute attr); /// \brief Determine whether this call has the given attribute. - bool hasFnAttr(Attribute::AttrKind A) const; + bool hasFnAttr(Attribute::AttrKind A) const { + assert(A != Attribute::NoBuiltin && + "Use CallInst::isNoBuiltin() to check for Attribute::NoBuiltin"); + return hasFnAttrImpl(A); + } /// \brief Determine whether the call or the callee has the given attributes. bool paramHasAttr(unsigned i, Attribute::AttrKind A) const; @@ -1288,6 +1284,13 @@ public: return AttributeList.getParamAlignment(i); } + /// \brief Return true if the call should not be treated as a call to a + /// builtin. + bool isNoBuiltin() const { + return hasFnAttrImpl(Attribute::NoBuiltin) && + !hasFnAttrImpl(Attribute::Builtin); + } + /// \brief Return true if the call should not be inlined. bool isNoInline() const { return hasFnAttr(Attribute::NoInline); } void setIsNoInline() { @@ -1378,6 +1381,9 @@ public: return isa(V) && classof(cast(V)); } private: + + bool hasFnAttrImpl(Attribute::AttrKind A) const; + // Shadow Instruction::setInstructionSubclassData with a private forwarding // method so that subclasses cannot accidentally use it. void setInstructionSubclassData(unsigned short D) { @@ -2443,31 +2449,10 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(BranchInst, Value) class SwitchInst : public TerminatorInst { void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; unsigned ReservedSpace; - // Operands format: // Operand[0] = Value to switch on // Operand[1] = Default basic block destination // Operand[2n ] = Value to match // Operand[2n+1] = BasicBlock to go to on match - - // Store case values separately from operands list. We needn't User-Use - // concept here, since it is just a case value, it will always constant, - // and case value couldn't reused with another instructions/values. - // Additionally: - // It allows us to use custom type for case values that is not inherited - // from Value. Since case value is a complex type that implements - // the subset of integers, we needn't extract sub-constants within - // slow getAggregateElement method. - // For case values we will use std::list to by two reasons: - // 1. It allows to add/remove cases without whole collection reallocation. - // 2. In most of cases we needn't random access. - // Currently case values are also stored in Operands List, but it will moved - // out in future commits. - typedef std::list Subsets; - typedef Subsets::iterator SubsetsIt; - typedef Subsets::const_iterator SubsetsConstIt; - - Subsets TheSubsets; - SwitchInst(const SwitchInst &SI); void init(Value *Value, BasicBlock *Default, unsigned NumReserved); void growOperands(); @@ -2492,25 +2477,121 @@ protected: virtual SwitchInst *clone_impl() const; public: - // FIXME: Currently there are a lot of unclean template parameters, - // we need to make refactoring in future. - // All these parameters are used to implement both iterator and const_iterator - // without code duplication. - // SwitchInstTy may be "const SwitchInst" or "SwitchInst" - // ConstantIntTy may be "const ConstantInt" or "ConstantInt" - // SubsetsItTy may be SubsetsConstIt or SubsetsIt - // BasicBlockTy may be "const BasicBlock" or "BasicBlock" - template - class CaseIteratorT; - - typedef CaseIteratorT ConstCaseIt; - class CaseIt; - // -2 static const unsigned DefaultPseudoIndex = static_cast(~0L-1); + template + class CaseIteratorT { + protected: + + SwitchInstTy *SI; + unsigned Index; + + public: + + typedef CaseIteratorT Self; + + /// Initializes case iterator for given SwitchInst and for given + /// case number. + CaseIteratorT(SwitchInstTy *SI, unsigned CaseNum) { + this->SI = SI; + Index = CaseNum; + } + + /// Initializes case iterator for given SwitchInst and for given + /// TerminatorInst's successor index. + static Self fromSuccessorIndex(SwitchInstTy *SI, unsigned SuccessorIndex) { + assert(SuccessorIndex < SI->getNumSuccessors() && + "Successor index # out of range!"); + return SuccessorIndex != 0 ? + Self(SI, SuccessorIndex - 1) : + Self(SI, DefaultPseudoIndex); + } + + /// Resolves case value for current case. + ConstantIntTy *getCaseValue() { + assert(Index < SI->getNumCases() && "Index out the number of cases."); + return reinterpret_cast(SI->getOperand(2 + Index*2)); + } + + /// Resolves successor for current case. + BasicBlockTy *getCaseSuccessor() { + assert((Index < SI->getNumCases() || + Index == DefaultPseudoIndex) && + "Index out the number of cases."); + return SI->getSuccessor(getSuccessorIndex()); + } + + /// Returns number of current case. + unsigned getCaseIndex() const { return Index; } + + /// Returns TerminatorInst's successor index for current case successor. + unsigned getSuccessorIndex() const { + assert((Index == DefaultPseudoIndex || Index < SI->getNumCases()) && + "Index out the number of cases."); + return Index != DefaultPseudoIndex ? Index + 1 : 0; + } + + Self operator++() { + // Check index correctness after increment. + // Note: Index == getNumCases() means end(). + assert(Index+1 <= SI->getNumCases() && "Index out the number of cases."); + ++Index; + return *this; + } + Self operator++(int) { + Self tmp = *this; + ++(*this); + return tmp; + } + Self operator--() { + // Check index correctness after decrement. + // Note: Index == getNumCases() means end(). + // Also allow "-1" iterator here. That will became valid after ++. + assert((Index == 0 || Index-1 <= SI->getNumCases()) && + "Index out the number of cases."); + --Index; + return *this; + } + Self operator--(int) { + Self tmp = *this; + --(*this); + return tmp; + } + bool operator==(const Self& RHS) const { + assert(RHS.SI == SI && "Incompatible operators."); + return RHS.Index == Index; + } + bool operator!=(const Self& RHS) const { + assert(RHS.SI == SI && "Incompatible operators."); + return RHS.Index != Index; + } + }; + + typedef CaseIteratorT + ConstCaseIt; + + class CaseIt : public CaseIteratorT { + + typedef CaseIteratorT ParentTy; + + public: + + CaseIt(const ParentTy& Src) : ParentTy(Src) {} + CaseIt(SwitchInst *SI, unsigned CaseNum) : ParentTy(SI, CaseNum) {} + + /// Sets the new value for current case. + void setValue(ConstantInt *V) { + assert(Index < SI->getNumCases() && "Index out the number of cases."); + SI->setOperand(2 + Index*2, reinterpret_cast(V)); + } + + /// Sets the new successor for current case. + void setSuccessor(BasicBlock *S) { + SI->setSuccessor(getSuccessorIndex(), S); + } + }; + static SwitchInst *Create(Value *Value, BasicBlock *Default, unsigned NumCases, Instruction *InsertBefore = 0) { return new SwitchInst(Value, Default, NumCases, InsertBefore); @@ -2546,23 +2627,23 @@ public: /// Returns a read/write iterator that points to the first /// case in SwitchInst. CaseIt case_begin() { - return CaseIt(this, 0, TheSubsets.begin()); + return CaseIt(this, 0); } /// Returns a read-only iterator that points to the first /// case in the SwitchInst. ConstCaseIt case_begin() const { - return ConstCaseIt(this, 0, TheSubsets.begin()); + return ConstCaseIt(this, 0); } /// Returns a read/write iterator that points one past the last /// in the SwitchInst. CaseIt case_end() { - return CaseIt(this, getNumCases(), TheSubsets.end()); + return CaseIt(this, getNumCases()); } /// Returns a read-only iterator that points one past the last /// in the SwitchInst. ConstCaseIt case_end() const { - return ConstCaseIt(this, getNumCases(), TheSubsets.end()); + return ConstCaseIt(this, getNumCases()); } /// Returns an iterator that points to the default case. /// Note: this iterator allows to resolve successor only. Attempt @@ -2570,10 +2651,10 @@ public: /// Also note, that increment and decrement also causes an assertion and /// makes iterator invalid. CaseIt case_default() { - return CaseIt(this, DefaultPseudoIndex, TheSubsets.end()); + return CaseIt(this, DefaultPseudoIndex); } ConstCaseIt case_default() const { - return ConstCaseIt(this, DefaultPseudoIndex, TheSubsets.end()); + return ConstCaseIt(this, DefaultPseudoIndex); } /// findCaseValue - Search all of the case values for the specified constant. @@ -2582,13 +2663,13 @@ public: /// that it is handled by the default handler. CaseIt findCaseValue(const ConstantInt *C) { for (CaseIt i = case_begin(), e = case_end(); i != e; ++i) - if (i.getCaseValueEx().isSatisfies(IntItem::fromConstantInt(C))) + if (i.getCaseValue() == C) return i; return case_default(); } ConstCaseIt findCaseValue(const ConstantInt *C) const { for (ConstCaseIt i = case_begin(), e = case_end(); i != e; ++i) - if (i.getCaseValueEx().isSatisfies(IntItem::fromConstantInt(C))) + if (i.getCaseValue() == C) return i; return case_default(); } @@ -2609,25 +2690,18 @@ public: } /// addCase - Add an entry to the switch instruction... - /// @deprecated /// Note: /// This action invalidates case_end(). Old case_end() iterator will /// point to the added case. void addCase(ConstantInt *OnVal, BasicBlock *Dest); - /// addCase - Add an entry to the switch instruction. - /// Note: - /// This action invalidates case_end(). Old case_end() iterator will - /// point to the added case. - void addCase(IntegersSubset& OnVal, BasicBlock *Dest); - /// removeCase - This method removes the specified case and its successor /// from the switch instruction. Note that this operation may reorder the /// remaining cases at index idx and above. /// Note: /// This action invalidates iterators for all cases following the one removed, /// including the case_end() iterator. - void removeCase(CaseIt& i); + void removeCase(CaseIt i); unsigned getNumSuccessors() const { return getNumOperands()/2; } BasicBlock *getSuccessor(unsigned idx) const { @@ -2639,192 +2713,7 @@ public: setOperand(idx*2+1, (Value*)NewSucc); } - uint16_t hash() const { - uint32_t NumberOfCases = (uint32_t)getNumCases(); - uint16_t Hash = (0xFFFF & NumberOfCases) ^ (NumberOfCases >> 16); - for (ConstCaseIt i = case_begin(), e = case_end(); - i != e; ++i) { - uint32_t NumItems = (uint32_t)i.getCaseValueEx().getNumItems(); - Hash = (Hash << 1) ^ (0xFFFF & NumItems) ^ (NumItems >> 16); - } - return Hash; - } - - // Case iterators definition. - - template - class CaseIteratorT { - protected: - - SwitchInstTy *SI; - unsigned Index; - SubsetsItTy SubsetIt; - - /// Initializes case iterator for given SwitchInst and for given - /// case number. - friend class SwitchInst; - CaseIteratorT(SwitchInstTy *SI, unsigned SuccessorIndex, - SubsetsItTy CaseValueIt) { - this->SI = SI; - Index = SuccessorIndex; - this->SubsetIt = CaseValueIt; - } - - public: - typedef typename SubsetsItTy::reference IntegersSubsetRef; - typedef CaseIteratorT Self; - - CaseIteratorT(SwitchInstTy *SI, unsigned CaseNum) { - this->SI = SI; - Index = CaseNum; - SubsetIt = SI->TheSubsets.begin(); - std::advance(SubsetIt, CaseNum); - } - - - /// Initializes case iterator for given SwitchInst and for given - /// TerminatorInst's successor index. - static Self fromSuccessorIndex(SwitchInstTy *SI, unsigned SuccessorIndex) { - assert(SuccessorIndex < SI->getNumSuccessors() && - "Successor index # out of range!"); - return SuccessorIndex != 0 ? - Self(SI, SuccessorIndex - 1) : - Self(SI, DefaultPseudoIndex); - } - - /// Resolves case value for current case. - /// @deprecated - ConstantIntTy *getCaseValue() { - assert(Index < SI->getNumCases() && "Index out the number of cases."); - IntegersSubsetRef CaseRanges = *SubsetIt; - - // FIXME: Currently we work with ConstantInt based cases. - // So return CaseValue as ConstantInt. - return CaseRanges.getSingleNumber(0).toConstantInt(); - } - - /// Resolves case value for current case. - IntegersSubsetRef getCaseValueEx() { - assert(Index < SI->getNumCases() && "Index out the number of cases."); - return *SubsetIt; - } - - /// Resolves successor for current case. - BasicBlockTy *getCaseSuccessor() { - assert((Index < SI->getNumCases() || - Index == DefaultPseudoIndex) && - "Index out the number of cases."); - return SI->getSuccessor(getSuccessorIndex()); - } - - /// Returns number of current case. - unsigned getCaseIndex() const { return Index; } - - /// Returns TerminatorInst's successor index for current case successor. - unsigned getSuccessorIndex() const { - assert((Index == DefaultPseudoIndex || Index < SI->getNumCases()) && - "Index out the number of cases."); - return Index != DefaultPseudoIndex ? Index + 1 : 0; - } - - Self operator++() { - // Check index correctness after increment. - // Note: Index == getNumCases() means end(). - assert(Index+1 <= SI->getNumCases() && "Index out the number of cases."); - ++Index; - if (Index == 0) - SubsetIt = SI->TheSubsets.begin(); - else - ++SubsetIt; - return *this; - } - Self operator++(int) { - Self tmp = *this; - ++(*this); - return tmp; - } - Self operator--() { - // Check index correctness after decrement. - // Note: Index == getNumCases() means end(). - // Also allow "-1" iterator here. That will became valid after ++. - unsigned NumCases = SI->getNumCases(); - assert((Index == 0 || Index-1 <= NumCases) && - "Index out the number of cases."); - --Index; - if (Index == NumCases) { - SubsetIt = SI->TheSubsets.end(); - return *this; - } - - if (Index != -1U) - --SubsetIt; - - return *this; - } - Self operator--(int) { - Self tmp = *this; - --(*this); - return tmp; - } - bool operator==(const Self& RHS) const { - assert(RHS.SI == SI && "Incompatible operators."); - return RHS.Index == Index; - } - bool operator!=(const Self& RHS) const { - assert(RHS.SI == SI && "Incompatible operators."); - return RHS.Index != Index; - } - }; - - class CaseIt : public CaseIteratorT { - typedef CaseIteratorT - ParentTy; - - protected: - friend class SwitchInst; - CaseIt(SwitchInst *SI, unsigned CaseNum, SubsetsIt SubsetIt) : - ParentTy(SI, CaseNum, SubsetIt) {} - - void updateCaseValueOperand(IntegersSubset& V) { - SI->setOperand(2 + Index*2, reinterpret_cast((Constant*)V)); - } - - public: - - CaseIt(SwitchInst *SI, unsigned CaseNum) : ParentTy(SI, CaseNum) {} - - CaseIt(const ParentTy& Src) : ParentTy(Src) {} - - /// Sets the new value for current case. - /// @deprecated. - void setValue(ConstantInt *V) { - assert(Index < SI->getNumCases() && "Index out the number of cases."); - IntegersSubsetToBB Mapping; - // FIXME: Currently we work with ConstantInt based cases. - // So inititalize IntItem container directly from ConstantInt. - Mapping.add(IntItem::fromConstantInt(V)); - *SubsetIt = Mapping.getCase(); - updateCaseValueOperand(*SubsetIt); - } - - /// Sets the new value for current case. - void setValueEx(IntegersSubset& V) { - assert(Index < SI->getNumCases() && "Index out the number of cases."); - *SubsetIt = V; - updateCaseValueOperand(*SubsetIt); - } - - /// Sets the new successor for current case. - void setSuccessor(BasicBlock *S) { - SI->setSuccessor(getSuccessorIndex(), S); - } - }; - // Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const Instruction *I) { return I->getOpcode() == Instruction::Switch; } @@ -3023,8 +2912,12 @@ public: /// removeAttribute - removes the attribute from the list of attributes. void removeAttribute(unsigned i, Attribute attr); - /// \brief Determine whether this call has the NoAlias attribute. - bool hasFnAttr(Attribute::AttrKind A) const; + /// \brief Determine whether this call has the given attribute. + bool hasFnAttr(Attribute::AttrKind A) const { + assert(A != Attribute::NoBuiltin && + "Use CallInst::isNoBuiltin() to check for Attribute::NoBuiltin"); + return hasFnAttrImpl(A); + } /// \brief Determine whether the call or the callee has the given attributes. bool paramHasAttr(unsigned i, Attribute::AttrKind A) const; @@ -3034,6 +2927,15 @@ public: return AttributeList.getParamAlignment(i); } + /// \brief Return true if the call should not be treated as a call to a + /// builtin. + bool isNoBuiltin() const { + // We assert in hasFnAttr if one passes in Attribute::NoBuiltin, so we have + // to check it by hand. + return hasFnAttrImpl(Attribute::NoBuiltin) && + !hasFnAttrImpl(Attribute::Builtin); + } + /// \brief Return true if the call should not be inlined. bool isNoInline() const { return hasFnAttr(Attribute::NoInline); } void setIsNoInline() { @@ -3140,6 +3042,8 @@ private: virtual unsigned getNumSuccessorsV() const; virtual void setSuccessorV(unsigned idx, BasicBlock *B); + bool hasFnAttrImpl(Attribute::AttrKind A) const; + // Shadow Instruction::setInstructionSubclassData with a private forwarding // method so that subclasses cannot accidentally use it. void setInstructionSubclassData(unsigned short D) { @@ -3711,6 +3615,43 @@ public: } }; +//===----------------------------------------------------------------------===// +// AddrSpaceCastInst Class +//===----------------------------------------------------------------------===// + +/// \brief This class represents a conversion between pointers from +/// one address space to another. +class AddrSpaceCastInst : public CastInst { +protected: + /// \brief Clone an identical AddrSpaceCastInst + virtual AddrSpaceCastInst *clone_impl() const; + +public: + /// \brief Constructor with insert-before-instruction semantics + AddrSpaceCastInst( + Value *S, ///< The value to be casted + Type *Ty, ///< The type to casted to + const Twine &NameStr = "", ///< A name for the new instruction + Instruction *InsertBefore = 0 ///< Where to insert the new instruction + ); + + /// \brief Constructor with insert-at-end-of-block semantics + AddrSpaceCastInst( + Value *S, ///< The value to be casted + Type *Ty, ///< The type to casted to + const Twine &NameStr, ///< A name for the new instruction + BasicBlock *InsertAtEnd ///< The block to insert the instruction into + ); + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Instruction *I) { + return I->getOpcode() == AddrSpaceCast; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +}; + } // End llvm namespace #endif diff --git a/contrib/llvm/include/llvm/IR/Intrinsics.h b/contrib/llvm/include/llvm/IR/Intrinsics.h index c81d110e3..473e525d9 100644 --- a/contrib/llvm/include/llvm/IR/Intrinsics.h +++ b/contrib/llvm/include/llvm/IR/Intrinsics.h @@ -77,7 +77,7 @@ namespace Intrinsic { /// getIntrinsicInfoTableEntries. struct IITDescriptor { enum IITDescriptorKind { - Void, MMX, Metadata, Half, Float, Double, + Void, VarArg, MMX, Metadata, Half, Float, Double, Integer, Vector, Pointer, Struct, Argument, ExtendVecArgument, TruncVecArgument } Kind; diff --git a/contrib/llvm/include/llvm/IR/Intrinsics.td b/contrib/llvm/include/llvm/IR/Intrinsics.td index e252664e4..ded6cc12b 100644 --- a/contrib/llvm/include/llvm/IR/Intrinsics.td +++ b/contrib/llvm/include/llvm/IR/Intrinsics.td @@ -55,6 +55,18 @@ class NoCapture : IntrinsicProperty { int ArgNo = argNo; } +// ReadOnly - The specified argument pointer is not written to through the +// pointer by the intrinsic. +class ReadOnly : IntrinsicProperty { + int ArgNo = argNo; +} + +// ReadNone - The specified argument pointer is not dereferenced by the +// intrinsic. +class ReadNone : IntrinsicProperty { + int ArgNo = argNo; +} + def IntrNoReturn : IntrinsicProperty; //===----------------------------------------------------------------------===// @@ -128,6 +140,7 @@ def llvm_v8i1_ty : LLVMType; // 8 x i1 def llvm_v16i1_ty : LLVMType; // 16 x i1 def llvm_v32i1_ty : LLVMType; // 32 x i1 def llvm_v64i1_ty : LLVMType; // 64 x i1 +def llvm_v1i8_ty : LLVMType; // 1 x i8 def llvm_v2i8_ty : LLVMType; // 2 x i8 def llvm_v4i8_ty : LLVMType; // 4 x i8 def llvm_v8i8_ty : LLVMType; // 8 x i8 @@ -153,10 +166,15 @@ def llvm_v4i64_ty : LLVMType; // 4 x i64 def llvm_v8i64_ty : LLVMType; // 8 x i64 def llvm_v16i64_ty : LLVMType; // 16 x i64 +def llvm_v2f16_ty : LLVMType; // 2 x half (__fp16) +def llvm_v4f16_ty : LLVMType; // 4 x half (__fp16) +def llvm_v8f16_ty : LLVMType; // 8 x half (__fp16) +def llvm_v1f32_ty : LLVMType; // 1 x float def llvm_v2f32_ty : LLVMType; // 2 x float def llvm_v4f32_ty : LLVMType; // 4 x float def llvm_v8f32_ty : LLVMType; // 8 x float def llvm_v16f32_ty : LLVMType; // 16 x float +def llvm_v1f64_ty : LLVMType; // 1 x double def llvm_v2f64_ty : LLVMType; // 2 x double def llvm_v4f64_ty : LLVMType; // 4 x double def llvm_v8f64_ty : LLVMType; // 8 x double @@ -246,6 +264,8 @@ def int_readcyclecounter : Intrinsic<[llvm_i64_ty]>; // Stack Protector Intrinsic - The stackprotector intrinsic writes the stack // guard to the correct place on the stack frame. def int_stackprotector : Intrinsic<[], [llvm_ptr_ty, llvm_ptrptr_ty], []>; +def int_stackprotectorcheck : Intrinsic<[], [llvm_ptrptr_ty], + [IntrReadWriteArgMem]>; //===------------------- Standard C Library Intrinsics --------------------===// // @@ -253,11 +273,13 @@ def int_stackprotector : Intrinsic<[], [llvm_ptr_ty, llvm_ptrptr_ty], []>; def int_memcpy : Intrinsic<[], [llvm_anyptr_ty, llvm_anyptr_ty, llvm_anyint_ty, llvm_i32_ty, llvm_i1_ty], - [IntrReadWriteArgMem, NoCapture<0>, NoCapture<1>]>; + [IntrReadWriteArgMem, NoCapture<0>, NoCapture<1>, + ReadOnly<1>]>; def int_memmove : Intrinsic<[], [llvm_anyptr_ty, llvm_anyptr_ty, llvm_anyint_ty, llvm_i32_ty, llvm_i1_ty], - [IntrReadWriteArgMem, NoCapture<0>, NoCapture<1>]>; + [IntrReadWriteArgMem, NoCapture<0>, NoCapture<1>, + ReadOnly<1>]>; def int_memset : Intrinsic<[], [llvm_anyptr_ty, llvm_i8_ty, llvm_anyint_ty, llvm_i32_ty, llvm_i1_ty], @@ -279,11 +301,14 @@ let Properties = [IntrReadMem] in { def int_exp : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; def int_exp2 : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; def int_fabs : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; + def int_copysign : Intrinsic<[llvm_anyfloat_ty], + [LLVMMatchType<0>, LLVMMatchType<0>]>; def int_floor : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; def int_ceil : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; def int_trunc : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; def int_rint : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; def int_nearbyint : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; + def int_round : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; } let Properties = [IntrNoMem] in { @@ -303,7 +328,7 @@ def int_sigsetjmp : Intrinsic<[llvm_i32_ty] , [llvm_ptr_ty, llvm_i32_ty]>; def int_siglongjmp : Intrinsic<[], [llvm_ptr_ty, llvm_i32_ty], [IntrNoReturn]>; // Internal interface for object size checking -def int_objectsize : Intrinsic<[llvm_anyint_ty], [llvm_ptr_ty, llvm_i1_ty], +def int_objectsize : Intrinsic<[llvm_anyint_ty], [llvm_anyptr_ty, llvm_i1_ty], [IntrNoMem]>, GCCBuiltin<"__builtin_object_size">; @@ -347,6 +372,9 @@ 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]>; +// __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. def int_eh_unwind_init: Intrinsic<[]>, GCCBuiltin<"__builtin_unwind_init">; @@ -427,6 +455,19 @@ def int_invariant_end : Intrinsic<[], llvm_ptr_ty], [IntrReadWriteArgMem, NoCapture<2>]>; +//===------------------------ Stackmap Intrinsics -------------------------===// +// +def int_experimental_stackmap : Intrinsic<[], + [llvm_i32_ty, llvm_i32_ty, llvm_vararg_ty]>; +def int_experimental_patchpoint_void : Intrinsic<[], + [llvm_i32_ty, llvm_i32_ty, + llvm_ptr_ty, llvm_i32_ty, + llvm_vararg_ty]>; +def int_experimental_patchpoint_i64 : Intrinsic<[llvm_i64_ty], + [llvm_i32_ty, llvm_i32_ty, + llvm_ptr_ty, llvm_i32_ty, + llvm_vararg_ty]>; + //===-------------------------- Other Intrinsics --------------------------===// // def int_flt_rounds : Intrinsic<[llvm_i32_ty]>, @@ -477,6 +518,7 @@ def int_convertuu : Intrinsic<[llvm_anyint_ty], include "llvm/IR/IntrinsicsPowerPC.td" include "llvm/IR/IntrinsicsX86.td" include "llvm/IR/IntrinsicsARM.td" +include "llvm/IR/IntrinsicsAArch64.td" include "llvm/IR/IntrinsicsXCore.td" include "llvm/IR/IntrinsicsHexagon.td" include "llvm/IR/IntrinsicsNVVM.td" diff --git a/contrib/llvm/include/llvm/IR/IntrinsicsAArch64.td b/contrib/llvm/include/llvm/IR/IntrinsicsAArch64.td new file mode 100644 index 000000000..68af8c116 --- /dev/null +++ b/contrib/llvm/include/llvm/IR/IntrinsicsAArch64.td @@ -0,0 +1,388 @@ +//===- IntrinsicsAArch64.td - Defines AArch64 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 AArch64-specific intrinsics. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Advanced SIMD (NEON) + +let TargetPrefix = "aarch64" in { // All intrinsics start with "llvm.aarch64.". + +// Vector Absolute Compare (Floating Point) +def int_aarch64_neon_vacgeq : + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; +def int_aarch64_neon_vacgtq : + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +// Vector saturating accumulate +def int_aarch64_neon_suqadd : Neon_2Arg_Intrinsic; +def int_aarch64_neon_usqadd : Neon_2Arg_Intrinsic; + +// Vector Bitwise reverse +def int_aarch64_neon_rbit : Neon_1Arg_Intrinsic; + +// Vector extract and narrow +def int_aarch64_neon_xtn : + Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty], [IntrNoMem]>; + +// Vector floating-point convert +def int_aarch64_neon_frintn : Neon_1Arg_Intrinsic; +def int_aarch64_neon_fsqrt : Neon_1Arg_Intrinsic; +def int_aarch64_neon_fcvtxn : + Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty], [IntrNoMem]>; +def int_aarch64_neon_fcvtns : + Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty], [IntrNoMem]>; +def int_aarch64_neon_fcvtnu : + Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty], [IntrNoMem]>; +def int_aarch64_neon_fcvtps : + Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty], [IntrNoMem]>; +def int_aarch64_neon_fcvtpu : + Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty], [IntrNoMem]>; +def int_aarch64_neon_fcvtms : + Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty], [IntrNoMem]>; +def int_aarch64_neon_fcvtmu : + Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty], [IntrNoMem]>; +def int_aarch64_neon_fcvtas : + Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty], [IntrNoMem]>; +def int_aarch64_neon_fcvtau : + Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty], [IntrNoMem]>; +def int_aarch64_neon_fcvtzs : + Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty], [IntrNoMem]>; +def int_aarch64_neon_fcvtzu : + Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty], [IntrNoMem]>; + +// Vector maxNum (Floating Point) +def int_aarch64_neon_vmaxnm : Neon_2Arg_Intrinsic; + +// Vector minNum (Floating Point) +def int_aarch64_neon_vminnm : Neon_2Arg_Intrinsic; + +// Vector Pairwise maxNum (Floating Point) +def int_aarch64_neon_vpmaxnm : Neon_2Arg_Intrinsic; + +// Vector Pairwise minNum (Floating Point) +def int_aarch64_neon_vpminnm : Neon_2Arg_Intrinsic; + +// Vector Multiply Extended and Scalar Multiply Extended (Floating Point) +def int_aarch64_neon_vmulx : + Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, LLVMMatchType<0>]>; + +class Neon_N2V_Intrinsic + : Intrinsic<[llvm_anyvector_ty], [LLVMMatchType<0>, llvm_i32_ty], + [IntrNoMem]>; +class Neon_N3V_Intrinsic + : Intrinsic<[llvm_anyvector_ty], + [LLVMMatchType<0>, LLVMMatchType<0>, llvm_i32_ty], + [IntrNoMem]>; +class Neon_N2V_Narrow_Intrinsic + : Intrinsic<[llvm_anyvector_ty], + [LLVMExtendedElementVectorType<0>, llvm_i32_ty], + [IntrNoMem]>; + +// Vector rounding shift right by immediate (Signed) +def int_aarch64_neon_vsrshr : Neon_N2V_Intrinsic; +def int_aarch64_neon_vurshr : Neon_N2V_Intrinsic; +def int_aarch64_neon_vsqshlu : Neon_N2V_Intrinsic; + +def int_aarch64_neon_vsri : Neon_N3V_Intrinsic; +def int_aarch64_neon_vsli : Neon_N3V_Intrinsic; + +def int_aarch64_neon_vsqshrun : Neon_N2V_Narrow_Intrinsic; +def int_aarch64_neon_vrshrn : Neon_N2V_Narrow_Intrinsic; +def int_aarch64_neon_vsqrshrun : Neon_N2V_Narrow_Intrinsic; +def int_aarch64_neon_vsqshrn : Neon_N2V_Narrow_Intrinsic; +def int_aarch64_neon_vuqshrn : Neon_N2V_Narrow_Intrinsic; +def int_aarch64_neon_vsqrshrn : Neon_N2V_Narrow_Intrinsic; +def int_aarch64_neon_vuqrshrn : Neon_N2V_Narrow_Intrinsic; + +// Vector across +class Neon_Across_Intrinsic + : Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty], [IntrNoMem]>; + +class Neon_2Arg_Across_Float_Intrinsic + : Intrinsic<[llvm_anyvector_ty], [llvm_v4f32_ty], [IntrNoMem]>; + +def int_aarch64_neon_saddlv : Neon_Across_Intrinsic; +def int_aarch64_neon_uaddlv : Neon_Across_Intrinsic; +def int_aarch64_neon_smaxv : Neon_Across_Intrinsic; +def int_aarch64_neon_umaxv : Neon_Across_Intrinsic; +def int_aarch64_neon_sminv : Neon_Across_Intrinsic; +def int_aarch64_neon_uminv : Neon_Across_Intrinsic; +def int_aarch64_neon_vaddv : Neon_Across_Intrinsic; +def int_aarch64_neon_vmaxv : Neon_Across_Intrinsic; +def int_aarch64_neon_vminv : Neon_Across_Intrinsic; +def int_aarch64_neon_vmaxnmv : Neon_Across_Intrinsic; +def int_aarch64_neon_vminnmv : Neon_Across_Intrinsic; + +// Vector Table Lookup. +def int_aarch64_neon_vtbl1 : + Intrinsic<[llvm_anyvector_ty], + [llvm_anyvector_ty, LLVMMatchType<0>], [IntrNoMem]>; + +def int_aarch64_neon_vtbl2 : + Intrinsic<[llvm_anyvector_ty], + [llvm_anyvector_ty, LLVMMatchType<1>, LLVMMatchType<0>], + [IntrNoMem]>; + +def int_aarch64_neon_vtbl3 : + Intrinsic<[llvm_anyvector_ty], + [llvm_anyvector_ty, LLVMMatchType<1>, LLVMMatchType<1>, + LLVMMatchType<0>], [IntrNoMem]>; + +def int_aarch64_neon_vtbl4 : + Intrinsic<[llvm_anyvector_ty], + [llvm_anyvector_ty, LLVMMatchType<1>, LLVMMatchType<1>, + LLVMMatchType<1>, LLVMMatchType<0>], [IntrNoMem]>; + +// Vector Table Extension. +// Some elements of the destination vector may not be updated, so the original +// value of that vector is passed as the first argument. The next 1-4 +// arguments after that are the table. +def int_aarch64_neon_vtbx1 : + Intrinsic<[llvm_anyvector_ty], + [LLVMMatchType<0>, llvm_anyvector_ty, LLVMMatchType<0>], + [IntrNoMem]>; + +def int_aarch64_neon_vtbx2 : + Intrinsic<[llvm_anyvector_ty], + [LLVMMatchType<0>, llvm_anyvector_ty, LLVMMatchType<1>, + LLVMMatchType<0>], [IntrNoMem]>; + +def int_aarch64_neon_vtbx3 : + Intrinsic<[llvm_anyvector_ty], + [LLVMMatchType<0>, llvm_anyvector_ty, LLVMMatchType<1>, + LLVMMatchType<1>, LLVMMatchType<0>], [IntrNoMem]>; + +def int_aarch64_neon_vtbx4 : + Intrinsic<[llvm_anyvector_ty], + [LLVMMatchType<0>, llvm_anyvector_ty, LLVMMatchType<1>, + LLVMMatchType<1>, LLVMMatchType<1>, LLVMMatchType<0>], + [IntrNoMem]>; + +// Vector Load/store +def int_aarch64_neon_vld1x2 : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>], + [llvm_ptr_ty, llvm_i32_ty], + [IntrReadArgMem]>; +def int_aarch64_neon_vld1x3 : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>, + LLVMMatchType<0>], + [llvm_ptr_ty, llvm_i32_ty], + [IntrReadArgMem]>; +def int_aarch64_neon_vld1x4 : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>, + LLVMMatchType<0>, LLVMMatchType<0>], + [llvm_ptr_ty, llvm_i32_ty], + [IntrReadArgMem]>; + +def int_aarch64_neon_vst1x2 : Intrinsic<[], + [llvm_ptr_ty, llvm_anyvector_ty, + LLVMMatchType<0>, llvm_i32_ty], + [IntrReadWriteArgMem]>; +def int_aarch64_neon_vst1x3 : Intrinsic<[], + [llvm_ptr_ty, llvm_anyvector_ty, + LLVMMatchType<0>, LLVMMatchType<0>, + llvm_i32_ty], [IntrReadWriteArgMem]>; +def int_aarch64_neon_vst1x4 : Intrinsic<[], + [llvm_ptr_ty, llvm_anyvector_ty, + LLVMMatchType<0>, LLVMMatchType<0>, + LLVMMatchType<0>, llvm_i32_ty], + [IntrReadWriteArgMem]>; + +// Scalar Add +def int_aarch64_neon_vaddds : + Intrinsic<[llvm_v1i64_ty], [llvm_v1i64_ty, llvm_v1i64_ty], [IntrNoMem]>; +def int_aarch64_neon_vadddu : + Intrinsic<[llvm_v1i64_ty], [llvm_v1i64_ty, llvm_v1i64_ty], [IntrNoMem]>; + + +// Scalar Sub +def int_aarch64_neon_vsubds : + Intrinsic<[llvm_v1i64_ty], [llvm_v1i64_ty, llvm_v1i64_ty], [IntrNoMem]>; +def int_aarch64_neon_vsubdu : + Intrinsic<[llvm_v1i64_ty], [llvm_v1i64_ty, llvm_v1i64_ty], [IntrNoMem]>; + + +// Scalar Shift +// Scalar Shift Left +def int_aarch64_neon_vshlds : + Intrinsic<[llvm_v1i64_ty], [llvm_v1i64_ty, llvm_v1i64_ty], [IntrNoMem]>; +def int_aarch64_neon_vshldu : + Intrinsic<[llvm_v1i64_ty], [llvm_v1i64_ty, llvm_v1i64_ty], [IntrNoMem]>; + +// Scalar Saturating Shift Left +def int_aarch64_neon_vqshls : Neon_2Arg_Intrinsic; +def int_aarch64_neon_vqshlu : Neon_2Arg_Intrinsic; + +// Scalar Shift Rouding Left +def int_aarch64_neon_vrshlds : + Intrinsic<[llvm_v1i64_ty], [llvm_v1i64_ty, llvm_v1i64_ty], [IntrNoMem]>; +def int_aarch64_neon_vrshldu : + Intrinsic<[llvm_v1i64_ty], [llvm_v1i64_ty, llvm_v1i64_ty], [IntrNoMem]>; + +// Scalar Saturating Rounding Shift Left +def int_aarch64_neon_vqrshls : Neon_2Arg_Intrinsic; +def int_aarch64_neon_vqrshlu : Neon_2Arg_Intrinsic; + +// Scalar Reduce Pairwise Add. +def int_aarch64_neon_vpadd : + Intrinsic<[llvm_v1i64_ty], [llvm_v2i64_ty],[IntrNoMem]>; +def int_aarch64_neon_vpfadd : + Intrinsic<[llvm_v1f32_ty], [llvm_v2f32_ty], [IntrNoMem]>; +def int_aarch64_neon_vpfaddq : + Intrinsic<[llvm_v1f64_ty], [llvm_v2f64_ty], [IntrNoMem]>; + +// Scalar Reduce Pairwise Floating Point Max/Min. +def int_aarch64_neon_vpmax : + Intrinsic<[llvm_v1f32_ty], [llvm_v2f32_ty], [IntrNoMem]>; +def int_aarch64_neon_vpmaxq : + Intrinsic<[llvm_v1f64_ty], [llvm_v2f64_ty], [IntrNoMem]>; +def int_aarch64_neon_vpmin : + Intrinsic<[llvm_v1f32_ty], [llvm_v2f32_ty], [IntrNoMem]>; +def int_aarch64_neon_vpminq : + Intrinsic<[llvm_v1f64_ty], [llvm_v2f64_ty], [IntrNoMem]>; + +// Scalar Reduce Pairwise Floating Point Maxnm/Minnm. +def int_aarch64_neon_vpfmaxnm : + Intrinsic<[llvm_v1f32_ty], [llvm_v2f32_ty], [IntrNoMem]>; +def int_aarch64_neon_vpfmaxnmq : + Intrinsic<[llvm_v1f64_ty], [llvm_v2f64_ty], [IntrNoMem]>; +def int_aarch64_neon_vpfminnm : + Intrinsic<[llvm_v1f32_ty], [llvm_v2f32_ty], [IntrNoMem]>; +def int_aarch64_neon_vpfminnmq : + Intrinsic<[llvm_v1f64_ty], [llvm_v2f64_ty], [IntrNoMem]>; + +// Scalar Signed Integer Convert To Floating-point +def int_aarch64_neon_vcvtf32_s32 : + Intrinsic<[llvm_float_ty], [llvm_v1i32_ty], [IntrNoMem]>; +def int_aarch64_neon_vcvtf64_s64 : + Intrinsic<[llvm_double_ty], [llvm_v1i64_ty], [IntrNoMem]>; + +// Scalar Unsigned Integer Convert To Floating-point +def int_aarch64_neon_vcvtf32_u32 : + Intrinsic<[llvm_float_ty], [llvm_v1i32_ty], [IntrNoMem]>; +def int_aarch64_neon_vcvtf64_u64 : + Intrinsic<[llvm_double_ty], [llvm_v1i64_ty], [IntrNoMem]>; + +// Scalar Floating-point Reciprocal Exponent +def int_aarch64_neon_vrecpx : Neon_1Arg_Intrinsic; + +class Neon_Cmp_Intrinsic + : Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty, llvm_anyvector_ty], + [IntrNoMem]>; + +// Scalar Compare Equal +def int_aarch64_neon_vceq : Neon_Cmp_Intrinsic; + +// Scalar Compare Greater-Than or Equal +def int_aarch64_neon_vcge : Neon_Cmp_Intrinsic; +def int_aarch64_neon_vchs : Neon_Cmp_Intrinsic; + +// Scalar Compare Less-Than or Equal +def int_aarch64_neon_vclez : Neon_Cmp_Intrinsic; + +// Scalar Compare Less-Than +def int_aarch64_neon_vcltz : Neon_Cmp_Intrinsic; + +// Scalar Compare Greater-Than +def int_aarch64_neon_vcgt : Neon_Cmp_Intrinsic; +def int_aarch64_neon_vchi : Neon_Cmp_Intrinsic; + +// Scalar Compare Bitwise Test Bits +def int_aarch64_neon_vtstd : Neon_Cmp_Intrinsic; + +// Scalar Floating-point Absolute Compare Greater Than Or Equal +def int_aarch64_neon_vcage : Neon_Cmp_Intrinsic; + +// Scalar Floating-point Absolute Compare Greater Than +def int_aarch64_neon_vcagt : Neon_Cmp_Intrinsic; + +// Scalar Signed Saturating Accumulated of Unsigned Value +def int_aarch64_neon_vuqadd : Neon_2Arg_Intrinsic; + +// Scalar Unsigned Saturating Accumulated of Signed Value +def int_aarch64_neon_vsqadd : Neon_2Arg_Intrinsic; + +// Scalar Absolute Value +def int_aarch64_neon_vabs : + Intrinsic<[llvm_v1i64_ty], [llvm_v1i64_ty], [IntrNoMem]>; + +// Scalar Absolute Difference +def int_aarch64_neon_vabd : Neon_2Arg_Intrinsic; + +// Scalar Negate Value +def int_aarch64_neon_vneg : + Intrinsic<[llvm_v1i64_ty], [llvm_v1i64_ty], [IntrNoMem]>; + +// Signed Saturating Doubling Multiply-Add Long +def int_aarch64_neon_vqdmlal : Neon_3Arg_Long_Intrinsic; + +// Signed Saturating Doubling Multiply-Subtract Long +def int_aarch64_neon_vqdmlsl : Neon_3Arg_Long_Intrinsic; + +class Neon_2Arg_ShiftImm_Intrinsic + : Intrinsic<[llvm_v1i64_ty], [llvm_v1i64_ty, llvm_i32_ty], [IntrNoMem]>; + +class Neon_3Arg_ShiftImm_Intrinsic + : Intrinsic<[llvm_v1i64_ty], [llvm_v1i64_ty, llvm_v1i64_ty, llvm_i32_ty], + [IntrNoMem]>; + +// Scalar Shift Right (Immediate) +def int_aarch64_neon_vshrds_n : Neon_2Arg_ShiftImm_Intrinsic; +def int_aarch64_neon_vshrdu_n : Neon_2Arg_ShiftImm_Intrinsic; + +// Scalar Shift Right and Accumulate (Immediate) +def int_aarch64_neon_vsrads_n : Neon_3Arg_ShiftImm_Intrinsic; +def int_aarch64_neon_vsradu_n : Neon_3Arg_ShiftImm_Intrinsic; + +// Scalar Rounding Shift Right and Accumulate (Immediate) +def int_aarch64_neon_vrsrads_n : Neon_3Arg_ShiftImm_Intrinsic; +def int_aarch64_neon_vrsradu_n : Neon_3Arg_ShiftImm_Intrinsic; + +// Scalar Shift Left (Immediate) +def int_aarch64_neon_vshld_n : Neon_2Arg_ShiftImm_Intrinsic; + +// Scalar Saturating Shift Left (Immediate) +def int_aarch64_neon_vqshls_n : Neon_N2V_Intrinsic; +def int_aarch64_neon_vqshlu_n : Neon_N2V_Intrinsic; + +// Scalar Signed Saturating Shift Left Unsigned (Immediate) +def int_aarch64_neon_vqshlus_n : Neon_N2V_Intrinsic; + +// Scalar Signed Fixed-point Convert To Floating-Point (Immediate) +def int_aarch64_neon_vcvtf32_n_s32 : + Intrinsic<[llvm_float_ty], [llvm_v1i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_aarch64_neon_vcvtf64_n_s64 : + Intrinsic<[llvm_double_ty], [llvm_v1i64_ty, llvm_i32_ty], [IntrNoMem]>; + +// Scalar Unsigned Fixed-point Convert To Floating-Point (Immediate) +def int_aarch64_neon_vcvtf32_n_u32 : + Intrinsic<[llvm_float_ty], [llvm_v1i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_aarch64_neon_vcvtf64_n_u64 : + Intrinsic<[llvm_double_ty], [llvm_v1i64_ty, llvm_i32_ty], [IntrNoMem]>; + +// Scalar Floating-point Convert To Signed Fixed-point (Immediate) +def int_aarch64_neon_vcvts_n_s32_f32 : + Intrinsic<[llvm_v1i32_ty], [llvm_v1f32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_aarch64_neon_vcvtd_n_s64_f64 : + Intrinsic<[llvm_v1i64_ty], [llvm_v1f64_ty, llvm_i32_ty], [IntrNoMem]>; + +// Scalar Floating-point Convert To Unsigned Fixed-point (Immediate) +def int_aarch64_neon_vcvts_n_u32_f32 : + Intrinsic<[llvm_v1i32_ty], [llvm_v1f32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_aarch64_neon_vcvtd_n_u64_f64 : + Intrinsic<[llvm_v1i64_ty], [llvm_v1f64_ty, llvm_i32_ty], [IntrNoMem]>; + +class Neon_SHA_Intrinsic + : Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v1i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + +def int_aarch64_neon_sha1c : Neon_SHA_Intrinsic; +def int_aarch64_neon_sha1m : Neon_SHA_Intrinsic; +def int_aarch64_neon_sha1p : Neon_SHA_Intrinsic; +} diff --git a/contrib/llvm/include/llvm/IR/IntrinsicsARM.td b/contrib/llvm/include/llvm/IR/IntrinsicsARM.td index 93b1ae1dc..0b50d64ae 100644 --- a/contrib/llvm/include/llvm/IR/IntrinsicsARM.td +++ b/contrib/llvm/include/llvm/IR/IntrinsicsARM.td @@ -34,12 +34,20 @@ def int_arm_usat : GCCBuiltin<"__builtin_arm_usat">, Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; //===----------------------------------------------------------------------===// -// Load and Store exclusive doubleword +// Load, Store and Clear exclusive + +def int_arm_ldrex : Intrinsic<[llvm_i32_ty], [llvm_anyptr_ty]>; +def int_arm_strex : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_anyptr_ty]>; +def int_arm_clrex : Intrinsic<[]>; def int_arm_strexd : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, - llvm_ptr_ty], [IntrReadWriteArgMem]>; -def int_arm_ldrexd : Intrinsic<[llvm_i32_ty, llvm_i32_ty], [llvm_ptr_ty], - [IntrReadArgMem]>; + llvm_ptr_ty]>; +def int_arm_ldrexd : Intrinsic<[llvm_i32_ty, llvm_i32_ty], [llvm_ptr_ty]>; + +//===----------------------------------------------------------------------===// +// Data barrier instructions +def int_arm_dmb : GCCBuiltin<"__builtin_arm_dmb">, Intrinsic<[], [llvm_i32_ty]>; +def int_arm_dsb : GCCBuiltin<"__builtin_arm_dsb">, Intrinsic<[], [llvm_i32_ty]>; //===----------------------------------------------------------------------===// // VFP @@ -88,6 +96,26 @@ def int_arm_mcrr2 : GCCBuiltin<"__builtin_arm_mcrr2">, Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], []>; +//===----------------------------------------------------------------------===// +// CRC32 + +def int_arm_crc32b : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; +def int_arm_crc32cb : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; +def int_arm_crc32h : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; +def int_arm_crc32ch : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; +def int_arm_crc32w : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; +def int_arm_crc32cw : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; + +//===----------------------------------------------------------------------===// +// HINT +def int_arm_sevl : Intrinsic<[], []>; + //===----------------------------------------------------------------------===// // Advanced SIMD (NEON) @@ -124,6 +152,8 @@ class Neon_CvtFxToFP_Intrinsic : Intrinsic<[llvm_anyfloat_ty], [llvm_anyint_ty, llvm_i32_ty], [IntrNoMem]>; class Neon_CvtFPToFx_Intrinsic : Intrinsic<[llvm_anyint_ty], [llvm_anyfloat_ty, llvm_i32_ty], [IntrNoMem]>; +class Neon_CvtFPtoInt_1Arg_Intrinsic + : Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty], [IntrNoMem]>; // The table operands for VTBL and VTBX consist of 1 to 4 v8i8 vectors. // Besides the table, VTBL has one other v8i8 argument and VTBX has two. @@ -158,7 +188,6 @@ let Properties = [IntrNoMem, Commutative] in { def int_arm_neon_vrhaddu : Neon_2Arg_Intrinsic; def int_arm_neon_vqadds : Neon_2Arg_Intrinsic; def int_arm_neon_vqaddu : Neon_2Arg_Intrinsic; - def int_arm_neon_vaddhn : Neon_2Arg_Narrow_Intrinsic; def int_arm_neon_vraddhn : Neon_2Arg_Narrow_Intrinsic; // Vector Multiply. @@ -170,17 +199,15 @@ let Properties = [IntrNoMem, Commutative] in { def int_arm_neon_vmullp : Neon_2Arg_Long_Intrinsic; def int_arm_neon_vqdmull : Neon_2Arg_Long_Intrinsic; - // Vector Multiply and Accumulate/Subtract. - def int_arm_neon_vqdmlal : Neon_3Arg_Long_Intrinsic; - def int_arm_neon_vqdmlsl : Neon_3Arg_Long_Intrinsic; - // Vector Maximum. def int_arm_neon_vmaxs : Neon_2Arg_Intrinsic; def int_arm_neon_vmaxu : Neon_2Arg_Intrinsic; + def int_arm_neon_vmaxnm : Neon_2Arg_Intrinsic; // Vector Minimum. def int_arm_neon_vmins : Neon_2Arg_Intrinsic; def int_arm_neon_vminu : Neon_2Arg_Intrinsic; + def int_arm_neon_vminnm : Neon_2Arg_Intrinsic; // Vector Reciprocal Step. def int_arm_neon_vrecps : Neon_2Arg_Intrinsic; @@ -194,7 +221,6 @@ def int_arm_neon_vhsubs : Neon_2Arg_Intrinsic; def int_arm_neon_vhsubu : Neon_2Arg_Intrinsic; def int_arm_neon_vqsubs : Neon_2Arg_Intrinsic; def int_arm_neon_vqsubu : Neon_2Arg_Intrinsic; -def int_arm_neon_vsubhn : Neon_2Arg_Narrow_Intrinsic; def int_arm_neon_vrsubhn : Neon_2Arg_Narrow_Intrinsic; // Vector Absolute Compare. @@ -314,6 +340,16 @@ def int_arm_neon_vrecpe : Neon_1Arg_Intrinsic; // Vector Reciprocal Square Root Estimate. def int_arm_neon_vrsqrte : Neon_1Arg_Intrinsic; +// Vector Conversions Between Floating-point and Integer +def int_arm_neon_vcvtau : Neon_CvtFPtoInt_1Arg_Intrinsic; +def int_arm_neon_vcvtas : Neon_CvtFPtoInt_1Arg_Intrinsic; +def int_arm_neon_vcvtnu : Neon_CvtFPtoInt_1Arg_Intrinsic; +def int_arm_neon_vcvtns : Neon_CvtFPtoInt_1Arg_Intrinsic; +def int_arm_neon_vcvtpu : Neon_CvtFPtoInt_1Arg_Intrinsic; +def int_arm_neon_vcvtps : Neon_CvtFPtoInt_1Arg_Intrinsic; +def int_arm_neon_vcvtmu : Neon_CvtFPtoInt_1Arg_Intrinsic; +def int_arm_neon_vcvtms : Neon_CvtFPtoInt_1Arg_Intrinsic; + // Vector Conversions Between Floating-point and Fixed-point. def int_arm_neon_vcvtfp2fxs : Neon_CvtFPToFx_Intrinsic; def int_arm_neon_vcvtfp2fxu : Neon_CvtFPToFx_Intrinsic; @@ -347,6 +383,14 @@ def int_arm_neon_vtbx2 : Neon_Tbl4Arg_Intrinsic; def int_arm_neon_vtbx3 : Neon_Tbl5Arg_Intrinsic; def int_arm_neon_vtbx4 : Neon_Tbl6Arg_Intrinsic; +// Vector Rounding +def int_arm_neon_vrintn : Neon_1Arg_Intrinsic; +def int_arm_neon_vrintx : Neon_1Arg_Intrinsic; +def int_arm_neon_vrinta : Neon_1Arg_Intrinsic; +def int_arm_neon_vrintz : Neon_1Arg_Intrinsic; +def int_arm_neon_vrintm : Neon_1Arg_Intrinsic; +def int_arm_neon_vrintp : Neon_1Arg_Intrinsic; + // De-interleaving vector loads from N-element structures. // Source operands are the address and alignment. def int_arm_neon_vld1 : Intrinsic<[llvm_anyvector_ty], @@ -426,4 +470,21 @@ def int_arm_neon_vbsl : Intrinsic<[llvm_anyvector_ty], [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem]>; + +// Crypto instructions +def int_arm_neon_aesd : Neon_2Arg_Intrinsic; +def int_arm_neon_aese : Neon_2Arg_Intrinsic; +def int_arm_neon_aesimc : Neon_1Arg_Intrinsic; +def int_arm_neon_aesmc : Neon_1Arg_Intrinsic; +def int_arm_neon_sha1h : Neon_1Arg_Intrinsic; +def int_arm_neon_sha1su1 : Neon_2Arg_Intrinsic; +def int_arm_neon_sha256su0 : Neon_2Arg_Intrinsic; +def int_arm_neon_sha1c : Neon_3Arg_Intrinsic; +def int_arm_neon_sha1m : Neon_3Arg_Intrinsic; +def int_arm_neon_sha1p : Neon_3Arg_Intrinsic; +def int_arm_neon_sha1su0: Neon_3Arg_Intrinsic; +def int_arm_neon_sha256h: Neon_3Arg_Intrinsic; +def int_arm_neon_sha256h2: Neon_3Arg_Intrinsic; +def int_arm_neon_sha256su1: Neon_3Arg_Intrinsic; + } // end TargetPrefix diff --git a/contrib/llvm/include/llvm/IR/IntrinsicsMips.td b/contrib/llvm/include/llvm/IR/IntrinsicsMips.td index a0987c815..42c582141 100644 --- a/contrib/llvm/include/llvm/IR/IntrinsicsMips.td +++ b/contrib/llvm/include/llvm/IR/IntrinsicsMips.td @@ -386,4 +386,1372 @@ def int_mips_subuh_qb: GCCBuiltin<"__builtin_mips_subuh_qb">, Intrinsic<[llvm_v4i8_ty], [llvm_v4i8_ty, llvm_v4i8_ty], [IntrNoMem]>; def int_mips_subuh_r_qb: GCCBuiltin<"__builtin_mips_subuh_r_qb">, Intrinsic<[llvm_v4i8_ty], [llvm_v4i8_ty, llvm_v4i8_ty], [IntrNoMem]>; + +//===----------------------------------------------------------------------===// +// MIPS MSA + +//===----------------------------------------------------------------------===// +// Addition/subtraction + +def int_mips_add_a_b : GCCBuiltin<"__builtin_msa_add_a_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], + [Commutative, IntrNoMem]>; +def int_mips_add_a_h : GCCBuiltin<"__builtin_msa_add_a_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [Commutative, IntrNoMem]>; +def int_mips_add_a_w : GCCBuiltin<"__builtin_msa_add_a_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [Commutative, IntrNoMem]>; +def int_mips_add_a_d : GCCBuiltin<"__builtin_msa_add_a_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], + [Commutative, IntrNoMem]>; + +def int_mips_adds_a_b : GCCBuiltin<"__builtin_msa_adds_a_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], + [Commutative, IntrNoMem]>; +def int_mips_adds_a_h : GCCBuiltin<"__builtin_msa_adds_a_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [Commutative, IntrNoMem]>; +def int_mips_adds_a_w : GCCBuiltin<"__builtin_msa_adds_a_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [Commutative, IntrNoMem]>; +def int_mips_adds_a_d : GCCBuiltin<"__builtin_msa_adds_a_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], + [Commutative, IntrNoMem]>; + +def int_mips_adds_s_b : GCCBuiltin<"__builtin_msa_adds_s_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], + [Commutative, IntrNoMem]>; +def int_mips_adds_s_h : GCCBuiltin<"__builtin_msa_adds_s_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [Commutative, IntrNoMem]>; +def int_mips_adds_s_w : GCCBuiltin<"__builtin_msa_adds_s_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [Commutative, IntrNoMem]>; +def int_mips_adds_s_d : GCCBuiltin<"__builtin_msa_adds_s_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], + [Commutative, IntrNoMem]>; + +def int_mips_adds_u_b : GCCBuiltin<"__builtin_msa_adds_u_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], + [Commutative, IntrNoMem]>; +def int_mips_adds_u_h : GCCBuiltin<"__builtin_msa_adds_u_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [Commutative, IntrNoMem]>; +def int_mips_adds_u_w : GCCBuiltin<"__builtin_msa_adds_u_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [Commutative, IntrNoMem]>; +def int_mips_adds_u_d : GCCBuiltin<"__builtin_msa_adds_u_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], + [Commutative, IntrNoMem]>; + +def int_mips_addv_b : GCCBuiltin<"__builtin_msa_addv_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], + [Commutative, IntrNoMem]>; +def int_mips_addv_h : GCCBuiltin<"__builtin_msa_addv_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [Commutative, IntrNoMem]>; +def int_mips_addv_w : GCCBuiltin<"__builtin_msa_addv_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [Commutative, IntrNoMem]>; +def int_mips_addv_d : GCCBuiltin<"__builtin_msa_addv_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], + [Commutative, IntrNoMem]>; + +def int_mips_addvi_b : GCCBuiltin<"__builtin_msa_addvi_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], + [Commutative, IntrNoMem]>; +def int_mips_addvi_h : GCCBuiltin<"__builtin_msa_addvi_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], + [Commutative, IntrNoMem]>; +def int_mips_addvi_w : GCCBuiltin<"__builtin_msa_addvi_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], + [Commutative, IntrNoMem]>; +def int_mips_addvi_d : GCCBuiltin<"__builtin_msa_addvi_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], + [Commutative, IntrNoMem]>; + +def int_mips_and_v : GCCBuiltin<"__builtin_msa_and_v">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; + +def int_mips_andi_b : GCCBuiltin<"__builtin_msa_andi_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_asub_s_b : GCCBuiltin<"__builtin_msa_asub_s_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_asub_s_h : GCCBuiltin<"__builtin_msa_asub_s_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_asub_s_w : GCCBuiltin<"__builtin_msa_asub_s_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_asub_s_d : GCCBuiltin<"__builtin_msa_asub_s_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_asub_u_b : GCCBuiltin<"__builtin_msa_asub_u_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_asub_u_h : GCCBuiltin<"__builtin_msa_asub_u_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_asub_u_w : GCCBuiltin<"__builtin_msa_asub_u_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_asub_u_d : GCCBuiltin<"__builtin_msa_asub_u_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_ave_s_b : GCCBuiltin<"__builtin_msa_ave_s_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], + [Commutative, IntrNoMem]>; +def int_mips_ave_s_h : GCCBuiltin<"__builtin_msa_ave_s_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [Commutative, IntrNoMem]>; +def int_mips_ave_s_w : GCCBuiltin<"__builtin_msa_ave_s_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [Commutative, IntrNoMem]>; +def int_mips_ave_s_d : GCCBuiltin<"__builtin_msa_ave_s_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], + [Commutative, IntrNoMem]>; + +def int_mips_ave_u_b : GCCBuiltin<"__builtin_msa_ave_u_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], + [Commutative, IntrNoMem]>; +def int_mips_ave_u_h : GCCBuiltin<"__builtin_msa_ave_u_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [Commutative, IntrNoMem]>; +def int_mips_ave_u_w : GCCBuiltin<"__builtin_msa_ave_u_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [Commutative, IntrNoMem]>; +def int_mips_ave_u_d : GCCBuiltin<"__builtin_msa_ave_u_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], + [Commutative, IntrNoMem]>; + +def int_mips_aver_s_b : GCCBuiltin<"__builtin_msa_aver_s_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], + [Commutative, IntrNoMem]>; +def int_mips_aver_s_h : GCCBuiltin<"__builtin_msa_aver_s_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [Commutative, IntrNoMem]>; +def int_mips_aver_s_w : GCCBuiltin<"__builtin_msa_aver_s_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [Commutative, IntrNoMem]>; +def int_mips_aver_s_d : GCCBuiltin<"__builtin_msa_aver_s_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], + [Commutative, IntrNoMem]>; + +def int_mips_aver_u_b : GCCBuiltin<"__builtin_msa_aver_u_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], + [Commutative, IntrNoMem]>; +def int_mips_aver_u_h : GCCBuiltin<"__builtin_msa_aver_u_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [Commutative, IntrNoMem]>; +def int_mips_aver_u_w : GCCBuiltin<"__builtin_msa_aver_u_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [Commutative, IntrNoMem]>; +def int_mips_aver_u_d : GCCBuiltin<"__builtin_msa_aver_u_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], + [Commutative, IntrNoMem]>; + +def int_mips_bclr_b : GCCBuiltin<"__builtin_msa_bclr_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_bclr_h : GCCBuiltin<"__builtin_msa_bclr_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_bclr_w : GCCBuiltin<"__builtin_msa_bclr_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_bclr_d : GCCBuiltin<"__builtin_msa_bclr_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_bclri_b : GCCBuiltin<"__builtin_msa_bclri_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_bclri_h : GCCBuiltin<"__builtin_msa_bclri_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_bclri_w : GCCBuiltin<"__builtin_msa_bclri_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_bclri_d : GCCBuiltin<"__builtin_msa_bclri_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_binsl_b : GCCBuiltin<"__builtin_msa_binsl_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem]>; +def int_mips_binsl_h : GCCBuiltin<"__builtin_msa_binsl_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; +def int_mips_binsl_w : GCCBuiltin<"__builtin_msa_binsl_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; +def int_mips_binsl_d : GCCBuiltin<"__builtin_msa_binsl_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty], + [IntrNoMem]>; + +def int_mips_binsli_b : GCCBuiltin<"__builtin_msa_binsli_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], + [IntrNoMem]>; +def int_mips_binsli_h : GCCBuiltin<"__builtin_msa_binsli_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty], + [IntrNoMem]>; +def int_mips_binsli_w : GCCBuiltin<"__builtin_msa_binsli_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty], + [IntrNoMem]>; +def int_mips_binsli_d : GCCBuiltin<"__builtin_msa_binsli_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty], + [IntrNoMem]>; + +def int_mips_binsr_b : GCCBuiltin<"__builtin_msa_binsr_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem]>; +def int_mips_binsr_h : GCCBuiltin<"__builtin_msa_binsr_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; +def int_mips_binsr_w : GCCBuiltin<"__builtin_msa_binsr_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; +def int_mips_binsr_d : GCCBuiltin<"__builtin_msa_binsr_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty], + [IntrNoMem]>; + +def int_mips_binsri_b : GCCBuiltin<"__builtin_msa_binsri_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], + [IntrNoMem]>; +def int_mips_binsri_h : GCCBuiltin<"__builtin_msa_binsri_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty], + [IntrNoMem]>; +def int_mips_binsri_w : GCCBuiltin<"__builtin_msa_binsri_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty], + [IntrNoMem]>; +def int_mips_binsri_d : GCCBuiltin<"__builtin_msa_binsri_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty], + [IntrNoMem]>; + +def int_mips_bmnz_v : GCCBuiltin<"__builtin_msa_bmnz_v">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem]>; + +def int_mips_bmnzi_b : GCCBuiltin<"__builtin_msa_bmnzi_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], + [IntrNoMem]>; + +def int_mips_bmz_v : GCCBuiltin<"__builtin_msa_bmz_v">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem]>; + +def int_mips_bmzi_b : GCCBuiltin<"__builtin_msa_bmzi_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], + [IntrNoMem]>; + +def int_mips_bneg_b : GCCBuiltin<"__builtin_msa_bneg_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_bneg_h : GCCBuiltin<"__builtin_msa_bneg_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_bneg_w : GCCBuiltin<"__builtin_msa_bneg_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_bneg_d : GCCBuiltin<"__builtin_msa_bneg_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_bnegi_b : GCCBuiltin<"__builtin_msa_bnegi_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_bnegi_h : GCCBuiltin<"__builtin_msa_bnegi_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_bnegi_w : GCCBuiltin<"__builtin_msa_bnegi_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_bnegi_d : GCCBuiltin<"__builtin_msa_bnegi_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_bnz_b : GCCBuiltin<"__builtin_msa_bnz_b">, + Intrinsic<[llvm_i32_ty], [llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_bnz_h : GCCBuiltin<"__builtin_msa_bnz_h">, + Intrinsic<[llvm_i32_ty], [llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_bnz_w : GCCBuiltin<"__builtin_msa_bnz_w">, + Intrinsic<[llvm_i32_ty], [llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_bnz_d : GCCBuiltin<"__builtin_msa_bnz_d">, + Intrinsic<[llvm_i32_ty], [llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_bnz_v : GCCBuiltin<"__builtin_msa_bnz_v">, + Intrinsic<[llvm_i32_ty], [llvm_v16i8_ty], [IntrNoMem]>; + +def int_mips_bsel_v : GCCBuiltin<"__builtin_msa_bsel_v">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem]>; + +def int_mips_bseli_b : GCCBuiltin<"__builtin_msa_bseli_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], + [IntrNoMem]>; + +def int_mips_bset_b : GCCBuiltin<"__builtin_msa_bset_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_bset_h : GCCBuiltin<"__builtin_msa_bset_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_bset_w : GCCBuiltin<"__builtin_msa_bset_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_bset_d : GCCBuiltin<"__builtin_msa_bset_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_bseti_b : GCCBuiltin<"__builtin_msa_bseti_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_bseti_h : GCCBuiltin<"__builtin_msa_bseti_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_bseti_w : GCCBuiltin<"__builtin_msa_bseti_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_bseti_d : GCCBuiltin<"__builtin_msa_bseti_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_bz_b : GCCBuiltin<"__builtin_msa_bz_b">, + Intrinsic<[llvm_i32_ty], [llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_bz_h : GCCBuiltin<"__builtin_msa_bz_h">, + Intrinsic<[llvm_i32_ty], [llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_bz_w : GCCBuiltin<"__builtin_msa_bz_w">, + Intrinsic<[llvm_i32_ty], [llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_bz_d : GCCBuiltin<"__builtin_msa_bz_d">, + Intrinsic<[llvm_i32_ty], [llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_bz_v : GCCBuiltin<"__builtin_msa_bz_v">, + Intrinsic<[llvm_i32_ty], [llvm_v16i8_ty], [IntrNoMem]>; + +def int_mips_ceq_b : GCCBuiltin<"__builtin_msa_ceq_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_ceq_h : GCCBuiltin<"__builtin_msa_ceq_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_ceq_w : GCCBuiltin<"__builtin_msa_ceq_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_ceq_d : GCCBuiltin<"__builtin_msa_ceq_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_ceqi_b : GCCBuiltin<"__builtin_msa_ceqi_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_ceqi_h : GCCBuiltin<"__builtin_msa_ceqi_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_ceqi_w : GCCBuiltin<"__builtin_msa_ceqi_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_ceqi_d : GCCBuiltin<"__builtin_msa_ceqi_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_cfcmsa : GCCBuiltin<"__builtin_msa_cfcmsa">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty], []>; + +def int_mips_cle_s_b : GCCBuiltin<"__builtin_msa_cle_s_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_cle_s_h : GCCBuiltin<"__builtin_msa_cle_s_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_cle_s_w : GCCBuiltin<"__builtin_msa_cle_s_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_cle_s_d : GCCBuiltin<"__builtin_msa_cle_s_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_cle_u_b : GCCBuiltin<"__builtin_msa_cle_u_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_cle_u_h : GCCBuiltin<"__builtin_msa_cle_u_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_cle_u_w : GCCBuiltin<"__builtin_msa_cle_u_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_cle_u_d : GCCBuiltin<"__builtin_msa_cle_u_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_clei_s_b : GCCBuiltin<"__builtin_msa_clei_s_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_clei_s_h : GCCBuiltin<"__builtin_msa_clei_s_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_clei_s_w : GCCBuiltin<"__builtin_msa_clei_s_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_clei_s_d : GCCBuiltin<"__builtin_msa_clei_s_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_clei_u_b : GCCBuiltin<"__builtin_msa_clei_u_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_clei_u_h : GCCBuiltin<"__builtin_msa_clei_u_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_clei_u_w : GCCBuiltin<"__builtin_msa_clei_u_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_clei_u_d : GCCBuiltin<"__builtin_msa_clei_u_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_clt_s_b : GCCBuiltin<"__builtin_msa_clt_s_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_clt_s_h : GCCBuiltin<"__builtin_msa_clt_s_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_clt_s_w : GCCBuiltin<"__builtin_msa_clt_s_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_clt_s_d : GCCBuiltin<"__builtin_msa_clt_s_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_clt_u_b : GCCBuiltin<"__builtin_msa_clt_u_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_clt_u_h : GCCBuiltin<"__builtin_msa_clt_u_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_clt_u_w : GCCBuiltin<"__builtin_msa_clt_u_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_clt_u_d : GCCBuiltin<"__builtin_msa_clt_u_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_clti_s_b : GCCBuiltin<"__builtin_msa_clti_s_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_clti_s_h : GCCBuiltin<"__builtin_msa_clti_s_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_clti_s_w : GCCBuiltin<"__builtin_msa_clti_s_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_clti_s_d : GCCBuiltin<"__builtin_msa_clti_s_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_clti_u_b : GCCBuiltin<"__builtin_msa_clti_u_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_clti_u_h : GCCBuiltin<"__builtin_msa_clti_u_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_clti_u_w : GCCBuiltin<"__builtin_msa_clti_u_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_clti_u_d : GCCBuiltin<"__builtin_msa_clti_u_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_copy_s_b : GCCBuiltin<"__builtin_msa_copy_s_b">, + Intrinsic<[llvm_i32_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_copy_s_h : GCCBuiltin<"__builtin_msa_copy_s_h">, + Intrinsic<[llvm_i32_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_copy_s_w : GCCBuiltin<"__builtin_msa_copy_s_w">, + Intrinsic<[llvm_i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_copy_s_d : GCCBuiltin<"__builtin_msa_copy_s_d">, + Intrinsic<[llvm_i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_copy_u_b : GCCBuiltin<"__builtin_msa_copy_u_b">, + Intrinsic<[llvm_i32_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_copy_u_h : GCCBuiltin<"__builtin_msa_copy_u_h">, + Intrinsic<[llvm_i32_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_copy_u_w : GCCBuiltin<"__builtin_msa_copy_u_w">, + Intrinsic<[llvm_i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_copy_u_d : GCCBuiltin<"__builtin_msa_copy_u_d">, + Intrinsic<[llvm_i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_ctcmsa : GCCBuiltin<"__builtin_msa_ctcmsa">, + Intrinsic<[], [llvm_i32_ty, llvm_i32_ty], []>; + +def int_mips_div_s_b : GCCBuiltin<"__builtin_msa_div_s_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_div_s_h : GCCBuiltin<"__builtin_msa_div_s_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_div_s_w : GCCBuiltin<"__builtin_msa_div_s_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_div_s_d : GCCBuiltin<"__builtin_msa_div_s_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_div_u_b : GCCBuiltin<"__builtin_msa_div_u_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_div_u_h : GCCBuiltin<"__builtin_msa_div_u_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_div_u_w : GCCBuiltin<"__builtin_msa_div_u_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_div_u_d : GCCBuiltin<"__builtin_msa_div_u_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_dotp_s_h : GCCBuiltin<"__builtin_msa_dotp_s_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_dotp_s_w : GCCBuiltin<"__builtin_msa_dotp_s_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_dotp_s_d : GCCBuiltin<"__builtin_msa_dotp_s_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; + +def int_mips_dotp_u_h : GCCBuiltin<"__builtin_msa_dotp_u_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_dotp_u_w : GCCBuiltin<"__builtin_msa_dotp_u_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_dotp_u_d : GCCBuiltin<"__builtin_msa_dotp_u_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; + +def int_mips_dpadd_s_h : GCCBuiltin<"__builtin_msa_dpadd_s_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem]>; +def int_mips_dpadd_s_w : GCCBuiltin<"__builtin_msa_dpadd_s_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; +def int_mips_dpadd_s_d : GCCBuiltin<"__builtin_msa_dpadd_s_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + +def int_mips_dpadd_u_h : GCCBuiltin<"__builtin_msa_dpadd_u_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem]>; +def int_mips_dpadd_u_w : GCCBuiltin<"__builtin_msa_dpadd_u_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; +def int_mips_dpadd_u_d : GCCBuiltin<"__builtin_msa_dpadd_u_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + +def int_mips_dpsub_s_h : GCCBuiltin<"__builtin_msa_dpsub_s_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem]>; +def int_mips_dpsub_s_w : GCCBuiltin<"__builtin_msa_dpsub_s_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; +def int_mips_dpsub_s_d : GCCBuiltin<"__builtin_msa_dpsub_s_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + +def int_mips_dpsub_u_h : GCCBuiltin<"__builtin_msa_dpsub_u_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem]>; +def int_mips_dpsub_u_w : GCCBuiltin<"__builtin_msa_dpsub_u_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; +def int_mips_dpsub_u_d : GCCBuiltin<"__builtin_msa_dpsub_u_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + +def int_mips_fadd_w : GCCBuiltin<"__builtin_msa_fadd_w">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fadd_d : GCCBuiltin<"__builtin_msa_fadd_d">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fcaf_w : GCCBuiltin<"__builtin_msa_fcaf_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fcaf_d : GCCBuiltin<"__builtin_msa_fcaf_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fceq_w : GCCBuiltin<"__builtin_msa_fceq_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fceq_d : GCCBuiltin<"__builtin_msa_fceq_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fcle_w : GCCBuiltin<"__builtin_msa_fcle_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fcle_d : GCCBuiltin<"__builtin_msa_fcle_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fclt_w : GCCBuiltin<"__builtin_msa_fclt_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fclt_d : GCCBuiltin<"__builtin_msa_fclt_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fclass_w : GCCBuiltin<"__builtin_msa_fclass_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fclass_d : GCCBuiltin<"__builtin_msa_fclass_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fcne_w : GCCBuiltin<"__builtin_msa_fcne_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fcne_d : GCCBuiltin<"__builtin_msa_fcne_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fcor_w : GCCBuiltin<"__builtin_msa_fcor_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fcor_d : GCCBuiltin<"__builtin_msa_fcor_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fcueq_w : GCCBuiltin<"__builtin_msa_fcueq_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fcueq_d : GCCBuiltin<"__builtin_msa_fcueq_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fcule_w : GCCBuiltin<"__builtin_msa_fcule_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fcule_d : GCCBuiltin<"__builtin_msa_fcule_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fcult_w : GCCBuiltin<"__builtin_msa_fcult_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fcult_d : GCCBuiltin<"__builtin_msa_fcult_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fcun_w : GCCBuiltin<"__builtin_msa_fcun_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fcun_d : GCCBuiltin<"__builtin_msa_fcun_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fcune_w : GCCBuiltin<"__builtin_msa_fcune_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fcune_d : GCCBuiltin<"__builtin_msa_fcune_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fdiv_w : GCCBuiltin<"__builtin_msa_fdiv_w">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fdiv_d : GCCBuiltin<"__builtin_msa_fdiv_d">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fexdo_h : GCCBuiltin<"__builtin_msa_fexdo_h">, + Intrinsic<[llvm_v8f16_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fexdo_w : GCCBuiltin<"__builtin_msa_fexdo_w">, + Intrinsic<[llvm_v4f32_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fexp2_w : GCCBuiltin<"__builtin_msa_fexp2_w">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_fexp2_d : GCCBuiltin<"__builtin_msa_fexp2_d">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_fexupl_w : GCCBuiltin<"__builtin_msa_fexupl_w">, + Intrinsic<[llvm_v4f32_ty], [llvm_v8f16_ty], [IntrNoMem]>; +def int_mips_fexupl_d : GCCBuiltin<"__builtin_msa_fexupl_d">, + Intrinsic<[llvm_v2f64_ty], [llvm_v4f32_ty], [IntrNoMem]>; + +def int_mips_fexupr_w : GCCBuiltin<"__builtin_msa_fexupr_w">, + Intrinsic<[llvm_v4f32_ty], [llvm_v8f16_ty], [IntrNoMem]>; +def int_mips_fexupr_d : GCCBuiltin<"__builtin_msa_fexupr_d">, + Intrinsic<[llvm_v2f64_ty], [llvm_v4f32_ty], [IntrNoMem]>; + +def int_mips_ffint_s_w : GCCBuiltin<"__builtin_msa_ffint_s_w">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_ffint_s_d : GCCBuiltin<"__builtin_msa_ffint_s_d">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_ffint_u_w : GCCBuiltin<"__builtin_msa_ffint_u_w">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_ffint_u_d : GCCBuiltin<"__builtin_msa_ffint_u_d">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_ffql_w : GCCBuiltin<"__builtin_msa_ffql_w">, + Intrinsic<[llvm_v4f32_ty], [llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_ffql_d : GCCBuiltin<"__builtin_msa_ffql_d">, + Intrinsic<[llvm_v2f64_ty], [llvm_v4i32_ty], [IntrNoMem]>; + +def int_mips_ffqr_w : GCCBuiltin<"__builtin_msa_ffqr_w">, + Intrinsic<[llvm_v4f32_ty], [llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_ffqr_d : GCCBuiltin<"__builtin_msa_ffqr_d">, + Intrinsic<[llvm_v2f64_ty], [llvm_v4i32_ty], [IntrNoMem]>; + +def int_mips_fill_b : GCCBuiltin<"__builtin_msa_fill_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_i32_ty], [IntrNoMem]>; +def int_mips_fill_h : GCCBuiltin<"__builtin_msa_fill_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_i32_ty], [IntrNoMem]>; +def int_mips_fill_w : GCCBuiltin<"__builtin_msa_fill_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_i32_ty], [IntrNoMem]>; +def int_mips_fill_d : GCCBuiltin<"__builtin_msa_fill_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_i64_ty], [IntrNoMem]>; + +def int_mips_flog2_w : GCCBuiltin<"__builtin_msa_flog2_w">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_flog2_d : GCCBuiltin<"__builtin_msa_flog2_d">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fmadd_w : GCCBuiltin<"__builtin_msa_fmadd_w">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty], + [IntrNoMem]>; +def int_mips_fmadd_d : GCCBuiltin<"__builtin_msa_fmadd_d">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty], + [IntrNoMem]>; + +def int_mips_fmax_w : GCCBuiltin<"__builtin_msa_fmax_w">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fmax_d : GCCBuiltin<"__builtin_msa_fmax_d">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fmax_a_w : GCCBuiltin<"__builtin_msa_fmax_a_w">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fmax_a_d : GCCBuiltin<"__builtin_msa_fmax_a_d">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fmin_w : GCCBuiltin<"__builtin_msa_fmin_w">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fmin_d : GCCBuiltin<"__builtin_msa_fmin_d">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fmin_a_w : GCCBuiltin<"__builtin_msa_fmin_a_w">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fmin_a_d : GCCBuiltin<"__builtin_msa_fmin_a_d">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fmsub_w : GCCBuiltin<"__builtin_msa_fmsub_w">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty], + [IntrNoMem]>; +def int_mips_fmsub_d : GCCBuiltin<"__builtin_msa_fmsub_d">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty], + [IntrNoMem]>; + +def int_mips_fmul_w : GCCBuiltin<"__builtin_msa_fmul_w">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fmul_d : GCCBuiltin<"__builtin_msa_fmul_d">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_frint_w : GCCBuiltin<"__builtin_msa_frint_w">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_frint_d : GCCBuiltin<"__builtin_msa_frint_d">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_frcp_w : GCCBuiltin<"__builtin_msa_frcp_w">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_frcp_d : GCCBuiltin<"__builtin_msa_frcp_d">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_frsqrt_w : GCCBuiltin<"__builtin_msa_frsqrt_w">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_frsqrt_d : GCCBuiltin<"__builtin_msa_frsqrt_d">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fsaf_w : GCCBuiltin<"__builtin_msa_fsaf_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fsaf_d : GCCBuiltin<"__builtin_msa_fsaf_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fseq_w : GCCBuiltin<"__builtin_msa_fseq_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fseq_d : GCCBuiltin<"__builtin_msa_fseq_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fsle_w : GCCBuiltin<"__builtin_msa_fsle_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fsle_d : GCCBuiltin<"__builtin_msa_fsle_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fslt_w : GCCBuiltin<"__builtin_msa_fslt_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fslt_d : GCCBuiltin<"__builtin_msa_fslt_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fsne_w : GCCBuiltin<"__builtin_msa_fsne_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fsne_d : GCCBuiltin<"__builtin_msa_fsne_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fsor_w : GCCBuiltin<"__builtin_msa_fsor_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fsor_d : GCCBuiltin<"__builtin_msa_fsor_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fsqrt_w : GCCBuiltin<"__builtin_msa_fsqrt_w">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fsqrt_d : GCCBuiltin<"__builtin_msa_fsqrt_d">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fsub_w : GCCBuiltin<"__builtin_msa_fsub_w">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fsub_d : GCCBuiltin<"__builtin_msa_fsub_d">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fsueq_w : GCCBuiltin<"__builtin_msa_fsueq_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fsueq_d : GCCBuiltin<"__builtin_msa_fsueq_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fsule_w : GCCBuiltin<"__builtin_msa_fsule_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fsule_d : GCCBuiltin<"__builtin_msa_fsule_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fsult_w : GCCBuiltin<"__builtin_msa_fsult_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fsult_d : GCCBuiltin<"__builtin_msa_fsult_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fsun_w : GCCBuiltin<"__builtin_msa_fsun_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fsun_d : GCCBuiltin<"__builtin_msa_fsun_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_fsune_w : GCCBuiltin<"__builtin_msa_fsune_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_fsune_d : GCCBuiltin<"__builtin_msa_fsune_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_ftint_s_w : GCCBuiltin<"__builtin_msa_ftint_s_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_ftint_s_d : GCCBuiltin<"__builtin_msa_ftint_s_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_ftint_u_w : GCCBuiltin<"__builtin_msa_ftint_u_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_ftint_u_d : GCCBuiltin<"__builtin_msa_ftint_u_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_ftq_h : GCCBuiltin<"__builtin_msa_ftq_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_ftq_w : GCCBuiltin<"__builtin_msa_ftq_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_ftrunc_s_w : GCCBuiltin<"__builtin_msa_ftrunc_s_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_ftrunc_s_d : GCCBuiltin<"__builtin_msa_ftrunc_s_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_ftrunc_u_w : GCCBuiltin<"__builtin_msa_ftrunc_u_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty], [IntrNoMem]>; +def int_mips_ftrunc_u_d : GCCBuiltin<"__builtin_msa_ftrunc_u_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty], [IntrNoMem]>; + +def int_mips_hadd_s_h : GCCBuiltin<"__builtin_msa_hadd_s_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_hadd_s_w : GCCBuiltin<"__builtin_msa_hadd_s_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_hadd_s_d : GCCBuiltin<"__builtin_msa_hadd_s_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; + +def int_mips_hadd_u_h : GCCBuiltin<"__builtin_msa_hadd_u_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_hadd_u_w : GCCBuiltin<"__builtin_msa_hadd_u_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_hadd_u_d : GCCBuiltin<"__builtin_msa_hadd_u_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; + +def int_mips_hsub_s_h : GCCBuiltin<"__builtin_msa_hsub_s_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_hsub_s_w : GCCBuiltin<"__builtin_msa_hsub_s_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_hsub_s_d : GCCBuiltin<"__builtin_msa_hsub_s_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; + +def int_mips_hsub_u_h : GCCBuiltin<"__builtin_msa_hsub_u_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_hsub_u_w : GCCBuiltin<"__builtin_msa_hsub_u_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_hsub_u_d : GCCBuiltin<"__builtin_msa_hsub_u_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; + +def int_mips_ilvev_b : GCCBuiltin<"__builtin_msa_ilvev_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_ilvev_h : GCCBuiltin<"__builtin_msa_ilvev_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_ilvev_w : GCCBuiltin<"__builtin_msa_ilvev_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_ilvev_d : GCCBuiltin<"__builtin_msa_ilvev_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_ilvl_b : GCCBuiltin<"__builtin_msa_ilvl_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_ilvl_h : GCCBuiltin<"__builtin_msa_ilvl_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_ilvl_w : GCCBuiltin<"__builtin_msa_ilvl_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_ilvl_d : GCCBuiltin<"__builtin_msa_ilvl_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_ilvod_b : GCCBuiltin<"__builtin_msa_ilvod_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_ilvod_h : GCCBuiltin<"__builtin_msa_ilvod_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_ilvod_w : GCCBuiltin<"__builtin_msa_ilvod_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_ilvod_d : GCCBuiltin<"__builtin_msa_ilvod_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_ilvr_b : GCCBuiltin<"__builtin_msa_ilvr_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_ilvr_h : GCCBuiltin<"__builtin_msa_ilvr_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_ilvr_w : GCCBuiltin<"__builtin_msa_ilvr_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_ilvr_d : GCCBuiltin<"__builtin_msa_ilvr_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_insert_b : GCCBuiltin<"__builtin_msa_insert_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; +def int_mips_insert_h : GCCBuiltin<"__builtin_msa_insert_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; +def int_mips_insert_w : GCCBuiltin<"__builtin_msa_insert_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; +def int_mips_insert_d : GCCBuiltin<"__builtin_msa_insert_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty, llvm_i64_ty], + [IntrNoMem]>; + +def int_mips_insve_b : GCCBuiltin<"__builtin_msa_insve_b">, + Intrinsic<[llvm_v16i8_ty], + [llvm_v16i8_ty, llvm_i32_ty, llvm_v16i8_ty], + [IntrNoMem]>; +def int_mips_insve_h : GCCBuiltin<"__builtin_msa_insve_h">, + Intrinsic<[llvm_v8i16_ty], + [llvm_v8i16_ty, llvm_i32_ty, llvm_v8i16_ty], + [IntrNoMem]>; +def int_mips_insve_w : GCCBuiltin<"__builtin_msa_insve_w">, + Intrinsic<[llvm_v4i32_ty], + [llvm_v4i32_ty, llvm_i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; +def int_mips_insve_d : GCCBuiltin<"__builtin_msa_insve_d">, + Intrinsic<[llvm_v2i64_ty], + [llvm_v2i64_ty, llvm_i32_ty, llvm_v2i64_ty], + [IntrNoMem]>; + +def int_mips_ld_b : GCCBuiltin<"__builtin_msa_ld_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_ptr_ty, llvm_i32_ty], + [IntrReadArgMem]>; +def int_mips_ld_h : GCCBuiltin<"__builtin_msa_ld_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_ptr_ty, llvm_i32_ty], + [IntrReadArgMem]>; +def int_mips_ld_w : GCCBuiltin<"__builtin_msa_ld_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_ptr_ty, llvm_i32_ty], + [IntrReadArgMem]>; +def int_mips_ld_d : GCCBuiltin<"__builtin_msa_ld_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_ptr_ty, llvm_i32_ty], + [IntrReadArgMem]>; + +def int_mips_ldi_b : GCCBuiltin<"__builtin_msa_ldi_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_i32_ty], [IntrNoMem]>; +def int_mips_ldi_h : GCCBuiltin<"__builtin_msa_ldi_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_i32_ty], [IntrNoMem]>; +def int_mips_ldi_w : GCCBuiltin<"__builtin_msa_ldi_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_i32_ty], [IntrNoMem]>; +def int_mips_ldi_d : GCCBuiltin<"__builtin_msa_ldi_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_i32_ty], [IntrNoMem]>; + +// This instruction is part of the MSA spec but it does not share the +// __builtin_msa prefix because it operates on the GPR registers. +def int_mips_lsa : GCCBuiltin<"__builtin_mips_lsa">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; + +def int_mips_madd_q_h : GCCBuiltin<"__builtin_msa_madd_q_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; +def int_mips_madd_q_w : GCCBuiltin<"__builtin_msa_madd_q_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + +def int_mips_maddr_q_h : GCCBuiltin<"__builtin_msa_maddr_q_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; +def int_mips_maddr_q_w : GCCBuiltin<"__builtin_msa_maddr_q_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + +def int_mips_maddv_b : GCCBuiltin<"__builtin_msa_maddv_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem]>; +def int_mips_maddv_h : GCCBuiltin<"__builtin_msa_maddv_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; +def int_mips_maddv_w : GCCBuiltin<"__builtin_msa_maddv_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; +def int_mips_maddv_d : GCCBuiltin<"__builtin_msa_maddv_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty], + [IntrNoMem]>; + +def int_mips_max_a_b : GCCBuiltin<"__builtin_msa_max_a_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_max_a_h : GCCBuiltin<"__builtin_msa_max_a_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_max_a_w : GCCBuiltin<"__builtin_msa_max_a_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_max_a_d : GCCBuiltin<"__builtin_msa_max_a_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_max_s_b : GCCBuiltin<"__builtin_msa_max_s_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_max_s_h : GCCBuiltin<"__builtin_msa_max_s_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_max_s_w : GCCBuiltin<"__builtin_msa_max_s_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_max_s_d : GCCBuiltin<"__builtin_msa_max_s_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_max_u_b : GCCBuiltin<"__builtin_msa_max_u_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_max_u_h : GCCBuiltin<"__builtin_msa_max_u_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_max_u_w : GCCBuiltin<"__builtin_msa_max_u_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_max_u_d : GCCBuiltin<"__builtin_msa_max_u_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_maxi_s_b : GCCBuiltin<"__builtin_msa_maxi_s_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_maxi_s_h : GCCBuiltin<"__builtin_msa_maxi_s_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_maxi_s_w : GCCBuiltin<"__builtin_msa_maxi_s_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_maxi_s_d : GCCBuiltin<"__builtin_msa_maxi_s_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_maxi_u_b : GCCBuiltin<"__builtin_msa_maxi_u_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_maxi_u_h : GCCBuiltin<"__builtin_msa_maxi_u_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_maxi_u_w : GCCBuiltin<"__builtin_msa_maxi_u_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_maxi_u_d : GCCBuiltin<"__builtin_msa_maxi_u_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_min_a_b : GCCBuiltin<"__builtin_msa_min_a_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_min_a_h : GCCBuiltin<"__builtin_msa_min_a_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_min_a_w : GCCBuiltin<"__builtin_msa_min_a_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_min_a_d : GCCBuiltin<"__builtin_msa_min_a_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_min_s_b : GCCBuiltin<"__builtin_msa_min_s_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_min_s_h : GCCBuiltin<"__builtin_msa_min_s_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_min_s_w : GCCBuiltin<"__builtin_msa_min_s_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_min_s_d : GCCBuiltin<"__builtin_msa_min_s_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_min_u_b : GCCBuiltin<"__builtin_msa_min_u_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_min_u_h : GCCBuiltin<"__builtin_msa_min_u_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_min_u_w : GCCBuiltin<"__builtin_msa_min_u_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_min_u_d : GCCBuiltin<"__builtin_msa_min_u_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_mini_s_b : GCCBuiltin<"__builtin_msa_mini_s_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_mini_s_h : GCCBuiltin<"__builtin_msa_mini_s_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_mini_s_w : GCCBuiltin<"__builtin_msa_mini_s_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_mini_s_d : GCCBuiltin<"__builtin_msa_mini_s_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_mini_u_b : GCCBuiltin<"__builtin_msa_mini_u_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_mini_u_h : GCCBuiltin<"__builtin_msa_mini_u_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_mini_u_w : GCCBuiltin<"__builtin_msa_mini_u_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_mini_u_d : GCCBuiltin<"__builtin_msa_mini_u_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_mod_s_b : GCCBuiltin<"__builtin_msa_mod_s_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_mod_s_h : GCCBuiltin<"__builtin_msa_mod_s_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_mod_s_w : GCCBuiltin<"__builtin_msa_mod_s_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_mod_s_d : GCCBuiltin<"__builtin_msa_mod_s_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_mod_u_b : GCCBuiltin<"__builtin_msa_mod_u_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_mod_u_h : GCCBuiltin<"__builtin_msa_mod_u_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_mod_u_w : GCCBuiltin<"__builtin_msa_mod_u_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_mod_u_d : GCCBuiltin<"__builtin_msa_mod_u_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_move_v : GCCBuiltin<"__builtin_msa_move_v">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty], [IntrNoMem]>; + +def int_mips_msub_q_h : GCCBuiltin<"__builtin_msa_msub_q_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; +def int_mips_msub_q_w : GCCBuiltin<"__builtin_msa_msub_q_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + +def int_mips_msubr_q_h : GCCBuiltin<"__builtin_msa_msubr_q_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; +def int_mips_msubr_q_w : GCCBuiltin<"__builtin_msa_msubr_q_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + +def int_mips_msubv_b : GCCBuiltin<"__builtin_msa_msubv_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem]>; +def int_mips_msubv_h : GCCBuiltin<"__builtin_msa_msubv_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; +def int_mips_msubv_w : GCCBuiltin<"__builtin_msa_msubv_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; +def int_mips_msubv_d : GCCBuiltin<"__builtin_msa_msubv_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty], + [IntrNoMem]>; + +def int_mips_mul_q_h : GCCBuiltin<"__builtin_msa_mul_q_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_mul_q_w : GCCBuiltin<"__builtin_msa_mul_q_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; + +def int_mips_mulr_q_h : GCCBuiltin<"__builtin_msa_mulr_q_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_mulr_q_w : GCCBuiltin<"__builtin_msa_mulr_q_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; + +def int_mips_mulv_b : GCCBuiltin<"__builtin_msa_mulv_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_mulv_h : GCCBuiltin<"__builtin_msa_mulv_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_mulv_w : GCCBuiltin<"__builtin_msa_mulv_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_mulv_d : GCCBuiltin<"__builtin_msa_mulv_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_nloc_b : GCCBuiltin<"__builtin_msa_nloc_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_nloc_h : GCCBuiltin<"__builtin_msa_nloc_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_nloc_w : GCCBuiltin<"__builtin_msa_nloc_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_nloc_d : GCCBuiltin<"__builtin_msa_nloc_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_nlzc_b : GCCBuiltin<"__builtin_msa_nlzc_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_nlzc_h : GCCBuiltin<"__builtin_msa_nlzc_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_nlzc_w : GCCBuiltin<"__builtin_msa_nlzc_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_nlzc_d : GCCBuiltin<"__builtin_msa_nlzc_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_nor_v : GCCBuiltin<"__builtin_msa_nor_v">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; + +def int_mips_nori_b : GCCBuiltin<"__builtin_msa_nori_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_or_v : GCCBuiltin<"__builtin_msa_or_v">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; + +def int_mips_ori_b : GCCBuiltin<"__builtin_msa_ori_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_pckev_b : GCCBuiltin<"__builtin_msa_pckev_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_pckev_h : GCCBuiltin<"__builtin_msa_pckev_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_pckev_w : GCCBuiltin<"__builtin_msa_pckev_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_pckev_d : GCCBuiltin<"__builtin_msa_pckev_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_pckod_b : GCCBuiltin<"__builtin_msa_pckod_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_pckod_h : GCCBuiltin<"__builtin_msa_pckod_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_pckod_w : GCCBuiltin<"__builtin_msa_pckod_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_pckod_d : GCCBuiltin<"__builtin_msa_pckod_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_pcnt_b : GCCBuiltin<"__builtin_msa_pcnt_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_pcnt_h : GCCBuiltin<"__builtin_msa_pcnt_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_pcnt_w : GCCBuiltin<"__builtin_msa_pcnt_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_pcnt_d : GCCBuiltin<"__builtin_msa_pcnt_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_sat_s_b : GCCBuiltin<"__builtin_msa_sat_s_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_sat_s_h : GCCBuiltin<"__builtin_msa_sat_s_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_sat_s_w : GCCBuiltin<"__builtin_msa_sat_s_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_sat_s_d : GCCBuiltin<"__builtin_msa_sat_s_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_sat_u_b : GCCBuiltin<"__builtin_msa_sat_u_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_sat_u_h : GCCBuiltin<"__builtin_msa_sat_u_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_sat_u_w : GCCBuiltin<"__builtin_msa_sat_u_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_sat_u_d : GCCBuiltin<"__builtin_msa_sat_u_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_shf_b : GCCBuiltin<"__builtin_msa_shf_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_shf_h : GCCBuiltin<"__builtin_msa_shf_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_shf_w : GCCBuiltin<"__builtin_msa_shf_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_sld_b : GCCBuiltin<"__builtin_msa_sld_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_sld_h : GCCBuiltin<"__builtin_msa_sld_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_sld_w : GCCBuiltin<"__builtin_msa_sld_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_sld_d : GCCBuiltin<"__builtin_msa_sld_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_sldi_b : GCCBuiltin<"__builtin_msa_sldi_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_sldi_h : GCCBuiltin<"__builtin_msa_sldi_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_sldi_w : GCCBuiltin<"__builtin_msa_sldi_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_sldi_d : GCCBuiltin<"__builtin_msa_sldi_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_sll_b : GCCBuiltin<"__builtin_msa_sll_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_sll_h : GCCBuiltin<"__builtin_msa_sll_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_sll_w : GCCBuiltin<"__builtin_msa_sll_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_sll_d : GCCBuiltin<"__builtin_msa_sll_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_slli_b : GCCBuiltin<"__builtin_msa_slli_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_slli_h : GCCBuiltin<"__builtin_msa_slli_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_slli_w : GCCBuiltin<"__builtin_msa_slli_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_slli_d : GCCBuiltin<"__builtin_msa_slli_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_splat_b : GCCBuiltin<"__builtin_msa_splat_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_splat_h : GCCBuiltin<"__builtin_msa_splat_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_splat_w : GCCBuiltin<"__builtin_msa_splat_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_splat_d : GCCBuiltin<"__builtin_msa_splat_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_splati_b : GCCBuiltin<"__builtin_msa_splati_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_splati_h : GCCBuiltin<"__builtin_msa_splati_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_splati_w : GCCBuiltin<"__builtin_msa_splati_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_splati_d : GCCBuiltin<"__builtin_msa_splati_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_sra_b : GCCBuiltin<"__builtin_msa_sra_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_sra_h : GCCBuiltin<"__builtin_msa_sra_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_sra_w : GCCBuiltin<"__builtin_msa_sra_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_sra_d : GCCBuiltin<"__builtin_msa_sra_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_srai_b : GCCBuiltin<"__builtin_msa_srai_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_srai_h : GCCBuiltin<"__builtin_msa_srai_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_srai_w : GCCBuiltin<"__builtin_msa_srai_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_srai_d : GCCBuiltin<"__builtin_msa_srai_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_srar_b : GCCBuiltin<"__builtin_msa_srar_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_srar_h : GCCBuiltin<"__builtin_msa_srar_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_srar_w : GCCBuiltin<"__builtin_msa_srar_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_srar_d : GCCBuiltin<"__builtin_msa_srar_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_srari_b : GCCBuiltin<"__builtin_msa_srari_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_srari_h : GCCBuiltin<"__builtin_msa_srari_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_srari_w : GCCBuiltin<"__builtin_msa_srari_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_srari_d : GCCBuiltin<"__builtin_msa_srari_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_srl_b : GCCBuiltin<"__builtin_msa_srl_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_srl_h : GCCBuiltin<"__builtin_msa_srl_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_srl_w : GCCBuiltin<"__builtin_msa_srl_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_srl_d : GCCBuiltin<"__builtin_msa_srl_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_srli_b : GCCBuiltin<"__builtin_msa_srli_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_srli_h : GCCBuiltin<"__builtin_msa_srli_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_srli_w : GCCBuiltin<"__builtin_msa_srli_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_srli_d : GCCBuiltin<"__builtin_msa_srli_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_srlr_b : GCCBuiltin<"__builtin_msa_srlr_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_srlr_h : GCCBuiltin<"__builtin_msa_srlr_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_srlr_w : GCCBuiltin<"__builtin_msa_srlr_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_srlr_d : GCCBuiltin<"__builtin_msa_srlr_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_srlri_b : GCCBuiltin<"__builtin_msa_srlri_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_srlri_h : GCCBuiltin<"__builtin_msa_srlri_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_srlri_w : GCCBuiltin<"__builtin_msa_srlri_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_srlri_d : GCCBuiltin<"__builtin_msa_srlri_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_st_b : GCCBuiltin<"__builtin_msa_st_b">, + Intrinsic<[], [llvm_v16i8_ty, llvm_ptr_ty, llvm_i32_ty], + [IntrReadWriteArgMem]>; +def int_mips_st_h : GCCBuiltin<"__builtin_msa_st_h">, + Intrinsic<[], [llvm_v8i16_ty, llvm_ptr_ty, llvm_i32_ty], + [IntrReadWriteArgMem]>; +def int_mips_st_w : GCCBuiltin<"__builtin_msa_st_w">, + Intrinsic<[], [llvm_v4i32_ty, llvm_ptr_ty, llvm_i32_ty], + [IntrReadWriteArgMem]>; +def int_mips_st_d : GCCBuiltin<"__builtin_msa_st_d">, + Intrinsic<[], [llvm_v2i64_ty, llvm_ptr_ty, llvm_i32_ty], + [IntrReadWriteArgMem]>; + +def int_mips_subs_s_b : GCCBuiltin<"__builtin_msa_subs_s_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_subs_s_h : GCCBuiltin<"__builtin_msa_subs_s_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_subs_s_w : GCCBuiltin<"__builtin_msa_subs_s_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_subs_s_d : GCCBuiltin<"__builtin_msa_subs_s_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_subs_u_b : GCCBuiltin<"__builtin_msa_subs_u_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_subs_u_h : GCCBuiltin<"__builtin_msa_subs_u_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_subs_u_w : GCCBuiltin<"__builtin_msa_subs_u_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_subs_u_d : GCCBuiltin<"__builtin_msa_subs_u_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_subsus_u_b : GCCBuiltin<"__builtin_msa_subsus_u_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_subsus_u_h : GCCBuiltin<"__builtin_msa_subsus_u_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_subsus_u_w : GCCBuiltin<"__builtin_msa_subsus_u_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_subsus_u_d : GCCBuiltin<"__builtin_msa_subsus_u_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_subsuu_s_b : GCCBuiltin<"__builtin_msa_subsuu_s_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_subsuu_s_h : GCCBuiltin<"__builtin_msa_subsuu_s_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_subsuu_s_w : GCCBuiltin<"__builtin_msa_subsuu_s_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_subsuu_s_d : GCCBuiltin<"__builtin_msa_subsuu_s_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_subv_b : GCCBuiltin<"__builtin_msa_subv_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; +def int_mips_subv_h : GCCBuiltin<"__builtin_msa_subv_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; +def int_mips_subv_w : GCCBuiltin<"__builtin_msa_subv_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +def int_mips_subv_d : GCCBuiltin<"__builtin_msa_subv_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + +def int_mips_subvi_b : GCCBuiltin<"__builtin_msa_subvi_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_subvi_h : GCCBuiltin<"__builtin_msa_subvi_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_subvi_w : GCCBuiltin<"__builtin_msa_subvi_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; +def int_mips_subvi_d : GCCBuiltin<"__builtin_msa_subvi_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_mips_vshf_b : GCCBuiltin<"__builtin_msa_vshf_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem]>; +def int_mips_vshf_h : GCCBuiltin<"__builtin_msa_vshf_h">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; +def int_mips_vshf_w : GCCBuiltin<"__builtin_msa_vshf_w">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; +def int_mips_vshf_d : GCCBuiltin<"__builtin_msa_vshf_d">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty], + [IntrNoMem]>; + +def int_mips_xor_v : GCCBuiltin<"__builtin_msa_xor_v">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; + +def int_mips_xori_b : GCCBuiltin<"__builtin_msa_xori_b">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; } diff --git a/contrib/llvm/include/llvm/IR/IntrinsicsNVVM.td b/contrib/llvm/include/llvm/IR/IntrinsicsNVVM.td index c248517de..a372c22e4 100644 --- a/contrib/llvm/include/llvm/IR/IntrinsicsNVVM.td +++ b/contrib/llvm/include/llvm/IR/IntrinsicsNVVM.td @@ -861,8 +861,6 @@ def int_nvvm_ptr_gen_to_param: Intrinsic<[llvm_anyptr_ty], // Move intrinsics, used in nvvm internally -def int_nvvm_move_i8 : Intrinsic<[llvm_i8_ty], [llvm_i8_ty], [IntrNoMem], - "llvm.nvvm.move.i8">; def int_nvvm_move_i16 : Intrinsic<[llvm_i16_ty], [llvm_i16_ty], [IntrNoMem], "llvm.nvvm.move.i16">; def int_nvvm_move_i32 : Intrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrNoMem], diff --git a/contrib/llvm/include/llvm/IR/IntrinsicsPowerPC.td b/contrib/llvm/include/llvm/IR/IntrinsicsPowerPC.td index 5664f7925..49ddfb8b6 100644 --- a/contrib/llvm/include/llvm/IR/IntrinsicsPowerPC.td +++ b/contrib/llvm/include/llvm/IR/IntrinsicsPowerPC.td @@ -30,6 +30,11 @@ let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.". // sync instruction def int_ppc_sync : Intrinsic<[], [], []>; + + // Intrinsics used to generate ctr-based loops. These should only be + // generated by the PowerPC backend! + def int_ppc_mtctr : Intrinsic<[], [llvm_anyint_ty], []>; + def int_ppc_is_decremented_ctr_nonzero : Intrinsic<[llvm_i1_ty], [], []>; } diff --git a/contrib/llvm/include/llvm/IR/IntrinsicsX86.td b/contrib/llvm/include/llvm/IR/IntrinsicsX86.td index 69e0ab4fa..4c5718f8c 100644 --- a/contrib/llvm/include/llvm/IR/IntrinsicsX86.td +++ b/contrib/llvm/include/llvm/IR/IntrinsicsX86.td @@ -206,6 +206,7 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_sse_cvtsi642ss : GCCBuiltin<"__builtin_ia32_cvtsi642ss">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_i64_ty], [IntrNoMem]>; + def int_x86_sse_cvtps2pi : GCCBuiltin<"__builtin_ia32_cvtps2pi">, Intrinsic<[llvm_x86mmx_ty], [llvm_v4f32_ty], [IntrNoMem]>; def int_x86_sse_cvttps2pi: GCCBuiltin<"__builtin_ia32_cvttps2pi">, @@ -936,9 +937,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_sse42_crc32_32_32 : GCCBuiltin<"__builtin_ia32_crc32si">, Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_sse42_crc32_64_8 : - Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i8_ty], - [IntrNoMem]>; def int_x86_sse42_crc32_64_64 : GCCBuiltin<"__builtin_ia32_crc32di">, Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty], [IntrNoMem]>; @@ -1635,7 +1633,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". GCCBuiltin<"__builtin_ia32_vbroadcastss_ps256">, Intrinsic<[llvm_v8f32_ty], [llvm_v4f32_ty], [IntrNoMem]>; def int_x86_avx2_vbroadcasti128 : - GCCBuiltin<"__builtin_ia32_vbroadcastsi256">, Intrinsic<[llvm_v4i64_ty], [llvm_ptr_ty], [IntrReadArgMem]>; def int_x86_avx2_pbroadcastb_128 : GCCBuiltin<"__builtin_ia32_pbroadcastb128">, @@ -1867,6 +1864,14 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; + def int_x86_fma_vfmadd_ps_512 : GCCBuiltin<"__builtin_ia32_vfmaddps512">, + Intrinsic<[llvm_v16f32_ty], + [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty], + [IntrNoMem]>; + def int_x86_fma_vfmadd_pd_512 : GCCBuiltin<"__builtin_ia32_vfmaddpd512">, + Intrinsic<[llvm_v8f64_ty], + [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_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], @@ -1891,6 +1896,14 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; + def int_x86_fma_vfmsub_ps_512 : GCCBuiltin<"__builtin_ia32_vfmsubps512">, + Intrinsic<[llvm_v16f32_ty], + [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty], + [IntrNoMem]>; + def int_x86_fma_vfmsub_pd_512 : GCCBuiltin<"__builtin_ia32_vfmsubpd512">, + Intrinsic<[llvm_v8f64_ty], + [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_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], @@ -1915,6 +1928,14 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; + def int_x86_fma_vfnmadd_ps_512 : GCCBuiltin<"__builtin_ia32_vfnmaddps512">, + Intrinsic<[llvm_v16f32_ty], + [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty], + [IntrNoMem]>; + def int_x86_fma_vfnmadd_pd_512 : GCCBuiltin<"__builtin_ia32_vfnmaddpd512">, + Intrinsic<[llvm_v8f64_ty], + [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_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], @@ -1939,6 +1960,14 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; + def int_x86_fma_vfnmsub_ps_512 : GCCBuiltin<"__builtin_ia32_vfnmsubps512">, + Intrinsic<[llvm_v16f32_ty], + [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty], + [IntrNoMem]>; + def int_x86_fma_vfnmsub_pd_512 : GCCBuiltin<"__builtin_ia32_vfnmsubpd512">, + Intrinsic<[llvm_v8f64_ty], + [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_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], @@ -1957,6 +1986,14 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; + def int_x86_fma_vfmaddsub_ps_512 : GCCBuiltin<"__builtin_ia32_vfmaddsubps512">, + Intrinsic<[llvm_v16f32_ty], + [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty], + [IntrNoMem]>; + def int_x86_fma_vfmaddsub_pd_512 : GCCBuiltin<"__builtin_ia32_vfmaddsubpd512">, + Intrinsic<[llvm_v8f64_ty], + [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_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], @@ -1975,6 +2012,14 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; + def int_x86_fma_vfmsubadd_ps_512 : GCCBuiltin<"__builtin_ia32_vfmsubaddps512">, + Intrinsic<[llvm_v16f32_ty], + [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty], + [IntrNoMem]>; + def int_x86_fma_vfmsubadd_pd_512 : GCCBuiltin<"__builtin_ia32_vfmsubaddpd512">, + Intrinsic<[llvm_v8f64_ty], + [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty], + [IntrNoMem]>; } //===----------------------------------------------------------------------===// @@ -2549,6 +2594,16 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". [IntrNoMem]>; } +//===----------------------------------------------------------------------===// +// TBM + +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_tbm_bextri_u32 : GCCBuiltin<"__builtin_ia32_bextri_u32">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_tbm_bextri_u64 : GCCBuiltin<"__builtin_ia32_bextri_u64">, + Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty], [IntrNoMem]>; +} + //===----------------------------------------------------------------------===// // RDRAND intrinsics - Return a random value and whether it is valid. // RDSEED intrinsics - Return a NIST SP800-90B & C compliant random value and @@ -2578,3 +2633,493 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_xtest : GCCBuiltin<"__builtin_ia32_xtest">, Intrinsic<[llvm_i32_ty], [], []>; } + +//===----------------------------------------------------------------------===// +// AVX512 + +// Mask ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + // Mask instructions + // 16-bit mask + def int_x86_kadd_v16i1 : GCCBuiltin<"__builtin_ia32_kaddw">, + Intrinsic<[llvm_v16i1_ty], [llvm_v16i1_ty, llvm_v16i1_ty], + [IntrNoMem]>; + def int_x86_kand_v16i1 : GCCBuiltin<"__builtin_ia32_kandw">, + Intrinsic<[llvm_v16i1_ty], [llvm_v16i1_ty, llvm_v16i1_ty], + [IntrNoMem]>; + def int_x86_kandn_v16i1 : GCCBuiltin<"__builtin_ia32_kandnw">, + Intrinsic<[llvm_v16i1_ty], [llvm_v16i1_ty, llvm_v16i1_ty], + [IntrNoMem]>; + def int_x86_knot_v16i1 : GCCBuiltin<"__builtin_ia32_knotw">, + Intrinsic<[llvm_v16i1_ty], [llvm_v16i1_ty], [IntrNoMem]>; + def int_x86_kor_v16i1 : GCCBuiltin<"__builtin_ia32_korw">, + Intrinsic<[llvm_v16i1_ty], [llvm_v16i1_ty, llvm_v16i1_ty], + [IntrNoMem]>; + def int_x86_kxor_v16i1 : GCCBuiltin<"__builtin_ia32_kxorw">, + Intrinsic<[llvm_v16i1_ty], [llvm_v16i1_ty, llvm_v16i1_ty], + [IntrNoMem]>; + def int_x86_kxnor_v16i1 : GCCBuiltin<"__builtin_ia32_kxnorw">, + Intrinsic<[llvm_v16i1_ty], [llvm_v16i1_ty, llvm_v16i1_ty], + [IntrNoMem]>; + def int_x86_mask2int_v16i1 : GCCBuiltin<"__builtin_ia32_mask2intw">, + Intrinsic<[llvm_i32_ty], [llvm_v16i1_ty], [IntrNoMem]>; + def int_x86_int2mask_v16i1 : GCCBuiltin<"__builtin_ia32_int2maskw">, + Intrinsic<[llvm_v16i1_ty], [llvm_i32_ty], [IntrNoMem]>; + def int_x86_kunpck_v16i1 : GCCBuiltin<"__builtin_ia32_kunpckbw">, + Intrinsic<[llvm_v16i1_ty], [llvm_v8i1_ty, llvm_v8i1_ty], + [IntrNoMem]>; + def int_x86_avx512_kortestz : GCCBuiltin<"__builtin_ia32_kortestz">, + Intrinsic<[llvm_i32_ty], [llvm_i16_ty, llvm_i16_ty], + [IntrNoMem]>; + def int_x86_avx512_kortestc : GCCBuiltin<"__builtin_ia32_kortestc">, + Intrinsic<[llvm_i32_ty], [llvm_i16_ty, llvm_i16_ty], + [IntrNoMem]>; +} + +// Conversion ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx512_cvtss2usi : GCCBuiltin<"__builtin_ia32_cvtss2usi">, + Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_avx512_cvtss2usi64 : GCCBuiltin<"__builtin_ia32_cvtss2usi64">, + Intrinsic<[llvm_i64_ty], [llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_avx512_cvttss2usi : GCCBuiltin<"__builtin_ia32_cvttss2usi">, + Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_avx512_cvttss2usi64 : GCCBuiltin<"__builtin_ia32_cvttss2usi64">, + Intrinsic<[llvm_i64_ty], [llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_avx512_cvtusi2ss : GCCBuiltin<"__builtin_ia32_cvtusi2ss">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_cvtusi642ss : GCCBuiltin<"__builtin_ia32_cvtusi642ss">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, + llvm_i64_ty], [IntrNoMem]>; + + def int_x86_avx512_cvtsd2usi : GCCBuiltin<"__builtin_ia32_cvtsd2usi">, + Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_avx512_cvtsd2usi64 : GCCBuiltin<"__builtin_ia32_cvtsd2usi64">, + Intrinsic<[llvm_i64_ty], [llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_avx512_cvttsd2usi : GCCBuiltin<"__builtin_ia32_cvttsd2usi">, + Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_avx512_cvttsd2usi64 : GCCBuiltin<"__builtin_ia32_cvttsd2usi64">, + Intrinsic<[llvm_i64_ty], [llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_avx512_cvtusi2sd : GCCBuiltin<"__builtin_ia32_cvtusi2sd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_cvtusi642sd : GCCBuiltin<"__builtin_ia32_cvtusi642sd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, + llvm_i64_ty], [IntrNoMem]>; + + def int_x86_avx512_vcvtph2ps_512 : GCCBuiltin<"__builtin_ia32_vcvtph2ps512">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16i16_ty], [IntrNoMem]>; + def int_x86_avx512_vcvtps2ph_512 : GCCBuiltin<"__builtin_ia32_vcvtps2ph512">, + Intrinsic<[llvm_v16i16_ty], [llvm_v16f32_ty, llvm_i32_ty], + [IntrNoMem]>; +} + +// Vector convert +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx512_cvt_ps2dq_512 : GCCBuiltin<"__builtin_ia32_cvtps2dq512">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16f32_ty], [IntrNoMem]>; + def int_x86_avx512_cvtdq2_ps_512 : GCCBuiltin<"__builtin_ia32_cvtdq2ps512">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16i32_ty], [IntrNoMem]>; +} + +// Vector load with broadcast +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx512_vbroadcast_ss_512 : + GCCBuiltin<"__builtin_ia32_vbroadcastss512">, + Intrinsic<[llvm_v16f32_ty], [llvm_ptr_ty], [IntrReadArgMem]>; + def int_x86_avx512_vbroadcast_ss_ps_512 : + GCCBuiltin<"__builtin_ia32_vbroadcastss_ps512">, + Intrinsic<[llvm_v16f32_ty], [llvm_v4f32_ty], [IntrNoMem]>; + + def int_x86_avx512_vbroadcast_sd_512 : + GCCBuiltin<"__builtin_ia32_vbroadcastsd512">, + Intrinsic<[llvm_v8f64_ty], [llvm_ptr_ty], [IntrReadArgMem]>; + def int_x86_avx512_vbroadcast_sd_pd_512 : + GCCBuiltin<"__builtin_ia32_vbroadcastsd_pd512">, + Intrinsic<[llvm_v8f64_ty], [llvm_v2f64_ty], [IntrNoMem]>; + + def int_x86_avx512_pbroadcastd_512 : + GCCBuiltin<"__builtin_ia32_pbroadcastd512">, + Intrinsic<[llvm_v16i32_ty], [llvm_v4i32_ty], [IntrNoMem]>; + def int_x86_avx512_pbroadcastd_i32_512 : + Intrinsic<[llvm_v16i32_ty], [llvm_i32_ty], [IntrNoMem]>; + + def int_x86_avx512_pbroadcastq_512 : + GCCBuiltin<"__builtin_ia32_pbroadcastq512">, + Intrinsic<[llvm_v8i64_ty], [llvm_v2i64_ty], [IntrNoMem]>; + def int_x86_avx512_pbroadcastq_i64_512 : + Intrinsic<[llvm_v8i64_ty], [llvm_i64_ty], [IntrNoMem]>; +} + +// Vector sign and zero extend +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx512_pmovzxbq : GCCBuiltin<"__builtin_ia32_pmovzxbq512">, + Intrinsic<[llvm_v8i64_ty], [llvm_v16i8_ty], + [IntrNoMem]>; + def int_x86_avx512_pmovzxwd : GCCBuiltin<"__builtin_ia32_pmovzxwd512">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i16_ty], + [IntrNoMem]>; + def int_x86_avx512_pmovzxbd : GCCBuiltin<"__builtin_ia32_pmovzxbd512">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i8_ty], + [IntrNoMem]>; + def int_x86_avx512_pmovzxwq : GCCBuiltin<"__builtin_ia32_pmovzxwq512">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i16_ty], + [IntrNoMem]>; + def int_x86_avx512_pmovzxdq : GCCBuiltin<"__builtin_ia32_pmovzxdq512">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i32_ty], + [IntrNoMem]>; +} + +// Arithmetic ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx512_min_ps_512 : GCCBuiltin<"__builtin_ia32_minps512">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, + llvm_v16f32_ty], [IntrNoMem]>; + def int_x86_avx512_min_pd_512 : GCCBuiltin<"__builtin_ia32_minpd512">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, + llvm_v8f64_ty], [IntrNoMem]>; + def int_x86_avx512_max_ps_512 : GCCBuiltin<"__builtin_ia32_maxps512">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, + llvm_v16f32_ty], [IntrNoMem]>; + def int_x86_avx512_max_pd_512 : GCCBuiltin<"__builtin_ia32_maxpd512">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, + llvm_v8f64_ty], [IntrNoMem]>; + + def int_x86_avx512_pmaxu_d : GCCBuiltin<"__builtin_ia32_pmaxud512">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, + llvm_v16i32_ty], [IntrNoMem]>; + def int_x86_avx512_pmaxu_q : GCCBuiltin<"__builtin_ia32_pmaxuq512">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, + llvm_v8i64_ty], [IntrNoMem]>; + def int_x86_avx512_pmaxs_d : GCCBuiltin<"__builtin_ia32_pmaxsd512">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, + llvm_v16i32_ty], [IntrNoMem]>; + def int_x86_avx512_pmaxs_q : GCCBuiltin<"__builtin_ia32_pmaxsq512">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, + llvm_v8i64_ty], [IntrNoMem]>; + + def int_x86_avx512_pminu_d : GCCBuiltin<"__builtin_ia32_pminud512">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, + llvm_v16i32_ty], [IntrNoMem]>; + def int_x86_avx512_pminu_q : GCCBuiltin<"__builtin_ia32_pminuq512">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, + llvm_v8i64_ty], [IntrNoMem]>; + def int_x86_avx512_pmins_d : GCCBuiltin<"__builtin_ia32_pminsd512">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, + llvm_v16i32_ty], [IntrNoMem]>; + def int_x86_avx512_pmins_q : GCCBuiltin<"__builtin_ia32_pminsq512">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, + llvm_v8i64_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_sqrt_ss : GCCBuiltin<"__builtin_ia32_sqrtrndss">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], + [IntrNoMem]>; + def int_x86_avx512_sqrt_sd : GCCBuiltin<"__builtin_ia32_sqrtrndsd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], + [IntrNoMem]>; + + def int_x86_avx512_rndscale_ps_512 : GCCBuiltin<"__builtin_ia32_rndscaleps512">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_rndscale_pd_512 : GCCBuiltin<"__builtin_ia32_rndscalepd512">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, + llvm_i32_ty], [IntrNoMem]>; + + def int_x86_avx512_sqrt_pd_512 : GCCBuiltin<"__builtin_ia32_sqrtpd512">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty], [IntrNoMem]>; + def int_x86_avx512_sqrt_ps_512 : GCCBuiltin<"__builtin_ia32_sqrtps512">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty], [IntrNoMem]>; + + def int_x86_avx512_rcp14_ps_512 : GCCBuiltin<"__builtin_ia32_rcp14ps512">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty], + [IntrNoMem]>; + def int_x86_avx512_rcp14_pd_512 : GCCBuiltin<"__builtin_ia32_rcp14pd512">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty], + [IntrNoMem]>; + def int_x86_avx512_rcp14_ss : GCCBuiltin<"__builtin_ia32_rcp14ss">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], + [IntrNoMem]>; + def int_x86_avx512_rcp14_sd : GCCBuiltin<"__builtin_ia32_rcp14sd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty], + [IntrNoMem]>; + def int_x86_avx512_rsqrt14_ps_512 : GCCBuiltin<"__builtin_ia32_rsqrt14ps512">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty], + [IntrNoMem]>; + def int_x86_avx512_rsqrt14_pd_512 : GCCBuiltin<"__builtin_ia32_rsqrt14pd512">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty], + [IntrNoMem]>; + def int_x86_avx512_rsqrt14_ss : GCCBuiltin<"__builtin_ia32_rsqrt14ss">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], + [IntrNoMem]>; + def int_x86_avx512_rsqrt14_sd : GCCBuiltin<"__builtin_ia32_rsqrt14sd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty], + [IntrNoMem]>; + + def int_x86_avx512_rcp28_ps_512 : GCCBuiltin<"__builtin_ia32_rcp28ps512">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty], + [IntrNoMem]>; + def int_x86_avx512_rcp28_pd_512 : GCCBuiltin<"__builtin_ia32_rcp28pd512">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty], + [IntrNoMem]>; + def int_x86_avx512_rcp28_ss : GCCBuiltin<"__builtin_ia32_rcp28ss">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], + [IntrNoMem]>; + def int_x86_avx512_rcp28_sd : GCCBuiltin<"__builtin_ia32_rcp28sd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty], + [IntrNoMem]>; + def int_x86_avx512_rsqrt28_ps_512 : GCCBuiltin<"__builtin_ia32_rsqrt28ps512">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty], + [IntrNoMem]>; + def int_x86_avx512_rsqrt28_pd_512 : GCCBuiltin<"__builtin_ia32_rsqrt28pd512">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty], + [IntrNoMem]>; + def int_x86_avx512_rsqrt28_ss : GCCBuiltin<"__builtin_ia32_rsqrt28ss">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], + [IntrNoMem]>; + def int_x86_avx512_rsqrt28_sd : GCCBuiltin<"__builtin_ia32_rsqrt28sd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty], + [IntrNoMem]>; +} + +// Integer shift ops. +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx512_psll_dq : GCCBuiltin<"__builtin_ia32_pslldqi512">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_psrl_dq : GCCBuiltin<"__builtin_ia32_psrldqi512">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_psll_dq_bs : GCCBuiltin<"__builtin_ia32_pslldqi512_byteshift">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_psrl_dq_bs : GCCBuiltin<"__builtin_ia32_psrldqi512_byteshift">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, + llvm_i32_ty], [IntrNoMem]>; +} + +// Gather and Scatter ops +let TargetPrefix = "x86" in { + def int_x86_avx512_gather_dpd_mask_512 : GCCBuiltin<"__builtin_ia32_mask_gatherdpd512">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_i8_ty, + llvm_v8i32_ty, llvm_ptr_ty, llvm_i32_ty], + [IntrReadMem]>; + def int_x86_avx512_gather_dps_mask_512 : GCCBuiltin<"__builtin_ia32_mask_gatherdps512">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_i16_ty, + llvm_v16i32_ty, llvm_ptr_ty, llvm_i32_ty], + [IntrReadMem]>; + def int_x86_avx512_gather_qpd_mask_512 : GCCBuiltin<"__builtin_ia32_mask_gatherqpd512">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_i8_ty, + llvm_v8i64_ty, llvm_ptr_ty, llvm_i32_ty], + [IntrReadMem]>; + def int_x86_avx512_gather_qps_mask_512 : GCCBuiltin<"__builtin_ia32_mask_gatherqps512">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_i8_ty, + llvm_v8i64_ty, llvm_ptr_ty, llvm_i32_ty], + [IntrReadMem]>; + + def int_x86_avx512_gather_dpd_512 : GCCBuiltin<"__builtin_ia32_gatherdpd512">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8i32_ty, llvm_ptr_ty, + llvm_i32_ty], + [IntrReadMem]>; + def int_x86_avx512_gather_dps_512 : GCCBuiltin<"__builtin_ia32_gatherdps512">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16i32_ty, llvm_ptr_ty, + llvm_i32_ty], + [IntrReadMem]>; + def int_x86_avx512_gather_qpd_512 : GCCBuiltin<"__builtin_ia32_gatherqpd512">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8i64_ty, llvm_ptr_ty, + llvm_i32_ty], + [IntrReadArgMem]>; + def int_x86_avx512_gather_qps_512 : GCCBuiltin<"__builtin_ia32_gatherqps512">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8i64_ty, llvm_ptr_ty, + llvm_i32_ty], + [IntrReadMem]>; + + def int_x86_avx512_gather_dpq_mask_512 : GCCBuiltin<"__builtin_ia32_mask_gatherdpq512">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_i8_ty, + llvm_v8i32_ty, llvm_ptr_ty, llvm_i32_ty], + [IntrReadMem]>; + def int_x86_avx512_gather_dpi_mask_512 : GCCBuiltin<"__builtin_ia32_mask_gatherdpi512">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_i16_ty, + llvm_v16i32_ty, llvm_ptr_ty, llvm_i32_ty], + [IntrReadArgMem]>; + def int_x86_avx512_gather_qpq_mask_512 : GCCBuiltin<"__builtin_ia32_mask_gatherqpq512">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_i8_ty, + llvm_v8i64_ty, llvm_ptr_ty, llvm_i32_ty], + [IntrReadArgMem]>; + def int_x86_avx512_gather_qpi_mask_512 : GCCBuiltin<"__builtin_ia32_mask_gatherqpi512">, + Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_i8_ty, + llvm_v8i64_ty, llvm_ptr_ty, llvm_i32_ty], + [IntrReadMem]>; + + def int_x86_avx512_gather_dpq_512 : GCCBuiltin<"__builtin_ia32_gatherdpq512">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i32_ty, llvm_ptr_ty, + llvm_i32_ty], + [IntrReadArgMem]>; + def int_x86_avx512_gather_dpi_512 : GCCBuiltin<"__builtin_ia32_gatherdpi512">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_ptr_ty, + llvm_i32_ty], + [IntrReadArgMem]>; + def int_x86_avx512_gather_qpq_512 : GCCBuiltin<"__builtin_ia32_gatherqpq512">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_ptr_ty, + llvm_i32_ty], + [IntrReadArgMem]>; + def int_x86_avx512_gather_qpi_512 : GCCBuiltin<"__builtin_ia32_gatherqpi512">, + Intrinsic<[llvm_v8i32_ty], [llvm_v8i64_ty, llvm_ptr_ty, + llvm_i32_ty], + [IntrReadArgMem]>; +// scatter + def int_x86_avx512_scatter_dpd_mask_512 : GCCBuiltin<"__builtin_ia32_mask_scatterdpd512">, + Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty, + llvm_v8i32_ty, llvm_v8f64_ty, llvm_i32_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_scatter_dps_mask_512 : GCCBuiltin<"__builtin_ia32_mask_scatterdps512">, + Intrinsic<[], [llvm_ptr_ty, llvm_i16_ty, + llvm_v16i32_ty, llvm_v16f32_ty, llvm_i32_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_scatter_qpd_mask_512 : GCCBuiltin<"__builtin_ia32_mask_scatterqpd512">, + Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty, + llvm_v8i64_ty, llvm_v8f64_ty, llvm_i32_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_scatter_qps_mask_512 : GCCBuiltin<"__builtin_ia32_mask_scatterqps512">, + Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty, + llvm_v8i64_ty, llvm_v8f32_ty, llvm_i32_ty], + [IntrReadWriteArgMem]>; + + def int_x86_avx512_scatter_dpd_512 : GCCBuiltin<"__builtin_ia32_scatterdpd512">, + Intrinsic<[], [llvm_ptr_ty, llvm_v8i32_ty, llvm_v8f64_ty, + llvm_i32_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_scatter_dps_512 : GCCBuiltin<"__builtin_ia32_scatterdps512">, + Intrinsic<[], [llvm_ptr_ty, llvm_v16i32_ty, llvm_v16f32_ty, + llvm_i32_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_scatter_qpd_512 : GCCBuiltin<"__builtin_ia32_scatterqpd512">, + Intrinsic<[], [llvm_ptr_ty, llvm_v8i64_ty, llvm_v8f64_ty, + llvm_i32_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_scatter_qps_512 : GCCBuiltin<"__builtin_ia32_scatterqps512">, + Intrinsic<[], [llvm_ptr_ty, llvm_v8i64_ty, llvm_v8f32_ty, + llvm_i32_ty], + [IntrReadWriteArgMem]>; + + def int_x86_avx512_scatter_dpq_mask_512 : GCCBuiltin<"__builtin_ia32_mask_scatterdpq512">, + Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty, llvm_v8i32_ty, + llvm_v8i64_ty, llvm_i32_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_scatter_dpi_mask_512 : GCCBuiltin<"__builtin_ia32_mask_scatterdpi512">, + Intrinsic<[], [llvm_ptr_ty, llvm_i16_ty, + llvm_v16i32_ty, llvm_v16i32_ty, llvm_i32_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_scatter_qpq_mask_512 : GCCBuiltin<"__builtin_ia32_mask_scatterqpq512">, + Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty, + llvm_v8i64_ty, llvm_v8i64_ty, llvm_i32_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_scatter_qpi_mask_512 : GCCBuiltin<"__builtin_ia32_mask_scatterqpi512">, + Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty, + llvm_v8i64_ty, llvm_v8i32_ty, llvm_i32_ty], + [IntrReadWriteArgMem]>; + + def int_x86_avx512_scatter_dpq_512 : GCCBuiltin<"__builtin_ia32_scatterdpq512">, + Intrinsic<[], [llvm_ptr_ty, + llvm_v8i32_ty, llvm_v8i64_ty, llvm_i32_ty], + []>; + def int_x86_avx512_scatter_dpi_512 : GCCBuiltin<"__builtin_ia32_scatterdpi512">, + Intrinsic<[], [llvm_ptr_ty, + llvm_v16i32_ty, llvm_v16i32_ty, llvm_i32_ty], + []>; + def int_x86_avx512_scatter_qpq_512 : GCCBuiltin<"__builtin_ia32_scatterqpq512">, + Intrinsic<[], [llvm_ptr_ty, llvm_v8i64_ty, llvm_v8i64_ty, + llvm_i32_ty], + []>; + def int_x86_avx512_scatter_qpi_512 : GCCBuiltin<"__builtin_ia32_scatterqpi512">, + Intrinsic<[], [llvm_ptr_ty, llvm_v8i64_ty, llvm_v8i32_ty, + llvm_i32_ty], + []>; +} + +// AVX-512 conflict detection +let TargetPrefix = "x86" in { + def int_x86_avx512_conflict_d_512 : GCCBuiltin<"__builtin_ia32_conflictd512">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty], + []>; + def int_x86_avx512_conflict_d_mask_512 : + GCCBuiltin<"__builtin_ia32_mask_conflictd512">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, + llvm_v16i1_ty, llvm_v16i32_ty], + []>; + def int_x86_avx512_conflict_d_maskz_512: + GCCBuiltin<"__builtin_ia32_maskz_conflictd512">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i1_ty, llvm_v16i32_ty], + []>; + + def int_x86_avx512_conflict_q_512 : GCCBuiltin<"__builtin_ia32_conflictq512">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty], + []>; + def int_x86_avx512_conflict_q_mask_512 : + GCCBuiltin<"__builtin_ia32_mask_conflictq512">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, + llvm_v8i1_ty, llvm_v8i64_ty], + []>; + def int_x86_avx512_conflict_q_maskz_512: + GCCBuiltin<"__builtin_ia32_maskz_conflictq512">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i1_ty, llvm_v8i64_ty], + []>; +} + +// Vector blend +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx512_mskblend_ps_512 : GCCBuiltin<"__builtin_ia32_mskblendps512">, + Intrinsic<[llvm_v16f32_ty], + [llvm_v16i1_ty, llvm_v16f32_ty, llvm_v16f32_ty], + [IntrNoMem]>; + def int_x86_avx512_mskblend_pd_512 : GCCBuiltin<"__builtin_ia32_mskblendpd512">, + Intrinsic<[llvm_v8f64_ty], + [llvm_v8i1_ty, llvm_v8f64_ty, llvm_v8f64_ty], + [IntrNoMem]>; + + def int_x86_avx512_mskblend_d_512 : GCCBuiltin<"__builtin_ia32_mskblendd512">, + Intrinsic<[llvm_v16i32_ty], + [llvm_v16i1_ty, llvm_v16i32_ty, llvm_v16i32_ty], + [IntrNoMem]>; + def int_x86_avx512_mskblend_q_512 : GCCBuiltin<"__builtin_ia32_mskblendq512">, + Intrinsic<[llvm_v8i64_ty], + [llvm_v8i1_ty, llvm_v8i64_ty, llvm_v8i64_ty], + [IntrNoMem]>; +} + +// Misc. +let TargetPrefix = "x86" in { + def int_x86_avx512_cmpeq_pi_512 : GCCBuiltin<"__builtin_ia32_cmpeqpi512">, + Intrinsic<[llvm_i16_ty], [llvm_v16i32_ty, llvm_v16i32_ty], + [IntrNoMem]>; + def int_x86_avx512_and_pi : GCCBuiltin<"__builtin_ia32_andpi512">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty], + [IntrNoMem]>; +} + +//===----------------------------------------------------------------------===// +// SHA intrinsics +let TargetPrefix = "x86" in { + def int_x86_sha1rnds4 : GCCBuiltin<"__builtin_ia32_sha1rnds4">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_sha1nexte : GCCBuiltin<"__builtin_ia32_sha1nexte">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; + def int_x86_sha1msg1 : GCCBuiltin<"__builtin_ia32_sha1msg1">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; + def int_x86_sha1msg2 : GCCBuiltin<"__builtin_ia32_sha1msg2">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; + def int_x86_sha256rnds2 : GCCBuiltin<"__builtin_ia32_sha256rnds2">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + def int_x86_sha256msg1 : GCCBuiltin<"__builtin_ia32_sha256msg1">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; + def int_x86_sha256msg2 : GCCBuiltin<"__builtin_ia32_sha256msg2">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +} diff --git a/contrib/llvm/include/llvm/IR/IntrinsicsXCore.td b/contrib/llvm/include/llvm/IR/IntrinsicsXCore.td index a4813135d..bf345d4d0 100644 --- a/contrib/llvm/include/llvm/IR/IntrinsicsXCore.td +++ b/contrib/llvm/include/llvm/IR/IntrinsicsXCore.td @@ -13,7 +13,8 @@ let TargetPrefix = "xcore" in { // All intrinsics start with "llvm.xcore.". // Miscellaneous instructions. - def int_xcore_bitrev : Intrinsic<[llvm_i32_ty],[llvm_i32_ty],[IntrNoMem]>; + def int_xcore_bitrev : Intrinsic<[llvm_i32_ty],[llvm_i32_ty],[IntrNoMem]>, + GCCBuiltin<"__builtin_bitrev">; def int_xcore_crc8 : Intrinsic<[llvm_i32_ty, llvm_i32_ty], [llvm_i32_ty,llvm_i32_ty,llvm_i32_ty], [IntrNoMem]>; @@ -24,9 +25,12 @@ let TargetPrefix = "xcore" in { // All intrinsics start with "llvm.xcore.". [IntrNoMem]>; def int_xcore_zext : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; - def int_xcore_getid : Intrinsic<[llvm_i32_ty],[],[IntrNoMem]>; - def int_xcore_getps : Intrinsic<[llvm_i32_ty],[llvm_i32_ty]>; - def int_xcore_setps : Intrinsic<[],[llvm_i32_ty, llvm_i32_ty]>; + def int_xcore_getid : Intrinsic<[llvm_i32_ty],[],[IntrNoMem]>, + GCCBuiltin<"__builtin_getid">; + def int_xcore_getps : Intrinsic<[llvm_i32_ty],[llvm_i32_ty]>, + GCCBuiltin<"__builtin_getps">; + def int_xcore_setps : Intrinsic<[],[llvm_i32_ty, llvm_i32_ty]>, + GCCBuiltin<"__builtin_setps">; def int_xcore_geted : Intrinsic<[llvm_i32_ty],[]>; def int_xcore_getet : Intrinsic<[llvm_i32_ty],[]>; def int_xcore_setsr : Intrinsic<[],[llvm_i32_ty]>; diff --git a/contrib/llvm/include/llvm/IR/LLVMContext.h b/contrib/llvm/include/llvm/IR/LLVMContext.h index f25d820c2..dd379ae5e 100644 --- a/contrib/llvm/include/llvm/IR/LLVMContext.h +++ b/contrib/llvm/include/llvm/IR/LLVMContext.h @@ -30,7 +30,7 @@ class SMDiagnostic; template class SmallVectorImpl; /// This is an important class for using LLVM in a threaded context. It -/// (opaquely) owns and manages the core "global" data of LLVM's core +/// (opaquely) owns and manages the core "global" data of LLVM's core /// infrastructure, including the type and constant uniquing tables. /// LLVMContext itself provides no locking guarantees, so you should be careful /// to have one context per thread. @@ -39,7 +39,7 @@ public: LLVMContextImpl *const pImpl; LLVMContext(); ~LLVMContext(); - + // Pinned metadata names, which always have the same value. This is a // compile-time performance optimization, not a correctness optimization. enum { @@ -51,19 +51,19 @@ public: MD_tbaa_struct = 5, // "tbaa.struct" MD_invariant_load = 6 // "invariant.load" }; - + /// getMDKindID - Return a unique non-zero ID for the specified metadata kind. /// This ID is uniqued across modules in the current LLVMContext. unsigned getMDKindID(StringRef Name) const; - + /// getMDKindNames - Populate client supplied SmallVector with the name for /// custom metadata IDs registered in this LLVMContext. void getMDKindNames(SmallVectorImpl &Result) const; - - + + typedef void (*InlineAsmDiagHandlerTy)(const SMDiagnostic&, void *Context, unsigned LocCookie); - + /// setInlineAsmDiagnosticHandler - This method sets a handler that is invoked /// when problems with inline asm are detected by the backend. The first /// argument is a function pointer and the second is a context pointer that @@ -81,8 +81,8 @@ public: /// getInlineAsmDiagnosticContext - Return the diagnostic context set by /// setInlineAsmDiagnosticHandler. void *getInlineAsmDiagnosticContext() const; - - + + /// emitError - Emit an error message to the currently installed error handler /// with optional location information. This function returns, so code should /// be prepared to drop the erroneous construct on the floor and "not crash". @@ -99,10 +99,10 @@ private: /// addModule - Register a module as being instantiated in this context. If /// the context is deleted, the module will be deleted as well. void addModule(Module*); - + /// removeModule - Unregister a module from this context. void removeModule(Module*); - + // Module needs access to the add/removeModule methods. friend class Module; }; diff --git a/contrib/llvm/include/llvm/IR/LegacyPassManager.h b/contrib/llvm/include/llvm/IR/LegacyPassManager.h new file mode 100644 index 000000000..fa1436ec6 --- /dev/null +++ b/contrib/llvm/include/llvm/IR/LegacyPassManager.h @@ -0,0 +1,111 @@ +//===- LegacyPassManager.h - Legacy 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 file defines the legacy PassManager class. This class is used to hold, +// maintain, and optimize execution of Passes. The PassManager class ensures +// that analysis results are available before a pass runs, and that Pass's are +// destroyed when the PassManager is destroyed. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_LEGACYPASSMANAGER_H +#define LLVM_IR_LEGACYPASSMANAGER_H + +#include "llvm/Pass.h" +#include "llvm/Support/CBindingWrapping.h" + +namespace llvm { + +class Pass; +class Module; + +namespace legacy { + +class PassManagerImpl; +class FunctionPassManagerImpl; + +/// PassManagerBase - An abstract interface to allow code to add passes to +/// a pass manager without having to hard-code what kind of pass manager +/// it is. +class PassManagerBase { +public: + virtual ~PassManagerBase(); + + /// 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'. + virtual void add(Pass *P) = 0; +}; + +/// PassManager manages ModulePassManagers +class PassManager : public PassManagerBase { +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); + + /// run - Execute all of the passes scheduled for execution. Keep track of + /// whether any of the passes modifies the module, and if so, return true. + bool run(Module &M); + +private: + /// PassManagerImpl_New is the actual class. PassManager is just the + /// wraper to publish simple pass manager interface + PassManagerImpl *PM; +}; + +/// FunctionPassManager manages FunctionPasses and BasicBlockPassManagers. +class FunctionPassManager : public PassManagerBase { +public: + /// FunctionPassManager ctor - This initializes the pass manager. It needs, + /// but does not take ownership of, the specified Module. + 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); + + /// run - Execute all of the passes scheduled for execution. Keep + /// track of whether any of the passes modifies the function, and if + /// so, return true. + /// + bool run(Function &F); + + /// doInitialization - Run all of the initializers for the function passes. + /// + bool doInitialization(); + + /// doFinalization - Run all of the finalizers for the function passes. + /// + bool doFinalization(); + +private: + FunctionPassManagerImpl *FPM; + Module *M; +}; + +} // End legacy namespace + +// Create wrappers for C Binding types (see CBindingWrapping.h). +DEFINE_STDCXX_CONVERSION_FUNCTIONS(legacy::PassManagerBase, LLVMPassManagerRef) + +} // End llvm namespace + +#endif diff --git a/contrib/llvm/include/llvm/PassManagers.h b/contrib/llvm/include/llvm/IR/LegacyPassManagers.h similarity index 99% rename from contrib/llvm/include/llvm/PassManagers.h rename to contrib/llvm/include/llvm/IR/LegacyPassManagers.h index 7afb0a0fb..d256a3e92 100644 --- a/contrib/llvm/include/llvm/PassManagers.h +++ b/contrib/llvm/include/llvm/IR/LegacyPassManagers.h @@ -1,4 +1,4 @@ -//===- llvm/PassManagers.h - Pass Infrastructure classes -------*- C++ -*-===// +//===- LegacyPassManagers.h - Legacy Pass Infrastructure --------*- C++ -*-===// // // The LLVM Compiler Infrastructure // diff --git a/contrib/llvm/include/llvm/IR/Metadata.h b/contrib/llvm/include/llvm/IR/Metadata.h index 8c2cfac23..9659c2e05 100644 --- a/contrib/llvm/include/llvm/IR/Metadata.h +++ b/contrib/llvm/include/llvm/IR/Metadata.h @@ -22,15 +22,16 @@ #include "llvm/IR/Value.h" namespace llvm { -class Constant; -class Instruction; class LLVMContext; class Module; -template class SmallVectorImpl; template class SymbolTableListTraits; +enum LLVMConstants LLVM_ENUM_INT_TYPE(uint32_t) { + DEBUG_METADATA_VERSION = 1 // Current debug info version number. +}; + //===----------------------------------------------------------------------===// /// MDString - a single uniqued string. /// These are used to efficiently contain a byte sequence for metadata. @@ -139,7 +140,7 @@ public: void replaceOperandWith(unsigned i, Value *NewVal); /// getOperand - Return specified operand. - Value *getOperand(unsigned i) const; + Value *getOperand(unsigned i) const LLVM_READONLY; /// getNumOperands - Return number of MDNode operands. unsigned getNumOperands() const { return NumOperands; } @@ -164,6 +165,9 @@ public: return V->getValueID() == MDNodeVal; } + /// Check whether MDNode is a vtable access. + bool isTBAAVtableAccess() const; + /// Methods for metadata merging. static MDNode *getMostGenericTBAA(MDNode *A, MDNode *B); static MDNode *getMostGenericFPMath(MDNode *A, MDNode *B); diff --git a/contrib/llvm/include/llvm/IR/Module.h b/contrib/llvm/include/llvm/IR/Module.h index cb500ffe7..b30a9a3d1 100644 --- a/contrib/llvm/include/llvm/IR/Module.h +++ b/contrib/llvm/include/llvm/IR/Module.h @@ -340,10 +340,6 @@ public: Constant *getOrInsertFunction(StringRef Name, Type *RetTy, ...) END_WITH_NULL; - Constant *getOrInsertTargetIntrinsic(StringRef Name, - FunctionType *Ty, - AttributeSet AttributeList); - /// getFunction - Look up the specified function in the module symbol table. /// If it does not exist, return null. Function *getFunction(StringRef Name) const; @@ -356,15 +352,22 @@ public: /// symbol table. If it does not exist, return null. If AllowInternal is set /// to true, this function will return types that have InternalLinkage. By /// default, these types are not returned. - GlobalVariable *getGlobalVariable(StringRef Name, - bool AllowInternal = false) const; + const GlobalVariable *getGlobalVariable(StringRef Name, + bool AllowInternal = false) const { + return const_cast(this)->getGlobalVariable(Name, AllowInternal); + } + + GlobalVariable *getGlobalVariable(StringRef Name, bool AllowInternal = false); /// getNamedGlobal - Return the global variable in the module with the /// specified name, of arbitrary type. This method returns null if a global /// with the specified name is not found. - GlobalVariable *getNamedGlobal(StringRef Name) const { + GlobalVariable *getNamedGlobal(StringRef Name) { return getGlobalVariable(Name, true); } + const GlobalVariable *getNamedGlobal(StringRef Name) const { + return const_cast(this)->getNamedGlobal(Name); + } /// getOrInsertGlobal - Look up the specified global in the module symbol /// table. @@ -388,7 +391,7 @@ public: /// @name Named Metadata Accessors /// @{ - /// getNamedMetadata - Return the NamedMDNode in the module with the + /// getNamedMetadata - Return the first NamedMDNode in the module with the /// specified name. This method returns null if a NamedMDNode with the /// specified name is not found. NamedMDNode *getNamedMetadata(const Twine &Name) const; @@ -409,6 +412,10 @@ public: /// getModuleFlagsMetadata - Returns the module flags in the provided vector. void getModuleFlagsMetadata(SmallVectorImpl &Flags) const; + /// Return the corresponding value if Key appears in module flags, otherwise + /// return null. + Value *getModuleFlag(StringRef Key) const; + /// getModuleFlagsMetadata - Returns the NamedMDNode in the module that /// represents module-level flags. This method returns null if there are no /// module-level flags. diff --git a/contrib/llvm/include/llvm/IR/Operator.h b/contrib/llvm/include/llvm/IR/Operator.h index 13ab72cfe..5b9bee7fc 100644 --- a/contrib/llvm/include/llvm/IR/Operator.h +++ b/contrib/llvm/include/llvm/IR/Operator.h @@ -439,8 +439,8 @@ public: /// offset of this GEP if the GEP is in fact constant. If the GEP is not /// all-constant, it returns false and the value of the offset APInt is /// undefined (it is *not* preserved!). The APInt passed into this routine - /// must be at least as wide as the IntPtr type for the address space of - /// the base GEP pointer. + /// must be at exactly as wide as the IntPtr type for the address space of the + /// base GEP pointer. bool accumulateConstantOffset(const DataLayout &DL, APInt &Offset) const { assert(Offset.getBitWidth() == DL.getPointerSizeInBits(getPointerAddressSpace()) && diff --git a/contrib/llvm/include/llvm/IR/PassManager.h b/contrib/llvm/include/llvm/IR/PassManager.h new file mode 100644 index 000000000..833547a23 --- /dev/null +++ b/contrib/llvm/include/llvm/IR/PassManager.h @@ -0,0 +1,383 @@ +//===- PassManager.h - Pass management infrastructure -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// +/// This header defines various interfaces for pass management in LLVM. There +/// is no "pass" interface in LLVM per se. Instead, an instance of any class +/// which supports a method to 'run' it over a unit of IR can be used as +/// a pass. A pass manager is generally a tool to collect a sequence of passes +/// which run over a particular IR construct, and run each of them in sequence +/// over each such construct in the containing IR construct. As there is no +/// containing IR construct for a Module, a manager for passes over modules +/// forms the base case which runs its managed passes in sequence over the +/// single module provided. +/// +/// The core IR library provides managers for running passes over +/// modules and functions. +/// +/// * FunctionPassManager can run over a Module, runs each pass over +/// a Function. +/// * ModulePassManager must be directly run, runs each pass over the Module. +/// +/// Note that the implementations of the pass managers use concept-based +/// polymorphism as outlined in the "Value Semantics and Concept-based +/// Polymorphism" talk (or its abbreviated sibling "Inheritance Is The Base +/// Class of Evil") by Sean Parent: +/// * http://github.com/sean-parent/sean-parent.github.com/wiki/Papers-and-Presentations +/// * http://www.youtube.com/watch?v=_BpMYeUFXv8 +/// * http://channel9.msdn.com/Events/GoingNative/2013/Inheritance-Is-The-Base-Class-of-Evil +/// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/polymorphic_ptr.h" +#include "llvm/Support/type_traits.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Module.h" +#include +#include + +namespace llvm { + +class Module; +class Function; + +/// \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() {} + virtual PassConcept *clone() = 0; + + /// \brief The polymorphic API which runs the pass over a given IR entity. + virtual bool run(T Arg) = 0; +}; + +/// \brief A template wrapper used to implement the polymorphic API. +/// +/// Can be instantiated for any object which provides a \c run method +/// accepting a \c T. It requires the pass to be a copyable +/// object. +template struct PassModel : PassConcept { + PassModel(PassT Pass) : Pass(llvm_move(Pass)) {} + virtual PassModel *clone() { return new PassModel(Pass); } + virtual bool run(T Arg) { return Pass.run(Arg); } + PassT Pass; +}; + +} + +class AnalysisManager; + +class ModulePassManager { +public: + ModulePassManager(Module *M, AnalysisManager *AM = 0) : M(M), AM(AM) {} + + template void addPass(ModulePassT Pass) { + Passes.push_back(new ModulePassModel(llvm_move(Pass))); + } + + void run(); + +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(Pass) {} + }; + + Module *M; + AnalysisManager *AM; + std::vector > Passes; +}; + +class FunctionPassManager { +public: + FunctionPassManager(AnalysisManager *AM = 0) : AM(AM) {} + + template void addPass(FunctionPassT Pass) { + Passes.push_back(new FunctionPassModel(llvm_move(Pass))); + } + + bool run(Module *M); + +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(Pass) {} + }; + + AnalysisManager *AM; + std::vector > Passes; +}; + + +/// \brief An analysis manager to coordinate and cache analyses run over +/// a module. +/// +/// The analysis manager is typically used by passes in a pass pipeline +/// (consisting potentially of several individual pass managers) over a module +/// of IR. It provides registration of available analyses, declaring +/// requirements on support for specific analyses, running of an specific +/// analysis over a specific unit of IR to compute an analysis result, and +/// caching of the analysis results to reuse them across multiple passes. +/// +/// It is the responsibility of callers to use the invalidation API to +/// invalidate analysis results when the IR they correspond to changes. The +/// \c ModulePassManager and \c FunctionPassManager do this automatically. +class AnalysisManager { +public: + AnalysisManager(Module *M) : M(M) {} + + /// \brief Get the result of an analysis pass for this module. + /// + /// If there is not a valid cached result in the manager already, this will + /// re-run the analysis to produce a valid result. + /// + /// The module passed in must be the same module as the analysis manager was + /// constructed around. + template + const typename PassT::Result &getResult(Module *M) { + assert(ModuleAnalysisPasses.count(PassT::ID()) && + "This analysis pass was not registered prior to being queried"); + + const AnalysisResultConcept &ResultConcept = + getResultImpl(PassT::ID(), M); + typedef AnalysisResultModel ResultModelT; + return static_cast(ResultConcept).Result; + } + + /// \brief Get the result of an analysis pass for a function. + /// + /// If there is not a valid cached result in the manager already, this will + /// re-run the analysis to produce a valid result. + template + const typename PassT::Result &getResult(Function *F) { + assert(FunctionAnalysisPasses.count(PassT::ID()) && + "This analysis pass was not registered prior to being queried"); + + const AnalysisResultConcept &ResultConcept = + getResultImpl(PassT::ID(), F); + typedef AnalysisResultModel ResultModelT; + return static_cast(ResultConcept).Result; + } + + /// \brief Register an analysis pass with the manager. + /// + /// This provides an initialized and set-up analysis pass to the + /// analysis + /// manager. Whomever is setting up analysis passes must use this to + /// populate + /// the manager with all of the analysis passes available. + template void registerAnalysisPass(PassT Pass) { + registerAnalysisPassImpl(llvm_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) { + invalidateImpl(PassT::ID(), M); + } + + /// \brief Invalidate a specific analysis pass for an IR function. + /// + /// Note that the analysis result can disregard invalidation. + template void invalidate(Function *F) { + invalidateImpl(PassT::ID(), F); + } + + /// \brief Invalidate analyses cached for an IR Module. + /// + /// Note that specific analysis results can disregard invalidation by + /// overriding their invalidate method. + /// + /// The module must be the module this analysis manager was constructed + /// around. + void invalidateAll(Module *M); + + /// \brief Invalidate analyses cached for an IR Function. + /// + /// Note that specific analysis results can disregard invalidation by + /// overriding the invalidate method. + void invalidateAll(Function *F); + +private: + /// \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() {} + virtual AnalysisResultConcept *clone() = 0; + + /// \brief Method to try and mark a result as invalid. + /// + /// When the outer \c AnalysisManager detects a change in some underlying + /// unit of the IR, it will call this method on all of the results cached. + /// + /// \returns true if the result should indeed be invalidated (the default). + virtual bool invalidate(IRUnitT *IR) = 0; + }; + + /// \brief Wrapper to model the analysis result concept. + /// + /// Can wrap any type which implements a suitable invalidate member and model + /// the AnalysisResultConcept for the AnalysisManager. + template + struct AnalysisResultModel : AnalysisResultConcept { + AnalysisResultModel(ResultT Result) : Result(llvm_move(Result)) {} + virtual AnalysisResultModel *clone() { + return new AnalysisResultModel(Result); + } + + /// \brief The model delegates to the \c ResultT method. + virtual bool invalidate(IRUnitT *IR) { return Result.invalidate(IR); } + + 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() {} + virtual AnalysisPassConcept *clone() = 0; + + /// \brief Method to run this analysis over a unit of IR. + /// \returns The analysis result object to be queried by users, the caller + /// takes ownership. + virtual AnalysisResultConcept *run(IRUnitT *IR) = 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 + struct AnalysisPassModel : AnalysisPassConcept { + AnalysisPassModel(PassT Pass) : Pass(llvm_move(Pass)) {} + virtual AnalysisPassModel *clone() { return new AnalysisPassModel(Pass); } + + // FIXME: Replace PassT::IRUnitT with type traits when we use C++11. + typedef typename PassT::IRUnitT IRUnitT; + + // 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. + virtual ResultModelT *run(IRUnitT *IR) { + return new ResultModelT(Pass.run(IR)); + } + + PassT Pass; + }; + + + /// \brief Get a module pass result, running the pass if necessary. + const AnalysisResultConcept &getResultImpl(void *PassID, Module *M); + + /// \brief Get a function pass result, running the pass if necessary. + const AnalysisResultConcept &getResultImpl(void *PassID, + Function *F); + + /// \brief Invalidate a module pass result. + void invalidateImpl(void *PassID, Module *M); + + /// \brief Invalidate a function pass result. + void invalidateImpl(void *PassID, Function *F); + + + /// \brief Module pass specific implementation of registration. + template + typename enable_if >::type + registerAnalysisPassImpl(PassT Pass) { + assert(!ModuleAnalysisPasses.count(PassT::ID()) && + "Registered the same analysis pass twice!"); + ModuleAnalysisPasses[PassT::ID()] = + new AnalysisPassModel(llvm_move(Pass)); + } + + /// \brief Function pass specific implementation of registration. + template + typename enable_if >::type + registerAnalysisPassImpl(PassT Pass) { + assert(!FunctionAnalysisPasses.count(PassT::ID()) && + "Registered the same analysis pass twice!"); + FunctionAnalysisPasses[PassT::ID()] = + new AnalysisPassModel(llvm_move(Pass)); + } + + + /// \brief Map type from module analysis pass ID to pass concept pointer. + typedef DenseMap > > + ModuleAnalysisPassMapT; + + /// \brief Collection of module analysis passes, indexed by ID. + ModuleAnalysisPassMapT ModuleAnalysisPasses; + + /// \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 Map type from function analysis pass ID to pass concept pointer. + typedef DenseMap > > + FunctionAnalysisPassMapT; + + /// \brief Collection of function analysis passes, indexed by ID. + FunctionAnalysisPassMapT FunctionAnalysisPasses; + + /// \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 > > > + FunctionAnalysisResultListT; + + /// \brief Map type from function pointer to our custom list type. + typedef DenseMap FunctionAnalysisResultListMapT; + + /// \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; + + /// \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; + + /// \brief Map from an analysis ID and function to a particular cached + /// analysis result. + FunctionAnalysisResultMapT FunctionAnalysisResults; + + /// \brief Module handle for the \c AnalysisManager. + Module *M; +}; + +} diff --git a/contrib/llvm/include/llvm/IR/Type.h b/contrib/llvm/include/llvm/IR/Type.h index 1bf8789d3..3cfb84edd 100644 --- a/contrib/llvm/include/llvm/IR/Type.h +++ b/contrib/llvm/include/llvm/IR/Type.h @@ -324,6 +324,14 @@ public: subtype_iterator subtype_begin() const { return ContainedTys; } subtype_iterator subtype_end() const { return &ContainedTys[NumContainedTys];} + typedef std::reverse_iterator subtype_reverse_iterator; + subtype_reverse_iterator subtype_rbegin() const { + return subtype_reverse_iterator(subtype_end()); + } + subtype_reverse_iterator subtype_rend() const { + return subtype_reverse_iterator(subtype_begin()); + } + /// getContainedType - This method is used to implement the type iterator /// (defined a the end of the file). For derived types, this returns the /// types 'contained' in the derived type. diff --git a/contrib/llvm/include/llvm/IR/TypeBuilder.h b/contrib/llvm/include/llvm/IR/TypeBuilder.h index 80c60a080..5a29e1e10 100644 --- a/contrib/llvm/include/llvm/IR/TypeBuilder.h +++ b/contrib/llvm/include/llvm/IR/TypeBuilder.h @@ -17,7 +17,7 @@ #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/LLVMContext.h" -#include +#include namespace llvm { diff --git a/contrib/llvm/include/llvm/IR/Use.h b/contrib/llvm/include/llvm/IR/Use.h index efd8b48a0..12cd150af 100644 --- a/contrib/llvm/include/llvm/IR/Use.h +++ b/contrib/llvm/include/llvm/IR/Use.h @@ -177,7 +177,6 @@ public: typedef typename super::reference reference; typedef typename super::pointer pointer; - value_use_iterator(const _Self &I) : U(I.U) {} value_use_iterator() {} bool operator==(const _Self &x) const { diff --git a/contrib/llvm/include/llvm/IR/Value.h b/contrib/llvm/include/llvm/IR/Value.h index 5fba3d571..e1361fef3 100644 --- a/contrib/llvm/include/llvm/IR/Value.h +++ b/contrib/llvm/include/llvm/IR/Value.h @@ -22,26 +22,29 @@ namespace llvm { -class Constant; +class APInt; class Argument; -class Instruction; +class AssemblyAnnotationWriter; class BasicBlock; -class GlobalValue; +class Constant; +class DataLayout; class Function; -class GlobalVariable; class GlobalAlias; +class GlobalValue; +class GlobalVariable; class InlineAsm; -class ValueSymbolTable; -template class StringMapEntry; -typedef StringMapEntry ValueName; -class raw_ostream; -class AssemblyAnnotationWriter; -class ValueHandleBase; +class Instruction; class LLVMContext; -class Twine; class MDNode; -class Type; class StringRef; +class Twine; +class Type; +class ValueHandleBase; +class ValueSymbolTable; +class raw_ostream; + +template class StringMapEntry; +typedef StringMapEntry ValueName; //===----------------------------------------------------------------------===// // Value Class @@ -260,37 +263,53 @@ public: /// this value. bool hasValueHandle() const { return HasValueHandle; } - /// \brief This method strips off any unneeded pointer casts, - /// all-zero GEPs and aliases from the specified value, returning the original - /// uncasted value. If this is called on a non-pointer value, it returns - /// 'this'. + /// \brief Strips off any unneeded pointer casts, all-zero GEPs and aliases + /// from the specified value, returning the original uncasted value. + /// + /// If this is called on a non-pointer value, it returns 'this'. Value *stripPointerCasts(); const Value *stripPointerCasts() const { return const_cast(this)->stripPointerCasts(); } - /// \brief This method strips off any unneeded pointer casts and - /// all-zero GEPs from the specified value, returning the original - /// uncasted value. If this is called on a non-pointer value, it returns - /// 'this'. + /// \brief Strips off any unneeded pointer casts and all-zero GEPs from the + /// specified value, returning the original uncasted value. + /// + /// If this is called on a non-pointer value, it returns 'this'. Value *stripPointerCastsNoFollowAliases(); const Value *stripPointerCastsNoFollowAliases() const { return const_cast(this)->stripPointerCastsNoFollowAliases(); } - /// stripInBoundsConstantOffsets - This method strips off unneeded pointer casts and - /// all-constant GEPs from the specified value, returning the original - /// pointer value. If this is called on a non-pointer value, it returns - /// 'this'. + /// \brief Strips off unneeded pointer casts and all-constant GEPs from the + /// specified value, returning the original pointer value. + /// + /// If this is called on a non-pointer value, it returns 'this'. Value *stripInBoundsConstantOffsets(); const Value *stripInBoundsConstantOffsets() const { return const_cast(this)->stripInBoundsConstantOffsets(); } - /// stripInBoundsOffsets - This method strips off unneeded pointer casts and - /// any in-bounds Offsets from the specified value, returning the original - /// pointer value. If this is called on a non-pointer value, it returns - /// 'this'. + /// \brief Strips like \c stripInBoundsConstantOffsets but also accumulates + /// the constant offset stripped. + /// + /// Stores the resulting constant offset stripped into the APInt provided. + /// The provided APInt will be extended or truncated as needed to be the + /// correct bitwidth for an offset of this pointer type. + /// + /// If this is called on a non-pointer value, it returns 'this'. + Value *stripAndAccumulateInBoundsConstantOffsets(const DataLayout &DL, + APInt &Offset); + const Value *stripAndAccumulateInBoundsConstantOffsets(const DataLayout &DL, + APInt &Offset) const { + return const_cast(this) + ->stripAndAccumulateInBoundsConstantOffsets(DL, Offset); + } + + /// \brief Strips off unneeded pointer casts and any in-bounds offsets from + /// the specified value, returning the original pointer value. + /// + /// If this is called on a non-pointer value, it returns 'this'. Value *stripInBoundsOffsets(); const Value *stripInBoundsOffsets() const { return const_cast(this)->stripInBoundsOffsets(); diff --git a/contrib/llvm/include/llvm/InitializePasses.h b/contrib/llvm/include/llvm/InitializePasses.h index 5b2cd603c..aefb3c065 100644 --- a/contrib/llvm/include/llvm/InitializePasses.h +++ b/contrib/llvm/include/llvm/InitializePasses.h @@ -70,13 +70,13 @@ void initializeAliasDebuggerPass(PassRegistry&); void initializeAliasSetPrinterPass(PassRegistry&); void initializeAlwaysInlinerPass(PassRegistry&); void initializeArgPromotionPass(PassRegistry&); +void initializeSampleProfileLoaderPass(PassRegistry&); void initializeBarrierNoopPass(PassRegistry&); void initializeBasicAliasAnalysisPass(PassRegistry&); -void initializeBasicCallGraphPass(PassRegistry&); +void initializeCallGraphPass(PassRegistry&); void initializeBasicTTIPass(PassRegistry&); void initializeBlockExtractorPassPass(PassRegistry&); void initializeBlockFrequencyInfoPass(PassRegistry&); -void initializeBlockPlacementPass(PassRegistry&); void initializeBoundsCheckingPass(PassRegistry&); void initializeBranchFolderPassPass(PassRegistry&); void initializeBranchProbabilityInfoPass(PassRegistry&); @@ -87,9 +87,9 @@ void initializeCFGOnlyPrinterPass(PassRegistry&); void initializeCFGOnlyViewerPass(PassRegistry&); void initializeCFGPrinterPass(PassRegistry&); void initializeCFGSimplifyPassPass(PassRegistry&); +void initializeFlattenCFGPassPass(PassRegistry&); +void initializeStructurizeCFGPass(PassRegistry&); void initializeCFGViewerPass(PassRegistry&); -void initializeCalculateSpillWeightsPass(PassRegistry&); -void initializeCallGraphAnalysisGroup(PassRegistry&); void initializeCodeGenPreparePass(PassRegistry&); void initializeConstantMergePass(PassRegistry&); void initializeConstantPropagationPass(PassRegistry&); @@ -100,8 +100,10 @@ void initializeDAEPass(PassRegistry&); void initializeDAHPass(PassRegistry&); void initializeDCEPass(PassRegistry&); void initializeDSEPass(PassRegistry&); +void initializeDebugIRPass(PassRegistry&); void initializeDeadInstEliminationPass(PassRegistry&); void initializeDeadMachineInstructionElimPass(PassRegistry&); +void initializeDelinearizationPass(PassRegistry &); void initializeDependenceAnalysisPass(PassRegistry&); void initializeDomOnlyPrinterPass(PassRegistry&); void initializeDomOnlyViewerPass(PassRegistry&); @@ -111,14 +113,13 @@ void initializeDominanceFrontierPass(PassRegistry&); void initializeDominatorTreePass(PassRegistry&); void initializeEarlyIfConverterPass(PassRegistry&); void initializeEdgeBundlesPass(PassRegistry&); -void initializeEdgeProfilerPass(PassRegistry&); void initializeExpandPostRAPass(PassRegistry&); -void initializePathProfilerPass(PassRegistry&); void initializeGCOVProfilerPass(PassRegistry&); void initializeAddressSanitizerPass(PassRegistry&); void initializeAddressSanitizerModulePass(PassRegistry&); void initializeMemorySanitizerPass(PassRegistry&); void initializeThreadSanitizerPass(PassRegistry&); +void initializeDataFlowSanitizerPass(PassRegistry&); void initializeEarlyCSEPass(PassRegistry&); void initializeExpandISelPseudosPass(PassRegistry&); void initializeFindUsedTypesPass(PassRegistry&); @@ -152,8 +153,6 @@ void initializeLiveRegMatrixPass(PassRegistry&); void initializeLiveStacksPass(PassRegistry&); void initializeLiveVariablesPass(PassRegistry&); void initializeLoaderPassPass(PassRegistry&); -void initializeProfileMetadataLoaderPassPass(PassRegistry&); -void initializePathProfileLoaderPassPass(PassRegistry&); void initializeLocalStackSlotPassPass(PassRegistry&); void initializeLoopDeletionPass(PassRegistry&); void initializeLoopExtractorPass(PassRegistry&); @@ -163,6 +162,7 @@ void initializeLoopRotatePass(PassRegistry&); void initializeLoopSimplifyPass(PassRegistry&); void initializeLoopStrengthReducePass(PassRegistry&); void initializeGlobalMergePass(PassRegistry&); +void initializeLoopRerollPass(PassRegistry&); void initializeLoopUnrollPass(PassRegistry&); void initializeLoopUnswitchPass(PassRegistry&); void initializeLoopIdiomRecognizePass(PassRegistry&); @@ -192,15 +192,13 @@ void initializeMetaRenamerPass(PassRegistry&); void initializeMergeFunctionsPass(PassRegistry&); void initializeModuleDebugInfoPrinterPass(PassRegistry&); void initializeNoAAPass(PassRegistry&); -void initializeNoProfileInfoPass(PassRegistry&); -void initializeNoPathProfileInfoPass(PassRegistry&); void initializeObjCARCAliasAnalysisPass(PassRegistry&); void initializeObjCARCAPElimPass(PassRegistry&); void initializeObjCARCExpandPass(PassRegistry&); void initializeObjCARCContractPass(PassRegistry&); void initializeObjCARCOptPass(PassRegistry&); -void initializeOptimalEdgeProfilerPass(PassRegistry&); void initializeOptimizePHIsPass(PassRegistry&); +void initializePartiallyInlineLibCallsPass(PassRegistry&); void initializePEIPass(PassRegistry&); void initializePHIEliminationPass(PassRegistry&); void initializePartialInlinerPass(PassRegistry&); @@ -216,11 +214,6 @@ void initializePrintFunctionPassPass(PassRegistry&); void initializePrintModulePassPass(PassRegistry&); void initializePrintBasicBlockPassPass(PassRegistry&); void initializeProcessImplicitDefsPass(PassRegistry&); -void initializeProfileEstimatorPassPass(PassRegistry&); -void initializeProfileInfoAnalysisGroup(PassRegistry&); -void initializePathProfileInfoAnalysisGroup(PassRegistry&); -void initializePathProfileVerifierPass(PassRegistry&); -void initializeProfileVerifierPassPass(PassRegistry&); void initializePromotePassPass(PassRegistry&); void initializePruneEHPass(PassRegistry&); void initializeReassociatePass(PassRegistry&); @@ -238,7 +231,6 @@ void initializeScalarEvolutionAliasAnalysisPass(PassRegistry&); void initializeScalarEvolutionPass(PassRegistry&); void initializeSimpleInlinerPass(PassRegistry&); void initializeRegisterCoalescerPass(PassRegistry&); -void initializeSimplifyLibCallsPass(PassRegistry&); void initializeSingleLoopExtractorPass(PassRegistry&); void initializeSinkingPass(PassRegistry&); void initializeSlotIndexesPass(PassRegistry&); @@ -251,7 +243,6 @@ void initializeStripDeadPrototypesPassPass(PassRegistry&); void initializeStripDebugDeclarePass(PassRegistry&); void initializeStripNonDebugSymbolsPass(PassRegistry&); void initializeStripSymbolsPass(PassRegistry&); -void initializeStrongPHIEliminationPass(PassRegistry&); void initializeTailCallElimPass(PassRegistry&); void initializeTailDuplicatePassPass(PassRegistry&); void initializeTargetPassConfigPass(PassRegistry&); diff --git a/contrib/llvm/include/llvm/InstVisitor.h b/contrib/llvm/include/llvm/InstVisitor.h index 291170334..de7206da6 100644 --- a/contrib/llvm/include/llvm/InstVisitor.h +++ b/contrib/llvm/include/llvm/InstVisitor.h @@ -191,6 +191,7 @@ public: RetTy visitPtrToIntInst(PtrToIntInst &I) { DELEGATE(CastInst);} RetTy visitIntToPtrInst(IntToPtrInst &I) { DELEGATE(CastInst);} RetTy visitBitCastInst(BitCastInst &I) { DELEGATE(CastInst);} + RetTy visitAddrSpaceCastInst(AddrSpaceCastInst &I) { DELEGATE(CastInst);} RetTy visitSelectInst(SelectInst &I) { DELEGATE(Instruction);} RetTy visitVAArgInst(VAArgInst &I) { DELEGATE(UnaryInstruction);} RetTy visitExtractElementInst(ExtractElementInst &I) { DELEGATE(Instruction);} diff --git a/contrib/llvm/include/llvm/LTO/LTOCodeGenerator.h b/contrib/llvm/include/llvm/LTO/LTOCodeGenerator.h new file mode 100644 index 000000000..c478bd980 --- /dev/null +++ b/contrib/llvm/include/llvm/LTO/LTOCodeGenerator.h @@ -0,0 +1,153 @@ +//===-LTOCodeGenerator.h - LLVM Link Time Optimizer -----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the LTOCodeGenerator class. +// +// LTO compilation consists of three phases: Pre-IPO, IPO and Post-IPO. +// +// The Pre-IPO phase compiles source code into bitcode file. The resulting +// bitcode files, along with object files and libraries, will be fed to the +// linker to through the IPO and Post-IPO phases. By using obj-file extension, +// the resulting bitcode file disguises itself as an object file, and therefore +// obviates the need of writing a special set of the make-rules only for LTO +// compilation. +// +// The IPO phase perform inter-procedural analyses and optimizations, and +// the Post-IPO consists two sub-phases: intra-procedural scalar optimizations +// (SOPT), and intra-procedural target-dependent code generator (CG). +// +// As of this writing, we don't separate IPO and the Post-IPO SOPT. They +// are intermingled together, and are driven by a single pass manager (see +// PassManagerBuilder::populateLTOPassManager()). +// +// The "LTOCodeGenerator" is the driver for the IPO and Post-IPO stages. +// The "CodeGenerator" here is bit confusing. Don't confuse the "CodeGenerator" +// with the machine specific code generator. +// +//===----------------------------------------------------------------------===// + +#ifndef LTO_CODE_GENERATOR_H +#define LTO_CODE_GENERATOR_H + +#include "llvm-c/lto.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/Linker.h" +#include "llvm/Target/TargetOptions.h" +#include +#include + +namespace llvm { + class LLVMContext; + class GlobalValue; + class Mangler; + class MemoryBuffer; + class TargetLibraryInfo; + class TargetMachine; + class raw_ostream; +} + +//===----------------------------------------------------------------------===// +/// LTOCodeGenerator - C++ class which implements the opaque lto_code_gen_t +/// type. +/// +struct LTOCodeGenerator { + static const char *getVersionString(); + + LTOCodeGenerator(); + ~LTOCodeGenerator(); + + // Merge given module, return true on success. + bool addModule(struct LTOModule*, std::string &errMsg); + + void setTargetOptions(llvm::TargetOptions options); + void setDebugInfo(lto_debug_model); + void setCodePICModel(lto_codegen_model); + + void setCpu(const char *mCpu) { MCpu = mCpu; } + + void addMustPreserveSymbol(const char *sym) { MustPreserveSymbols[sym] = 1; } + + // To pass options to the driver and optimization passes. These options are + // not necessarily for debugging purpose (The function name is misleading). + // This function should be called before LTOCodeGenerator::compilexxx(), + // and LTOCodeGenerator::writeMergedModules(). + // + void setCodeGenDebugOptions(const char *opts); + + // Parse the options set in setCodeGenDebugOptions. Like + // setCodeGenDebugOptions, this must be called before + // LTOCodeGenerator::compilexxx() and LTOCodeGenerator::writeMergedModules() + void parseCodeGenDebugOptions(); + + // Write the merged module to the file specified by the given path. + // Return true on success. + bool writeMergedModules(const char *path, std::string &errMsg); + + // Compile the merged module into a *single* object file; the path to object + // file is returned to the caller via argument "name". Return true on + // success. + // + // NOTE that it is up to the linker to remove the intermediate object file. + // Do not try to remove the object file in LTOCodeGenerator's destructor + // as we don't who (LTOCodeGenerator or the obj file) will last longer. + // + bool compile_to_file(const char **name, + bool disableOpt, + bool disableInline, + bool disableGVNLoadPRE, + std::string &errMsg); + + // As with compile_to_file(), this function compiles the merged module into + // single object file. Instead of returning the object-file-path to the caller + // (linker), it brings the object to a buffer, and return the buffer to the + // caller. This function should delete intermediate object file once its content + // is brought to memory. Return NULL if the compilation was not successful. + // + const void *compile(size_t *length, + bool disableOpt, + bool disableInline, + bool disableGVNLoadPRE, + std::string &errMsg); + +private: + void initializeLTOPasses(); + + bool generateObjectFile(llvm::raw_ostream &out, + bool disableOpt, + bool disableInline, + bool disableGVNLoadPRE, + std::string &errMsg); + void applyScopeRestrictions(); + void applyRestriction(llvm::GlobalValue &GV, + const llvm::ArrayRef &Libcalls, + std::vector &MustPreserveList, + llvm::SmallPtrSet &AsmUsed, + llvm::Mangler &Mangler); + bool determineTarget(std::string &errMsg); + + typedef llvm::StringMap StringSet; + + llvm::LLVMContext &Context; + llvm::Linker Linker; + llvm::TargetMachine *TargetMach; + bool EmitDwarfDebugInfo; + bool ScopeRestrictionsDone; + lto_codegen_model CodeModel; + StringSet MustPreserveSymbols; + StringSet AsmUndefinedRefs; + llvm::MemoryBuffer *NativeObjectFile; + std::vector CodegenOptions; + std::string MCpu; + std::string NativeObjectPath; + llvm::TargetOptions Options; +}; + +#endif // LTO_CODE_GENERATOR_H diff --git a/contrib/llvm/include/llvm/LTO/LTOModule.h b/contrib/llvm/include/llvm/LTO/LTOModule.h new file mode 100644 index 000000000..f4693c8d2 --- /dev/null +++ b/contrib/llvm/include/llvm/LTO/LTOModule.h @@ -0,0 +1,196 @@ +//===-LTOModule.h - LLVM Link Time Optimizer ------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the LTOModule class. +// +//===----------------------------------------------------------------------===// + +#ifndef LTO_MODULE_H +#define LTO_MODULE_H + +#include "llvm-c/lto.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/IR/Module.h" +#include "llvm/MC/MCContext.h" +#include "llvm/Target/Mangler.h" +#include "llvm/Target/TargetMachine.h" +#include +#include + +// Forward references to llvm classes. +namespace llvm { + class Function; + class GlobalValue; + class MemoryBuffer; + class TargetOptions; + class Value; +} + +//===----------------------------------------------------------------------===// +/// LTOModule - C++ class which implements the opaque lto_module_t type. +/// +struct LTOModule { +private: + typedef llvm::StringMap StringSet; + + struct NameAndAttributes { + const char *name; + uint32_t attributes; + bool isFunction; + const llvm::GlobalValue *symbol; + }; + + llvm::OwningPtr _module; + llvm::OwningPtr _target; + std::vector _symbols; + + // _defines and _undefines only needed to disambiguate tentative definitions + StringSet _defines; + llvm::StringMap _undefines; + std::vector _asm_undefines; + llvm::MCContext _context; + + // Use mangler to add GlobalPrefix to names to match linker names. + llvm::Mangler _mangler; + + LTOModule(llvm::Module *m, llvm::TargetMachine *t); +public: + /// isBitcodeFile - Returns 'true' if the file or memory contents is LLVM + /// bitcode. + static bool isBitcodeFile(const void *mem, size_t length); + static bool isBitcodeFile(const char *path); + + /// isBitcodeFileForTarget - Returns 'true' if the file or memory contents + /// is LLVM bitcode for the specified triple. + static bool isBitcodeFileForTarget(const void *mem, + size_t length, + const char *triplePrefix); + static bool isBitcodeFileForTarget(const char *path, + const char *triplePrefix); + + /// makeLTOModule - Create an LTOModule. N.B. These methods take ownership + /// of the buffer. The caller must have initialized the Targets, the + /// TargetMCs, the AsmPrinters, and the AsmParsers by calling: + /// + /// InitializeAllTargets(); + /// InitializeAllTargetMCs(); + /// InitializeAllAsmPrinters(); + /// InitializeAllAsmParsers(); + static LTOModule *makeLTOModule(const char* path, + llvm::TargetOptions options, + std::string &errMsg); + static LTOModule *makeLTOModule(int fd, const char *path, + size_t size, llvm::TargetOptions options, + std::string &errMsg); + static LTOModule *makeLTOModule(int fd, const char *path, + size_t map_size, + off_t offset, llvm::TargetOptions options, + std::string& errMsg); + static LTOModule *makeLTOModule(const void *mem, size_t length, + llvm::TargetOptions options, + std::string &errMsg); + + /// getTargetTriple - Return the Module's target triple. + const char *getTargetTriple() { + return _module->getTargetTriple().c_str(); + } + + /// setTargetTriple - Set the Module's target triple. + void setTargetTriple(const char *triple) { + _module->setTargetTriple(triple); + } + + /// getSymbolCount - Get the number of symbols + uint32_t getSymbolCount() { + return _symbols.size(); + } + + /// getSymbolAttributes - Get the attributes for a symbol at the specified + /// index. + lto_symbol_attributes getSymbolAttributes(uint32_t index) { + if (index < _symbols.size()) + return lto_symbol_attributes(_symbols[index].attributes); + return lto_symbol_attributes(0); + } + + /// getSymbolName - Get the name of the symbol at the specified index. + const char *getSymbolName(uint32_t index) { + if (index < _symbols.size()) + return _symbols[index].name; + return NULL; + } + + /// getLLVVMModule - Return the Module. + llvm::Module *getLLVVMModule() { return _module.get(); } + + /// getAsmUndefinedRefs - + const std::vector &getAsmUndefinedRefs() { + return _asm_undefines; + } + +private: + /// parseSymbols - Parse the symbols from the module and model-level ASM and + /// add them to either the defined or undefined lists. + bool parseSymbols(std::string &errMsg); + + /// addPotentialUndefinedSymbol - Add a symbol which isn't defined just yet + /// to a list to be resolved later. + void addPotentialUndefinedSymbol(const llvm::GlobalValue *dcl, bool isFunc); + + /// addDefinedSymbol - Add a defined symbol to the list. + void addDefinedSymbol(const llvm::GlobalValue *def, bool isFunction); + + /// addDefinedFunctionSymbol - Add a function symbol as defined to the list. + void addDefinedFunctionSymbol(const llvm::Function *f); + + /// addDefinedDataSymbol - Add a data symbol as defined to the list. + void addDefinedDataSymbol(const llvm::GlobalValue *v); + + /// addAsmGlobalSymbols - Add global symbols from module-level ASM to the + /// defined or undefined lists. + bool addAsmGlobalSymbols(std::string &errMsg); + + /// addAsmGlobalSymbol - Add a global symbol from module-level ASM to the + /// defined list. + void addAsmGlobalSymbol(const char *, lto_symbol_attributes scope); + + /// addAsmGlobalSymbolUndef - Add a global symbol from module-level ASM to + /// the undefined list. + void addAsmGlobalSymbolUndef(const char *); + + /// addObjCClass - Parse i386/ppc ObjC class data structure. + void addObjCClass(const llvm::GlobalVariable *clgv); + + /// addObjCCategory - Parse i386/ppc ObjC category data structure. + void addObjCCategory(const llvm::GlobalVariable *clgv); + + /// addObjCClassRef - Parse i386/ppc ObjC class list data structure. + void addObjCClassRef(const llvm::GlobalVariable *clgv); + + /// objcClassNameFromExpression - Get string that the data pointer points + /// to. + bool objcClassNameFromExpression(const llvm::Constant* c, std::string &name); + + /// isTargetMatch - Returns 'true' if the memory buffer is for the specified + /// target triple. + static bool isTargetMatch(llvm::MemoryBuffer *memBuffer, + const char *triplePrefix); + + /// makeLTOModule - Create an LTOModule (private version). N.B. This + /// method takes ownership of the buffer. + static LTOModule *makeLTOModule(llvm::MemoryBuffer *buffer, + llvm::TargetOptions options, + std::string &errMsg); + + /// makeBuffer - Create a MemoryBuffer from a memory range. + static llvm::MemoryBuffer *makeBuffer(const void *mem, size_t length); +}; + +#endif // LTO_MODULE_H diff --git a/contrib/llvm/include/llvm/LinkAllPasses.h b/contrib/llvm/include/llvm/LinkAllPasses.h index ca1c13924..8183fa299 100644 --- a/contrib/llvm/include/llvm/LinkAllPasses.h +++ b/contrib/llvm/include/llvm/LinkAllPasses.h @@ -56,12 +56,12 @@ namespace { (void) llvm::createLibCallAliasAnalysisPass(0); (void) llvm::createScalarEvolutionAliasAnalysisPass(); (void) llvm::createTypeBasedAliasAnalysisPass(); - (void) llvm::createBlockPlacementPass(); (void) llvm::createBoundsCheckingPass(); (void) llvm::createBreakCriticalEdgesPass(); (void) llvm::createCallGraphPrinterPass(); (void) llvm::createCallGraphViewerPass(); (void) llvm::createCFGSimplificationPass(); + (void) llvm::createStructurizeCFGPass(); (void) llvm::createConstantMergePass(); (void) llvm::createConstantPropagationPass(); (void) llvm::createCostModelAnalysisPass(); @@ -74,9 +74,6 @@ namespace { (void) llvm::createDomPrinterPass(); (void) llvm::createDomOnlyViewerPass(); (void) llvm::createDomViewerPass(); - (void) llvm::createEdgeProfilerPass(); - (void) llvm::createOptimalEdgeProfilerPass(); - (void) llvm::createPathProfilerPass(); (void) llvm::createGCOVProfilerPass(); (void) llvm::createFunctionInliningPass(); (void) llvm::createAlwaysInlinerPass(); @@ -94,6 +91,7 @@ namespace { (void) llvm::createLoopExtractorPass(); (void) llvm::createLoopSimplifyPass(); (void) llvm::createLoopStrengthReducePass(); + (void) llvm::createLoopRerollPass(); (void) llvm::createLoopUnrollPass(); (void) llvm::createLoopUnswitchPass(); (void) llvm::createLoopIdiomPass(); @@ -102,18 +100,11 @@ namespace { (void) llvm::createLowerInvokePass(); (void) llvm::createLowerSwitchPass(); (void) llvm::createNoAAPass(); - (void) llvm::createNoProfileInfoPass(); (void) llvm::createObjCARCAliasAnalysisPass(); (void) llvm::createObjCARCAPElimPass(); (void) llvm::createObjCARCExpandPass(); (void) llvm::createObjCARCContractPass(); (void) llvm::createObjCARCOptPass(); - (void) llvm::createProfileEstimatorPass(); - (void) llvm::createProfileVerifierPass(); - (void) llvm::createPathProfileVerifierPass(); - (void) llvm::createProfileLoaderPass(); - (void) llvm::createProfileMetadataLoaderPass(); - (void) llvm::createPathProfileLoaderPass(); (void) llvm::createPromoteMemoryToRegisterPass(); (void) llvm::createDemoteRegisterToMemoryPass(); (void) llvm::createPruneEHPass(); @@ -129,7 +120,6 @@ namespace { (void) llvm::createRegionViewerPass(); (void) llvm::createSCCPPass(); (void) llvm::createScalarReplAggregatesPass(); - (void) llvm::createSimplifyLibCallsPass(); (void) llvm::createSingleLoopExtractorPass(); (void) llvm::createStripSymbolsPass(); (void) llvm::createStripNonDebugSymbolsPass(); @@ -163,6 +153,7 @@ namespace { (void) llvm::createLoopVectorizePass(); (void) llvm::createSLPVectorizerPass(); (void) llvm::createBBVectorizePass(); + (void) llvm::createPartiallyInlineLibCallsPass(); (void)new llvm::IntervalPartition(); (void)new llvm::FindUsedTypes(); diff --git a/contrib/llvm/include/llvm/Linker.h b/contrib/llvm/include/llvm/Linker.h index 3667b8521..4f37459eb 100644 --- a/contrib/llvm/include/llvm/Linker.h +++ b/contrib/llvm/include/llvm/Linker.h @@ -32,7 +32,9 @@ class Linker { Linker(Module *M); ~Linker(); + Module *getModule() const { return Composite; } + void deleteModule(); /// \brief Link \p Src into the composite. The source is destroyed if /// \p Mode is DestroySource and preserved if it is PreserveSource. diff --git a/contrib/llvm/include/llvm/MC/MCAsmBackend.h b/contrib/llvm/include/llvm/MC/MCAsmBackend.h index 9a6b70340..f946f4198 100644 --- a/contrib/llvm/include/llvm/MC/MCAsmBackend.h +++ b/contrib/llvm/include/llvm/MC/MCAsmBackend.h @@ -10,7 +10,9 @@ #ifndef LLVM_MC_MCASMBACKEND_H #define LLVM_MC_MCASMBACKEND_H +#include "llvm/ADT/ArrayRef.h" #include "llvm/MC/MCDirectives.h" +#include "llvm/MC/MCDwarf.h" #include "llvm/MC/MCFixup.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/ErrorHandling.h" @@ -32,6 +34,7 @@ class raw_ostream; class MCAsmBackend { MCAsmBackend(const MCAsmBackend &) LLVM_DELETED_FUNCTION; void operator=(const MCAsmBackend &) LLVM_DELETED_FUNCTION; + protected: // Can only create subclasses. MCAsmBackend(); @@ -42,7 +45,7 @@ public: virtual ~MCAsmBackend(); /// lifetime management - virtual void reset() { } + virtual void reset() {} /// createObjectWriter - Create a new MCObjectWriter instance for use by the /// assembler backend to emit the final object file. @@ -50,7 +53,7 @@ public: /// createELFObjectTargetWriter - Create a new ELFObjectTargetWriter to enable /// non-standard ELFObjectWriters. - virtual MCELFObjectTargetWriter *createELFObjectTargetWriter() const { + virtual MCELFObjectTargetWriter *createELFObjectTargetWriter() const { llvm_unreachable("createELFObjectTargetWriter is not supported by asm " "backend"); } @@ -71,9 +74,7 @@ public: /// hasDataInCodeSupport - Check whether this target implements data-in-code /// markers. If not, data region directives will be ignored. - bool hasDataInCodeSupport() const { - return HasDataInCodeSupport; - } + bool hasDataInCodeSupport() const { return HasDataInCodeSupport; } /// doesSectionRequireSymbols - Check whether the given section requires that /// all symbols (even temporaries) have symbol table entries. @@ -128,8 +129,7 @@ public: /// fixupNeedsRelaxation - Target specific predicate for whether a given /// fixup requires the associated instruction to be relaxed. - virtual bool fixupNeedsRelaxation(const MCFixup &Fixup, - uint64_t Value, + virtual bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value, const MCRelaxableFragment *DF, const MCAsmLayout &Layout) const = 0; @@ -160,6 +160,12 @@ public: /// handleAssemblerFlag - Handle any target-specific assembler flags. /// By default, do nothing. virtual void handleAssemblerFlag(MCAssemblerFlag Flag) {} + + /// \brief Generate the compact unwind encoding for the CFI instructions. + virtual uint32_t + generateCompactUnwindEncoding(ArrayRef) const { + return 0; + } }; } // End llvm namespace diff --git a/contrib/llvm/include/llvm/MC/MCAsmInfo.h b/contrib/llvm/include/llvm/MC/MCAsmInfo.h index d020de300..7a9939462 100644 --- a/contrib/llvm/include/llvm/MC/MCAsmInfo.h +++ b/contrib/llvm/include/llvm/MC/MCAsmInfo.h @@ -17,6 +17,7 @@ #define LLVM_MC_MCASMINFO_H #include "llvm/MC/MCDirectives.h" +#include "llvm/MC/MCDwarf.h" #include "llvm/MC/MachineLocation.h" #include #include @@ -88,9 +89,13 @@ namespace llvm { /// which is needed to compute the size of an inline asm. unsigned MaxInstLength; // Defaults to 4. - /// PCSymbol - The symbol used to represent the current PC. Used in PC - /// relative expressions. - const char *PCSymbol; // Defaults to "$". + /// MinInstAlignment - Every possible instruction length is a multiple of + /// this value. Factored out in .debug_frame and .debug_line. + unsigned MinInstAlignment; // Defaults to 1. + + /// DollarIsPC - The '$' token, when not referencing an identifier or + /// constant, refers to the current PC. + bool DollarIsPC; // Defaults to false. /// SeparatorString - This string, if specified, is used to separate /// instructions from each other when on the same line. @@ -139,21 +144,9 @@ namespace llvm { /// AssemblerDialect - Which dialect of an assembler variant to use. unsigned AssemblerDialect; // Defaults to 0 - /// AllowQuotesInName - This is true if the assembler allows for complex - /// symbol names to be surrounded in quotes. This defaults to false. - bool AllowQuotesInName; - - /// AllowNameToStartWithDigit - This is true if the assembler allows symbol - /// names to start with a digit (e.g., "0x0021"). This defaults to false. - bool AllowNameToStartWithDigit; - - /// AllowPeriodsInName - This is true if the assembler allows periods in - /// symbol names. This defaults to true. - bool AllowPeriodsInName; - - /// AllowUTF8 - This is true if the assembler accepts UTF-8 input. - // FIXME: Make this a more general encoding setting? - bool AllowUTF8; + /// \brief This is true if the assembler allows @ characters in symbol + /// names. Defaults to false. + bool AllowAtInName; /// UseDataRegionDirectives - This is true if data region markers should /// be printed as ".data_region/.end_data_region" directives. If false, @@ -195,13 +188,6 @@ namespace llvm { /// on Mips or .gprel32 on Alpha. const char *GPRel32Directive; // Defaults to NULL. - /// getDataASDirective - Return the directive that should be used to emit - /// data of the specified size to the specified numeric address space. - virtual const char *getDataASDirective(unsigned Size, unsigned AS) const { - assert(AS != 0 && "Don't know the directives for default addr space"); - return 0; - } - /// SunStyleELFSectionSwitchSyntax - This is true if this target uses "Sun /// Style" syntax for section switching ("#alloc,#write" etc) instead of the /// normal ELF syntax (,"a,w") in .section directives. @@ -242,11 +228,6 @@ namespace llvm { /// const char *GlobalDirective; // Defaults to NULL. - /// ExternDirective - This is the directive used to declare external - /// globals. - /// - const char *ExternDirective; // Defaults to NULL. - /// HasSetDirective - True if the assembler supports the .set directive. bool HasSetDirective; // Defaults to true. @@ -273,14 +254,14 @@ namespace llvm { /// .file directive, this is true for ELF targets. bool HasSingleParameterDotFile; // Defaults to true. + /// hasIdentDirective - True if the target has a .ident directive, this is + /// true for ELF targets. + bool HasIdentDirective; // Defaults to false. + /// HasNoDeadStrip - True if this target supports the MachO .no_dead_strip /// directive. bool HasNoDeadStrip; // Defaults to false. - /// HasSymbolResolver - True if this target supports the MachO - /// .symbol_resolver directive. - bool HasSymbolResolver; // Defaults to false. - /// WeakRefDirective - This directive, if non-null, is used to declare a /// global as being a weak undefined symbol. const char *WeakRefDirective; // Defaults to NULL. @@ -318,10 +299,6 @@ namespace llvm { /// SupportsExceptionHandling - True if target supports exception handling. ExceptionHandling::ExceptionsType ExceptionsType; // Defaults to None - /// DwarfUsesInlineInfoSection - True if DwarfDebugInlineSection is used to - /// encode inline subroutine information. - bool DwarfUsesInlineInfoSection; // Defaults to false. - /// DwarfUsesRelocationsAcrossSections - True if Dwarf2 output generally /// uses relocations for references to other .debug_* sections. bool DwarfUsesRelocationsAcrossSections; @@ -332,15 +309,15 @@ namespace llvm { //===--- Prologue State ----------------------------------------------===// - std::vector InitialFrameState; + std::vector InitialFrameState; public: explicit MCAsmInfo(); virtual ~MCAsmInfo(); // FIXME: move these methods to DwarfPrinter when the JIT stops using them. - static unsigned getSLEB128Size(int Value); - static unsigned getULEB128Size(unsigned Value); + static unsigned getSLEB128Size(int64_t Value); + static unsigned getULEB128Size(uint64_t Value); /// getPointerSize - Get the pointer size in bytes. unsigned getPointerSize() const { @@ -367,17 +344,17 @@ namespace llvm { // Data directive accessors. // - const char *getData8bitsDirective(unsigned AS = 0) const { - return AS == 0 ? Data8bitsDirective : getDataASDirective(8, AS); + const char *getData8bitsDirective() const { + return Data8bitsDirective; } - const char *getData16bitsDirective(unsigned AS = 0) const { - return AS == 0 ? Data16bitsDirective : getDataASDirective(16, AS); + const char *getData16bitsDirective() const { + return Data16bitsDirective; } - const char *getData32bitsDirective(unsigned AS = 0) const { - return AS == 0 ? Data32bitsDirective : getDataASDirective(32, AS); + const char *getData32bitsDirective() const { + return Data32bitsDirective; } - const char *getData64bitsDirective(unsigned AS = 0) const { - return AS == 0 ? Data64bitsDirective : getDataASDirective(64, AS); + const char *getData64bitsDirective() const { + return Data64bitsDirective; } const char *getGPRel64Directive() const { return GPRel64Directive; } const char *getGPRel32Directive() const { return GPRel32Directive; } @@ -428,8 +405,11 @@ namespace llvm { unsigned getMaxInstLength() const { return MaxInstLength; } - const char *getPCSymbol() const { - return PCSymbol; + unsigned getMinInstAlignment() const { + return MinInstAlignment; + } + bool getDollarIsPC() const { + return DollarIsPC; } const char *getSeparatorString() const { return SeparatorString; @@ -475,17 +455,8 @@ namespace llvm { unsigned getAssemblerDialect() const { return AssemblerDialect; } - bool doesAllowQuotesInName() const { - return AllowQuotesInName; - } - bool doesAllowNameToStartWithDigit() const { - return AllowNameToStartWithDigit; - } - bool doesAllowPeriodsInName() const { - return AllowPeriodsInName; - } - bool doesAllowUTF8() const { - return AllowUTF8; + bool doesAllowAtInName() const { + return AllowAtInName; } bool doesSupportDataRegionDirectives() const { return UseDataRegionDirectives; @@ -511,9 +482,6 @@ namespace llvm { const char *getGlobalDirective() const { return GlobalDirective; } - const char *getExternDirective() const { - return ExternDirective; - } bool hasSetDirective() const { return HasSetDirective; } bool hasAggressiveSymbolFolding() const { return HasAggressiveSymbolFolding; @@ -526,8 +494,8 @@ namespace llvm { } bool hasDotTypeDotSizeDirective() const {return HasDotTypeDotSizeDirective;} bool hasSingleParameterDotFile() const { return HasSingleParameterDotFile; } + bool hasIdentDirective() const { return HasIdentDirective; } bool hasNoDeadStrip() const { return HasNoDeadStrip; } - bool hasSymbolResolver() const { return HasSymbolResolver; } const char *getWeakRefDirective() const { return WeakRefDirective; } const char *getWeakDefDirective() const { return WeakDefDirective; } const char *getLinkOnceDirective() const { return LinkOnceDirective; } @@ -557,9 +525,6 @@ namespace llvm { ExceptionsType == ExceptionHandling::ARM || ExceptionsType == ExceptionHandling::Win64); } - bool doesDwarfUseInlineInfoSection() const { - return DwarfUsesInlineInfoSection; - } bool doesDwarfUseRelocationsAcrossSections() const { return DwarfUsesRelocationsAcrossSections; } @@ -567,11 +532,11 @@ namespace llvm { return DwarfRegNumForCFI; } - void addInitialFrameState(MCSymbol *label, const MachineLocation &D, - const MachineLocation &S) { - InitialFrameState.push_back(MachineMove(label, D, S)); + void addInitialFrameState(const MCCFIInstruction &Inst) { + InitialFrameState.push_back(Inst); } - const std::vector &getInitialFrameState() const { + + const std::vector &getInitialFrameState() const { return InitialFrameState; } }; diff --git a/contrib/llvm/include/llvm/MC/MCAsmInfoELF.h b/contrib/llvm/include/llvm/MC/MCAsmInfoELF.h new file mode 100644 index 000000000..27fea84e7 --- /dev/null +++ b/contrib/llvm/include/llvm/MC/MCAsmInfoELF.h @@ -0,0 +1,23 @@ +//===-- llvm/MC/MCAsmInfoELF.h - ELF Asm info -------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCASMINFOELF_H +#define LLVM_MC_MCASMINFOELF_H + +#include "llvm/MC/MCAsmInfo.h" + +namespace llvm { +class MCAsmInfoELF : public MCAsmInfo { + virtual void anchor(); +protected: + MCAsmInfoELF(); +}; +} + +#endif diff --git a/contrib/llvm/include/llvm/MC/MCAssembler.h b/contrib/llvm/include/llvm/MC/MCAssembler.h index 38a70f0ad..8735a55ce 100644 --- a/contrib/llvm/include/llvm/MC/MCAssembler.h +++ b/contrib/llvm/include/llvm/MC/MCAssembler.h @@ -19,6 +19,7 @@ #include "llvm/MC/MCInst.h" #include "llvm/Support/Casting.h" #include "llvm/Support/DataTypes.h" +#include #include // FIXME: Shouldn't be needed. namespace llvm { @@ -816,6 +817,9 @@ public: typedef SymbolDataListType::const_iterator const_symbol_iterator; typedef SymbolDataListType::iterator symbol_iterator; + typedef std::vector FileNameVectorType; + typedef FileNameVectorType::const_iterator const_file_name_iterator; + typedef std::vector::const_iterator const_indirect_symbol_iterator; typedef std::vector::iterator indirect_symbol_iterator; @@ -859,6 +863,9 @@ private: /// The list of linker options to propagate into the object file. std::vector > LinkerOptions; + /// List of declared file names + FileNameVectorType FileNames; + /// The set of function symbols for which a .thumb_func directive has /// been seen. // @@ -1152,6 +1159,20 @@ public: return *Entry; } + const_file_name_iterator file_names_begin() const { + return FileNames.begin(); + } + + const_file_name_iterator file_names_end() const { + return FileNames.end(); + } + + void addFileName(StringRef FileName) { + if (std::find(file_names_begin(), file_names_end(), FileName) == + file_names_end()) + FileNames.push_back(FileName); + } + /// @} void dump(); diff --git a/contrib/llvm/include/llvm/MC/MCAtom.h b/contrib/llvm/include/llvm/MC/MCAtom.h index ae5bf0bc2..eab32d691 100644 --- a/contrib/llvm/include/llvm/MC/MCAtom.h +++ b/contrib/llvm/include/llvm/MC/MCAtom.h @@ -1,4 +1,4 @@ -//===-- llvm/MC/MCAtom.h - MCAtom class ---------------------*- C++ -*-===// +//===-- llvm/MC/MCAtom.h ----------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -9,13 +9,14 @@ // // This file contains the declaration of the MCAtom class, which is used to // represent a contiguous region in a decoded object that is uniformly data or -// instructions; +// instructions. // //===----------------------------------------------------------------------===// #ifndef LLVM_MC_MCATOM_H #define LLVM_MC_MCATOM_H +#include "llvm/ADT/ArrayRef.h" #include "llvm/MC/MCInst.h" #include "llvm/Support/DataTypes.h" #include @@ -24,45 +25,175 @@ namespace llvm { class MCModule; -/// MCData - An entry in a data MCAtom. -// NOTE: This may change to a more complex type in the future. -typedef uint8_t MCData; +class MCAtom; +class MCTextAtom; +class MCDataAtom; -/// MCAtom - Represents a contiguous range of either instructions (a TextAtom) +/// \brief Represents a contiguous range of either instructions (a TextAtom) /// or data (a DataAtom). Address ranges are expressed as _closed_ intervals. class MCAtom { - friend class MCModule; - typedef enum { TextAtom, DataAtom } AtomType; - - AtomType Type; + virtual void anchor(); +public: + virtual ~MCAtom() {} + + enum AtomKind { TextAtom, DataAtom }; + AtomKind getKind() const { return Kind; } + + /// \brief Get the start address of the atom. + uint64_t getBeginAddr() const { return Begin; } + /// \brief Get the end address, i.e. the last one inside the atom. + uint64_t getEndAddr() const { return End; } + + /// \name Atom modification methods: + /// When modifying a TextAtom, keep instruction boundaries in mind. + /// For instance, split must me given the start address of an instruction. + /// @{ + + /// \brief Splits the atom in two at a given address. + /// \param SplitPt Address at which to start a new atom, splitting this one. + /// \returns The newly created atom starting at \p SplitPt. + virtual MCAtom *split(uint64_t SplitPt) = 0; + + /// \brief Truncates an atom, discarding everything after \p TruncPt. + /// \param TruncPt Last byte address to be contained in this atom. + virtual void truncate(uint64_t TruncPt) = 0; + /// @} + + /// \name Naming: + /// + /// This is mostly for display purposes, and may contain anything that hints + /// at what the atom contains: section or symbol name, BB start address, .. + /// @{ + StringRef getName() const { return Name; } + void setName(StringRef NewName) { Name = NewName.str(); } + /// @} + +protected: + const AtomKind Kind; + std::string Name; MCModule *Parent; uint64_t Begin, End; - std::vector > Text; - std::vector Data; + friend class MCModule; + MCAtom(AtomKind K, MCModule *P, uint64_t B, uint64_t E) + : Kind(K), Name("(unknown)"), Parent(P), Begin(B), End(E) { } + + /// \name Atom remapping helpers + /// @{ + + /// \brief Remap the atom, using the given range, updating Begin/End. + /// One or both of the bounds can remain the same, but overlapping with other + /// atoms in the module is still forbidden. + void remap(uint64_t NewBegin, uint64_t NewEnd); + + /// \brief Remap the atom to prepare for a truncation at TruncPt. + /// Equivalent to: + /// \code + /// // Bound checks + /// remap(Begin, TruncPt); + /// \endcode + void remapForTruncate(uint64_t TruncPt); + + /// \brief Remap the atom to prepare for a split at SplitPt. + /// The bounds for the resulting atoms are returned in {L,R}{Begin,End}. + /// The current atom is truncated to \p LEnd. + void remapForSplit(uint64_t SplitPt, + uint64_t &LBegin, uint64_t &LEnd, + uint64_t &RBegin, uint64_t &REnd); + /// @} +}; - // Private constructor - only callable by MCModule - MCAtom(AtomType T, MCModule *P, uint64_t B, uint64_t E) - : Type(T), Parent(P), Begin(B), End(E) { } +/// \name Text atom +/// @{ +/// \brief An entry in an MCTextAtom: a disassembled instruction. +/// NOTE: Both the Address and Size field are actually redundant when taken in +/// the context of the text atom, and may better be exposed in an iterator +/// instead of stored in the atom, which would replace this class. +class MCDecodedInst { public: - bool isTextAtom() const { return Type == TextAtom; } - bool isDataAtom() const { return Type == DataAtom; } + MCInst Inst; + uint64_t Address; + uint64_t Size; + MCDecodedInst(const MCInst &Inst, uint64_t Address, uint64_t Size) + : Inst(Inst), Address(Address), Size(Size) {} +}; + +/// \brief An atom consisting of disassembled instructions. +class MCTextAtom : public MCAtom { +private: + typedef std::vector InstListTy; + InstListTy Insts; - void addInst(const MCInst &I, uint64_t Address, unsigned Size); + /// \brief The address of the next appended instruction, i.e., the + /// address immediately after the last instruction in the atom. + uint64_t NextInstAddress; +public: + /// Append an instruction, expanding the atom if necessary. + void addInst(const MCInst &Inst, uint64_t Size); + + /// \name Instruction list access + /// @{ + typedef InstListTy::const_iterator const_iterator; + const_iterator begin() const { return Insts.begin(); } + const_iterator end() const { return Insts.end(); } + + const MCDecodedInst &back() const { return Insts.back(); } + const MCDecodedInst &at(size_t n) const { return Insts.at(n); } + size_t size() const { return Insts.size(); } + /// @} + + /// \name Atom type specific split/truncate logic. + /// @{ + MCTextAtom *split(uint64_t SplitPt) LLVM_OVERRIDE; + void truncate(uint64_t TruncPt) LLVM_OVERRIDE; + /// @} + + // Class hierarchy. + static bool classof(const MCAtom *A) { return A->getKind() == TextAtom; } +private: + friend class MCModule; + // Private constructor - only callable by MCModule + MCTextAtom(MCModule *P, uint64_t Begin, uint64_t End) + : MCAtom(TextAtom, P, Begin, End), NextInstAddress(Begin) {} +}; +/// @} + +/// \name Data atom +/// @{ + +/// \brief An entry in an MCDataAtom. +// NOTE: This may change to a more complex type in the future. +typedef uint8_t MCData; + +/// \brief An atom consising of a sequence of bytes. +class MCDataAtom : public MCAtom { + std::vector Data; + +public: + /// Append a data entry, expanding the atom if necessary. void addData(const MCData &D); - /// split - Splits the atom in two at a given address, which must align with - /// and instruction boundary if this is a TextAtom. Returns the newly created - /// atom representing the high part of the split. - MCAtom *split(uint64_t SplitPt); + /// Get a reference to the data in this atom. + ArrayRef getData() const { return Data; } + + /// \name Atom type specific split/truncate logic. + /// @{ + MCDataAtom *split(uint64_t SplitPt) LLVM_OVERRIDE; + void truncate(uint64_t TruncPt) LLVM_OVERRIDE; + /// @} - /// truncate - Truncates an atom so that TruncPt is the last byte address - /// contained in the atom. - void truncate(uint64_t TruncPt); + // Class hierarchy. + static bool classof(const MCAtom *A) { return A->getKind() == DataAtom; } +private: + friend class MCModule; + // Private constructor - only callable by MCModule + MCDataAtom(MCModule *P, uint64_t Begin, uint64_t End) + : MCAtom(DataAtom, P, Begin, End) { + Data.reserve(End + 1 - Begin); + } }; } #endif - diff --git a/contrib/llvm/include/llvm/MC/MCCodeGenInfo.h b/contrib/llvm/include/llvm/MC/MCCodeGenInfo.h index d1765e124..84ce934d8 100644 --- a/contrib/llvm/include/llvm/MC/MCCodeGenInfo.h +++ b/contrib/llvm/include/llvm/MC/MCCodeGenInfo.h @@ -42,6 +42,9 @@ namespace llvm { CodeModel::Model getCodeModel() const { return CMModel; } CodeGenOpt::Level getOptLevel() const { return OptLevel; } + + // Allow overriding OptLevel on a per-function basis. + void setOptLevel(CodeGenOpt::Level Level) { OptLevel = Level; } }; } // namespace llvm diff --git a/contrib/llvm/include/llvm/MC/MCContext.h b/contrib/llvm/include/llvm/MC/MCContext.h index 0db3dee2f..17a37ed3b 100644 --- a/contrib/llvm/include/llvm/MC/MCContext.h +++ b/contrib/llvm/include/llvm/MC/MCContext.h @@ -11,6 +11,7 @@ #define LLVM_MC_MCCONTEXT_H #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/MC/MCDwarf.h" @@ -37,6 +38,7 @@ namespace llvm { class Twine; class MCSectionMachO; class MCSectionELF; + class MCSectionCOFF; /// MCContext - Context object for machine code objects. This class owns all /// of the sections that it creates. @@ -51,10 +53,10 @@ namespace llvm { const SourceMgr *SrcMgr; /// The MCAsmInfo for this target. - const MCAsmInfo &MAI; + const MCAsmInfo *MAI; /// The MCRegisterInfo for this target. - const MCRegisterInfo &MRI; + const MCRegisterInfo *MRI; /// The MCObjectFileInfo for this target. const MCObjectFileInfo *MOFI; @@ -97,7 +99,7 @@ namespace llvm { bool SecureLogUsed; /// The compilation directory to use for DW_AT_comp_dir. - std::string CompilationDir; + SmallString<128> CompilationDir; /// The main file name if passed in explicitly. std::string MainFileName; @@ -163,16 +165,16 @@ namespace llvm { MCSymbol *CreateSymbol(StringRef Name); public: - explicit MCContext(const MCAsmInfo &MAI, const MCRegisterInfo &MRI, + explicit MCContext(const MCAsmInfo *MAI, const MCRegisterInfo *MRI, const MCObjectFileInfo *MOFI, const SourceMgr *Mgr = 0, bool DoAutoReset = true); ~MCContext(); const SourceMgr *getSourceManager() const { return SrcMgr; } - const MCAsmInfo &getAsmInfo() const { return MAI; } + const MCAsmInfo *getAsmInfo() const { return MAI; } - const MCRegisterInfo &getRegisterInfo() const { return MRI; } + const MCRegisterInfo *getRegisterInfo() const { return MRI; } const MCObjectFileInfo *getObjectFileInfo() const { return MOFI; } @@ -254,14 +256,18 @@ namespace llvm { const MCSectionELF *CreateELFGroupSection(); - const MCSection *getCOFFSection(StringRef Section, unsigned Characteristics, - int Selection, SectionKind Kind); + const MCSectionCOFF *getCOFFSection(StringRef Section, + unsigned Characteristics, + SectionKind Kind, + StringRef COMDATSymName, + int Selection, + const MCSectionCOFF *Assoc = 0); - const MCSection *getCOFFSection(StringRef Section, unsigned Characteristics, - SectionKind Kind) { - return getCOFFSection (Section, Characteristics, 0, Kind); - } + const MCSectionCOFF *getCOFFSection(StringRef Section, + unsigned Characteristics, + SectionKind Kind); + const MCSectionCOFF *getCOFFSection(StringRef Section); /// @} @@ -272,7 +278,8 @@ namespace llvm { /// This can be overridden by clients which want to control the reported /// compilation directory and have it be something other than the current /// working directory. - const std::string &getCompilationDir() const { return CompilationDir; } + /// Returns an empty string if the current directory cannot be determined. + StringRef getCompilationDir() const { return CompilationDir; } /// \brief Set the compilation directory for DW_AT_comp_dir /// Override the default (CWD) compilation directory. @@ -406,7 +413,7 @@ namespace llvm { void Deallocate(void *Ptr) { } - // Unrecoverable error has occured. Display the best diagnostic we can + // Unrecoverable error has occurred. Display the best diagnostic we can // and bail via exit(1). For now, most MC backend errors are unrecoverable. // FIXME: We should really do something about that. LLVM_ATTRIBUTE_NORETURN void FatalError(SMLoc L, const Twine &Msg); diff --git a/contrib/llvm/include/llvm/MC/MCDisassembler.h b/contrib/llvm/include/llvm/MC/MCDisassembler.h index 36fbcb02d..83f26ef3e 100644 --- a/contrib/llvm/include/llvm/MC/MCDisassembler.h +++ b/contrib/llvm/include/llvm/MC/MCDisassembler.h @@ -10,6 +10,9 @@ #define LLVM_MC_MCDISASSEMBLER_H #include "llvm-c/Disassembler.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/MC/MCSymbolizer.h" +#include "llvm/MC/MCRelocationInfo.h" #include "llvm/Support/DataTypes.h" namespace llvm { @@ -55,7 +58,8 @@ public: /// Constructor - Performs initial setup for the disassembler. MCDisassembler(const MCSubtargetInfo &STI) : GetOpInfo(0), SymbolLookUp(0), DisInfo(0), Ctx(0), - STI(STI), CommentStream(0) {} + STI(STI), Symbolizer(0), + CommentStream(0) {} virtual ~MCDisassembler(); @@ -81,7 +85,6 @@ public: uint64_t address, raw_ostream &vStream, raw_ostream &cStream) const = 0; - private: // // Hooks for symbolic disassembly via the public 'C' interface. @@ -95,20 +98,32 @@ private: // The assembly context for creating symbols and MCExprs in place of // immediate operands when there is symbolic information. MCContext *Ctx; + protected: // Subtarget information, for instruction decoding predicates if required. const MCSubtargetInfo &STI; + OwningPtr Symbolizer; public: - void setupForSymbolicDisassembly(LLVMOpInfoCallback getOpInfo, - LLVMSymbolLookupCallback symbolLookUp, - void *disInfo, - MCContext *ctx) { - GetOpInfo = getOpInfo; - SymbolLookUp = symbolLookUp; - DisInfo = disInfo; - Ctx = ctx; - } + // Helpers around MCSymbolizer + bool tryAddingSymbolicOperand(MCInst &Inst, + int64_t Value, + uint64_t Address, bool IsBranch, + uint64_t Offset, uint64_t InstSize) const; + + void tryAddingPcLoadReferenceComment(int64_t Value, uint64_t Address) const; + + /// Set \p Symzer as the current symbolizer. + /// This takes ownership of \p Symzer, and deletes the previously set one. + void setSymbolizer(OwningPtr &Symzer); + + /// Sets up an external symbolizer that uses the C API callbacks. + void setupForSymbolicDisassembly(LLVMOpInfoCallback GetOpInfo, + LLVMSymbolLookupCallback SymbolLookUp, + void *DisInfo, + MCContext *Ctx, + OwningPtr &RelInfo); + LLVMOpInfoCallback getLLVMOpInfoCallback() const { return GetOpInfo; } LLVMSymbolLookupCallback getLLVMSymbolLookupCallback() const { return SymbolLookUp; @@ -116,6 +131,8 @@ public: void *getDisInfoBlock() const { return DisInfo; } MCContext *getMCContext() const { return Ctx; } + const MCSubtargetInfo& getSubtargetInfo() const { return STI; } + // Marked mutable because we cache it inside the disassembler, rather than // having to pass it around as an argument through all the autogenerated code. mutable raw_ostream *CommentStream; diff --git a/contrib/llvm/include/llvm/MC/MCDwarf.h b/contrib/llvm/include/llvm/MC/MCDwarf.h index 1a392e875..65b920bf2 100644 --- a/contrib/llvm/include/llvm/MC/MCDwarf.h +++ b/contrib/llvm/include/llvm/MC/MCDwarf.h @@ -23,403 +23,445 @@ #include namespace llvm { - class MCContext; - class MCObjectWriter; - class MCSection; - class MCStreamer; - class MCSymbol; - class SourceMgr; - class SMLoc; - - /// MCDwarfFile - Instances of this class represent the name of the dwarf - /// .file directive and its associated dwarf file number in the MC file, - /// and MCDwarfFile's are created and unique'd by the MCContext class where - /// the file number for each is its index into the vector of DwarfFiles (note - /// index 0 is not used and not a valid dwarf file number). - class MCDwarfFile { - // Name - the base name of the file without its directory path. - // The StringRef references memory allocated in the MCContext. - StringRef Name; - - // DirIndex - the index into the list of directory names for this file name. - unsigned DirIndex; - - private: // MCContext creates and uniques these. - friend class MCContext; - MCDwarfFile(StringRef name, unsigned dirIndex) +class MCAsmBackend; +class MCContext; +class MCSection; +class MCStreamer; +class MCSymbol; +class SourceMgr; +class SMLoc; + +/// MCDwarfFile - Instances of this class represent the name of the dwarf +/// .file directive and its associated dwarf file number in the MC file, +/// and MCDwarfFile's are created and unique'd by the MCContext class where +/// the file number for each is its index into the vector of DwarfFiles (note +/// index 0 is not used and not a valid dwarf file number). +class MCDwarfFile { + // Name - the base name of the file without its directory path. + // The StringRef references memory allocated in the MCContext. + StringRef Name; + + // DirIndex - the index into the list of directory names for this file name. + unsigned DirIndex; + +private: // MCContext creates and uniques these. + friend class MCContext; + MCDwarfFile(StringRef name, unsigned dirIndex) : Name(name), DirIndex(dirIndex) {} - MCDwarfFile(const MCDwarfFile&) LLVM_DELETED_FUNCTION; - void operator=(const MCDwarfFile&) LLVM_DELETED_FUNCTION; - public: - /// getName - Get the base name of this MCDwarfFile. - StringRef getName() const { return Name; } - - /// getDirIndex - Get the dirIndex of this MCDwarfFile. - unsigned getDirIndex() const { return DirIndex; } - - - /// print - Print the value to the stream \p OS. - void print(raw_ostream &OS) const; - - /// dump - Print the value to stderr. - void dump() const; - }; - - inline raw_ostream &operator<<(raw_ostream &OS, const MCDwarfFile &DwarfFile){ - DwarfFile.print(OS); - return OS; - } - - /// MCDwarfLoc - Instances of this class represent the information from a - /// dwarf .loc directive. - class MCDwarfLoc { - // FileNum - the file number. - unsigned FileNum; - // Line - the line number. - unsigned Line; - // Column - the column position. - unsigned Column; - // Flags (see #define's below) - unsigned Flags; - // Isa - unsigned Isa; - // Discriminator - unsigned Discriminator; + MCDwarfFile(const MCDwarfFile &) LLVM_DELETED_FUNCTION; + void operator=(const MCDwarfFile &) LLVM_DELETED_FUNCTION; + +public: + /// getName - Get the base name of this MCDwarfFile. + StringRef getName() const { return Name; } + + /// getDirIndex - Get the dirIndex of this MCDwarfFile. + unsigned getDirIndex() const { return DirIndex; } + + /// print - Print the value to the stream \p OS. + void print(raw_ostream &OS) const; + + /// dump - Print the value to stderr. + void dump() const; +}; + +inline raw_ostream &operator<<(raw_ostream &OS, const MCDwarfFile &DwarfFile) { + DwarfFile.print(OS); + return OS; +} + +/// MCDwarfLoc - Instances of this class represent the information from a +/// dwarf .loc directive. +class MCDwarfLoc { + // FileNum - the file number. + unsigned FileNum; + // Line - the line number. + unsigned Line; + // Column - the column position. + unsigned Column; + // Flags (see #define's below) + unsigned Flags; + // Isa + unsigned Isa; + // Discriminator + unsigned Discriminator; // Flag that indicates the initial value of the is_stmt_start flag. -#define DWARF2_LINE_DEFAULT_IS_STMT 1 +#define DWARF2_LINE_DEFAULT_IS_STMT 1 -#define DWARF2_FLAG_IS_STMT (1 << 0) -#define DWARF2_FLAG_BASIC_BLOCK (1 << 1) -#define DWARF2_FLAG_PROLOGUE_END (1 << 2) +#define DWARF2_FLAG_IS_STMT (1 << 0) +#define DWARF2_FLAG_BASIC_BLOCK (1 << 1) +#define DWARF2_FLAG_PROLOGUE_END (1 << 2) #define DWARF2_FLAG_EPILOGUE_BEGIN (1 << 3) - private: // MCContext manages these - friend class MCContext; - friend class MCLineEntry; - MCDwarfLoc(unsigned fileNum, unsigned line, unsigned column, unsigned flags, - unsigned isa, unsigned discriminator) +private: // MCContext manages these + friend class MCContext; + friend class MCLineEntry; + MCDwarfLoc(unsigned fileNum, unsigned line, unsigned column, unsigned flags, + unsigned isa, unsigned discriminator) : FileNum(fileNum), Line(line), Column(column), Flags(flags), Isa(isa), Discriminator(discriminator) {} - // Allow the default copy constructor and assignment operator to be used - // for an MCDwarfLoc object. + // Allow the default copy constructor and assignment operator to be used + // for an MCDwarfLoc object. - public: - /// getFileNum - Get the FileNum of this MCDwarfLoc. - unsigned getFileNum() const { return FileNum; } +public: + /// getFileNum - Get the FileNum of this MCDwarfLoc. + unsigned getFileNum() const { return FileNum; } - /// getLine - Get the Line of this MCDwarfLoc. - unsigned getLine() const { return Line; } + /// getLine - Get the Line of this MCDwarfLoc. + unsigned getLine() const { return Line; } - /// getColumn - Get the Column of this MCDwarfLoc. - unsigned getColumn() const { return Column; } + /// getColumn - Get the Column of this MCDwarfLoc. + unsigned getColumn() const { return Column; } - /// getFlags - Get the Flags of this MCDwarfLoc. - unsigned getFlags() const { return Flags; } + /// getFlags - Get the Flags of this MCDwarfLoc. + unsigned getFlags() const { return Flags; } - /// getIsa - Get the Isa of this MCDwarfLoc. - unsigned getIsa() const { return Isa; } + /// getIsa - Get the Isa of this MCDwarfLoc. + unsigned getIsa() const { return Isa; } - /// getDiscriminator - Get the Discriminator of this MCDwarfLoc. - unsigned getDiscriminator() const { return Discriminator; } + /// getDiscriminator - Get the Discriminator of this MCDwarfLoc. + unsigned getDiscriminator() const { return Discriminator; } - /// setFileNum - Set the FileNum of this MCDwarfLoc. - void setFileNum(unsigned fileNum) { FileNum = fileNum; } + /// setFileNum - Set the FileNum of this MCDwarfLoc. + void setFileNum(unsigned fileNum) { FileNum = fileNum; } - /// setLine - Set the Line of this MCDwarfLoc. - void setLine(unsigned line) { Line = line; } + /// setLine - Set the Line of this MCDwarfLoc. + void setLine(unsigned line) { Line = line; } - /// setColumn - Set the Column of this MCDwarfLoc. - void setColumn(unsigned column) { Column = column; } + /// setColumn - Set the Column of this MCDwarfLoc. + void setColumn(unsigned column) { Column = column; } - /// setFlags - Set the Flags of this MCDwarfLoc. - void setFlags(unsigned flags) { Flags = flags; } + /// setFlags - Set the Flags of this MCDwarfLoc. + void setFlags(unsigned flags) { Flags = flags; } - /// setIsa - Set the Isa of this MCDwarfLoc. - void setIsa(unsigned isa) { Isa = isa; } + /// setIsa - Set the Isa of this MCDwarfLoc. + void setIsa(unsigned isa) { Isa = isa; } - /// setDiscriminator - Set the Discriminator of this MCDwarfLoc. - void setDiscriminator(unsigned discriminator) { - Discriminator = discriminator; - } - }; + /// setDiscriminator - Set the Discriminator of this MCDwarfLoc. + void setDiscriminator(unsigned discriminator) { + Discriminator = discriminator; + } +}; + +/// MCLineEntry - Instances of this class represent the line information for +/// the dwarf line table entries. Which is created after a machine +/// instruction is assembled and uses an address from a temporary label +/// created at the current address in the current section and the info from +/// the last .loc directive seen as stored in the context. +class MCLineEntry : public MCDwarfLoc { + MCSymbol *Label; + +private: + // Allow the default copy constructor and assignment operator to be used + // for an MCLineEntry object. + +public: + // Constructor to create an MCLineEntry given a symbol and the dwarf loc. + MCLineEntry(MCSymbol *label, const MCDwarfLoc loc) + : MCDwarfLoc(loc), Label(label) {} + + MCSymbol *getLabel() const { return Label; } + + // This is called when an instruction is assembled into the specified + // section and if there is information from the last .loc directive that + // has yet to have a line entry made for it is made. + static void Make(MCStreamer *MCOS, const MCSection *Section); +}; + +/// MCLineSection - Instances of this class represent the line information +/// for a section where machine instructions have been assembled after seeing +/// .loc directives. This is the information used to build the dwarf line +/// table for a section. +class MCLineSection { + +private: + MCLineSection(const MCLineSection &) LLVM_DELETED_FUNCTION; + void operator=(const MCLineSection &) LLVM_DELETED_FUNCTION; + +public: + // Constructor to create an MCLineSection with an empty MCLineEntries + // vector. + MCLineSection() {} + + // addLineEntry - adds an entry to this MCLineSection's line entries + void addLineEntry(const MCLineEntry &LineEntry, unsigned CUID) { + MCLineDivisions[CUID].push_back(LineEntry); + } - /// MCLineEntry - Instances of this class represent the line information for - /// the dwarf line table entries. Which is created after a machine - /// instruction is assembled and uses an address from a temporary label - /// created at the current address in the current section and the info from - /// the last .loc directive seen as stored in the context. - class MCLineEntry : public MCDwarfLoc { - MCSymbol *Label; - - private: - // Allow the default copy constructor and assignment operator to be used - // for an MCLineEntry object. - - public: - // Constructor to create an MCLineEntry given a symbol and the dwarf loc. - MCLineEntry(MCSymbol *label, const MCDwarfLoc loc) : MCDwarfLoc(loc), - Label(label) {} - - MCSymbol *getLabel() const { return Label; } - - // This is called when an instruction is assembled into the specified - // section and if there is information from the last .loc directive that - // has yet to have a line entry made for it is made. - static void Make(MCStreamer *MCOS, const MCSection *Section); - }; + typedef std::vector MCLineEntryCollection; + typedef MCLineEntryCollection::iterator iterator; + typedef MCLineEntryCollection::const_iterator const_iterator; + typedef std::map MCLineDivisionMap; + +private: + // A collection of MCLineEntry for each Compile Unit ID. + MCLineDivisionMap MCLineDivisions; - /// MCLineSection - Instances of this class represent the line information - /// for a section where machine instructions have been assembled after seeing - /// .loc directives. This is the information used to build the dwarf line - /// table for a section. - class MCLineSection { - - private: - MCLineSection(const MCLineSection&) LLVM_DELETED_FUNCTION; - void operator=(const MCLineSection&) LLVM_DELETED_FUNCTION; - - public: - // Constructor to create an MCLineSection with an empty MCLineEntries - // vector. - MCLineSection() {} - - // addLineEntry - adds an entry to this MCLineSection's line entries - void addLineEntry(const MCLineEntry &LineEntry, unsigned CUID) { - MCLineDivisions[CUID].push_back(LineEntry); - } - - typedef std::vector MCLineEntryCollection; - typedef MCLineEntryCollection::iterator iterator; - typedef MCLineEntryCollection::const_iterator const_iterator; - typedef std::map MCLineDivisionMap; - - private: - // A collection of MCLineEntry for each Compile Unit ID. - MCLineDivisionMap MCLineDivisions; - - public: - // Returns whether MCLineSection contains entries for a given Compile - // Unit ID. - bool containEntriesForID(unsigned CUID) const { - return MCLineDivisions.count(CUID); - } - // Returns the collection of MCLineEntry for a given Compile Unit ID. - const MCLineEntryCollection &getMCLineEntries(unsigned CUID) const { - MCLineDivisionMap::const_iterator CIter = MCLineDivisions.find(CUID); - assert(CIter != MCLineDivisions.end()); - return CIter->second; - } +public: + // Returns whether MCLineSection contains entries for a given Compile + // Unit ID. + bool containEntriesForID(unsigned CUID) const { + return MCLineDivisions.count(CUID); + } + // Returns the collection of MCLineEntry for a given Compile Unit ID. + const MCLineEntryCollection &getMCLineEntries(unsigned CUID) const { + MCLineDivisionMap::const_iterator CIter = MCLineDivisions.find(CUID); + assert(CIter != MCLineDivisions.end()); + return CIter->second; + } +}; + +class MCDwarfFileTable { +public: + // + // This emits the Dwarf file and the line tables for all Compile Units. + // + static const MCSymbol *Emit(MCStreamer *MCOS); + // + // This emits the Dwarf file and the line tables for a given Compile Unit. + // + static const MCSymbol *EmitCU(MCStreamer *MCOS, unsigned ID); +}; + +class MCDwarfLineAddr { +public: + /// Utility function to encode a Dwarf pair of LineDelta and AddrDeltas. + static void Encode(MCContext &Context, int64_t LineDelta, uint64_t AddrDelta, + raw_ostream &OS); + + /// Utility function to emit the encoding to a streamer. + static void Emit(MCStreamer *MCOS, int64_t LineDelta, uint64_t AddrDelta); +}; + +class MCGenDwarfInfo { +public: + // + // When generating dwarf for assembly source files this emits the Dwarf + // sections. + // + static void Emit(MCStreamer *MCOS, const MCSymbol *LineSectionSymbol); +}; + +// When generating dwarf for assembly source files this is the info that is +// needed to be gathered for each symbol that will have a dwarf label. +class MCGenDwarfLabelEntry { +private: + // Name of the symbol without a leading underbar, if any. + StringRef Name; + // The dwarf file number this symbol is in. + unsigned FileNumber; + // The line number this symbol is at. + unsigned LineNumber; + // The low_pc for the dwarf label is taken from this symbol. + MCSymbol *Label; + +public: + MCGenDwarfLabelEntry(StringRef name, unsigned fileNumber, unsigned lineNumber, + MCSymbol *label) + : Name(name), FileNumber(fileNumber), LineNumber(lineNumber), + Label(label) {} + + StringRef getName() const { return Name; } + unsigned getFileNumber() const { return FileNumber; } + unsigned getLineNumber() const { return LineNumber; } + MCSymbol *getLabel() const { return Label; } + + // This is called when label is created when we are generating dwarf for + // assembly source files. + static void Make(MCSymbol *Symbol, MCStreamer *MCOS, SourceMgr &SrcMgr, + SMLoc &Loc); +}; + +class MCCFIInstruction { +public: + enum OpType { + OpSameValue, + OpRememberState, + OpRestoreState, + OpOffset, + OpDefCfaRegister, + OpDefCfaOffset, + OpDefCfa, + OpRelOffset, + OpAdjustCfaOffset, + OpEscape, + OpRestore, + OpUndefined, + OpRegister, + OpWindowSave }; - class MCDwarfFileTable { - public: - // - // This emits the Dwarf file and the line tables for all Compile Units. - // - static const MCSymbol *Emit(MCStreamer *MCOS); - // - // This emits the Dwarf file and the line tables for a given Compile Unit. - // - static const MCSymbol *EmitCU(MCStreamer *MCOS, unsigned ID); +private: + OpType Operation; + MCSymbol *Label; + unsigned Register; + union { + int Offset; + unsigned Register2; }; + std::vector Values; - class MCDwarfLineAddr { - public: - /// Utility function to encode a Dwarf pair of LineDelta and AddrDeltas. - static void Encode(int64_t LineDelta, uint64_t AddrDelta, raw_ostream &OS); + MCCFIInstruction(OpType Op, MCSymbol *L, unsigned R, int O, StringRef V) + : Operation(Op), Label(L), Register(R), Offset(O), + Values(V.begin(), V.end()) { + assert(Op != OpRegister); + } - /// Utility function to emit the encoding to a streamer. - static void Emit(MCStreamer *MCOS, - int64_t LineDelta,uint64_t AddrDelta); + MCCFIInstruction(OpType Op, MCSymbol *L, unsigned R1, unsigned R2) + : Operation(Op), Label(L), Register(R1), Register2(R2) { + assert(Op == OpRegister); + } - /// Utility function to write the encoding to an object writer. - static void Write(MCObjectWriter *OW, - int64_t LineDelta, uint64_t AddrDelta); - }; +public: + /// \brief .cfi_def_cfa defines a rule for computing CFA as: take address from + /// Register and add Offset to it. + static MCCFIInstruction createDefCfa(MCSymbol *L, unsigned Register, + int Offset) { + return MCCFIInstruction(OpDefCfa, L, Register, -Offset, ""); + } - class MCGenDwarfInfo { - public: - // - // When generating dwarf for assembly source files this emits the Dwarf - // sections. - // - static void Emit(MCStreamer *MCOS, const MCSymbol *LineSectionSymbol); - }; + /// \brief .cfi_def_cfa_register modifies a rule for computing CFA. From now + /// on Register will be used instead of the old one. Offset remains the same. + static MCCFIInstruction createDefCfaRegister(MCSymbol *L, unsigned Register) { + return MCCFIInstruction(OpDefCfaRegister, L, Register, 0, ""); + } - // When generating dwarf for assembly source files this is the info that is - // needed to be gathered for each symbol that will have a dwarf label. - class MCGenDwarfLabelEntry { - private: - // Name of the symbol without a leading underbar, if any. - StringRef Name; - // The dwarf file number this symbol is in. - unsigned FileNumber; - // The line number this symbol is at. - unsigned LineNumber; - // The low_pc for the dwarf label is taken from this symbol. - MCSymbol *Label; - - public: - MCGenDwarfLabelEntry(StringRef name, unsigned fileNumber, - unsigned lineNumber, MCSymbol *label) : - Name(name), FileNumber(fileNumber), LineNumber(lineNumber), Label(label){} - - StringRef getName() const { return Name; } - unsigned getFileNumber() const { return FileNumber; } - unsigned getLineNumber() const { return LineNumber; } - MCSymbol *getLabel() const { return Label; } - - // This is called when label is created when we are generating dwarf for - // assembly source files. - static void Make(MCSymbol *Symbol, MCStreamer *MCOS, SourceMgr &SrcMgr, - SMLoc &Loc); - }; + /// \brief .cfi_def_cfa_offset modifies a rule for computing CFA. Register + /// remains the same, but offset is new. Note that it is the absolute offset + /// that will be added to a defined register to the compute CFA address. + static MCCFIInstruction createDefCfaOffset(MCSymbol *L, int Offset) { + return MCCFIInstruction(OpDefCfaOffset, L, 0, -Offset, ""); + } - class MCCFIInstruction { - public: - enum OpType { OpSameValue, OpRememberState, OpRestoreState, OpOffset, - OpDefCfaRegister, OpDefCfaOffset, OpDefCfa, OpRelOffset, - OpAdjustCfaOffset, OpEscape, OpRestore, OpUndefined, - OpRegister }; - private: - OpType Operation; - MCSymbol *Label; - unsigned Register; - union { - int Offset; - unsigned Register2; - }; - std::vector Values; - - MCCFIInstruction(OpType Op, MCSymbol *L, unsigned R, int O, StringRef V) : - Operation(Op), Label(L), Register(R), Offset(O), - Values(V.begin(), V.end()) { - assert(Op != OpRegister); - } - - MCCFIInstruction(OpType Op, MCSymbol *L, unsigned R1, unsigned R2) : - Operation(Op), Label(L), Register(R1), Register2(R2) { - assert(Op == OpRegister); - } - - public: - static MCCFIInstruction - createOffset(MCSymbol *L, unsigned Register, int Offset) { - return MCCFIInstruction(OpOffset, L, Register, Offset, ""); - } - - static MCCFIInstruction - createDefCfaRegister(MCSymbol *L, unsigned Register) { - return MCCFIInstruction(OpDefCfaRegister, L, Register, 0, ""); - } - - static MCCFIInstruction createDefCfaOffset(MCSymbol *L, int Offset) { - return MCCFIInstruction(OpDefCfaOffset, L, 0, -Offset, ""); - } - - static MCCFIInstruction - createDefCfa(MCSymbol *L, unsigned Register, int Offset) { - return MCCFIInstruction(OpDefCfa, L, Register, -Offset, ""); - } - - static MCCFIInstruction createUndefined(MCSymbol *L, unsigned Register) { - return MCCFIInstruction(OpUndefined, L, Register, 0, ""); - } - - static MCCFIInstruction createRestore(MCSymbol *L, unsigned Register) { - return MCCFIInstruction(OpRestore, L, Register, 0, ""); - } - - static MCCFIInstruction createSameValue(MCSymbol *L, unsigned Register) { - return MCCFIInstruction(OpSameValue, L, Register, 0, ""); - } - - static MCCFIInstruction createRestoreState(MCSymbol *L) { - return MCCFIInstruction(OpRestoreState, L, 0, 0, ""); - } - - static MCCFIInstruction createRememberState(MCSymbol *L) { - return MCCFIInstruction(OpRememberState, L, 0, 0, ""); - } - - static MCCFIInstruction - createRelOffset(MCSymbol *L, unsigned Register, int Offset) { - return MCCFIInstruction(OpRelOffset, L, Register, Offset, ""); - } - - static MCCFIInstruction - createAdjustCfaOffset(MCSymbol *L, int Adjustment) { - return MCCFIInstruction(OpAdjustCfaOffset, L, 0, Adjustment, ""); - } - - static MCCFIInstruction createEscape(MCSymbol *L, StringRef Vals) { - return MCCFIInstruction(OpEscape, L, 0, 0, Vals); - } - - static MCCFIInstruction - createRegister(MCSymbol *L, unsigned Register1, unsigned Register2) { - return MCCFIInstruction(OpRegister, L, Register1, Register2); - } - - OpType getOperation() const { return Operation; } - MCSymbol *getLabel() const { return Label; } - - unsigned getRegister() const { - assert(Operation == OpDefCfa || Operation == OpOffset || - Operation == OpRestore || Operation == OpUndefined || - Operation == OpSameValue || Operation == OpDefCfaRegister || - Operation == OpRelOffset || Operation == OpRegister); - return Register; - } - - unsigned getRegister2() const { - assert(Operation == OpRegister); - return Register2; - } - - int getOffset() const { - assert(Operation == OpDefCfa || Operation == OpOffset || - Operation == OpRelOffset || Operation == OpDefCfaOffset || - Operation == OpAdjustCfaOffset); - return Offset; - } - - const StringRef getValues() const { - assert(Operation == OpEscape); - return StringRef(&Values[0], Values.size()); - } - }; + /// \brief .cfi_adjust_cfa_offset Same as .cfi_def_cfa_offset, but + /// Offset is a relative value that is added/subtracted from the previous + /// offset. + static MCCFIInstruction createAdjustCfaOffset(MCSymbol *L, int Adjustment) { + return MCCFIInstruction(OpAdjustCfaOffset, L, 0, Adjustment, ""); + } - struct MCDwarfFrameInfo { - MCDwarfFrameInfo() : Begin(0), End(0), Personality(0), Lsda(0), - Function(0), Instructions(), PersonalityEncoding(), - LsdaEncoding(0), CompactUnwindEncoding(0), - IsSignalFrame(false) {} - MCSymbol *Begin; - MCSymbol *End; - const MCSymbol *Personality; - const MCSymbol *Lsda; - const MCSymbol *Function; - std::vector Instructions; - unsigned PersonalityEncoding; - unsigned LsdaEncoding; - uint32_t CompactUnwindEncoding; - bool IsSignalFrame; - }; + /// \brief .cfi_offset Previous value of Register is saved at offset Offset + /// from CFA. + static MCCFIInstruction createOffset(MCSymbol *L, unsigned Register, + int Offset) { + return MCCFIInstruction(OpOffset, L, Register, Offset, ""); + } - class MCDwarfFrameEmitter { - public: - // - // This emits the frame info section. - // - static void Emit(MCStreamer &streamer, bool usingCFI, - bool isEH); - static void EmitAdvanceLoc(MCStreamer &Streamer, uint64_t AddrDelta); - static void EncodeAdvanceLoc(uint64_t AddrDelta, raw_ostream &OS); - }; + /// \brief .cfi_rel_offset Previous value of Register is saved at offset + /// Offset from the current CFA register. This is transformed to .cfi_offset + /// using the known displacement of the CFA register from the CFA. + static MCCFIInstruction createRelOffset(MCSymbol *L, unsigned Register, + int Offset) { + return MCCFIInstruction(OpRelOffset, L, Register, Offset, ""); + } + + /// \brief .cfi_register Previous value of Register1 is saved in + /// register Register2. + static MCCFIInstruction createRegister(MCSymbol *L, unsigned Register1, + unsigned Register2) { + return MCCFIInstruction(OpRegister, L, Register1, Register2); + } + + /// \brief .cfi_window_save SPARC register window is saved. + static MCCFIInstruction createWindowSave(MCSymbol *L) { + return MCCFIInstruction(OpWindowSave, L, 0, 0, ""); + } + + /// \brief .cfi_restore says that the rule for Register is now the same as it + /// was at the beginning of the function, after all initial instructions added + /// by .cfi_startproc were executed. + static MCCFIInstruction createRestore(MCSymbol *L, unsigned Register) { + return MCCFIInstruction(OpRestore, L, Register, 0, ""); + } + + /// \brief .cfi_undefined From now on the previous value of Register can't be + /// restored anymore. + static MCCFIInstruction createUndefined(MCSymbol *L, unsigned Register) { + return MCCFIInstruction(OpUndefined, L, Register, 0, ""); + } + + /// \brief .cfi_same_value Current value of Register is the same as in the + /// previous frame. I.e., no restoration is needed. + static MCCFIInstruction createSameValue(MCSymbol *L, unsigned Register) { + return MCCFIInstruction(OpSameValue, L, Register, 0, ""); + } + + /// \brief .cfi_remember_state Save all current rules for all registers. + static MCCFIInstruction createRememberState(MCSymbol *L) { + return MCCFIInstruction(OpRememberState, L, 0, 0, ""); + } + + /// \brief .cfi_restore_state Restore the previously saved state. + static MCCFIInstruction createRestoreState(MCSymbol *L) { + return MCCFIInstruction(OpRestoreState, L, 0, 0, ""); + } + + /// \brief .cfi_escape Allows the user to add arbitrary bytes to the unwind + /// info. + static MCCFIInstruction createEscape(MCSymbol *L, StringRef Vals) { + return MCCFIInstruction(OpEscape, L, 0, 0, Vals); + } + + OpType getOperation() const { return Operation; } + MCSymbol *getLabel() const { return Label; } + + unsigned getRegister() const { + assert(Operation == OpDefCfa || Operation == OpOffset || + Operation == OpRestore || Operation == OpUndefined || + Operation == OpSameValue || Operation == OpDefCfaRegister || + Operation == OpRelOffset || Operation == OpRegister); + return Register; + } + + unsigned getRegister2() const { + assert(Operation == OpRegister); + return Register2; + } + + int getOffset() const { + assert(Operation == OpDefCfa || Operation == OpOffset || + Operation == OpRelOffset || Operation == OpDefCfaOffset || + Operation == OpAdjustCfaOffset); + return Offset; + } + + const StringRef getValues() const { + assert(Operation == OpEscape); + return StringRef(&Values[0], Values.size()); + } +}; + +struct MCDwarfFrameInfo { + MCDwarfFrameInfo() + : Begin(0), End(0), Personality(0), Lsda(0), Function(0), Instructions(), + PersonalityEncoding(), LsdaEncoding(0), CompactUnwindEncoding(0), + IsSignalFrame(false) {} + MCSymbol *Begin; + MCSymbol *End; + const MCSymbol *Personality; + const MCSymbol *Lsda; + const MCSymbol *Function; + std::vector Instructions; + unsigned PersonalityEncoding; + unsigned LsdaEncoding; + uint32_t CompactUnwindEncoding; + bool IsSignalFrame; +}; + +class MCDwarfFrameEmitter { +public: + // + // This emits the frame info section. + // + static void Emit(MCStreamer &streamer, MCAsmBackend *MAB, + bool usingCFI, bool isEH); + static void EmitAdvanceLoc(MCStreamer &Streamer, uint64_t AddrDelta); + static void EncodeAdvanceLoc(MCContext &Context, uint64_t AddrDelta, + raw_ostream &OS); +}; } // end namespace llvm #endif diff --git a/contrib/llvm/include/llvm/MC/MCELFObjectWriter.h b/contrib/llvm/include/llvm/MC/MCELFObjectWriter.h index 65dd1e899..92ad1b1a4 100644 --- a/contrib/llvm/include/llvm/MC/MCELFObjectWriter.h +++ b/contrib/llvm/include/llvm/MC/MCELFObjectWriter.h @@ -42,18 +42,6 @@ struct ELFRelocationEntry { const MCSymbol *Sym, uint64_t Addend, const MCFixup &Fixup) : r_offset(RelocOffset), Index(Idx), Type(RelType), Symbol(Sym), r_addend(Addend), Fixup(&Fixup) {} - - // Support lexicographic sorting. - bool operator<(const ELFRelocationEntry &RE) const { - if (RE.r_offset != r_offset) - return RE.r_offset < r_offset; - if (Type != RE.Type) - return Type < RE.Type; - if (Index != RE.Index) - return Index < RE.Index; - llvm_unreachable("ELFRelocs might be unstable!"); - return 0; - } }; class MCELFObjectTargetWriter { @@ -94,8 +82,6 @@ public: virtual const MCSymbol *undefinedExplicitRelSym(const MCValue &Target, const MCFixup &Fixup, bool IsPCRel) const; - virtual void adjustFixupOffset(const MCFixup &Fixup, - uint64_t &RelocOffset); virtual void sortRelocs(const MCAssembler &Asm, std::vector &Relocs); diff --git a/contrib/llvm/include/llvm/MC/MCELFStreamer.h b/contrib/llvm/include/llvm/MC/MCELFStreamer.h index 55c05b036..4e24dcfac 100644 --- a/contrib/llvm/include/llvm/MC/MCELFStreamer.h +++ b/contrib/llvm/include/llvm/MC/MCELFStreamer.h @@ -28,20 +28,17 @@ class MCSymbolData; class raw_ostream; class MCELFStreamer : public MCObjectStreamer { -protected: - MCELFStreamer(StreamerKind Kind, MCContext &Context, MCAsmBackend &TAB, - raw_ostream &OS, MCCodeEmitter *Emitter) - : MCObjectStreamer(Kind, Context, TAB, OS, Emitter) {} - public: - MCELFStreamer(MCContext &Context, MCAsmBackend &TAB, raw_ostream &OS, - MCCodeEmitter *Emitter) - : MCObjectStreamer(SK_ELFStreamer, Context, TAB, OS, Emitter) {} + MCELFStreamer(MCContext &Context, MCTargetStreamer *TargetStreamer, + MCAsmBackend &TAB, raw_ostream &OS, MCCodeEmitter *Emitter) + : MCObjectStreamer(Context, TargetStreamer, TAB, OS, Emitter), + SeenIdent(false) {} - MCELFStreamer(MCContext &Context, MCAsmBackend &TAB, raw_ostream &OS, - MCCodeEmitter *Emitter, MCAssembler *Assembler) - : MCObjectStreamer(SK_ELFStreamer, Context, TAB, OS, Emitter, - Assembler) {} + MCELFStreamer(MCContext &Context, MCTargetStreamer *TargetStreamer, + MCAsmBackend &TAB, raw_ostream &OS, MCCodeEmitter *Emitter, + MCAssembler *Assembler) + : MCObjectStreamer(Context, TargetStreamer, TAB, OS, Emitter, Assembler), + SeenIdent(false) {} virtual ~MCELFStreamer(); @@ -57,7 +54,7 @@ public: virtual void EmitAssemblerFlag(MCAssemblerFlag Flag); virtual void EmitThumbFunc(MCSymbol *Func); virtual void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol); - virtual void EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute); + virtual bool EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute); virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue); virtual void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment); @@ -77,21 +74,17 @@ public: uint64_t Size = 0, unsigned ByteAlignment = 0); virtual void EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment = 0); - virtual void EmitValueImpl(const MCExpr *Value, unsigned Size, - unsigned AddrSpace); + virtual void EmitValueImpl(const MCExpr *Value, unsigned Size); virtual void EmitFileDirective(StringRef Filename); - virtual void EmitTCEntry(const MCSymbol &S); + virtual void EmitIdent(StringRef IdentString); virtual void EmitValueToAlignment(unsigned, int64_t, unsigned, unsigned); - virtual void FinishImpl(); - /// @} + virtual void Flush(); - static bool classof(const MCStreamer *S) { - return S->getKind() == SK_ELFStreamer || S->getKind() == SK_ARMELFStreamer; - } + virtual void FinishImpl(); private: virtual void EmitInstToFragment(const MCInst &Inst); @@ -103,6 +96,8 @@ private: void fixSymbolsInTLSFixups(const MCExpr *expr); + bool SeenIdent; + struct LocalCommon { MCSymbolData *SD; uint64_t Size; @@ -121,6 +116,11 @@ private: void SetSectionBss(); }; +MCELFStreamer *createARMELFStreamer(MCContext &Context, MCAsmBackend &TAB, + raw_ostream &OS, MCCodeEmitter *Emitter, + bool RelaxAll, bool NoExecStack, + bool IsThumb); + } // end namespace llvm #endif diff --git a/contrib/llvm/include/llvm/MC/MCELFSymbolFlags.h b/contrib/llvm/include/llvm/MC/MCELFSymbolFlags.h index 2225ea078..d0e1dace9 100644 --- a/contrib/llvm/include/llvm/MC/MCELFSymbolFlags.h +++ b/contrib/llvm/include/llvm/MC/MCELFSymbolFlags.h @@ -27,7 +27,7 @@ namespace llvm { ELF_Other_Shift = 10 // Shift value for other flags. }; - enum SymbolFlags { + enum ELFSymbolFlags { ELF_STB_Local = (ELF::STB_LOCAL << ELF_STB_Shift), ELF_STB_Global = (ELF::STB_GLOBAL << ELF_STB_Shift), ELF_STB_Weak = (ELF::STB_WEAK << ELF_STB_Shift), diff --git a/contrib/llvm/include/llvm/MC/MCExpr.h b/contrib/llvm/include/llvm/MC/MCExpr.h index a2c5bd3f7..5d559744d 100644 --- a/contrib/llvm/include/llvm/MC/MCExpr.h +++ b/contrib/llvm/include/llvm/MC/MCExpr.h @@ -171,26 +171,56 @@ public: VK_ARM_TARGET2, VK_ARM_PREL31, - VK_PPC_TOC, // TOC base - VK_PPC_TOC_ENTRY, // TOC entry - VK_PPC_DARWIN_HA16, // ha16(symbol) - VK_PPC_DARWIN_LO16, // lo16(symbol) - VK_PPC_GAS_HA16, // symbol@ha - VK_PPC_GAS_LO16, // symbol@l - VK_PPC_TPREL16_HA, // symbol@tprel@ha - VK_PPC_TPREL16_LO, // symbol@tprel@l - VK_PPC_DTPREL16_HA, // symbol@dtprel@ha - VK_PPC_DTPREL16_LO, // symbol@dtprel@l - VK_PPC_TOC16_HA, // symbol@toc@ha - VK_PPC_TOC16_LO, // symbol@toc@l - VK_PPC_GOT_TPREL16_HA, // symbol@got@tprel@ha - VK_PPC_GOT_TPREL16_LO, // symbol@got@tprel@l + VK_PPC_LO, // symbol@l + VK_PPC_HI, // symbol@h + VK_PPC_HA, // symbol@ha + VK_PPC_HIGHER, // symbol@higher + VK_PPC_HIGHERA, // symbol@highera + VK_PPC_HIGHEST, // symbol@highest + VK_PPC_HIGHESTA, // symbol@highesta + VK_PPC_GOT_LO, // symbol@got@l + VK_PPC_GOT_HI, // symbol@got@h + VK_PPC_GOT_HA, // symbol@got@ha + VK_PPC_TOCBASE, // symbol@tocbase + VK_PPC_TOC, // symbol@toc + VK_PPC_TOC_LO, // symbol@toc@l + VK_PPC_TOC_HI, // symbol@toc@h + VK_PPC_TOC_HA, // symbol@toc@ha + VK_PPC_DTPMOD, // symbol@dtpmod + VK_PPC_TPREL, // symbol@tprel + VK_PPC_TPREL_LO, // symbol@tprel@l + VK_PPC_TPREL_HI, // symbol@tprel@h + VK_PPC_TPREL_HA, // symbol@tprel@ha + VK_PPC_TPREL_HIGHER, // symbol@tprel@higher + VK_PPC_TPREL_HIGHERA, // symbol@tprel@highera + VK_PPC_TPREL_HIGHEST, // symbol@tprel@highest + VK_PPC_TPREL_HIGHESTA, // symbol@tprel@highesta + VK_PPC_DTPREL, // symbol@dtprel + VK_PPC_DTPREL_LO, // symbol@dtprel@l + VK_PPC_DTPREL_HI, // symbol@dtprel@h + VK_PPC_DTPREL_HA, // symbol@dtprel@ha + VK_PPC_DTPREL_HIGHER, // symbol@dtprel@higher + VK_PPC_DTPREL_HIGHERA, // symbol@dtprel@highera + VK_PPC_DTPREL_HIGHEST, // symbol@dtprel@highest + VK_PPC_DTPREL_HIGHESTA,// symbol@dtprel@highesta + VK_PPC_GOT_TPREL, // symbol@got@tprel + VK_PPC_GOT_TPREL_LO, // symbol@got@tprel@l + VK_PPC_GOT_TPREL_HI, // symbol@got@tprel@h + VK_PPC_GOT_TPREL_HA, // symbol@got@tprel@ha + VK_PPC_GOT_DTPREL, // symbol@got@dtprel + VK_PPC_GOT_DTPREL_LO, // symbol@got@dtprel@l + VK_PPC_GOT_DTPREL_HI, // symbol@got@dtprel@h + VK_PPC_GOT_DTPREL_HA, // symbol@got@dtprel@ha VK_PPC_TLS, // symbol@tls - VK_PPC_GOT_TLSGD16_HA, // symbol@got@tlsgd@ha - VK_PPC_GOT_TLSGD16_LO, // symbol@got@tlsgd@l + VK_PPC_GOT_TLSGD, // symbol@got@tlsgd + VK_PPC_GOT_TLSGD_LO, // symbol@got@tlsgd@l + VK_PPC_GOT_TLSGD_HI, // symbol@got@tlsgd@h + VK_PPC_GOT_TLSGD_HA, // symbol@got@tlsgd@ha VK_PPC_TLSGD, // symbol@tlsgd - VK_PPC_GOT_TLSLD16_HA, // symbol@got@tlsld@ha - VK_PPC_GOT_TLSLD16_LO, // symbol@got@tlsld@l + VK_PPC_GOT_TLSLD, // symbol@got@tlsld + VK_PPC_GOT_TLSLD_LO, // symbol@got@tlsld@l + VK_PPC_GOT_TLSLD_HI, // symbol@got@tlsld@h + VK_PPC_GOT_TLSLD_HA, // symbol@got@tlsld@ha VK_PPC_TLSLD, // symbol@tlsld VK_Mips_GPREL, diff --git a/contrib/llvm/include/llvm/MC/MCExternalSymbolizer.h b/contrib/llvm/include/llvm/MC/MCExternalSymbolizer.h new file mode 100644 index 000000000..c942adca3 --- /dev/null +++ b/contrib/llvm/include/llvm/MC/MCExternalSymbolizer.h @@ -0,0 +1,58 @@ +//===-- llvm/MC/MCExternalSymbolizer.h - ------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the MCExternalSymbolizer class, which +// enables library users to provide callbacks (through the C API) to do the +// symbolization externally. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCEXTERNALSYMBOLIZER_H +#define LLVM_MC_MCEXTERNALSYMBOLIZER_H + +#include "llvm-c/Disassembler.h" +#include "llvm/MC/MCSymbolizer.h" + +namespace llvm { + +/// \brief Symbolize using user-provided, C API, callbacks. +/// +/// See llvm-c/Disassembler.h. +class MCExternalSymbolizer : public MCSymbolizer { + + /// \name Hooks for symbolic disassembly via the public 'C' interface. + /// @{ + /// The function to get the symbolic information for operands. + LLVMOpInfoCallback GetOpInfo; + /// The function to lookup a symbol name. + LLVMSymbolLookupCallback SymbolLookUp; + /// The pointer to the block of symbolic information for above call back. + void *DisInfo; + /// @} + +public: + MCExternalSymbolizer(MCContext &Ctx, + OwningPtr &RelInfo, + LLVMOpInfoCallback getOpInfo, + LLVMSymbolLookupCallback symbolLookUp, + void *disInfo) + : MCSymbolizer(Ctx, RelInfo), + GetOpInfo(getOpInfo), SymbolLookUp(symbolLookUp), DisInfo(disInfo) {} + + bool tryAddingSymbolicOperand(MCInst &MI, raw_ostream &CommentStream, + int64_t Value, + uint64_t Address, bool IsBranch, + uint64_t Offset, uint64_t InstSize); + void tryAddingPcLoadReferenceComment(raw_ostream &CommentStream, + int64_t Value, uint64_t Address); +}; + +} + +#endif diff --git a/contrib/llvm/include/llvm/MC/MCFunction.h b/contrib/llvm/include/llvm/MC/MCFunction.h new file mode 100644 index 000000000..22c9192ac --- /dev/null +++ b/contrib/llvm/include/llvm/MC/MCFunction.h @@ -0,0 +1,142 @@ +//===-- llvm/MC/MCFunction.h ------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the data structures to hold a CFG reconstructed from +// machine code. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCFUNCTION_H +#define LLVM_MC_MCFUNCTION_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/MC/MCInst.h" +#include +#include + +namespace llvm { + +class MCFunction; +class MCModule; +class MCTextAtom; + +/// \brief Basic block containing a sequence of disassembled instructions. +/// The basic block is backed by an MCTextAtom, which holds the instructions, +/// and the address range it covers. +/// Create a basic block using MCFunction::createBlock. +class MCBasicBlock { + const MCTextAtom *Insts; + + // MCFunction owns the basic block. + MCFunction *Parent; + friend class MCFunction; + MCBasicBlock(const MCTextAtom &Insts, MCFunction *Parent); + + /// \name Predecessors/Successors, to represent the CFG. + /// @{ + typedef std::vector BasicBlockListTy; + BasicBlockListTy Successors; + BasicBlockListTy Predecessors; + /// @} +public: + + /// \brief Get the backing MCTextAtom, containing the instruction sequence. + const MCTextAtom *getInsts() const { return Insts; } + + /// \name Get the owning MCFunction. + /// @{ + const MCFunction *getParent() const { return Parent; } + MCFunction *getParent() { return Parent; } + /// @} + + /// MC CFG access: Predecessors/Successors. + /// @{ + typedef BasicBlockListTy::const_iterator succ_const_iterator; + succ_const_iterator succ_begin() const { return Successors.begin(); } + succ_const_iterator succ_end() const { return Successors.end(); } + + typedef BasicBlockListTy::const_iterator pred_const_iterator; + pred_const_iterator pred_begin() const { return Predecessors.begin(); } + pred_const_iterator pred_end() const { return Predecessors.end(); } + + void addSuccessor(const MCBasicBlock *MCBB); + bool isSuccessor(const MCBasicBlock *MCBB) const; + + void addPredecessor(const MCBasicBlock *MCBB); + bool isPredecessor(const MCBasicBlock *MCBB) const; + + /// \brief Split block, mirrorring NewAtom = Insts->split(..). + /// This moves all successors to \p SplitBB, and + /// adds a fallthrough to it. + /// \p SplitBB The result of splitting Insts, a basic block directly following + /// this basic block. + void splitBasicBlock(MCBasicBlock *SplitBB); + /// @} +}; + +/// \brief Represents a function in machine code, containing MCBasicBlocks. +/// MCFunctions are created by MCModule. +class MCFunction { + MCFunction (const MCFunction&) LLVM_DELETED_FUNCTION; + MCFunction& operator=(const MCFunction&) LLVM_DELETED_FUNCTION; + + std::string Name; + MCModule *ParentModule; + typedef std::vector BasicBlockListTy; + BasicBlockListTy Blocks; + + // MCModule owns the function. + friend class MCModule; + MCFunction(StringRef Name, MCModule *Parent); + ~MCFunction(); + +public: + /// \brief Create an MCBasicBlock backed by Insts and add it to this function. + /// \param Insts Sequence of straight-line code backing the basic block. + /// \returns The newly created basic block. + MCBasicBlock &createBlock(const MCTextAtom &Insts); + + StringRef getName() const { return Name; } + + /// \name Get the owning MC Module. + /// @{ + const MCModule *getParent() const { return ParentModule; } + MCModule *getParent() { return ParentModule; } + /// @} + + /// \name Access to the function's basic blocks. No ordering is enforced, + /// except that the first block is the entry block. + /// @{ + /// \brief Get the entry point basic block. + const MCBasicBlock *getEntryBlock() const { return front(); } + MCBasicBlock *getEntryBlock() { return front(); } + + bool empty() const { return Blocks.empty(); } + + typedef BasicBlockListTy::const_iterator const_iterator; + typedef BasicBlockListTy:: iterator iterator; + const_iterator begin() const { return Blocks.begin(); } + iterator begin() { return Blocks.begin(); } + const_iterator end() const { return Blocks.end(); } + iterator end() { return Blocks.end(); } + + const MCBasicBlock* front() const { return Blocks.front(); } + MCBasicBlock* front() { return Blocks.front(); } + const MCBasicBlock* back() const { return Blocks.back(); } + MCBasicBlock* back() { return Blocks.back(); } + + /// \brief Find the basic block, if any, that starts at \p StartAddr. + const MCBasicBlock *find(uint64_t StartAddr) const; + MCBasicBlock *find(uint64_t StartAddr); + /// @} +}; + +} + +#endif diff --git a/contrib/llvm/include/llvm/MC/MCInstPrinter.h b/contrib/llvm/include/llvm/MC/MCInstPrinter.h index a18cbd94b..b4258bef0 100644 --- a/contrib/llvm/include/llvm/MC/MCInstPrinter.h +++ b/contrib/llvm/include/llvm/MC/MCInstPrinter.h @@ -21,6 +21,13 @@ class MCInstrInfo; class MCRegisterInfo; class StringRef; +namespace HexStyle { + enum Style { + C, ///< 0xff + Asm ///< 0ffh + }; +} + /// MCInstPrinter - This is an instance of a target assembly language printer /// that converts an MCInst to valid target assembly syntax. class MCInstPrinter { @@ -34,7 +41,7 @@ protected: const MCRegisterInfo &MRI; /// The current set of available features. - unsigned AvailableFeatures; + uint64_t AvailableFeatures; /// True if we are printing marked up assembly. bool UseMarkup; @@ -42,13 +49,16 @@ protected: /// True if we are printing immediates as hex. bool PrintImmHex; + /// Which style to use for printing hexadecimal values. + HexStyle::Style PrintHexStyle; + /// Utility function for printing annotations. void printAnnotation(raw_ostream &OS, StringRef Annot); public: MCInstPrinter(const MCAsmInfo &mai, const MCInstrInfo &mii, const MCRegisterInfo &mri) : CommentStream(0), MAI(mai), MII(mii), MRI(mri), AvailableFeatures(0), - UseMarkup(0), PrintImmHex(0) {} + UseMarkup(0), PrintImmHex(0), PrintHexStyle(HexStyle::C) {} virtual ~MCInstPrinter(); @@ -67,8 +77,8 @@ public: /// printRegName - Print the assembler register name. virtual void printRegName(raw_ostream &OS, unsigned RegNo) const; - unsigned getAvailableFeatures() const { return AvailableFeatures; } - void setAvailableFeatures(unsigned Value) { AvailableFeatures = Value; } + uint64_t getAvailableFeatures() const { return AvailableFeatures; } + void setAvailableFeatures(uint64_t Value) { AvailableFeatures = Value; } bool getUseMarkup() const { return UseMarkup; } void setUseMarkup(bool Value) { UseMarkup = Value; } @@ -80,8 +90,16 @@ public: bool getPrintImmHex() const { return PrintImmHex; } void setPrintImmHex(bool Value) { PrintImmHex = Value; } + HexStyle::Style getPrintHexStyleHex() const { return PrintHexStyle; } + void setPrintImmHex(HexStyle::Style Value) { PrintHexStyle = Value; } + /// Utility function to print immediates in decimal or hex. - format_object1 formatImm(const int64_t Value) const; + format_object1 formatImm(const 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; }; } // namespace llvm diff --git a/contrib/llvm/include/llvm/MC/MCInstrAnalysis.h b/contrib/llvm/include/llvm/MC/MCInstrAnalysis.h index acad6336a..17bfd1582 100644 --- a/contrib/llvm/include/llvm/MC/MCInstrAnalysis.h +++ b/contrib/llvm/include/llvm/MC/MCInstrAnalysis.h @@ -52,10 +52,15 @@ public: return Info->get(Inst.getOpcode()).isReturn(); } + virtual bool isTerminator(const MCInst &Inst) const { + return Info->get(Inst.getOpcode()).isTerminator(); + } + /// evaluateBranch - Given a branch instruction try to get the address the - /// branch targets. Otherwise return -1. - virtual uint64_t - evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size) const; + /// branch targets. Return true on success, and the address in Target. + virtual bool + evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size, + uint64_t &Target) const; }; } diff --git a/contrib/llvm/include/llvm/MC/MCInstrDesc.h b/contrib/llvm/include/llvm/MC/MCInstrDesc.h index 9b5415add..214b593f4 100644 --- a/contrib/llvm/include/llvm/MC/MCInstrDesc.h +++ b/contrib/llvm/include/llvm/MC/MCInstrDesc.h @@ -17,6 +17,7 @@ #include "llvm/MC/MCInst.h" #include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCSubtargetInfo.h" #include "llvm/Support/DataTypes.h" namespace llvm { @@ -145,6 +146,10 @@ public: const uint16_t *ImplicitUses; // Registers implicitly read by this instr const uint16_t *ImplicitDefs; // Registers implicitly defined by this instr const MCOperandInfo *OpInfo; // 'NumOperands' entries about operands + uint64_t DeprecatedFeatureMask;// Feature bits that this is deprecated on, if any + // A complex method to determine is a certain is deprecated or not, and return + // the reason for deprecation. + bool (*ComplexDeprecationInfo)(MCInst &, MCSubtargetInfo &, std::string &); /// \brief Returns the value of the specific constraint if /// it is set. Returns -1 if it is not set. @@ -158,6 +163,20 @@ public: return -1; } + /// \brief Returns true if a certain instruction is deprecated and if so + /// returns the reason in \p Info. + bool getDeprecatedInfo(MCInst &MI, MCSubtargetInfo &STI, + std::string &Info) const { + if (ComplexDeprecationInfo) + return ComplexDeprecationInfo(MI, STI, Info); + if ((DeprecatedFeatureMask & STI.getFeatureBits()) != 0) { + // FIXME: it would be nice to include the subtarget feature here. + Info = "deprecated"; + return true; + } + return false; + } + /// \brief Return the opcode number for this descriptor. unsigned getOpcode() const { return Opcode; @@ -268,8 +287,20 @@ public: if (isBranch() || isCall() || isReturn() || isIndirectBranch()) return true; unsigned PC = RI.getProgramCounter(); - if (PC == 0) return false; - return hasDefOfPhysReg(MI, PC, RI); + if (PC == 0) + return false; + if (hasDefOfPhysReg(MI, PC, RI)) + return true; + // A variadic instruction may define PC in the variable operand list. + // There's currently no indication of which entries in a variable + // list are defs and which are uses. While that's the case, this function + // needs to assume they're defs in order to be conservatively correct. + for (int i = NumOperands, e = MI.getNumOperands(); i != e; ++i) { + if (MI.getOperand(i).isReg() && + RI.isSubRegisterEq(PC, MI.getOperand(i).getReg())) + return true; + } + return false; } /// \brief Return true if this instruction has a predicate operand diff --git a/contrib/llvm/include/llvm/MC/MCInstrItineraries.h b/contrib/llvm/include/llvm/MC/MCInstrItineraries.h index 65d1559ac..c4f9e1c32 100644 --- a/contrib/llvm/include/llvm/MC/MCInstrItineraries.h +++ b/contrib/llvm/include/llvm/MC/MCInstrItineraries.h @@ -157,17 +157,12 @@ public: /// class. The latency is the maximum completion time for any stage /// in the itinerary. /// - /// InstrStages override the itinerary's MinLatency property. In fact, if the - /// stage latencies, which may be zero, are less than MinLatency, - /// getStageLatency returns a value less than MinLatency. - /// - /// If no stages exist, MinLatency is used. If MinLatency is invalid (<0), - /// then it defaults to one cycle. + /// If no stages exist, it defaults to one cycle. unsigned getStageLatency(unsigned ItinClassIndx) const { // If the target doesn't provide itinerary information, use a simple // non-zero default value for all instructions. if (isEmpty()) - return SchedModel->MinLatency < 0 ? 1 : SchedModel->MinLatency; + return 1; // Calculate the maximum completion time for any stage. unsigned Latency = 0, StartCycle = 0; @@ -176,7 +171,6 @@ public: Latency = std::max(Latency, StartCycle + IS->getCycles()); StartCycle += IS->getNextCycles(); } - return Latency; } diff --git a/contrib/llvm/include/llvm/MC/MCMachOSymbolFlags.h b/contrib/llvm/include/llvm/MC/MCMachOSymbolFlags.h index 696436dff..71f01fab2 100644 --- a/contrib/llvm/include/llvm/MC/MCMachOSymbolFlags.h +++ b/contrib/llvm/include/llvm/MC/MCMachOSymbolFlags.h @@ -19,9 +19,9 @@ // the correct relocation information. namespace llvm { - /// SymbolFlags - We store the value for the 'desc' symbol field in the lowest - /// 16 bits of the implementation defined flags. - enum SymbolFlags { // See . + /// MachOSymbolFlags - We store the value for the 'desc' symbol field in the + /// lowest 16 bits of the implementation defined flags. + enum MachOSymbolFlags { // See . SF_DescFlagsMask = 0xFFFF, // Reference type flags. diff --git a/contrib/llvm/include/llvm/MC/MCMachObjectWriter.h b/contrib/llvm/include/llvm/MC/MCMachObjectWriter.h index 3c9a588d0..3ba6e6510 100644 --- a/contrib/llvm/include/llvm/MC/MCMachObjectWriter.h +++ b/contrib/llvm/include/llvm/MC/MCMachObjectWriter.h @@ -15,8 +15,8 @@ #include "llvm/ADT/SmallString.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCObjectWriter.h" -#include "llvm/Object/MachOFormat.h" #include "llvm/Support/DataTypes.h" +#include "llvm/Support/MachO.h" #include namespace llvm { @@ -98,7 +98,7 @@ class MachObjectWriter : public MCObjectWriter { /// @{ llvm::DenseMap > Relocations; + std::vector > Relocations; llvm::DenseMap IndirectSymBase; /// @} @@ -155,9 +155,8 @@ public: bool is64Bit() const { return TargetObjectWriter->is64Bit(); } bool isARM() const { - uint32_t CPUType = TargetObjectWriter->getCPUType() & - ~object::mach::CTFM_ArchMask; - return CPUType == object::mach::CTM_ARM; + uint32_t CPUType = TargetObjectWriter->getCPUType() & ~MachO::CPU_ARCH_MASK; + return CPUType == MachO::CPU_TYPE_ARM; } /// @} @@ -213,7 +212,7 @@ public: // these through in many cases. void addRelocation(const MCSectionData *SD, - object::macho::RelocationEntry &MRE) { + MachO::any_relocation_info &MRE) { Relocations[SD].push_back(MRE); } diff --git a/contrib/llvm/include/llvm/MC/MCModule.h b/contrib/llvm/include/llvm/MC/MCModule.h index 755fa025f..63635c747 100644 --- a/contrib/llvm/include/llvm/MC/MCModule.h +++ b/contrib/llvm/include/llvm/MC/MCModule.h @@ -15,44 +15,119 @@ #ifndef LLVM_MC_MCMODULE_H #define LLVM_MC_MCMODULE_H -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/IntervalMap.h" -#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Compiler.h" #include "llvm/Support/DataTypes.h" +#include namespace llvm { class MCAtom; +class MCBasicBlock; +class MCDataAtom; +class MCFunction; +class MCObjectDisassembler; +class MCTextAtom; -/// MCModule - This class represent a completely disassembled object file or -/// executable. It comprises a list of MCAtom's, and a branch target table. -/// Each atom represents a contiguous range of either instructions or data. +/// \brief A completely disassembled object file or executable. +/// It comprises a list of MCAtom's, each representing a contiguous range of +/// either instructions or data. +/// An MCModule is created using MCObjectDisassembler::buildModule. class MCModule { - /// AtomAllocationTracker - An MCModule owns its component MCAtom's, so it - /// must track them in order to ensure they are properly freed as atoms are - /// merged or otherwise manipulated. - SmallPtrSet AtomAllocationTracker; + /// \name Atom tracking + /// @{ - /// OffsetMap - Efficiently maps offset ranges to MCAtom's. - IntervalMap OffsetMap; - - /// BranchTargetMap - Maps offsets that are determined to be branches and - /// can be statically resolved to their target offsets. - DenseMap BranchTargetMap; + /// \brief Atoms in this module, sorted by begin address. + /// FIXME: This doesn't handle overlapping atoms (which happen when a basic + /// block starts in the middle of an instruction of another basic block.) + typedef std::vector AtomListTy; + AtomListTy Atoms; + // For access to map/remap. friend class MCAtom; - /// remap - Update the interval mapping for an MCAtom. + /// \brief Remap \p Atom to the given range, and update its Begin/End fields. + /// \param Atom An atom belonging to this module. + /// An atom should always use this method to update its bounds, because this + /// enables the owning MCModule to keep track of its atoms. void remap(MCAtom *Atom, uint64_t NewBegin, uint64_t NewEnd); + /// \brief Insert an atom in the module, using its Begin and End addresses. + void map(MCAtom *NewAtom); + /// @} + + /// \name Basic block tracking + /// @{ + typedef std::vector BBsByAtomTy; + BBsByAtomTy BBsByAtom; + + // For access to basic block > atom tracking. + friend class MCBasicBlock; + friend class MCTextAtom; + + /// \brief Keep track of \p BBBackedByAtom as being backed by \p Atom. + /// This is used to update succs/preds when \p Atom is split. + void trackBBForAtom(const MCTextAtom *Atom, MCBasicBlock *BBBackedByAtom); + void splitBasicBlocksForAtom(const MCTextAtom *TA, const MCTextAtom *NewTA); + /// @} + + /// \name Function tracking + /// @{ + typedef std::vector FunctionListTy; + FunctionListTy Functions; + /// @} + + /// The address of the entrypoint function. + uint64_t Entrypoint; + + MCModule (const MCModule &) LLVM_DELETED_FUNCTION; + MCModule& operator=(const MCModule &) LLVM_DELETED_FUNCTION; + + // MCObjectDisassembler creates MCModules. + friend class MCObjectDisassembler; + public: - MCModule(IntervalMap::Allocator &A) : OffsetMap(A) { } + MCModule() : Entrypoint(0) { } + ~MCModule(); + + /// \name Create a new MCAtom covering the specified offset range. + /// @{ + MCTextAtom *createTextAtom(uint64_t Begin, uint64_t End); + MCDataAtom *createDataAtom(uint64_t Begin, uint64_t End); + /// @} + + /// \name Access to the owned atom list, ordered by begin address. + /// @{ + const MCAtom *findAtomContaining(uint64_t Addr) const; + MCAtom *findAtomContaining(uint64_t Addr); + const MCAtom *findFirstAtomAfter(uint64_t Addr) const; + MCAtom *findFirstAtomAfter(uint64_t Addr); + + typedef AtomListTy::const_iterator const_atom_iterator; + typedef AtomListTy:: iterator atom_iterator; + const_atom_iterator atom_begin() const { return Atoms.begin(); } + atom_iterator atom_begin() { return Atoms.begin(); } + const_atom_iterator atom_end() const { return Atoms.end(); } + atom_iterator atom_end() { return Atoms.end(); } + /// @} - /// createAtom - Creates a new MCAtom covering the specified offset range. - MCAtom *createAtom(MCAtom::AtomType Type, uint64_t Begin, uint64_t End); + /// \brief Create a new MCFunction. + MCFunction *createFunction(StringRef Name); + + /// \name Access to the owned function list. + /// @{ + typedef FunctionListTy::const_iterator const_func_iterator; + typedef FunctionListTy:: iterator func_iterator; + const_func_iterator func_begin() const { return Functions.begin(); } + func_iterator func_begin() { return Functions.begin(); } + const_func_iterator func_end() const { return Functions.end(); } + func_iterator func_end() { return Functions.end(); } + /// @} + + /// \brief Get the address of the entrypoint function, or 0 if there is none. + uint64_t getEntrypoint() const { return Entrypoint; } }; } #endif - diff --git a/contrib/llvm/include/llvm/MC/MCModuleYAML.h b/contrib/llvm/include/llvm/MC/MCModuleYAML.h new file mode 100644 index 000000000..281e3d8dc --- /dev/null +++ b/contrib/llvm/include/llvm/MC/MCModuleYAML.h @@ -0,0 +1,41 @@ +//===- MCModuleYAML.h - MCModule YAMLIO implementation ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief This file declares classes for handling the YAML representation +/// of MCModule. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCMODULEYAML_H +#define LLVM_MC_MCMODULEYAML_H + +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/MC/MCModule.h" +#include "llvm/Support/raw_ostream.h" + +namespace llvm { + +class MCInstrInfo; +class MCRegisterInfo; + +/// \brief Dump a YAML representation of the MCModule \p MCM to \p OS. +/// \returns The empty string on success, an error message on failure. +StringRef mcmodule2yaml(raw_ostream &OS, const MCModule &MCM, + const MCInstrInfo &MII, const MCRegisterInfo &MRI); + +/// \brief Creates a new module and returns it in \p MCM. +/// \returns The empty string on success, an error message on failure. +StringRef yaml2mcmodule(OwningPtr &MCM, StringRef YamlContent, + const MCInstrInfo &MII, const MCRegisterInfo &MRI); + +} // end namespace llvm + +#endif diff --git a/contrib/llvm/include/llvm/MC/MCObjectDisassembler.h b/contrib/llvm/include/llvm/MC/MCObjectDisassembler.h new file mode 100644 index 000000000..0d87d33ba --- /dev/null +++ b/contrib/llvm/include/llvm/MC/MCObjectDisassembler.h @@ -0,0 +1,175 @@ +//===-- llvm/MC/MCObjectDisassembler.h --------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the MCObjectDisassembler class, which +// can be used to construct an MCModule and an MC CFG from an ObjectFile. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCOBJECTDISASSEMBLER_H +#define LLVM_MC_MCOBJECTDISASSEMBLER_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/DataTypes.h" +#include "llvm/Support/MemoryObject.h" +#include + +namespace llvm { + +namespace object { + class ObjectFile; + class MachOObjectFile; +} + +class MCBasicBlock; +class MCDisassembler; +class MCFunction; +class MCInstrAnalysis; +class MCModule; +class MCObjectSymbolizer; + +/// \brief Disassemble an ObjectFile to an MCModule and MCFunctions. +/// This class builds on MCDisassembler to disassemble whole sections, creating +/// MCAtom (MCTextAtom for disassembled sections and MCDataAtom for raw data). +/// It can also be used to create a control flow graph consisting of MCFunctions +/// and MCBasicBlocks. +class MCObjectDisassembler { +public: + MCObjectDisassembler(const object::ObjectFile &Obj, + const MCDisassembler &Dis, + const MCInstrAnalysis &MIA); + virtual ~MCObjectDisassembler() {} + + /// \brief Build an MCModule, creating atoms and optionally functions. + /// \param withCFG Also build a CFG by adding MCFunctions to the Module. + /// If withCFG is false, the MCModule built only contains atoms, representing + /// what was found in the object file. If withCFG is true, MCFunctions are + /// created, containing MCBasicBlocks. All text atoms are split to form basic + /// block atoms, which then each back an MCBasicBlock. + MCModule *buildModule(bool withCFG = false); + + MCModule *buildEmptyModule(); + + typedef std::vector AddressSetTy; + /// \name Create a new MCFunction. + MCFunction *createFunction(MCModule *Module, uint64_t BeginAddr, + AddressSetTy &CallTargets, + AddressSetTy &TailCallTargets); + + /// \brief Set the region on which to fallback if disassembly was requested + /// somewhere not accessible in the object file. + /// This is used for dynamic disassembly (see RawMemoryObject). + void setFallbackRegion(OwningPtr &Region) { + FallbackRegion.reset(Region.take()); + } + + /// \brief Set the symbolizer to use to get information on external functions. + /// Note that this isn't used to do instruction-level symbolization (that is, + /// plugged into MCDisassembler), but to symbolize function call targets. + void setSymbolizer(MCObjectSymbolizer *ObjectSymbolizer) { + MOS = ObjectSymbolizer; + } + + /// \brief Get the effective address of the entrypoint, or 0 if there is none. + virtual uint64_t getEntrypoint(); + + /// \name Get the addresses of static constructors/destructors in the object. + /// The caller is expected to know how to interpret the addresses; + /// for example, Mach-O init functions expect 5 arguments, not for ELF. + /// The addresses are original object file load addresses, not effective. + /// @{ + virtual ArrayRef getStaticInitFunctions(); + virtual ArrayRef getStaticExitFunctions(); + /// @} + + /// \name Translation between effective and objectfile load address. + /// @{ + /// \brief Compute the effective load address, from an objectfile virtual + /// address. This is implemented in a format-specific way, to take into + /// account things like PIE/ASLR when doing dynamic disassembly. + /// For example, on Mach-O this would be done by adding the VM addr slide, + /// on glibc ELF by keeping a map between segment load addresses, filled + /// using dl_iterate_phdr, etc.. + /// In most static situations and in the default impl., this returns \p Addr. + virtual uint64_t getEffectiveLoadAddr(uint64_t Addr); + + /// \brief Compute the original load address, as specified in the objectfile. + /// This is the inverse of getEffectiveLoadAddr. + virtual uint64_t getOriginalLoadAddr(uint64_t EffectiveAddr); + /// @} + +protected: + const object::ObjectFile &Obj; + const MCDisassembler &Dis; + const MCInstrAnalysis &MIA; + MCObjectSymbolizer *MOS; + + /// \brief The fallback memory region, outside the object file. + OwningPtr FallbackRegion; + + /// \brief Return a memory region suitable for reading starting at \p Addr. + /// In most cases, this returns a StringRefMemoryObject backed by the + /// containing section. When no section was found, this returns the + /// FallbackRegion, if it is suitable. + /// If it is not, or if there is no fallback region, this returns 0. + MemoryObject *getRegionFor(uint64_t Addr); + +private: + /// \brief Fill \p Module by creating an atom for each section. + /// This could be made much smarter, using information like symbols, but also + /// format-specific features, like mach-o function_start or data_in_code LCs. + void buildSectionAtoms(MCModule *Module); + + /// \brief Enrich \p Module with a CFG consisting of MCFunctions. + /// \param Module An MCModule returned by buildModule, with no CFG. + /// NOTE: Each MCBasicBlock in a MCFunction is backed by a single MCTextAtom. + /// When the CFG is built, contiguous instructions that were previously in a + /// single MCTextAtom will be split in multiple basic block atoms. + void buildCFG(MCModule *Module); + + MCBasicBlock *getBBAt(MCModule *Module, MCFunction *MCFN, uint64_t BeginAddr, + AddressSetTy &CallTargets, + AddressSetTy &TailCallTargets); +}; + +class MCMachOObjectDisassembler : public MCObjectDisassembler { + const object::MachOObjectFile &MOOF; + + uint64_t VMAddrSlide; + uint64_t HeaderLoadAddress; + + // __DATA;__mod_init_func support. + llvm::StringRef ModInitContents; + // __DATA;__mod_exit_func support. + llvm::StringRef ModExitContents; + +public: + /// \brief Construct a Mach-O specific object disassembler. + /// \param VMAddrSlide The virtual address slide applied by dyld. + /// \param HeaderLoadAddress The load address of the mach_header for this + /// object. + MCMachOObjectDisassembler(const object::MachOObjectFile &MOOF, + const MCDisassembler &Dis, + const MCInstrAnalysis &MIA, uint64_t VMAddrSlide, + uint64_t HeaderLoadAddress); + +protected: + uint64_t getEffectiveLoadAddr(uint64_t Addr) LLVM_OVERRIDE; + uint64_t getOriginalLoadAddr(uint64_t EffectiveAddr) LLVM_OVERRIDE; + uint64_t getEntrypoint() LLVM_OVERRIDE; + + ArrayRef getStaticInitFunctions() LLVM_OVERRIDE; + ArrayRef getStaticExitFunctions() LLVM_OVERRIDE; +}; + +} + +#endif diff --git a/contrib/llvm/include/llvm/MC/MCObjectFileInfo.h b/contrib/llvm/include/llvm/MC/MCObjectFileInfo.h index a5853b602..c48dcb021 100644 --- a/contrib/llvm/include/llvm/MC/MCObjectFileInfo.h +++ b/contrib/llvm/include/llvm/MC/MCObjectFileInfo.h @@ -125,6 +125,10 @@ protected: const MCSection *DwarfStrOffDWOSection; const MCSection *DwarfAddrSection; + /// Sections for newer gnu pubnames and pubtypes. + const MCSection *DwarfGnuPubNamesSection; + const MCSection *DwarfGnuPubTypesSection; + // Extra TLS Variable Data section. If the target needs to put additional // information for a TLS variable, it'll go here. const MCSection *TLSExtraDataSection; @@ -138,6 +142,8 @@ protected: /// ELF and MachO only. const MCSection *TLSBSSSection; // Defaults to ".tbss". + /// StackMap section. + const MCSection *StackMapSection; /// EHFrameSection - EH frame section. It is initialized on demand so it /// can be overwritten (with uniquing). @@ -223,6 +229,12 @@ public: const MCSection *getDwarfFrameSection() const { return DwarfFrameSection; } const MCSection *getDwarfPubNamesSection() const{return DwarfPubNamesSection;} const MCSection *getDwarfPubTypesSection() const{return DwarfPubTypesSection;} + const MCSection *getDwarfGnuPubNamesSection() const { + return DwarfGnuPubNamesSection; + } + const MCSection *getDwarfGnuPubTypesSection() const { + return DwarfGnuPubTypesSection; + } const MCSection *getDwarfDebugInlineSection() const { return DwarfDebugInlineSection; } @@ -275,6 +287,8 @@ public: const MCSection *getTLSDataSection() const { return TLSDataSection; } const MCSection *getTLSBSSSection() const { return TLSBSSSection; } + const MCSection *getStackMapSection() const { return StackMapSection; } + /// ELF specific sections. /// const MCSection *getDataRelSection() const { return DataRelSection; } diff --git a/contrib/llvm/include/llvm/MC/MCObjectStreamer.h b/contrib/llvm/include/llvm/MC/MCObjectStreamer.h index 22a283986..566754430 100644 --- a/contrib/llvm/include/llvm/MC/MCObjectStreamer.h +++ b/contrib/llvm/include/llvm/MC/MCObjectStreamer.h @@ -40,10 +40,11 @@ class MCObjectStreamer : public MCStreamer { virtual void EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame); protected: - MCObjectStreamer(StreamerKind Kind, MCContext &Context, MCAsmBackend &TAB, - raw_ostream &_OS, MCCodeEmitter *_Emitter); - MCObjectStreamer(StreamerKind Kind, MCContext &Context, MCAsmBackend &TAB, - raw_ostream &_OS, MCCodeEmitter *_Emitter, + MCObjectStreamer(MCContext &Context, MCTargetStreamer *TargetStreamer, + MCAsmBackend &TAB, raw_ostream &_OS, + MCCodeEmitter *_Emitter); + MCObjectStreamer(MCContext &Context, MCTargetStreamer *TargetStreamer, + MCAsmBackend &TAB, raw_ostream &_OS, MCCodeEmitter *_Emitter, MCAssembler *_Assembler); ~MCObjectStreamer(); @@ -78,8 +79,7 @@ public: virtual void EmitLabel(MCSymbol *Symbol); virtual void EmitDebugLabel(MCSymbol *Symbol); virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value); - virtual void EmitValueImpl(const MCExpr *Value, unsigned Size, - unsigned AddrSpace); + virtual void EmitValueImpl(const MCExpr *Value, unsigned Size); virtual void EmitULEB128Value(const MCExpr *Value); virtual void EmitSLEB128Value(const MCExpr *Value); virtual void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol); @@ -94,7 +94,7 @@ public: virtual void EmitBundleAlignMode(unsigned AlignPow2); virtual void EmitBundleLock(bool AlignToEnd); virtual void EmitBundleUnlock(); - virtual void EmitBytes(StringRef Data, unsigned AddrSpace = 0); + virtual void EmitBytes(StringRef Data); virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0, unsigned ValueSize = 1, @@ -102,6 +102,10 @@ public: virtual void EmitCodeAlignment(unsigned ByteAlignment, unsigned MaxBytesToEmit = 0); virtual bool EmitValueToOffset(const MCExpr *Offset, unsigned char Value); + virtual void EmitDwarfLocDirective(unsigned FileNo, unsigned Line, + unsigned Column, unsigned Flags, + unsigned Isa, unsigned Discriminator, + StringRef FileName); virtual void EmitDwarfAdvanceLineAddr(int64_t LineDelta, const MCSymbol *LastLabel, const MCSymbol *Label, @@ -110,15 +114,9 @@ public: const MCSymbol *Label); virtual void EmitGPRel32Value(const MCExpr *Value); virtual void EmitGPRel64Value(const MCExpr *Value); - virtual void EmitFill(uint64_t NumBytes, uint8_t FillValue, - unsigned AddrSpace = 0); + virtual void EmitFill(uint64_t NumBytes, uint8_t FillValue); + virtual void EmitZeros(uint64_t NumBytes); virtual void FinishImpl(); - - /// @} - - static bool classof(const MCStreamer *S) { - return S->getKind() >= SK_ELFStreamer && S->getKind() <= SK_WinCOFFStreamer; - } }; } // end namespace llvm diff --git a/contrib/llvm/include/llvm/MC/MCObjectSymbolizer.h b/contrib/llvm/include/llvm/MC/MCObjectSymbolizer.h new file mode 100644 index 000000000..64b932ebe --- /dev/null +++ b/contrib/llvm/include/llvm/MC/MCObjectSymbolizer.h @@ -0,0 +1,81 @@ +//===-- llvm/MC/MCObjectSymbolizer.h --------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the MCObjectSymbolizer class, an MCSymbolizer that is +// backed by an object::ObjectFile. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCOBJECTSYMBOLIZER_H +#define LLVM_MC_MCOBJECTSYMBOLIZER_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/MC/MCSymbolizer.h" +#include "llvm/Object/ObjectFile.h" +#include + +namespace llvm { + +class MCExpr; +class MCInst; +class MCRelocationInfo; +class raw_ostream; + +/// \brief An ObjectFile-backed symbolizer. +class MCObjectSymbolizer : public MCSymbolizer { +protected: + const object::ObjectFile *Obj; + + // Map a load address to the first relocation that applies there. As far as I + // know, if there are several relocations at the exact same address, they are + // related and the others can be determined from the first that was found in + // the relocation table. For instance, on x86-64 mach-o, a SUBTRACTOR + // relocation (referencing the minuend symbol) is followed by an UNSIGNED + // relocation (referencing the subtrahend symbol). + const object::RelocationRef *findRelocationAt(uint64_t Addr); + const object::SectionRef *findSectionContaining(uint64_t Addr); + + MCObjectSymbolizer(MCContext &Ctx, OwningPtr &RelInfo, + const object::ObjectFile *Obj); + +public: + /// \name Overridden MCSymbolizer methods: + /// @{ + bool tryAddingSymbolicOperand(MCInst &MI, raw_ostream &cStream, + int64_t Value, uint64_t Address, + bool IsBranch, uint64_t Offset, + uint64_t InstSize); + + void tryAddingPcLoadReferenceComment(raw_ostream &cStream, + int64_t Value, uint64_t Address); + /// @} + + /// \brief Look for an external function symbol at \p Addr. + /// (References through the ELF PLT, Mach-O stubs, and similar). + /// \returns An MCExpr representing the external symbol, or 0 if not found. + virtual StringRef findExternalFunctionAt(uint64_t Addr); + + /// \brief Create an object symbolizer for \p Obj. + static MCObjectSymbolizer * + createObjectSymbolizer(MCContext &Ctx, OwningPtr &RelInfo, + const object::ObjectFile *Obj); + +private: + typedef DenseMap AddrToRelocMap; + typedef std::vector SortedSectionList; + SortedSectionList SortedSections; + AddrToRelocMap AddrToReloc; + + void buildSectionList(); + void buildRelocationByAddrMap(); +}; + +} + +#endif diff --git a/contrib/llvm/include/llvm/MC/MCParser/AsmLexer.h b/contrib/llvm/include/llvm/MC/MCParser/AsmLexer.h index 0dab31489..1b3ab5775 100644 --- a/contrib/llvm/include/llvm/MC/MCParser/AsmLexer.h +++ b/contrib/llvm/include/llvm/MC/MCParser/AsmLexer.h @@ -63,6 +63,7 @@ private: AsmToken LexSingleQuote(); AsmToken LexQuote(); AsmToken LexFloatLiteral(); + AsmToken LexHexFloatLiteral(bool NoIntDigits); }; } // end namespace llvm diff --git a/contrib/llvm/include/llvm/MC/MCParser/MCAsmParser.h b/contrib/llvm/include/llvm/MC/MCParser/MCAsmParser.h index dcc988633..1d1553429 100644 --- a/contrib/llvm/include/llvm/MC/MCParser/MCAsmParser.h +++ b/contrib/llvm/include/llvm/MC/MCParser/MCAsmParser.h @@ -47,7 +47,7 @@ public: } } InlineAsmIdentifierInfo; - virtual ~MCAsmParserSemaCallback(); + virtual ~MCAsmParserSemaCallback(); virtual void *LookupInlineAsmIdentifier(StringRef &LineBuf, InlineAsmIdentifierInfo &Info, bool IsUnevaluatedContext) = 0; diff --git a/contrib/llvm/include/llvm/MC/MCRegisterInfo.h b/contrib/llvm/include/llvm/MC/MCRegisterInfo.h index f5b4dddc5..3fa89c109 100644 --- a/contrib/llvm/include/llvm/MC/MCRegisterInfo.h +++ b/contrib/llvm/include/llvm/MC/MCRegisterInfo.h @@ -99,19 +99,15 @@ public: bool isAllocatable() const { return Allocatable; } }; -/// MCRegisterDesc - This record contains all of the information known about -/// a particular register. The Overlaps field contains a pointer to a zero -/// terminated array of registers that this register aliases, starting with -/// itself. This is needed for architectures like X86 which have AL alias AX -/// alias EAX. The SubRegs field is a zero terminated array of registers that -/// are sub-registers of the specific register, e.g. AL, AH are sub-registers of -/// AX. The SuperRegs field is a zero terminated array of registers that are -/// super-registers of the specific register, e.g. RAX, EAX, are super-registers -/// of AX. +/// MCRegisterDesc - This record contains information about a particular +/// register. The SubRegs field is a zero terminated array of registers that +/// are sub-registers of the specific register, e.g. AL, AH are sub-registers +/// of AX. The SuperRegs field is a zero terminated array of registers that are +/// super-registers of the specific register, e.g. RAX, EAX, are +/// super-registers of AX. /// struct MCRegisterDesc { uint32_t Name; // Printable name for the reg (for debugging) - uint32_t Overlaps; // Overlapping registers, described above uint32_t SubRegs; // Sub-register set, described above uint32_t SuperRegs; // Super-register set, described above @@ -148,6 +144,13 @@ public: bool operator<(DwarfLLVMRegPair RHS) const { return FromReg < RHS.FromReg; } }; + + /// SubRegCoveredBits - Emitted by tablegen: bit range covered by a subreg + /// index, -1 in any being invalid. + struct SubRegCoveredBits { + uint16_t Offset; + uint16_t Size; + }; private: const MCRegisterDesc *Desc; // Pointer to the descriptor array unsigned NumRegs; // Number of entries in the array @@ -161,6 +164,8 @@ private: const char *RegStrings; // Pointer to the string table. const uint16_t *SubRegIndices; // Pointer to the subreg lookup // array. + const SubRegCoveredBits *SubRegIdxRanges; // Pointer to the subreg covered + // bit ranges array. unsigned NumSubRegIndices; // Number of subreg indices. const uint16_t *RegEncodingTable; // Pointer to array of register // encodings. @@ -226,7 +231,6 @@ public: // internal list pointers. friend class MCSubRegIterator; friend class MCSuperRegIterator; - friend class MCRegAliasIterator; friend class MCRegUnitIterator; friend class MCRegUnitRootIterator; @@ -241,6 +245,7 @@ public: const char *Strings, const uint16_t *SubIndices, unsigned NumIndices, + const SubRegCoveredBits *SubIdxRanges, const uint16_t *RET) { Desc = D; NumRegs = NR; @@ -254,6 +259,7 @@ public: NumRegUnits = NRU; SubRegIndices = SubIndices; NumSubRegIndices = NumIndices; + SubRegIdxRanges = SubIdxRanges; RegEncodingTable = RET; } @@ -332,6 +338,16 @@ public: /// otherwise. unsigned getSubRegIndex(unsigned RegNo, unsigned SubRegNo) const; + /// \brief Get the size of the bit range covered by a sub-register index. + /// If the index isn't continuous, return the sum of the sizes of its parts. + /// If the index is used to access subregisters of different sizes, return -1. + unsigned getSubRegIdxSize(unsigned Idx) const; + + /// \brief Get the offset of the bit range covered by a sub-register index. + /// If an Offset doesn't make sense (the index isn't continuous, or is used to + /// access sub-registers at different offsets), return -1. + unsigned getSubRegIdxOffset(unsigned Idx) const; + /// \brief Return the human-readable symbolic target-specific name for the /// specified physical register. const char *getName(unsigned RegNo) const { @@ -421,30 +437,26 @@ public: // aliasing registers. Use these iterator classes to traverse the lists. /// MCSubRegIterator enumerates all sub-registers of Reg. +/// If IncludeSelf is set, Reg itself is included in the list. class MCSubRegIterator : public MCRegisterInfo::DiffListIterator { public: - MCSubRegIterator(unsigned Reg, const MCRegisterInfo *MCRI) { + MCSubRegIterator(unsigned Reg, const MCRegisterInfo *MCRI, + bool IncludeSelf = false) { init(Reg, MCRI->DiffLists + MCRI->get(Reg).SubRegs); - ++*this; + // Initially, the iterator points to Reg itself. + if (!IncludeSelf) + ++*this; } }; /// MCSuperRegIterator enumerates all super-registers of Reg. +/// If IncludeSelf is set, Reg itself is included in the list. class MCSuperRegIterator : public MCRegisterInfo::DiffListIterator { public: - MCSuperRegIterator(unsigned Reg, const MCRegisterInfo *MCRI) { + MCSuperRegIterator() {} + MCSuperRegIterator(unsigned Reg, const MCRegisterInfo *MCRI, + bool IncludeSelf = false) { init(Reg, MCRI->DiffLists + MCRI->get(Reg).SuperRegs); - ++*this; - } -}; - -/// MCRegAliasIterator enumerates all registers aliasing Reg. -/// If IncludeSelf is set, Reg itself is included in the list. -class MCRegAliasIterator : public MCRegisterInfo::DiffListIterator { -public: - MCRegAliasIterator(unsigned Reg, const MCRegisterInfo *MCRI, - bool IncludeSelf) { - init(Reg, MCRI->DiffLists + MCRI->get(Reg).Overlaps); // Initially, the iterator points to Reg itself. if (!IncludeSelf) ++*this; @@ -478,6 +490,7 @@ class MCRegUnitIterator : public MCRegisterInfo::DiffListIterator { public: /// MCRegUnitIterator - Create an iterator that traverses the register units /// in Reg. + MCRegUnitIterator() {} MCRegUnitIterator(unsigned Reg, const MCRegisterInfo *MCRI) { assert(Reg && "Null register has no regunits"); // Decode the RegUnits MCRegisterDesc field. @@ -502,9 +515,7 @@ public: // super-registers. All registers aliasing Unit can be visited like this: // // for (MCRegUnitRootIterator RI(Unit, MCRI); RI.isValid(); ++RI) { -// unsigned Root = *RI; -// visit(Root); -// for (MCSuperRegIterator SI(Root, MCRI); SI.isValid(); ++SI) +// for (MCSuperRegIterator SI(*RI, MCRI, true); SI.isValid(); ++SI) // visit(*SI); // } @@ -513,6 +524,7 @@ class MCRegUnitRootIterator { uint16_t Reg0; uint16_t Reg1; public: + MCRegUnitRootIterator() : Reg0(0), Reg1(0) {} MCRegUnitRootIterator(unsigned RegUnit, const MCRegisterInfo *MCRI) { assert(RegUnit < MCRI->getNumRegUnits() && "Invalid register unit"); Reg0 = MCRI->RegUnitRoots[RegUnit][0]; @@ -537,6 +549,68 @@ public: } }; +/// MCRegAliasIterator enumerates all registers aliasing Reg. If IncludeSelf is +/// set, Reg itself is included in the list. This iterator does not guarantee +/// any ordering or that entries are unique. +class MCRegAliasIterator { +private: + unsigned Reg; + const MCRegisterInfo *MCRI; + bool IncludeSelf; + + MCRegUnitIterator RI; + MCRegUnitRootIterator RRI; + MCSuperRegIterator SI; +public: + MCRegAliasIterator(unsigned Reg, const MCRegisterInfo *MCRI, + bool IncludeSelf) + : Reg(Reg), MCRI(MCRI), IncludeSelf(IncludeSelf) { + + // Initialize the iterators. + for (RI = MCRegUnitIterator(Reg, MCRI); RI.isValid(); ++RI) { + for (RRI = MCRegUnitRootIterator(*RI, MCRI); RRI.isValid(); ++RRI) { + for (SI = MCSuperRegIterator(*RRI, MCRI, true); SI.isValid(); ++SI) { + if (!(!IncludeSelf && Reg == *SI)) + return; + } + } + } + } + + bool isValid() const { + return RI.isValid(); + } + + unsigned operator*() const { + assert (SI.isValid() && "Cannot dereference an invalid iterator."); + return *SI; + } + + void advance() { + // Assuming SI is valid. + ++SI; + if (SI.isValid()) return; + + ++RRI; + if (RRI.isValid()) { + SI = MCSuperRegIterator(*RRI, MCRI, true); + return; + } + + ++RI; + if (RI.isValid()) { + RRI = MCRegUnitRootIterator(*RI, MCRI); + SI = MCSuperRegIterator(*RRI, MCRI, true); + } + } + + void operator++() { + assert(isValid() && "Cannot move off the end of the list."); + do advance(); + while (!IncludeSelf && isValid() && *SI == Reg); + } +}; + } // End llvm namespace #endif diff --git a/contrib/llvm/include/llvm/MC/MCRelocationInfo.h b/contrib/llvm/include/llvm/MC/MCRelocationInfo.h new file mode 100644 index 000000000..9dab90099 --- /dev/null +++ b/contrib/llvm/include/llvm/MC/MCRelocationInfo.h @@ -0,0 +1,55 @@ +//==-- llvm/MC/MCRelocationInfo.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 declares the MCRelocationInfo class, which provides methods to +// create MCExprs from relocations, either found in an object::ObjectFile +// (object::RelocationRef), or provided through the C API. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCRELOCATIONINFO_H +#define LLVM_MC_MCRELOCATIONINFO_H + +#include "llvm/Support/Compiler.h" + +namespace llvm { + +namespace object { +class RelocationRef; +} +class MCExpr; +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; + +protected: + MCContext &Ctx; + +public: + MCRelocationInfo(MCContext &Ctx); + virtual ~MCRelocationInfo(); + + /// \brief Create an MCExpr for the relocation \p Rel. + /// \returns If possible, an MCExpr corresponding to Rel, else 0. + virtual const MCExpr *createExprForRelocation(object::RelocationRef Rel); + + /// \brief Create an MCExpr for the target-specific \p VariantKind. + /// The VariantKinds are defined in llvm-c/Disassembler.h. + /// Used by MCExternalSymbolizer. + /// \returns If possible, an MCExpr corresponding to VariantKind, else 0. + virtual const MCExpr *createExprForCAPIVariantKind(const MCExpr *SubExpr, + unsigned VariantKind); +}; + +} + +#endif diff --git a/contrib/llvm/include/llvm/MC/MCSchedule.h b/contrib/llvm/include/llvm/MC/MCSchedule.h index defa29903..6881e1d05 100644 --- a/contrib/llvm/include/llvm/MC/MCSchedule.h +++ b/contrib/llvm/include/llvm/MC/MCSchedule.h @@ -30,15 +30,18 @@ struct MCProcResourceDesc { unsigned NumUnits; // Number of resource of this kind unsigned SuperIdx; // Index of the resources kind that contains this kind. - // Buffered resources may be consumed at some indeterminate cycle after - // dispatch (e.g. for instructions that may issue out-of-order). Unbuffered - // resources always consume their resource some fixed number of cycles after - // dispatch (e.g. for instruction interlocking that may stall the pipeline). - bool IsBuffered; + // Number of resources that may be buffered. + // + // Buffered resources (BufferSize > 0 || BufferSize == -1) may be consumed at + // some indeterminate cycle after dispatch (e.g. for instructions that may + // issue out-of-order). Unbuffered resources (BufferSize == 0) always consume + // their resource some fixed number of cycles after dispatch (e.g. for + // instruction interlocking that may stall the pipeline). + int BufferSize; bool operator==(const MCProcResourceDesc &Other) const { return NumUnits == Other.NumUnits && SuperIdx == Other.SuperIdx - && IsBuffered == Other.IsBuffered; + && BufferSize == Other.BufferSize; } }; @@ -121,7 +124,7 @@ struct MCSchedClassDesc { /// microarchitecture to the scheduler in the form of properties. It also /// optionally refers to scheduler resource tables and itinerary /// tables. Scheduler resource tables model the latency and cost for each -/// instruction type. Itinerary tables are an independant mechanism that +/// instruction type. Itinerary tables are an independent mechanism that /// provides a detailed reservation table describing each cycle of instruction /// execution. Subtargets may define any or all of the above categories of data /// depending on the type of CPU and selected scheduler. @@ -134,28 +137,22 @@ public: unsigned IssueWidth; static const unsigned DefaultIssueWidth = 1; - // MinLatency is the minimum latency between a register write - // followed by a data dependent read. This determines which - // instructions may be scheduled in the same per-cycle group. This - // is distinct from *expected* latency, which determines the likely - // critical path but does not guarantee a pipeline - // hazard. MinLatency can always be overridden by the number of - // InstrStage cycles. + // MicroOpBufferSize is the number of micro-ops that the processor may buffer + // for out-of-order execution. // - // (-1) Standard in-order processor. - // Use InstrItinerary OperandCycles as MinLatency. - // If no OperandCycles exist, then use the cycle of the last InstrStage. + // "0" means operations that are not ready in this cycle are not considered + // for scheduling (they go in the pending queue). Latency is paramount. This + // may be more efficient if many instructions are pending in a schedule. // - // (0) Out-of-order processor, or in-order with bundled dependencies. - // RAW dependencies may be dispatched in the same cycle. - // Optional InstrItinerary OperandCycles provides expected latency. + // "1" means all instructions are considered for scheduling regardless of + // whether they are ready in this cycle. Latency still causes issue stalls, + // but we balance those stalls against other heuristics. // - // (>0) In-order processor with variable latencies. - // Use the greater of this value or the cycle of the last InstrStage. - // Optional InstrItinerary OperandCycles provides expected latency. - // TODO: can't yet specify both min and expected latency per operand. - int MinLatency; - static const int DefaultMinLatency = -1; + // "> 1" means the processor is out-of-order. This is a machine independent + // estimate of highly machine specific characteristics such are the register + // renaming pool and reorder buffer. + unsigned MicroOpBufferSize; + static const unsigned DefaultMicroOpBufferSize = 0; // LoadLatency is the expected latency of load instructions. // @@ -172,21 +169,13 @@ public: unsigned HighLatency; static const unsigned DefaultHighLatency = 10; - // ILPWindow is the number of cycles that the scheduler effectively ignores - // before attempting to hide latency. This should be zero for in-order cpus to - // always hide expected latency. For out-of-order cpus, it may be tweaked as - // desired to roughly approximate instruction buffers. The actual threshold is - // not very important for an OOO processor, as long as it isn't too high. A - // nonzero value helps avoid rescheduling to hide latency when its is fairly - // obviously useless and makes register pressure heuristics more effective. - unsigned ILPWindow; - static const unsigned DefaultILPWindow = 0; - // MispredictPenalty is the typical number of extra cycles the processor // takes to recover from a branch misprediction. unsigned MispredictPenalty; static const unsigned DefaultMispredictPenalty = 10; + bool CompleteModel; + private: unsigned ProcID; const MCProcResourceDesc *ProcResourceTable; @@ -203,11 +192,11 @@ public: // initialized in this default ctor because some clients directly instantiate // MCSchedModel instead of using a generated itinerary. MCSchedModel(): IssueWidth(DefaultIssueWidth), - MinLatency(DefaultMinLatency), + MicroOpBufferSize(DefaultMicroOpBufferSize), LoadLatency(DefaultLoadLatency), HighLatency(DefaultHighLatency), - ILPWindow(DefaultILPWindow), MispredictPenalty(DefaultMispredictPenalty), + CompleteModel(true), ProcID(0), ProcResourceTable(0), SchedClassTable(0), NumProcResourceKinds(0), NumSchedClasses(0), InstrItineraries(0) { @@ -216,20 +205,24 @@ public: } // Table-gen driven ctor. - MCSchedModel(unsigned iw, int ml, unsigned ll, unsigned hl, unsigned ilp, - unsigned mp, unsigned pi, const MCProcResourceDesc *pr, + MCSchedModel(unsigned iw, int mbs, unsigned ll, unsigned hl, + unsigned mp, bool cm, unsigned pi, const MCProcResourceDesc *pr, const MCSchedClassDesc *sc, unsigned npr, unsigned nsc, const InstrItinerary *ii): - IssueWidth(iw), MinLatency(ml), LoadLatency(ll), HighLatency(hl), - ILPWindow(ilp), MispredictPenalty(mp), ProcID(pi), ProcResourceTable(pr), - SchedClassTable(sc), NumProcResourceKinds(npr), NumSchedClasses(nsc), - InstrItineraries(ii) {} + IssueWidth(iw), MicroOpBufferSize(mbs), LoadLatency(ll), HighLatency(hl), + MispredictPenalty(mp), CompleteModel(cm), ProcID(pi), + ProcResourceTable(pr), SchedClassTable(sc), NumProcResourceKinds(npr), + NumSchedClasses(nsc), InstrItineraries(ii) {} unsigned getProcessorID() const { return ProcID; } /// Does this machine model include instruction-level scheduling. bool hasInstrSchedModel() const { return SchedClassTable; } + /// Return true if this machine model data for all instructions with a + /// scheduling class (itinerary class or SchedRW list). + bool isComplete() const { return CompleteModel; } + unsigned getNumProcResourceKinds() const { return NumProcResourceKinds; } diff --git a/contrib/llvm/include/llvm/MC/MCSectionCOFF.h b/contrib/llvm/include/llvm/MC/MCSectionCOFF.h index 50e33a5b0..45c84ae71 100644 --- a/contrib/llvm/include/llvm/MC/MCSectionCOFF.h +++ b/contrib/llvm/include/llvm/MC/MCSectionCOFF.h @@ -19,28 +19,47 @@ #include "llvm/Support/COFF.h" namespace llvm { +class MCSymbol; /// MCSectionCOFF - This represents a section on Windows class MCSectionCOFF : public MCSection { // The memory for this string is stored in the same MCContext as *this. StringRef SectionName; + // FIXME: The following fields should not be mutable, but are for now so + // the asm parser can honor the .linkonce directive. + /// Characteristics - This is the Characteristics field of a section, - // drawn from the enums below. - unsigned Characteristics; + /// drawn from the enums below. + mutable unsigned Characteristics; + + /// The COMDAT symbol of this section. Only valid if this is a COMDAT + /// section. Two COMDAT sections are merged if they have the same + /// COMDAT symbol. + const MCSymbol *COMDATSymbol; /// Selection - This is the Selection field for the section symbol, if /// it is a COMDAT section (Characteristics & IMAGE_SCN_LNK_COMDAT) != 0 - int Selection; + mutable int Selection; + + /// Assoc - This is name of the associated section, if it is a COMDAT + /// section (Characteristics & IMAGE_SCN_LNK_COMDAT) != 0 with an + /// associative Selection (IMAGE_COMDAT_SELECT_ASSOCIATIVE). + mutable const MCSectionCOFF *Assoc; private: friend class MCContext; MCSectionCOFF(StringRef Section, unsigned Characteristics, - int Selection, SectionKind K) - : MCSection(SV_COFF, K), SectionName(Section), - Characteristics(Characteristics), Selection (Selection) { + const MCSymbol *COMDATSymbol, int Selection, + const MCSectionCOFF *Assoc, SectionKind K) + : MCSection(SV_COFF, K), SectionName(Section), + Characteristics(Characteristics), COMDATSymbol(COMDATSymbol), + Selection(Selection), Assoc(Assoc) { assert ((Characteristics & 0x00F00000) == 0 && "alignment must not be set upon section creation"); + assert ((Selection == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) == + (Assoc != 0) && + "associative COMDAT section must have an associated section"); } ~MCSectionCOFF(); @@ -57,7 +76,10 @@ namespace llvm { return SectionName.str() + "_end"; } unsigned getCharacteristics() const { return Characteristics; } - int getSelection () const { return Selection; } + int getSelection() const { return Selection; } + const MCSectionCOFF *getAssocSection() const { return Assoc; } + + void setSelection(int Selection, const MCSectionCOFF *Assoc = 0) const; virtual void PrintSwitchToSection(const MCAsmInfo &MAI, raw_ostream &OS, diff --git a/contrib/llvm/include/llvm/MC/MCSectionMachO.h b/contrib/llvm/include/llvm/MC/MCSectionMachO.h index b68bd8596..d7e88ea56 100644 --- a/contrib/llvm/include/llvm/MC/MCSectionMachO.h +++ b/contrib/llvm/include/llvm/MC/MCSectionMachO.h @@ -41,7 +41,7 @@ public: /// These are the section type and attributes fields. A MachO section can /// have only one Type, but can have any of the attributes specified. - enum { + enum LLVM_ENUM_INT_TYPE(uint32_t) { // TypeAndAttributes bitmasks. SECTION_TYPE = 0x000000FFU, SECTION_ATTRIBUTES = 0xFFFFFF00U, diff --git a/contrib/llvm/include/llvm/MC/MCStreamer.h b/contrib/llvm/include/llvm/MC/MCStreamer.h index 2cab481c3..0b1fe6ec0 100644 --- a/contrib/llvm/include/llvm/MC/MCStreamer.h +++ b/contrib/llvm/include/llvm/MC/MCStreamer.h @@ -24,683 +24,716 @@ #include namespace llvm { - class MCAsmBackend; - class MCCodeEmitter; - class MCContext; - class MCExpr; - class MCInst; - class MCInstPrinter; - class MCSection; - class MCSymbol; - class StringRef; - class Twine; - class raw_ostream; - class formatted_raw_ostream; - - typedef std::pair MCSectionSubPair; - - /// MCStreamer - Streaming machine code generation interface. This interface - /// is intended to provide a programatic interface that is very similar to the - /// level that an assembler .s file provides. It has callbacks to emit bytes, - /// handle directives, etc. The implementation of this interface retains - /// state to know what the current section is etc. - /// - /// There are multiple implementations of this interface: one for writing out - /// a .s file, and implementations that write out .o files of various formats. - /// - class MCStreamer { - public: - enum StreamerKind { - SK_AsmStreamer, - SK_NullStreamer, - SK_RecordStreamer, - - // MCObjectStreamer subclasses. - SK_ELFStreamer, - SK_ARMELFStreamer, - SK_MachOStreamer, - SK_PureStreamer, - SK_MipsELFStreamer, - SK_WinCOFFStreamer - }; - - private: - const StreamerKind Kind; - MCContext &Context; - - MCStreamer(const MCStreamer&) LLVM_DELETED_FUNCTION; - MCStreamer &operator=(const MCStreamer&) LLVM_DELETED_FUNCTION; - - bool EmitEHFrame; - bool EmitDebugFrame; - - std::vector FrameInfos; - MCDwarfFrameInfo *getCurrentFrameInfo(); - MCSymbol *EmitCFICommon(); - void EnsureValidFrame(); - - std::vector W64UnwindInfos; - MCWin64EHUnwindInfo *CurrentW64UnwindInfo; - void setCurrentW64UnwindInfo(MCWin64EHUnwindInfo *Frame); - void EnsureValidW64UnwindInfo(); - - MCSymbol* LastSymbol; - - /// SectionStack - This is stack of current and previous section - /// values saved by PushSection. - SmallVector, 4> SectionStack; - - bool AutoInitSections; - - protected: - MCStreamer(StreamerKind Kind, MCContext &Ctx); - - const MCExpr *BuildSymbolDiff(MCContext &Context, const MCSymbol *A, - const MCSymbol *B); - - const MCExpr *ForceExpAbs(const MCExpr* Expr); - - void RecordProcStart(MCDwarfFrameInfo &Frame); - virtual void EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame); - void RecordProcEnd(MCDwarfFrameInfo &Frame); - virtual void EmitCFIEndProcImpl(MCDwarfFrameInfo &CurFrame); - void EmitFrames(bool usingCFI); - - MCWin64EHUnwindInfo *getCurrentW64UnwindInfo(){return CurrentW64UnwindInfo;} - void EmitW64Tables(); - - public: - virtual ~MCStreamer(); - - StreamerKind getKind() const { return Kind; } - - /// State management - /// - virtual void reset(); - - MCContext &getContext() const { return Context; } - - unsigned getNumFrameInfos() { - return FrameInfos.size(); - } +class MCAsmBackend; +class MCCodeEmitter; +class MCContext; +class MCExpr; +class MCInst; +class MCInstPrinter; +class MCSection; +class MCStreamer; +class MCSymbol; +class StringRef; +class Twine; +class raw_ostream; +class formatted_raw_ostream; + +typedef std::pair MCSectionSubPair; + +/// Target specific streamer interface. This is used so that targets can +/// implement support for target specific assembly directives. +/// +/// If target foo wants to use this, it should implement 3 classes: +/// * FooTargetStreamer : public MCTargetStreamer +/// * FooTargetAsmSreamer : 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 +/// method. The assembly streamer just prints ".bar symbol_name". The object +/// streamer does whatever is needed to implement .bar in the object file. +/// +/// In the assembly printer and parser the target streamer can be used by +/// calling getTargetStreamer and casting it to FooTargetStreamer: +/// +/// 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. +class MCTargetStreamer { +protected: + MCStreamer *Streamer; + +public: + virtual ~MCTargetStreamer(); + void setStreamer(MCStreamer *S) { Streamer = S; } +}; + +// FIXME: declared here because it is used from +// lib/CodeGen/AsmPrinter/ARMException.cpp. +class ARMTargetStreamer : public MCTargetStreamer { + virtual void anchor(); +public: + virtual void emitFnStart() = 0; + virtual void emitFnEnd() = 0; + virtual void emitCantUnwind() = 0; + virtual void emitPersonality(const MCSymbol *Personality) = 0; + virtual void emitHandlerData() = 0; + virtual void emitSetFP(unsigned FpReg, unsigned SpReg, + int64_t Offset = 0) = 0; + virtual void emitPad(int64_t Offset) = 0; + virtual void emitRegSave(const SmallVectorImpl &RegList, + bool isVector) = 0; + + virtual void switchVendor(StringRef Vendor) = 0; + virtual void emitAttribute(unsigned Attribute, unsigned Value) = 0; + virtual void emitTextAttribute(unsigned Attribute, StringRef String) = 0; + virtual void emitFPU(unsigned FPU) = 0; + virtual void finishAttributeSection() = 0; +}; + +/// MCStreamer - Streaming machine code generation interface. This interface +/// is intended to provide a programatic interface that is very similar to the +/// level that an assembler .s file provides. It has callbacks to emit bytes, +/// handle directives, etc. The implementation of this interface retains +/// state to know what the current section is etc. +/// +/// There are multiple implementations of this interface: one for writing out +/// a .s file, and implementations that write out .o files of various formats. +/// +class MCStreamer { + MCContext &Context; + OwningPtr TargetStreamer; + + MCStreamer(const MCStreamer &) LLVM_DELETED_FUNCTION; + MCStreamer &operator=(const MCStreamer &) LLVM_DELETED_FUNCTION; + + bool EmitEHFrame; + bool EmitDebugFrame; + + std::vector FrameInfos; + MCDwarfFrameInfo *getCurrentFrameInfo(); + MCSymbol *EmitCFICommon(); + void EnsureValidFrame(); + + std::vector W64UnwindInfos; + MCWin64EHUnwindInfo *CurrentW64UnwindInfo; + void setCurrentW64UnwindInfo(MCWin64EHUnwindInfo *Frame); + void EnsureValidW64UnwindInfo(); + + MCSymbol *LastSymbol; + + // SymbolOrdering - Tracks an index to represent the order + // a symbol was emitted in. Zero means we did not emit that symbol. + DenseMap SymbolOrdering; + + /// SectionStack - This is stack of current and previous section + /// values saved by PushSection. + SmallVector, 4> SectionStack; + + bool AutoInitSections; + +protected: + MCStreamer(MCContext &Ctx, MCTargetStreamer *TargetStreamer); + + const MCExpr *BuildSymbolDiff(MCContext &Context, const MCSymbol *A, + const MCSymbol *B); + + const MCExpr *ForceExpAbs(const MCExpr *Expr); + + void RecordProcStart(MCDwarfFrameInfo &Frame); + virtual void EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame); + void RecordProcEnd(MCDwarfFrameInfo &Frame); + virtual void EmitCFIEndProcImpl(MCDwarfFrameInfo &CurFrame); + void EmitFrames(MCAsmBackend *MAB, bool usingCFI); + + MCWin64EHUnwindInfo *getCurrentW64UnwindInfo() { + return CurrentW64UnwindInfo; + } + void EmitW64Tables(); + + virtual void EmitRawTextImpl(StringRef String); + +public: + virtual ~MCStreamer(); + + /// State management + /// + virtual void reset(); - const MCDwarfFrameInfo &getFrameInfo(unsigned i) { - return FrameInfos[i]; - } + MCContext &getContext() const { return Context; } - ArrayRef getFrameInfos() { - return FrameInfos; - } + MCTargetStreamer &getTargetStreamer() { + assert(TargetStreamer); + return *TargetStreamer; + } - unsigned getNumW64UnwindInfos() { - return W64UnwindInfos.size(); - } + unsigned getNumFrameInfos() { return FrameInfos.size(); } - MCWin64EHUnwindInfo &getW64UnwindInfo(unsigned i) { - return *W64UnwindInfos[i]; - } + const MCDwarfFrameInfo &getFrameInfo(unsigned i) { return FrameInfos[i]; } - /// @name Assembly File Formatting. - /// @{ - - /// isVerboseAsm - Return true if this streamer supports verbose assembly - /// and if it is enabled. - virtual bool isVerboseAsm() const { return false; } - - /// hasRawTextSupport - Return true if this asm streamer supports emitting - /// unformatted text to the .s file with EmitRawText. - virtual bool hasRawTextSupport() const { return false; } - - /// AddComment - Add a comment that can be emitted to the generated .s - /// file if applicable as a QoI issue to make the output of the compiler - /// more readable. This only affects the MCAsmStreamer, and only when - /// verbose assembly output is enabled. - /// - /// If the comment includes embedded \n's, they will each get the comment - /// prefix as appropriate. The added comment should not end with a \n. - virtual void AddComment(const Twine &T) {} - - /// GetCommentOS - Return a raw_ostream that comments can be written to. - /// Unlike AddComment, you are required to terminate comments with \n if you - /// use this method. - virtual raw_ostream &GetCommentOS(); - - /// AddBlankLine - Emit a blank line to a .s file to pretty it up. - virtual void AddBlankLine() {} - - /// @} - - /// @name Symbol & Section Management - /// @{ - - /// getCurrentSection - Return the current section that the streamer is - /// emitting code to. - MCSectionSubPair getCurrentSection() const { - if (!SectionStack.empty()) - return SectionStack.back().first; - return MCSectionSubPair(); - } + ArrayRef getFrameInfos() const { return FrameInfos; } - /// getPreviousSection - Return the previous section that the streamer is - /// emitting code to. - MCSectionSubPair getPreviousSection() const { - if (!SectionStack.empty()) - return SectionStack.back().second; - return MCSectionSubPair(); - } + unsigned getNumW64UnwindInfos() { return W64UnwindInfos.size(); } - /// ChangeSection - Update streamer for a new active section. - /// - /// This is called by PopSection and SwitchSection, if the current - /// section changes. - virtual void ChangeSection(const MCSection *, const MCExpr *) = 0; - - /// pushSection - Save the current and previous section on the - /// section stack. - void PushSection() { - SectionStack.push_back(std::make_pair(getCurrentSection(), - getPreviousSection())); - } + MCWin64EHUnwindInfo &getW64UnwindInfo(unsigned i) { + return *W64UnwindInfos[i]; + } - /// popSection - Restore the current and previous section from - /// the section stack. Calls ChangeSection as needed. - /// - /// Returns false if the stack was empty. - bool PopSection() { - if (SectionStack.size() <= 1) - return false; - MCSectionSubPair oldSection = SectionStack.pop_back_val().first; - MCSectionSubPair curSection = SectionStack.back().first; - - if (oldSection != curSection) - ChangeSection(curSection.first, curSection.second); - return true; - } + void generateCompactUnwindEncodings(MCAsmBackend *MAB); - bool SubSection(const MCExpr *Subsection) { - if (SectionStack.empty()) - return false; + /// @name Assembly File Formatting. + /// @{ - SwitchSection(SectionStack.back().first.first, Subsection); - return true; - } + /// isVerboseAsm - Return true if this streamer supports verbose assembly + /// and if it is enabled. + virtual bool isVerboseAsm() const { return false; } - /// SwitchSection - Set the current section where code is being emitted to - /// @p Section. This is required to update CurSection. - /// - /// This corresponds to assembler directives like .section, .text, etc. - void SwitchSection(const MCSection *Section, const MCExpr *Subsection = 0) { - assert(Section && "Cannot switch to a null section!"); - MCSectionSubPair curSection = SectionStack.back().first; - SectionStack.back().second = curSection; - if (MCSectionSubPair(Section, Subsection) != curSection) { - SectionStack.back().first = MCSectionSubPair(Section, Subsection); - ChangeSection(Section, Subsection); - } - } + /// hasRawTextSupport - Return true if this asm streamer supports emitting + /// unformatted text to the .s file with EmitRawText. + virtual bool hasRawTextSupport() const { return false; } - /// SwitchSectionNoChange - Set the current section where code is being - /// emitted to @p Section. This is required to update CurSection. This - /// version does not call ChangeSection. - void SwitchSectionNoChange(const MCSection *Section, - const MCExpr *Subsection = 0) { - assert(Section && "Cannot switch to a null section!"); - MCSectionSubPair curSection = SectionStack.back().first; - SectionStack.back().second = curSection; - if (MCSectionSubPair(Section, Subsection) != curSection) - SectionStack.back().first = MCSectionSubPair(Section, Subsection); + /// AddComment - Add a comment that can be emitted to the generated .s + /// file if applicable as a QoI issue to make the output of the compiler + /// more readable. This only affects the MCAsmStreamer, and only when + /// verbose assembly output is enabled. + /// + /// If the comment includes embedded \n's, they will each get the comment + /// prefix as appropriate. The added comment should not end with a \n. + virtual void AddComment(const Twine &T) {} + + /// GetCommentOS - Return a raw_ostream that comments can be written to. + /// Unlike AddComment, you are required to terminate comments with \n if you + /// use this method. + virtual raw_ostream &GetCommentOS(); + + /// AddBlankLine - Emit a blank line to a .s file to pretty it up. + virtual void AddBlankLine() {} + + /// @} + + /// @name Symbol & Section Management + /// @{ + + /// getCurrentSection - Return the current section that the streamer is + /// emitting code to. + MCSectionSubPair getCurrentSection() const { + if (!SectionStack.empty()) + return SectionStack.back().first; + return MCSectionSubPair(); + } + + /// getPreviousSection - Return the previous section that the streamer is + /// emitting code to. + MCSectionSubPair getPreviousSection() const { + if (!SectionStack.empty()) + return SectionStack.back().second; + return MCSectionSubPair(); + } + + /// GetSymbolOrder - Returns an index to represent the order + /// a symbol was emitted in. (zero if we did not emit that symbol) + unsigned GetSymbolOrder(const MCSymbol *Sym) const { + return SymbolOrdering.lookup(Sym); + } + + /// ChangeSection - Update streamer for a new active section. + /// + /// This is called by PopSection and SwitchSection, if the current + /// section changes. + virtual void ChangeSection(const MCSection *, const MCExpr *) = 0; + + /// pushSection - Save the current and previous section on the + /// section stack. + void PushSection() { + SectionStack.push_back( + std::make_pair(getCurrentSection(), getPreviousSection())); + } + + /// popSection - Restore the current and previous section from + /// the section stack. Calls ChangeSection as needed. + /// + /// Returns false if the stack was empty. + bool PopSection() { + if (SectionStack.size() <= 1) + return false; + MCSectionSubPair oldSection = SectionStack.pop_back_val().first; + MCSectionSubPair curSection = SectionStack.back().first; + + if (oldSection != curSection) + ChangeSection(curSection.first, curSection.second); + return true; + } + + bool SubSection(const MCExpr *Subsection) { + if (SectionStack.empty()) + return false; + + SwitchSection(SectionStack.back().first.first, Subsection); + return true; + } + + /// SwitchSection - Set the current section where code is being emitted to + /// @p Section. This is required to update CurSection. + /// + /// This corresponds to assembler directives like .section, .text, etc. + void SwitchSection(const MCSection *Section, const MCExpr *Subsection = 0) { + assert(Section && "Cannot switch to a null section!"); + MCSectionSubPair curSection = SectionStack.back().first; + SectionStack.back().second = curSection; + if (MCSectionSubPair(Section, Subsection) != curSection) { + SectionStack.back().first = MCSectionSubPair(Section, Subsection); + ChangeSection(Section, Subsection); } + } + + /// SwitchSectionNoChange - Set the current section where code is being + /// emitted to @p Section. This is required to update CurSection. This + /// version does not call ChangeSection. + void SwitchSectionNoChange(const MCSection *Section, + const MCExpr *Subsection = 0) { + assert(Section && "Cannot switch to a null section!"); + MCSectionSubPair curSection = SectionStack.back().first; + SectionStack.back().second = curSection; + if (MCSectionSubPair(Section, Subsection) != curSection) + SectionStack.back().first = MCSectionSubPair(Section, Subsection); + } + + /// Initialize the streamer. + void InitStreamer() { + if (AutoInitSections) + InitSections(); + } + + /// Tell this MCStreamer to call InitSections upon initialization. + void setAutoInitSections(bool AutoInitSections) { + this->AutoInitSections = AutoInitSections; + } + + /// InitSections - Create the default sections and set the initial one. + virtual void InitSections() = 0; + + /// InitToTextSection - Create a text section and switch the streamer to it. + virtual void InitToTextSection() = 0; + + /// AssignSection - Sets the symbol's section. + /// + /// Each emitted symbol will be tracked in the ordering table, + /// so we can sort on them later. + void AssignSection(MCSymbol *Symbol, const MCSection *Section); - /// Initialize the streamer. - void InitStreamer() { - if (AutoInitSections) - InitSections(); - } + /// EmitLabel - Emit a label for @p Symbol into the current section. + /// + /// This corresponds to an assembler statement such as: + /// foo: + /// + /// @param Symbol - The symbol to emit. A given symbol should only be + /// emitted as a label once, and symbols emitted as a label should never be + /// used in an assignment. + virtual void EmitLabel(MCSymbol *Symbol); - /// Tell this MCStreamer to call InitSections upon initialization. - void setAutoInitSections(bool AutoInitSections) { - this->AutoInitSections = AutoInitSections; - } + virtual void EmitDebugLabel(MCSymbol *Symbol); - /// InitSections - Create the default sections and set the initial one. - virtual void InitSections() = 0; - - /// InitToTextSection - Create a text section and switch the streamer to it. - virtual void InitToTextSection() = 0; - - /// EmitLabel - Emit a label for @p Symbol into the current section. - /// - /// This corresponds to an assembler statement such as: - /// foo: - /// - /// @param Symbol - The symbol to emit. A given symbol should only be - /// emitted as a label once, and symbols emitted as a label should never be - /// used in an assignment. - virtual void EmitLabel(MCSymbol *Symbol); - - virtual void EmitDebugLabel(MCSymbol *Symbol); - - virtual void EmitEHSymAttributes(const MCSymbol *Symbol, - MCSymbol *EHSymbol); - - /// EmitAssemblerFlag - Note in the output the specified @p Flag. - virtual void EmitAssemblerFlag(MCAssemblerFlag Flag) = 0; - - /// EmitLinkerOptions - Emit the given list @p Options of strings as linker - /// options into the output. - virtual void EmitLinkerOptions(ArrayRef Kind) {} - - /// EmitDataRegion - Note in the output the specified region @p Kind. - virtual void EmitDataRegion(MCDataRegionType Kind) {} - - /// EmitThumbFunc - Note in the output that the specified @p Func is - /// a Thumb mode function (ARM target only). - virtual void EmitThumbFunc(MCSymbol *Func) = 0; - - /// getOrCreateSymbolData - Get symbol data for given symbol. - virtual MCSymbolData &getOrCreateSymbolData(MCSymbol *Symbol); - - /// EmitAssignment - Emit an assignment of @p Value to @p Symbol. - /// - /// This corresponds to an assembler statement such as: - /// symbol = value - /// - /// The assignment generates no code, but has the side effect of binding the - /// value in the current context. For the assembly streamer, this prints the - /// binding into the .s file. - /// - /// @param Symbol - The symbol being assigned to. - /// @param Value - The value for the symbol. - virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) = 0; - - /// EmitWeakReference - Emit an weak reference from @p Alias to @p Symbol. - /// - /// This corresponds to an assembler statement such as: - /// .weakref alias, symbol - /// - /// @param Alias - The alias that is being created. - /// @param Symbol - The symbol being aliased. - virtual void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) = 0; - - /// EmitSymbolAttribute - Add the given @p Attribute to @p Symbol. - virtual void EmitSymbolAttribute(MCSymbol *Symbol, - MCSymbolAttr Attribute) = 0; - - /// EmitSymbolDesc - Set the @p DescValue for the @p Symbol. - /// - /// @param Symbol - The symbol to have its n_desc field set. - /// @param DescValue - The value to set into the n_desc field. - virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) = 0; - - /// BeginCOFFSymbolDef - Start emitting COFF symbol definition - /// - /// @param Symbol - The symbol to have its External & Type fields set. - virtual void BeginCOFFSymbolDef(const MCSymbol *Symbol) = 0; - - /// EmitCOFFSymbolStorageClass - Emit the storage class of the symbol. - /// - /// @param StorageClass - The storage class the symbol should have. - virtual void EmitCOFFSymbolStorageClass(int StorageClass) = 0; - - /// EmitCOFFSymbolType - Emit the type of the symbol. - /// - /// @param Type - A COFF type identifier (see COFF::SymbolType in X86COFF.h) - virtual void EmitCOFFSymbolType(int Type) = 0; - - /// EndCOFFSymbolDef - Marks the end of the symbol definition. - virtual void EndCOFFSymbolDef() = 0; - - /// EmitCOFFSecRel32 - Emits a COFF section relative relocation. - /// - /// @param Symbol - Symbol the section relative realocation should point to. - virtual void EmitCOFFSecRel32(MCSymbol const *Symbol); - - /// EmitELFSize - Emit an ELF .size directive. - /// - /// This corresponds to an assembler statement such as: - /// .size symbol, expression - /// - virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) = 0; - - /// EmitCommonSymbol - Emit a common symbol. - /// - /// @param Symbol - The common symbol to emit. - /// @param Size - The size of the common symbol. - /// @param ByteAlignment - The alignment of the symbol if - /// non-zero. This must be a power of 2. - virtual void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, - unsigned ByteAlignment) = 0; - - /// EmitLocalCommonSymbol - Emit a local common (.lcomm) symbol. - /// - /// @param Symbol - The common symbol to emit. - /// @param Size - The size of the common symbol. - /// @param ByteAlignment - The alignment of the common symbol in bytes. - virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, - unsigned ByteAlignment) = 0; - - /// EmitZerofill - Emit the zerofill section and an optional symbol. - /// - /// @param Section - The zerofill section to create and or to put the symbol - /// @param Symbol - The zerofill symbol to emit, if non-NULL. - /// @param Size - The size of the zerofill symbol. - /// @param ByteAlignment - The alignment of the zerofill symbol if - /// non-zero. This must be a power of 2 on some targets. - virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = 0, - uint64_t Size = 0,unsigned ByteAlignment = 0) = 0; - - /// EmitTBSSSymbol - Emit a thread local bss (.tbss) symbol. - /// - /// @param Section - The thread local common section. - /// @param Symbol - The thread local common symbol to emit. - /// @param Size - The size of the symbol. - /// @param ByteAlignment - The alignment of the thread local common symbol - /// if non-zero. This must be a power of 2 on some targets. - virtual void EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol, - uint64_t Size, unsigned ByteAlignment = 0) = 0; - - /// @} - /// @name Generating Data - /// @{ - - /// EmitBytes - Emit the bytes in \p Data into the output. - /// - /// This is used to implement assembler directives such as .byte, .ascii, - /// etc. - virtual void EmitBytes(StringRef Data, unsigned AddrSpace = 0) = 0; - - /// EmitValue - Emit the expression @p Value into the output as a native - /// integer of the given @p Size bytes. - /// - /// This is used to implement assembler directives such as .word, .quad, - /// etc. - /// - /// @param Value - The value to emit. - /// @param Size - The size of the integer (in bytes) to emit. This must - /// match a native machine width. - virtual void EmitValueImpl(const MCExpr *Value, unsigned Size, - unsigned AddrSpace) = 0; - - void EmitValue(const MCExpr *Value, unsigned Size, unsigned AddrSpace = 0); - - /// EmitIntValue - Special case of EmitValue that avoids the client having - /// to pass in a MCExpr for constant integers. - virtual void EmitIntValue(uint64_t Value, unsigned Size, - unsigned AddrSpace = 0); - - /// EmitAbsValue - Emit the Value, but try to avoid relocations. On MachO - /// this is done by producing - /// foo = value - /// .long foo - void EmitAbsValue(const MCExpr *Value, unsigned Size, - unsigned AddrSpace = 0); - - virtual void EmitULEB128Value(const MCExpr *Value) = 0; - - virtual void EmitSLEB128Value(const MCExpr *Value) = 0; - - /// EmitULEB128Value - Special case of EmitULEB128Value that avoids the - /// client having to pass in a MCExpr for constant integers. - void EmitULEB128IntValue(uint64_t Value, unsigned Padding = 0, - unsigned AddrSpace = 0); - - /// EmitSLEB128Value - Special case of EmitSLEB128Value that avoids the - /// client having to pass in a MCExpr for constant integers. - void EmitSLEB128IntValue(int64_t Value, unsigned AddrSpace = 0); - - /// EmitSymbolValue - Special case of EmitValue that avoids the client - /// having to pass in a MCExpr for MCSymbols. - void EmitSymbolValue(const MCSymbol *Sym, unsigned Size, - unsigned AddrSpace = 0); - - /// EmitGPRel64Value - Emit the expression @p Value into the output as a - /// gprel64 (64-bit GP relative) value. - /// - /// This is used to implement assembler directives such as .gpdword on - /// targets that support them. - virtual void EmitGPRel64Value(const MCExpr *Value); - - /// EmitGPRel32Value - Emit the expression @p Value into the output as a - /// gprel32 (32-bit GP relative) value. - /// - /// This is used to implement assembler directives such as .gprel32 on - /// targets that support them. - virtual void EmitGPRel32Value(const MCExpr *Value); - - /// EmitFill - Emit NumBytes bytes worth of the value specified by - /// FillValue. This implements directives such as '.space'. - virtual void EmitFill(uint64_t NumBytes, uint8_t FillValue, - unsigned AddrSpace = 0); - - /// EmitZeros - Emit NumBytes worth of zeros. This is a convenience - /// function that just wraps EmitFill. - void EmitZeros(uint64_t NumBytes, unsigned AddrSpace = 0) { - EmitFill(NumBytes, 0, AddrSpace); - } + virtual void EmitEHSymAttributes(const MCSymbol *Symbol, MCSymbol *EHSymbol); - /// EmitValueToAlignment - Emit some number of copies of @p Value until - /// the byte alignment @p ByteAlignment is reached. - /// - /// If the number of bytes need to emit for the alignment is not a multiple - /// of @p ValueSize, then the contents of the emitted fill bytes is - /// undefined. - /// - /// This used to implement the .align assembler directive. - /// - /// @param ByteAlignment - The alignment to reach. This must be a power of - /// two on some targets. - /// @param Value - The value to use when filling bytes. - /// @param ValueSize - The size of the integer (in bytes) to emit for - /// @p Value. This must match a native machine width. - /// @param MaxBytesToEmit - The maximum numbers of bytes to emit, or 0. If - /// the alignment cannot be reached in this many bytes, no bytes are - /// emitted. - virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0, - unsigned ValueSize = 1, - unsigned MaxBytesToEmit = 0) = 0; - - /// EmitCodeAlignment - Emit nops until the byte alignment @p ByteAlignment - /// is reached. - /// - /// This used to align code where the alignment bytes may be executed. This - /// can emit different bytes for different sizes to optimize execution. - /// - /// @param ByteAlignment - The alignment to reach. This must be a power of - /// two on some targets. - /// @param MaxBytesToEmit - The maximum numbers of bytes to emit, or 0. If - /// the alignment cannot be reached in this many bytes, no bytes are - /// emitted. - virtual void EmitCodeAlignment(unsigned ByteAlignment, - unsigned MaxBytesToEmit = 0) = 0; - - /// EmitValueToOffset - Emit some number of copies of @p Value until the - /// byte offset @p Offset is reached. - /// - /// This is used to implement assembler directives such as .org. - /// - /// @param Offset - The offset to reach. This may be an expression, but the - /// expression must be associated with the current section. - /// @param Value - The value to use when filling bytes. - /// @return false on success, true if the offset was invalid. - virtual bool EmitValueToOffset(const MCExpr *Offset, - unsigned char Value = 0) = 0; - - /// @} - - /// EmitFileDirective - Switch to a new logical file. This is used to - /// implement the '.file "foo.c"' assembler directive. - virtual void EmitFileDirective(StringRef Filename) = 0; - - /// EmitDwarfFileDirective - Associate a filename with a specified logical - /// file number. This implements the DWARF2 '.file 4 "foo.c"' assembler - /// directive. - virtual bool EmitDwarfFileDirective(unsigned FileNo, StringRef Directory, - StringRef Filename, unsigned CUID = 0); - - /// EmitDwarfLocDirective - This implements the DWARF2 - // '.loc fileno lineno ...' assembler directive. - virtual void EmitDwarfLocDirective(unsigned FileNo, unsigned Line, - unsigned Column, unsigned Flags, - unsigned Isa, - unsigned Discriminator, - StringRef FileName); - - virtual void EmitDwarfAdvanceLineAddr(int64_t LineDelta, - const MCSymbol *LastLabel, - const MCSymbol *Label, - unsigned PointerSize) = 0; - - virtual void EmitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel, - const MCSymbol *Label) { - } + /// EmitAssemblerFlag - Note in the output the specified @p Flag. + virtual void EmitAssemblerFlag(MCAssemblerFlag Flag) = 0; - void EmitDwarfSetLineAddr(int64_t LineDelta, const MCSymbol *Label, - int PointerSize); - - virtual void EmitCompactUnwindEncoding(uint32_t CompactUnwindEncoding); - virtual void EmitCFISections(bool EH, bool Debug); - void EmitCFIStartProc(); - void EmitCFIEndProc(); - virtual void EmitCFIDefCfa(int64_t Register, int64_t Offset); - virtual void EmitCFIDefCfaOffset(int64_t Offset); - virtual void EmitCFIDefCfaRegister(int64_t Register); - virtual void EmitCFIOffset(int64_t Register, int64_t Offset); - virtual void EmitCFIPersonality(const MCSymbol *Sym, unsigned Encoding); - virtual void EmitCFILsda(const MCSymbol *Sym, unsigned Encoding); - virtual void EmitCFIRememberState(); - virtual void EmitCFIRestoreState(); - virtual void EmitCFISameValue(int64_t Register); - virtual void EmitCFIRestore(int64_t Register); - virtual void EmitCFIRelOffset(int64_t Register, int64_t Offset); - virtual void EmitCFIAdjustCfaOffset(int64_t Adjustment); - virtual void EmitCFIEscape(StringRef Values); - virtual void EmitCFISignalFrame(); - virtual void EmitCFIUndefined(int64_t Register); - virtual void EmitCFIRegister(int64_t Register1, int64_t Register2); - - virtual void EmitWin64EHStartProc(const MCSymbol *Symbol); - virtual void EmitWin64EHEndProc(); - virtual void EmitWin64EHStartChained(); - virtual void EmitWin64EHEndChained(); - virtual void EmitWin64EHHandler(const MCSymbol *Sym, bool Unwind, - bool Except); - virtual void EmitWin64EHHandlerData(); - virtual void EmitWin64EHPushReg(unsigned Register); - virtual void EmitWin64EHSetFrame(unsigned Register, unsigned Offset); - virtual void EmitWin64EHAllocStack(unsigned Size); - virtual void EmitWin64EHSaveReg(unsigned Register, unsigned Offset); - virtual void EmitWin64EHSaveXMM(unsigned Register, unsigned Offset); - virtual void EmitWin64EHPushFrame(bool Code); - virtual void EmitWin64EHEndProlog(); - - /// EmitInstruction - Emit the given @p Instruction into the current - /// section. - virtual void EmitInstruction(const MCInst &Inst) = 0; - - /// \brief Set the bundle alignment mode from now on in the section. - /// The argument is the power of 2 to which the alignment is set. The - /// value 0 means turn the bundle alignment off. - virtual void EmitBundleAlignMode(unsigned AlignPow2) = 0; - - /// \brief The following instructions are a bundle-locked group. - /// - /// \param AlignToEnd - If true, the bundle-locked group will be aligned to - /// the end of a bundle. - virtual void EmitBundleLock(bool AlignToEnd) = 0; - - /// \brief Ends a bundle-locked group. - virtual void EmitBundleUnlock() = 0; - - /// EmitRawText - If this file is backed by a assembly streamer, this dumps - /// the specified string in the output .s file. This capability is - /// indicated by the hasRawTextSupport() predicate. By default this aborts. - virtual void EmitRawText(StringRef String); - void EmitRawText(const Twine &String); - - /// ARM-related methods. - /// FIXME: Eventually we should have some "target MC streamer" and move - /// these methods there. - virtual void EmitFnStart(); - virtual void EmitFnEnd(); - virtual void EmitCantUnwind(); - virtual void EmitPersonality(const MCSymbol *Personality); - virtual void EmitHandlerData(); - virtual void EmitSetFP(unsigned FpReg, unsigned SpReg, int64_t Offset = 0); - virtual void EmitPad(int64_t Offset); - virtual void EmitRegSave(const SmallVectorImpl &RegList, - bool isVector); - - /// PPC-related methods. - /// FIXME: Eventually replace it with some "target MC streamer" and move - /// these methods there. - virtual void EmitTCEntry(const MCSymbol &S); - - /// FinishImpl - Streamer specific finalization. - virtual void FinishImpl() = 0; - /// Finish - Finish emission of machine code. - void Finish(); - }; - - /// createNullStreamer - Create a dummy machine code streamer, which does - /// nothing. This is useful for timing the assembler front end. - MCStreamer *createNullStreamer(MCContext &Ctx); - - /// createAsmStreamer - Create a machine code streamer which will print out - /// assembly for the native target, suitable for compiling with a native - /// assembler. - /// - /// \param InstPrint - If given, the instruction printer to use. If not given - /// the MCInst representation will be printed. This method takes ownership of - /// InstPrint. - /// - /// \param CE - If given, a code emitter to use to show the instruction - /// encoding inline with the assembly. This method takes ownership of \p CE. - /// - /// \param TAB - If given, a target asm backend to use to show the fixup - /// information in conjunction with encoding information. This method takes - /// ownership of \p TAB. - /// - /// \param ShowInst - Whether to show the MCInst representation inline with - /// the assembly. - MCStreamer *createAsmStreamer(MCContext &Ctx, formatted_raw_ostream &OS, - bool isVerboseAsm, - bool useLoc, - bool useCFI, - bool useDwarfDirectory, - MCInstPrinter *InstPrint = 0, - MCCodeEmitter *CE = 0, - MCAsmBackend *TAB = 0, - bool ShowInst = false); - - /// createMachOStreamer - Create a machine code streamer which will generate - /// Mach-O format object files. - /// - /// Takes ownership of \p TAB and \p CE. - MCStreamer *createMachOStreamer(MCContext &Ctx, MCAsmBackend &TAB, - raw_ostream &OS, MCCodeEmitter *CE, - bool RelaxAll = false); + /// EmitLinkerOptions - Emit the given list @p Options of strings as linker + /// options into the output. + virtual void EmitLinkerOptions(ArrayRef Kind) {} + + /// EmitDataRegion - Note in the output the specified region @p Kind. + virtual void EmitDataRegion(MCDataRegionType Kind) {} + + /// EmitThumbFunc - Note in the output that the specified @p Func is + /// a Thumb mode function (ARM target only). + virtual void EmitThumbFunc(MCSymbol *Func) = 0; - /// createWinCOFFStreamer - Create a machine code streamer which will - /// generate Microsoft COFF format object files. + /// getOrCreateSymbolData - Get symbol data for given symbol. + virtual MCSymbolData &getOrCreateSymbolData(MCSymbol *Symbol); + + /// EmitAssignment - Emit an assignment of @p Value to @p Symbol. + /// + /// This corresponds to an assembler statement such as: + /// symbol = value + /// + /// The assignment generates no code, but has the side effect of binding the + /// value in the current context. For the assembly streamer, this prints the + /// binding into the .s file. /// - /// Takes ownership of \p TAB and \p CE. - MCStreamer *createWinCOFFStreamer(MCContext &Ctx, - MCAsmBackend &TAB, - MCCodeEmitter &CE, raw_ostream &OS, - bool RelaxAll = false); + /// @param Symbol - The symbol being assigned to. + /// @param Value - The value for the symbol. + virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) = 0; - /// createELFStreamer - Create a machine code streamer which will generate - /// ELF format object files. - MCStreamer *createELFStreamer(MCContext &Ctx, MCAsmBackend &TAB, - raw_ostream &OS, MCCodeEmitter *CE, - bool RelaxAll, bool NoExecStack); + /// EmitWeakReference - Emit an weak reference from @p Alias to @p Symbol. + /// + /// This corresponds to an assembler statement such as: + /// .weakref alias, symbol + /// + /// @param Alias - The alias that is being created. + /// @param Symbol - The symbol being aliased. + virtual void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) = 0; + + /// EmitSymbolAttribute - Add the given @p Attribute to @p Symbol. + virtual bool EmitSymbolAttribute(MCSymbol *Symbol, + MCSymbolAttr Attribute) = 0; + + /// EmitSymbolDesc - Set the @p DescValue for the @p Symbol. + /// + /// @param Symbol - The symbol to have its n_desc field set. + /// @param DescValue - The value to set into the n_desc field. + virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) = 0; + + /// BeginCOFFSymbolDef - Start emitting COFF symbol definition + /// + /// @param Symbol - The symbol to have its External & Type fields set. + virtual void BeginCOFFSymbolDef(const MCSymbol *Symbol) = 0; + + /// EmitCOFFSymbolStorageClass - Emit the storage class of the symbol. + /// + /// @param StorageClass - The storage class the symbol should have. + virtual void EmitCOFFSymbolStorageClass(int StorageClass) = 0; - /// createPureStreamer - Create a machine code streamer which will generate - /// "pure" MC object files, for use with MC-JIT and testing tools. + /// EmitCOFFSymbolType - Emit the type of the symbol. /// - /// Takes ownership of \p TAB and \p CE. - MCStreamer *createPureStreamer(MCContext &Ctx, MCAsmBackend &TAB, - raw_ostream &OS, MCCodeEmitter *CE); + /// @param Type - A COFF type identifier (see COFF::SymbolType in X86COFF.h) + virtual void EmitCOFFSymbolType(int Type) = 0; + + /// EndCOFFSymbolDef - Marks the end of the symbol definition. + virtual void EndCOFFSymbolDef() = 0; + + /// EmitCOFFSecRel32 - Emits a COFF section relative relocation. + /// + /// @param Symbol - Symbol the section relative realocation should point to. + virtual void EmitCOFFSecRel32(MCSymbol const *Symbol); + + /// EmitELFSize - Emit an ELF .size directive. + /// + /// This corresponds to an assembler statement such as: + /// .size symbol, expression + /// + virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) = 0; + + /// EmitCommonSymbol - Emit a common symbol. + /// + /// @param Symbol - The common symbol to emit. + /// @param Size - The size of the common symbol. + /// @param ByteAlignment - The alignment of the symbol if + /// non-zero. This must be a power of 2. + virtual void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment) = 0; + + /// EmitLocalCommonSymbol - Emit a local common (.lcomm) symbol. + /// + /// @param Symbol - The common symbol to emit. + /// @param Size - The size of the common symbol. + /// @param ByteAlignment - The alignment of the common symbol in bytes. + virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment) = 0; + + /// EmitZerofill - Emit the zerofill section and an optional symbol. + /// + /// @param Section - The zerofill section to create and or to put the symbol + /// @param Symbol - The zerofill symbol to emit, if non-NULL. + /// @param Size - The size of the zerofill symbol. + /// @param ByteAlignment - The alignment of the zerofill symbol if + /// non-zero. This must be a power of 2 on some targets. + virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = 0, + uint64_t Size = 0, unsigned ByteAlignment = 0) = 0; + + /// EmitTBSSSymbol - Emit a thread local bss (.tbss) symbol. + /// + /// @param Section - The thread local common section. + /// @param Symbol - The thread local common symbol to emit. + /// @param Size - The size of the symbol. + /// @param ByteAlignment - The alignment of the thread local common symbol + /// if non-zero. This must be a power of 2 on some targets. + virtual void EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol, + uint64_t Size, unsigned ByteAlignment = 0) = 0; + + /// @} + /// @name Generating Data + /// @{ + + /// EmitBytes - Emit the bytes in \p Data into the output. + /// + /// This is used to implement assembler directives such as .byte, .ascii, + /// etc. + virtual void EmitBytes(StringRef Data) = 0; + + /// EmitValue - Emit the expression @p Value into the output as a native + /// integer of the given @p Size bytes. + /// + /// This is used to implement assembler directives such as .word, .quad, + /// etc. + /// + /// @param Value - The value to emit. + /// @param Size - The size of the integer (in bytes) to emit. This must + /// match a native machine width. + virtual void EmitValueImpl(const MCExpr *Value, unsigned Size) = 0; + + void EmitValue(const MCExpr *Value, unsigned Size); + + /// EmitIntValue - Special case of EmitValue that avoids the client having + /// to pass in a MCExpr for constant integers. + virtual void EmitIntValue(uint64_t Value, unsigned Size); + + /// EmitAbsValue - Emit the Value, but try to avoid relocations. On MachO + /// this is done by producing + /// foo = value + /// .long foo + void EmitAbsValue(const MCExpr *Value, unsigned Size); + + virtual void EmitULEB128Value(const MCExpr *Value) = 0; + + virtual void EmitSLEB128Value(const MCExpr *Value) = 0; + + /// EmitULEB128Value - Special case of EmitULEB128Value that avoids the + /// client having to pass in a MCExpr for constant integers. + void EmitULEB128IntValue(uint64_t Value, unsigned Padding = 0); + + /// EmitSLEB128Value - Special case of EmitSLEB128Value that avoids the + /// client having to pass in a MCExpr for constant integers. + void EmitSLEB128IntValue(int64_t Value); + + /// EmitSymbolValue - Special case of EmitValue that avoids the client + /// having to pass in a MCExpr for MCSymbols. + void EmitSymbolValue(const MCSymbol *Sym, unsigned Size); + + /// EmitGPRel64Value - Emit the expression @p Value into the output as a + /// gprel64 (64-bit GP relative) value. + /// + /// This is used to implement assembler directives such as .gpdword on + /// targets that support them. + virtual void EmitGPRel64Value(const MCExpr *Value); + + /// EmitGPRel32Value - Emit the expression @p Value into the output as a + /// gprel32 (32-bit GP relative) value. + /// + /// This is used to implement assembler directives such as .gprel32 on + /// targets that support them. + virtual void EmitGPRel32Value(const MCExpr *Value); + + /// EmitFill - Emit NumBytes bytes worth of the value specified by + /// FillValue. This implements directives such as '.space'. + virtual void EmitFill(uint64_t NumBytes, uint8_t FillValue); + + /// \brief Emit NumBytes worth of zeros. + /// This function properly handles data in virtual sections. + virtual void EmitZeros(uint64_t NumBytes); + + /// EmitValueToAlignment - Emit some number of copies of @p Value until + /// the byte alignment @p ByteAlignment is reached. + /// + /// If the number of bytes need to emit for the alignment is not a multiple + /// of @p ValueSize, then the contents of the emitted fill bytes is + /// undefined. + /// + /// This used to implement the .align assembler directive. + /// + /// @param ByteAlignment - The alignment to reach. This must be a power of + /// two on some targets. + /// @param Value - The value to use when filling bytes. + /// @param ValueSize - The size of the integer (in bytes) to emit for + /// @p Value. This must match a native machine width. + /// @param MaxBytesToEmit - The maximum numbers of bytes to emit, or 0. If + /// the alignment cannot be reached in this many bytes, no bytes are + /// emitted. + virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0, + unsigned ValueSize = 1, + unsigned MaxBytesToEmit = 0) = 0; + + /// EmitCodeAlignment - Emit nops until the byte alignment @p ByteAlignment + /// is reached. + /// + /// This used to align code where the alignment bytes may be executed. This + /// can emit different bytes for different sizes to optimize execution. + /// + /// @param ByteAlignment - The alignment to reach. This must be a power of + /// two on some targets. + /// @param MaxBytesToEmit - The maximum numbers of bytes to emit, or 0. If + /// the alignment cannot be reached in this many bytes, no bytes are + /// emitted. + virtual void EmitCodeAlignment(unsigned ByteAlignment, + unsigned MaxBytesToEmit = 0) = 0; + + /// EmitValueToOffset - Emit some number of copies of @p Value until the + /// byte offset @p Offset is reached. + /// + /// This is used to implement assembler directives such as .org. + /// + /// @param Offset - The offset to reach. This may be an expression, but the + /// expression must be associated with the current section. + /// @param Value - The value to use when filling bytes. + /// @return false on success, true if the offset was invalid. + virtual bool EmitValueToOffset(const MCExpr *Offset, + unsigned char Value = 0) = 0; + + /// @} + + /// EmitFileDirective - Switch to a new logical file. This is used to + /// implement the '.file "foo.c"' assembler directive. + virtual void EmitFileDirective(StringRef Filename) = 0; + + /// Emit the "identifiers" directive. This implements the + /// '.ident "version foo"' assembler directive. + virtual void EmitIdent(StringRef IdentString) {} + + /// EmitDwarfFileDirective - Associate a filename with a specified logical + /// file number. This implements the DWARF2 '.file 4 "foo.c"' assembler + /// directive. + virtual bool EmitDwarfFileDirective(unsigned FileNo, StringRef Directory, + StringRef Filename, unsigned CUID = 0); + + /// EmitDwarfLocDirective - This implements the DWARF2 + // '.loc fileno lineno ...' assembler directive. + virtual void EmitDwarfLocDirective(unsigned FileNo, unsigned Line, + unsigned Column, unsigned Flags, + unsigned Isa, unsigned Discriminator, + StringRef FileName); + + virtual void EmitDwarfAdvanceLineAddr(int64_t LineDelta, + const MCSymbol *LastLabel, + const MCSymbol *Label, + unsigned PointerSize) = 0; + + virtual void EmitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel, + const MCSymbol *Label) {} + + void EmitDwarfSetLineAddr(int64_t LineDelta, const MCSymbol *Label, + int PointerSize); + + virtual void EmitCompactUnwindEncoding(uint32_t CompactUnwindEncoding); + virtual void EmitCFISections(bool EH, bool Debug); + void EmitCFIStartProc(); + void EmitCFIEndProc(); + virtual void EmitCFIDefCfa(int64_t Register, int64_t Offset); + virtual void EmitCFIDefCfaOffset(int64_t Offset); + virtual void EmitCFIDefCfaRegister(int64_t Register); + virtual void EmitCFIOffset(int64_t Register, int64_t Offset); + virtual void EmitCFIPersonality(const MCSymbol *Sym, unsigned Encoding); + virtual void EmitCFILsda(const MCSymbol *Sym, unsigned Encoding); + virtual void EmitCFIRememberState(); + virtual void EmitCFIRestoreState(); + virtual void EmitCFISameValue(int64_t Register); + virtual void EmitCFIRestore(int64_t Register); + virtual void EmitCFIRelOffset(int64_t Register, int64_t Offset); + virtual void EmitCFIAdjustCfaOffset(int64_t Adjustment); + virtual void EmitCFIEscape(StringRef Values); + virtual void EmitCFISignalFrame(); + virtual void EmitCFIUndefined(int64_t Register); + virtual void EmitCFIRegister(int64_t Register1, int64_t Register2); + virtual void EmitCFIWindowSave(); + + virtual void EmitWin64EHStartProc(const MCSymbol *Symbol); + virtual void EmitWin64EHEndProc(); + virtual void EmitWin64EHStartChained(); + virtual void EmitWin64EHEndChained(); + virtual void EmitWin64EHHandler(const MCSymbol *Sym, bool Unwind, + bool Except); + virtual void EmitWin64EHHandlerData(); + virtual void EmitWin64EHPushReg(unsigned Register); + virtual void EmitWin64EHSetFrame(unsigned Register, unsigned Offset); + virtual void EmitWin64EHAllocStack(unsigned Size); + virtual void EmitWin64EHSaveReg(unsigned Register, unsigned Offset); + virtual void EmitWin64EHSaveXMM(unsigned Register, unsigned Offset); + virtual void EmitWin64EHPushFrame(bool Code); + virtual void EmitWin64EHEndProlog(); + + /// EmitInstruction - Emit the given @p Instruction into the current + /// section. + virtual void EmitInstruction(const MCInst &Inst) = 0; + + /// \brief Set the bundle alignment mode from now on in the section. + /// The argument is the power of 2 to which the alignment is set. The + /// value 0 means turn the bundle alignment off. + virtual void EmitBundleAlignMode(unsigned AlignPow2) = 0; + + /// \brief The following instructions are a bundle-locked group. + /// + /// \param AlignToEnd - If true, the bundle-locked group will be aligned to + /// the end of a bundle. + virtual void EmitBundleLock(bool AlignToEnd) = 0; + + /// \brief Ends a bundle-locked group. + virtual void EmitBundleUnlock() = 0; + + /// EmitRawText - If this file is backed by a assembly streamer, this dumps + /// the specified string in the output .s file. This capability is + /// indicated by the hasRawTextSupport() predicate. By default this aborts. + void EmitRawText(const Twine &String); + + /// Flush - Causes any cached state to be written out. + virtual void Flush() {} + + /// FinishImpl - Streamer specific finalization. + virtual void FinishImpl() = 0; + /// Finish - Finish emission of machine code. + void Finish(); +}; + +/// createNullStreamer - Create a dummy machine code streamer, which does +/// nothing. This is useful for timing the assembler front end. +MCStreamer *createNullStreamer(MCContext &Ctx); + +/// createAsmStreamer - Create a machine code streamer which will print out +/// assembly for the native target, suitable for compiling with a native +/// assembler. +/// +/// \param InstPrint - If given, the instruction printer to use. If not given +/// the MCInst representation will be printed. This method takes ownership of +/// InstPrint. +/// +/// \param CE - If given, a code emitter to use to show the instruction +/// encoding inline with the assembly. This method takes ownership of \p CE. +/// +/// \param TAB - If given, a target asm backend to use to show the fixup +/// information in conjunction with encoding information. This method takes +/// ownership of \p TAB. +/// +/// \param ShowInst - Whether to show the MCInst representation inline with +/// the assembly. +MCStreamer *createAsmStreamer(MCContext &Ctx, MCTargetStreamer *TargetStreamer, + formatted_raw_ostream &OS, bool isVerboseAsm, + bool useLoc, bool useCFI, bool useDwarfDirectory, + MCInstPrinter *InstPrint = 0, + MCCodeEmitter *CE = 0, MCAsmBackend *TAB = 0, + bool ShowInst = false); + +/// createMachOStreamer - Create a machine code streamer which will generate +/// Mach-O format object files. +/// +/// Takes ownership of \p TAB and \p CE. +MCStreamer *createMachOStreamer(MCContext &Ctx, MCAsmBackend &TAB, + raw_ostream &OS, MCCodeEmitter *CE, + bool RelaxAll = false); + +/// createWinCOFFStreamer - Create a machine code streamer which will +/// generate Microsoft COFF format object files. +/// +/// Takes ownership of \p TAB and \p CE. +MCStreamer *createWinCOFFStreamer(MCContext &Ctx, MCAsmBackend &TAB, + MCCodeEmitter &CE, raw_ostream &OS, + bool RelaxAll = false); + +/// createELFStreamer - Create a machine code streamer which will generate +/// ELF format object files. +MCStreamer *createELFStreamer(MCContext &Ctx, MCTargetStreamer *TargetStreamer, + MCAsmBackend &TAB, raw_ostream &OS, + MCCodeEmitter *CE, bool RelaxAll, + bool NoExecStack); + +/// createPureStreamer - Create a machine code streamer which will generate +/// "pure" MC object files, for use with MC-JIT and testing tools. +/// +/// Takes ownership of \p TAB and \p CE. +MCStreamer *createPureStreamer(MCContext &Ctx, MCAsmBackend &TAB, + raw_ostream &OS, MCCodeEmitter *CE); } // end namespace llvm diff --git a/contrib/llvm/include/llvm/MC/MCSubtargetInfo.h b/contrib/llvm/include/llvm/MC/MCSubtargetInfo.h index 346fb2df0..01e823648 100644 --- a/contrib/llvm/include/llvm/MC/MCSubtargetInfo.h +++ b/contrib/llvm/include/llvm/MC/MCSubtargetInfo.h @@ -72,6 +72,9 @@ public: /// feature string). Recompute feature bits and scheduling model. void InitMCProcessorInfo(StringRef CPU, StringRef FS); + /// InitCPUSchedModel - Recompute scheduling model based on CPU. + void InitCPUSchedModel(StringRef CPU); + /// ToggleFeature - Toggle a feature and returns the re-computed feature /// bits. This version does not change the implied bits. uint64_t ToggleFeature(uint64_t FB); diff --git a/contrib/llvm/include/llvm/MC/MCSymbolizer.h b/contrib/llvm/include/llvm/MC/MCSymbolizer.h new file mode 100644 index 000000000..e42a2146d --- /dev/null +++ b/contrib/llvm/include/llvm/MC/MCSymbolizer.h @@ -0,0 +1,81 @@ +//===-- llvm/MC/MCSymbolizer.h - MCSymbolizer class -------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the MCSymbolizer class, which is used +// to symbolize instructions decoded from an object, that is, transform their +// immediate operands to MCExprs. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCSYMBOLIZER_H +#define LLVM_MC_MCSYMBOLIZER_H + +#include "llvm/ADT/OwningPtr.h" +#include "llvm/MC/MCRelocationInfo.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/DataTypes.h" + +namespace llvm { + +class MCContext; +class MCInst; +class raw_ostream; + +/// \brief Symbolize and annotate disassembled instructions. +/// +/// For now this mimics the old symbolization logic (from both ARM and x86), that +/// relied on user-provided (C API) callbacks to do the actual symbol lookup in +/// the object file. This was moved to MCExternalSymbolizer. +/// A better API would not rely on actually calling the two methods here from +/// inside each disassembler, but would use the instr info to determine what +/// 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; + +protected: + MCContext &Ctx; + OwningPtr RelInfo; + +public: + /// \brief Construct an MCSymbolizer, taking ownership of \p RelInfo. + MCSymbolizer(MCContext &Ctx, OwningPtr &RelInfo); + virtual ~MCSymbolizer(); + + /// \brief Try to add a symbolic operand instead of \p Value to the MCInst. + /// + /// Instead of having a difficult to read immediate, a symbolic operand would + /// represent this immediate in a more understandable way, for instance as a + /// symbol or an offset from a symbol. Relocations can also be used to enrich + /// the symbolic expression. + /// @param Inst - The MCInst where to insert the symbolic operand. + /// @param cStream - Stream to print comments and annotations on. + /// @param Value - Operand value, pc-adjusted by the caller if necessary. + /// @param Address - Load address of the instruction. + /// @param IsBranch - Is the instruction a branch? + /// @param Offset - Byte offset of the operand inside the inst. + /// @param InstSize - Size of the instruction in bytes. + /// @return Whether a symbolic operand was added. + virtual bool tryAddingSymbolicOperand(MCInst &Inst, raw_ostream &cStream, + int64_t Value, uint64_t Address, + bool IsBranch, uint64_t Offset, + uint64_t InstSize) = 0; + + /// \brief Try to add a comment on the PC-relative load. + /// For instance, in Mach-O, this is used to add annotations to instructions + /// that use C string literals, as found in __cstring. + virtual void tryAddingPcLoadReferenceComment(raw_ostream &cStream, + int64_t Value, + uint64_t Address) = 0; +}; + +} + +#endif diff --git a/contrib/llvm/include/llvm/MC/MCTargetAsmParser.h b/contrib/llvm/include/llvm/MC/MCTargetAsmParser.h index 6e878df3c..d132a732c 100644 --- a/contrib/llvm/include/llvm/MC/MCTargetAsmParser.h +++ b/contrib/llvm/include/llvm/MC/MCTargetAsmParser.h @@ -11,6 +11,7 @@ #define LLVM_MC_TARGETPARSER_H #include "llvm/MC/MCParser/MCAsmParserExtension.h" +#include "llvm/MC/MCExpr.h" namespace llvm { class MCStreamer; @@ -143,7 +144,7 @@ public: /// mnemonicIsValid - This returns true if this is a valid mnemonic and false /// otherwise. - virtual bool mnemonicIsValid(StringRef Mnemonic) = 0; + virtual bool mnemonicIsValid(StringRef Mnemonic, unsigned VariantID) = 0; /// MatchAndEmitInstruction - Recognize a series of operands of a parsed /// instruction as an actual MCInst and emit it to the specified MCStreamer. @@ -174,6 +175,14 @@ public: virtual void convertToMapAndConstraints(unsigned Kind, const SmallVectorImpl &Operands) = 0; + + virtual const MCExpr *applyModifierToExpr(const MCExpr *E, + MCSymbolRefExpr::VariantKind, + MCContext &Ctx) { + return 0; + } + + virtual void onLabelParsed(MCSymbol *Symbol) { }; }; } // End llvm namespace diff --git a/contrib/llvm/include/llvm/MC/MCWinCOFFObjectWriter.h b/contrib/llvm/include/llvm/MC/MCWinCOFFObjectWriter.h index f13e7d548..213481c90 100644 --- a/contrib/llvm/include/llvm/MC/MCWinCOFFObjectWriter.h +++ b/contrib/llvm/include/llvm/MC/MCWinCOFFObjectWriter.h @@ -17,6 +17,7 @@ namespace llvm { class raw_ostream; class MCWinCOFFObjectTargetWriter { + virtual void anchor(); const unsigned Machine; protected: diff --git a/contrib/llvm/include/llvm/MC/MachineLocation.h b/contrib/llvm/include/llvm/MC/MachineLocation.h index 83c8b72ee..b3fbee770 100644 --- a/contrib/llvm/include/llvm/MC/MachineLocation.h +++ b/contrib/llvm/include/llvm/MC/MachineLocation.h @@ -10,17 +10,15 @@ // frame. Locations will be one of two forms; a register or an address formed // from a base address plus an offset. Register indirection can be specified by // explicitly passing an offset to the constructor. -// -// The MachineMove class is used to represent abstract move operations in the -// prolog/epilog of a compiled function. A collection of these objects can be -// used by a debug consumer to track the location of values when unwinding stack -// frames. //===----------------------------------------------------------------------===// #ifndef LLVM_MC_MACHINELOCATION_H #define LLVM_MC_MACHINELOCATION_H +#include "llvm/Support/Compiler.h" +#include "llvm/Support/DataTypes.h" + namespace llvm { class MCSymbol; @@ -30,7 +28,7 @@ private: unsigned Register; // gcc/gdb register number. int Offset; // Displacement if not register. public: - enum { + enum LLVM_ENUM_INT_TYPE(uint32_t) { // The target register number for an abstract frame pointer. The value is // an arbitrary value that doesn't collide with any real target register. VirtualFP = ~0U @@ -49,7 +47,8 @@ public: Offset == Other.Offset; } - // Accessors + // Accessors. + /// \return true iff this is a register-indirect location. bool isIndirect() const { return !IsRegister; } bool isReg() const { return IsRegister; } unsigned getReg() const { return Register; } @@ -74,30 +73,6 @@ public: void dump(); #endif }; - -/// MachineMove - This class represents the save or restore of a callee saved -/// register that exception or debug info needs to know about. -class MachineMove { -private: - /// Label - Symbol for post-instruction address when result of move takes - /// effect. - MCSymbol *Label; - - // Move to & from location. - MachineLocation Destination, Source; -public: - MachineMove() : Label(0) {} - - MachineMove(MCSymbol *label, const MachineLocation &D, - const MachineLocation &S) - : Label(label), Destination(D), Source(S) {} - - // Accessors - MCSymbol *getLabel() const { return Label; } - const MachineLocation &getDestination() const { return Destination; } - const MachineLocation &getSource() const { return Source; } -}; - } // End llvm namespace #endif diff --git a/contrib/llvm/include/llvm/MC/SubtargetFeature.h b/contrib/llvm/include/llvm/MC/SubtargetFeature.h index 8862c8b76..d0735ccd9 100644 --- a/contrib/llvm/include/llvm/MC/SubtargetFeature.h +++ b/contrib/llvm/include/llvm/MC/SubtargetFeature.h @@ -37,9 +37,9 @@ struct SubtargetFeatureKV { uint64_t Value; // K-V integer value uint64_t Implies; // K-V bit mask - // Compare routine for std binary search - bool operator<(const SubtargetFeatureKV &S) const { - return strcmp(Key, S.Key) < 0; + // Compare routine for std::lower_bound + bool operator<(StringRef S) const { + return StringRef(Key) < S; } }; @@ -52,9 +52,9 @@ struct SubtargetInfoKV { const char *Key; // K-V key string const void *Value; // K-V pointer value - // Compare routine for std binary search - bool operator<(const SubtargetInfoKV &S) const { - return strcmp(Key, S.Key) < 0; + // Compare routine for std::lower_bound + bool operator<(StringRef S) const { + return StringRef(Key) < S; } }; @@ -99,8 +99,7 @@ public: // Dump feature info. void dump() const; - /// Retrieve a formatted string of the default features for the specified - /// target triple. + /// Adds the default features for the specified target triple. void getDefaultSubtargetFeatures(const Triple& Triple); }; diff --git a/contrib/llvm/include/llvm/Object/Archive.h b/contrib/llvm/include/llvm/Object/Archive.h index e2478f675..1cba51954 100644 --- a/contrib/llvm/include/llvm/Object/Archive.h +++ b/contrib/llvm/include/llvm/Object/Archive.h @@ -14,12 +14,10 @@ #ifndef LLVM_OBJECT_ARCHIVE_H #define LLVM_OBJECT_ARCHIVE_H -#include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringRef.h" -#include "llvm/ADT/Twine.h" #include "llvm/Object/Binary.h" -#include "llvm/Support/DataTypes.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/FileSystem.h" #include "llvm/Support/MemoryBuffer.h" namespace llvm { @@ -33,33 +31,17 @@ struct ArchiveMemberHeader { char Size[10]; ///< Size of data, not including header or padding. char Terminator[2]; - ///! Get the name without looking up long names. - llvm::StringRef getName() const { - char EndCond; - if (Name[0] == '/' || Name[0] == '#') - EndCond = ' '; - else - EndCond = '/'; - llvm::StringRef::size_type end = - llvm::StringRef(Name, sizeof(Name)).find(EndCond); - if (end == llvm::StringRef::npos) - end = sizeof(Name); - assert(end <= sizeof(Name) && end > 0); - // Don't include the EndCond if there is one. - return llvm::StringRef(Name, end); - } + /// Get the name without looking up long names. + llvm::StringRef getName() const; - uint64_t getSize() const { - uint64_t ret; - if (llvm::StringRef(Size, sizeof(Size)).rtrim(" ").getAsInteger(10, ret)) - llvm_unreachable("Size is not an integer."); - return ret; - } -}; + /// Members are not larger than 4GB. + uint32_t getSize() const; -static const ArchiveMemberHeader *ToHeader(const char *base) { - return reinterpret_cast(base); -} + sys::fs::perms getAccessMode() const; + sys::TimeValue getLastModified() const; + unsigned getUID() const; + unsigned getGID() const; +}; class Archive : public Binary { virtual void anchor(); @@ -71,53 +53,34 @@ public: /// \brief Offset from Data to the start of the file. uint16_t StartOfFile; - public: - Child(const Archive *p, StringRef d) : Parent(p), Data(d) { - if (!p || d.empty()) - return; - // Setup StartOfFile and PaddingBytes. - StartOfFile = sizeof(ArchiveMemberHeader); - // Don't include attached name. - StringRef Name = ToHeader(Data.data())->getName(); - if (Name.startswith("#1/")) { - uint64_t NameSize; - if (Name.substr(3).rtrim(" ").getAsInteger(10, NameSize)) - llvm_unreachable("Long name length is not an integer"); - StartOfFile += NameSize; - } + const ArchiveMemberHeader *getHeader() const { + return reinterpret_cast(Data.data()); } + public: + Child(const Archive *Parent, const char *Start); + bool operator ==(const Child &other) const { - return (Parent == other.Parent) && (Data.begin() == other.Data.begin()); + assert(Parent == other.Parent); + return Data.begin() == other.Data.begin(); } bool operator <(const Child &other) const { return Data.begin() < other.Data.begin(); } - Child getNext() const { - size_t SpaceToSkip = Data.size(); - // If it's odd, add 1 to make it even. - if (SpaceToSkip & 1) - ++SpaceToSkip; - - const char *NextLoc = Data.data() + SpaceToSkip; - - // Check to see if this is past the end of the archive. - if (NextLoc >= Parent->Data->getBufferEnd()) - return Child(Parent, StringRef(0, 0)); - - size_t NextSize = - sizeof(ArchiveMemberHeader) + ToHeader(NextLoc)->getSize(); - - return Child(Parent, StringRef(NextLoc, NextSize)); - } + Child getNext() const; error_code getName(StringRef &Result) const; - int getLastModified() const; - int getUID() const; - int getGID() const; - int getAccessMode() const; + StringRef getRawName() const { return getHeader()->getName(); } + sys::TimeValue getLastModified() const { + return getHeader()->getLastModified(); + } + 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; } @@ -126,16 +89,7 @@ public: } error_code getMemoryBuffer(OwningPtr &Result, - bool FullPath = false) const { - StringRef Name; - if (error_code ec = getName(Name)) - return ec; - SmallString<128> Path; - Result.reset(MemoryBuffer::getMemBuffer( - getBuffer(), FullPath ? (Twine(Parent->getFileName()) + "(" + Name + - ")").toStringRef(Path) : Name, false)); - return error_code::success(); - } + bool FullPath = false) const; error_code getAsBinary(OwningPtr &Result) const; }; @@ -143,7 +97,7 @@ public: class child_iterator { Child child; public: - child_iterator() : child(Child(0, StringRef())) {} + child_iterator() : child(Child(0, 0)) {} child_iterator(const Child &c) : child(c) {} const Child* operator->() const { return &child; @@ -220,7 +174,7 @@ public: return Format; } - child_iterator begin_children(bool skip_internal = true) const; + child_iterator begin_children(bool SkipInternal = true) const; child_iterator end_children() const; symbol_iterator begin_symbols() const; @@ -234,9 +188,12 @@ public: // check if a symbol is in the archive child_iterator findSym(StringRef name) const; + bool hasSymbolTable() const; + private: child_iterator SymbolTable; child_iterator StringTable; + child_iterator FirstRegular; Kind Format; }; diff --git a/contrib/llvm/include/llvm/Object/Binary.h b/contrib/llvm/include/llvm/Object/Binary.h index 78fcf6feb..a3f5625cc 100644 --- a/contrib/llvm/include/llvm/Object/Binary.h +++ b/contrib/llvm/include/llvm/Object/Binary.h @@ -38,6 +38,7 @@ protected: enum { ID_Archive, + ID_MachOUniversalBinary, // Object and children. ID_StartObjects, ID_COFF, @@ -87,6 +88,10 @@ public: return TypeID == ID_Archive; } + bool isMachOUniversalBinary() const { + return TypeID == ID_MachOUniversalBinary; + } + bool isELF() const { return TypeID >= ID_ELF32L && TypeID <= ID_ELF64B; } diff --git a/contrib/llvm/include/llvm/Object/COFF.h b/contrib/llvm/include/llvm/Object/COFF.h index 6f42d76ee..e05ae6c65 100644 --- a/contrib/llvm/include/llvm/Object/COFF.h +++ b/contrib/llvm/include/llvm/Object/COFF.h @@ -23,6 +23,31 @@ namespace llvm { class ArrayRef; namespace object { +class ImportDirectoryEntryRef; +typedef content_iterator import_directory_iterator; + +/// The DOS compatible header at the front of all PE/COFF executables. +struct dos_header { + support::ulittle16_t Magic; + support::ulittle16_t UsedBytesInTheLastPage; + support::ulittle16_t FileSizeInPages; + support::ulittle16_t NumberOfRelocationItems; + support::ulittle16_t HeaderSizeInParagraphs; + support::ulittle16_t MinimumExtraParagraphs; + support::ulittle16_t MaximumExtraParagraphs; + support::ulittle16_t InitialRelativeSS; + support::ulittle16_t InitialSP; + support::ulittle16_t Checksum; + support::ulittle16_t InitialIP; + support::ulittle16_t InitialRelativeCS; + support::ulittle16_t AddressOfRelocationTable; + support::ulittle16_t OverlayNumber; + support::ulittle16_t Reserved[4]; + support::ulittle16_t OEMid; + support::ulittle16_t OEMinfo; + support::ulittle16_t Reserved2[10]; + support::ulittle32_t AddressOfNewExeHeader; +}; struct coff_file_header { support::ulittle16_t Machine; @@ -32,6 +57,104 @@ struct coff_file_header { support::ulittle32_t NumberOfSymbols; support::ulittle16_t SizeOfOptionalHeader; support::ulittle16_t Characteristics; + + bool isImportLibrary() const { return NumberOfSections == 0xffff; } +}; + +/// The 32-bit PE header that follows the COFF header. +struct pe32_header { + support::ulittle16_t Magic; + uint8_t MajorLinkerVersion; + uint8_t MinorLinkerVersion; + support::ulittle32_t SizeOfCode; + support::ulittle32_t SizeOfInitializedData; + support::ulittle32_t SizeOfUninitializedData; + support::ulittle32_t AddressOfEntryPoint; + support::ulittle32_t BaseOfCode; + support::ulittle32_t BaseOfData; + support::ulittle32_t ImageBase; + support::ulittle32_t SectionAlignment; + support::ulittle32_t FileAlignment; + support::ulittle16_t MajorOperatingSystemVersion; + support::ulittle16_t MinorOperatingSystemVersion; + support::ulittle16_t MajorImageVersion; + support::ulittle16_t MinorImageVersion; + support::ulittle16_t MajorSubsystemVersion; + support::ulittle16_t MinorSubsystemVersion; + support::ulittle32_t Win32VersionValue; + support::ulittle32_t SizeOfImage; + support::ulittle32_t SizeOfHeaders; + support::ulittle32_t CheckSum; + support::ulittle16_t Subsystem; + support::ulittle16_t DLLCharacteristics; + support::ulittle32_t SizeOfStackReserve; + support::ulittle32_t SizeOfStackCommit; + support::ulittle32_t SizeOfHeapReserve; + support::ulittle32_t SizeOfHeapCommit; + support::ulittle32_t LoaderFlags; + support::ulittle32_t NumberOfRvaAndSize; +}; + +/// The 64-bit PE header that follows the COFF header. +struct pe32plus_header { + support::ulittle16_t Magic; + uint8_t MajorLinkerVersion; + uint8_t MinorLinkerVersion; + support::ulittle32_t SizeOfCode; + support::ulittle32_t SizeOfInitializedData; + support::ulittle32_t SizeOfUninitializedData; + support::ulittle32_t AddressOfEntryPoint; + support::ulittle32_t BaseOfCode; + support::ulittle64_t ImageBase; + support::ulittle32_t SectionAlignment; + support::ulittle32_t FileAlignment; + support::ulittle16_t MajorOperatingSystemVersion; + support::ulittle16_t MinorOperatingSystemVersion; + support::ulittle16_t MajorImageVersion; + support::ulittle16_t MinorImageVersion; + support::ulittle16_t MajorSubsystemVersion; + support::ulittle16_t MinorSubsystemVersion; + support::ulittle32_t Win32VersionValue; + support::ulittle32_t SizeOfImage; + support::ulittle32_t SizeOfHeaders; + support::ulittle32_t CheckSum; + support::ulittle16_t Subsystem; + support::ulittle16_t DLLCharacteristics; + support::ulittle64_t SizeOfStackReserve; + support::ulittle64_t SizeOfStackCommit; + support::ulittle64_t SizeOfHeapReserve; + support::ulittle64_t SizeOfHeapCommit; + support::ulittle32_t LoaderFlags; + support::ulittle32_t NumberOfRvaAndSize; +}; + +struct data_directory { + support::ulittle32_t RelativeVirtualAddress; + support::ulittle32_t Size; +}; + +struct import_directory_table_entry { + support::ulittle32_t ImportLookupTableRVA; + support::ulittle32_t TimeDateStamp; + support::ulittle32_t ForwarderChain; + support::ulittle32_t NameRVA; + support::ulittle32_t ImportAddressTableRVA; +}; + +struct import_lookup_table_entry32 { + support::ulittle32_t data; + + bool isOrdinal() const { return data & 0x80000000; } + + uint16_t getOrdinal() const { + assert(isOrdinal() && "ILT entry is not an ordinal!"); + return data & 0xFFFF; + } + + uint32_t getHintNameRVA() const { + assert(!isOrdinal() && "ILT entry is not a Hint/Name RVA!"); + return data; + } }; struct coff_symbol { @@ -81,6 +204,12 @@ struct coff_relocation { support::ulittle16_t Type; }; +struct coff_aux_weak_external { + support::ulittle32_t TagIndex; + support::ulittle32_t Characteristics; + char Unused[10]; +}; + struct coff_aux_section_definition { support::ulittle32_t Length; support::ulittle16_t NumberOfRelocations; @@ -93,11 +222,16 @@ struct coff_aux_section_definition { class COFFObjectFile : public ObjectFile { private: - const coff_file_header *Header; + friend class ImportDirectoryEntryRef; + const coff_file_header *COFFHeader; + const pe32_header *PE32Header; + const data_directory *DataDirectory; const coff_section *SectionTable; const coff_symbol *SymbolTable; const char *StringTable; uint32_t StringTableSize; + const import_directory_table_entry *ImportDirectory; + uint32_t NumberOfImportDirectory; error_code getString(uint32_t offset, StringRef &Res) const; @@ -105,13 +239,15 @@ private: const coff_section *toSec(DataRefImpl Sec) const; const coff_relocation *toRel(DataRefImpl Rel) const; + error_code initSymbolTablePtr(); + error_code initImportTablePtr(); + protected: virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const; virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const; virtual error_code getSymbolFileOffset(DataRefImpl Symb, uint64_t &Res) const; virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const; virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const; - virtual error_code getSymbolNMTypeChar(DataRefImpl Symb, char &Res) const; virtual error_code getSymbolFlags(DataRefImpl Symb, uint32_t &Res) const; virtual error_code getSymbolType(DataRefImpl Symb, SymbolRef::Type &Res) const; virtual error_code getSymbolSection(DataRefImpl Symb, @@ -134,8 +270,8 @@ protected: bool &Res) const; virtual error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, bool &Result) const; - virtual relocation_iterator getSectionRelBegin(DataRefImpl Sec) const; - virtual relocation_iterator getSectionRelEnd(DataRefImpl Sec) const; + virtual relocation_iterator section_rel_begin(DataRefImpl Sec) const; + virtual relocation_iterator section_rel_end(DataRefImpl Sec) const; virtual error_code getRelocationNext(DataRefImpl Rel, RelocationRef &Res) const; @@ -143,14 +279,11 @@ protected: uint64_t &Res) const; virtual error_code getRelocationOffset(DataRefImpl Rel, uint64_t &Res) const; - virtual error_code getRelocationSymbol(DataRefImpl Rel, - SymbolRef &Res) const; + virtual symbol_iterator getRelocationSymbol(DataRefImpl Rel) const; virtual error_code getRelocationType(DataRefImpl Rel, uint64_t &Res) const; virtual error_code getRelocationTypeName(DataRefImpl Rel, SmallVectorImpl &Result) const; - virtual error_code getRelocationAdditionalInfo(DataRefImpl Rel, - int64_t &Res) const; virtual error_code getRelocationValueString(DataRefImpl Rel, SmallVectorImpl &Result) const; @@ -173,13 +306,19 @@ public: const coff_section *getCOFFSection(section_iterator &It) const; const coff_symbol *getCOFFSymbol(symbol_iterator &It) const; const coff_relocation *getCOFFRelocation(relocation_iterator &It) const; - + virtual uint8_t getBytesInAddress() const; virtual StringRef getFileFormatName() const; virtual unsigned getArch() const; virtual StringRef getLoadName() const; + import_directory_iterator import_directory_begin() const; + import_directory_iterator import_directory_end() const; + error_code getHeader(const coff_file_header *&Res) const; + error_code getCOFFHeader(const coff_file_header *&Res) const; + error_code getPE32Header(const pe32_header *&Res) const; + error_code getDataDirectory(uint32_t index, const data_directory *&Res) const; error_code getSection(int32_t index, const coff_section *&Res) const; error_code getSymbol(uint32_t index, const coff_symbol *&Res) const; template @@ -196,12 +335,37 @@ public: error_code getSectionContents(const coff_section *Sec, ArrayRef &Res) const; + error_code getRvaPtr(uint32_t Rva, uintptr_t &Res) const; + error_code getHintName(uint32_t Rva, uint16_t &Hint, StringRef &Name) const; + static inline bool classof(const Binary *v) { return v->isCOFF(); } }; -} -} +// The iterator for the import directory table. +class ImportDirectoryEntryRef { +public: + ImportDirectoryEntryRef() : OwningObject(0) {} + ImportDirectoryEntryRef(DataRefImpl ImportDirectory, + const COFFObjectFile *Owner) + : ImportDirectoryPimpl(ImportDirectory), OwningObject(Owner) {} + + bool operator==(const ImportDirectoryEntryRef &Other) const; + error_code getNext(ImportDirectoryEntryRef &Result) const; + error_code getName(StringRef &Result) const; + + error_code + getImportTableEntry(const import_directory_table_entry *&Result) const; + + error_code + getImportLookupEntry(const import_lookup_table_entry32 *&Result) const; + +private: + DataRefImpl ImportDirectoryPimpl; + const COFFObjectFile *OwningObject; +}; +} // end namespace object +} // end namespace llvm #endif diff --git a/contrib/llvm/include/llvm/Object/COFFYAML.h b/contrib/llvm/include/llvm/Object/COFFYAML.h new file mode 100644 index 000000000..3fa3ec6c1 --- /dev/null +++ b/contrib/llvm/include/llvm/Object/COFFYAML.h @@ -0,0 +1,141 @@ +//===- COFFYAML.h - COFF YAMLIO implementation ------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares classes for handling the YAML representation of COFF. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_COFFYAML_H +#define LLVM_OBJECT_COFFYAML_H + +#include "llvm/Object/YAML.h" +#include "llvm/Support/COFF.h" + +namespace llvm { + +namespace COFF { +inline Characteristics operator|(Characteristics a, Characteristics b) { + uint32_t Ret = static_cast(a) | static_cast(b); + return static_cast(Ret); +} + +inline SectionCharacteristics operator|(SectionCharacteristics a, + SectionCharacteristics b) { + uint32_t Ret = static_cast(a) | static_cast(b); + return static_cast(Ret); +} +} + +// The structure of the yaml files is not an exact 1:1 match to COFF. In order +// to use yaml::IO, we use these structures which are closer to the source. +namespace COFFYAML { + struct Relocation { + uint32_t VirtualAddress; + uint16_t Type; + StringRef SymbolName; + }; + + struct Section { + COFF::section Header; + unsigned Alignment; + object::yaml::BinaryRef SectionData; + std::vector Relocations; + StringRef Name; + Section(); + }; + + struct Symbol { + COFF::symbol Header; + COFF::SymbolBaseType SimpleType; + COFF::SymbolComplexType ComplexType; + object::yaml::BinaryRef AuxiliaryData; + StringRef Name; + Symbol(); + }; + + struct Object { + COFF::header Header; + std::vector
    Sections; + std::vector Symbols; + Object(); + }; +} +} + +LLVM_YAML_IS_SEQUENCE_VECTOR(COFFYAML::Section) +LLVM_YAML_IS_SEQUENCE_VECTOR(COFFYAML::Symbol) +LLVM_YAML_IS_SEQUENCE_VECTOR(COFFYAML::Relocation) + +namespace llvm { +namespace yaml { + +template <> +struct ScalarEnumerationTraits { + static void enumeration(IO &IO, COFF::MachineTypes &Value); +}; + +template <> +struct ScalarEnumerationTraits { + static void enumeration(IO &IO, COFF::SymbolBaseType &Value); +}; + +template <> +struct ScalarEnumerationTraits { + static void enumeration(IO &IO, COFF::SymbolStorageClass &Value); +}; + +template <> +struct ScalarEnumerationTraits { + static void enumeration(IO &IO, COFF::SymbolComplexType &Value); +}; + +template <> +struct ScalarEnumerationTraits { + static void enumeration(IO &IO, COFF::RelocationTypeX86 &Value); +}; + +template <> +struct ScalarBitSetTraits { + static void bitset(IO &IO, COFF::Characteristics &Value); +}; + +template <> +struct ScalarBitSetTraits { + static void bitset(IO &IO, COFF::SectionCharacteristics &Value); +}; + +template <> +struct MappingTraits { + static void mapping(IO &IO, COFFYAML::Relocation &Rel); +}; + +template <> +struct MappingTraits { + static void mapping(IO &IO, COFF::header &H); +}; + +template <> +struct MappingTraits { + static void mapping(IO &IO, COFFYAML::Symbol &S); +}; + +template <> +struct MappingTraits { + static void mapping(IO &IO, COFFYAML::Section &Sec); +}; + +template <> +struct MappingTraits { + static void mapping(IO &IO, COFFYAML::Object &Obj); +}; + +} // end namespace yaml +} // end namespace llvm + +#endif diff --git a/contrib/llvm/include/llvm/Object/ELF.h b/contrib/llvm/include/llvm/Object/ELF.h index eb2390ab5..a6774c115 100644 --- a/contrib/llvm/include/llvm/Object/ELF.h +++ b/contrib/llvm/include/llvm/Object/ELF.h @@ -7,23 +7,26 @@ // //===----------------------------------------------------------------------===// // -// This file declares the ELFObjectFile template class. +// This file declares the ELFFile template class. // //===----------------------------------------------------------------------===// #ifndef LLVM_OBJECT_ELF_H #define LLVM_OBJECT_ELF_H +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Triple.h" -#include "llvm/Object/ObjectFile.h" +#include "llvm/Object/ELFTypes.h" +#include "llvm/Object/Error.h" #include "llvm/Support/Casting.h" #include "llvm/Support/ELF.h" #include "llvm/Support/Endian.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/ErrorOr.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/raw_ostream.h" #include @@ -33,467 +36,26 @@ namespace llvm { namespace object { -using support::endianness; +StringRef getELFRelocationTypeName(uint32_t Machine, uint32_t Type); -template -struct ELFType { - static const endianness TargetEndianness = target_endianness; - static const std::size_t MaxAlignment = max_alignment; - static const bool Is64Bits = is64Bits; -}; - -template -struct MaximumAlignment { - enum {value = AlignOf::Alignment > max_align ? max_align - : AlignOf::Alignment}; -}; - -// Subclasses of ELFObjectFile may need this for template instantiation +// Subclasses of ELFFile may need this for template instantiation inline std::pair getElfArchType(MemoryBuffer *Object) { if (Object->getBufferSize() < ELF::EI_NIDENT) return std::make_pair((uint8_t)ELF::ELFCLASSNONE,(uint8_t)ELF::ELFDATANONE); - return std::make_pair( (uint8_t)Object->getBufferStart()[ELF::EI_CLASS] - , (uint8_t)Object->getBufferStart()[ELF::EI_DATA]); + return std::make_pair((uint8_t) Object->getBufferStart()[ELF::EI_CLASS], + (uint8_t) Object->getBufferStart()[ELF::EI_DATA]); } -// Templates to choose Elf_Addr and Elf_Off depending on is64Bits. -template -struct ELFDataTypeTypedefHelperCommon { - typedef support::detail::packed_endian_specific_integral - ::value> Elf_Half; - typedef support::detail::packed_endian_specific_integral - ::value> Elf_Word; - typedef support::detail::packed_endian_specific_integral - ::value> Elf_Sword; - typedef support::detail::packed_endian_specific_integral - ::value> Elf_Xword; - typedef support::detail::packed_endian_specific_integral - ::value> Elf_Sxword; -}; - -template -struct ELFDataTypeTypedefHelper; - -/// ELF 32bit types. -template -struct ELFDataTypeTypedefHelper > - : ELFDataTypeTypedefHelperCommon { - typedef uint32_t value_type; - typedef support::detail::packed_endian_specific_integral - ::value> Elf_Addr; - typedef support::detail::packed_endian_specific_integral - ::value> Elf_Off; -}; - -/// ELF 64bit types. -template -struct ELFDataTypeTypedefHelper > - : ELFDataTypeTypedefHelperCommon { - typedef uint64_t value_type; - typedef support::detail::packed_endian_specific_integral - ::value> Elf_Addr; - typedef support::detail::packed_endian_specific_integral - ::value> Elf_Off; -}; - -// I really don't like doing this, but the alternative is copypasta. -#define LLVM_ELF_IMPORT_TYPES(E, M, W) \ -typedef typename ELFDataTypeTypedefHelper >::Elf_Addr Elf_Addr; \ -typedef typename ELFDataTypeTypedefHelper >::Elf_Off Elf_Off; \ -typedef typename ELFDataTypeTypedefHelper >::Elf_Half Elf_Half; \ -typedef typename ELFDataTypeTypedefHelper >::Elf_Word Elf_Word; \ -typedef typename \ - ELFDataTypeTypedefHelper >::Elf_Sword Elf_Sword; \ -typedef typename \ - ELFDataTypeTypedefHelper >::Elf_Xword Elf_Xword; \ -typedef typename \ - ELFDataTypeTypedefHelper >::Elf_Sxword Elf_Sxword; - -#define LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) \ - LLVM_ELF_IMPORT_TYPES(ELFT::TargetEndianness, ELFT::MaxAlignment, \ - ELFT::Is64Bits) - -// Section header. -template -struct Elf_Shdr_Base; - -template -struct Elf_Shdr_Base > { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) - Elf_Word sh_name; // Section name (index into string table) - Elf_Word sh_type; // Section type (SHT_*) - Elf_Word sh_flags; // Section flags (SHF_*) - Elf_Addr sh_addr; // Address where section is to be loaded - Elf_Off sh_offset; // File offset of section data, in bytes - Elf_Word sh_size; // Size of section, in bytes - Elf_Word sh_link; // Section type-specific header table index link - Elf_Word sh_info; // Section type-specific extra information - Elf_Word sh_addralign;// Section address alignment - Elf_Word sh_entsize; // Size of records contained within the section -}; - -template -struct Elf_Shdr_Base > { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) - Elf_Word sh_name; // Section name (index into string table) - Elf_Word sh_type; // Section type (SHT_*) - Elf_Xword sh_flags; // Section flags (SHF_*) - Elf_Addr sh_addr; // Address where section is to be loaded - Elf_Off sh_offset; // File offset of section data, in bytes - Elf_Xword sh_size; // Size of section, in bytes - Elf_Word sh_link; // Section type-specific header table index link - Elf_Word sh_info; // Section type-specific extra information - Elf_Xword sh_addralign;// Section address alignment - Elf_Xword sh_entsize; // Size of records contained within the section -}; - -template -struct Elf_Shdr_Impl : Elf_Shdr_Base { - using Elf_Shdr_Base::sh_entsize; - using Elf_Shdr_Base::sh_size; - - /// @brief Get the number of entities this section contains if it has any. - unsigned getEntityCount() const { - if (sh_entsize == 0) - return 0; - return sh_size / sh_entsize; - } -}; - -template -struct Elf_Sym_Base; - -template -struct Elf_Sym_Base > { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) - Elf_Word st_name; // Symbol name (index into string table) - Elf_Addr st_value; // Value or address associated with the symbol - Elf_Word st_size; // Size of the symbol - unsigned char st_info; // Symbol's type and binding attributes - unsigned char st_other; // Must be zero; reserved - Elf_Half st_shndx; // Which section (header table index) it's defined in -}; - -template -struct Elf_Sym_Base > { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) - Elf_Word st_name; // Symbol name (index into string table) - unsigned char st_info; // Symbol's type and binding attributes - unsigned char st_other; // Must be zero; reserved - Elf_Half st_shndx; // Which section (header table index) it's defined in - Elf_Addr st_value; // Value or address associated with the symbol - Elf_Xword st_size; // Size of the symbol -}; - -template -struct Elf_Sym_Impl : Elf_Sym_Base { - using Elf_Sym_Base::st_info; - - // These accessors and mutators correspond to the ELF32_ST_BIND, - // ELF32_ST_TYPE, and ELF32_ST_INFO macros defined in the ELF specification: - unsigned char getBinding() const { return st_info >> 4; } - unsigned char getType() const { return st_info & 0x0f; } - void setBinding(unsigned char b) { setBindingAndType(b, getType()); } - void setType(unsigned char t) { setBindingAndType(getBinding(), t); } - void setBindingAndType(unsigned char b, unsigned char t) { - st_info = (b << 4) + (t & 0x0f); - } -}; - -/// Elf_Versym: This is the structure of entries in the SHT_GNU_versym section -/// (.gnu.version). This structure is identical for ELF32 and ELF64. -template -struct Elf_Versym_Impl { - LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) - Elf_Half vs_index; // Version index with flags (e.g. VERSYM_HIDDEN) -}; - -template -struct Elf_Verdaux_Impl; - -/// Elf_Verdef: This is the structure of entries in the SHT_GNU_verdef section -/// (.gnu.version_d). This structure is identical for ELF32 and ELF64. -template -struct Elf_Verdef_Impl { - LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) - typedef Elf_Verdaux_Impl Elf_Verdaux; - Elf_Half vd_version; // Version of this structure (e.g. VER_DEF_CURRENT) - Elf_Half vd_flags; // Bitwise flags (VER_DEF_*) - Elf_Half vd_ndx; // Version index, used in .gnu.version entries - Elf_Half vd_cnt; // Number of Verdaux entries - Elf_Word vd_hash; // Hash of name - Elf_Word vd_aux; // Offset to the first Verdaux entry (in bytes) - Elf_Word vd_next; // Offset to the next Verdef entry (in bytes) - - /// Get the first Verdaux entry for this Verdef. - const Elf_Verdaux *getAux() const { - return reinterpret_cast((const char*)this + vd_aux); - } -}; - -/// Elf_Verdaux: This is the structure of auxiliary data in the SHT_GNU_verdef -/// section (.gnu.version_d). This structure is identical for ELF32 and ELF64. -template -struct Elf_Verdaux_Impl { - LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) - Elf_Word vda_name; // Version name (offset in string table) - Elf_Word vda_next; // Offset to next Verdaux entry (in bytes) -}; - -/// Elf_Verneed: This is the structure of entries in the SHT_GNU_verneed -/// section (.gnu.version_r). This structure is identical for ELF32 and ELF64. -template -struct Elf_Verneed_Impl { - LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) - Elf_Half vn_version; // Version of this structure (e.g. VER_NEED_CURRENT) - Elf_Half vn_cnt; // Number of associated Vernaux entries - Elf_Word vn_file; // Library name (string table offset) - Elf_Word vn_aux; // Offset to first Vernaux entry (in bytes) - Elf_Word vn_next; // Offset to next Verneed entry (in bytes) -}; - -/// Elf_Vernaux: This is the structure of auxiliary data in SHT_GNU_verneed -/// section (.gnu.version_r). This structure is identical for ELF32 and ELF64. -template -struct Elf_Vernaux_Impl { - LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) - Elf_Word vna_hash; // Hash of dependency name - Elf_Half vna_flags; // Bitwise Flags (VER_FLAG_*) - Elf_Half vna_other; // Version index, used in .gnu.version entries - Elf_Word vna_name; // Dependency name - Elf_Word vna_next; // Offset to next Vernaux entry (in bytes) -}; - -/// Elf_Dyn_Base: This structure matches the form of entries in the dynamic -/// table section (.dynamic) look like. -template -struct Elf_Dyn_Base; - -template -struct Elf_Dyn_Base > { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) - Elf_Sword d_tag; - union { - Elf_Word d_val; - Elf_Addr d_ptr; - } d_un; -}; - -template -struct Elf_Dyn_Base > { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) - Elf_Sxword d_tag; - union { - Elf_Xword d_val; - Elf_Addr d_ptr; - } d_un; -}; - -/// Elf_Dyn_Impl: This inherits from Elf_Dyn_Base, adding getters and setters. -template -struct Elf_Dyn_Impl : Elf_Dyn_Base { - using Elf_Dyn_Base::d_tag; - using Elf_Dyn_Base::d_un; - int64_t getTag() const { return d_tag; } - uint64_t getVal() const { return d_un.d_val; } - uint64_t getPtr() const { return d_un.ptr; } -}; - -// Elf_Rel: Elf Relocation -template -struct Elf_Rel_Base; - -template -struct Elf_Rel_Base, false> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) - Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) - Elf_Word r_info; // Symbol table index and type of relocation to apply - - uint32_t getRInfo(bool isMips64EL) const { - assert(!isMips64EL); - return r_info; - } - void setRInfo(uint32_t R) { - r_info = R; - } -}; - -template -struct Elf_Rel_Base, false> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) - Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) - Elf_Xword r_info; // Symbol table index and type of relocation to apply - - uint64_t getRInfo(bool isMips64EL) const { - uint64_t t = r_info; - if (!isMips64EL) - return t; - // Mip64 little endian has a "special" encoding of r_info. Instead of one - // 64 bit little endian number, it is a little ending 32 bit number followed - // by a 32 bit big endian number. - return (t << 32) | ((t >> 8) & 0xff000000) | ((t >> 24) & 0x00ff0000) | - ((t >> 40) & 0x0000ff00) | ((t >> 56) & 0x000000ff); - return r_info; - } - void setRInfo(uint64_t R) { - // FIXME: Add mips64el support. - r_info = R; - } -}; - -template -struct Elf_Rel_Base, true> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) - Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) - Elf_Word r_info; // Symbol table index and type of relocation to apply - Elf_Sword r_addend; // Compute value for relocatable field by adding this - - uint32_t getRInfo(bool isMips64EL) const { - assert(!isMips64EL); - return r_info; - } - void setRInfo(uint32_t R) { - r_info = R; - } -}; - -template -struct Elf_Rel_Base, true> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) - Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) - Elf_Xword r_info; // Symbol table index and type of relocation to apply - Elf_Sxword r_addend; // Compute value for relocatable field by adding this. - - uint64_t getRInfo(bool isMips64EL) const { - // Mip64 little endian has a "special" encoding of r_info. Instead of one - // 64 bit little endian number, it is a little ending 32 bit number followed - // by a 32 bit big endian number. - uint64_t t = r_info; - if (!isMips64EL) - return t; - 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; - } -}; - -template -struct Elf_Rel_Impl; - -template -struct Elf_Rel_Impl, isRela> - : Elf_Rel_Base, isRela> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) - - // These accessors and mutators correspond to the ELF64_R_SYM, ELF64_R_TYPE, - // and ELF64_R_INFO macros defined in the ELF specification: - uint32_t getSymbol(bool isMips64EL) const { - return (uint32_t) (this->getRInfo(isMips64EL) >> 32); - } - 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)); - } -}; - -template -struct Elf_Rel_Impl, isRela> - : Elf_Rel_Base, isRela> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) - - // These accessors and mutators correspond to the ELF32_R_SYM, ELF32_R_TYPE, - // and ELF32_R_INFO macros defined in the ELF specification: - uint32_t getSymbol(bool isMips64EL) const { - return this->getRInfo(isMips64EL) >> 8; - } - 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); - } -}; - -template -struct Elf_Ehdr_Impl { - LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) - unsigned char e_ident[ELF::EI_NIDENT]; // ELF Identification bytes - Elf_Half e_type; // Type of file (see ET_*) - Elf_Half e_machine; // Required architecture for this file (see EM_*) - Elf_Word e_version; // Must be equal to 1 - Elf_Addr e_entry; // Address to jump to in order to start program - Elf_Off e_phoff; // Program header table's file offset, in bytes - Elf_Off e_shoff; // Section header table's file offset, in bytes - Elf_Word e_flags; // Processor-specific flags - Elf_Half e_ehsize; // Size of ELF header, in bytes - Elf_Half e_phentsize;// Size of an entry in the program header table - Elf_Half e_phnum; // Number of entries in the program header table - Elf_Half e_shentsize;// Size of an entry in the section header table - Elf_Half e_shnum; // Number of entries in the section header table - Elf_Half e_shstrndx; // Section header table index of section name - // string table - bool checkMagic() const { - return (memcmp(e_ident, ELF::ElfMagic, strlen(ELF::ElfMagic))) == 0; - } - unsigned char getFileClass() const { return e_ident[ELF::EI_CLASS]; } - unsigned char getDataEncoding() const { return e_ident[ELF::EI_DATA]; } -}; - -template -struct Elf_Phdr_Impl; - -template -struct Elf_Phdr_Impl > { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) - Elf_Word p_type; // Type of segment - Elf_Off p_offset; // FileOffset where segment is located, in bytes - Elf_Addr p_vaddr; // Virtual Address of beginning of segment - Elf_Addr p_paddr; // Physical address of beginning of segment (OS-specific) - Elf_Word p_filesz; // Num. of bytes in file image of segment (may be zero) - Elf_Word p_memsz; // Num. of bytes in mem image of segment (may be zero) - Elf_Word p_flags; // Segment flags - Elf_Word p_align; // Segment alignment constraint -}; - -template -struct Elf_Phdr_Impl > { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) - Elf_Word p_type; // Type of segment - Elf_Word p_flags; // Segment flags - Elf_Off p_offset; // FileOffset where segment is located, in bytes - Elf_Addr p_vaddr; // Virtual Address of beginning of segment - Elf_Addr p_paddr; // Physical address of beginning of segment (OS-specific) - Elf_Xword p_filesz; // Num. of bytes in file image of segment (may be zero) - Elf_Xword p_memsz; // Num. of bytes in mem image of segment (may be zero) - Elf_Xword p_align; // Segment alignment constraint -}; - -template -class ELFObjectFile : public ObjectFile { +template +class ELFFile { +public: LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) + typedef typename conditional::type uintX_t; -public: /// \brief Iterate over constant sized entities. - template + template class ELFEntityIterator { public: typedef ptrdiff_t difference_type; @@ -504,9 +66,8 @@ public: /// \brief Default construct iterator. ELFEntityIterator() : EntitySize(0), Current(0) {} - ELFEntityIterator(uint64_t EntSize, const char *Start) - : EntitySize(EntSize) - , Current(Start) {} + ELFEntityIterator(uintX_t EntSize, const char *Start) + : EntitySize(EntSize), Current(Start) {} reference operator *() { assert(Current && "Attempted to dereference an invalid iterator!"); @@ -546,14 +107,16 @@ public: difference_type operator -(const ELFEntityIterator &Other) const { assert(EntitySize == Other.EntitySize && - "Subtracting iterators of different EntitiySize!"); + "Subtracting iterators of different EntitySize!"); return (Current - Other.Current) / EntitySize; } const char *get() const { return Current; } + uintX_t getEntSize() const { return EntitySize; } + private: - uint64_t EntitySize; + uintX_t EntitySize; const char *Current; }; @@ -569,46 +132,141 @@ public: typedef Elf_Verneed_Impl Elf_Verneed; typedef Elf_Vernaux_Impl Elf_Vernaux; typedef Elf_Versym_Impl Elf_Versym; - typedef ELFEntityIterator Elf_Dyn_iterator; - typedef ELFEntityIterator Elf_Sym_iterator; + typedef ELFEntityIterator Elf_Dyn_Iter; typedef ELFEntityIterator Elf_Rela_Iter; typedef ELFEntityIterator Elf_Rel_Iter; + typedef ELFEntityIterator Elf_Shdr_Iter; + + /// \brief Archive files are 2 byte aligned, so we need this for + /// PointerIntPair to work. + template + class ArchivePointerTypeTraits { + public: + static inline const void *getAsVoidPointer(T *P) { return P; } + static inline T *getFromVoidPointer(const void *P) { + return static_cast(P); + } + enum { NumLowBitsAvailable = 1 }; + }; + + class Elf_Sym_Iter { + public: + typedef ptrdiff_t difference_type; + typedef const Elf_Sym value_type; + typedef std::random_access_iterator_tag iterator_category; + typedef value_type &reference; + typedef value_type *pointer; + + /// \brief Default construct iterator. + Elf_Sym_Iter() : EntitySize(0), Current(0, false) {} + Elf_Sym_Iter(uintX_t EntSize, const char *Start, bool IsDynamic) + : EntitySize(EntSize), Current(Start, IsDynamic) {} + + reference operator*() { + assert(Current.getPointer() && + "Attempted to dereference an invalid iterator!"); + return *reinterpret_cast(Current.getPointer()); + } + + pointer operator->() { + assert(Current.getPointer() && + "Attempted to dereference an invalid iterator!"); + return reinterpret_cast(Current.getPointer()); + } + + bool operator==(const Elf_Sym_Iter &Other) { + return Current == Other.Current; + } + + bool operator!=(const Elf_Sym_Iter &Other) { return !(*this == Other); } + + Elf_Sym_Iter &operator++() { + assert(Current.getPointer() && + "Attempted to increment an invalid iterator!"); + Current.setPointer(Current.getPointer() + EntitySize); + return *this; + } -protected: - // 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. - bool isDyldELFObject; + Elf_Sym_Iter operator++(int) { + Elf_Sym_Iter Tmp = *this; + ++*this; + return Tmp; + } + + Elf_Sym_Iter operator+(difference_type Dist) { + assert(Current.getPointer() && + "Attempted to increment an invalid iterator!"); + Current.setPointer(Current.getPointer() + EntitySize * Dist); + return *this; + } + + Elf_Sym_Iter &operator=(const Elf_Sym_Iter &Other) { + EntitySize = Other.EntitySize; + Current = Other.Current; + return *this; + } + + difference_type operator-(const Elf_Sym_Iter &Other) const { + assert(EntitySize == Other.EntitySize && + "Subtracting iterators of different EntitySize!"); + return (Current.getPointer() - Other.Current.getPointer()) / EntitySize; + } + + const char *get() const { return Current.getPointer(); } + + bool isDynamic() const { return Current.getInt(); } + + uintX_t getEntSize() const { return EntitySize; } + + private: + uintX_t EntitySize; + PointerIntPair > Current; + }; private: typedef SmallVector Sections_t; typedef DenseMap IndexMap_t; - typedef DenseMap > RelocMap_t; + + MemoryBuffer *Buf; + + const uint8_t *base() const { + return reinterpret_cast(Buf->getBufferStart()); + } const Elf_Ehdr *Header; const Elf_Shdr *SectionHeaderTable; const Elf_Shdr *dot_shstrtab_sec; // Section header string table. const Elf_Shdr *dot_strtab_sec; // Symbol header string table. - const Elf_Shdr *dot_dynstr_sec; // Dynamic symbol string table. + const Elf_Shdr *dot_symtab_sec; // Symbol table section. - // SymbolTableSections[0] always points to the dynamic string table section - // header, or NULL if there is no dynamic string table. - Sections_t SymbolTableSections; - IndexMap_t SymbolTableSectionsIndexMap; - DenseMap ExtendedSymbolTable; + const Elf_Shdr *SymbolTableSectionHeaderIndex; + DenseMap ExtendedSymbolTable; - const Elf_Shdr *dot_dynamic_sec; // .dynamic const Elf_Shdr *dot_gnu_version_sec; // .gnu.version const Elf_Shdr *dot_gnu_version_r_sec; // .gnu.version_r const Elf_Shdr *dot_gnu_version_d_sec; // .gnu.version_d + /// \brief Represents a region described by entries in the .dynamic table. + struct DynRegionInfo { + DynRegionInfo() : Addr(0), Size(0), EntSize(0) {} + /// \brief Address in current address space. + const void *Addr; + /// \brief Size in bytes of the region. + uintX_t Size; + /// \brief Size of each entity in the region. + uintX_t EntSize; + }; + + DynRegionInfo DynamicRegion; + DynRegionInfo DynHashRegion; + DynRegionInfo DynStrRegion; + DynRegionInfo DynSymRegion; + // Pointer to SONAME entry in dynamic string table // This is set the first time getLoadName is called. mutable const char *dt_soname; -private: - uint64_t getROffset(DataRefImpl Rel) const; - // Records for each version index the corresponding Verdef or Vernaux entry. // This is filled the first time LoadVersionMap() is called. class VersionMapEntry : public PointerIntPair { @@ -635,103 +293,29 @@ private: void LoadVersionNeeds(const Elf_Shdr *ec) const; void LoadVersionMap() const; - /// @brief Map sections to an array of relocation sections that reference - /// them sorted by section index. - RelocMap_t SectionRelocMap; - - /// @brief Get the relocation section that contains \a Rel. - const Elf_Shdr *getRelSection(DataRefImpl Rel) const { - return getSection(Rel.w.b); - } - public: - bool isRelocationHasAddend(DataRefImpl Rel) const; - template - const T *getEntry(uint16_t Section, uint32_t Entry) const; template - const T *getEntry(const Elf_Shdr *Section, uint32_t Entry) const; - const Elf_Shdr *getSection(DataRefImpl index) const; - const Elf_Shdr *getSection(uint32_t index) const; - const Elf_Rel *getRel(DataRefImpl Rel) const; - const Elf_Rela *getRela(DataRefImpl Rela) const; + const T *getEntry(uint32_t Section, uint32_t Entry) const; + template + const T *getEntry(const Elf_Shdr *Section, uint32_t Entry) const; const char *getString(uint32_t section, uint32_t offset) const; const char *getString(const Elf_Shdr *section, uint32_t offset) const; - error_code getSymbolVersion(const Elf_Shdr *section, - const Elf_Sym *Symb, - StringRef &Version, - bool &IsDefault) const; + const char *getDynamicString(uintX_t Offset) const; + ErrorOr getSymbolVersion(const Elf_Shdr *section, + const Elf_Sym *Symb, + bool &IsDefault) const; void VerifyStrTab(const Elf_Shdr *sh) const; -protected: - const Elf_Sym *getSymbol(DataRefImpl Symb) const; // FIXME: Should be private? - void validateSymbol(DataRefImpl Symb) const; - StringRef getRelocationTypeName(uint32_t Type) const; + StringRef getRelocationTypeName(uint32_t Type) const; + void getRelocationTypeName(uint32_t Type, + SmallVectorImpl &Result) const; -public: - error_code getSymbolName(const Elf_Shdr *section, - const Elf_Sym *Symb, - StringRef &Res) const; - error_code getSectionName(const Elf_Shdr *section, - StringRef &Res) const; - const Elf_Dyn *getDyn(DataRefImpl DynData) const; - error_code getSymbolVersion(SymbolRef Symb, StringRef &Version, - bool &IsDefault) const; - uint64_t getSymbolIndex(const Elf_Sym *sym) const; -protected: - virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const; - virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const; - virtual error_code getSymbolFileOffset(DataRefImpl Symb, uint64_t &Res) const; - virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const; - virtual error_code getSymbolAlignment(DataRefImpl Symb, uint32_t &Res) const; - virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const; - virtual error_code getSymbolNMTypeChar(DataRefImpl Symb, char &Res) const; - virtual error_code getSymbolFlags(DataRefImpl Symb, uint32_t &Res) const; - virtual error_code getSymbolType(DataRefImpl Symb, SymbolRef::Type &Res) const; - virtual error_code getSymbolSection(DataRefImpl Symb, - section_iterator &Res) const; - virtual error_code getSymbolValue(DataRefImpl Symb, uint64_t &Val) const; - - virtual error_code getLibraryNext(DataRefImpl Data, LibraryRef &Result) const; - virtual error_code getLibraryPath(DataRefImpl Data, StringRef &Res) const; - - virtual error_code getSectionNext(DataRefImpl Sec, SectionRef &Res) const; - virtual error_code getSectionName(DataRefImpl Sec, StringRef &Res) const; - virtual error_code getSectionAddress(DataRefImpl Sec, uint64_t &Res) const; - virtual error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const; - virtual error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const; - virtual error_code getSectionAlignment(DataRefImpl Sec, uint64_t &Res) const; - virtual error_code isSectionText(DataRefImpl Sec, bool &Res) const; - virtual error_code isSectionData(DataRefImpl Sec, bool &Res) const; - virtual error_code isSectionBSS(DataRefImpl Sec, bool &Res) const; - virtual error_code isSectionRequiredForExecution(DataRefImpl Sec, - bool &Res) const; - virtual error_code isSectionVirtual(DataRefImpl Sec, bool &Res) const; - virtual error_code isSectionZeroInit(DataRefImpl Sec, bool &Res) const; - virtual error_code isSectionReadOnlyData(DataRefImpl Sec, bool &Res) const; - virtual error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, - bool &Result) const; - virtual relocation_iterator getSectionRelBegin(DataRefImpl Sec) const; - virtual relocation_iterator getSectionRelEnd(DataRefImpl Sec) const; - - virtual error_code getRelocationNext(DataRefImpl Rel, - RelocationRef &Res) const; - virtual error_code getRelocationAddress(DataRefImpl Rel, - uint64_t &Res) const; - virtual error_code getRelocationOffset(DataRefImpl Rel, - uint64_t &Res) const; - virtual error_code getRelocationSymbol(DataRefImpl Rel, - SymbolRef &Res) const; - virtual error_code getRelocationType(DataRefImpl Rel, - uint64_t &Res) const; - virtual error_code getRelocationTypeName(DataRefImpl Rel, - SmallVectorImpl &Result) const; - virtual error_code getRelocationAdditionalInfo(DataRefImpl Rel, - int64_t &Res) const; - virtual error_code getRelocationValueString(DataRefImpl Rel, - SmallVectorImpl &Result) const; + /// \brief Get the symbol table section and symbol for a given relocation. + template + std::pair + getRelocationSymbol(const Elf_Shdr *RelSec, const RelT *Rel) const; -public: - ELFObjectFile(MemoryBuffer *Object, error_code &ec); + ELFFile(MemoryBuffer *Object, error_code &ec); bool isMips64EL() const { return Header->e_machine == ELF::EM_MIPS && @@ -739,65 +323,51 @@ public: Header->getDataEncoding() == ELF::ELFDATA2LSB; } - virtual symbol_iterator begin_symbols() const; - virtual symbol_iterator end_symbols() const; - - virtual symbol_iterator begin_dynamic_symbols() const; - virtual symbol_iterator end_dynamic_symbols() const; - - virtual section_iterator begin_sections() const; - virtual section_iterator end_sections() const; + Elf_Shdr_Iter begin_sections() const; + Elf_Shdr_Iter end_sections() const; - virtual library_iterator begin_libraries_needed() const; - virtual library_iterator end_libraries_needed() const; + Elf_Sym_Iter begin_symbols() const; + Elf_Sym_Iter end_symbols() const; - const Elf_Shdr *getDynamicSymbolTableSectionHeader() const { - return SymbolTableSections[0]; - } - - const Elf_Shdr *getDynamicStringTableSectionHeader() const { - return dot_dynstr_sec; - } - - Elf_Dyn_iterator begin_dynamic_table() const; + Elf_Dyn_Iter begin_dynamic_table() const; /// \param NULLEnd use one past the first DT_NULL entry as the end instead of /// the section size. - Elf_Dyn_iterator end_dynamic_table(bool NULLEnd = false) const; - - Elf_Sym_iterator begin_elf_dynamic_symbols() const { - const Elf_Shdr *DynSymtab = SymbolTableSections[0]; - if (DynSymtab) - return Elf_Sym_iterator(DynSymtab->sh_entsize, - (const char *)base() + DynSymtab->sh_offset); - return Elf_Sym_iterator(0, 0); + Elf_Dyn_Iter end_dynamic_table(bool NULLEnd = false) const; + + Elf_Sym_Iter begin_dynamic_symbols() const { + if (DynSymRegion.Addr) + return Elf_Sym_Iter(DynSymRegion.EntSize, (const char *)DynSymRegion.Addr, + true); + return Elf_Sym_Iter(0, 0, true); } - Elf_Sym_iterator end_elf_dynamic_symbols() const { - const Elf_Shdr *DynSymtab = SymbolTableSections[0]; - if (DynSymtab) - return Elf_Sym_iterator(DynSymtab->sh_entsize, (const char *)base() + - DynSymtab->sh_offset + DynSymtab->sh_size); - return Elf_Sym_iterator(0, 0); + Elf_Sym_Iter end_dynamic_symbols() const { + if (DynSymRegion.Addr) + return Elf_Sym_Iter(DynSymRegion.EntSize, + (const char *)DynSymRegion.Addr + DynSymRegion.Size, + true); + return Elf_Sym_Iter(0, 0, true); } - Elf_Rela_Iter beginELFRela(const Elf_Shdr *sec) const { + Elf_Rela_Iter begin_rela(const Elf_Shdr *sec) const { return Elf_Rela_Iter(sec->sh_entsize, (const char *)(base() + sec->sh_offset)); } - Elf_Rela_Iter endELFRela(const Elf_Shdr *sec) const { - return Elf_Rela_Iter(sec->sh_entsize, (const char *) - (base() + sec->sh_offset + sec->sh_size)); + Elf_Rela_Iter end_rela(const Elf_Shdr *sec) const { + return Elf_Rela_Iter( + sec->sh_entsize, + (const char *)(base() + sec->sh_offset + sec->sh_size)); } - Elf_Rel_Iter beginELFRel(const Elf_Shdr *sec) const { + Elf_Rel_Iter begin_rel(const Elf_Shdr *sec) const { return Elf_Rel_Iter(sec->sh_entsize, (const char *)(base() + sec->sh_offset)); } - Elf_Rel_Iter endELFRel(const Elf_Shdr *sec) const { - return Elf_Rel_Iter(sec->sh_entsize, (const char *) - (base() + sec->sh_offset + sec->sh_size)); + Elf_Rel_Iter end_rel(const Elf_Shdr *sec) const { + return Elf_Rel_Iter(sec->sh_entsize, + (const char *)(base() + sec->sh_offset + sec->sh_size)); } /// \brief Iterate over program header table. @@ -815,36 +385,42 @@ public: (Header->e_phnum * Header->e_phentsize)); } - virtual uint8_t getBytesInAddress() const; - virtual StringRef getFileFormatName() const; - virtual StringRef getObjectType() const { return "ELF"; } - virtual unsigned getArch() const; - virtual StringRef getLoadName() const; - virtual error_code getSectionContents(const Elf_Shdr *sec, - StringRef &Res) const; - uint64_t getNumSections() const; - uint64_t getStringTableIndex() const; + uintX_t getStringTableIndex() const; ELF::Elf64_Word getSymbolTableIndex(const Elf_Sym *symb) const; - const Elf_Ehdr *getElfHeader() const; + const Elf_Ehdr *getHeader() const { return Header; } const Elf_Shdr *getSection(const Elf_Sym *symb) const; - const Elf_Shdr *getElfSection(section_iterator &It) const; - const Elf_Sym *getElfSymbol(symbol_iterator &It) const; - const Elf_Sym *getElfSymbol(uint32_t index) const; - - // Methods for type inquiry through isa, cast, and dyn_cast - bool isDyldType() const { return isDyldELFObject; } - static inline bool classof(const Binary *v) { - return v->getType() == getELFType(ELFT::TargetEndianness == support::little, - ELFT::Is64Bits); - } + const Elf_Shdr *getSection(uint32_t Index) const; + const Elf_Sym *getSymbol(uint32_t index) const; + + ErrorOr getSymbolName(Elf_Sym_Iter Sym) const; + + /// \brief Get the name of \p Symb. + /// \param SymTab The symbol table section \p Symb is contained in. + /// \param Symb The symbol to get the name of. + /// + /// \p SymTab is used to lookup the string table to use to get the symbol's + /// name. + ErrorOr getSymbolName(const Elf_Shdr *SymTab, + const Elf_Sym *Symb) const; + ErrorOr getSectionName(const Elf_Shdr *Section) const; + uint64_t getSymbolIndex(const Elf_Sym *sym) const; + ErrorOr > getSectionContents(const Elf_Shdr *Sec) const; + StringRef getLoadName() const; }; +// Use an alignment of 2 for the typedefs since that is the worst case for +// ELF files in archives. +typedef ELFFile > ELF32LEFile; +typedef ELFFile > ELF64LEFile; +typedef ELFFile > ELF32BEFile; +typedef ELFFile > ELF64BEFile; + // Iterate through the version definitions, and place each Elf_Verdef // in the VersionMap according to its index. -template -void ELFObjectFile::LoadVersionDefs(const Elf_Shdr *sec) const { - unsigned vd_size = sec->sh_size; // Size of section in bytes +template +void ELFFile::LoadVersionDefs(const Elf_Shdr *sec) const { + unsigned vd_size = sec->sh_size; // Size of section in bytes unsigned vd_count = sec->sh_info; // Number of Verdef entries const char *sec_start = (const char*)base() + sec->sh_offset; const char *sec_end = sec_start + vd_size; @@ -859,7 +435,7 @@ void ELFObjectFile::LoadVersionDefs(const Elf_Shdr *sec) const { report_fatal_error("Unexpected verdef version"); size_t index = vd->vd_ndx & ELF::VERSYM_VERSION; if (index >= VersionMap.size()) - VersionMap.resize(index+1); + VersionMap.resize(index + 1); VersionMap[index] = VersionMapEntry(vd); p += vd->vd_next; } @@ -867,11 +443,11 @@ void ELFObjectFile::LoadVersionDefs(const Elf_Shdr *sec) const { // Iterate through the versions needed section, and place each Elf_Vernaux // in the VersionMap according to its index. -template -void ELFObjectFile::LoadVersionNeeds(const Elf_Shdr *sec) const { - unsigned vn_size = sec->sh_size; // Size of section in bytes +template +void ELFFile::LoadVersionNeeds(const Elf_Shdr *sec) const { + unsigned vn_size = sec->sh_size; // Size of section in bytes unsigned vn_count = sec->sh_info; // Number of Verneed entries - const char *sec_start = (const char*)base() + sec->sh_offset; + const char *sec_start = (const char *)base() + sec->sh_offset; const char *sec_end = sec_start + vn_size; // The first Verneed entry is at the start of the section. const char *p = sec_start; @@ -891,7 +467,7 @@ void ELFObjectFile::LoadVersionNeeds(const Elf_Shdr *sec) const { const Elf_Vernaux *vna = reinterpret_cast(paux); size_t index = vna->vna_other & ELF::VERSYM_VERSION; if (index >= VersionMap.size()) - VersionMap.resize(index+1); + VersionMap.resize(index + 1); VersionMap[index] = VersionMapEntry(vna); paux += vna->vna_next; } @@ -899,10 +475,10 @@ void ELFObjectFile::LoadVersionNeeds(const Elf_Shdr *sec) const { } } -template -void ELFObjectFile::LoadVersionMap() const { +template +void ELFFile::LoadVersionMap() const { // If there is no dynamic symtab or version table, there is nothing to do. - if (SymbolTableSections[0] == NULL || dot_gnu_version_sec == NULL) + if (DynSymRegion.Addr == NULL || dot_gnu_version_sec == NULL) return; // Has the VersionMap already been loaded? @@ -921,83 +497,16 @@ void ELFObjectFile::LoadVersionMap() const { LoadVersionNeeds(dot_gnu_version_r_sec); } -template -void ELFObjectFile::validateSymbol(DataRefImpl Symb) const { -#ifndef NDEBUG - const Elf_Sym *symb = getSymbol(Symb); - const Elf_Shdr *SymbolTableSection = SymbolTableSections[Symb.d.b]; - // FIXME: We really need to do proper error handling in the case of an invalid - // input file. Because we don't use exceptions, I think we'll just pass - // an error object around. - if (!( symb - && SymbolTableSection - && symb >= (const Elf_Sym*)(base() - + SymbolTableSection->sh_offset) - && symb < (const Elf_Sym*)(base() - + SymbolTableSection->sh_offset - + SymbolTableSection->sh_size))) - // FIXME: Proper error handling. - report_fatal_error("Symb must point to a valid symbol!"); -#endif -} - -template -error_code ELFObjectFile::getSymbolNext(DataRefImpl Symb, - SymbolRef &Result) const { - validateSymbol(Symb); - const Elf_Shdr *SymbolTableSection = SymbolTableSections[Symb.d.b]; - - ++Symb.d.a; - // Check to see if we are at the end of this symbol table. - if (Symb.d.a >= SymbolTableSection->getEntityCount()) { - // We are at the end. If there are other symbol tables, jump to them. - // If the symbol table is .dynsym, we are iterating dynamic symbols, - // and there is only one table of these. - if (Symb.d.b != 0) { - ++Symb.d.b; - Symb.d.a = 1; // The 0th symbol in ELF is fake. - } - // Otherwise return the terminator. - if (Symb.d.b == 0 || Symb.d.b >= SymbolTableSections.size()) { - Symb.d.a = std::numeric_limits::max(); - Symb.d.b = std::numeric_limits::max(); - } - } - - Result = SymbolRef(Symb, this); - return object_error::success; -} - -template -error_code ELFObjectFile::getSymbolName(DataRefImpl Symb, - StringRef &Result) const { - validateSymbol(Symb); - const Elf_Sym *symb = getSymbol(Symb); - return getSymbolName(SymbolTableSections[Symb.d.b], symb, Result); -} - -template -error_code ELFObjectFile::getSymbolVersion(SymbolRef SymRef, - StringRef &Version, - bool &IsDefault) const { - DataRefImpl Symb = SymRef.getRawDataRefImpl(); - validateSymbol(Symb); - const Elf_Sym *symb = getSymbol(Symb); - return getSymbolVersion(SymbolTableSections[Symb.d.b], symb, - Version, IsDefault); -} - -template -ELF::Elf64_Word ELFObjectFile - ::getSymbolTableIndex(const Elf_Sym *symb) const { +template +ELF::Elf64_Word ELFFile::getSymbolTableIndex(const Elf_Sym *symb) const { if (symb->st_shndx == ELF::SHN_XINDEX) return ExtendedSymbolTable.lookup(symb); return symb->st_shndx; } -template -const typename ELFObjectFile::Elf_Shdr * -ELFObjectFile::getSection(const Elf_Sym *symb) const { +template +const typename ELFFile::Elf_Shdr * +ELFFile::getSection(const Elf_Sym *symb) const { if (symb->st_shndx == ELF::SHN_XINDEX) return getSection(ExtendedSymbolTable.lookup(symb)); if (symb->st_shndx >= ELF::SHN_LORESERVE) @@ -1005,1202 +514,36 @@ ELFObjectFile::getSection(const Elf_Sym *symb) const { return getSection(symb->st_shndx); } -template -const typename ELFObjectFile::Elf_Ehdr * -ELFObjectFile::getElfHeader() const { - return Header; -} - -template -const typename ELFObjectFile::Elf_Shdr * -ELFObjectFile::getElfSection(section_iterator &It) const { - llvm::object::DataRefImpl ShdrRef = It->getRawDataRefImpl(); - return reinterpret_cast(ShdrRef.p); -} - -template -const typename ELFObjectFile::Elf_Sym * -ELFObjectFile::getElfSymbol(symbol_iterator &It) const { - return getSymbol(It->getRawDataRefImpl()); -} - -template -const typename ELFObjectFile::Elf_Sym * -ELFObjectFile::getElfSymbol(uint32_t index) const { - DataRefImpl SymbolData; - SymbolData.d.a = index; - SymbolData.d.b = 1; - return getSymbol(SymbolData); -} - -template -error_code ELFObjectFile::getSymbolFileOffset(DataRefImpl Symb, - uint64_t &Result) const { - validateSymbol(Symb); - const Elf_Sym *symb = getSymbol(Symb); - const Elf_Shdr *Section; - switch (getSymbolTableIndex(symb)) { - case ELF::SHN_COMMON: - // Unintialized symbols have no offset in the object file - case ELF::SHN_UNDEF: - Result = UnknownAddressOrSize; - return object_error::success; - case ELF::SHN_ABS: - Result = symb->st_value; - return object_error::success; - default: Section = getSection(symb); - } - - switch (symb->getType()) { - case ELF::STT_SECTION: - Result = Section ? Section->sh_offset : UnknownAddressOrSize; - return object_error::success; - case ELF::STT_FUNC: - case ELF::STT_OBJECT: - case ELF::STT_NOTYPE: - Result = symb->st_value + - (Section ? Section->sh_offset : 0); - return object_error::success; - default: - Result = UnknownAddressOrSize; - return object_error::success; - } -} - -template -error_code ELFObjectFile::getSymbolAddress(DataRefImpl Symb, - uint64_t &Result) const { - validateSymbol(Symb); - const Elf_Sym *symb = getSymbol(Symb); - const Elf_Shdr *Section; - switch (getSymbolTableIndex(symb)) { - case ELF::SHN_COMMON: - case ELF::SHN_UNDEF: - Result = UnknownAddressOrSize; - return object_error::success; - case ELF::SHN_ABS: - Result = symb->st_value; - return object_error::success; - default: Section = getSection(symb); - } - - switch (symb->getType()) { - case ELF::STT_SECTION: - Result = Section ? Section->sh_addr : UnknownAddressOrSize; - return object_error::success; - case ELF::STT_FUNC: - case ELF::STT_OBJECT: - case ELF::STT_NOTYPE: - bool IsRelocatable; - switch(Header->e_type) { - case ELF::ET_EXEC: - case ELF::ET_DYN: - IsRelocatable = false; - break; - default: - IsRelocatable = true; - } - Result = symb->st_value; - - // Clear the ARM/Thumb indicator flag. - if (Header->e_machine == ELF::EM_ARM) - Result &= ~1; - - if (IsRelocatable && Section != 0) - Result += Section->sh_addr; - return object_error::success; - default: - Result = UnknownAddressOrSize; - return object_error::success; - } -} - -template -error_code ELFObjectFile::getSymbolAlignment(DataRefImpl Symb, - uint32_t &Res) const { - uint32_t flags; - getSymbolFlags(Symb, flags); - if (flags & SymbolRef::SF_Common) { - uint64_t Value; - getSymbolValue(Symb, Value); - Res = Value; - } else { - Res = 0; - } - return object_error::success; -} - -template -error_code ELFObjectFile::getSymbolSize(DataRefImpl Symb, - uint64_t &Result) const { - validateSymbol(Symb); - const Elf_Sym *symb = getSymbol(Symb); - if (symb->st_size == 0) - Result = UnknownAddressOrSize; - Result = symb->st_size; - return object_error::success; -} - -template -error_code ELFObjectFile::getSymbolNMTypeChar(DataRefImpl Symb, - char &Result) const { - validateSymbol(Symb); - const Elf_Sym *symb = getSymbol(Symb); - const Elf_Shdr *Section = getSection(symb); - - char ret = '?'; - - if (Section) { - switch (Section->sh_type) { - case ELF::SHT_PROGBITS: - case ELF::SHT_DYNAMIC: - switch (Section->sh_flags) { - case (ELF::SHF_ALLOC | ELF::SHF_EXECINSTR): - ret = 't'; break; - case (ELF::SHF_ALLOC | ELF::SHF_WRITE): - ret = 'd'; break; - case ELF::SHF_ALLOC: - case (ELF::SHF_ALLOC | ELF::SHF_MERGE): - case (ELF::SHF_ALLOC | ELF::SHF_MERGE | ELF::SHF_STRINGS): - ret = 'r'; break; - } - break; - case ELF::SHT_NOBITS: ret = 'b'; - } - } - - switch (getSymbolTableIndex(symb)) { - case ELF::SHN_UNDEF: - if (ret == '?') - ret = 'U'; - break; - case ELF::SHN_ABS: ret = 'a'; break; - case ELF::SHN_COMMON: ret = 'c'; break; - } - - switch (symb->getBinding()) { - case ELF::STB_GLOBAL: ret = ::toupper(ret); break; - case ELF::STB_WEAK: - if (getSymbolTableIndex(symb) == ELF::SHN_UNDEF) - ret = 'w'; - else - if (symb->getType() == ELF::STT_OBJECT) - ret = 'V'; - else - ret = 'W'; - } - - if (ret == '?' && symb->getType() == ELF::STT_SECTION) { - StringRef name; - if (error_code ec = getSymbolName(Symb, name)) - return ec; - Result = StringSwitch(name) - .StartsWith(".debug", 'N') - .StartsWith(".note", 'n') - .Default('?'); - return object_error::success; - } - - Result = ret; - return object_error::success; -} - -template -error_code ELFObjectFile::getSymbolType(DataRefImpl Symb, - SymbolRef::Type &Result) const { - validateSymbol(Symb); - const Elf_Sym *symb = getSymbol(Symb); - - switch (symb->getType()) { - case ELF::STT_NOTYPE: - Result = SymbolRef::ST_Unknown; - break; - case ELF::STT_SECTION: - Result = SymbolRef::ST_Debug; - break; - case ELF::STT_FILE: - Result = SymbolRef::ST_File; - break; - case ELF::STT_FUNC: - Result = SymbolRef::ST_Function; - break; - case ELF::STT_OBJECT: - case ELF::STT_COMMON: - case ELF::STT_TLS: - Result = SymbolRef::ST_Data; - break; - default: - Result = SymbolRef::ST_Other; - break; - } - return object_error::success; -} - -template -error_code ELFObjectFile::getSymbolFlags(DataRefImpl Symb, - uint32_t &Result) const { - validateSymbol(Symb); - const Elf_Sym *symb = getSymbol(Symb); - - Result = SymbolRef::SF_None; - - if (symb->getBinding() != ELF::STB_LOCAL) - Result |= SymbolRef::SF_Global; - - if (symb->getBinding() == ELF::STB_WEAK) - Result |= SymbolRef::SF_Weak; - - if (symb->st_shndx == ELF::SHN_ABS) - Result |= SymbolRef::SF_Absolute; - - if (symb->getType() == ELF::STT_FILE || - symb->getType() == ELF::STT_SECTION) - Result |= SymbolRef::SF_FormatSpecific; - - if (getSymbolTableIndex(symb) == ELF::SHN_UNDEF) - Result |= SymbolRef::SF_Undefined; - - if (symb->getType() == ELF::STT_COMMON || - getSymbolTableIndex(symb) == ELF::SHN_COMMON) - Result |= SymbolRef::SF_Common; - - if (symb->getType() == ELF::STT_TLS) - Result |= SymbolRef::SF_ThreadLocal; - - return object_error::success; -} - -template -error_code ELFObjectFile::getSymbolSection(DataRefImpl Symb, - section_iterator &Res) const { - validateSymbol(Symb); - const Elf_Sym *symb = getSymbol(Symb); - const Elf_Shdr *sec = getSection(symb); - if (!sec) - Res = end_sections(); - else { - DataRefImpl Sec; - Sec.p = reinterpret_cast(sec); - Res = section_iterator(SectionRef(Sec, this)); - } - return object_error::success; -} - -template -error_code ELFObjectFile::getSymbolValue(DataRefImpl Symb, - uint64_t &Val) const { - validateSymbol(Symb); - const Elf_Sym *symb = getSymbol(Symb); - Val = symb->st_value; - return object_error::success; -} - -template -error_code ELFObjectFile::getSectionNext(DataRefImpl Sec, - SectionRef &Result) const { - const uint8_t *sec = reinterpret_cast(Sec.p); - sec += Header->e_shentsize; - Sec.p = reinterpret_cast(sec); - Result = SectionRef(Sec, this); - return object_error::success; -} - -template -error_code ELFObjectFile::getSectionName(DataRefImpl Sec, - StringRef &Result) const { - const Elf_Shdr *sec = reinterpret_cast(Sec.p); - Result = StringRef(getString(dot_shstrtab_sec, sec->sh_name)); - return object_error::success; -} - -template -error_code ELFObjectFile::getSectionAddress(DataRefImpl Sec, - uint64_t &Result) const { - const Elf_Shdr *sec = reinterpret_cast(Sec.p); - Result = sec->sh_addr; - return object_error::success; -} - -template -error_code ELFObjectFile::getSectionSize(DataRefImpl Sec, - uint64_t &Result) const { - const Elf_Shdr *sec = reinterpret_cast(Sec.p); - Result = sec->sh_size; - return object_error::success; -} - -template -error_code ELFObjectFile::getSectionContents(DataRefImpl Sec, - StringRef &Result) const { - const Elf_Shdr *sec = reinterpret_cast(Sec.p); - const char *start = (const char*)base() + sec->sh_offset; - Result = StringRef(start, sec->sh_size); - return object_error::success; -} - -template -error_code ELFObjectFile::getSectionContents(const Elf_Shdr *Sec, - StringRef &Result) const { - const char *start = (const char*)base() + Sec->sh_offset; - Result = StringRef(start, Sec->sh_size); - return object_error::success; -} - -template -error_code ELFObjectFile::getSectionAlignment(DataRefImpl Sec, - uint64_t &Result) const { - const Elf_Shdr *sec = reinterpret_cast(Sec.p); - Result = sec->sh_addralign; - return object_error::success; -} - -template -error_code ELFObjectFile::isSectionText(DataRefImpl Sec, - bool &Result) const { - const Elf_Shdr *sec = reinterpret_cast(Sec.p); - if (sec->sh_flags & ELF::SHF_EXECINSTR) - Result = true; - else - Result = false; - return object_error::success; -} - -template -error_code ELFObjectFile::isSectionData(DataRefImpl Sec, - bool &Result) const { - const Elf_Shdr *sec = reinterpret_cast(Sec.p); - if (sec->sh_flags & (ELF::SHF_ALLOC | ELF::SHF_WRITE) - && sec->sh_type == ELF::SHT_PROGBITS) - Result = true; - else - Result = false; - return object_error::success; -} - -template -error_code ELFObjectFile::isSectionBSS(DataRefImpl Sec, - bool &Result) const { - const Elf_Shdr *sec = reinterpret_cast(Sec.p); - if (sec->sh_flags & (ELF::SHF_ALLOC | ELF::SHF_WRITE) - && sec->sh_type == ELF::SHT_NOBITS) - Result = true; - else - Result = false; - return object_error::success; -} - -template -error_code ELFObjectFile::isSectionRequiredForExecution( - DataRefImpl Sec, bool &Result) const { - const Elf_Shdr *sec = reinterpret_cast(Sec.p); - if (sec->sh_flags & ELF::SHF_ALLOC) - Result = true; - else - Result = false; - return object_error::success; -} - -template -error_code ELFObjectFile::isSectionVirtual(DataRefImpl Sec, - bool &Result) const { - const Elf_Shdr *sec = reinterpret_cast(Sec.p); - if (sec->sh_type == ELF::SHT_NOBITS) - Result = true; - else - Result = false; - return object_error::success; -} - -template -error_code ELFObjectFile::isSectionZeroInit(DataRefImpl Sec, - bool &Result) const { - const Elf_Shdr *sec = reinterpret_cast(Sec.p); - // For ELF, all zero-init sections are virtual (that is, they occupy no space - // in the object image) and vice versa. - Result = sec->sh_type == ELF::SHT_NOBITS; - return object_error::success; -} - -template -error_code ELFObjectFile::isSectionReadOnlyData(DataRefImpl Sec, - bool &Result) const { - const Elf_Shdr *sec = reinterpret_cast(Sec.p); - if (sec->sh_flags & ELF::SHF_WRITE || sec->sh_flags & ELF::SHF_EXECINSTR) - Result = false; - else - Result = true; - return object_error::success; -} - -template -error_code ELFObjectFile::sectionContainsSymbol(DataRefImpl Sec, - DataRefImpl Symb, - bool &Result) const { - validateSymbol(Symb); - - const Elf_Shdr *sec = reinterpret_cast(Sec.p); - const Elf_Sym *symb = getSymbol(Symb); - - unsigned shndx = symb->st_shndx; - bool Reserved = shndx >= ELF::SHN_LORESERVE - && shndx <= ELF::SHN_HIRESERVE; - - Result = !Reserved && (sec == getSection(symb->st_shndx)); - return object_error::success; -} - -template -relocation_iterator -ELFObjectFile::getSectionRelBegin(DataRefImpl Sec) const { - DataRefImpl RelData; - const Elf_Shdr *sec = reinterpret_cast(Sec.p); - typename RelocMap_t::const_iterator ittr = SectionRelocMap.find(sec); - if (sec != 0 && ittr != SectionRelocMap.end()) { - RelData.w.a = getSection(ittr->second[0])->sh_info; - RelData.w.b = ittr->second[0]; - RelData.w.c = 0; - } - return relocation_iterator(RelocationRef(RelData, this)); -} - -template -relocation_iterator -ELFObjectFile::getSectionRelEnd(DataRefImpl Sec) const { - DataRefImpl RelData; - const Elf_Shdr *sec = reinterpret_cast(Sec.p); - typename RelocMap_t::const_iterator ittr = SectionRelocMap.find(sec); - if (sec != 0 && ittr != SectionRelocMap.end()) { - // Get the index of the last relocation section for this section. - std::size_t relocsecindex = ittr->second[ittr->second.size() - 1]; - const Elf_Shdr *relocsec = getSection(relocsecindex); - RelData.w.a = relocsec->sh_info; - RelData.w.b = relocsecindex; - RelData.w.c = relocsec->sh_size / relocsec->sh_entsize; - } - return relocation_iterator(RelocationRef(RelData, this)); -} - -// Relocations -template -error_code ELFObjectFile::getRelocationNext(DataRefImpl Rel, - RelocationRef &Result) const { - ++Rel.w.c; - const Elf_Shdr *relocsec = getSection(Rel.w.b); - if (Rel.w.c >= (relocsec->sh_size / relocsec->sh_entsize)) { - // We have reached the end of the relocations for this section. See if there - // is another relocation section. - typename RelocMap_t::mapped_type relocseclist = - SectionRelocMap.lookup(getSection(Rel.w.a)); - - // Do a binary search for the current reloc section index (which must be - // present). Then get the next one. - typename RelocMap_t::mapped_type::const_iterator loc = - std::lower_bound(relocseclist.begin(), relocseclist.end(), Rel.w.b); - ++loc; - - // If there is no next one, don't do anything. The ++Rel.w.c above sets Rel - // to the end iterator. - if (loc != relocseclist.end()) { - Rel.w.b = *loc; - Rel.w.a = 0; - } - } - Result = RelocationRef(Rel, this); - return object_error::success; +template +const typename ELFFile::Elf_Sym * +ELFFile::getSymbol(uint32_t Index) const { + return &*(begin_symbols() + Index); } -template -error_code ELFObjectFile::getRelocationSymbol(DataRefImpl Rel, - SymbolRef &Result) const { - uint32_t symbolIdx; - const Elf_Shdr *sec = getSection(Rel.w.b); - switch (sec->sh_type) { - default : - report_fatal_error("Invalid section type in Rel!"); - case ELF::SHT_REL : { - symbolIdx = getRel(Rel)->getSymbol(isMips64EL()); - break; - } - case ELF::SHT_RELA : { - symbolIdx = getRela(Rel)->getSymbol(isMips64EL()); - break; - } - } - DataRefImpl SymbolData; - IndexMap_t::const_iterator it = SymbolTableSectionsIndexMap.find(sec->sh_link); - if (it == SymbolTableSectionsIndexMap.end()) - report_fatal_error("Relocation symbol table not found!"); - SymbolData.d.a = symbolIdx; - SymbolData.d.b = it->second; - Result = SymbolRef(SymbolData, this); - return object_error::success; -} - -template -error_code ELFObjectFile::getRelocationAddress(DataRefImpl Rel, - uint64_t &Result) const { - assert((Header->e_type == ELF::ET_EXEC || Header->e_type == ELF::ET_DYN) && - "Only executable and shared objects files have addresses"); - Result = getROffset(Rel); - return object_error::success; -} - -template -error_code ELFObjectFile::getRelocationOffset(DataRefImpl Rel, - uint64_t &Result) const { - assert(Header->e_type == ELF::ET_REL && - "Only relocatable object files have relocation offsets"); - Result = getROffset(Rel); - return object_error::success; -} - -template -uint64_t ELFObjectFile::getROffset(DataRefImpl Rel) const { - const Elf_Shdr *sec = getSection(Rel.w.b); - switch (sec->sh_type) { - default: - report_fatal_error("Invalid section type in Rel!"); - case ELF::SHT_REL: - return getRel(Rel)->r_offset; - case ELF::SHT_RELA: - return getRela(Rel)->r_offset; - } -} - -template -error_code ELFObjectFile::getRelocationType(DataRefImpl Rel, - uint64_t &Result) const { - const Elf_Shdr *sec = getSection(Rel.w.b); - switch (sec->sh_type) { - default : - report_fatal_error("Invalid section type in Rel!"); - case ELF::SHT_REL : { - Result = getRel(Rel)->getType(isMips64EL()); - break; - } - case ELF::SHT_RELA : { - Result = getRela(Rel)->getType(isMips64EL()); - break; - } - } - return object_error::success; +template +ErrorOr > +ELFFile::getSectionContents(const Elf_Shdr *Sec) const { + if (Sec->sh_offset + Sec->sh_size > Buf->getBufferSize()) + return object_error::parse_failed; + const uint8_t *Start = base() + Sec->sh_offset; + return ArrayRef(Start, Sec->sh_size); } -#define LLVM_ELF_SWITCH_RELOC_TYPE_NAME(enum) \ - case ELF::enum: Res = #enum; break; - -template -StringRef ELFObjectFile::getRelocationTypeName(uint32_t Type) const { - StringRef Res = "Unknown"; - switch (Header->e_machine) { - case ELF::EM_X86_64: - switch (Type) { - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_NONE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_PC32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOT32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_PLT32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_COPY); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GLOB_DAT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_JUMP_SLOT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_RELATIVE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOTPCREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_32S); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_PC16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_8); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_PC8); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_DTPMOD64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_DTPOFF64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_TPOFF64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_TLSGD); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_TLSLD); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_DTPOFF32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOTTPOFF); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_TPOFF32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_PC64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOTOFF64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOTPC32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOT64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOTPCREL64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOTPC64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOTPLT64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_PLTOFF64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_SIZE32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_SIZE64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOTPC32_TLSDESC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_TLSDESC_CALL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_TLSDESC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_IRELATIVE); - default: break; - } - break; - case ELF::EM_386: - switch (Type) { - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_NONE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_PC32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_GOT32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_PLT32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_COPY); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_GLOB_DAT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_JUMP_SLOT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_RELATIVE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_GOTOFF); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_GOTPC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_32PLT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_TPOFF); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_IE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_GOTIE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_GD); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LDM); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_PC16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_8); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_PC8); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_GD_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_GD_PUSH); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_GD_CALL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_GD_POP); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LDM_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LDM_PUSH); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LDM_CALL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LDM_POP); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LDO_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_IE_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LE_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_DTPMOD32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_DTPOFF32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_TPOFF32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_GOTDESC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_DESC_CALL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_DESC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_IRELATIVE); - default: break; - } - break; - case ELF::EM_MIPS: - switch (Type) { - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_NONE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_REL32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_26); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_HI16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_LO16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_GPREL16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_LITERAL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_GOT16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_PC16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_CALL16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_GPREL32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_SHIFT5); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_SHIFT6); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_GOT_DISP); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_GOT_PAGE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_GOT_OFST); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_GOT_HI16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_GOT_LO16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_SUB); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_INSERT_A); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_INSERT_B); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_DELETE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_HIGHER); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_HIGHEST); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_CALL_HI16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_CALL_LO16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_SCN_DISP); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_REL16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_ADD_IMMEDIATE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_PJUMP); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_RELGOT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_JALR); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_DTPMOD32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_DTPREL32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_DTPMOD64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_DTPREL64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_GD); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_LDM); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_DTPREL_HI16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_DTPREL_LO16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_GOTTPREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_TPREL32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_TPREL64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_TPREL_HI16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_TPREL_LO16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_GLOB_DAT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_COPY); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_JUMP_SLOT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_NUM); - default: break; - } - break; - case ELF::EM_AARCH64: - switch (Type) { - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_NONE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_ABS64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_ABS32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_ABS16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_PREL64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_PREL32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_PREL16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_MOVW_UABS_G0); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_MOVW_UABS_G0_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_MOVW_UABS_G1); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_MOVW_UABS_G1_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_MOVW_UABS_G2); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_MOVW_UABS_G2_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_MOVW_UABS_G3); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_MOVW_SABS_G0); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_MOVW_SABS_G1); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_MOVW_SABS_G2); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_LD_PREL_LO19); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_ADR_PREL_LO21); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_ADR_PREL_PG_HI21); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_ADD_ABS_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_LDST8_ABS_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TSTBR14); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_CONDBR19); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_JUMP26); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_CALL26); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_LDST16_ABS_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_LDST32_ABS_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_LDST64_ABS_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_LDST128_ABS_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_ADR_GOT_PAGE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_LD64_GOT_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_MOVW_DTPREL_G2); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_MOVW_DTPREL_G1); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_MOVW_DTPREL_G0); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_ADD_DTPREL_HI12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_ADD_DTPREL_LO12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_LDST8_DTPREL_LO12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_LDST16_DTPREL_LO12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_LDST32_DTPREL_LO12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_LDST64_DTPREL_LO12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSIE_MOVW_GOTTPREL_G1); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSIE_LD_GOTTPREL_PREL19); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_MOVW_TPREL_G2); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_MOVW_TPREL_G1); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_MOVW_TPREL_G1_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_MOVW_TPREL_G0); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_MOVW_TPREL_G0_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_ADD_TPREL_HI12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_ADD_TPREL_LO12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_ADD_TPREL_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_LDST8_TPREL_LO12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_LDST16_TPREL_LO12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_LDST32_TPREL_LO12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_LDST64_TPREL_LO12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSDESC_ADR_PAGE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSDESC_LD64_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSDESC_ADD_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSDESC_CALL); - default: break; - } - break; - case ELF::EM_ARM: - switch (Type) { - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_NONE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PC24); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ABS32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_REL32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDR_PC_G0); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ABS16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ABS12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_ABS5); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ABS8); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_SBREL32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_CALL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_PC8); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_BREL_ADJ); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_DESC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_SWI8); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_XPC25); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_XPC22); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_DTPMOD32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_DTPOFF32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_TPOFF32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_COPY); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_GLOB_DAT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_JUMP_SLOT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_RELATIVE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_GOTOFF32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_BASE_PREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_GOT_BREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PLT32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_CALL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_JUMP24); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_JUMP24); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_BASE_ABS); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_PCREL_7_0); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_PCREL_15_8); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_PCREL_23_15); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDR_SBREL_11_0_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_SBREL_19_12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_SBREL_27_20_CK); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TARGET1); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_SBREL31); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_V4BX); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TARGET2); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PREL31); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_MOVW_ABS_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_MOVT_ABS); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_MOVW_PREL_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_MOVT_PREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_MOVW_ABS_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_MOVT_ABS); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_MOVW_PREL_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_MOVT_PREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_JUMP19); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_JUMP6); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_ALU_PREL_11_0); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_PC12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ABS32_NOI); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_REL32_NOI); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_PC_G0_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_PC_G0); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_PC_G1_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_PC_G1); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_PC_G2); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDR_PC_G1); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDR_PC_G2); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDRS_PC_G0); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDRS_PC_G1); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDRS_PC_G2); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDC_PC_G0); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDC_PC_G1); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDC_PC_G2); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_SB_G0_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_SB_G0); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_SB_G1_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_SB_G1); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_SB_G2); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDR_SB_G0); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDR_SB_G1); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDR_SB_G2); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDRS_SB_G0); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDRS_SB_G1); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDRS_SB_G2); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDC_SB_G0); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDC_SB_G1); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDC_SB_G2); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_MOVW_BREL_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_MOVT_BREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_MOVW_BREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_MOVW_BREL_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_MOVT_BREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_MOVW_BREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_GOTDESC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_CALL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_DESCSEQ); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_TLS_CALL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PLT32_ABS); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_GOT_ABS); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_GOT_PREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_GOT_BREL12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_GOTOFF12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_GOTRELAX); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_GNU_VTENTRY); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_GNU_VTINHERIT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_JUMP11); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_JUMP8); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_GD32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_LDM32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_LDO32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_IE32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_LE32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_LDO12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_LE12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_IE12GP); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_0); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_1); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_2); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_3); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_4); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_5); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_6); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_7); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_8); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_9); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_10); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_11); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_13); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_14); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_15); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ME_TOO); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_TLS_DESCSEQ16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_TLS_DESCSEQ32); - default: break; - } - break; - case ELF::EM_HEXAGON: - switch (Type) { - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_NONE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B22_PCREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B15_PCREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B7_PCREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_LO16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_HI16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_8); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GPREL16_0); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GPREL16_1); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GPREL16_2); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GPREL16_3); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_HL16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B13_PCREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B9_PCREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B32_PCREL_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_32_6_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B22_PCREL_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B15_PCREL_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B13_PCREL_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B9_PCREL_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B7_PCREL_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_16_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_12_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_11_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_10_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_9_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_8_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_7_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_6_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_32_PCREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_COPY); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GLOB_DAT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_JMP_SLOT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_RELATIVE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_PLT_B22_PCREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOTREL_LO16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOTREL_HI16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOTREL_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOT_LO16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOT_HI16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOT_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOT_16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_DTPMOD_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_DTPREL_LO16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_DTPREL_HI16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_DTPREL_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_DTPREL_16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GD_PLT_B22_PCREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GD_GOT_LO16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GD_GOT_HI16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GD_GOT_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GD_GOT_16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_LO16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_HI16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_GOT_LO16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_GOT_HI16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_GOT_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_GOT_16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_TPREL_LO16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_TPREL_HI16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_TPREL_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_TPREL_16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_6_PCREL_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOTREL_32_6_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOTREL_16_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOTREL_11_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOT_32_6_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOT_16_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOT_11_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_DTPREL_32_6_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_DTPREL_16_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_DTPREL_11_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GD_GOT_32_6_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GD_GOT_16_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GD_GOT_11_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_32_6_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_16_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_GOT_32_6_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_GOT_16_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_GOT_11_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_TPREL_32_6_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_TPREL_16_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_TPREL_11_X); - default: break; - } - break; - case ELF::EM_PPC: - switch (Type) { - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_NONE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_ADDR32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_ADDR24); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_ADDR16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_ADDR16_LO); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_ADDR16_HI); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_ADDR16_HA); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_ADDR14); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_ADDR14_BRTAKEN); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_ADDR14_BRNTAKEN); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_REL24); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_REL14); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_REL14_BRTAKEN); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_REL14_BRNTAKEN); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_REL32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_TPREL16_LO); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_TPREL16_HA); - default: break; - } - break; - case ELF::EM_PPC64: - switch (Type) { - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_NONE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16_LO); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16_HI); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR14); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_REL24); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_REL32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16_HIGHER); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16_HIGHEST); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_REL64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TOC16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TOC16_LO); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TOC16_HA); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TOC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16_DS); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16_LO_DS); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TOC16_DS); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TOC16_LO_DS); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TLS); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TPREL16_LO); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TPREL16_HA); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_DTPREL16_LO); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_DTPREL16_HA); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TLSGD16_LO); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TLSGD16_HA); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TLSLD16_LO); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TLSLD16_HA); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TPREL16_LO_DS); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TPREL16_HA); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TLSGD); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TLSLD); - default: break; - } - break; - case ELF::EM_S390: - switch (Type) { - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_NONE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_8); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PC32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOT12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOT32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PLT32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_COPY); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GLOB_DAT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_JMP_SLOT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_RELATIVE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTOFF); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTPC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOT16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PC16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PC16DBL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PLT16DBL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PC32DBL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PLT32DBL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTPCDBL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PC64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOT64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PLT64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTENT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTOFF16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTOFF64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTPLT12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTPLT16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTPLT32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTPLT64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTPLTENT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PLTOFF16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PLTOFF32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PLTOFF64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_LOAD); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_GDCALL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_LDCALL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_GD32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_GD64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_GOTIE12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_GOTIE32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_GOTIE64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_LDM32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_LDM64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_IE32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_IE64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_IEENT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_LE32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_LE64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_LDO32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_LDO64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_DTPMOD); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_DTPOFF); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_TPOFF); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_20); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOT20); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTPLT20); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_GOTIE20); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_IRELATIVE); - default: break; - } - break; - default: break; - } - return Res; +template +StringRef ELFFile::getRelocationTypeName(uint32_t Type) const { + return getELFRelocationTypeName(Header->e_machine, Type); } -#undef LLVM_ELF_SWITCH_RELOC_TYPE_NAME - -template -error_code ELFObjectFile::getRelocationTypeName( - DataRefImpl Rel, SmallVectorImpl &Result) const { - const Elf_Shdr *sec = getSection(Rel.w.b); - uint32_t type; - switch (sec->sh_type) { - default : - return object_error::parse_failed; - case ELF::SHT_REL : { - type = getRel(Rel)->getType(isMips64EL()); - break; - } - case ELF::SHT_RELA : { - type = getRela(Rel)->getType(isMips64EL()); - break; - } - } - +template +void ELFFile::getRelocationTypeName(uint32_t Type, + SmallVectorImpl &Result) const { if (!isMips64EL()) { - StringRef Name = getRelocationTypeName(type); + StringRef Name = getRelocationTypeName(Type); Result.append(Name.begin(), Name.end()); } else { - uint8_t Type1 = (type >> 0) & 0xFF; - uint8_t Type2 = (type >> 8) & 0xFF; - uint8_t Type3 = (type >> 16) & 0xFF; + uint8_t Type1 = (Type >> 0) & 0xFF; + uint8_t Type2 = (Type >> 8) & 0xFF; + uint8_t Type3 = (Type >> 16) & 0xFF; // Concat all three relocation type names. StringRef Name = getRelocationTypeName(Type1); @@ -2214,126 +557,63 @@ error_code ELFObjectFile::getRelocationTypeName( Result.append(1, '/'); Result.append(Name.begin(), Name.end()); } - - return object_error::success; } -template -error_code ELFObjectFile::getRelocationAdditionalInfo( - DataRefImpl Rel, int64_t &Result) const { - const Elf_Shdr *sec = getSection(Rel.w.b); - switch (sec->sh_type) { - default : - report_fatal_error("Invalid section type in Rel!"); - case ELF::SHT_REL : { - Result = 0; - return object_error::success; - } - case ELF::SHT_RELA : { - Result = getRela(Rel)->r_addend; - return object_error::success; - } - } -} - -template -error_code ELFObjectFile::getRelocationValueString( - DataRefImpl Rel, SmallVectorImpl &Result) const { - const Elf_Shdr *sec = getSection(Rel.w.b); - uint8_t type; - StringRef res; - int64_t addend = 0; - uint16_t symbol_index = 0; - switch (sec->sh_type) { - default: - return object_error::parse_failed; - case ELF::SHT_REL: { - type = getRel(Rel)->getType(isMips64EL()); - symbol_index = getRel(Rel)->getSymbol(isMips64EL()); - // TODO: Read implicit addend from section data. - break; - } - case ELF::SHT_RELA: { - type = getRela(Rel)->getType(isMips64EL()); - symbol_index = getRela(Rel)->getSymbol(isMips64EL()); - addend = getRela(Rel)->r_addend; - break; - } - } - const Elf_Sym *symb = getEntry(sec->sh_link, symbol_index); - StringRef symname; - if (error_code ec = getSymbolName(getSection(sec->sh_link), symb, symname)) - return ec; - switch (Header->e_machine) { - case ELF::EM_X86_64: - switch (type) { - case ELF::R_X86_64_PC8: - case ELF::R_X86_64_PC16: - case ELF::R_X86_64_PC32: { - std::string fmtbuf; - raw_string_ostream fmt(fmtbuf); - fmt << symname << (addend < 0 ? "" : "+") << addend << "-P"; - fmt.flush(); - Result.append(fmtbuf.begin(), fmtbuf.end()); - } - break; - case ELF::R_X86_64_8: - case ELF::R_X86_64_16: - case ELF::R_X86_64_32: - case ELF::R_X86_64_32S: - case ELF::R_X86_64_64: { - std::string fmtbuf; - raw_string_ostream fmt(fmtbuf); - fmt << symname << (addend < 0 ? "" : "+") << addend; - fmt.flush(); - Result.append(fmtbuf.begin(), fmtbuf.end()); - } - break; - default: - res = "Unknown"; - } - break; - case ELF::EM_AARCH64: - case ELF::EM_ARM: - case ELF::EM_HEXAGON: - res = symname; - break; - default: - res = "Unknown"; - } - if (Result.empty()) - Result.append(res.begin(), res.end()); - return object_error::success; +template +template +std::pair::Elf_Shdr *, + const typename ELFFile::Elf_Sym *> +ELFFile::getRelocationSymbol(const Elf_Shdr *Sec, const RelT *Rel) const { + if (!Sec->sh_link) + return std::make_pair((const Elf_Shdr *)0, (const Elf_Sym *)0); + const Elf_Shdr *SymTable = getSection(Sec->sh_link); + return std::make_pair( + SymTable, getEntry(SymTable, Rel->getSymbol(isMips64EL()))); } // Verify that the last byte in the string table in a null. -template -void ELFObjectFile::VerifyStrTab(const Elf_Shdr *sh) const { - const char *strtab = (const char*)base() + sh->sh_offset; +template +void ELFFile::VerifyStrTab(const Elf_Shdr *sh) const { + const char *strtab = (const char *)base() + sh->sh_offset; if (strtab[sh->sh_size - 1] != 0) // FIXME: Proper error handling. report_fatal_error("String table must end with a null terminator!"); } -template -ELFObjectFile::ELFObjectFile(MemoryBuffer *Object, error_code &ec) - : ObjectFile(getELFType( - static_cast(ELFT::TargetEndianness) == support::little, - ELFT::Is64Bits), - Object) - , isDyldELFObject(false) - , SectionHeaderTable(0) - , dot_shstrtab_sec(0) - , dot_strtab_sec(0) - , dot_dynstr_sec(0) - , dot_dynamic_sec(0) - , dot_gnu_version_sec(0) - , dot_gnu_version_r_sec(0) - , dot_gnu_version_d_sec(0) - , dt_soname(0) - { - - const uint64_t FileSize = Data->getBufferSize(); +template +uint64_t ELFFile::getNumSections() const { + assert(Header && "Header not initialized!"); + if (Header->e_shnum == ELF::SHN_UNDEF) { + assert(SectionHeaderTable && "SectionHeaderTable not initialized!"); + return SectionHeaderTable->sh_size; + } + return Header->e_shnum; +} + +template +typename ELFFile::uintX_t ELFFile::getStringTableIndex() const { + if (Header->e_shnum == ELF::SHN_UNDEF) { + if (Header->e_shstrndx == ELF::SHN_HIRESERVE) + return SectionHeaderTable->sh_link; + if (Header->e_shstrndx >= getNumSections()) + return 0; + } + return Header->e_shstrndx; +} + +template +ELFFile::ELFFile(MemoryBuffer *Object, error_code &ec) + : Buf(Object), + SectionHeaderTable(0), + dot_shstrtab_sec(0), + dot_strtab_sec(0), + dot_symtab_sec(0), + SymbolTableSectionHeaderIndex(0), + dot_gnu_version_sec(0), + dot_gnu_version_r_sec(0), + dot_gnu_version_d_sec(0), + dt_soname(0) { + const uint64_t FileSize = Buf->getBufferSize(); if (sizeof(Elf_Ehdr) > FileSize) // FIXME: Proper error handling. @@ -2359,76 +639,64 @@ ELFObjectFile::ELFObjectFile(MemoryBuffer *Object, error_code &ec) // FIXME: Proper error handling. report_fatal_error("Section table goes past end of file!"); - // To find the symbol tables we walk the section table to find SHT_SYMTAB. - const Elf_Shdr* SymbolTableSectionHeaderIndex = 0; - const Elf_Shdr* sh = SectionHeaderTable; - - // Reserve SymbolTableSections[0] for .dynsym - SymbolTableSections.push_back(NULL); + // Scan sections for special sections. - for (uint64_t i = 0, e = getNumSections(); i != e; ++i) { - switch (sh->sh_type) { - case ELF::SHT_SYMTAB_SHNDX: { + for (Elf_Shdr_Iter SecI = begin_sections(), SecE = end_sections(); + SecI != SecE; ++SecI) { + switch (SecI->sh_type) { + case ELF::SHT_SYMTAB_SHNDX: if (SymbolTableSectionHeaderIndex) // FIXME: Proper error handling. report_fatal_error("More than one .symtab_shndx!"); - SymbolTableSectionHeaderIndex = sh; + SymbolTableSectionHeaderIndex = &*SecI; break; - } - case ELF::SHT_SYMTAB: { - SymbolTableSectionsIndexMap[i] = SymbolTableSections.size(); - SymbolTableSections.push_back(sh); + case ELF::SHT_SYMTAB: + if (dot_symtab_sec) + // FIXME: Proper error handling. + report_fatal_error("More than one .symtab!"); + dot_symtab_sec = &*SecI; + dot_strtab_sec = getSection(SecI->sh_link); break; - } case ELF::SHT_DYNSYM: { - if (SymbolTableSections[0] != NULL) + if (DynSymRegion.Addr) // FIXME: Proper error handling. report_fatal_error("More than one .dynsym!"); - SymbolTableSectionsIndexMap[i] = 0; - SymbolTableSections[0] = sh; - break; - } - case ELF::SHT_REL: - case ELF::SHT_RELA: { - SectionRelocMap[getSection(sh->sh_info)].push_back(i); + DynSymRegion.Addr = base() + SecI->sh_offset; + DynSymRegion.Size = SecI->sh_size; + DynSymRegion.EntSize = SecI->sh_entsize; + const Elf_Shdr *DynStr = getSection(SecI->sh_link); + DynStrRegion.Addr = base() + DynStr->sh_offset; + DynStrRegion.Size = DynStr->sh_size; + DynStrRegion.EntSize = DynStr->sh_entsize; break; } - case ELF::SHT_DYNAMIC: { - if (dot_dynamic_sec != NULL) + case ELF::SHT_DYNAMIC: + if (DynamicRegion.Addr) // FIXME: Proper error handling. report_fatal_error("More than one .dynamic!"); - dot_dynamic_sec = sh; + DynamicRegion.Addr = base() + SecI->sh_offset; + DynamicRegion.Size = SecI->sh_size; + DynamicRegion.EntSize = SecI->sh_entsize; break; - } - case ELF::SHT_GNU_versym: { + case ELF::SHT_GNU_versym: if (dot_gnu_version_sec != NULL) // FIXME: Proper error handling. report_fatal_error("More than one .gnu.version section!"); - dot_gnu_version_sec = sh; + dot_gnu_version_sec = &*SecI; break; - } - case ELF::SHT_GNU_verdef: { + case ELF::SHT_GNU_verdef: if (dot_gnu_version_d_sec != NULL) // FIXME: Proper error handling. report_fatal_error("More than one .gnu.version_d section!"); - dot_gnu_version_d_sec = sh; + dot_gnu_version_d_sec = &*SecI; break; - } - case ELF::SHT_GNU_verneed: { + case ELF::SHT_GNU_verneed: if (dot_gnu_version_r_sec != NULL) // FIXME: Proper error handling. report_fatal_error("More than one .gnu.version_r section!"); - dot_gnu_version_r_sec = sh; + dot_gnu_version_r_sec = &*SecI; break; } - } - ++sh; - } - - // Sort section relocation lists by index. - for (typename RelocMap_t::iterator i = SectionRelocMap.begin(), - e = SectionRelocMap.end(); i != e; ++i) { - std::sort(i->second.begin(), i->second.end()); } // Get string table sections. @@ -2438,162 +706,117 @@ ELFObjectFile::ELFObjectFile(MemoryBuffer *Object, error_code &ec) VerifyStrTab(dot_shstrtab_sec); } - // Merge this into the above loop. - for (const char *i = reinterpret_cast(SectionHeaderTable), - *e = i + getNumSections() * Header->e_shentsize; - i != e; i += Header->e_shentsize) { - const Elf_Shdr *sh = reinterpret_cast(i); - if (sh->sh_type == ELF::SHT_STRTAB) { - StringRef SectionName(getString(dot_shstrtab_sec, sh->sh_name)); - if (SectionName == ".strtab") { - if (dot_strtab_sec != 0) - // FIXME: Proper error handling. - report_fatal_error("Already found section named .strtab!"); - dot_strtab_sec = sh; - VerifyStrTab(dot_strtab_sec); - } else if (SectionName == ".dynstr") { - if (dot_dynstr_sec != 0) - // FIXME: Proper error handling. - report_fatal_error("Already found section named .dynstr!"); - dot_dynstr_sec = sh; - VerifyStrTab(dot_dynstr_sec); - } - } - } - // Build symbol name side-mapping if there is one. if (SymbolTableSectionHeaderIndex) { const Elf_Word *ShndxTable = reinterpret_cast(base() + SymbolTableSectionHeaderIndex->sh_offset); - error_code ec; - for (symbol_iterator si = begin_symbols(), - se = end_symbols(); si != se; si.increment(ec)) { - if (ec) - report_fatal_error("Fewer extended symbol table entries than symbols!"); + for (Elf_Sym_Iter SI = begin_symbols(), SE = end_symbols(); SI != SE; + ++SI) { if (*ShndxTable != ELF::SHN_UNDEF) - ExtendedSymbolTable[getSymbol(si->getRawDataRefImpl())] = *ShndxTable; + ExtendedSymbolTable[&*SI] = *ShndxTable; ++ShndxTable; } } + + // Scan program headers. + for (Elf_Phdr_Iter PhdrI = begin_program_headers(), + PhdrE = end_program_headers(); + PhdrI != PhdrE; ++PhdrI) { + if (PhdrI->p_type == ELF::PT_DYNAMIC) { + DynamicRegion.Addr = base() + PhdrI->p_offset; + DynamicRegion.Size = PhdrI->p_filesz; + DynamicRegion.EntSize = sizeof(Elf_Dyn); + break; + } + } + + ec = error_code::success(); } // Get the symbol table index in the symtab section given a symbol -template -uint64_t ELFObjectFile::getSymbolIndex(const Elf_Sym *Sym) const { - assert(SymbolTableSections.size() == 1 && "Only one symbol table supported!"); - const Elf_Shdr *SymTab = *SymbolTableSections.begin(); +template +uint64_t ELFFile::getSymbolIndex(const Elf_Sym *Sym) const { uintptr_t SymLoc = uintptr_t(Sym); - uintptr_t SymTabLoc = uintptr_t(base() + SymTab->sh_offset); + uintptr_t SymTabLoc = uintptr_t(base() + dot_symtab_sec->sh_offset); assert(SymLoc > SymTabLoc && "Symbol not in symbol table!"); uint64_t SymOffset = SymLoc - SymTabLoc; - assert(SymOffset % SymTab->sh_entsize == 0 && + assert(SymOffset % dot_symtab_sec->sh_entsize == 0 && "Symbol not multiple of symbol size!"); - return SymOffset / SymTab->sh_entsize; + return SymOffset / dot_symtab_sec->sh_entsize; } -template -symbol_iterator ELFObjectFile::begin_symbols() const { - DataRefImpl SymbolData; - if (SymbolTableSections.size() <= 1) { - SymbolData.d.a = std::numeric_limits::max(); - SymbolData.d.b = std::numeric_limits::max(); - } else { - SymbolData.d.a = 1; // The 0th symbol in ELF is fake. - SymbolData.d.b = 1; // The 0th table is .dynsym - } - return symbol_iterator(SymbolRef(SymbolData, this)); +template +typename ELFFile::Elf_Shdr_Iter ELFFile::begin_sections() const { + return Elf_Shdr_Iter(Header->e_shentsize, + (const char *)base() + Header->e_shoff); } -template -symbol_iterator ELFObjectFile::end_symbols() const { - DataRefImpl SymbolData; - SymbolData.d.a = std::numeric_limits::max(); - SymbolData.d.b = std::numeric_limits::max(); - return symbol_iterator(SymbolRef(SymbolData, this)); +template +typename ELFFile::Elf_Shdr_Iter ELFFile::end_sections() const { + return Elf_Shdr_Iter(Header->e_shentsize, + (const char *)base() + Header->e_shoff + + (getNumSections() * Header->e_shentsize)); } -template -symbol_iterator ELFObjectFile::begin_dynamic_symbols() const { - DataRefImpl SymbolData; - if (SymbolTableSections[0] == NULL) { - SymbolData.d.a = std::numeric_limits::max(); - SymbolData.d.b = std::numeric_limits::max(); - } else { - SymbolData.d.a = 1; // The 0th symbol in ELF is fake. - SymbolData.d.b = 0; // The 0th table is .dynsym - } - return symbol_iterator(SymbolRef(SymbolData, this)); +template +typename ELFFile::Elf_Sym_Iter ELFFile::begin_symbols() const { + if (!dot_symtab_sec) + return Elf_Sym_Iter(0, 0, false); + return Elf_Sym_Iter(dot_symtab_sec->sh_entsize, + (const char *)base() + dot_symtab_sec->sh_offset, false); } -template -symbol_iterator ELFObjectFile::end_dynamic_symbols() const { - DataRefImpl SymbolData; - SymbolData.d.a = std::numeric_limits::max(); - SymbolData.d.b = std::numeric_limits::max(); - return symbol_iterator(SymbolRef(SymbolData, this)); +template +typename ELFFile::Elf_Sym_Iter ELFFile::end_symbols() const { + if (!dot_symtab_sec) + return Elf_Sym_Iter(0, 0, false); + return Elf_Sym_Iter(dot_symtab_sec->sh_entsize, + (const char *)base() + dot_symtab_sec->sh_offset + + dot_symtab_sec->sh_size, + false); } -template -section_iterator ELFObjectFile::begin_sections() const { - DataRefImpl ret; - ret.p = reinterpret_cast(base() + Header->e_shoff); - return section_iterator(SectionRef(ret, this)); +template +typename ELFFile::Elf_Dyn_Iter +ELFFile::begin_dynamic_table() const { + if (DynamicRegion.Addr) + return Elf_Dyn_Iter(DynamicRegion.EntSize, + (const char *)DynamicRegion.Addr); + return Elf_Dyn_Iter(0, 0); } -template -section_iterator ELFObjectFile::end_sections() const { - DataRefImpl ret; - ret.p = reinterpret_cast(base() - + Header->e_shoff - + (Header->e_shentsize*getNumSections())); - return section_iterator(SectionRef(ret, this)); -} +template +typename ELFFile::Elf_Dyn_Iter +ELFFile::end_dynamic_table(bool NULLEnd) const { + if (!DynamicRegion.Addr) + return Elf_Dyn_Iter(0, 0); + Elf_Dyn_Iter Ret(DynamicRegion.EntSize, + (const char *)DynamicRegion.Addr + DynamicRegion.Size); -template -typename ELFObjectFile::Elf_Dyn_iterator -ELFObjectFile::begin_dynamic_table() const { - if (dot_dynamic_sec) - return Elf_Dyn_iterator(dot_dynamic_sec->sh_entsize, - (const char *)base() + dot_dynamic_sec->sh_offset); - return Elf_Dyn_iterator(0, 0); -} + if (NULLEnd) { + Elf_Dyn_Iter Start = begin_dynamic_table(); + while (Start != Ret && Start->getTag() != ELF::DT_NULL) + ++Start; -template -typename ELFObjectFile::Elf_Dyn_iterator -ELFObjectFile::end_dynamic_table(bool NULLEnd) const { - if (dot_dynamic_sec) { - Elf_Dyn_iterator Ret(dot_dynamic_sec->sh_entsize, - (const char *)base() + dot_dynamic_sec->sh_offset + - dot_dynamic_sec->sh_size); - - if (NULLEnd) { - Elf_Dyn_iterator Start = begin_dynamic_table(); - while (Start != Ret && Start->getTag() != ELF::DT_NULL) - ++Start; - - // Include the DT_NULL. - if (Start != Ret) - ++Start; - Ret = Start; - } - return Ret; + // Include the DT_NULL. + if (Start != Ret) + ++Start; + Ret = Start; } - return Elf_Dyn_iterator(0, 0); + return Ret; } -template -StringRef ELFObjectFile::getLoadName() const { +template +StringRef ELFFile::getLoadName() const { if (!dt_soname) { // Find the DT_SONAME entry - Elf_Dyn_iterator it = begin_dynamic_table(); - Elf_Dyn_iterator ie = end_dynamic_table(); + Elf_Dyn_Iter it = begin_dynamic_table(); + Elf_Dyn_Iter ie = end_dynamic_table(); while (it != ie && it->getTag() != ELF::DT_SONAME) ++it; if (it != ie) { - if (dot_dynstr_sec == NULL) - report_fatal_error("Dynamic string table is missing"); - dt_soname = getString(dot_dynstr_sec, it->getVal()); + dt_soname = getDynamicString(it->getVal()); } else { dt_soname = ""; } @@ -2601,207 +824,23 @@ StringRef ELFObjectFile::getLoadName() const { return dt_soname; } -template -library_iterator ELFObjectFile::begin_libraries_needed() const { - // Find the first DT_NEEDED entry - Elf_Dyn_iterator i = begin_dynamic_table(); - Elf_Dyn_iterator e = end_dynamic_table(); - while (i != e && i->getTag() != ELF::DT_NEEDED) - ++i; - - DataRefImpl DRI; - DRI.p = reinterpret_cast(i.get()); - return library_iterator(LibraryRef(DRI, this)); -} - -template -error_code ELFObjectFile::getLibraryNext(DataRefImpl Data, - LibraryRef &Result) const { - // Use the same DataRefImpl format as DynRef. - Elf_Dyn_iterator i = Elf_Dyn_iterator(dot_dynamic_sec->sh_entsize, - reinterpret_cast(Data.p)); - Elf_Dyn_iterator e = end_dynamic_table(); - - // Skip the current dynamic table entry and find the next DT_NEEDED entry. - do - ++i; - while (i != e && i->getTag() != ELF::DT_NEEDED); - - DataRefImpl DRI; - DRI.p = reinterpret_cast(i.get()); - Result = LibraryRef(DRI, this); - return object_error::success; -} - -template -error_code ELFObjectFile::getLibraryPath(DataRefImpl Data, - StringRef &Res) const { - Elf_Dyn_iterator i = Elf_Dyn_iterator(dot_dynamic_sec->sh_entsize, - reinterpret_cast(Data.p)); - if (i == end_dynamic_table()) - report_fatal_error("getLibraryPath() called on iterator end"); - - if (i->getTag() != ELF::DT_NEEDED) - report_fatal_error("Invalid library_iterator"); - - // This uses .dynstr to lookup the name of the DT_NEEDED entry. - // THis works as long as DT_STRTAB == .dynstr. This is true most of - // the time, but the specification allows exceptions. - // TODO: This should really use DT_STRTAB instead. Doing this requires - // reading the program headers. - if (dot_dynstr_sec == NULL) - report_fatal_error("Dynamic string table is missing"); - Res = getString(dot_dynstr_sec, i->getVal()); - return object_error::success; -} - -template -library_iterator ELFObjectFile::end_libraries_needed() const { - Elf_Dyn_iterator e = end_dynamic_table(); - DataRefImpl DRI; - DRI.p = reinterpret_cast(e.get()); - return library_iterator(LibraryRef(DRI, this)); -} - -template -uint8_t ELFObjectFile::getBytesInAddress() const { - return ELFT::Is64Bits ? 8 : 4; -} - -template -StringRef ELFObjectFile::getFileFormatName() const { - switch(Header->e_ident[ELF::EI_CLASS]) { - case ELF::ELFCLASS32: - switch(Header->e_machine) { - case ELF::EM_386: - return "ELF32-i386"; - case ELF::EM_X86_64: - return "ELF32-x86-64"; - case ELF::EM_ARM: - return "ELF32-arm"; - case ELF::EM_HEXAGON: - return "ELF32-hexagon"; - case ELF::EM_MIPS: - return "ELF32-mips"; - default: - return "ELF32-unknown"; - } - case ELF::ELFCLASS64: - switch(Header->e_machine) { - case ELF::EM_386: - return "ELF64-i386"; - case ELF::EM_X86_64: - return "ELF64-x86-64"; - case ELF::EM_AARCH64: - return "ELF64-aarch64"; - case ELF::EM_PPC64: - return "ELF64-ppc64"; - case ELF::EM_S390: - return "ELF64-s390"; - default: - return "ELF64-unknown"; - } - default: - // FIXME: Proper error handling. - report_fatal_error("Invalid ELFCLASS!"); - } -} - -template -unsigned ELFObjectFile::getArch() const { - switch(Header->e_machine) { - case ELF::EM_386: - return Triple::x86; - case ELF::EM_X86_64: - return Triple::x86_64; - case ELF::EM_AARCH64: - return Triple::aarch64; - case ELF::EM_ARM: - return Triple::arm; - case ELF::EM_HEXAGON: - return Triple::hexagon; - case ELF::EM_MIPS: - return (ELFT::TargetEndianness == support::little) ? - Triple::mipsel : Triple::mips; - case ELF::EM_PPC64: - return Triple::ppc64; - case ELF::EM_S390: - return Triple::systemz; - default: - return Triple::UnknownArch; - } -} - -template -uint64_t ELFObjectFile::getNumSections() const { - assert(Header && "Header not initialized!"); - if (Header->e_shnum == ELF::SHN_UNDEF) { - assert(SectionHeaderTable && "SectionHeaderTable not initialized!"); - return SectionHeaderTable->sh_size; - } - return Header->e_shnum; -} - -template -uint64_t -ELFObjectFile::getStringTableIndex() const { - if (Header->e_shnum == ELF::SHN_UNDEF) { - if (Header->e_shstrndx == ELF::SHN_HIRESERVE) - return SectionHeaderTable->sh_link; - if (Header->e_shstrndx >= getNumSections()) - return 0; - } - return Header->e_shstrndx; -} - -template -template -inline const T * -ELFObjectFile::getEntry(uint16_t Section, uint32_t Entry) const { +template +template +const T *ELFFile::getEntry(uint32_t Section, uint32_t Entry) const { return getEntry(getSection(Section), Entry); } -template -template -inline const T * -ELFObjectFile::getEntry(const Elf_Shdr * Section, uint32_t Entry) const { - return reinterpret_cast( - base() - + Section->sh_offset - + (Entry * Section->sh_entsize)); -} - -template -const typename ELFObjectFile::Elf_Sym * -ELFObjectFile::getSymbol(DataRefImpl Symb) const { - return getEntry(SymbolTableSections[Symb.d.b], Symb.d.a); -} - -template -const typename ELFObjectFile::Elf_Rel * -ELFObjectFile::getRel(DataRefImpl Rel) const { - return getEntry(Rel.w.b, Rel.w.c); -} - -template -const typename ELFObjectFile::Elf_Rela * -ELFObjectFile::getRela(DataRefImpl Rela) const { - return getEntry(Rela.w.b, Rela.w.c); -} - -template -const typename ELFObjectFile::Elf_Shdr * -ELFObjectFile::getSection(DataRefImpl Symb) const { - const Elf_Shdr *sec = getSection(Symb.d.b); - if (sec->sh_type != ELF::SHT_SYMTAB || sec->sh_type != ELF::SHT_DYNSYM) - // FIXME: Proper error handling. - report_fatal_error("Invalid symbol table section!"); - return sec; +template +template +const T *ELFFile::getEntry(const Elf_Shdr *Section, + uint32_t Entry) const { + return reinterpret_cast(base() + Section->sh_offset + + (Entry * Section->sh_entsize)); } -template -const typename ELFObjectFile::Elf_Shdr * -ELFObjectFile::getSection(uint32_t index) const { +template +const typename ELFFile::Elf_Shdr * +ELFFile::getSection(uint32_t index) const { if (index == 0) return 0; if (!SectionHeaderTable || index >= getNumSections()) @@ -2813,15 +852,15 @@ ELFObjectFile::getSection(uint32_t index) const { + (index * Header->e_shentsize)); } -template -const char *ELFObjectFile::getString(uint32_t section, - ELF::Elf32_Word offset) const { +template +const char *ELFFile::getString(uint32_t section, + ELF::Elf32_Word offset) const { return getString(getSection(section), offset); } -template -const char *ELFObjectFile::getString(const Elf_Shdr *section, - ELF::Elf32_Word offset) const { +template +const char *ELFFile::getString(const Elf_Shdr *section, + ELF::Elf32_Word offset) const { assert(section && section->sh_type == ELF::SHT_STRTAB && "Invalid section!"); if (offset >= section->sh_size) // FIXME: Proper error handling. @@ -2829,55 +868,63 @@ const char *ELFObjectFile::getString(const Elf_Shdr *section, return (const char *)base() + section->sh_offset + offset; } -template -error_code ELFObjectFile::getSymbolName(const Elf_Shdr *section, - const Elf_Sym *symb, - StringRef &Result) const { - if (symb->st_name == 0) { - const Elf_Shdr *section = getSection(symb); - if (!section) - Result = ""; - else - Result = getString(dot_shstrtab_sec, section->sh_name); - return object_error::success; - } +template +const char *ELFFile::getDynamicString(uintX_t Offset) const { + if (!DynStrRegion.Addr || Offset >= DynStrRegion.Size) + return 0; + return (const char *)DynStrRegion.Addr + Offset; +} - if (section == SymbolTableSections[0]) { - // Symbol is in .dynsym, use .dynstr string table - Result = getString(dot_dynstr_sec, symb->st_name); - } else { - // Use the default symbol table name section. - Result = getString(dot_strtab_sec, symb->st_name); +template +ErrorOr ELFFile::getSymbolName(Elf_Sym_Iter Sym) const { + if (!Sym.isDynamic()) + return getSymbolName(dot_symtab_sec, &*Sym); + + if (!DynStrRegion.Addr || Sym->st_name >= DynStrRegion.Size) + return object_error::parse_failed; + return StringRef(getDynamicString(Sym->st_name)); +} + +template +ErrorOr ELFFile::getSymbolName(const Elf_Shdr *Section, + const Elf_Sym *Symb) const { + if (Symb->st_name == 0) { + const Elf_Shdr *ContainingSec = getSection(Symb); + if (ContainingSec) + return getSectionName(ContainingSec); } - return object_error::success; + + const Elf_Shdr *StrTab = getSection(Section->sh_link); + if (Symb->st_name >= StrTab->sh_size) + return object_error::parse_failed; + return StringRef(getString(StrTab, Symb->st_name)); } -template -error_code ELFObjectFile::getSectionName(const Elf_Shdr *section, - StringRef &Result) const { - Result = StringRef(getString(dot_shstrtab_sec, section->sh_name)); - return object_error::success; +template +ErrorOr +ELFFile::getSectionName(const Elf_Shdr *Section) const { + if (Section->sh_name >= dot_shstrtab_sec->sh_size) + return object_error::parse_failed; + return StringRef(getString(dot_shstrtab_sec, Section->sh_name)); } -template -error_code ELFObjectFile::getSymbolVersion(const Elf_Shdr *section, - const Elf_Sym *symb, - StringRef &Version, - bool &IsDefault) const { +template +ErrorOr ELFFile::getSymbolVersion(const Elf_Shdr *section, + const Elf_Sym *symb, + bool &IsDefault) const { // Handle non-dynamic symbols. - if (section != SymbolTableSections[0]) { + if (section != DynSymRegion.Addr && section != 0) { // Non-dynamic symbols can have versions in their names // A name of the form 'foo@V1' indicates version 'V1', non-default. // A name of the form 'foo@@V2' indicates version 'V2', default version. - StringRef Name; - error_code ec = getSymbolName(section, symb, Name); - if (ec != object_error::success) - return ec; + ErrorOr SymName = getSymbolName(section, symb); + if (!SymName) + return SymName; + StringRef Name = *SymName; size_t atpos = Name.find('@'); if (atpos == StringRef::npos) { - Version = ""; IsDefault = false; - return object_error::success; + return StringRef(""); } ++atpos; if (atpos < Name.size() && Name[atpos] == '@') { @@ -2886,21 +933,19 @@ error_code ELFObjectFile::getSymbolVersion(const Elf_Shdr *section, } else { IsDefault = false; } - Version = Name.substr(atpos); - return object_error::success; + return Name.substr(atpos); } // This is a dynamic symbol. Look in the GNU symbol version table. if (dot_gnu_version_sec == NULL) { // No version table. - Version = ""; IsDefault = false; - return object_error::success; + return StringRef(""); } // Determine the position in the symbol table of this entry. - const char *sec_start = (const char*)base() + section->sh_offset; - size_t entry_index = ((const char*)symb - sec_start)/section->sh_entsize; + size_t entry_index = ((const char *)symb - (const char *)DynSymRegion.Addr) / + DynSymRegion.EntSize; // Get the corresponding version index entry const Elf_Versym *vs = getEntry(dot_gnu_version_sec, entry_index); @@ -2909,16 +954,14 @@ error_code ELFObjectFile::getSymbolVersion(const Elf_Shdr *section, // Special markers for unversioned symbols. if (version_index == ELF::VER_NDX_LOCAL || version_index == ELF::VER_NDX_GLOBAL) { - Version = ""; IsDefault = false; - return object_error::success; + return StringRef(""); } // Lookup this symbol in the version table LoadVersionMap(); if (version_index >= VersionMap.size() || VersionMap[version_index].isNull()) - report_fatal_error("Symbol has version index without corresponding " - "define or reference entry"); + return object_error::parse_failed; const VersionMapEntry &entry = VersionMap[version_index]; // Get the version name string @@ -2929,7 +972,6 @@ error_code ELFObjectFile::getSymbolVersion(const Elf_Shdr *section, } else { name_offset = entry.getVernaux()->vna_name; } - Version = getString(dot_dynstr_sec, name_offset); // Set IsDefault if (entry.isVerdef()) { @@ -2938,36 +980,9 @@ error_code ELFObjectFile::getSymbolVersion(const Elf_Shdr *section, IsDefault = false; } - return object_error::success; -} - -/// This is a generic interface for retrieving GNU symbol version -/// information from an ELFObjectFile. -static inline error_code GetELFSymbolVersion(const ObjectFile *Obj, - const SymbolRef &Sym, - StringRef &Version, - bool &IsDefault) { - // Little-endian 32-bit - if (const ELFObjectFile > *ELFObj = - dyn_cast > >(Obj)) - return ELFObj->getSymbolVersion(Sym, Version, IsDefault); - - // Big-endian 32-bit - if (const ELFObjectFile > *ELFObj = - dyn_cast > >(Obj)) - return ELFObj->getSymbolVersion(Sym, Version, IsDefault); - - // Little-endian 64-bit - if (const ELFObjectFile > *ELFObj = - dyn_cast > >(Obj)) - return ELFObj->getSymbolVersion(Sym, Version, IsDefault); - - // Big-endian 64-bit - if (const ELFObjectFile > *ELFObj = - dyn_cast > >(Obj)) - return ELFObj->getSymbolVersion(Sym, Version, IsDefault); - - llvm_unreachable("Object passed to GetELFSymbolVersion() is not ELF"); + if (name_offset >= DynStrRegion.Size) + return object_error::parse_failed; + return StringRef(getDynamicString(name_offset)); } /// This function returns the hash value for a symbol in the .dynsym section @@ -2984,8 +999,7 @@ static inline unsigned elf_hash(StringRef &symbolName) { } return h; } - -} -} +} // end namespace object +} // end namespace llvm #endif diff --git a/contrib/llvm/include/llvm/Object/ELFObjectFile.h b/contrib/llvm/include/llvm/Object/ELFObjectFile.h new file mode 100644 index 000000000..962a3e2a8 --- /dev/null +++ b/contrib/llvm/include/llvm/Object/ELFObjectFile.h @@ -0,0 +1,1027 @@ +//===- ELFObjectFile.h - ELF object file implementation ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the ELFObjectFile template class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_ELF_OBJECT_FILE_H +#define LLVM_OBJECT_ELF_OBJECT_FILE_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/PointerIntPair.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringSwitch.h" +#include "llvm/ADT/Triple.h" +#include "llvm/Object/ELF.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/ELF.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/raw_ostream.h" +#include +#include +#include +#include + +namespace llvm { +namespace object { + +template +class ELFObjectFile : public ObjectFile { +public: + LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) + + typedef typename ELFFile::uintX_t uintX_t; + + typedef typename ELFFile::Elf_Sym Elf_Sym; + typedef typename ELFFile::Elf_Shdr Elf_Shdr; + typedef typename ELFFile::Elf_Rel Elf_Rel; + typedef typename ELFFile::Elf_Rela Elf_Rela; + typedef typename ELFFile::Elf_Dyn Elf_Dyn; + + typedef typename ELFFile::Elf_Sym_Iter Elf_Sym_Iter; + typedef typename ELFFile::Elf_Shdr_Iter Elf_Shdr_Iter; + typedef typename ELFFile::Elf_Dyn_Iter Elf_Dyn_Iter; + +protected: + ELFFile EF; + + virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const; + virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const; + virtual error_code getSymbolFileOffset(DataRefImpl Symb, uint64_t &Res) const; + virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const; + virtual error_code getSymbolAlignment(DataRefImpl Symb, uint32_t &Res) const; + virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const; + virtual error_code getSymbolFlags(DataRefImpl Symb, uint32_t &Res) const; + virtual error_code getSymbolType(DataRefImpl Symb, + SymbolRef::Type &Res) const; + virtual error_code getSymbolSection(DataRefImpl Symb, + section_iterator &Res) const; + virtual error_code getSymbolValue(DataRefImpl Symb, uint64_t &Val) const; + + virtual error_code getLibraryNext(DataRefImpl Data, LibraryRef &Result) const; + virtual error_code getLibraryPath(DataRefImpl Data, StringRef &Res) const; + + virtual error_code getSectionNext(DataRefImpl Sec, SectionRef &Res) const; + virtual error_code getSectionName(DataRefImpl Sec, StringRef &Res) const; + virtual error_code getSectionAddress(DataRefImpl Sec, uint64_t &Res) const; + virtual error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const; + virtual error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const; + virtual error_code getSectionAlignment(DataRefImpl Sec, uint64_t &Res) const; + virtual error_code isSectionText(DataRefImpl Sec, bool &Res) const; + virtual error_code isSectionData(DataRefImpl Sec, bool &Res) const; + virtual error_code isSectionBSS(DataRefImpl Sec, bool &Res) const; + virtual error_code isSectionRequiredForExecution(DataRefImpl Sec, + bool &Res) const; + virtual error_code isSectionVirtual(DataRefImpl Sec, bool &Res) const; + virtual error_code isSectionZeroInit(DataRefImpl Sec, bool &Res) const; + virtual error_code isSectionReadOnlyData(DataRefImpl Sec, bool &Res) const; + virtual error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, + bool &Result) const; + virtual relocation_iterator section_rel_begin(DataRefImpl Sec) const; + virtual relocation_iterator section_rel_end(DataRefImpl Sec) const; + virtual section_iterator getRelocatedSection(DataRefImpl Sec) const; + + virtual error_code getRelocationNext(DataRefImpl Rel, + RelocationRef &Res) const; + virtual error_code getRelocationAddress(DataRefImpl Rel, uint64_t &Res) const; + virtual error_code getRelocationOffset(DataRefImpl Rel, uint64_t &Res) const; + virtual symbol_iterator getRelocationSymbol(DataRefImpl Rel) const; + virtual error_code getRelocationType(DataRefImpl Rel, uint64_t &Res) const; + virtual error_code getRelocationTypeName(DataRefImpl Rel, + SmallVectorImpl &Result) const; + virtual error_code + getRelocationValueString(DataRefImpl Rel, + SmallVectorImpl &Result) const; + + uint64_t getROffset(DataRefImpl Rel) const; + StringRef getRelocationTypeName(uint32_t Type) const; + + /// \brief Get the relocation section that contains \a Rel. + const Elf_Shdr *getRelSection(DataRefImpl Rel) const { + return EF.getSection(Rel.d.a); + } + + const Elf_Rel *getRel(DataRefImpl Rel) const; + const Elf_Rela *getRela(DataRefImpl Rela) const; + + Elf_Sym_Iter toELFSymIter(DataRefImpl Symb) const { + bool IsDynamic = Symb.p & 1; + if (IsDynamic) + return Elf_Sym_Iter( + EF.begin_dynamic_symbols().getEntSize(), + reinterpret_cast(Symb.p & ~uintptr_t(1)), IsDynamic); + return Elf_Sym_Iter(EF.begin_symbols().getEntSize(), + reinterpret_cast(Symb.p), IsDynamic); + } + + DataRefImpl toDRI(Elf_Sym_Iter Symb) const { + DataRefImpl DRI; + DRI.p = reinterpret_cast(Symb.get()) | + static_cast(Symb.isDynamic()); + return DRI; + } + + Elf_Shdr_Iter toELFShdrIter(DataRefImpl Sec) const { + return Elf_Shdr_Iter(EF.getHeader()->e_shentsize, + reinterpret_cast(Sec.p)); + } + + DataRefImpl toDRI(Elf_Shdr_Iter Sec) const { + DataRefImpl DRI; + DRI.p = reinterpret_cast(Sec.get()); + return DRI; + } + + DataRefImpl toDRI(const Elf_Shdr *Sec) const { + DataRefImpl DRI; + DRI.p = reinterpret_cast(Sec); + return DRI; + } + + Elf_Dyn_Iter toELFDynIter(DataRefImpl Dyn) const { + return Elf_Dyn_Iter(EF.begin_dynamic_table().getEntSize(), + reinterpret_cast(Dyn.p)); + } + + DataRefImpl toDRI(Elf_Dyn_Iter Dyn) const { + DataRefImpl DRI; + DRI.p = reinterpret_cast(Dyn.get()); + return DRI; + } + + // 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. + bool isDyldELFObject; + +public: + ELFObjectFile(MemoryBuffer *Object, error_code &ec); + + const Elf_Sym *getSymbol(DataRefImpl Symb) const; + + virtual symbol_iterator begin_symbols() const; + virtual symbol_iterator end_symbols() const; + + virtual symbol_iterator begin_dynamic_symbols() const; + virtual symbol_iterator end_dynamic_symbols() const; + + virtual section_iterator begin_sections() const; + virtual section_iterator end_sections() const; + + virtual library_iterator begin_libraries_needed() const; + virtual library_iterator end_libraries_needed() const; + + error_code getRelocationAddend(DataRefImpl Rel, int64_t &Res) const; + error_code getSymbolVersion(SymbolRef Symb, StringRef &Version, + bool &IsDefault) const; + + virtual uint8_t getBytesInAddress() const; + virtual StringRef getFileFormatName() const; + virtual StringRef getObjectType() const { return "ELF"; } + virtual unsigned getArch() const; + virtual StringRef getLoadName() const; + + const ELFFile *getELFFile() const { return &EF; } + + bool isDyldType() const { return isDyldELFObject; } + static inline bool classof(const Binary *v) { + return v->getType() == getELFType(ELFT::TargetEndianness == support::little, + ELFT::Is64Bits); + } +}; + +// Use an alignment of 2 for the typedefs since that is the worst case for +// ELF files in archives. +typedef ELFObjectFile > ELF32LEObjectFile; +typedef ELFObjectFile > ELF64LEObjectFile; +typedef ELFObjectFile > ELF32BEObjectFile; +typedef ELFObjectFile > ELF64BEObjectFile; + +template +error_code ELFObjectFile::getSymbolNext(DataRefImpl Symb, + SymbolRef &Result) const { + Result = SymbolRef(toDRI(++toELFSymIter(Symb)), this); + return object_error::success; +} + +template +error_code ELFObjectFile::getSymbolName(DataRefImpl Symb, + StringRef &Result) const { + ErrorOr Name = EF.getSymbolName(toELFSymIter(Symb)); + if (!Name) + return Name; + Result = *Name; + return object_error::success; +} + +template +error_code ELFObjectFile::getSymbolVersion(SymbolRef SymRef, + StringRef &Version, + bool &IsDefault) const { + DataRefImpl Symb = SymRef.getRawDataRefImpl(); + const Elf_Sym *symb = getSymbol(Symb); + ErrorOr Ver = + EF.getSymbolVersion(EF.getSection(Symb.d.b), symb, IsDefault); + if (!Ver) + return Ver; + Version = *Ver; + return object_error::success; +} + +template +error_code ELFObjectFile::getSymbolFileOffset(DataRefImpl Symb, + uint64_t &Result) const { + const Elf_Sym *ESym = getSymbol(Symb); + const Elf_Shdr *ESec; + switch (EF.getSymbolTableIndex(ESym)) { + case ELF::SHN_COMMON: + // Unintialized symbols have no offset in the object file + case ELF::SHN_UNDEF: + Result = UnknownAddressOrSize; + return object_error::success; + case ELF::SHN_ABS: + Result = ESym->st_value; + return object_error::success; + default: + ESec = EF.getSection(ESym); + } + + switch (ESym->getType()) { + case ELF::STT_SECTION: + Result = ESec ? ESec->sh_offset : UnknownAddressOrSize; + return object_error::success; + case ELF::STT_FUNC: + case ELF::STT_OBJECT: + case ELF::STT_NOTYPE: + Result = ESym->st_value + (ESec ? ESec->sh_offset : 0); + return object_error::success; + default: + Result = UnknownAddressOrSize; + return object_error::success; + } +} + +template +error_code ELFObjectFile::getSymbolAddress(DataRefImpl Symb, + uint64_t &Result) const { + const Elf_Sym *ESym = getSymbol(Symb); + const Elf_Shdr *ESec; + switch (EF.getSymbolTableIndex(ESym)) { + case ELF::SHN_COMMON: + case ELF::SHN_UNDEF: + Result = UnknownAddressOrSize; + return object_error::success; + case ELF::SHN_ABS: + Result = ESym->st_value; + return object_error::success; + default: + ESec = EF.getSection(ESym); + } + + switch (ESym->getType()) { + case ELF::STT_SECTION: + Result = ESec ? ESec->sh_addr : UnknownAddressOrSize; + return object_error::success; + case ELF::STT_FUNC: + case ELF::STT_OBJECT: + case ELF::STT_NOTYPE: + bool IsRelocatable; + switch (EF.getHeader()->e_type) { + case ELF::ET_EXEC: + case ELF::ET_DYN: + IsRelocatable = false; + break; + default: + IsRelocatable = true; + } + Result = ESym->st_value; + + // Clear the ARM/Thumb indicator flag. + if (EF.getHeader()->e_machine == ELF::EM_ARM) + Result &= ~1; + + if (IsRelocatable && ESec != 0) + Result += ESec->sh_addr; + return object_error::success; + default: + Result = UnknownAddressOrSize; + return object_error::success; + } +} + +template +error_code ELFObjectFile::getSymbolAlignment(DataRefImpl Symb, + uint32_t &Res) const { + Elf_Sym_Iter Sym = toELFSymIter(Symb); + if (Sym->st_shndx == ELF::SHN_COMMON) + Res = Sym->st_value; + else + Res = 0; + return object_error::success; +} + +template +error_code ELFObjectFile::getSymbolSize(DataRefImpl Symb, + uint64_t &Result) const { + Result = toELFSymIter(Symb)->st_size; + return object_error::success; +} + +template +error_code ELFObjectFile::getSymbolType(DataRefImpl Symb, + SymbolRef::Type &Result) const { + const Elf_Sym *ESym = getSymbol(Symb); + + switch (ESym->getType()) { + case ELF::STT_NOTYPE: + Result = SymbolRef::ST_Unknown; + break; + case ELF::STT_SECTION: + Result = SymbolRef::ST_Debug; + break; + case ELF::STT_FILE: + Result = SymbolRef::ST_File; + break; + case ELF::STT_FUNC: + Result = SymbolRef::ST_Function; + break; + case ELF::STT_OBJECT: + case ELF::STT_COMMON: + case ELF::STT_TLS: + Result = SymbolRef::ST_Data; + break; + default: + Result = SymbolRef::ST_Other; + break; + } + return object_error::success; +} + +template +error_code ELFObjectFile::getSymbolFlags(DataRefImpl Symb, + uint32_t &Result) const { + const Elf_Sym *ESym = getSymbol(Symb); + + Result = SymbolRef::SF_None; + + if (ESym->getBinding() != ELF::STB_LOCAL) + Result |= SymbolRef::SF_Global; + + if (ESym->getBinding() == ELF::STB_WEAK) + Result |= SymbolRef::SF_Weak; + + if (ESym->st_shndx == ELF::SHN_ABS) + Result |= SymbolRef::SF_Absolute; + + if (ESym->getType() == ELF::STT_FILE || ESym->getType() == ELF::STT_SECTION || + ESym == &*EF.begin_symbols()) + Result |= SymbolRef::SF_FormatSpecific; + + if (EF.getSymbolTableIndex(ESym) == ELF::SHN_UNDEF) + Result |= SymbolRef::SF_Undefined; + + if (ESym->getType() == ELF::STT_COMMON || + EF.getSymbolTableIndex(ESym) == ELF::SHN_COMMON) + Result |= SymbolRef::SF_Common; + + if (ESym->getType() == ELF::STT_TLS) + Result |= SymbolRef::SF_ThreadLocal; + + return object_error::success; +} + +template +error_code ELFObjectFile::getSymbolSection(DataRefImpl Symb, + section_iterator &Res) const { + const Elf_Sym *ESym = getSymbol(Symb); + const Elf_Shdr *ESec = EF.getSection(ESym); + if (!ESec) + Res = end_sections(); + else { + DataRefImpl Sec; + Sec.p = reinterpret_cast(ESec); + Res = section_iterator(SectionRef(Sec, this)); + } + return object_error::success; +} + +template +error_code ELFObjectFile::getSymbolValue(DataRefImpl Symb, + uint64_t &Val) const { + const Elf_Sym *ESym = getSymbol(Symb); + Val = ESym->st_value; + return object_error::success; +} + +template +error_code ELFObjectFile::getSectionNext(DataRefImpl Sec, + SectionRef &Result) const { + Result = SectionRef(toDRI(++toELFShdrIter(Sec)), this); + return object_error::success; +} + +template +error_code ELFObjectFile::getSectionName(DataRefImpl Sec, + StringRef &Result) const { + ErrorOr Name = EF.getSectionName(&*toELFShdrIter(Sec)); + if (!Name) + return Name; + Result = *Name; + return object_error::success; +} + +template +error_code ELFObjectFile::getSectionAddress(DataRefImpl Sec, + uint64_t &Result) const { + Result = toELFShdrIter(Sec)->sh_addr; + return object_error::success; +} + +template +error_code ELFObjectFile::getSectionSize(DataRefImpl Sec, + uint64_t &Result) const { + Result = toELFShdrIter(Sec)->sh_size; + return object_error::success; +} + +template +error_code ELFObjectFile::getSectionContents(DataRefImpl Sec, + StringRef &Result) const { + Elf_Shdr_Iter EShdr = toELFShdrIter(Sec); + Result = StringRef((const char *)base() + EShdr->sh_offset, EShdr->sh_size); + return object_error::success; +} + +template +error_code ELFObjectFile::getSectionAlignment(DataRefImpl Sec, + uint64_t &Result) const { + Result = toELFShdrIter(Sec)->sh_addralign; + return object_error::success; +} + +template +error_code ELFObjectFile::isSectionText(DataRefImpl Sec, + bool &Result) const { + Result = toELFShdrIter(Sec)->sh_flags & ELF::SHF_EXECINSTR; + return object_error::success; +} + +template +error_code ELFObjectFile::isSectionData(DataRefImpl Sec, + bool &Result) const { + Elf_Shdr_Iter EShdr = toELFShdrIter(Sec); + Result = EShdr->sh_flags & (ELF::SHF_ALLOC | ELF::SHF_WRITE) && + EShdr->sh_type == ELF::SHT_PROGBITS; + return object_error::success; +} + +template +error_code ELFObjectFile::isSectionBSS(DataRefImpl Sec, + bool &Result) const { + Elf_Shdr_Iter EShdr = toELFShdrIter(Sec); + Result = EShdr->sh_flags & (ELF::SHF_ALLOC | ELF::SHF_WRITE) && + EShdr->sh_type == ELF::SHT_NOBITS; + return object_error::success; +} + +template +error_code +ELFObjectFile::isSectionRequiredForExecution(DataRefImpl Sec, + bool &Result) const { + Result = toELFShdrIter(Sec)->sh_flags & ELF::SHF_ALLOC; + return object_error::success; +} + +template +error_code ELFObjectFile::isSectionVirtual(DataRefImpl Sec, + bool &Result) const { + Result = toELFShdrIter(Sec)->sh_type == ELF::SHT_NOBITS; + return object_error::success; +} + +template +error_code ELFObjectFile::isSectionZeroInit(DataRefImpl Sec, + bool &Result) const { + Result = toELFShdrIter(Sec)->sh_type == ELF::SHT_NOBITS; + return object_error::success; +} + +template +error_code ELFObjectFile::isSectionReadOnlyData(DataRefImpl Sec, + bool &Result) const { + Elf_Shdr_Iter EShdr = toELFShdrIter(Sec); + Result = !(EShdr->sh_flags & (ELF::SHF_WRITE | ELF::SHF_EXECINSTR)); + return object_error::success; +} + +template +error_code ELFObjectFile::sectionContainsSymbol(DataRefImpl Sec, + DataRefImpl Symb, + bool &Result) const { + Elf_Sym_Iter ESym = toELFSymIter(Symb); + + uintX_t Index = ESym->st_shndx; + bool Reserved = Index >= ELF::SHN_LORESERVE && Index <= ELF::SHN_HIRESERVE; + + Result = !Reserved && (&*toELFShdrIter(Sec) == EF.getSection(ESym->st_shndx)); + return object_error::success; +} + +template +relocation_iterator +ELFObjectFile::section_rel_begin(DataRefImpl Sec) const { + DataRefImpl RelData; + uintptr_t SHT = reinterpret_cast(EF.begin_sections().get()); + RelData.d.a = (Sec.p - SHT) / EF.getHeader()->e_shentsize; + RelData.d.b = 0; + return relocation_iterator(RelocationRef(RelData, this)); +} + +template +relocation_iterator +ELFObjectFile::section_rel_end(DataRefImpl Sec) const { + DataRefImpl RelData; + uintptr_t SHT = reinterpret_cast(EF.begin_sections().get()); + const Elf_Shdr *S = reinterpret_cast(Sec.p); + RelData.d.a = (Sec.p - SHT) / EF.getHeader()->e_shentsize; + if (S->sh_type != ELF::SHT_RELA && S->sh_type != ELF::SHT_REL) + RelData.d.b = 0; + else + RelData.d.b = S->sh_size / S->sh_entsize; + + return relocation_iterator(RelocationRef(RelData, this)); +} + +template +section_iterator +ELFObjectFile::getRelocatedSection(DataRefImpl Sec) const { + if (EF.getHeader()->e_type != ELF::ET_REL) + return end_sections(); + + Elf_Shdr_Iter EShdr = toELFShdrIter(Sec); + uintX_t Type = EShdr->sh_type; + if (Type != ELF::SHT_REL && Type != ELF::SHT_RELA) + return end_sections(); + + const Elf_Shdr *R = EF.getSection(EShdr->sh_info); + return section_iterator(SectionRef(toDRI(R), this)); +} + +// Relocations +template +error_code ELFObjectFile::getRelocationNext(DataRefImpl Rel, + RelocationRef &Result) const { + ++Rel.d.b; + Result = RelocationRef(Rel, this); + return object_error::success; +} + +template +symbol_iterator +ELFObjectFile::getRelocationSymbol(DataRefImpl Rel) const { + uint32_t symbolIdx; + const Elf_Shdr *sec = getRelSection(Rel); + switch (sec->sh_type) { + default: + report_fatal_error("Invalid section type in Rel!"); + case ELF::SHT_REL: { + symbolIdx = getRel(Rel)->getSymbol(EF.isMips64EL()); + break; + } + case ELF::SHT_RELA: { + symbolIdx = getRela(Rel)->getSymbol(EF.isMips64EL()); + break; + } + } + if (!symbolIdx) + return end_symbols(); + + const Elf_Shdr *SymSec = EF.getSection(sec->sh_link); + + DataRefImpl SymbolData; + switch (SymSec->sh_type) { + default: + report_fatal_error("Invalid symbol table section type!"); + case ELF::SHT_SYMTAB: + SymbolData = toDRI(EF.begin_symbols() + symbolIdx); + break; + case ELF::SHT_DYNSYM: + SymbolData = toDRI(EF.begin_dynamic_symbols() + symbolIdx); + break; + } + + return symbol_iterator(SymbolRef(SymbolData, this)); +} + +template +error_code ELFObjectFile::getRelocationAddress(DataRefImpl Rel, + uint64_t &Result) const { + Result = getROffset(Rel); + return object_error::success; +} + +template +error_code ELFObjectFile::getRelocationOffset(DataRefImpl Rel, + uint64_t &Result) const { + Result = getROffset(Rel); + return object_error::success; +} + +template +uint64_t ELFObjectFile::getROffset(DataRefImpl Rel) const { + const Elf_Shdr *sec = getRelSection(Rel); + switch (sec->sh_type) { + default: + report_fatal_error("Invalid section type in Rel!"); + case ELF::SHT_REL: + return getRel(Rel)->r_offset; + case ELF::SHT_RELA: + return getRela(Rel)->r_offset; + } +} + +template +error_code ELFObjectFile::getRelocationType(DataRefImpl Rel, + uint64_t &Result) const { + const Elf_Shdr *sec = getRelSection(Rel); + switch (sec->sh_type) { + default: + report_fatal_error("Invalid section type in Rel!"); + case ELF::SHT_REL: { + Result = getRel(Rel)->getType(EF.isMips64EL()); + break; + } + case ELF::SHT_RELA: { + Result = getRela(Rel)->getType(EF.isMips64EL()); + break; + } + } + return object_error::success; +} + +template +StringRef ELFObjectFile::getRelocationTypeName(uint32_t Type) const { + return getELFRelocationTypeName(EF.getHeader()->e_machine, Type); +} + +template +error_code ELFObjectFile::getRelocationTypeName( + DataRefImpl Rel, SmallVectorImpl &Result) const { + const Elf_Shdr *sec = getRelSection(Rel); + uint32_t type; + switch (sec->sh_type) { + default: + return object_error::parse_failed; + case ELF::SHT_REL: { + type = getRel(Rel)->getType(EF.isMips64EL()); + break; + } + case ELF::SHT_RELA: { + type = getRela(Rel)->getType(EF.isMips64EL()); + break; + } + } + + EF.getRelocationTypeName(type, Result); + return object_error::success; +} + +template +error_code ELFObjectFile::getRelocationAddend(DataRefImpl Rel, + int64_t &Result) const { + const Elf_Shdr *sec = getRelSection(Rel); + switch (sec->sh_type) { + default: + report_fatal_error("Invalid section type in Rel!"); + case ELF::SHT_REL: { + Result = 0; + return object_error::success; + } + case ELF::SHT_RELA: { + Result = getRela(Rel)->r_addend; + return object_error::success; + } + } +} + +template +error_code ELFObjectFile::getRelocationValueString( + DataRefImpl Rel, SmallVectorImpl &Result) const { + const Elf_Shdr *sec = getRelSection(Rel); + uint8_t type; + StringRef res; + int64_t addend = 0; + uint16_t symbol_index = 0; + switch (sec->sh_type) { + default: + return object_error::parse_failed; + case ELF::SHT_REL: { + type = getRel(Rel)->getType(EF.isMips64EL()); + symbol_index = getRel(Rel)->getSymbol(EF.isMips64EL()); + // TODO: Read implicit addend from section data. + break; + } + case ELF::SHT_RELA: { + type = getRela(Rel)->getType(EF.isMips64EL()); + symbol_index = getRela(Rel)->getSymbol(EF.isMips64EL()); + addend = getRela(Rel)->r_addend; + break; + } + } + const Elf_Sym *symb = + EF.template getEntry(sec->sh_link, symbol_index); + ErrorOr SymName = + EF.getSymbolName(EF.getSection(sec->sh_link), symb); + if (!SymName) + return SymName; + switch (EF.getHeader()->e_machine) { + case ELF::EM_X86_64: + switch (type) { + case ELF::R_X86_64_PC8: + case ELF::R_X86_64_PC16: + case ELF::R_X86_64_PC32: { + std::string fmtbuf; + raw_string_ostream fmt(fmtbuf); + fmt << *SymName << (addend < 0 ? "" : "+") << addend << "-P"; + fmt.flush(); + Result.append(fmtbuf.begin(), fmtbuf.end()); + } break; + case ELF::R_X86_64_8: + case ELF::R_X86_64_16: + case ELF::R_X86_64_32: + case ELF::R_X86_64_32S: + case ELF::R_X86_64_64: { + std::string fmtbuf; + raw_string_ostream fmt(fmtbuf); + fmt << *SymName << (addend < 0 ? "" : "+") << addend; + fmt.flush(); + Result.append(fmtbuf.begin(), fmtbuf.end()); + } break; + default: + res = "Unknown"; + } + break; + case ELF::EM_AARCH64: { + std::string fmtbuf; + raw_string_ostream fmt(fmtbuf); + fmt << *SymName; + if (addend != 0) + fmt << (addend < 0 ? "" : "+") << addend; + fmt.flush(); + Result.append(fmtbuf.begin(), fmtbuf.end()); + break; + } + case ELF::EM_ARM: + case ELF::EM_HEXAGON: + res = *SymName; + break; + default: + res = "Unknown"; + } + if (Result.empty()) + Result.append(res.begin(), res.end()); + return object_error::success; +} + +template +const typename ELFFile::Elf_Sym * +ELFObjectFile::getSymbol(DataRefImpl Symb) const { + return &*toELFSymIter(Symb); +} + +template +const typename ELFObjectFile::Elf_Rel * +ELFObjectFile::getRel(DataRefImpl Rel) const { + return EF.template getEntry(Rel.d.a, Rel.d.b); +} + +template +const typename ELFObjectFile::Elf_Rela * +ELFObjectFile::getRela(DataRefImpl Rela) const { + return EF.template getEntry(Rela.d.a, Rela.d.b); +} + +template +ELFObjectFile::ELFObjectFile(MemoryBuffer *Object, error_code &ec) + : ObjectFile(getELFType(static_cast(ELFT::TargetEndianness) == + support::little, + ELFT::Is64Bits), + Object), + EF(Object, ec) {} + +template +symbol_iterator ELFObjectFile::begin_symbols() const { + return symbol_iterator(SymbolRef(toDRI(EF.begin_symbols()), this)); +} + +template +symbol_iterator ELFObjectFile::end_symbols() const { + return symbol_iterator(SymbolRef(toDRI(EF.end_symbols()), this)); +} + +template +symbol_iterator ELFObjectFile::begin_dynamic_symbols() const { + return symbol_iterator(SymbolRef(toDRI(EF.begin_dynamic_symbols()), this)); +} + +template +symbol_iterator ELFObjectFile::end_dynamic_symbols() const { + return symbol_iterator(SymbolRef(toDRI(EF.end_dynamic_symbols()), this)); +} + +template +section_iterator ELFObjectFile::begin_sections() const { + return section_iterator(SectionRef(toDRI(EF.begin_sections()), this)); +} + +template +section_iterator ELFObjectFile::end_sections() const { + return section_iterator(SectionRef(toDRI(EF.end_sections()), this)); +} + +template +StringRef ELFObjectFile::getLoadName() const { + Elf_Dyn_Iter DI = EF.begin_dynamic_table(); + Elf_Dyn_Iter DE = EF.end_dynamic_table(); + + while (DI != DE && DI->getTag() != ELF::DT_SONAME) + ++DI; + + if (DI != DE) + return EF.getDynamicString(DI->getVal()); + return ""; +} + +template +library_iterator ELFObjectFile::begin_libraries_needed() const { + Elf_Dyn_Iter DI = EF.begin_dynamic_table(); + Elf_Dyn_Iter DE = EF.end_dynamic_table(); + + while (DI != DE && DI->getTag() != ELF::DT_SONAME) + ++DI; + + return library_iterator(LibraryRef(toDRI(DI), this)); +} + +template +error_code ELFObjectFile::getLibraryNext(DataRefImpl Data, + LibraryRef &Result) const { + Elf_Dyn_Iter DI = toELFDynIter(Data); + Elf_Dyn_Iter DE = EF.end_dynamic_table(); + + // Skip to the next DT_NEEDED entry. + do + ++DI; + while (DI != DE && DI->getTag() != ELF::DT_NEEDED); + + Result = LibraryRef(toDRI(DI), this); + return object_error::success; +} + +template +error_code ELFObjectFile::getLibraryPath(DataRefImpl Data, + StringRef &Res) const { + Res = EF.getDynamicString(toELFDynIter(Data)->getVal()); + return object_error::success; +} + +template +library_iterator ELFObjectFile::end_libraries_needed() const { + return library_iterator(LibraryRef(toDRI(EF.end_dynamic_table()), this)); +} + +template +uint8_t ELFObjectFile::getBytesInAddress() const { + return ELFT::Is64Bits ? 8 : 4; +} + +template +StringRef ELFObjectFile::getFileFormatName() const { + switch (EF.getHeader()->e_ident[ELF::EI_CLASS]) { + case ELF::ELFCLASS32: + switch (EF.getHeader()->e_machine) { + case ELF::EM_386: + return "ELF32-i386"; + case ELF::EM_X86_64: + return "ELF32-x86-64"; + case ELF::EM_ARM: + return "ELF32-arm"; + case ELF::EM_HEXAGON: + return "ELF32-hexagon"; + case ELF::EM_MIPS: + return "ELF32-mips"; + case ELF::EM_PPC: + return "ELF32-ppc"; + default: + return "ELF32-unknown"; + } + case ELF::ELFCLASS64: + switch (EF.getHeader()->e_machine) { + case ELF::EM_386: + return "ELF64-i386"; + case ELF::EM_X86_64: + return "ELF64-x86-64"; + case ELF::EM_AARCH64: + return "ELF64-aarch64"; + case ELF::EM_PPC64: + return "ELF64-ppc64"; + case ELF::EM_S390: + return "ELF64-s390"; + default: + return "ELF64-unknown"; + } + default: + // FIXME: Proper error handling. + report_fatal_error("Invalid ELFCLASS!"); + } +} + +template +unsigned ELFObjectFile::getArch() const { + switch (EF.getHeader()->e_machine) { + case ELF::EM_386: + return Triple::x86; + case ELF::EM_X86_64: + return Triple::x86_64; + case ELF::EM_AARCH64: + return Triple::aarch64; + case ELF::EM_ARM: + return Triple::arm; + case ELF::EM_HEXAGON: + return Triple::hexagon; + case ELF::EM_MIPS: + return (ELFT::TargetEndianness == support::little) ? Triple::mipsel + : Triple::mips; + case ELF::EM_PPC64: + return (ELFT::TargetEndianness == support::little) ? Triple::ppc64le + : Triple::ppc64; + case ELF::EM_S390: + return Triple::systemz; + default: + return Triple::UnknownArch; + } +} + +/// FIXME: Maybe we should have a base ElfObjectFile that is not a template +/// and make these member functions? +static inline error_code getELFRelocationAddend(const RelocationRef R, + int64_t &Addend) { + const ObjectFile *Obj = R.getObjectFile(); + DataRefImpl DRI = R.getRawDataRefImpl(); + // Little-endian 32-bit + if (const ELF32LEObjectFile *ELFObj = dyn_cast(Obj)) + return ELFObj->getRelocationAddend(DRI, Addend); + + // Big-endian 32-bit + if (const ELF32BEObjectFile *ELFObj = dyn_cast(Obj)) + return ELFObj->getRelocationAddend(DRI, Addend); + + // Little-endian 64-bit + if (const ELF64LEObjectFile *ELFObj = dyn_cast(Obj)) + return ELFObj->getRelocationAddend(DRI, Addend); + + // Big-endian 64-bit + if (const ELF64BEObjectFile *ELFObj = dyn_cast(Obj)) + return ELFObj->getRelocationAddend(DRI, Addend); + + llvm_unreachable("Object passed to getELFRelocationAddend() is not ELF"); +} + +/// This is a generic interface for retrieving GNU symbol version +/// information from an ELFObjectFile. +static inline error_code GetELFSymbolVersion(const ObjectFile *Obj, + const SymbolRef &Sym, + StringRef &Version, + bool &IsDefault) { + // Little-endian 32-bit + if (const ELF32LEObjectFile *ELFObj = dyn_cast(Obj)) + return ELFObj->getSymbolVersion(Sym, Version, IsDefault); + + // Big-endian 32-bit + if (const ELF32BEObjectFile *ELFObj = dyn_cast(Obj)) + return ELFObj->getSymbolVersion(Sym, Version, IsDefault); + + // Little-endian 64-bit + if (const ELF64LEObjectFile *ELFObj = dyn_cast(Obj)) + return ELFObj->getSymbolVersion(Sym, Version, IsDefault); + + // Big-endian 64-bit + if (const ELF64BEObjectFile *ELFObj = dyn_cast(Obj)) + return ELFObj->getSymbolVersion(Sym, Version, IsDefault); + + llvm_unreachable("Object passed to GetELFSymbolVersion() is not ELF"); +} +} +} + +#endif diff --git a/contrib/llvm/include/llvm/Object/ELFTypes.h b/contrib/llvm/include/llvm/Object/ELFTypes.h new file mode 100644 index 000000000..84b603125 --- /dev/null +++ b/contrib/llvm/include/llvm/Object/ELFTypes.h @@ -0,0 +1,463 @@ +//===- ELFTypes.h - Endian specific types for ELF ---------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_ELF_TYPES_H +#define LLVM_OBJECT_ELF_TYPES_H + +#include "llvm/Support/AlignOf.h" +#include "llvm/Support/DataTypes.h" +#include "llvm/Support/ELF.h" +#include "llvm/Support/Endian.h" + +namespace llvm { +namespace object { + +using support::endianness; + +template +struct ELFType { + static const endianness TargetEndianness = target_endianness; + static const std::size_t MaxAlignment = max_alignment; + static const bool Is64Bits = is64Bits; +}; + +template struct MaximumAlignment { + enum { value = AlignOf::Alignment > max_align ? max_align + : AlignOf::Alignment + }; +}; + +// Templates to choose Elf_Addr and Elf_Off depending on is64Bits. +template +struct ELFDataTypeTypedefHelperCommon { + typedef support::detail::packed_endian_specific_integral< + uint16_t, target_endianness, + MaximumAlignment::value> Elf_Half; + typedef support::detail::packed_endian_specific_integral< + uint32_t, target_endianness, + MaximumAlignment::value> Elf_Word; + typedef support::detail::packed_endian_specific_integral< + int32_t, target_endianness, + MaximumAlignment::value> Elf_Sword; + typedef support::detail::packed_endian_specific_integral< + uint64_t, target_endianness, + MaximumAlignment::value> Elf_Xword; + typedef support::detail::packed_endian_specific_integral< + int64_t, target_endianness, + MaximumAlignment::value> Elf_Sxword; +}; + +template struct ELFDataTypeTypedefHelper; + +/// ELF 32bit types. +template +struct ELFDataTypeTypedefHelper > + : ELFDataTypeTypedefHelperCommon { + typedef uint32_t value_type; + typedef support::detail::packed_endian_specific_integral< + value_type, TargetEndianness, + MaximumAlignment::value> Elf_Addr; + typedef support::detail::packed_endian_specific_integral< + value_type, TargetEndianness, + MaximumAlignment::value> Elf_Off; +}; + +/// ELF 64bit types. +template +struct ELFDataTypeTypedefHelper > + : ELFDataTypeTypedefHelperCommon { + typedef uint64_t value_type; + typedef support::detail::packed_endian_specific_integral< + value_type, TargetEndianness, + MaximumAlignment::value> Elf_Addr; + typedef support::detail::packed_endian_specific_integral< + value_type, TargetEndianness, + MaximumAlignment::value> Elf_Off; +}; + +// I really don't like doing this, but the alternative is copypasta. +#define LLVM_ELF_IMPORT_TYPES(E, M, W) \ +typedef typename ELFDataTypeTypedefHelper >::Elf_Addr \ + Elf_Addr; \ +typedef typename ELFDataTypeTypedefHelper >::Elf_Off \ + Elf_Off; \ +typedef typename ELFDataTypeTypedefHelper >::Elf_Half \ + Elf_Half; \ +typedef typename ELFDataTypeTypedefHelper >::Elf_Word \ + Elf_Word; \ +typedef typename ELFDataTypeTypedefHelper >::Elf_Sword \ + Elf_Sword; \ +typedef typename ELFDataTypeTypedefHelper >::Elf_Xword \ + Elf_Xword; \ +typedef typename ELFDataTypeTypedefHelper >::Elf_Sxword \ + Elf_Sxword; + +#define LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) \ + LLVM_ELF_IMPORT_TYPES(ELFT::TargetEndianness, ELFT::MaxAlignment, \ + ELFT::Is64Bits) + +// Section header. +template struct Elf_Shdr_Base; + +template +struct Elf_Shdr_Base > { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) + Elf_Word sh_name; // Section name (index into string table) + Elf_Word sh_type; // Section type (SHT_*) + Elf_Word sh_flags; // Section flags (SHF_*) + Elf_Addr sh_addr; // Address where section is to be loaded + Elf_Off sh_offset; // File offset of section data, in bytes + Elf_Word sh_size; // Size of section, in bytes + Elf_Word sh_link; // Section type-specific header table index link + Elf_Word sh_info; // Section type-specific extra information + Elf_Word sh_addralign; // Section address alignment + Elf_Word sh_entsize; // Size of records contained within the section +}; + +template +struct Elf_Shdr_Base > { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) + Elf_Word sh_name; // Section name (index into string table) + Elf_Word sh_type; // Section type (SHT_*) + Elf_Xword sh_flags; // Section flags (SHF_*) + Elf_Addr sh_addr; // Address where section is to be loaded + Elf_Off sh_offset; // File offset of section data, in bytes + Elf_Xword sh_size; // Size of section, in bytes + Elf_Word sh_link; // Section type-specific header table index link + Elf_Word sh_info; // Section type-specific extra information + Elf_Xword sh_addralign; // Section address alignment + Elf_Xword sh_entsize; // Size of records contained within the section +}; + +template +struct Elf_Shdr_Impl : Elf_Shdr_Base { + using Elf_Shdr_Base::sh_entsize; + using Elf_Shdr_Base::sh_size; + + /// @brief Get the number of entities this section contains if it has any. + unsigned getEntityCount() const { + if (sh_entsize == 0) + return 0; + return sh_size / sh_entsize; + } +}; + +template struct Elf_Sym_Base; + +template +struct Elf_Sym_Base > { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) + Elf_Word st_name; // Symbol name (index into string table) + Elf_Addr st_value; // Value or address associated with the symbol + Elf_Word st_size; // Size of the symbol + unsigned char st_info; // Symbol's type and binding attributes + unsigned char st_other; // Must be zero; reserved + Elf_Half st_shndx; // Which section (header table index) it's defined in +}; + +template +struct Elf_Sym_Base > { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) + Elf_Word st_name; // Symbol name (index into string table) + unsigned char st_info; // Symbol's type and binding attributes + unsigned char st_other; // Must be zero; reserved + Elf_Half st_shndx; // Which section (header table index) it's defined in + Elf_Addr st_value; // Value or address associated with the symbol + Elf_Xword st_size; // Size of the symbol +}; + +template +struct Elf_Sym_Impl : Elf_Sym_Base { + using Elf_Sym_Base::st_info; + + // These accessors and mutators correspond to the ELF32_ST_BIND, + // ELF32_ST_TYPE, and ELF32_ST_INFO macros defined in the ELF specification: + unsigned char getBinding() const { return st_info >> 4; } + unsigned char getType() const { return st_info & 0x0f; } + void setBinding(unsigned char b) { setBindingAndType(b, getType()); } + void setType(unsigned char t) { setBindingAndType(getBinding(), t); } + void setBindingAndType(unsigned char b, unsigned char t) { + st_info = (b << 4) + (t & 0x0f); + } +}; + +/// Elf_Versym: This is the structure of entries in the SHT_GNU_versym section +/// (.gnu.version). This structure is identical for ELF32 and ELF64. +template +struct Elf_Versym_Impl { + LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) + Elf_Half vs_index; // Version index with flags (e.g. VERSYM_HIDDEN) +}; + +template struct Elf_Verdaux_Impl; + +/// Elf_Verdef: This is the structure of entries in the SHT_GNU_verdef section +/// (.gnu.version_d). This structure is identical for ELF32 and ELF64. +template +struct Elf_Verdef_Impl { + LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) + typedef Elf_Verdaux_Impl Elf_Verdaux; + Elf_Half vd_version; // Version of this structure (e.g. VER_DEF_CURRENT) + Elf_Half vd_flags; // Bitwise flags (VER_DEF_*) + Elf_Half vd_ndx; // Version index, used in .gnu.version entries + Elf_Half vd_cnt; // Number of Verdaux entries + Elf_Word vd_hash; // Hash of name + Elf_Word vd_aux; // Offset to the first Verdaux entry (in bytes) + Elf_Word vd_next; // Offset to the next Verdef entry (in bytes) + + /// Get the first Verdaux entry for this Verdef. + const Elf_Verdaux *getAux() const { + return reinterpret_cast((const char *)this + vd_aux); + } +}; + +/// Elf_Verdaux: This is the structure of auxiliary data in the SHT_GNU_verdef +/// section (.gnu.version_d). This structure is identical for ELF32 and ELF64. +template +struct Elf_Verdaux_Impl { + LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) + Elf_Word vda_name; // Version name (offset in string table) + Elf_Word vda_next; // Offset to next Verdaux entry (in bytes) +}; + +/// Elf_Verneed: This is the structure of entries in the SHT_GNU_verneed +/// section (.gnu.version_r). This structure is identical for ELF32 and ELF64. +template +struct Elf_Verneed_Impl { + LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) + Elf_Half vn_version; // Version of this structure (e.g. VER_NEED_CURRENT) + Elf_Half vn_cnt; // Number of associated Vernaux entries + Elf_Word vn_file; // Library name (string table offset) + Elf_Word vn_aux; // Offset to first Vernaux entry (in bytes) + Elf_Word vn_next; // Offset to next Verneed entry (in bytes) +}; + +/// Elf_Vernaux: This is the structure of auxiliary data in SHT_GNU_verneed +/// section (.gnu.version_r). This structure is identical for ELF32 and ELF64. +template +struct Elf_Vernaux_Impl { + LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) + Elf_Word vna_hash; // Hash of dependency name + Elf_Half vna_flags; // Bitwise Flags (VER_FLAG_*) + Elf_Half vna_other; // Version index, used in .gnu.version entries + Elf_Word vna_name; // Dependency name + Elf_Word vna_next; // Offset to next Vernaux entry (in bytes) +}; + +/// Elf_Dyn_Base: This structure matches the form of entries in the dynamic +/// table section (.dynamic) look like. +template struct Elf_Dyn_Base; + +template +struct Elf_Dyn_Base > { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) + Elf_Sword d_tag; + union { + Elf_Word d_val; + Elf_Addr d_ptr; + } d_un; +}; + +template +struct Elf_Dyn_Base > { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) + Elf_Sxword d_tag; + union { + Elf_Xword d_val; + Elf_Addr d_ptr; + } d_un; +}; + +/// Elf_Dyn_Impl: This inherits from Elf_Dyn_Base, adding getters and setters. +template +struct Elf_Dyn_Impl : Elf_Dyn_Base { + using Elf_Dyn_Base::d_tag; + using Elf_Dyn_Base::d_un; + int64_t getTag() const { return d_tag; } + uint64_t getVal() const { return d_un.d_val; } + uint64_t getPtr() const { return d_un.ptr; } +}; + +// Elf_Rel: Elf Relocation +template struct Elf_Rel_Base; + +template +struct Elf_Rel_Base, false> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) + Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) + Elf_Word r_info; // Symbol table index and type of relocation to apply + + uint32_t getRInfo(bool isMips64EL) const { + assert(!isMips64EL); + return r_info; + } + void setRInfo(uint32_t R) { r_info = R; } +}; + +template +struct Elf_Rel_Base, false> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) + Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) + Elf_Xword r_info; // Symbol table index and type of relocation to apply + + uint64_t getRInfo(bool isMips64EL) const { + uint64_t t = r_info; + if (!isMips64EL) + return t; + // Mips64 little endian has a "special" encoding of r_info. Instead of one + // 64 bit little endian number, it is a little endian 32 bit number followed + // by a 32 bit big endian number. + 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; + } +}; + +template +struct Elf_Rel_Base, true> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) + Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) + Elf_Word r_info; // Symbol table index and type of relocation to apply + Elf_Sword r_addend; // Compute value for relocatable field by adding this + + uint32_t getRInfo(bool isMips64EL) const { + assert(!isMips64EL); + return r_info; + } + void setRInfo(uint32_t R) { r_info = R; } +}; + +template +struct Elf_Rel_Base, true> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) + Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) + Elf_Xword r_info; // Symbol table index and type of relocation to apply + Elf_Sxword r_addend; // Compute value for relocatable field by adding this. + + uint64_t getRInfo(bool isMips64EL) const { + // Mips64 little endian has a "special" encoding of r_info. Instead of one + // 64 bit little endian number, it is a little endian 32 bit number followed + // by a 32 bit big endian number. + uint64_t t = r_info; + if (!isMips64EL) + return t; + 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; + } +}; + +template struct Elf_Rel_Impl; + +template +struct Elf_Rel_Impl, + isRela> : Elf_Rel_Base< + ELFType, isRela> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) + + // These accessors and mutators correspond to the ELF64_R_SYM, ELF64_R_TYPE, + // and ELF64_R_INFO macros defined in the ELF specification: + uint32_t getSymbol(bool isMips64EL) const { + return (uint32_t)(this->getRInfo(isMips64EL) >> 32); + } + 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)); + } +}; + +template +struct Elf_Rel_Impl, + isRela> : Elf_Rel_Base< + ELFType, isRela> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) + + // These accessors and mutators correspond to the ELF32_R_SYM, ELF32_R_TYPE, + // and ELF32_R_INFO macros defined in the ELF specification: + uint32_t getSymbol(bool isMips64EL) const { + return this->getRInfo(isMips64EL) >> 8; + } + 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); + } +}; + +template +struct Elf_Ehdr_Impl { + LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) + unsigned char e_ident[ELF::EI_NIDENT]; // ELF Identification bytes + Elf_Half e_type; // Type of file (see ET_*) + Elf_Half e_machine; // Required architecture for this file (see EM_*) + Elf_Word e_version; // Must be equal to 1 + Elf_Addr e_entry; // Address to jump to in order to start program + Elf_Off e_phoff; // Program header table's file offset, in bytes + Elf_Off e_shoff; // Section header table's file offset, in bytes + Elf_Word e_flags; // Processor-specific flags + Elf_Half e_ehsize; // Size of ELF header, in bytes + Elf_Half e_phentsize; // Size of an entry in the program header table + Elf_Half e_phnum; // Number of entries in the program header table + Elf_Half e_shentsize; // Size of an entry in the section header table + Elf_Half e_shnum; // Number of entries in the section header table + Elf_Half e_shstrndx; // Section header table index of section name + // string table + bool checkMagic() const { + return (memcmp(e_ident, ELF::ElfMagic, strlen(ELF::ElfMagic))) == 0; + } + unsigned char getFileClass() const { return e_ident[ELF::EI_CLASS]; } + unsigned char getDataEncoding() const { return e_ident[ELF::EI_DATA]; } +}; + +template struct Elf_Phdr_Impl; + +template +struct Elf_Phdr_Impl > { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) + Elf_Word p_type; // Type of segment + Elf_Off p_offset; // FileOffset where segment is located, in bytes + Elf_Addr p_vaddr; // Virtual Address of beginning of segment + Elf_Addr p_paddr; // Physical address of beginning of segment (OS-specific) + Elf_Word p_filesz; // Num. of bytes in file image of segment (may be zero) + Elf_Word p_memsz; // Num. of bytes in mem image of segment (may be zero) + Elf_Word p_flags; // Segment flags + Elf_Word p_align; // Segment alignment constraint +}; + +template +struct Elf_Phdr_Impl > { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) + Elf_Word p_type; // Type of segment + Elf_Word p_flags; // Segment flags + Elf_Off p_offset; // FileOffset where segment is located, in bytes + Elf_Addr p_vaddr; // Virtual Address of beginning of segment + Elf_Addr p_paddr; // Physical address of beginning of segment (OS-specific) + Elf_Xword p_filesz; // Num. of bytes in file image of segment (may be zero) + Elf_Xword p_memsz; // Num. of bytes in mem image of segment (may be zero) + Elf_Xword p_align; // Segment alignment constraint +}; + +} // end namespace object. +} // end namespace llvm. + +#endif diff --git a/contrib/llvm/include/llvm/Object/ELFYAML.h b/contrib/llvm/include/llvm/Object/ELFYAML.h new file mode 100644 index 000000000..fca965f3d --- /dev/null +++ b/contrib/llvm/include/llvm/Object/ELFYAML.h @@ -0,0 +1,163 @@ +//===- ELFYAML.h - ELF YAMLIO implementation --------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief This file declares classes for handling the YAML representation +/// of ELF. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_ELFYAML_H +#define LLVM_OBJECT_ELFYAML_H + +#include "llvm/Object/YAML.h" +#include "llvm/Support/ELF.h" + +namespace llvm { +namespace ELFYAML { + +// These types are invariant across 32/64-bit ELF, so for simplicity just +// directly give them their exact sizes. We don't need to worry about +// endianness because these are just the types in the YAMLIO structures, +// and are appropriately converted to the necessary endianness when +// reading/generating binary object files. +// The naming of these types is intended to be ELF_PREFIX, where PREFIX is +// the common prefix of the respective constants. E.g. ELF_EM corresponds +// to the `e_machine` constants, like `EM_X86_64`. +// In the future, these would probably be better suited by C++11 enum +// class's with appropriate fixed underlying type. +LLVM_YAML_STRONG_TYPEDEF(uint16_t, ELF_ET) +LLVM_YAML_STRONG_TYPEDEF(uint32_t, ELF_EM) +LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_ELFCLASS) +LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_ELFDATA) +LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_ELFOSABI) +LLVM_YAML_STRONG_TYPEDEF(uint32_t, ELF_SHT) +// 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) + +// For now, hardcode 64 bits everywhere that 32 or 64 would be needed +// since 64-bit can hold 32-bit values too. +struct FileHeader { + ELF_ELFCLASS Class; + ELF_ELFDATA Data; + ELF_ELFOSABI OSABI; + ELF_ET Type; + ELF_EM Machine; + llvm::yaml::Hex64 Entry; +}; +struct Symbol { + StringRef Name; + ELF_STT Type; + StringRef Section; + llvm::yaml::Hex64 Value; + llvm::yaml::Hex64 Size; +}; +struct LocalGlobalWeakSymbols { + std::vector Local; + std::vector Global; + std::vector Weak; +}; +struct Section { + StringRef Name; + ELF_SHT Type; + ELF_SHF Flags; + llvm::yaml::Hex64 Address; + object::yaml::BinaryRef Content; + StringRef Link; + llvm::yaml::Hex64 AddressAlign; +}; +struct Object { + FileHeader Header; + std::vector
    Sections; + // Although in reality the symbols reside in a section, it is a lot + // cleaner and nicer if we read them from the YAML as a separate + // top-level key, which automatically ensures that invariants like there + // being a single SHT_SYMTAB section are upheld. + LocalGlobalWeakSymbols Symbols; +}; + +} // end namespace ELFYAML +} // end namespace llvm + +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::Section) +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::Symbol) + +namespace llvm { +namespace yaml { + +template <> +struct ScalarEnumerationTraits { + static void enumeration(IO &IO, ELFYAML::ELF_ET &Value); +}; + +template <> +struct ScalarEnumerationTraits { + static void enumeration(IO &IO, ELFYAML::ELF_EM &Value); +}; + +template <> +struct ScalarEnumerationTraits { + static void enumeration(IO &IO, ELFYAML::ELF_ELFCLASS &Value); +}; + +template <> +struct ScalarEnumerationTraits { + static void enumeration(IO &IO, ELFYAML::ELF_ELFDATA &Value); +}; + +template <> +struct ScalarEnumerationTraits { + static void enumeration(IO &IO, ELFYAML::ELF_ELFOSABI &Value); +}; + +template <> +struct ScalarEnumerationTraits { + static void enumeration(IO &IO, ELFYAML::ELF_SHT &Value); +}; + +template <> +struct ScalarBitSetTraits { + static void bitset(IO &IO, ELFYAML::ELF_SHF &Value); +}; + +template <> +struct ScalarEnumerationTraits { + static void enumeration(IO &IO, ELFYAML::ELF_STT &Value); +}; + +template <> +struct MappingTraits { + static void mapping(IO &IO, ELFYAML::FileHeader &FileHdr); +}; + +template <> +struct MappingTraits { + static void mapping(IO &IO, ELFYAML::Symbol &Symbol); +}; + +template <> +struct MappingTraits { + static void mapping(IO &IO, ELFYAML::LocalGlobalWeakSymbols &Symbols); +}; + +template <> +struct MappingTraits { + static void mapping(IO &IO, ELFYAML::Section &Section); +}; + +template <> +struct MappingTraits { + static void mapping(IO &IO, ELFYAML::Object &Object); +}; + +} // end namespace yaml +} // end namespace llvm + +#endif diff --git a/contrib/llvm/include/llvm/Object/Error.h b/contrib/llvm/include/llvm/Object/Error.h index fbaf71c17..8b0570b02 100644 --- a/contrib/llvm/include/llvm/Object/Error.h +++ b/contrib/llvm/include/llvm/Object/Error.h @@ -22,17 +22,17 @@ namespace object { const error_category &object_category(); struct object_error { -enum _ { - success = 0, - invalid_file_type, - parse_failed, - unexpected_eof -}; - _ v_; - - object_error(_ v) : v_(v) {} - explicit object_error(int v) : v_(_(v)) {} - operator int() const {return v_;} + enum Impl { + success = 0, + arch_not_found, + invalid_file_type, + parse_failed, + unexpected_eof + }; + Impl V; + + object_error(Impl V) : V(V) {} + operator Impl() const { return V; } }; inline error_code make_error_code(object_error e) { @@ -43,7 +43,8 @@ inline error_code make_error_code(object_error e) { template <> struct is_error_code_enum : true_type { }; -template <> struct is_error_code_enum : true_type { }; +template <> struct is_error_code_enum : true_type { +}; } // end namespace llvm. diff --git a/contrib/llvm/include/llvm/Object/MachO.h b/contrib/llvm/include/llvm/Object/MachO.h index 14cd4d767..100613ac8 100644 --- a/contrib/llvm/include/llvm/Object/MachO.h +++ b/contrib/llvm/include/llvm/Object/MachO.h @@ -17,19 +17,43 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/Object/MachOFormat.h" +#include "llvm/ADT/Triple.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/MachO.h" -#include "llvm/Support/raw_ostream.h" namespace llvm { namespace object { +/// DiceRef - This is a value type class that represents a single +/// data in code entry in the table in a Mach-O object file. +class DiceRef { + DataRefImpl DicePimpl; + const ObjectFile *OwningObject; + +public: + DiceRef() : OwningObject(NULL) { } + + DiceRef(DataRefImpl DiceP, const ObjectFile *Owner); + + bool operator==(const DiceRef &Other) const; + bool operator<(const DiceRef &Other) const; + + error_code getNext(DiceRef &Result) const; + + error_code getOffset(uint32_t &Result) const; + error_code getLength(uint16_t &Result) const; + error_code getKind(uint16_t &Result) const; + + DataRefImpl getRawDataRefImpl() const; + const ObjectFile *getObjectFile() const; +}; +typedef content_iterator dice_iterator; + class MachOObjectFile : public ObjectFile { public: struct LoadCommandInfo { const char *Ptr; // Where in memory the load command is. - macho::LoadCommand C; // The command itself. + MachO::load_command C; // The command itself. }; MachOObjectFile(MemoryBuffer *Object, bool IsLittleEndian, bool Is64Bits, @@ -43,7 +67,6 @@ public: virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const; virtual error_code getSymbolType(DataRefImpl Symb, SymbolRef::Type &Res) const; - virtual error_code getSymbolNMTypeChar(DataRefImpl Symb, char &Res) const; virtual error_code getSymbolFlags(DataRefImpl Symb, uint32_t &Res) const; virtual error_code getSymbolSection(DataRefImpl Symb, section_iterator &Res) const; @@ -65,19 +88,17 @@ public: virtual error_code isSectionReadOnlyData(DataRefImpl Sec, bool &Res) const; virtual error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, bool &Result) const; - virtual relocation_iterator getSectionRelBegin(DataRefImpl Sec) const; - virtual relocation_iterator getSectionRelEnd(DataRefImpl Sec) const; + virtual relocation_iterator section_rel_begin(DataRefImpl Sec) const; + virtual relocation_iterator section_rel_end(DataRefImpl Sec) const; virtual error_code getRelocationNext(DataRefImpl Rel, RelocationRef &Res) const; virtual error_code getRelocationAddress(DataRefImpl Rel, uint64_t &Res) const; virtual error_code getRelocationOffset(DataRefImpl Rel, uint64_t &Res) const; - virtual error_code getRelocationSymbol(DataRefImpl Rel, SymbolRef &Res) const; + virtual symbol_iterator getRelocationSymbol(DataRefImpl Rel) const; virtual error_code getRelocationType(DataRefImpl Rel, uint64_t &Res) const; virtual error_code getRelocationTypeName(DataRefImpl Rel, SmallVectorImpl &Result) const; - virtual error_code getRelocationAdditionalInfo(DataRefImpl Rel, - int64_t &Res) const; virtual error_code getRelocationValueString(DataRefImpl Rel, SmallVectorImpl &Result) const; virtual error_code getRelocationHidden(DataRefImpl Rel, bool &Result) const; @@ -107,8 +128,11 @@ public: virtual StringRef getLoadName() const; - relocation_iterator getSectionRelBegin(unsigned Index) const; - relocation_iterator getSectionRelEnd(unsigned Index) const; + relocation_iterator section_rel_begin(unsigned Index) const; + relocation_iterator section_rel_end(unsigned Index) const; + + dice_iterator begin_dices() const; + dice_iterator end_dices() const; // In a MachO file, sections have a segment name. This is used in the .o // files. They have a single segment, but this field specifies which segment @@ -121,53 +145,60 @@ public: ArrayRef getSectionRawFinalSegmentName(DataRefImpl Sec) const; // MachO specific Info about relocations. - bool isRelocationScattered(const macho::RelocationEntry &RE) const; - unsigned getPlainRelocationSymbolNum(const macho::RelocationEntry &RE) const; - bool getPlainRelocationExternal(const macho::RelocationEntry &RE) const; - bool getScatteredRelocationScattered(const macho::RelocationEntry &RE) const; - uint32_t getScatteredRelocationValue(const macho::RelocationEntry &RE) const; - unsigned getAnyRelocationAddress(const macho::RelocationEntry &RE) const; - unsigned getAnyRelocationPCRel(const macho::RelocationEntry &RE) const; - unsigned getAnyRelocationLength(const macho::RelocationEntry &RE) const; - unsigned getAnyRelocationType(const macho::RelocationEntry &RE) const; - SectionRef getRelocationSection(const macho::RelocationEntry &RE) const; + bool isRelocationScattered(const MachO::any_relocation_info &RE) const; + unsigned getPlainRelocationSymbolNum( + const MachO::any_relocation_info &RE) const; + bool getPlainRelocationExternal(const MachO::any_relocation_info &RE) const; + bool getScatteredRelocationScattered( + const MachO::any_relocation_info &RE) const; + uint32_t getScatteredRelocationValue( + const MachO::any_relocation_info &RE) const; + unsigned getAnyRelocationAddress(const MachO::any_relocation_info &RE) const; + unsigned getAnyRelocationPCRel(const MachO::any_relocation_info &RE) const; + unsigned getAnyRelocationLength(const MachO::any_relocation_info &RE) const; + unsigned getAnyRelocationType(const MachO::any_relocation_info &RE) const; + SectionRef getRelocationSection(const MachO::any_relocation_info &RE) const; // Walk load commands. LoadCommandInfo getFirstLoadCommandInfo() const; LoadCommandInfo getNextLoadCommandInfo(const LoadCommandInfo &L) const; // MachO specific structures. - macho::Section getSection(DataRefImpl DRI) const; - macho::Section64 getSection64(DataRefImpl DRI) const; - macho::Section getSection(const LoadCommandInfo &L, unsigned Index) const; - macho::Section64 getSection64(const LoadCommandInfo &L, unsigned Index) const; - macho::SymbolTableEntry getSymbolTableEntry(DataRefImpl DRI) const; - macho::Symbol64TableEntry getSymbol64TableEntry(DataRefImpl DRI) const; - - macho::LinkeditDataLoadCommand + MachO::section getSection(DataRefImpl DRI) const; + MachO::section_64 getSection64(DataRefImpl DRI) const; + MachO::section getSection(const LoadCommandInfo &L, unsigned Index) const; + MachO::section_64 getSection64(const LoadCommandInfo &L,unsigned Index) const; + MachO::nlist getSymbolTableEntry(DataRefImpl DRI) const; + MachO::nlist_64 getSymbol64TableEntry(DataRefImpl DRI) const; + + MachO::linkedit_data_command getLinkeditDataLoadCommand(const LoadCommandInfo &L) const; - macho::SegmentLoadCommand + MachO::segment_command getSegmentLoadCommand(const LoadCommandInfo &L) const; - macho::Segment64LoadCommand + MachO::segment_command_64 getSegment64LoadCommand(const LoadCommandInfo &L) const; - macho::LinkerOptionsLoadCommand + MachO::linker_options_command getLinkerOptionsLoadCommand(const LoadCommandInfo &L) const; - macho::RelocationEntry getRelocation(DataRefImpl Rel) const; - macho::Header getHeader() const; - macho::Header64Ext getHeader64Ext() const; - macho::IndirectSymbolTableEntry - getIndirectSymbolTableEntry(const macho::DysymtabLoadCommand &DLC, + MachO::any_relocation_info getRelocation(DataRefImpl Rel) const; + MachO::data_in_code_entry getDice(DataRefImpl Rel) const; + MachO::mach_header getHeader() const; + MachO::mach_header_64 getHeader64() const; + uint32_t + getIndirectSymbolTableEntry(const MachO::dysymtab_command &DLC, unsigned Index) const; - macho::DataInCodeTableEntry getDataInCodeTableEntry(uint32_t DataOffset, - unsigned Index) const; - macho::SymtabLoadCommand getSymtabLoadCommand() const; - macho::DysymtabLoadCommand getDysymtabLoadCommand() const; + MachO::data_in_code_entry getDataInCodeTableEntry(uint32_t DataOffset, + unsigned Index) const; + MachO::symtab_command getSymtabLoadCommand() const; + MachO::dysymtab_command getDysymtabLoadCommand() const; + MachO::linkedit_data_command getDataInCodeLoadCommand() const; StringRef getStringTableData() const; bool is64Bit() const; void ReadULEB128s(uint64_t Index, SmallVectorImpl &Out) const; + static Triple::ArchType getArch(uint32_t CPUType); + static bool classof(const Binary *v) { return v->isMachO(); } @@ -177,8 +208,66 @@ private: SectionList Sections; const char *SymtabLoadCmd; const char *DysymtabLoadCmd; + const char *DataInCodeLoadCmd; }; +/// DiceRef +inline DiceRef::DiceRef(DataRefImpl DiceP, const ObjectFile *Owner) + : DicePimpl(DiceP) , OwningObject(Owner) {} + +inline bool DiceRef::operator==(const DiceRef &Other) const { + return DicePimpl == Other.DicePimpl; +} + +inline bool DiceRef::operator<(const DiceRef &Other) const { + return DicePimpl < Other.DicePimpl; +} + +inline error_code DiceRef::getNext(DiceRef &Result) const { + DataRefImpl Rel = DicePimpl; + const MachO::data_in_code_entry *P = + reinterpret_cast(Rel.p); + Rel.p = reinterpret_cast(P + 1); + Result = DiceRef(Rel, OwningObject); + return object_error::success; +} + +// Since a Mach-O data in code reference, a DiceRef, can only be created when +// the OwningObject ObjectFile is a MachOObjectFile a static_cast<> is used for +// the methods that get the values of the fields of the reference. + +inline error_code DiceRef::getOffset(uint32_t &Result) const { + const MachOObjectFile *MachOOF = + static_cast(OwningObject); + MachO::data_in_code_entry Dice = MachOOF->getDice(DicePimpl); + Result = Dice.offset; + return object_error::success; +} + +inline error_code DiceRef::getLength(uint16_t &Result) const { + const MachOObjectFile *MachOOF = + static_cast(OwningObject); + MachO::data_in_code_entry Dice = MachOOF->getDice(DicePimpl); + Result = Dice.length; + return object_error::success; +} + +inline error_code DiceRef::getKind(uint16_t &Result) const { + const MachOObjectFile *MachOOF = + static_cast(OwningObject); + MachO::data_in_code_entry Dice = MachOOF->getDice(DicePimpl); + Result = Dice.kind; + return object_error::success; +} + +inline DataRefImpl DiceRef::getRawDataRefImpl() const { + return DicePimpl; +} + +inline const ObjectFile *DiceRef::getObjectFile() const { + return OwningObject; +} + } } diff --git a/contrib/llvm/include/llvm/Object/MachOFormat.h b/contrib/llvm/include/llvm/Object/MachOFormat.h deleted file mode 100644 index ffca391ea..000000000 --- a/contrib/llvm/include/llvm/Object/MachOFormat.h +++ /dev/null @@ -1,415 +0,0 @@ -//===- MachOFormat.h - Mach-O Format Structures And Constants ---*- 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 various structures and constants which are platform -// independent and can be shared by any client which wishes to interact with -// Mach object files. -// -// The definitions here are purposely chosen to match the LLVM style as opposed -// to following the platform specific definition of the format. -// -// On a Mach system, see the includes for more information, in -// particular . -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_OBJECT_MACHOFORMAT_H -#define LLVM_OBJECT_MACHOFORMAT_H - -#include "llvm/Support/DataTypes.h" - -namespace llvm { -namespace object { - -/// General Mach platform information. -namespace mach { - /// @name CPU Type and Subtype Information - /// { - - /// \brief Capability bits used in CPU type encoding. - enum CPUTypeFlagsMask { - CTFM_ArchMask = 0xFF000000, - CTFM_ArchABI64 = 0x01000000 - }; - - /// \brief Machine type IDs used in CPU type encoding. - enum CPUTypeMachine { - CTM_i386 = 7, - CTM_x86_64 = CTM_i386 | CTFM_ArchABI64, - CTM_ARM = 12, - CTM_SPARC = 14, - CTM_PowerPC = 18, - CTM_PowerPC64 = CTM_PowerPC | CTFM_ArchABI64 - }; - - /// \brief Capability bits used in CPU subtype encoding. - enum CPUSubtypeFlagsMask { - CSFM_SubtypeMask = 0xFF000000, - CSFM_SubtypeLib64 = 0x80000000 - }; - - /// \brief ARM Machine Subtypes. - enum CPUSubtypeARM { - CSARM_ALL = 0, - CSARM_V4T = 5, - CSARM_V6 = 6, - CSARM_V5TEJ = 7, - CSARM_XSCALE = 8, - CSARM_V7 = 9, - CSARM_V7F = 10, - CSARM_V7S = 11, - CSARM_V7K = 12, - CSARM_V6M = 14, - CSARM_V7M = 15, - CSARM_V7EM = 16 - }; - - /// \brief PowerPC Machine Subtypes. - enum CPUSubtypePowerPC { - CSPPC_ALL = 0 - }; - - /// \brief SPARC Machine Subtypes. - enum CPUSubtypeSPARC { - CSSPARC_ALL = 0 - }; - - /// \brief x86 Machine Subtypes. - enum CPUSubtypeX86 { - CSX86_ALL = 3 - }; - - /// @} - -} // end namespace mach - -/// Format information for Mach object files. -namespace macho { - /// \brief Constants for structure sizes. - enum StructureSizes { - Header32Size = 28, - Header64Size = 32, - SegmentLoadCommand32Size = 56, - SegmentLoadCommand64Size = 72, - Section32Size = 68, - Section64Size = 80, - SymtabLoadCommandSize = 24, - DysymtabLoadCommandSize = 80, - Nlist32Size = 12, - Nlist64Size = 16, - RelocationInfoSize = 8, - LinkeditLoadCommandSize = 16 - }; - - /// \brief Constants for header magic field. - enum HeaderMagic { - HM_Object32 = 0xFEEDFACE, ///< 32-bit mach object file - HM_Object64 = 0xFEEDFACF, ///< 64-bit mach object file - HM_Universal = 0xCAFEBABE ///< Universal object file - }; - - /// \brief Header common to all Mach object files. - struct Header { - uint32_t Magic; - uint32_t CPUType; - uint32_t CPUSubtype; - uint32_t FileType; - uint32_t NumLoadCommands; - uint32_t SizeOfLoadCommands; - uint32_t Flags; - }; - - /// \brief Extended header for 64-bit object files. - struct Header64Ext { - uint32_t Reserved; - }; - - // See . - enum HeaderFileType { - HFT_Object = 0x1 - }; - - enum HeaderFlags { - HF_SubsectionsViaSymbols = 0x2000 - }; - - enum LoadCommandType { - LCT_Segment = 0x1, - LCT_Symtab = 0x2, - LCT_Dysymtab = 0xb, - LCT_Segment64 = 0x19, - LCT_UUID = 0x1b, - LCT_CodeSignature = 0x1d, - LCT_SegmentSplitInfo = 0x1e, - LCT_FunctionStarts = 0x26, - LCT_DataInCode = 0x29, - LCT_LinkerOptions = 0x2D - }; - - /// \brief Load command structure. - struct LoadCommand { - uint32_t Type; - uint32_t Size; - }; - - /// @name Load Command Structures - /// @{ - - struct SegmentLoadCommand { - uint32_t Type; - uint32_t Size; - char Name[16]; - uint32_t VMAddress; - uint32_t VMSize; - uint32_t FileOffset; - uint32_t FileSize; - uint32_t MaxVMProtection; - uint32_t InitialVMProtection; - uint32_t NumSections; - uint32_t Flags; - }; - - struct Segment64LoadCommand { - uint32_t Type; - uint32_t Size; - char Name[16]; - uint64_t VMAddress; - uint64_t VMSize; - uint64_t FileOffset; - uint64_t FileSize; - uint32_t MaxVMProtection; - uint32_t InitialVMProtection; - uint32_t NumSections; - uint32_t Flags; - }; - - struct SymtabLoadCommand { - uint32_t Type; - uint32_t Size; - uint32_t SymbolTableOffset; - uint32_t NumSymbolTableEntries; - uint32_t StringTableOffset; - uint32_t StringTableSize; - }; - - struct DysymtabLoadCommand { - uint32_t Type; - uint32_t Size; - - uint32_t LocalSymbolsIndex; - uint32_t NumLocalSymbols; - - uint32_t ExternalSymbolsIndex; - uint32_t NumExternalSymbols; - - uint32_t UndefinedSymbolsIndex; - uint32_t NumUndefinedSymbols; - - uint32_t TOCOffset; - uint32_t NumTOCEntries; - - uint32_t ModuleTableOffset; - uint32_t NumModuleTableEntries; - - uint32_t ReferenceSymbolTableOffset; - uint32_t NumReferencedSymbolTableEntries; - - uint32_t IndirectSymbolTableOffset; - uint32_t NumIndirectSymbolTableEntries; - - uint32_t ExternalRelocationTableOffset; - uint32_t NumExternalRelocationTableEntries; - - uint32_t LocalRelocationTableOffset; - uint32_t NumLocalRelocationTableEntries; - }; - - struct LinkeditDataLoadCommand { - uint32_t Type; - uint32_t Size; - uint32_t DataOffset; - uint32_t DataSize; - }; - - struct LinkerOptionsLoadCommand { - uint32_t Type; - uint32_t Size; - uint32_t Count; - // Load command is followed by Count number of zero-terminated UTF8 strings, - // and then zero-filled to be 4-byte aligned. - }; - - /// @} - /// @name Section Data - /// @{ - - enum SectionFlags { - SF_PureInstructions = 0x80000000 - }; - - struct Section { - char Name[16]; - char SegmentName[16]; - uint32_t Address; - uint32_t Size; - uint32_t Offset; - uint32_t Align; - uint32_t RelocationTableOffset; - uint32_t NumRelocationTableEntries; - uint32_t Flags; - uint32_t Reserved1; - uint32_t Reserved2; - }; - struct Section64 { - char Name[16]; - char SegmentName[16]; - uint64_t Address; - uint64_t Size; - uint32_t Offset; - uint32_t Align; - uint32_t RelocationTableOffset; - uint32_t NumRelocationTableEntries; - uint32_t Flags; - uint32_t Reserved1; - uint32_t Reserved2; - uint32_t Reserved3; - }; - - /// @} - /// @name Symbol Table Entries - /// @{ - - struct SymbolTableEntry { - uint32_t StringIndex; - uint8_t Type; - uint8_t SectionIndex; - uint16_t Flags; - uint32_t Value; - }; - // Despite containing a uint64_t, this structure is only 4-byte aligned within - // a MachO file. -#pragma pack(push) -#pragma pack(4) - struct Symbol64TableEntry { - uint32_t StringIndex; - uint8_t Type; - uint8_t SectionIndex; - uint16_t Flags; - uint64_t Value; - }; -#pragma pack(pop) - - /// @} - /// @name Data-in-code Table Entry - /// @{ - - // See . - enum DataRegionType { Data = 1, JumpTable8, JumpTable16, JumpTable32 }; - struct DataInCodeTableEntry { - uint32_t Offset; /* from mach_header to start of data region */ - uint16_t Length; /* number of bytes in data region */ - uint16_t Kind; /* a DataRegionType value */ - }; - - /// @} - /// @name Indirect Symbol Table - /// @{ - - struct IndirectSymbolTableEntry { - uint32_t Index; - }; - - /// @} - /// @name Relocation Data - /// @{ - - struct RelocationEntry { - uint32_t Word0; - uint32_t Word1; - }; - - /// @} - - // See . - enum SymbolTypeType { - STT_Undefined = 0x00, - STT_Absolute = 0x02, - STT_Section = 0x0e - }; - - enum SymbolTypeFlags { - // If any of these bits are set, then the entry is a stab entry number (see - // . Otherwise the other masks apply. - STF_StabsEntryMask = 0xe0, - - STF_TypeMask = 0x0e, - STF_External = 0x01, - STF_PrivateExtern = 0x10 - }; - - /// IndirectSymbolFlags - Flags for encoding special values in the indirect - /// symbol entry. - enum IndirectSymbolFlags { - ISF_Local = 0x80000000, - ISF_Absolute = 0x40000000 - }; - - /// RelocationFlags - Special flags for addresses. - enum RelocationFlags { - RF_Scattered = 0x80000000 - }; - - /// Common relocation info types. - enum RelocationInfoType { - RIT_Vanilla = 0, - RIT_Pair = 1, - RIT_Difference = 2 - }; - - /// Generic relocation info types, which are shared by some (but not all) - /// platforms. - enum RelocationInfoType_Generic { - RIT_Generic_PreboundLazyPointer = 3, - RIT_Generic_LocalDifference = 4, - RIT_Generic_TLV = 5 - }; - - /// X86_64 uses its own relocation types. - enum RelocationInfoTypeX86_64 { - // Note that x86_64 doesn't even share the common relocation types. - RIT_X86_64_Unsigned = 0, - RIT_X86_64_Signed = 1, - RIT_X86_64_Branch = 2, - RIT_X86_64_GOTLoad = 3, - RIT_X86_64_GOT = 4, - RIT_X86_64_Subtractor = 5, - RIT_X86_64_Signed1 = 6, - RIT_X86_64_Signed2 = 7, - RIT_X86_64_Signed4 = 8, - RIT_X86_64_TLV = 9 - }; - - /// ARM uses its own relocation types. - enum RelocationInfoTypeARM { - RIT_ARM_LocalDifference = 3, - RIT_ARM_PreboundLazyPointer = 4, - RIT_ARM_Branch24Bit = 5, - RIT_ARM_ThumbBranch22Bit = 6, - RIT_ARM_ThumbBranch32Bit = 7, - RIT_ARM_Half = 8, - RIT_ARM_HalfDifference = 9 - - }; - -} // end namespace macho - -} // end namespace object -} // end namespace llvm - -#endif diff --git a/contrib/llvm/include/llvm/Object/MachOUniversal.h b/contrib/llvm/include/llvm/Object/MachOUniversal.h new file mode 100644 index 000000000..c5d135925 --- /dev/null +++ b/contrib/llvm/include/llvm/Object/MachOUniversal.h @@ -0,0 +1,102 @@ +//===- MachOUniversal.h - Mach-O universal binaries -------------*- 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 Mach-O fat/universal binaries. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_MACHOUNIVERSAL_H +#define LLVM_OBJECT_MACHOUNIVERSAL_H + +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Triple.h" +#include "llvm/Object/Binary.h" +#include "llvm/Support/MachO.h" + +namespace llvm { +namespace object { + +class ObjectFile; + +class MachOUniversalBinary : public Binary { + virtual void anchor(); + + uint32_t NumberOfObjects; +public: + class ObjectForArch { + const MachOUniversalBinary *Parent; + /// \brief Index of object in the universal binary. + uint32_t Index; + /// \brief Descriptor of the object. + MachO::fat_arch Header; + + public: + ObjectForArch(const MachOUniversalBinary *Parent, uint32_t Index); + + void clear() { + Parent = 0; + Index = 0; + } + + bool operator==(const ObjectForArch &Other) const { + return (Parent == Other.Parent) && (Index == Other.Index); + } + + ObjectForArch getNext() const { return ObjectForArch(Parent, Index + 1); } + uint32_t getCPUType() const { return Header.cputype; } + + error_code getAsObjectFile(OwningPtr &Result) const; + }; + + class object_iterator { + ObjectForArch Obj; + public: + object_iterator(const ObjectForArch &Obj) : Obj(Obj) {} + const ObjectForArch* operator->() const { + return &Obj; + } + + bool operator==(const object_iterator &Other) const { + return Obj == Other.Obj; + } + bool operator!=(const object_iterator &Other) const { + return !(*this == Other); + } + + object_iterator& operator++() { // Preincrement + Obj = Obj.getNext(); + return *this; + } + }; + + MachOUniversalBinary(MemoryBuffer *Source, error_code &ec); + + object_iterator begin_objects() const { + return ObjectForArch(this, 0); + } + object_iterator end_objects() const { + return ObjectForArch(0, 0); + } + + uint32_t getNumberOfObjects() const { return NumberOfObjects; } + + // Cast methods. + static inline bool classof(Binary const *V) { + return V->isMachOUniversalBinary(); + } + + error_code getObjectForArch(Triple::ArchType Arch, + OwningPtr &Result) const; +}; + +} +} + +#endif diff --git a/contrib/llvm/include/llvm/Object/ObjectFile.h b/contrib/llvm/include/llvm/Object/ObjectFile.h index eb53cc0aa..9aea639ef 100644 --- a/contrib/llvm/include/llvm/Object/ObjectFile.h +++ b/contrib/llvm/include/llvm/Object/ObjectFile.h @@ -28,12 +28,8 @@ namespace object { class ObjectFile; union DataRefImpl { - struct { - // ELF needs this for relocations. This entire union should probably be a - // char[max(8, sizeof(uintptr_t))] and require the impl to cast. - uint16_t a, b; - uint32_t c; - } w; + // This entire union should probably be a + // char[max(8, sizeof(uintptr_t))] and require the impl to cast. struct { uint32_t a, b; } d; @@ -89,6 +85,7 @@ inline bool operator<(const DataRefImpl &a, const DataRefImpl &b) { } class SymbolRef; +typedef content_iterator symbol_iterator; /// RelocationRef - This is a value type class that represents a single /// relocation in the list of relocations in the object file. @@ -107,7 +104,7 @@ public: error_code getAddress(uint64_t &Result) const; error_code getOffset(uint64_t &Result) const; - error_code getSymbol(SymbolRef &Result) const; + symbol_iterator getSymbol() const; error_code getType(uint64_t &Result) const; /// @brief Indicates whether this relocation should hidden when listing @@ -119,7 +116,6 @@ public: /// /// This is for display purposes only. error_code getTypeName(SmallVectorImpl &Result) const; - error_code getAdditionalInfo(int64_t &Result) const; /// @brief Get a string that represents the calculation of the value of this /// relocation. @@ -128,11 +124,14 @@ public: error_code getValueString(SmallVectorImpl &Result) const; DataRefImpl getRawDataRefImpl() const; + const ObjectFile *getObjectFile() const; }; typedef content_iterator relocation_iterator; /// SectionRef - This is a value type class that represents a single section in /// the list of sections in the object file. +class SectionRef; +typedef content_iterator section_iterator; class SectionRef { friend class SymbolRef; DataRefImpl SectionPimpl; @@ -169,10 +168,10 @@ public: relocation_iterator begin_relocations() const; relocation_iterator end_relocations() const; + section_iterator getRelocatedSection() const; DataRefImpl getRawDataRefImpl() const; }; -typedef content_iterator section_iterator; /// SymbolRef - This is a value type class that represents a single symbol in /// the list of symbols in the object file. @@ -193,7 +192,7 @@ public: ST_Other }; - enum Flags { + enum Flags LLVM_ENUM_INT_TYPE(unsigned) { SF_None = 0, SF_Undefined = 1U << 0, // Symbol is defined in another object file SF_Global = 1U << 1, // Global symbol @@ -222,10 +221,6 @@ public: error_code getSize(uint64_t &Result) const; error_code getType(SymbolRef::Type &Result) const; - /// Returns the ascii char that should be displayed in a symbol table dump via - /// nm for this symbol. - error_code getNMTypeChar(char &Result) const; - /// Get symbol flags (bitwise OR of SymbolRef::Flags) error_code getFlags(uint32_t &Result) const; @@ -238,7 +233,6 @@ public: DataRefImpl getRawDataRefImpl() const; }; -typedef content_iterator symbol_iterator; /// LibraryRef - This is a value type class that represents a single library in /// the list of libraries needed by a shared or dynamic object. @@ -298,7 +292,6 @@ protected: virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const = 0; virtual error_code getSymbolType(DataRefImpl Symb, SymbolRef::Type &Res) const = 0; - virtual error_code getSymbolNMTypeChar(DataRefImpl Symb, char &Res) const = 0; virtual error_code getSymbolFlags(DataRefImpl Symb, uint32_t &Res) const = 0; virtual error_code getSymbolSection(DataRefImpl Symb, @@ -324,9 +317,9 @@ protected: virtual error_code isSectionReadOnlyData(DataRefImpl Sec, bool &Res) const =0; virtual error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, bool &Result) const = 0; - virtual relocation_iterator getSectionRelBegin(DataRefImpl Sec) const = 0; - virtual relocation_iterator getSectionRelEnd(DataRefImpl Sec) const = 0; - + virtual relocation_iterator section_rel_begin(DataRefImpl Sec) const = 0; + virtual relocation_iterator section_rel_end(DataRefImpl Sec) const = 0; + virtual section_iterator getRelocatedSection(DataRefImpl Sec) const; // Same as above for RelocationRef. friend class RelocationRef; @@ -336,14 +329,11 @@ protected: uint64_t &Res) const =0; virtual error_code getRelocationOffset(DataRefImpl Rel, uint64_t &Res) const =0; - virtual error_code getRelocationSymbol(DataRefImpl Rel, - SymbolRef &Res) const = 0; + virtual symbol_iterator getRelocationSymbol(DataRefImpl Rel) const = 0; virtual error_code getRelocationType(DataRefImpl Rel, uint64_t &Res) const = 0; virtual error_code getRelocationTypeName(DataRefImpl Rel, SmallVectorImpl &Result) const = 0; - virtual error_code getRelocationAdditionalInfo(DataRefImpl Rel, - int64_t &Res) const = 0; virtual error_code getRelocationValueString(DataRefImpl Rel, SmallVectorImpl &Result) const = 0; virtual error_code getRelocationHidden(DataRefImpl Rel, bool &Result) const { @@ -436,10 +426,6 @@ inline error_code SymbolRef::getSize(uint64_t &Result) const { return OwningObject->getSymbolSize(SymbolPimpl, Result); } -inline error_code SymbolRef::getNMTypeChar(char &Result) const { - return OwningObject->getSymbolNMTypeChar(SymbolPimpl, Result); -} - inline error_code SymbolRef::getFlags(uint32_t &Result) const { return OwningObject->getSymbolFlags(SymbolPimpl, Result); } @@ -533,11 +519,15 @@ inline error_code SectionRef::containsSymbol(SymbolRef S, bool &Result) const { } inline relocation_iterator SectionRef::begin_relocations() const { - return OwningObject->getSectionRelBegin(SectionPimpl); + return OwningObject->section_rel_begin(SectionPimpl); } inline relocation_iterator SectionRef::end_relocations() const { - return OwningObject->getSectionRelEnd(SectionPimpl); + return OwningObject->section_rel_end(SectionPimpl); +} + +inline section_iterator SectionRef::getRelocatedSection() const { + return OwningObject->getRelocatedSection(SectionPimpl); } inline DataRefImpl SectionRef::getRawDataRefImpl() const { @@ -566,8 +556,8 @@ inline error_code RelocationRef::getOffset(uint64_t &Result) const { return OwningObject->getRelocationOffset(RelocationPimpl, Result); } -inline error_code RelocationRef::getSymbol(SymbolRef &Result) const { - return OwningObject->getRelocationSymbol(RelocationPimpl, Result); +inline symbol_iterator RelocationRef::getSymbol() const { + return OwningObject->getRelocationSymbol(RelocationPimpl); } inline error_code RelocationRef::getType(uint64_t &Result) const { @@ -579,10 +569,6 @@ inline error_code RelocationRef::getTypeName(SmallVectorImpl &Result) return OwningObject->getRelocationTypeName(RelocationPimpl, Result); } -inline error_code RelocationRef::getAdditionalInfo(int64_t &Result) const { - return OwningObject->getRelocationAdditionalInfo(RelocationPimpl, Result); -} - inline error_code RelocationRef::getValueString(SmallVectorImpl &Result) const { return OwningObject->getRelocationValueString(RelocationPimpl, Result); @@ -596,6 +582,10 @@ inline DataRefImpl RelocationRef::getRawDataRefImpl() const { return RelocationPimpl; } +inline const ObjectFile *RelocationRef::getObjectFile() const { + return OwningObject; +} + // Inline function definitions. inline LibraryRef::LibraryRef(DataRefImpl LibraryP, const ObjectFile *Owner) : LibraryPimpl(LibraryP) diff --git a/contrib/llvm/include/llvm/Object/RelocVisitor.h b/contrib/llvm/include/llvm/Object/RelocVisitor.h index 6239ec179..97912fe52 100644 --- a/contrib/llvm/include/llvm/Object/RelocVisitor.h +++ b/contrib/llvm/include/llvm/Object/RelocVisitor.h @@ -18,6 +18,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/Object/ObjectFile.h" +#include "llvm/Object/ELFObjectFile.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ELF.h" #include "llvm/Support/raw_ostream.h" @@ -80,6 +81,16 @@ public: switch (RelocType) { case llvm::ELF::R_PPC64_ADDR32: return visitELF_PPC64_ADDR32(R, Value); + case llvm::ELF::R_PPC64_ADDR64: + return visitELF_PPC64_ADDR64(R, Value); + default: + HasError = true; + return RelocToApply(); + } + } else if (FileFormat == "ELF32-ppc") { + switch (RelocType) { + case llvm::ELF::R_PPC_ADDR32: + return visitELF_PPC_ADDR32(R, Value); default: HasError = true; return RelocToApply(); @@ -123,6 +134,37 @@ private: StringRef FileFormat; bool HasError; + int64_t getAddend32LE(RelocationRef R) { + const ELF32LEObjectFile *Obj = cast(R.getObjectFile()); + DataRefImpl DRI = R.getRawDataRefImpl(); + int64_t Addend; + Obj->getRelocationAddend(DRI, Addend); + return Addend; + } + + int64_t getAddend64LE(RelocationRef R) { + const ELF64LEObjectFile *Obj = cast(R.getObjectFile()); + DataRefImpl DRI = R.getRawDataRefImpl(); + int64_t Addend; + Obj->getRelocationAddend(DRI, Addend); + return Addend; + } + + int64_t getAddend32BE(RelocationRef R) { + const ELF32BEObjectFile *Obj = cast(R.getObjectFile()); + DataRefImpl DRI = R.getRawDataRefImpl(); + int64_t Addend; + Obj->getRelocationAddend(DRI, Addend); + return Addend; + } + + int64_t getAddend64BE(RelocationRef R) { + const ELF64BEObjectFile *Obj = cast(R.getObjectFile()); + DataRefImpl DRI = R.getRawDataRefImpl(); + int64_t Addend; + Obj->getRelocationAddend(DRI, Addend); + return Addend; + } /// Operations /// 386-ELF @@ -133,15 +175,13 @@ private: // Ideally the Addend here will be the addend in the data for // the relocation. It's not actually the case for Rel relocations. RelocToApply visitELF_386_32(RelocationRef R, uint64_t Value) { - int64_t Addend; - R.getAdditionalInfo(Addend); + int64_t Addend = getAddend32LE(R); return RelocToApply(Value + Addend, 4); } RelocToApply visitELF_386_PC32(RelocationRef R, uint64_t Value, uint64_t SecAddr) { - int64_t Addend; - R.getAdditionalInfo(Addend); + int64_t Addend = getAddend32LE(R); uint64_t Address; R.getOffset(Address); return RelocToApply(Value + Addend - Address, 4); @@ -152,35 +192,41 @@ private: return RelocToApply(0, 0); } RelocToApply visitELF_X86_64_64(RelocationRef R, uint64_t Value) { - int64_t Addend; - R.getAdditionalInfo(Addend); + int64_t Addend = getAddend64LE(R); return RelocToApply(Value + Addend, 8); } RelocToApply visitELF_X86_64_PC32(RelocationRef R, uint64_t Value, uint64_t SecAddr) { - int64_t Addend; - R.getAdditionalInfo(Addend); + int64_t Addend = getAddend64LE(R); uint64_t Address; R.getOffset(Address); return RelocToApply(Value + Addend - Address, 4); } RelocToApply visitELF_X86_64_32(RelocationRef R, uint64_t Value) { - int64_t Addend; - R.getAdditionalInfo(Addend); + int64_t Addend = getAddend64LE(R); uint32_t Res = (Value + Addend) & 0xFFFFFFFF; return RelocToApply(Res, 4); } RelocToApply visitELF_X86_64_32S(RelocationRef R, uint64_t Value) { - int64_t Addend; - R.getAdditionalInfo(Addend); + int64_t Addend = getAddend64LE(R); int32_t Res = (Value + Addend) & 0xFFFFFFFF; return RelocToApply(Res, 4); } /// PPC64 ELF RelocToApply visitELF_PPC64_ADDR32(RelocationRef R, uint64_t Value) { - int64_t Addend; - R.getAdditionalInfo(Addend); + int64_t Addend = getAddend64BE(R); + uint32_t Res = (Value + Addend) & 0xFFFFFFFF; + return RelocToApply(Res, 4); + } + RelocToApply visitELF_PPC64_ADDR64(RelocationRef R, uint64_t Value) { + int64_t Addend = getAddend64BE(R); + return RelocToApply(Value + Addend, 8); + } + + /// PPC32 ELF + RelocToApply visitELF_PPC_ADDR32(RelocationRef R, uint64_t Value) { + int64_t Addend = getAddend32BE(R); uint32_t Res = (Value + Addend) & 0xFFFFFFFF; return RelocToApply(Res, 4); } @@ -188,15 +234,14 @@ private: /// MIPS ELF RelocToApply visitELF_MIPS_32(RelocationRef R, uint64_t Value) { int64_t Addend; - R.getAdditionalInfo(Addend); + getELFRelocationAddend(R, Addend); uint32_t Res = (Value + Addend) & 0xFFFFFFFF; return RelocToApply(Res, 4); } // AArch64 ELF RelocToApply visitELF_AARCH64_ABS32(RelocationRef R, uint64_t Value) { - int64_t Addend; - R.getAdditionalInfo(Addend); + int64_t Addend = getAddend64LE(R); int64_t Res = Value + Addend; // Overflow check allows for both signed and unsigned interpretation. @@ -207,15 +252,13 @@ private: } RelocToApply visitELF_AARCH64_ABS64(RelocationRef R, uint64_t Value) { - int64_t Addend; - R.getAdditionalInfo(Addend); + int64_t Addend = getAddend64LE(R); return RelocToApply(Value + Addend, 8); } // SystemZ ELF RelocToApply visitELF_390_32(RelocationRef R, uint64_t Value) { - int64_t Addend; - R.getAdditionalInfo(Addend); + int64_t Addend = getAddend64BE(R); int64_t Res = Value + Addend; // Overflow check allows for both signed and unsigned interpretation. @@ -226,8 +269,7 @@ private: } RelocToApply visitELF_390_64(RelocationRef R, uint64_t Value) { - int64_t Addend; - R.getAdditionalInfo(Addend); + int64_t Addend = getAddend64BE(R); return RelocToApply(Value + Addend, 8); } }; diff --git a/contrib/llvm/include/llvm/Object/YAML.h b/contrib/llvm/include/llvm/Object/YAML.h new file mode 100644 index 000000000..89fe5047a --- /dev/null +++ b/contrib/llvm/include/llvm/Object/YAML.h @@ -0,0 +1,116 @@ +//===- YAML.h - YAMLIO utilities for object files ---------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares utility classes for handling the YAML representation of +// object files. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_YAML_H +#define LLVM_OBJECT_YAML_H + +#include "llvm/Support/YAMLTraits.h" + +namespace llvm { +namespace object { +namespace yaml { + +/// \brief Specialized YAMLIO scalar type for representing a binary blob. +/// +/// A typical use case would be to represent the content of a section in a +/// binary file. +/// This class has custom YAMLIO traits for convenient reading and writing. +/// It renders as a string of hex digits in a YAML file. +/// For example, it might render as `DEADBEEFCAFEBABE` (YAML does not +/// require the quotation marks, so for simplicity when outputting they are +/// omitted). +/// When reading, any string whose content is an even number of hex digits +/// will be accepted. +/// For example, all of the following are acceptable: +/// `DEADBEEF`, `"DeADbEeF"`, `"\x44EADBEEF"` (Note: '\x44' == 'D') +/// +/// A significant advantage of using this class is that it never allocates +/// temporary strings or buffers for any of its functionality. +/// +/// Example: +/// +/// The YAML mapping: +/// \code +/// Foo: DEADBEEFCAFEBABE +/// \endcode +/// +/// Could be modeled in YAMLIO by the struct: +/// \code +/// struct FooHolder { +/// BinaryRef Foo; +/// }; +/// namespace llvm { +/// namespace yaml { +/// template <> +/// struct MappingTraits { +/// static void mapping(IO &IO, FooHolder &FH) { +/// IO.mapRequired("Foo", FH.Foo); +/// } +/// }; +/// } // end namespace yaml +/// } // end namespace llvm +/// \endcode +class BinaryRef { + friend bool operator==(const BinaryRef &LHS, const BinaryRef &RHS); + /// \brief Either raw binary data, or a string of hex bytes (must always + /// be an even number of characters). + ArrayRef Data; + /// \brief Discriminator between the two states of the `Data` member. + bool DataIsHexString; + +public: + BinaryRef(ArrayRef Data) : Data(Data), DataIsHexString(false) {} + BinaryRef(StringRef Data) + : Data(reinterpret_cast(Data.data()), Data.size()), + DataIsHexString(true) {} + BinaryRef() : DataIsHexString(true) {} + /// \brief The number of bytes that are represented by this BinaryRef. + /// This is the number of bytes that writeAsBinary() will write. + ArrayRef::size_type binary_size() const { + if (DataIsHexString) + return Data.size() / 2; + return Data.size(); + } + /// \brief Write the contents (regardless of whether it is binary or a + /// hex string) as binary to the given raw_ostream. + void writeAsBinary(raw_ostream &OS) const; + /// \brief Write the contents (regardless of whether it is binary or a + /// hex string) as hex to the given raw_ostream. + /// + /// For example, a possible output could be `DEADBEEFCAFEBABE`. + void writeAsHex(raw_ostream &OS) const; +}; + +inline bool operator==(const BinaryRef &LHS, const BinaryRef &RHS) { + // Special case for default constructed BinaryRef. + if (LHS.Data.empty() && RHS.Data.empty()) + return true; + + return LHS.DataIsHexString == RHS.DataIsHexString && LHS.Data == RHS.Data; +} + +} +} + +namespace yaml { +template <> struct ScalarTraits { + static void output(const object::yaml::BinaryRef &, void *, + llvm::raw_ostream &); + static StringRef input(StringRef, void *, object::yaml::BinaryRef &); +}; +} + +} + +#endif diff --git a/contrib/llvm/include/llvm/Option/ArgList.h b/contrib/llvm/include/llvm/Option/ArgList.h index d3accfe7f..06ba679c2 100644 --- a/contrib/llvm/include/llvm/Option/ArgList.h +++ b/contrib/llvm/include/llvm/Option/ArgList.h @@ -222,8 +222,17 @@ public: /// negation are present, the last one wins. bool hasFlag(OptSpecifier Pos, OptSpecifier Neg, bool Default=true) const; + /// hasFlag - Given an option \p Pos, an alias \p PosAlias and its negative + /// form \p Neg, return true if the option or its alias is present, false if + /// the negation is present, and \p Default if none of the options are + /// given. If multiple options are present, the last one wins. + bool hasFlag(OptSpecifier Pos, OptSpecifier PosAlias, OptSpecifier Neg, + bool Default = true) const; + /// AddLastArg - Render only the last argument match \p Id0, if present. void AddLastArg(ArgStringList &Output, OptSpecifier Id0) const; + void AddLastArg(ArgStringList &Output, OptSpecifier Id0, + OptSpecifier Id1) const; /// AddAllArgs - Render all arguments matching the given ids. void AddAllArgs(ArgStringList &Output, OptSpecifier Id0, diff --git a/contrib/llvm/include/llvm/Option/OptParser.td b/contrib/llvm/include/llvm/Option/OptParser.td index e781fa02d..963389f0b 100644 --- a/contrib/llvm/include/llvm/Option/OptParser.td +++ b/contrib/llvm/include/llvm/Option/OptParser.td @@ -14,10 +14,10 @@ // Define the kinds of options. -class OptionKind { +class OptionKind { string Name = name; // The kind precedence, kinds with lower precedence are matched first. - int Precedence = predecence; + int Precedence = precedence; // Indicate a sentinel option. bit Sentinel = sentinel; } @@ -44,6 +44,8 @@ def KIND_JOINED_OR_SEPARATE : OptionKind<"JoinedOrSeparate">; // An option which is both joined to its (first) value, and followed by its // (second) value. def KIND_JOINED_AND_SEPARATE : OptionKind<"JoinedAndSeparate">; +// An option which consumes all remaining arguments if there are any. +def KIND_REMAINING_ARGS : OptionKind<"RemainingArgs">; // Define the option flags. @@ -89,6 +91,7 @@ class Option prefixes, string name, OptionKind kind> { list Flags = []; OptionGroup Group = ?; Option Alias = ?; + list AliasArgs = []; } // Helpers for defining options. @@ -113,6 +116,7 @@ class JoinedAndSeparate prefixes, string name> // Mix-ins for adding optional attributes. class Alias