From 84352263094535b949890be955bc402783e2d9e8 Mon Sep 17 00:00:00 2001 From: dim Date: Fri, 28 Oct 2011 21:08:39 +0000 Subject: [PATCH] MFC r226633: Upgrade our copy of llvm/clang to r142614, from upstream's release_30 branch. This brings us very close to the 3.0 release, which is expected November 16, 2011. Approved by: re (kib) git-svn-id: svn://svn.freebsd.org/base/stable/9@226890 ccf9f872-aa2e-dd11-9fc8-001c23d0bc1f --- Makefile.inc1 | 4 +- contrib/llvm/include/llvm-c/Core.h | 75 +- contrib/llvm/include/llvm-c/Disassembler.h | 32 +- contrib/llvm/include/llvm-c/Object.h | 8 +- contrib/llvm/include/llvm-c/Target.h | 20 +- contrib/llvm/include/llvm-c/Transforms/IPO.h | 9 +- .../llvm-c/Transforms/PassManagerBuilder.h | 90 + .../llvm/include/llvm-c/Transforms/Scalar.h | 3 + contrib/llvm/include/llvm/ADT/APInt.h | 30 +- contrib/llvm/include/llvm/ADT/ArrayRef.h | 48 +- contrib/llvm/include/llvm/ADT/DenseMap.h | 6 + contrib/llvm/include/llvm/ADT/DenseMapInfo.h | 14 +- contrib/llvm/include/llvm/ADT/DenseSet.h | 2 +- contrib/llvm/include/llvm/ADT/ImmutableMap.h | 157 + contrib/llvm/include/llvm/ADT/ImmutableSet.h | 134 + contrib/llvm/include/llvm/ADT/IntervalMap.h | 3 + contrib/llvm/include/llvm/ADT/PointerUnion.h | 6 +- .../llvm/include/llvm/ADT/PostOrderIterator.h | 10 + contrib/llvm/include/llvm/ADT/SCCIterator.h | 10 +- contrib/llvm/include/llvm/ADT/STLExtras.h | 34 +- contrib/llvm/include/llvm/ADT/SmallVector.h | 17 +- contrib/llvm/include/llvm/ADT/Statistic.h | 18 +- contrib/llvm/include/llvm/ADT/StringExtras.h | 1 + contrib/llvm/include/llvm/ADT/TinyPtrVector.h | 133 + contrib/llvm/include/llvm/ADT/Triple.h | 37 +- contrib/llvm/include/llvm/ADT/Twine.h | 108 +- .../include/llvm/Analysis/AliasAnalysis.h | 42 +- .../include/llvm/Analysis/AliasSetTracker.h | 34 +- .../llvm/Analysis/BlockFrequencyImpl.h | 76 +- ...{BlockFrequency.h => BlockFrequencyInfo.h} | 26 +- .../llvm/Analysis/BranchProbabilityInfo.h | 14 +- .../llvm/include/llvm/Analysis/CodeMetrics.h | 17 +- .../include/llvm/Analysis/ConstantFolding.h | 14 +- .../llvm/include/llvm/Analysis/DIBuilder.h | 25 + .../llvm/include/llvm/Analysis/DebugInfo.h | 80 +- .../include/llvm/Analysis/FindUsedTypes.h | 6 +- contrib/llvm/include/llvm/Analysis/IVUsers.h | 2 + .../llvm/include/llvm/Analysis/InlineCost.h | 9 +- .../llvm/Analysis/InstructionSimplify.h | 11 +- contrib/llvm/include/llvm/Analysis/LoopInfo.h | 78 +- .../llvm/include/llvm/Analysis/LoopIterator.h | 186 + contrib/llvm/include/llvm/Analysis/LoopPass.h | 2 +- .../include/llvm/Analysis/MemoryBuiltins.h | 4 +- .../llvm/Analysis/MemoryDependenceAnalysis.h | 61 +- .../llvm/include/llvm/Analysis/RegionPass.h | 2 +- .../include/llvm/Analysis/ScalarEvolution.h | 242 +- .../llvm/Analysis/ScalarEvolutionExpander.h | 53 +- .../Analysis/ScalarEvolutionExpressions.h | 28 +- contrib/llvm/include/llvm/Argument.h | 2 +- contrib/llvm/include/llvm/Attributes.h | 7 +- contrib/llvm/include/llvm/AutoUpgrade.h | 4 + contrib/llvm/include/llvm/BasicBlock.h | 17 + .../llvm/include/llvm/Bitcode/LLVMBitCodes.h | 48 +- contrib/llvm/include/llvm/CodeGen/Analysis.h | 6 +- .../include/llvm/CodeGen/CalcSpillWeights.h | 5 - contrib/llvm/include/llvm/CodeGen/FastISel.h | 20 +- .../llvm/CodeGen/FunctionLoweringInfo.h | 16 +- .../llvm/include/llvm/CodeGen/ISDOpcodes.h | 66 +- .../llvm/include/llvm/CodeGen/LexicalScopes.h | 248 + .../llvm/include/llvm/CodeGen/LiveInterval.h | 18 +- .../include/llvm/CodeGen/LiveStackAnalysis.h | 2 + .../llvm/include/llvm/CodeGen/LiveVariables.h | 2 + .../include/llvm/CodeGen/MachineBasicBlock.h | 2 +- ...requency.h => MachineBlockFrequencyInfo.h} | 25 +- .../llvm/CodeGen/MachineConstantPool.h | 10 +- .../include/llvm/CodeGen/MachineFrameInfo.h | 10 + .../llvm/include/llvm/CodeGen/MachineInstr.h | 30 +- .../include/llvm/CodeGen/MachineModuleInfo.h | 92 +- .../include/llvm/CodeGen/MachineOperand.h | 28 +- .../llvm/CodeGen/MachineRegisterInfo.h | 43 +- contrib/llvm/include/llvm/CodeGen/Passes.h | 25 +- .../llvm/include/llvm/CodeGen/SelectionDAG.h | 48 +- .../include/llvm/CodeGen/SelectionDAGNodes.h | 53 +- .../llvm/include/llvm/CodeGen/SlotIndexes.h | 2 +- .../CodeGen/TargetLoweringObjectFileImpl.h | 116 +- .../llvm/include/llvm/CodeGen/ValueTypes.h | 26 +- .../llvm/include/llvm/CompilerDriver/Action.h | 54 - .../llvm/CompilerDriver/AutoGenerated.h | 40 - .../llvm/CompilerDriver/BuiltinOptions.h | 39 - .../include/llvm/CompilerDriver/Common.td | 127 - .../llvm/CompilerDriver/CompilationGraph.h | 330 -- .../llvm/include/llvm/CompilerDriver/Error.h | 29 - .../llvm/include/llvm/CompilerDriver/Main.h | 21 - .../llvm/include/llvm/CompilerDriver/Main.inc | 23 - .../llvm/include/llvm/CompilerDriver/Tool.h | 100 - contrib/llvm/include/llvm/Constant.h | 12 +- contrib/llvm/include/llvm/Constants.h | 179 +- .../llvm/include/llvm/DebugInfo/DIContext.h | 68 + contrib/llvm/include/llvm/DerivedTypes.h | 104 +- .../llvm/ExecutionEngine/ExecutionEngine.h | 35 +- contrib/llvm/include/llvm/Function.h | 4 +- contrib/llvm/include/llvm/GlobalAlias.h | 11 +- contrib/llvm/include/llvm/GlobalValue.h | 2 +- contrib/llvm/include/llvm/GlobalVariable.h | 4 +- contrib/llvm/include/llvm/InitializePasses.h | 6 +- contrib/llvm/include/llvm/InlineAsm.h | 35 +- contrib/llvm/include/llvm/InstrTypes.h | 80 +- contrib/llvm/include/llvm/Instruction.def | 120 +- contrib/llvm/include/llvm/Instruction.h | 11 +- contrib/llvm/include/llvm/Instructions.h | 899 +++- contrib/llvm/include/llvm/IntrinsicInst.h | 2 +- contrib/llvm/include/llvm/Intrinsics.h | 2 +- contrib/llvm/include/llvm/Intrinsics.td | 93 +- contrib/llvm/include/llvm/IntrinsicsXCore.td | 23 +- contrib/llvm/include/llvm/LinkAllPasses.h | 4 +- contrib/llvm/include/llvm/Linker.h | 12 +- contrib/llvm/include/llvm/MC/EDInstInfo.h | 2 +- .../TargetAsmBackend.h => MC/MCAsmBackend.h} | 18 +- contrib/llvm/include/llvm/MC/MCAsmInfo.h | 76 +- .../llvm/include/llvm/MC/MCAsmInfoDarwin.h | 5 - contrib/llvm/include/llvm/MC/MCAssembler.h | 12 +- contrib/llvm/include/llvm/MC/MCAtom.h | 68 + contrib/llvm/include/llvm/MC/MCCodeGenInfo.h | 41 + contrib/llvm/include/llvm/MC/MCContext.h | 16 +- contrib/llvm/include/llvm/MC/MCDirectives.h | 5 +- contrib/llvm/include/llvm/MC/MCDisassembler.h | 58 +- contrib/llvm/include/llvm/MC/MCDwarf.h | 7 +- contrib/llvm/include/llvm/MC/MCInst.h | 10 + contrib/llvm/include/llvm/MC/MCInstPrinter.h | 6 +- .../llvm/include/llvm/MC/MCInstrAnalysis.h | 61 + contrib/llvm/include/llvm/MC/MCInstrDesc.h | 121 +- contrib/llvm/include/llvm/MC/MCModule.h | 58 + .../llvm/include/llvm/MC/MCObjectFileInfo.h | 294 ++ .../llvm/include/llvm/MC/MCObjectStreamer.h | 6 +- .../llvm/include/llvm/MC/MCParser/AsmLexer.h | 2 + .../include/llvm/MC/MCParser/MCAsmLexer.h | 3 +- .../include/llvm/MC/MCParser/MCAsmParser.h | 11 +- contrib/llvm/include/llvm/MC/MCRegisterInfo.h | 184 +- contrib/llvm/include/llvm/MC/MCStreamer.h | 76 +- .../MCTargetAsmLexer.h} | 18 +- .../MCTargetAsmParser.h} | 44 +- contrib/llvm/include/llvm/MC/MCValue.h | 10 - .../llvm/{CodeGen => MC}/MachineLocation.h | 12 +- contrib/llvm/include/llvm/Module.h | 38 +- contrib/llvm/include/llvm/Object/Archive.h | 90 + contrib/llvm/include/llvm/Object/COFF.h | 32 + contrib/llvm/include/llvm/Object/MachO.h | 106 + .../llvm/include/llvm/Object/MachOFormat.h | 12 +- .../llvm/include/llvm/Object/MachOObject.h | 4 + contrib/llvm/include/llvm/Object/ObjectFile.h | 250 +- contrib/llvm/include/llvm/OperandTraits.h | 41 +- contrib/llvm/include/llvm/Operator.h | 4 +- contrib/llvm/include/llvm/PassManagers.h | 7 +- .../include/llvm/Support/BlockFrequency.h | 63 + .../include/llvm/Support/BranchProbability.h | 6 +- contrib/llvm/include/llvm/Support/CallSite.h | 2 +- contrib/llvm/include/llvm/Support/Capacity.h | 30 + contrib/llvm/include/llvm/Support/CodeGen.h | 32 + .../llvm/include/llvm/Support/CommandLine.h | 31 + .../include/llvm/Support/ConstantFolder.h | 56 +- .../llvm/include/llvm/Support/DataExtractor.h | 352 ++ .../llvm/include/llvm/Support/DataTypes.h.in | 92 +- contrib/llvm/include/llvm/Support/Dwarf.h | 53 +- .../include/llvm/Support/DynamicLibrary.h | 75 +- contrib/llvm/include/llvm/Support/ELF.h | 347 +- .../llvm/include/llvm/Support/FileSystem.h | 162 +- contrib/llvm/include/llvm/Support/Format.h | 62 + contrib/llvm/include/llvm/Support/GCOV.h | 224 + .../llvm/Support/GetElementPtrTypeIterator.h | 34 +- contrib/llvm/include/llvm/Support/IRBuilder.h | 148 +- .../llvm/include/llvm/Support/InstVisitor.h | 5 + contrib/llvm/include/llvm/Support/MachO.h | 11 + .../llvm/include/llvm/Support/MemoryBuffer.h | 6 +- contrib/llvm/include/llvm/Support/NoFolder.h | 44 +- .../include/llvm/Support/PassManagerBuilder.h | 331 -- contrib/llvm/include/llvm/Support/PathV1.h | 1 + contrib/llvm/include/llvm/Support/PathV2.h | 13 +- contrib/llvm/include/llvm/Support/Process.h | 3 + contrib/llvm/include/llvm/Support/SMLoc.h | 10 +- contrib/llvm/include/llvm/Support/SourceMgr.h | 11 +- .../llvm/include/llvm/Support/TargetFolder.h | 54 +- .../llvm/{Target => Support}/TargetRegistry.h | 459 +- .../llvm/{Target => Support}/TargetSelect.h | 52 +- .../llvm/include/llvm/Support/TypeBuilder.h | 101 +- .../{utils => include/llvm}/TableGen/Error.h | 6 +- contrib/llvm/include/llvm/TableGen/Main.h | 26 + .../{utils => include/llvm}/TableGen/Record.h | 491 +- .../include/llvm/TableGen/TableGenAction.h | 34 + .../llvm}/TableGen/TableGenBackend.h | 6 +- contrib/llvm/include/llvm/Target/Target.td | 7 +- .../llvm/include/llvm/Target/TargetAsmInfo.h | 103 - contrib/llvm/include/llvm/Target/TargetData.h | 44 +- .../include/llvm/Target/TargetFrameLowering.h | 17 +- .../include/llvm/Target/TargetInstrInfo.h | 55 +- .../include/llvm/Target/TargetIntrinsicInfo.h | 4 +- .../llvm/include/llvm/Target/TargetLowering.h | 246 +- .../llvm/Target/TargetLoweringObjectFile.h | 124 +- .../llvm/include/llvm/Target/TargetMachine.h | 44 +- .../llvm/include/llvm/Target/TargetOptions.h | 2 + .../include/llvm/Target/TargetRegisterInfo.h | 206 +- .../include/llvm/Target/TargetSelectionDAG.td | 44 +- contrib/llvm/include/llvm/Transforms/IPO.h | 9 +- .../llvm/Transforms/IPO/PassManagerBuilder.h | 133 + contrib/llvm/include/llvm/Transforms/Scalar.h | 7 - .../llvm/Transforms/Utils/AddrModeMatcher.h | 6 +- .../llvm/Transforms/Utils/BasicBlockUtils.h | 46 +- .../llvm/Transforms/Utils/FunctionUtils.h | 14 +- .../llvm/Transforms/Utils/SSAUpdater.h | 4 +- .../llvm/Transforms/Utils/SimplifyIndVar.h | 58 + .../llvm/Transforms/Utils/UnrollLoop.h | 3 +- .../llvm/Transforms/Utils/ValueMapper.h | 4 +- contrib/llvm/include/llvm/Type.h | 12 +- contrib/llvm/include/llvm/User.h | 2 +- contrib/llvm/include/llvm/Value.h | 4 +- contrib/llvm/lib/Analysis/AliasAnalysis.cpp | 50 +- .../lib/Analysis/AliasAnalysisEvaluator.cpp | 6 +- contrib/llvm/lib/Analysis/AliasSetTracker.cpp | 107 +- contrib/llvm/lib/Analysis/Analysis.cpp | 3 +- .../llvm/lib/Analysis/BasicAliasAnalysis.cpp | 136 +- contrib/llvm/lib/Analysis/BlockFrequency.cpp | 59 - .../llvm/lib/Analysis/BlockFrequencyInfo.cpp | 63 + .../lib/Analysis/BranchProbabilityInfo.cpp | 276 +- contrib/llvm/lib/Analysis/ConstantFolding.cpp | 126 +- contrib/llvm/lib/Analysis/DIBuilder.cpp | 286 +- contrib/llvm/lib/Analysis/DbgInfoPrinter.cpp | 2 +- contrib/llvm/lib/Analysis/DebugInfo.cpp | 275 +- .../lib/Analysis/IPA/CallGraphSCCPass.cpp | 7 +- .../llvm/lib/Analysis/IPA/FindUsedTypes.cpp | 4 +- contrib/llvm/lib/Analysis/IVUsers.cpp | 3 +- contrib/llvm/lib/Analysis/InlineCost.cpp | 124 +- .../llvm/lib/Analysis/InstructionSimplify.cpp | 173 +- contrib/llvm/lib/Analysis/LazyValueInfo.cpp | 6 +- contrib/llvm/lib/Analysis/Lint.cpp | 8 +- contrib/llvm/lib/Analysis/Loads.cpp | 12 +- .../lib/Analysis/LoopDependenceAnalysis.cpp | 8 +- contrib/llvm/lib/Analysis/LoopInfo.cpp | 296 +- contrib/llvm/lib/Analysis/LoopPass.cpp | 108 +- contrib/llvm/lib/Analysis/MemDepPrinter.cpp | 80 +- contrib/llvm/lib/Analysis/MemoryBuiltins.cpp | 16 +- .../lib/Analysis/MemoryDependenceAnalysis.cpp | 48 +- contrib/llvm/lib/Analysis/PHITransAddr.cpp | 8 +- contrib/llvm/lib/Analysis/PathNumbering.cpp | 2 +- contrib/llvm/lib/Analysis/RegionPass.cpp | 6 +- contrib/llvm/lib/Analysis/ScalarEvolution.cpp | 844 ++- .../lib/Analysis/ScalarEvolutionExpander.cpp | 393 +- .../Analysis/ScalarEvolutionNormalization.cpp | 101 +- contrib/llvm/lib/Analysis/ValueTracking.cpp | 39 +- contrib/llvm/lib/AsmParser/LLLexer.cpp | 30 +- contrib/llvm/lib/AsmParser/LLParser.cpp | 352 +- contrib/llvm/lib/AsmParser/LLParser.h | 26 +- contrib/llvm/lib/AsmParser/LLToken.h | 15 +- .../llvm/lib/Bitcode/Reader/BitcodeReader.cpp | 316 +- .../llvm/lib/Bitcode/Reader/BitcodeReader.h | 8 +- .../llvm/lib/Bitcode/Writer/BitcodeWriter.cpp | 156 +- .../lib/Bitcode/Writer/ValueEnumerator.cpp | 6 +- .../llvm/lib/Bitcode/Writer/ValueEnumerator.h | 8 +- contrib/llvm/lib/CodeGen/Analysis.cpp | 16 +- .../lib/CodeGen/AsmPrinter/ARMException.cpp | 2 - .../lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 155 +- .../CodeGen/AsmPrinter/AsmPrinterDwarf.cpp | 2 +- .../AsmPrinter/AsmPrinterInlineAsm.cpp | 15 +- contrib/llvm/lib/CodeGen/AsmPrinter/DIE.cpp | 2 +- .../CodeGen/AsmPrinter/DwarfCFIException.cpp | 5 +- .../CodeGen/AsmPrinter/DwarfCompileUnit.cpp | 407 +- .../lib/CodeGen/AsmPrinter/DwarfCompileUnit.h | 20 +- .../lib/CodeGen/AsmPrinter/DwarfDebug.cpp | 1403 ++--- .../llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h | 133 +- .../lib/CodeGen/AsmPrinter/DwarfException.cpp | 100 +- .../lib/CodeGen/AsmPrinter/Win64Exception.cpp | 1 - contrib/llvm/lib/CodeGen/BranchFolding.cpp | 29 +- contrib/llvm/lib/CodeGen/CalcSpillWeights.cpp | 32 - contrib/llvm/lib/CodeGen/CodeGen.cpp | 1 + contrib/llvm/lib/CodeGen/DwarfEHPrepare.cpp | 67 +- contrib/llvm/lib/CodeGen/ELFCodeEmitter.cpp | 2 +- contrib/llvm/lib/CodeGen/ELFCodeEmitter.h | 4 +- contrib/llvm/lib/CodeGen/ELFWriter.cpp | 12 +- .../ExecutionDepsFix.cpp} | 99 +- ...werSubregs.cpp => ExpandPostRAPseudos.cpp} | 114 +- contrib/llvm/lib/CodeGen/IfConversion.cpp | 39 +- contrib/llvm/lib/CodeGen/InlineSpiller.cpp | 434 +- .../llvm/lib/CodeGen/InterferenceCache.cpp | 5 +- contrib/llvm/lib/CodeGen/InterferenceCache.h | 3 +- .../llvm/lib/CodeGen/IntrinsicLowering.cpp | 10 +- .../llvm/lib/CodeGen/LLVMTargetMachine.cpp | 96 +- contrib/llvm/lib/CodeGen/LexicalScopes.cpp | 335 ++ .../llvm/lib/CodeGen/LiveDebugVariables.cpp | 71 +- contrib/llvm/lib/CodeGen/LiveInterval.cpp | 35 +- .../llvm/lib/CodeGen/LiveIntervalAnalysis.cpp | 29 +- .../llvm/lib/CodeGen/LiveIntervalUnion.cpp | 230 +- contrib/llvm/lib/CodeGen/LiveIntervalUnion.h | 78 +- contrib/llvm/lib/CodeGen/LiveRangeCalc.cpp | 270 + contrib/llvm/lib/CodeGen/LiveRangeCalc.h | 226 + contrib/llvm/lib/CodeGen/LiveRangeEdit.cpp | 5 +- contrib/llvm/lib/CodeGen/LiveRangeEdit.h | 2 +- .../llvm/lib/CodeGen/LiveStackAnalysis.cpp | 5 +- contrib/llvm/lib/CodeGen/LiveVariables.cpp | 2 +- .../llvm/lib/CodeGen/MachineBasicBlock.cpp | 5 + ...ency.cpp => MachineBlockFrequencyInfo.cpp} | 32 +- contrib/llvm/lib/CodeGen/MachineCSE.cpp | 11 + contrib/llvm/lib/CodeGen/MachineFunction.cpp | 2 +- contrib/llvm/lib/CodeGen/MachineInstr.cpp | 366 +- contrib/llvm/lib/CodeGen/MachineLICM.cpp | 156 +- .../llvm/lib/CodeGen/MachineModuleInfo.cpp | 37 +- .../llvm/lib/CodeGen/MachineRegisterInfo.cpp | 44 +- contrib/llvm/lib/CodeGen/MachineSink.cpp | 31 + contrib/llvm/lib/CodeGen/MachineVerifier.cpp | 70 +- contrib/llvm/lib/CodeGen/PHIElimination.cpp | 3 + .../llvm/lib/CodeGen/PeepholeOptimizer.cpp | 17 +- .../llvm/lib/CodeGen/ProcessImplicitDefs.cpp | 6 + .../llvm/lib/CodeGen/PrologEpilogInserter.cpp | 14 +- contrib/llvm/lib/CodeGen/RegAllocBasic.cpp | 10 +- contrib/llvm/lib/CodeGen/RegAllocGreedy.cpp | 523 +- .../llvm/lib/CodeGen/RegAllocLinearScan.cpp | 3 +- contrib/llvm/lib/CodeGen/RegAllocPBQP.cpp | 2 +- .../llvm/lib/CodeGen/RegisterClassInfo.cpp | 7 +- contrib/llvm/lib/CodeGen/RegisterClassInfo.h | 15 +- .../llvm/lib/CodeGen/RegisterCoalescer.cpp | 630 ++- contrib/llvm/lib/CodeGen/RegisterCoalescer.h | 205 +- .../llvm/lib/CodeGen/RegisterScavenging.cpp | 1 + contrib/llvm/lib/CodeGen/ScheduleDAG.cpp | 3 +- .../llvm/lib/CodeGen/ScheduleDAGInstrs.cpp | 3 +- contrib/llvm/lib/CodeGen/ScheduleDAGInstrs.h | 7 +- .../CodeGen/ScoreboardHazardRecognizer.cpp | 1 - .../lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 121 +- .../lib/CodeGen/SelectionDAG/FastISel.cpp | 48 +- .../SelectionDAG/FunctionLoweringInfo.cpp | 47 +- .../lib/CodeGen/SelectionDAG/InstrEmitter.cpp | 186 +- .../lib/CodeGen/SelectionDAG/InstrEmitter.h | 6 + .../lib/CodeGen/SelectionDAG/LegalizeDAG.cpp | 341 +- .../SelectionDAG/LegalizeFloatTypes.cpp | 27 +- .../SelectionDAG/LegalizeIntegerTypes.cpp | 184 +- .../CodeGen/SelectionDAG/LegalizeTypes.cpp | 33 +- .../lib/CodeGen/SelectionDAG/LegalizeTypes.h | 33 +- .../SelectionDAG/LegalizeTypesGeneric.cpp | 44 +- .../SelectionDAG/LegalizeVectorOps.cpp | 46 +- .../SelectionDAG/LegalizeVectorTypes.cpp | 118 +- .../SelectionDAG/ScheduleDAGRRList.cpp | 36 +- .../lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 184 +- .../SelectionDAG/SelectionDAGBuilder.cpp | 526 +- .../SelectionDAG/SelectionDAGBuilder.h | 39 +- .../CodeGen/SelectionDAG/SelectionDAGISel.cpp | 37 +- .../CodeGen/SelectionDAG/TargetLowering.cpp | 48 +- contrib/llvm/lib/CodeGen/ShadowStackGC.cpp | 52 +- contrib/llvm/lib/CodeGen/SjLjEHPrepare.cpp | 514 +- contrib/llvm/lib/CodeGen/SpillPlacement.cpp | 17 + contrib/llvm/lib/CodeGen/SpillPlacement.h | 14 + contrib/llvm/lib/CodeGen/SplitKit.cpp | 718 +-- contrib/llvm/lib/CodeGen/SplitKit.h | 171 +- contrib/llvm/lib/CodeGen/Splitter.cpp | 4 +- contrib/llvm/lib/CodeGen/StackProtector.cpp | 4 +- .../llvm/lib/CodeGen/StrongPHIElimination.cpp | 3 +- contrib/llvm/lib/CodeGen/TailDuplication.cpp | 1 + .../llvm/lib/CodeGen/TargetInstrInfoImpl.cpp | 76 +- .../CodeGen/TargetLoweringObjectFileImpl.cpp | 535 -- .../lib/CodeGen/TwoAddressInstructionPass.cpp | 13 +- contrib/llvm/lib/CodeGen/VirtRegMap.cpp | 32 +- contrib/llvm/lib/CompilerDriver/Action.cpp | 134 - .../lib/CompilerDriver/BuiltinOptions.cpp | 61 - .../lib/CompilerDriver/CompilationGraph.cpp | 655 --- contrib/llvm/lib/CompilerDriver/Main.cpp | 146 - contrib/llvm/lib/CompilerDriver/Tool.cpp | 95 - contrib/llvm/lib/DebugInfo/DIContext.cpp | 24 + .../DWARFAbbreviationDeclaration.cpp | 83 + .../DebugInfo/DWARFAbbreviationDeclaration.h | 54 + contrib/llvm/lib/DebugInfo/DWARFAttribute.h | 30 + .../llvm/lib/DebugInfo/DWARFCompileUnit.cpp | 238 + contrib/llvm/lib/DebugInfo/DWARFCompileUnit.h | 111 + contrib/llvm/lib/DebugInfo/DWARFContext.cpp | 167 + contrib/llvm/lib/DebugInfo/DWARFContext.h | 118 + .../llvm/lib/DebugInfo/DWARFDebugAbbrev.cpp | 106 + contrib/llvm/lib/DebugInfo/DWARFDebugAbbrev.h | 73 + .../lib/DebugInfo/DWARFDebugArangeSet.cpp | 150 + .../llvm/lib/DebugInfo/DWARFDebugArangeSet.h | 75 + .../llvm/lib/DebugInfo/DWARFDebugAranges.cpp | 223 + .../llvm/lib/DebugInfo/DWARFDebugAranges.h | 98 + .../lib/DebugInfo/DWARFDebugInfoEntry.cpp | 444 ++ .../llvm/lib/DebugInfo/DWARFDebugInfoEntry.h | 135 + contrib/llvm/lib/DebugInfo/DWARFDebugLine.cpp | 475 ++ contrib/llvm/lib/DebugInfo/DWARFDebugLine.h | 190 + contrib/llvm/lib/DebugInfo/DWARFFormValue.cpp | 427 ++ contrib/llvm/lib/DebugInfo/DWARFFormValue.h | 78 + .../lib/ExecutionEngine/ExecutionEngine.cpp | 34 +- .../ExecutionEngine/Interpreter/Execution.cpp | 133 +- .../Interpreter/ExternalFunctions.cpp | 34 +- .../ExecutionEngine/Interpreter/Interpreter.h | 30 +- .../lib/ExecutionEngine/JIT/Intercept.cpp | 1 + contrib/llvm/lib/ExecutionEngine/JIT/JIT.cpp | 8 +- contrib/llvm/lib/ExecutionEngine/JIT/JIT.h | 5 +- .../ExecutionEngine/JIT/JITDwarfEmitter.cpp | 10 +- .../lib/ExecutionEngine/JIT/JITDwarfEmitter.h | 4 +- .../lib/ExecutionEngine/JIT/JITEmitter.cpp | 5 +- .../lib/ExecutionEngine/MCJIT/CMakeLists.txt | 4 - .../lib/ExecutionEngine/MCJIT/Intercept.cpp | 1 + .../llvm/lib/ExecutionEngine/MCJIT/MCJIT.cpp | 7 +- .../llvm/lib/ExecutionEngine/MCJIT/Makefile | 13 - .../RuntimeDyld/CMakeLists.txt | 3 - .../lib/ExecutionEngine/RuntimeDyld/Makefile | 13 - .../RuntimeDyld/RuntimeDyldImpl.h | 2 +- .../llvm/lib/ExecutionEngine/TargetSelect.cpp | 13 +- contrib/llvm/lib/Linker/LinkModules.cpp | 112 +- contrib/llvm/lib/Linker/Linker.cpp | 8 + contrib/llvm/lib/MC/ELFObjectWriter.cpp | 124 +- contrib/llvm/lib/MC/ELFObjectWriter.h | 32 + ...{TargetAsmBackend.cpp => MCAsmBackend.cpp} | 10 +- contrib/llvm/lib/MC/MCAsmInfo.cpp | 12 +- contrib/llvm/lib/MC/MCAsmInfoCOFF.cpp | 7 +- contrib/llvm/lib/MC/MCAsmInfoDarwin.cpp | 8 + contrib/llvm/lib/MC/MCAsmStreamer.cpp | 57 +- contrib/llvm/lib/MC/MCAssembler.cpp | 6 +- contrib/llvm/lib/MC/MCAtom.cpp | 97 + contrib/llvm/lib/MC/MCCodeGenInfo.cpp | 21 + contrib/llvm/lib/MC/MCContext.cpp | 13 +- .../lib/MC/MCDisassembler/Disassembler.cpp | 82 +- .../llvm/lib/MC/MCDisassembler/Disassembler.h | 25 +- .../lib/MC/MCDisassembler/EDDisassembler.cpp | 70 +- .../lib/MC/MCDisassembler/EDDisassembler.h | 19 +- contrib/llvm/lib/MC/MCDisassembler/EDInst.h | 2 +- .../llvm/lib/MC/MCDisassembler/EDToken.cpp | 8 +- contrib/llvm/lib/MC/MCDisassembler/EDToken.h | 2 +- contrib/llvm/lib/MC/MCDwarf.cpp | 95 +- contrib/llvm/lib/MC/MCELF.cpp | 1 - contrib/llvm/lib/MC/MCELFStreamer.cpp | 17 +- contrib/llvm/lib/MC/MCELFStreamer.h | 7 +- contrib/llvm/lib/MC/MCExpr.cpp | 1 - contrib/llvm/lib/MC/MCInstPrinter.cpp | 11 + contrib/llvm/lib/MC/MCInstrAnalysis.cpp | 21 + contrib/llvm/lib/MC/MCLoggingStreamer.cpp | 5 +- contrib/llvm/lib/MC/MCMachOStreamer.cpp | 20 +- contrib/llvm/lib/MC/MCModule.cpp | 45 + contrib/llvm/lib/MC/MCNullStreamer.cpp | 4 +- contrib/llvm/lib/MC/MCObjectFileInfo.cpp | 554 ++ contrib/llvm/lib/MC/MCObjectStreamer.cpp | 6 +- contrib/llvm/lib/MC/MCParser/AsmLexer.cpp | 32 +- contrib/llvm/lib/MC/MCParser/AsmParser.cpp | 198 +- .../llvm/lib/MC/MCParser/COFFAsmParser.cpp | 47 +- contrib/llvm/lib/MC/MCParser/ELFAsmParser.cpp | 59 +- contrib/llvm/lib/MC/MCParser/MCAsmParser.cpp | 6 +- ...getAsmParser.cpp => MCTargetAsmParser.cpp} | 8 +- contrib/llvm/lib/MC/MCPureStreamer.cpp | 9 +- contrib/llvm/lib/MC/MCStreamer.cpp | 113 +- .../MCTargetAsmLexer.cpp} | 10 +- contrib/llvm/lib/MC/MCWin64EH.cpp | 34 +- contrib/llvm/lib/MC/MachObjectWriter.cpp | 25 +- contrib/llvm/lib/MC/WinCOFFObjectWriter.cpp | 2 +- contrib/llvm/lib/MC/WinCOFFStreamer.cpp | 22 +- contrib/llvm/lib/Object/Archive.cpp | 172 + contrib/llvm/lib/Object/Binary.cpp | 11 +- contrib/llvm/lib/Object/CMakeLists.txt | 6 - contrib/llvm/lib/Object/COFFObjectFile.cpp | 239 +- contrib/llvm/lib/Object/ELFObjectFile.cpp | 773 ++- contrib/llvm/lib/Object/MachOObject.cpp | 38 + contrib/llvm/lib/Object/MachOObjectFile.cpp | 316 +- contrib/llvm/lib/Object/Makefile | 14 - contrib/llvm/lib/Object/Object.cpp | 4 +- contrib/llvm/lib/Object/ObjectFile.cpp | 1 + contrib/llvm/lib/Support/APFloat.cpp | 31 +- contrib/llvm/lib/Support/APInt.cpp | 56 +- contrib/llvm/lib/Support/Atomic.cpp | 10 +- contrib/llvm/lib/Support/BlockFrequency.cpp | 126 + .../llvm/lib/Support/BranchProbability.cpp | 3 +- contrib/llvm/lib/Support/CommandLine.cpp | 68 +- contrib/llvm/lib/Support/ConstantRange.cpp | 25 +- .../llvm/lib/Support/CrashRecoveryContext.cpp | 68 +- contrib/llvm/lib/Support/DataExtractor.cpp | 175 + contrib/llvm/lib/Support/Disassembler.cpp | 2 +- contrib/llvm/lib/Support/Dwarf.cpp | 49 + contrib/llvm/lib/Support/DynamicLibrary.cpp | 99 +- contrib/llvm/lib/Support/FoldingSet.cpp | 6 +- contrib/llvm/lib/Support/Host.cpp | 4 +- contrib/llvm/lib/Support/IncludeFile.cpp | 2 +- contrib/llvm/lib/Support/Memory.cpp | 6 + contrib/llvm/lib/Support/MemoryBuffer.cpp | 8 +- contrib/llvm/lib/Support/MemoryObject.cpp | 7 +- contrib/llvm/lib/Support/Mutex.cpp | 2 +- contrib/llvm/lib/Support/Path.cpp | 2 +- contrib/llvm/lib/Support/PathV2.cpp | 36 +- contrib/llvm/lib/Support/PrettyStackTrace.cpp | 2 +- contrib/llvm/lib/Support/RWMutex.cpp | 2 +- .../SearchForAddressOfSpecialSymbol.cpp | 15 - contrib/llvm/lib/Support/StringExtras.cpp | 9 +- contrib/llvm/lib/Support/StringRef.cpp | 19 +- contrib/llvm/lib/Support/TargetRegistry.cpp | 32 +- contrib/llvm/lib/Support/ThreadLocal.cpp | 2 +- contrib/llvm/lib/Support/Threading.cpp | 41 +- contrib/llvm/lib/Support/Triple.cpp | 44 +- contrib/llvm/lib/Support/Twine.cpp | 60 +- contrib/llvm/lib/Support/Unix/Host.inc | 1 + contrib/llvm/lib/Support/Unix/Path.inc | 4 +- contrib/llvm/lib/Support/Unix/PathV2.inc | 22 +- contrib/llvm/lib/Support/Unix/Process.inc | 4 + .../lib/Support/Windows/DynamicLibrary.inc | 76 +- contrib/llvm/lib/Support/Windows/Memory.inc | 57 +- contrib/llvm/lib/Support/Windows/PathV2.inc | 51 +- contrib/llvm/lib/Support/Windows/Process.inc | 5 + contrib/llvm/lib/Support/Windows/RWMutex.inc | 98 +- contrib/llvm/lib/Support/Windows/Signals.inc | 224 +- contrib/llvm/lib/Support/Windows/Windows.h | 6 +- contrib/llvm/lib/Support/raw_ostream.cpp | 7 +- .../llvm/{utils => lib}/TableGen/Error.cpp | 2 +- contrib/llvm/lib/TableGen/Main.cpp | 124 + .../llvm/{utils => lib}/TableGen/Record.cpp | 782 ++- .../llvm/{utils => lib}/TableGen/TGLexer.cpp | 54 +- .../llvm/{utils => lib}/TableGen/TGLexer.h | 0 .../llvm/{utils => lib}/TableGen/TGParser.cpp | 314 +- .../llvm/{utils => lib}/TableGen/TGParser.h | 19 +- .../TableGen/TableGenBackend.cpp | 4 +- contrib/llvm/lib/Target/ARM/ARM.h | 21 +- contrib/llvm/lib/Target/ARM/ARM.td | 23 +- contrib/llvm/lib/Target/ARM/ARMAsmPrinter.cpp | 194 +- .../llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp | 522 +- .../llvm/lib/Target/ARM/ARMBaseInstrInfo.h | 161 +- .../lib/Target/ARM/ARMBaseRegisterInfo.cpp | 287 +- .../llvm/lib/Target/ARM/ARMBaseRegisterInfo.h | 19 +- .../llvm/lib/Target/ARM/ARMCodeEmitter.cpp | 35 +- .../lib/Target/ARM/ARMConstantIslandPass.cpp | 23 +- .../lib/Target/ARM/ARMConstantPoolValue.cpp | 317 +- .../lib/Target/ARM/ARMConstantPoolValue.h | 189 +- .../lib/Target/ARM/ARMExpandPseudoInsts.cpp | 61 +- contrib/llvm/lib/Target/ARM/ARMFastISel.cpp | 93 +- .../llvm/lib/Target/ARM/ARMFrameLowering.cpp | 31 +- .../llvm/lib/Target/ARM/ARMGlobalMerge.cpp | 10 +- .../llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp | 336 +- .../llvm/lib/Target/ARM/ARMISelLowering.cpp | 1295 ++++- contrib/llvm/lib/Target/ARM/ARMISelLowering.h | 47 +- .../llvm/lib/Target/ARM/ARMInstrFormats.td | 341 +- contrib/llvm/lib/Target/ARM/ARMInstrInfo.cpp | 26 +- contrib/llvm/lib/Target/ARM/ARMInstrInfo.td | 2752 ++++++---- contrib/llvm/lib/Target/ARM/ARMInstrNEON.td | 153 +- contrib/llvm/lib/Target/ARM/ARMInstrThumb.td | 489 +- contrib/llvm/lib/Target/ARM/ARMInstrThumb2.td | 1957 ++++--- contrib/llvm/lib/Target/ARM/ARMInstrVFP.td | 113 +- .../lib/Target/ARM/ARMLoadStoreOptimizer.cpp | 49 +- .../llvm/lib/Target/ARM/ARMMCInstLower.cpp | 2 +- .../llvm/lib/Target/ARM/ARMRegisterInfo.td | 24 +- .../lib/Target/ARM/ARMSelectionDAGInfo.cpp | 15 +- .../llvm/lib/Target/ARM/ARMSelectionDAGInfo.h | 17 + contrib/llvm/lib/Target/ARM/ARMSubtarget.cpp | 5 + contrib/llvm/lib/Target/ARM/ARMSubtarget.h | 18 + .../llvm/lib/Target/ARM/ARMTargetMachine.cpp | 91 +- .../llvm/lib/Target/ARM/ARMTargetMachine.h | 16 +- .../lib/Target/ARM/AsmParser/ARMAsmLexer.cpp | 37 +- .../lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 4071 +++++++++++---- .../ARM/Disassembler/ARMDisassembler.cpp | 4489 ++++++++++++++-- .../Target/ARM/Disassembler/ARMDisassembler.h | 99 - .../ARM/Disassembler/ARMDisassemblerCore.cpp | 3818 -------------- .../ARM/Disassembler/ARMDisassemblerCore.h | 336 -- .../ARM/Disassembler/ThumbDisassemblerCore.h | 2459 --------- .../Target/ARM/InstPrinter/ARMInstPrinter.cpp | 399 +- .../Target/ARM/InstPrinter/ARMInstPrinter.h | 34 +- .../lib/Target/ARM/InstPrinter/CMakeLists.txt | 6 - .../llvm/lib/Target/ARM/InstPrinter/Makefile | 15 - .../{ => MCTargetDesc}/ARMAddressingModes.h | 104 +- .../ARM/{ => MCTargetDesc}/ARMAsmBackend.cpp | 77 +- .../ARM/{ => MCTargetDesc}/ARMBaseInfo.h | 163 +- .../ARM/{ => MCTargetDesc}/ARMFixupKinds.h | 0 .../Target/ARM/MCTargetDesc/ARMMCAsmInfo.cpp | 11 +- .../{ => MCTargetDesc}/ARMMCCodeEmitter.cpp | 386 +- .../ARM/{ => MCTargetDesc}/ARMMCExpr.cpp | 0 .../Target/ARM/{ => MCTargetDesc}/ARMMCExpr.h | 0 .../ARM/MCTargetDesc/ARMMCTargetDesc.cpp | 179 +- .../Target/ARM/MCTargetDesc/ARMMCTargetDesc.h | 21 +- .../ARMMachObjectWriter.cpp | 5 +- .../Target/ARM/MCTargetDesc/CMakeLists.txt | 7 - contrib/llvm/lib/Target/ARM/NEONMoveFix.cpp | 149 - .../Target/ARM/TargetInfo/ARMTargetInfo.cpp | 2 +- .../lib/Target/ARM/Thumb1FrameLowering.cpp | 11 +- .../lib/Target/ARM/Thumb1RegisterInfo.cpp | 34 +- .../llvm/lib/Target/ARM/Thumb2ITBlockPass.cpp | 21 + .../llvm/lib/Target/ARM/Thumb2InstrInfo.cpp | 13 +- .../lib/Target/ARM/Thumb2SizeReduction.cpp | 21 +- .../llvm/lib/Target/Alpha/AlphaAsmPrinter.cpp | 2 +- .../lib/Target/Alpha/AlphaISelDAGToDAG.cpp | 7 +- .../lib/Target/Alpha/AlphaISelLowering.cpp | 8 +- .../llvm/lib/Target/Alpha/AlphaISelLowering.h | 2 +- .../llvm/lib/Target/Alpha/AlphaInstrInfo.cpp | 1 - .../llvm/lib/Target/Alpha/AlphaInstrInfo.td | 2 + .../lib/Target/Alpha/AlphaRegisterInfo.cpp | 18 +- .../llvm/lib/Target/Alpha/AlphaRegisterInfo.h | 4 - .../llvm/lib/Target/Alpha/AlphaSubtarget.cpp | 1 - .../lib/Target/Alpha/AlphaTargetMachine.cpp | 12 +- .../lib/Target/Alpha/AlphaTargetMachine.h | 5 +- .../Alpha/MCTargetDesc/AlphaMCTargetDesc.cpp | 35 +- .../Target/Alpha/MCTargetDesc/CMakeLists.txt | 4 - .../lib/Target/Alpha/MCTargetDesc/Makefile | 16 - .../Alpha/TargetInfo/AlphaTargetInfo.cpp | 2 +- .../Target/Blackfin/BlackfinAsmPrinter.cpp | 2 +- .../Target/Blackfin/BlackfinFrameLowering.h | 4 +- .../Target/Blackfin/BlackfinISelLowering.cpp | 4 +- .../Target/Blackfin/BlackfinISelLowering.h | 2 +- .../lib/Target/Blackfin/BlackfinInstrInfo.cpp | 2 +- .../Target/Blackfin/BlackfinIntrinsicInfo.cpp | 8 +- .../Target/Blackfin/BlackfinIntrinsicInfo.h | 4 +- .../Target/Blackfin/BlackfinRegisterInfo.cpp | 18 +- .../Target/Blackfin/BlackfinRegisterInfo.h | 4 - .../lib/Target/Blackfin/BlackfinSubtarget.cpp | 2 +- .../Target/Blackfin/BlackfinTargetMachine.cpp | 12 +- .../Target/Blackfin/BlackfinTargetMachine.h | 5 +- .../MCTargetDesc/BlackfinMCTargetDesc.cpp | 39 +- .../Blackfin/MCTargetDesc/CMakeLists.txt | 4 - .../lib/Target/Blackfin/MCTargetDesc/Makefile | 16 - .../TargetInfo/BlackfinTargetInfo.cpp | 2 +- contrib/llvm/lib/Target/CBackend/CBackend.cpp | 180 +- .../llvm/lib/Target/CBackend/CTargetMachine.h | 5 +- .../TargetInfo/CBackendTargetInfo.cpp | 4 +- .../CellSPU/MCTargetDesc/CMakeLists.txt | 4 - .../lib/Target/CellSPU/MCTargetDesc/Makefile | 16 - .../CellSPU/MCTargetDesc/SPUMCTargetDesc.cpp | 52 +- .../CellSPU/MCTargetDesc/SPUMCTargetDesc.h | 4 +- .../llvm/lib/Target/CellSPU/SPUAsmPrinter.cpp | 2 +- .../lib/Target/CellSPU/SPUFrameLowering.cpp | 20 - .../lib/Target/CellSPU/SPUFrameLowering.h | 14 - .../lib/Target/CellSPU/SPUISelLowering.cpp | 16 +- .../llvm/lib/Target/CellSPU/SPUISelLowering.h | 6 +- .../llvm/lib/Target/CellSPU/SPUInstrInfo.cpp | 4 +- .../llvm/lib/Target/CellSPU/SPUInstrInfo.td | 10 +- .../lib/Target/CellSPU/SPURegisterInfo.cpp | 19 +- .../llvm/lib/Target/CellSPU/SPURegisterInfo.h | 6 - .../llvm/lib/Target/CellSPU/SPUSubtarget.cpp | 2 +- .../lib/Target/CellSPU/SPUTargetMachine.cpp | 25 +- .../lib/Target/CellSPU/SPUTargetMachine.h | 5 +- .../CellSPU/TargetInfo/CellSPUTargetInfo.cpp | 2 +- .../llvm/lib/Target/CppBackend/CPPBackend.cpp | 141 +- .../lib/Target/CppBackend/CPPTargetMachine.h | 5 +- .../TargetInfo/CppBackendTargetInfo.cpp | 4 +- .../Target/MBlaze/AsmParser/CMakeLists.txt | 8 - .../MBlaze/AsmParser/MBlazeAsmLexer.cpp | 27 +- .../MBlaze/AsmParser/MBlazeAsmParser.cpp | 24 +- .../llvm/lib/Target/MBlaze/AsmParser/Makefile | 15 - .../Target/MBlaze/Disassembler/CMakeLists.txt | 16 - .../Disassembler/MBlazeDisassembler.cpp | 76 +- .../MBlaze/Disassembler/MBlazeDisassembler.h | 9 +- .../lib/Target/MBlaze/Disassembler/Makefile | 16 - .../Target/MBlaze/InstPrinter/CMakeLists.txt | 8 - .../MBlaze/InstPrinter/MBlazeInstPrinter.cpp | 4 +- .../MBlaze/InstPrinter/MBlazeInstPrinter.h | 2 +- .../lib/Target/MBlaze/InstPrinter/Makefile | 16 - contrib/llvm/lib/Target/MBlaze/MBlaze.h | 12 +- .../lib/Target/MBlaze/MBlazeAsmPrinter.cpp | 21 +- .../lib/Target/MBlaze/MBlazeFrameLowering.cpp | 2 +- .../lib/Target/MBlaze/MBlazeISelLowering.cpp | 13 +- .../lib/Target/MBlaze/MBlazeISelLowering.h | 2 +- .../lib/Target/MBlaze/MBlazeInstrInfo.cpp | 5 +- .../llvm/lib/Target/MBlaze/MBlazeInstrInfo.h | 56 - .../llvm/lib/Target/MBlaze/MBlazeInstrInfo.td | 21 +- .../lib/Target/MBlaze/MBlazeIntrinsicInfo.cpp | 8 +- .../lib/Target/MBlaze/MBlazeIntrinsicInfo.h | 4 +- .../lib/Target/MBlaze/MBlazeRegisterInfo.cpp | 172 +- .../lib/Target/MBlaze/MBlazeRegisterInfo.h | 12 - .../lib/Target/MBlaze/MBlazeSubtarget.cpp | 2 +- .../lib/Target/MBlaze/MBlazeTargetMachine.cpp | 50 +- .../lib/Target/MBlaze/MBlazeTargetMachine.h | 5 +- .../Target/MBlaze/MBlazeTargetObjectFile.cpp | 2 +- .../Target/MBlaze/MCTargetDesc/CMakeLists.txt | 4 - .../{ => MCTargetDesc}/MBlazeAsmBackend.cpp | 17 +- .../MBlaze/MCTargetDesc/MBlazeBaseInfo.h | 240 + .../MBlazeMCCodeEmitter.cpp | 8 +- .../MCTargetDesc/MBlazeMCTargetDesc.cpp | 93 +- .../MBlaze/MCTargetDesc/MBlazeMCTargetDesc.h | 11 + .../lib/Target/MBlaze/MCTargetDesc/Makefile | 16 - .../MBlaze/TargetInfo/MBlazeTargetInfo.cpp | 2 +- .../Target/MSP430/InstPrinter/CMakeLists.txt | 6 - .../MSP430/InstPrinter/MSP430InstPrinter.cpp | 4 +- .../MSP430/InstPrinter/MSP430InstPrinter.h | 4 +- .../lib/Target/MSP430/InstPrinter/Makefile | 15 - .../Target/MSP430/MCTargetDesc/CMakeLists.txt | 4 - .../MCTargetDesc/MSP430MCTargetDesc.cpp | 51 +- .../MSP430/MCTargetDesc/MSP430MCTargetDesc.h | 4 +- .../lib/Target/MSP430/MCTargetDesc/Makefile | 16 - .../lib/Target/MSP430/MSP430AsmPrinter.cpp | 14 +- .../lib/Target/MSP430/MSP430ISelLowering.cpp | 7 +- .../lib/Target/MSP430/MSP430ISelLowering.h | 4 +- .../lib/Target/MSP430/MSP430InstrInfo.cpp | 2 +- .../lib/Target/MSP430/MSP430RegisterInfo.cpp | 16 +- .../lib/Target/MSP430/MSP430RegisterInfo.h | 5 - .../lib/Target/MSP430/MSP430Subtarget.cpp | 2 +- .../lib/Target/MSP430/MSP430TargetMachine.cpp | 11 +- .../lib/Target/MSP430/MSP430TargetMachine.h | 5 +- .../MSP430/TargetInfo/MSP430TargetInfo.cpp | 2 +- contrib/llvm/lib/Target/Mangler.cpp | 4 +- .../Target/Mips/InstPrinter/CMakeLists.txt | 6 - .../llvm/lib/Target/Mips/InstPrinter/Makefile | 16 - .../Mips/InstPrinter/MipsInstPrinter.cpp | 6 +- .../Target/Mips/InstPrinter/MipsInstPrinter.h | 4 +- .../Target/Mips/MCTargetDesc/CMakeLists.txt | 4 - .../lib/Target/Mips/MCTargetDesc/Makefile | 16 - .../Mips/MCTargetDesc/MipsAsmBackend.cpp | 117 + .../Target/Mips/MCTargetDesc/MipsBaseInfo.h | 113 + .../Target/Mips/MCTargetDesc/MipsFixupKinds.h | 90 + .../Mips/MCTargetDesc/MipsMCAsmInfo.cpp | 3 +- .../Mips/MCTargetDesc/MipsMCCodeEmitter.cpp | 52 + .../Mips/MCTargetDesc/MipsMCTargetDesc.cpp | 122 +- .../Mips/MCTargetDesc/MipsMCTargetDesc.h | 21 +- contrib/llvm/lib/Target/Mips/Mips.h | 3 + contrib/llvm/lib/Target/Mips/Mips.td | 32 +- .../llvm/lib/Target/Mips/Mips64InstrInfo.td | 214 + .../llvm/lib/Target/Mips/MipsAsmPrinter.cpp | 42 +- .../llvm/lib/Target/Mips/MipsCallingConv.td | 55 +- .../llvm/lib/Target/Mips/MipsCodeEmitter.cpp | 245 + .../lib/Target/Mips/MipsDelaySlotFiller.cpp | 204 +- .../lib/Target/Mips/MipsFrameLowering.cpp | 19 +- .../llvm/lib/Target/Mips/MipsFrameLowering.h | 5 +- .../llvm/lib/Target/Mips/MipsISelDAGToDAG.cpp | 185 +- .../llvm/lib/Target/Mips/MipsISelLowering.cpp | 848 ++-- .../llvm/lib/Target/Mips/MipsISelLowering.h | 16 +- contrib/llvm/lib/Target/Mips/MipsInstrFPU.td | 236 +- .../llvm/lib/Target/Mips/MipsInstrFormats.td | 44 +- .../llvm/lib/Target/Mips/MipsInstrInfo.cpp | 210 +- contrib/llvm/lib/Target/Mips/MipsInstrInfo.h | 37 +- contrib/llvm/lib/Target/Mips/MipsInstrInfo.td | 832 +-- contrib/llvm/lib/Target/Mips/MipsJITInfo.cpp | 230 + contrib/llvm/lib/Target/Mips/MipsJITInfo.h | 70 + .../llvm/lib/Target/Mips/MipsMCInstLower.cpp | 64 +- .../llvm/lib/Target/Mips/MipsMCInstLower.h | 5 +- .../lib/Target/Mips/MipsMCSymbolRefExpr.cpp | 9 +- .../lib/Target/Mips/MipsMCSymbolRefExpr.h | 7 +- .../lib/Target/Mips/MipsMachineFunction.h | 9 +- .../llvm/lib/Target/Mips/MipsRegisterInfo.cpp | 205 +- .../llvm/lib/Target/Mips/MipsRegisterInfo.h | 4 - .../llvm/lib/Target/Mips/MipsRegisterInfo.td | 119 +- .../llvm/lib/Target/Mips/MipsRelocations.h | 41 + .../llvm/lib/Target/Mips/MipsSubtarget.cpp | 38 +- contrib/llvm/lib/Target/Mips/MipsSubtarget.h | 15 +- .../lib/Target/Mips/MipsTargetMachine.cpp | 73 +- .../llvm/lib/Target/Mips/MipsTargetMachine.h | 48 +- .../lib/Target/Mips/MipsTargetObjectFile.cpp | 2 +- .../Target/Mips/TargetInfo/MipsTargetInfo.cpp | 16 +- contrib/llvm/lib/Target/PTX/CMakeLists.txt | 26 - .../Target/PTX/InstPrinter/PTXInstPrinter.cpp | 192 + .../Target/PTX/InstPrinter/PTXInstPrinter.h | 47 + .../Target/PTX/MCTargetDesc/CMakeLists.txt | 4 - .../llvm/lib/Target/PTX/MCTargetDesc/Makefile | 16 - .../lib/Target/PTX/MCTargetDesc/PTXBaseInfo.h | 63 + .../PTX/MCTargetDesc/PTXMCTargetDesc.cpp | 53 +- contrib/llvm/lib/Target/PTX/PTX.h | 28 +- contrib/llvm/lib/Target/PTX/PTX.td | 28 +- contrib/llvm/lib/Target/PTX/PTXAsmPrinter.cpp | 500 +- contrib/llvm/lib/Target/PTX/PTXAsmPrinter.h | 57 + contrib/llvm/lib/Target/PTX/PTXCallingConv.td | 29 - .../lib/Target/PTX/PTXFPRoundingModePass.cpp | 179 + .../llvm/lib/Target/PTX/PTXISelDAGToDAG.cpp | 182 +- .../llvm/lib/Target/PTX/PTXISelLowering.cpp | 273 +- contrib/llvm/lib/Target/PTX/PTXISelLowering.h | 19 +- .../llvm/lib/Target/PTX/PTXInstrFormats.td | 31 +- contrib/llvm/lib/Target/PTX/PTXInstrInfo.cpp | 82 +- contrib/llvm/lib/Target/PTX/PTXInstrInfo.td | 1241 +++-- .../llvm/lib/Target/PTX/PTXInstrLoadStore.td | 278 + .../lib/Target/PTX/PTXIntrinsicInstrInfo.td | 78 +- .../llvm/lib/Target/PTX/PTXMCAsmStreamer.cpp | 15 +- .../llvm/lib/Target/PTX/PTXMCInstLower.cpp | 32 + .../llvm/lib/Target/PTX/PTXMFInfoExtract.cpp | 36 +- .../lib/Target/PTX/PTXMachineFunctionInfo.h | 163 +- .../llvm/lib/Target/PTX/PTXParamManager.cpp | 73 + contrib/llvm/lib/Target/PTX/PTXParamManager.h | 86 + contrib/llvm/lib/Target/PTX/PTXRegAlloc.cpp | 58 + .../llvm/lib/Target/PTX/PTXRegisterInfo.cpp | 29 +- contrib/llvm/lib/Target/PTX/PTXRegisterInfo.h | 18 +- .../llvm/lib/Target/PTX/PTXRegisterInfo.td | 540 +- .../lib/Target/PTX/PTXSelectionDAGInfo.cpp | 149 + .../llvm/lib/Target/PTX/PTXSelectionDAGInfo.h | 53 + contrib/llvm/lib/Target/PTX/PTXSubtarget.cpp | 2 +- contrib/llvm/lib/Target/PTX/PTXSubtarget.h | 11 +- .../llvm/lib/Target/PTX/PTXTargetMachine.cpp | 318 +- .../llvm/lib/Target/PTX/PTXTargetMachine.h | 60 +- .../lib/Target/PTX/TargetInfo/CMakeLists.txt | 7 - .../llvm/lib/Target/PTX/TargetInfo/Makefile | 15 - .../Target/PTX/TargetInfo/PTXTargetInfo.cpp | 2 +- .../lib/Target/PTX/generate-register-td.py | 163 - .../Target/PowerPC/InstPrinter/CMakeLists.txt | 6 - .../lib/Target/PowerPC/InstPrinter/Makefile | 16 - .../PowerPC/InstPrinter/PPCInstPrinter.cpp | 11 +- .../PowerPC/InstPrinter/PPCInstPrinter.h | 2 +- .../PowerPC/MCTargetDesc/CMakeLists.txt | 4 - .../lib/Target/PowerPC/MCTargetDesc/Makefile | 16 - .../{ => MCTargetDesc}/PPCAsmBackend.cpp | 88 +- .../Target/PowerPC/MCTargetDesc/PPCBaseInfo.h | 70 + .../{ => MCTargetDesc}/PPCFixupKinds.h | 0 .../PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp | 6 +- .../{ => MCTargetDesc}/PPCMCCodeEmitter.cpp | 9 +- .../PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp | 115 +- .../PowerPC/MCTargetDesc/PPCMCTargetDesc.h | 10 + .../{ => MCTargetDesc}/PPCPredicates.cpp | 0 .../{ => MCTargetDesc}/PPCPredicates.h | 2 - contrib/llvm/lib/Target/PowerPC/PPC.h | 11 +- contrib/llvm/lib/Target/PowerPC/PPC.td | 4 +- .../llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp | 14 +- .../lib/Target/PowerPC/PPCBranchSelector.cpp | 2 +- .../lib/Target/PowerPC/PPCCodeEmitter.cpp | 4 +- .../lib/Target/PowerPC/PPCFrameLowering.cpp | 17 +- .../lib/Target/PowerPC/PPCFrameLowering.h | 1 - .../lib/Target/PowerPC/PPCISelDAGToDAG.cpp | 2 +- .../lib/Target/PowerPC/PPCISelLowering.cpp | 65 +- .../llvm/lib/Target/PowerPC/PPCISelLowering.h | 17 +- .../llvm/lib/Target/PowerPC/PPCInstrInfo.cpp | 36 +- .../llvm/lib/Target/PowerPC/PPCInstrInfo.td | 6 + .../lib/Target/PowerPC/PPCRegisterInfo.cpp | 79 +- .../llvm/lib/Target/PowerPC/PPCRegisterInfo.h | 8 - .../llvm/lib/Target/PowerPC/PPCSubtarget.cpp | 2 +- .../lib/Target/PowerPC/PPCTargetMachine.cpp | 71 +- .../lib/Target/PowerPC/PPCTargetMachine.h | 16 +- .../PowerPC/TargetInfo/PowerPCTargetInfo.cpp | 2 +- .../Target/Sparc/MCTargetDesc/CMakeLists.txt | 4 - .../lib/Target/Sparc/MCTargetDesc/Makefile | 16 - .../Sparc/MCTargetDesc/SparcMCTargetDesc.cpp | 36 +- .../llvm/lib/Target/Sparc/SparcAsmPrinter.cpp | 2 +- .../lib/Target/Sparc/SparcISelLowering.cpp | 8 +- .../llvm/lib/Target/Sparc/SparcInstrInfo.cpp | 2 +- .../lib/Target/Sparc/SparcRegisterInfo.cpp | 15 +- .../llvm/lib/Target/Sparc/SparcRegisterInfo.h | 4 - .../llvm/lib/Target/Sparc/SparcSubtarget.cpp | 2 +- .../lib/Target/Sparc/SparcTargetMachine.cpp | 27 +- .../lib/Target/Sparc/SparcTargetMachine.h | 16 +- .../Sparc/TargetInfo/SparcTargetInfo.cpp | 2 +- .../SystemZ/MCTargetDesc/CMakeLists.txt | 7 - .../lib/Target/SystemZ/MCTargetDesc/Makefile | 16 - .../MCTargetDesc/SystemZMCTargetDesc.cpp | 39 +- .../lib/Target/SystemZ/SystemZAsmPrinter.cpp | 4 +- .../Target/SystemZ/SystemZISelLowering.cpp | 1 + .../lib/Target/SystemZ/SystemZInstrInfo.cpp | 2 +- .../lib/Target/SystemZ/SystemZInstrInfo.td | 2 +- .../Target/SystemZ/SystemZRegisterInfo.cpp | 17 +- .../lib/Target/SystemZ/SystemZRegisterInfo.h | 4 - .../lib/Target/SystemZ/SystemZSubtarget.cpp | 2 +- .../Target/SystemZ/SystemZTargetMachine.cpp | 13 +- .../lib/Target/SystemZ/SystemZTargetMachine.h | 5 +- .../SystemZ/TargetInfo/SystemZTargetInfo.cpp | 2 +- contrib/llvm/lib/Target/Target.cpp | 10 +- contrib/llvm/lib/Target/TargetAsmInfo.cpp | 23 - contrib/llvm/lib/Target/TargetData.cpp | 53 +- .../llvm/lib/Target/TargetFrameLowering.cpp | 8 - .../lib/Target/TargetLoweringObjectFile.cpp | 59 +- contrib/llvm/lib/Target/TargetMachine.cpp | 67 +- .../llvm/lib/Target/TargetRegisterInfo.cpp | 49 +- .../lib/Target/X86/AsmParser/X86AsmLexer.cpp | 20 +- .../lib/Target/X86/AsmParser/X86AsmParser.cpp | 84 +- .../X86/Disassembler/X86Disassembler.cpp | 77 +- .../Target/X86/Disassembler/X86Disassembler.h | 26 +- .../X86/Disassembler/X86DisassemblerDecoder.c | 165 +- .../X86DisassemblerDecoderCommon.h | 8 +- .../lib/Target/X86/InstPrinter/CMakeLists.txt | 8 - .../llvm/lib/Target/X86/InstPrinter/Makefile | 15 - .../X86/InstPrinter/X86ATTInstPrinter.cpp | 10 +- .../X86/InstPrinter/X86ATTInstPrinter.h | 2 +- .../X86/InstPrinter/X86InstComments.cpp | 31 +- .../X86/InstPrinter/X86IntelInstPrinter.cpp | 7 +- .../X86/InstPrinter/X86IntelInstPrinter.h | 2 +- .../Target/X86/MCTargetDesc/CMakeLists.txt | 7 - .../llvm/lib/Target/X86/MCTargetDesc/Makefile | 16 - .../X86/{ => MCTargetDesc}/X86AsmBackend.cpp | 29 +- .../lib/Target/X86/MCTargetDesc/X86BaseInfo.h | 548 ++ .../X86/{ => MCTargetDesc}/X86FixupKinds.h | 0 .../{ => MCTargetDesc}/X86MCCodeEmitter.cpp | 198 +- .../X86/MCTargetDesc/X86MCTargetDesc.cpp | 338 +- .../Target/X86/MCTargetDesc/X86MCTargetDesc.h | 45 +- .../X86MachObjectWriter.cpp | 6 +- .../Target/X86/TargetInfo/X86TargetInfo.cpp | 2 +- .../llvm/lib/Target/X86/Utils/CMakeLists.txt | 6 - contrib/llvm/lib/Target/X86/Utils/Makefile | 15 - .../lib/Target/X86/Utils/X86ShuffleDecode.cpp | 75 +- .../lib/Target/X86/Utils/X86ShuffleDecode.h | 20 + contrib/llvm/lib/Target/X86/X86.h | 30 +- contrib/llvm/lib/Target/X86/X86.td | 78 +- contrib/llvm/lib/Target/X86/X86AsmPrinter.cpp | 23 +- .../llvm/lib/Target/X86/X86CodeEmitter.cpp | 36 +- .../llvm/lib/Target/X86/X86ELFWriterInfo.cpp | 2 +- contrib/llvm/lib/Target/X86/X86FastISel.cpp | 93 +- .../llvm/lib/Target/X86/X86FloatingPoint.cpp | 34 + .../llvm/lib/Target/X86/X86FrameLowering.cpp | 625 ++- .../llvm/lib/Target/X86/X86FrameLowering.h | 7 +- .../llvm/lib/Target/X86/X86ISelDAGToDAG.cpp | 16 +- .../llvm/lib/Target/X86/X86ISelLowering.cpp | 2940 ++++++++--- contrib/llvm/lib/Target/X86/X86ISelLowering.h | 62 +- .../llvm/lib/Target/X86/X86InstrArithmetic.td | 96 +- .../llvm/lib/Target/X86/X86InstrCompiler.td | 102 +- .../llvm/lib/Target/X86/X86InstrExtension.td | 4 +- .../llvm/lib/Target/X86/X86InstrFormats.td | 8 +- .../lib/Target/X86/X86InstrFragmentsSIMD.td | 84 +- contrib/llvm/lib/Target/X86/X86InstrInfo.cpp | 1838 ++++--- contrib/llvm/lib/Target/X86/X86InstrInfo.h | 553 +- contrib/llvm/lib/Target/X86/X86InstrInfo.td | 209 +- contrib/llvm/lib/Target/X86/X86InstrSSE.td | 4174 +++++++++------ contrib/llvm/lib/Target/X86/X86InstrSystem.td | 114 +- contrib/llvm/lib/Target/X86/X86InstrVMX.td | 10 +- .../llvm/lib/Target/X86/X86MCInstLower.cpp | 23 +- .../lib/Target/X86/X86MachineFunctionInfo.h | 20 +- .../llvm/lib/Target/X86/X86RegisterInfo.cpp | 165 +- contrib/llvm/lib/Target/X86/X86RegisterInfo.h | 25 +- .../llvm/lib/Target/X86/X86RegisterInfo.td | 11 +- .../lib/Target/X86/X86SelectionDAGInfo.cpp | 2 +- contrib/llvm/lib/Target/X86/X86Subtarget.cpp | 78 +- contrib/llvm/lib/Target/X86/X86Subtarget.h | 36 +- .../llvm/lib/Target/X86/X86TargetMachine.cpp | 173 +- .../llvm/lib/Target/X86/X86TargetMachine.h | 22 +- .../lib/Target/X86/X86TargetObjectFile.cpp | 76 - .../llvm/lib/Target/X86/X86TargetObjectFile.h | 22 - contrib/llvm/lib/Target/X86/X86VZeroUpper.cpp | 105 + .../Target/XCore/MCTargetDesc/CMakeLists.txt | 7 - .../lib/Target/XCore/MCTargetDesc/Makefile | 16 - .../XCore/MCTargetDesc/XCoreMCTargetDesc.cpp | 48 +- .../XCore/TargetInfo/XCoreTargetInfo.cpp | 2 +- .../llvm/lib/Target/XCore/XCoreAsmPrinter.cpp | 60 +- .../lib/Target/XCore/XCoreFrameLowering.cpp | 11 +- .../lib/Target/XCore/XCoreFrameLowering.h | 2 - .../lib/Target/XCore/XCoreISelDAGToDAG.cpp | 11 +- .../lib/Target/XCore/XCoreISelLowering.cpp | 37 +- .../llvm/lib/Target/XCore/XCoreISelLowering.h | 5 +- .../llvm/lib/Target/XCore/XCoreInstrInfo.cpp | 12 +- .../llvm/lib/Target/XCore/XCoreInstrInfo.h | 5 + .../llvm/lib/Target/XCore/XCoreInstrInfo.td | 81 +- .../lib/Target/XCore/XCoreRegisterInfo.cpp | 15 +- .../llvm/lib/Target/XCore/XCoreRegisterInfo.h | 5 - .../llvm/lib/Target/XCore/XCoreSubtarget.cpp | 2 +- .../lib/Target/XCore/XCoreTargetMachine.cpp | 10 +- .../lib/Target/XCore/XCoreTargetMachine.h | 5 +- .../lib/Transforms/IPO/ArgumentPromotion.cpp | 43 +- .../llvm/lib/Transforms/IPO/ConstantMerge.cpp | 49 +- .../IPO/DeadArgumentElimination.cpp | 12 +- .../llvm/lib/Transforms/IPO/FunctionAttrs.cpp | 4 +- contrib/llvm/lib/Transforms/IPO/GlobalOpt.cpp | 125 +- .../Transforms/IPO/IPConstantPropagation.cpp | 2 +- contrib/llvm/lib/Transforms/IPO/IPO.cpp | 15 +- .../llvm/lib/Transforms/IPO/InlineAlways.cpp | 15 +- .../llvm/lib/Transforms/IPO/InlineSimple.cpp | 26 +- contrib/llvm/lib/Transforms/IPO/Inliner.cpp | 4 +- .../llvm/lib/Transforms/IPO/LoopExtractor.cpp | 73 +- .../llvm/lib/Transforms/IPO/LowerSetJmp.cpp | 547 -- .../lib/Transforms/IPO/MergeFunctions.cpp | 70 +- .../lib/Transforms/IPO/PassManagerBuilder.cpp | 343 ++ contrib/llvm/lib/Transforms/IPO/PruneEH.cpp | 5 +- .../llvm/lib/Transforms/IPO/StripSymbols.cpp | 2 +- .../lib/Transforms/InstCombine/InstCombine.h | 15 +- .../InstCombine/InstCombineAddSub.cpp | 8 +- .../InstCombine/InstCombineAndOrXor.cpp | 53 +- .../InstCombine/InstCombineCalls.cpp | 192 +- .../InstCombine/InstCombineCasts.cpp | 112 +- .../InstCombine/InstCombineCompares.cpp | 495 +- .../InstCombineLoadStoreAlloca.cpp | 99 +- .../InstCombine/InstCombineMulDivRem.cpp | 13 +- .../Transforms/InstCombine/InstCombinePHI.cpp | 20 +- .../InstCombine/InstCombineSelect.cpp | 20 +- .../InstCombine/InstCombineShifts.cpp | 49 +- .../InstCombineSimplifyDemanded.cpp | 24 +- .../InstCombine/InstCombineVectorOps.cpp | 8 +- .../InstCombine/InstructionCombining.cpp | 630 ++- .../Instrumentation/EdgeProfiling.cpp | 2 +- .../Instrumentation/GCOVProfiling.cpp | 372 +- .../Instrumentation/OptimalEdgeProfiling.cpp | 4 +- .../Instrumentation/PathProfiling.cpp | 29 +- .../Instrumentation/ProfilingUtils.cpp | 13 +- contrib/llvm/lib/Transforms/Scalar/ADCE.cpp | 2 +- .../lib/Transforms/Scalar/CodeGenPrepare.cpp | 108 +- .../Scalar/DeadStoreElimination.cpp | 182 +- .../llvm/lib/Transforms/Scalar/EarlyCSE.cpp | 8 +- contrib/llvm/lib/Transforms/Scalar/GVN.cpp | 274 +- .../lib/Transforms/Scalar/IndVarSimplify.cpp | 1142 +++-- .../lib/Transforms/Scalar/JumpThreading.cpp | 4 +- contrib/llvm/lib/Transforms/Scalar/LICM.cpp | 64 +- .../Transforms/Scalar/LoopIdiomRecognize.cpp | 10 +- .../Transforms/Scalar/LoopStrengthReduce.cpp | 215 +- .../lib/Transforms/Scalar/LoopUnrollPass.cpp | 61 +- .../lib/Transforms/Scalar/LoopUnswitch.cpp | 28 +- .../lib/Transforms/Scalar/LowerAtomic.cpp | 173 +- .../lib/Transforms/Scalar/MemCpyOptimizer.cpp | 14 +- .../llvm/lib/Transforms/Scalar/ObjCARC.cpp | 440 +- .../lib/Transforms/Scalar/Reassociate.cpp | 2 +- contrib/llvm/lib/Transforms/Scalar/SCCP.cpp | 250 +- contrib/llvm/lib/Transforms/Scalar/Scalar.cpp | 5 +- .../Scalar/ScalarReplAggregates.cpp | 598 +-- .../Transforms/Scalar/SimplifyLibCalls.cpp | 111 +- contrib/llvm/lib/Transforms/Scalar/Sink.cpp | 13 +- .../lib/Transforms/Scalar/TailDuplication.cpp | 373 -- .../lib/Transforms/Utils/AddrModeMatcher.cpp | 4 +- .../lib/Transforms/Utils/BasicBlockUtils.cpp | 346 +- .../Transforms/Utils/BreakCriticalEdges.cpp | 56 +- .../lib/Transforms/Utils/BuildLibCalls.cpp | 10 +- .../lib/Transforms/Utils/CloneFunction.cpp | 13 +- .../llvm/lib/Transforms/Utils/CloneModule.cpp | 27 +- .../lib/Transforms/Utils/CodeExtractor.cpp | 45 +- .../lib/Transforms/Utils/InlineFunction.cpp | 178 +- contrib/llvm/lib/Transforms/Utils/Local.cpp | 25 +- .../lib/Transforms/Utils/LoopSimplify.cpp | 47 +- .../llvm/lib/Transforms/Utils/LoopUnroll.cpp | 186 +- .../Transforms/Utils/LowerExpectIntrinsic.cpp | 4 +- .../llvm/lib/Transforms/Utils/LowerInvoke.cpp | 37 +- .../llvm/lib/Transforms/Utils/LowerSwitch.cpp | 4 +- .../Utils/PromoteMemoryToRegister.cpp | 4 + .../llvm/lib/Transforms/Utils/SSAUpdater.cpp | 8 +- .../llvm/lib/Transforms/Utils/SimplifyCFG.cpp | 155 +- .../lib/Transforms/Utils/SimplifyIndVar.cpp | 432 ++ .../llvm/lib/Transforms/Utils/ValueMapper.cpp | 5 +- contrib/llvm/lib/VMCore/AsmWriter.cpp | 252 +- contrib/llvm/lib/VMCore/Attributes.cpp | 6 +- contrib/llvm/lib/VMCore/AutoUpgrade.cpp | 395 +- contrib/llvm/lib/VMCore/BasicBlock.cpp | 34 +- contrib/llvm/lib/VMCore/ConstantFold.cpp | 209 +- contrib/llvm/lib/VMCore/ConstantFold.h | 6 +- contrib/llvm/lib/VMCore/Constants.cpp | 265 +- contrib/llvm/lib/VMCore/ConstantsContext.h | 32 +- contrib/llvm/lib/VMCore/Core.cpp | 183 +- contrib/llvm/lib/VMCore/DebugLoc.cpp | 4 +- contrib/llvm/lib/VMCore/Function.cpp | 43 +- contrib/llvm/lib/VMCore/GCOV.cpp | 281 + contrib/llvm/lib/VMCore/Globals.cpp | 8 +- contrib/llvm/lib/VMCore/IRBuilder.cpp | 2 +- contrib/llvm/lib/VMCore/InlineAsm.cpp | 8 +- contrib/llvm/lib/VMCore/Instruction.cpp | 68 +- contrib/llvm/lib/VMCore/Instructions.cpp | 674 ++- contrib/llvm/lib/VMCore/LLVMContextImpl.h | 4 +- contrib/llvm/lib/VMCore/Module.cpp | 48 +- contrib/llvm/lib/VMCore/PassManager.cpp | 59 +- contrib/llvm/lib/VMCore/PassRegistry.cpp | 1 + contrib/llvm/lib/VMCore/Type.cpp | 95 +- contrib/llvm/lib/VMCore/Value.cpp | 8 +- contrib/llvm/lib/VMCore/ValueTypes.cpp | 16 +- contrib/llvm/lib/VMCore/Verifier.cpp | 284 +- .../llvm/tools/clang/include/clang-c/Index.h | 651 ++- .../clang/include/clang/ARCMigrate/ARCMT.h | 46 +- .../include/clang/ARCMigrate/ARCMTActions.h | 6 +- .../include/clang/ARCMigrate/FileRemapper.h | 23 +- .../tools/clang/include/clang/AST/APValue.h | 10 +- .../clang/include/clang/AST/ASTContext.h | 311 +- .../clang/include/clang/AST/ASTDiagnostic.h | 16 +- .../clang/include/clang/AST/ASTImporter.h | 4 +- .../include/clang/AST/ASTMutationListener.h | 6 + .../llvm/tools/clang/include/clang/AST/Attr.h | 46 +- .../clang/include/clang/AST/BaseSubobject.h | 87 + .../clang/include/clang/AST/CXXInheritance.h | 14 +- .../tools/clang/include/clang/AST/CharUnits.h | 6 + .../llvm/tools/clang/include/clang/AST/Decl.h | 183 +- .../tools/clang/include/clang/AST/DeclBase.h | 110 +- .../tools/clang/include/clang/AST/DeclCXX.h | 113 +- .../include/clang/AST/DeclContextInternals.h | 2 +- .../tools/clang/include/clang/AST/DeclObjC.h | 305 +- .../clang/include/clang/AST/DeclTemplate.h | 67 +- .../clang/include/clang/AST/DeclVisitor.h | 2 +- .../clang/include/clang/AST/DeclarationName.h | 10 +- .../llvm/tools/clang/include/clang/AST/Expr.h | 336 +- .../tools/clang/include/clang/AST/ExprCXX.h | 79 +- .../tools/clang/include/clang/AST/ExprObjC.h | 136 +- .../include/clang/AST/ExternalASTSource.h | 199 +- .../tools/clang/include/clang/AST/Mangle.h | 58 +- .../include/clang/AST/NestedNameSpecifier.h | 8 +- .../clang/include/clang/AST/OperationKinds.h | 52 +- .../tools/clang/include/clang/AST/ParentMap.h | 1 + .../clang/include/clang/AST/PrettyPrinter.h | 16 +- .../clang/include/clang/AST/RecordLayout.h | 10 +- .../include/clang/AST/RecursiveASTVisitor.h | 25 +- .../include/clang/AST/SelectorLocationsKind.h | 83 + .../llvm/tools/clang/include/clang/AST/Stmt.h | 62 +- .../clang/include/clang/AST/StmtVisitor.h | 6 +- .../clang/include/clang/AST/TemplateBase.h | 51 +- .../clang/include/clang/AST/TemplateName.h | 7 +- .../llvm/tools/clang/include/clang/AST/Type.h | 104 +- .../tools/clang/include/clang/AST/TypeLoc.h | 68 + .../clang/include/clang/AST/TypeNodes.def | 3 +- .../clang/include/clang/AST/TypeVisitor.h | 2 +- .../clang/include/clang/AST/UnresolvedSet.h | 4 +- .../clang/include/clang/AST/VTTBuilder.h | 176 + .../clang/include/clang/AST/VTableBuilder.h | 357 ++ .../clang/Analysis/Analyses/FormatString.h | 8 +- .../clang/Analysis/Analyses/LiveVariables.h | 175 +- .../clang/Analysis/Analyses/ReachableCode.h | 2 +- .../clang/Analysis/Analyses/ThreadSafety.h | 153 + .../Analysis/Analyses/UninitializedValues.h | 8 +- .../include/clang/Analysis/AnalysisContext.h | 97 +- .../clang/Analysis/AnalysisDiagnostic.h | 2 +- .../tools/clang/include/clang/Analysis/CFG.h | 154 +- .../DomainSpecific/CocoaConventions.h | 11 +- .../Analysis/FlowSensitive/DataflowSolver.h | 62 +- .../Analysis/FlowSensitive/DataflowValues.h | 12 +- .../include/clang/Analysis/ProgramPoint.h | 163 +- .../Analysis/Support/BlkExprDeclBitVector.h | 24 +- .../Analysis/Visitors/CFGRecStmtDeclVisitor.h | 18 +- .../Analysis/Visitors/CFGRecStmtVisitor.h | 6 +- .../clang/Analysis/Visitors/CFGStmtVisitor.h | 22 +- .../tools/clang/include/clang/Basic/Attr.td | 149 +- .../clang/include/clang/Basic/Builtins.def | 62 +- .../clang/include/clang/Basic/Builtins.h | 17 +- .../clang/include/clang/Basic/DeclNodes.td | 1 + .../include/clang/Basic/DelayedCleanupPool.h | 5 +- .../clang/include/clang/Basic/Diagnostic.h | 296 +- .../clang/include/clang/Basic/Diagnostic.td | 10 +- .../include/clang/Basic/DiagnosticASTKinds.td | 4 + .../clang/Basic/DiagnosticCommonKinds.td | 15 +- .../clang/Basic/DiagnosticDriverKinds.td | 6 + .../clang/Basic/DiagnosticFrontendKinds.td | 157 +- .../include/clang/Basic/DiagnosticGroups.td | 54 +- .../clang/include/clang/Basic/DiagnosticIDs.h | 137 +- .../include/clang/Basic/DiagnosticLexKinds.td | 69 +- .../clang/Basic/DiagnosticParseKinds.td | 90 +- .../clang/Basic/DiagnosticSemaKinds.td | 783 ++- .../clang/include/clang/Basic/FileManager.h | 33 +- .../include/clang/Basic/IdentifierTable.h | 46 +- .../tools/clang/include/clang/Basic/LLVM.h | 53 + .../clang/include/clang/Basic/LangOptions.def | 159 + .../clang/include/clang/Basic/LangOptions.h | 278 +- .../clang/include/clang/Basic/MacroBuilder.h | 10 +- .../include/clang/Basic/OnDiskHashTable.h | 18 +- .../include/clang/Basic/OpenCLExtensions.def | 4 + .../include/clang/Basic/PartialDiagnostic.h | 31 +- .../include/clang/Basic/PrettyStackTrace.h | 2 +- .../include/clang/Basic/SourceLocation.h | 70 +- .../clang/include/clang/Basic/SourceManager.h | 780 ++- .../clang/Basic/SourceManagerInternals.h | 14 +- .../clang/include/clang/Basic/Specifiers.h | 3 + .../clang/include/clang/Basic/StmtNodes.td | 3 + .../clang/include/clang/Basic/TargetInfo.h | 74 +- .../clang/include/clang/Basic/TokenKinds.def | 28 +- .../clang/include/clang/Basic/VersionTuple.h | 7 +- .../clang/include/clang/CodeGen/BackendUtil.h | 9 +- .../include/clang/CodeGen/CodeGenAction.h | 2 +- .../include/clang/CodeGen/ModuleBuilder.h | 4 +- .../clang/include/clang/Config/config.h.cmake | 17 - .../tools/clang/include/clang/Driver/Action.h | 22 +- .../tools/clang/include/clang/Driver/Arg.h | 6 +- .../clang/include/clang/Driver/ArgList.h | 62 +- .../clang/include/clang/Driver/CC1Options.td | 71 +- .../clang/include/clang/Driver/Compilation.h | 16 +- .../tools/clang/include/clang/Driver/Driver.h | 67 +- .../include/clang/Driver/DriverDiagnostic.h | 2 +- .../tools/clang/include/clang/Driver/Job.h | 13 +- .../clang/include/clang/Driver/OptTable.h | 8 +- .../tools/clang/include/clang/Driver/Option.h | 13 +- .../clang/include/clang/Driver/Options.td | 27 +- .../tools/clang/include/clang/Driver/Tool.h | 6 +- .../clang/include/clang/Driver/ToolChain.h | 27 +- .../clang/include/clang/Driver/Types.def | 3 + .../tools/clang/include/clang/Driver/Util.h | 8 +- .../include/clang/Frontend/ASTConsumers.h | 9 +- .../clang/include/clang/Frontend/ASTUnit.h | 292 +- .../clang/include/clang/Frontend/Analyses.def | 20 +- .../include/clang/Frontend/AnalyzerOptions.h | 15 +- ...icClient.h => ChainedDiagnosticConsumer.h} | 30 +- .../include/clang/Frontend/CodeGenOptions.h | 3 + .../clang/Frontend/CommandLineSourceLoc.h | 7 +- .../include/clang/Frontend/CompilerInstance.h | 116 +- .../clang/Frontend/CompilerInvocation.h | 12 +- .../clang/Frontend/DiagnosticOptions.h | 4 +- .../include/clang/Frontend/FrontendAction.h | 31 +- .../include/clang/Frontend/FrontendActions.h | 38 +- .../clang/Frontend/FrontendDiagnostic.h | 2 +- .../include/clang/Frontend/FrontendOptions.h | 15 +- .../clang/Frontend/HeaderSearchOptions.h | 40 +- .../include/clang/Frontend/LangStandard.h | 3 +- .../include/clang/Frontend/LangStandards.def | 18 +- .../clang/Frontend/LogDiagnosticPrinter.h | 18 +- .../clang/Frontend/PreprocessorOptions.h | 36 +- .../clang/Frontend/TextDiagnosticBuffer.h | 10 +- .../clang/Frontend/TextDiagnosticPrinter.h | 29 +- .../clang/include/clang/Frontend/Utils.h | 16 +- ...icsClient.h => VerifyDiagnosticConsumer.h} | 33 +- .../clang/include/clang/Index/ASTLocation.h | 6 +- .../clang/include/clang/Index/CallGraph.h | 2 +- .../tools/clang/include/clang/Index/Entity.h | 3 +- .../clang/include/clang/Index/Handlers.h | 3 +- .../include/clang/Index/TranslationUnit.h | 4 +- .../include/clang/Lex/CodeCompletionHandler.h | 4 + .../clang/include/clang/Lex/DirectoryLookup.h | 47 +- .../tools/clang/include/clang/Lex/HeaderMap.h | 6 +- .../clang/include/clang/Lex/HeaderSearch.h | 84 +- .../clang/include/clang/Lex/LexDiagnostic.h | 2 +- .../tools/clang/include/clang/Lex/Lexer.h | 53 +- .../clang/include/clang/Lex/LiteralSupport.h | 43 +- .../tools/clang/include/clang/Lex/MacroInfo.h | 33 +- .../clang/include/clang/Lex/ModuleLoader.h | 55 + .../clang/include/clang/Lex/PPCallbacks.h | 74 +- .../clang/include/clang/Lex/PTHManager.h | 6 +- .../tools/clang/include/clang/Lex/Pragma.h | 9 +- .../include/clang/Lex/PreprocessingRecord.h | 377 +- .../clang/include/clang/Lex/Preprocessor.h | 220 +- .../include/clang/Lex/PreprocessorLexer.h | 18 +- .../tools/clang/include/clang/Lex/Token.h | 5 +- .../include/clang/Lex/TokenConcatenation.h | 9 +- .../clang/include/clang/Lex/TokenLexer.h | 16 +- .../clang/include/clang/Parse/ParseAST.h | 8 +- .../include/clang/Parse/ParseDiagnostic.h | 2 +- .../tools/clang/include/clang/Parse/Parser.h | 346 +- .../include/clang/Rewrite/ASTConsumers.h | 12 +- .../include/clang/Rewrite/FixItRewriter.h | 22 +- .../include/clang/Rewrite/FrontendActions.h | 8 +- .../clang/include/clang/Rewrite/Rewriter.h | 28 +- .../clang/include/clang/Rewrite/Rewriters.h | 7 +- .../clang/Sema/AnalysisBasedWarnings.h | 1 + .../clang/include/clang/Sema/AttributeList.h | 67 +- .../include/clang/Sema/CXXFieldCollector.h | 4 +- .../include/clang/Sema/CodeCompleteConsumer.h | 80 +- .../tools/clang/include/clang/Sema/DeclSpec.h | 110 +- .../include/clang/Sema/DelayedDiagnostic.h | 6 +- .../clang/include/clang/Sema/Designator.h | 2 +- .../include/clang/Sema/ExternalSemaSource.h | 120 +- .../include/clang/Sema/IdentifierResolver.h | 2 +- .../clang/include/clang/Sema/Initialization.h | 58 +- .../tools/clang/include/clang/Sema/Lookup.h | 36 +- .../include/clang/Sema/MultiInitializer.h | 72 + .../tools/clang/include/clang/Sema/Overload.h | 44 +- .../clang/include/clang/Sema/Ownership.h | 3 +- .../clang/include/clang/Sema/ParsedTemplate.h | 2 +- .../include/clang/Sema/PrettyDeclStackTrace.h | 2 +- .../tools/clang/include/clang/Sema/Scope.h | 4 +- .../clang/include/clang/Sema/ScopeInfo.h | 12 +- .../tools/clang/include/clang/Sema/Sema.h | 844 +-- .../clang/include/clang/Sema/SemaDiagnostic.h | 2 +- .../clang/include/clang/Sema/SemaFixItUtils.h | 91 + .../tools/clang/include/clang/Sema/Template.h | 19 +- .../include/clang/Sema/TemplateDeduction.h | 4 +- .../clang/include/clang/Sema/TypoCorrection.h | 73 +- .../tools/clang/include/clang/Sema/Weak.h | 46 + .../include/clang/Serialization/ASTBitCodes.h | 199 +- .../ASTDeserializationListener.h | 2 +- .../include/clang/Serialization/ASTReader.h | 828 ++- .../Serialization/ASTSerializationListener.h | 44 - .../include/clang/Serialization/ASTWriter.h | 136 +- .../Serialization/ChainedIncludesSource.h | 3 +- .../clang/Serialization/ContinuousRangeMap.h | 120 + .../include/clang/Serialization/Module.h | 319 ++ .../clang/Serialization/ModuleManager.h | 156 + .../StaticAnalyzer/Checkers/ClangCheckers.h | 22 + .../StaticAnalyzer/Checkers/LocalCheckers.h | 22 +- .../Core/BugReporter/BugReporter.h | 360 +- .../Core/BugReporter/BugReporterVisitor.h | 183 + .../StaticAnalyzer/Core/BugReporter/BugType.h | 10 +- .../Core/BugReporter/PathDiagnostic.h | 231 +- .../clang/StaticAnalyzer/Core/Checker.h | 81 +- .../StaticAnalyzer/Core/CheckerManager.h | 117 +- .../StaticAnalyzer/Core/CheckerOptInfo.h | 43 + .../StaticAnalyzer/Core/CheckerProvider.h | 58 - .../StaticAnalyzer/Core/CheckerRegistry.h | 132 + ...ticClients.h => PathDiagnosticConsumers.h} | 18 +- .../Core/PathSensitive/AnalysisManager.h | 43 +- .../Core/PathSensitive/BasicValueFactory.h | 22 +- .../Core/PathSensitive/BlockCounter.h | 9 +- .../Core/PathSensitive/CheckerContext.h | 118 +- .../Core/PathSensitive/ConstraintManager.h | 40 +- .../Core/PathSensitive/CoreEngine.h | 246 +- .../Core/PathSensitive/Environment.h | 8 +- .../Core/PathSensitive/ExplodedGraph.h | 49 +- .../Core/PathSensitive/ExprEngine.h | 215 +- .../Core/PathSensitive/ExprEngineBuilders.h | 18 +- .../Core/PathSensitive/MemRegion.h | 164 +- .../Core/PathSensitive/ObjCMessage.h | 184 +- .../{GRState.h => ProgramState.h} | 433 +- .../{GRStateTrait.h => ProgramStateTrait.h} | 57 +- .../Core/PathSensitive/SValBuilder.h | 37 +- .../StaticAnalyzer/Core/PathSensitive/SVals.h | 50 +- .../StaticAnalyzer/Core/PathSensitive/Store.h | 57 +- .../Core/PathSensitive/StoreRef.h | 3 +- .../Core/PathSensitive/SubEngine.h | 36 +- .../Core/PathSensitive/SymbolManager.h | 238 +- .../Core/PathSensitive/TransferFuncs.h | 93 - .../Core/PathSensitive/WorkList.h | 10 +- .../Frontend/CheckerRegistration.h | 14 +- .../StaticAnalyzer/Frontend/FrontendActions.h | 4 +- .../llvm/tools/clang/lib/ARCMigrate/ARCMT.cpp | 154 +- .../clang/lib/ARCMigrate/ARCMTActions.cpp | 18 +- .../tools/clang/lib/ARCMigrate/CMakeLists.txt | 24 - .../clang/lib/ARCMigrate/FileRemapper.cpp | 82 +- .../tools/clang/lib/ARCMigrate/Internals.h | 47 +- .../llvm/tools/clang/lib/ARCMigrate/Makefile | 18 - .../clang/lib/ARCMigrate/PlistReporter.cpp | 195 + .../clang/lib/ARCMigrate/TransAPIUses.cpp | 109 + .../clang/lib/ARCMigrate/TransARCAssign.cpp | 1 - .../lib/ARCMigrate/TransAutoreleasePool.cpp | 24 +- .../lib/ARCMigrate/TransBlockObjCVariable.cpp | 5 +- .../TransEmptyStatementsAndDealloc.cpp | 86 +- .../clang/lib/ARCMigrate/TransProperties.cpp | 105 +- .../ARCMigrate/TransRetainReleaseDealloc.cpp | 8 +- .../lib/ARCMigrate/TransUnbridgedCasts.cpp | 127 +- .../ARCMigrate/TransUnusedInitDelegate.cpp | 1 - .../ARCMigrate/TransZeroOutPropsInDealloc.cpp | 1 - .../clang/lib/ARCMigrate/TransformActions.cpp | 81 +- .../tools/clang/lib/ARCMigrate/Transforms.cpp | 30 +- .../tools/clang/lib/ARCMigrate/Transforms.h | 13 +- contrib/llvm/tools/clang/lib/AST/APValue.cpp | 50 +- .../llvm/tools/clang/lib/AST/ASTContext.cpp | 705 +-- .../tools/clang/lib/AST/ASTDiagnostic.cpp | 46 +- .../llvm/tools/clang/lib/AST/ASTImporter.cpp | 612 ++- .../tools/clang/lib/AST/CXXInheritance.cpp | 12 +- contrib/llvm/tools/clang/lib/AST/Decl.cpp | 172 +- contrib/llvm/tools/clang/lib/AST/DeclBase.cpp | 141 +- contrib/llvm/tools/clang/lib/AST/DeclCXX.cpp | 97 +- contrib/llvm/tools/clang/lib/AST/DeclObjC.cpp | 179 +- .../llvm/tools/clang/lib/AST/DeclPrinter.cpp | 277 +- .../llvm/tools/clang/lib/AST/DeclTemplate.cpp | 52 +- .../tools/clang/lib/AST/DeclarationName.cpp | 25 +- contrib/llvm/tools/clang/lib/AST/DumpXML.cpp | 39 +- contrib/llvm/tools/clang/lib/AST/Expr.cpp | 423 +- contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp | 38 +- .../clang/lib/AST/ExprClassification.cpp | 3 +- .../llvm/tools/clang/lib/AST/ExprConstant.cpp | 180 +- .../tools/clang/lib/AST/ExternalASTSource.cpp | 4 +- .../llvm/tools/clang/lib/AST/InheritViz.cpp | 8 +- .../tools/clang/lib/AST/ItaniumCXXABI.cpp | 2 +- .../tools/clang/lib/AST/ItaniumMangle.cpp | 116 +- contrib/llvm/tools/clang/lib/AST/Mangle.cpp | 16 +- .../tools/clang/lib/AST/MicrosoftCXXABI.cpp | 4 +- .../tools/clang/lib/AST/MicrosoftMangle.cpp | 149 +- .../clang/lib/AST/NestedNameSpecifier.cpp | 4 +- .../llvm/tools/clang/lib/AST/ParentMap.cpp | 8 + .../llvm/tools/clang/lib/AST/RecordLayout.cpp | 12 +- .../clang/lib/AST/RecordLayoutBuilder.cpp | 419 +- .../clang/lib/AST/SelectorLocationsKind.cpp | 128 + contrib/llvm/tools/clang/lib/AST/Stmt.cpp | 30 +- .../llvm/tools/clang/lib/AST/StmtDumper.cpp | 36 +- .../llvm/tools/clang/lib/AST/StmtPrinter.cpp | 102 +- .../llvm/tools/clang/lib/AST/StmtProfile.cpp | 9 +- .../llvm/tools/clang/lib/AST/TemplateBase.cpp | 72 +- .../llvm/tools/clang/lib/AST/TemplateName.cpp | 6 +- contrib/llvm/tools/clang/lib/AST/Type.cpp | 116 +- contrib/llvm/tools/clang/lib/AST/TypeLoc.cpp | 3 +- .../llvm/tools/clang/lib/AST/TypePrinter.cpp | 15 +- .../llvm/tools/clang/lib/AST/VTTBuilder.cpp | 212 + .../tools/clang/lib/AST/VTableBuilder.cpp | 2404 +++++++++ .../clang/lib/Analysis/AnalysisContext.cpp | 93 +- contrib/llvm/tools/clang/lib/Analysis/CFG.cpp | 488 +- .../lib/Analysis/CFGReachabilityAnalysis.cpp | 2 +- .../tools/clang/lib/Analysis/CFGStmtMap.cpp | 2 +- .../clang/lib/Analysis/CocoaConventions.cpp | 33 +- .../tools/clang/lib/Analysis/FormatString.cpp | 8 +- .../clang/lib/Analysis/LiveVariables.cpp | 874 ++-- .../clang/lib/Analysis/PrintfFormatString.cpp | 11 +- .../tools/clang/lib/Analysis/ProgramPoint.cpp | 51 + .../lib/Analysis/PseudoConstantAnalysis.cpp | 2 +- .../clang/lib/Analysis/ReachableCode.cpp | 377 +- .../tools/clang/lib/Analysis/ThreadSafety.cpp | 799 +++ .../lib/Analysis/UninitializedValues.cpp | 326 +- .../llvm/tools/clang/lib/Basic/Builtins.cpp | 10 +- .../llvm/tools/clang/lib/Basic/Diagnostic.cpp | 239 +- .../tools/clang/lib/Basic/DiagnosticIDs.cpp | 397 +- .../tools/clang/lib/Basic/FileManager.cpp | 50 +- .../tools/clang/lib/Basic/IdentifierTable.cpp | 47 +- .../tools/clang/lib/Basic/LangOptions.cpp | 30 + .../tools/clang/lib/Basic/SourceLocation.cpp | 22 +- .../tools/clang/lib/Basic/SourceManager.cpp | 797 +-- .../llvm/tools/clang/lib/Basic/TargetInfo.cpp | 29 +- .../llvm/tools/clang/lib/Basic/Targets.cpp | 1102 +++- .../llvm/tools/clang/lib/Basic/Version.cpp | 9 +- .../tools/clang/lib/Basic/VersionTuple.cpp | 2 +- .../tools/clang/lib/CodeGen/BackendUtil.cpp | 52 +- .../llvm/tools/clang/lib/CodeGen/CGBlocks.cpp | 162 +- .../llvm/tools/clang/lib/CodeGen/CGBlocks.h | 2 +- .../tools/clang/lib/CodeGen/CGBuiltin.cpp | 495 +- .../llvm/tools/clang/lib/CodeGen/CGCUDANV.cpp | 126 + .../tools/clang/lib/CodeGen/CGCUDARuntime.cpp | 55 + .../tools/clang/lib/CodeGen/CGCUDARuntime.h | 54 + .../llvm/tools/clang/lib/CodeGen/CGCXX.cpp | 42 +- .../llvm/tools/clang/lib/CodeGen/CGCXXABI.cpp | 10 +- .../llvm/tools/clang/lib/CodeGen/CGCXXABI.h | 8 +- .../llvm/tools/clang/lib/CodeGen/CGCall.cpp | 285 +- contrib/llvm/tools/clang/lib/CodeGen/CGCall.h | 10 +- .../llvm/tools/clang/lib/CodeGen/CGClass.cpp | 92 +- .../tools/clang/lib/CodeGen/CGCleanup.cpp | 383 +- .../llvm/tools/clang/lib/CodeGen/CGCleanup.h | 323 +- .../tools/clang/lib/CodeGen/CGDebugInfo.cpp | 499 +- .../tools/clang/lib/CodeGen/CGDebugInfo.h | 71 +- .../llvm/tools/clang/lib/CodeGen/CGDecl.cpp | 184 +- .../tools/clang/lib/CodeGen/CGDeclCXX.cpp | 25 +- .../tools/clang/lib/CodeGen/CGException.cpp | 692 +-- .../tools/clang/lib/CodeGen/CGException.h | 12 +- .../llvm/tools/clang/lib/CodeGen/CGExpr.cpp | 502 +- .../tools/clang/lib/CodeGen/CGExprAgg.cpp | 156 +- .../tools/clang/lib/CodeGen/CGExprCXX.cpp | 284 +- .../tools/clang/lib/CodeGen/CGExprComplex.cpp | 83 +- .../clang/lib/CodeGen/CGExprConstant.cpp | 111 +- .../tools/clang/lib/CodeGen/CGExprScalar.cpp | 204 +- .../llvm/tools/clang/lib/CodeGen/CGObjC.cpp | 1362 +++-- .../tools/clang/lib/CodeGen/CGObjCGNU.cpp | 378 +- .../tools/clang/lib/CodeGen/CGObjCMac.cpp | 383 +- .../tools/clang/lib/CodeGen/CGObjCRuntime.cpp | 45 +- .../tools/clang/lib/CodeGen/CGObjCRuntime.h | 3 +- .../clang/lib/CodeGen/CGOpenCLRuntime.cpp | 28 + .../tools/clang/lib/CodeGen/CGOpenCLRuntime.h | 46 + .../llvm/tools/clang/lib/CodeGen/CGRTTI.cpp | 50 +- .../tools/clang/lib/CodeGen/CGRecordLayout.h | 11 +- .../lib/CodeGen/CGRecordLayoutBuilder.cpp | 32 +- .../llvm/tools/clang/lib/CodeGen/CGStmt.cpp | 129 +- .../llvm/tools/clang/lib/CodeGen/CGVTT.cpp | 421 +- .../tools/clang/lib/CodeGen/CGVTables.cpp | 2688 +--------- .../llvm/tools/clang/lib/CodeGen/CGVTables.h | 168 +- .../llvm/tools/clang/lib/CodeGen/CGValue.h | 109 +- .../tools/clang/lib/CodeGen/CodeGenAction.cpp | 29 +- .../clang/lib/CodeGen/CodeGenFunction.cpp | 96 +- .../tools/clang/lib/CodeGen/CodeGenFunction.h | 197 +- .../tools/clang/lib/CodeGen/CodeGenModule.cpp | 712 +-- .../tools/clang/lib/CodeGen/CodeGenModule.h | 156 +- .../tools/clang/lib/CodeGen/CodeGenTBAA.cpp | 4 +- .../tools/clang/lib/CodeGen/CodeGenTBAA.h | 4 +- .../tools/clang/lib/CodeGen/CodeGenTypes.cpp | 44 +- .../tools/clang/lib/CodeGen/CodeGenTypes.h | 10 +- .../tools/clang/lib/CodeGen/ItaniumCXXABI.cpp | 128 +- .../clang/lib/CodeGen/MicrosoftCXXABI.cpp | 4 +- .../tools/clang/lib/CodeGen/ModuleBuilder.cpp | 12 +- .../tools/clang/lib/CodeGen/TargetInfo.cpp | 420 +- .../llvm/tools/clang/lib/CodeGen/TargetInfo.h | 42 +- .../llvm/tools/clang/lib/Driver/Action.cpp | 9 +- .../llvm/tools/clang/lib/Driver/ArgList.cpp | 53 +- .../tools/clang/lib/Driver/Compilation.cpp | 45 +- .../llvm/tools/clang/lib/Driver/Driver.cpp | 367 +- .../llvm/tools/clang/lib/Driver/HostInfo.cpp | 2 +- contrib/llvm/tools/clang/lib/Driver/Job.cpp | 6 + .../llvm/tools/clang/lib/Driver/OptTable.cpp | 13 +- .../llvm/tools/clang/lib/Driver/Option.cpp | 12 +- .../llvm/tools/clang/lib/Driver/Phases.cpp | 4 +- .../llvm/tools/clang/lib/Driver/ToolChain.cpp | 34 +- .../tools/clang/lib/Driver/ToolChains.cpp | 792 +-- .../llvm/tools/clang/lib/Driver/ToolChains.h | 27 +- contrib/llvm/tools/clang/lib/Driver/Tools.cpp | 880 ++-- contrib/llvm/tools/clang/lib/Driver/Tools.h | 16 + contrib/llvm/tools/clang/lib/Driver/Types.cpp | 10 +- .../tools/clang/lib/Frontend/ASTConsumers.cpp | 77 +- .../tools/clang/lib/Frontend/ASTMerge.cpp | 12 +- .../llvm/tools/clang/lib/Frontend/ASTUnit.cpp | 674 +-- .../tools/clang/lib/Frontend/CacheTokens.cpp | 20 +- .../clang/lib/Frontend/CompilerInstance.cpp | 674 ++- .../clang/lib/Frontend/CompilerInvocation.cpp | 388 +- .../CreateInvocationFromCommandLine.cpp | 10 +- .../clang/lib/Frontend/DependencyFile.cpp | 44 +- .../clang/lib/Frontend/FrontendAction.cpp | 30 +- .../clang/lib/Frontend/FrontendActions.cpp | 90 +- .../clang/lib/Frontend/FrontendOptions.cpp | 2 +- .../clang/lib/Frontend/HeaderIncludeGen.cpp | 14 +- .../clang/lib/Frontend/InitHeaderSearch.cpp | 204 +- .../clang/lib/Frontend/InitPreprocessor.cpp | 175 +- .../clang/lib/Frontend/LangStandards.cpp | 2 +- .../lib/Frontend/LogDiagnosticPrinter.cpp | 67 +- .../clang/lib/Frontend/MultiplexConsumer.cpp | 4 +- .../lib/Frontend/PrintPreprocessedOutput.cpp | 44 +- .../lib/Frontend/TextDiagnosticBuffer.cpp | 33 +- .../lib/Frontend/TextDiagnosticPrinter.cpp | 1368 ++--- ...lient.cpp => VerifyDiagnosticConsumer.cpp} | 104 +- .../tools/clang/lib/Frontend/Warnings.cpp | 47 +- .../ExecuteCompilerInvocation.cpp | 39 +- .../llvm/tools/clang/lib/Headers/avxintrin.h | 2 +- .../llvm/tools/clang/lib/Headers/emmintrin.h | 70 +- contrib/llvm/tools/clang/lib/Headers/float.h | 2 +- .../llvm/tools/clang/lib/Headers/mm_malloc.h | 4 +- .../llvm/tools/clang/lib/Headers/pmmintrin.h | 6 +- .../llvm/tools/clang/lib/Headers/stdalign.h | 30 + contrib/llvm/tools/clang/lib/Headers/tgmath.h | 7 +- .../llvm/tools/clang/lib/Headers/xmmintrin.h | 41 +- .../tools/clang/lib/Index/ASTLocation.cpp | 11 +- .../llvm/tools/clang/lib/Index/CallGraph.cpp | 2 +- contrib/llvm/tools/clang/lib/Index/Entity.cpp | 8 +- .../llvm/tools/clang/lib/Index/EntityImpl.h | 2 +- .../tools/clang/lib/Index/GlobalSelector.cpp | 4 +- .../llvm/tools/clang/lib/Lex/HeaderMap.cpp | 4 +- .../llvm/tools/clang/lib/Lex/HeaderSearch.cpp | 208 +- contrib/llvm/tools/clang/lib/Lex/Lexer.cpp | 650 ++- .../tools/clang/lib/Lex/LiteralSupport.cpp | 394 +- .../llvm/tools/clang/lib/Lex/MacroArgs.cpp | 48 +- contrib/llvm/tools/clang/lib/Lex/MacroArgs.h | 13 +- .../llvm/tools/clang/lib/Lex/MacroInfo.cpp | 6 +- .../llvm/tools/clang/lib/Lex/PPCaching.cpp | 2 + .../llvm/tools/clang/lib/Lex/PPDirectives.cpp | 140 +- .../tools/clang/lib/Lex/PPExpressions.cpp | 56 +- .../tools/clang/lib/Lex/PPLexerChange.cpp | 64 +- .../tools/clang/lib/Lex/PPMacroExpansion.cpp | 182 +- contrib/llvm/tools/clang/lib/Lex/PTHLexer.cpp | 19 +- contrib/llvm/tools/clang/lib/Lex/Pragma.cpp | 95 +- .../clang/lib/Lex/PreprocessingRecord.cpp | 283 +- .../llvm/tools/clang/lib/Lex/Preprocessor.cpp | 268 +- .../tools/clang/lib/Lex/PreprocessorLexer.cpp | 8 + .../tools/clang/lib/Lex/ScratchBuffer.cpp | 2 +- .../clang/lib/Lex/TokenConcatenation.cpp | 72 +- .../llvm/tools/clang/lib/Lex/TokenLexer.cpp | 219 +- .../llvm/tools/clang/lib/Parse/ParseAST.cpp | 6 +- .../clang/lib/Parse/ParseCXXInlineMethods.cpp | 140 +- .../llvm/tools/clang/lib/Parse/ParseDecl.cpp | 810 ++- .../tools/clang/lib/Parse/ParseDeclCXX.cpp | 418 +- .../llvm/tools/clang/lib/Parse/ParseExpr.cpp | 184 +- .../tools/clang/lib/Parse/ParseExprCXX.cpp | 577 ++- .../llvm/tools/clang/lib/Parse/ParseInit.cpp | 25 +- .../llvm/tools/clang/lib/Parse/ParseObjc.cpp | 631 ++- .../tools/clang/lib/Parse/ParsePragma.cpp | 19 +- .../llvm/tools/clang/lib/Parse/ParseStmt.cpp | 395 +- .../tools/clang/lib/Parse/ParseTemplate.cpp | 115 +- .../tools/clang/lib/Parse/ParseTentative.cpp | 26 +- contrib/llvm/tools/clang/lib/Parse/Parser.cpp | 187 +- .../clang/lib/Parse/RAIIObjectsForParser.h | 4 +- .../tools/clang/lib/Rewrite/DeltaTree.cpp | 4 +- .../tools/clang/lib/Rewrite/FixItRewriter.cpp | 20 +- .../clang/lib/Rewrite/FrontendActions.cpp | 16 +- .../tools/clang/lib/Rewrite/HTMLPrint.cpp | 6 +- .../tools/clang/lib/Rewrite/HTMLRewrite.cpp | 40 +- .../tools/clang/lib/Rewrite/RewriteMacros.cpp | 6 +- .../tools/clang/lib/Rewrite/RewriteObjC.cpp | 571 ++- .../tools/clang/lib/Rewrite/RewriteRope.cpp | 4 +- .../tools/clang/lib/Rewrite/RewriteTest.cpp | 2 +- .../llvm/tools/clang/lib/Rewrite/Rewriter.cpp | 25 +- .../clang/lib/Sema/AnalysisBasedWarnings.cpp | 476 +- .../tools/clang/lib/Sema/AttributeList.cpp | 26 +- .../clang/lib/Sema/CodeCompleteConsumer.cpp | 52 +- .../llvm/tools/clang/lib/Sema/DeclSpec.cpp | 92 +- .../clang/lib/Sema/DelayedDiagnostic.cpp | 2 +- .../clang/lib/Sema/IdentifierResolver.cpp | 2 +- .../tools/clang/lib/Sema/JumpDiagnostics.cpp | 79 +- .../tools/clang/lib/Sema/MultiInitializer.cpp | 92 + contrib/llvm/tools/clang/lib/Sema/Sema.cpp | 388 +- .../llvm/tools/clang/lib/Sema/SemaAccess.cpp | 57 +- .../llvm/tools/clang/lib/Sema/SemaAttr.cpp | 16 +- .../tools/clang/lib/Sema/SemaCXXScopeSpec.cpp | 30 +- .../Sema/{SemaCXXCast.cpp => SemaCast.cpp} | 659 ++- .../tools/clang/lib/Sema/SemaChecking.cpp | 808 ++- .../tools/clang/lib/Sema/SemaCodeComplete.cpp | 473 +- .../llvm/tools/clang/lib/Sema/SemaDecl.cpp | 1787 +++++-- .../tools/clang/lib/Sema/SemaDeclAttr.cpp | 1126 +++- .../llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp | 2783 +++++++--- .../tools/clang/lib/Sema/SemaDeclObjC.cpp | 909 ++-- .../clang/lib/Sema/SemaExceptionSpec.cpp | 14 +- .../llvm/tools/clang/lib/Sema/SemaExpr.cpp | 4510 +++++++++-------- .../llvm/tools/clang/lib/Sema/SemaExprCXX.cpp | 322 +- .../tools/clang/lib/Sema/SemaExprMember.cpp | 99 +- .../tools/clang/lib/Sema/SemaExprObjC.cpp | 539 +- .../tools/clang/lib/Sema/SemaFixItUtils.cpp | 160 + .../llvm/tools/clang/lib/Sema/SemaInit.cpp | 1022 ++-- .../llvm/tools/clang/lib/Sema/SemaLookup.cpp | 285 +- .../tools/clang/lib/Sema/SemaObjCProperty.cpp | 422 +- .../tools/clang/lib/Sema/SemaOverload.cpp | 622 ++- .../llvm/tools/clang/lib/Sema/SemaStmt.cpp | 417 +- .../tools/clang/lib/Sema/SemaTemplate.cpp | 206 +- .../clang/lib/Sema/SemaTemplateDeduction.cpp | 233 +- .../lib/Sema/SemaTemplateInstantiate.cpp | 88 +- .../lib/Sema/SemaTemplateInstantiateDecl.cpp | 636 +-- .../clang/lib/Sema/SemaTemplateVariadic.cpp | 55 +- .../llvm/tools/clang/lib/Sema/SemaType.cpp | 332 +- .../clang/lib/Sema/TargetAttributesSema.cpp | 20 +- .../llvm/tools/clang/lib/Sema/TreeTransform.h | 249 +- .../clang/lib/Serialization/ASTCommon.cpp | 1 + .../tools/clang/lib/Serialization/ASTCommon.h | 8 +- .../clang/lib/Serialization/ASTReader.cpp | 4300 ++++++++-------- .../clang/lib/Serialization/ASTReaderDecl.cpp | 798 +-- .../lib/Serialization/ASTReaderInternals.h | 243 + .../clang/lib/Serialization/ASTReaderStmt.cpp | 352 +- .../clang/lib/Serialization/ASTWriter.cpp | 1259 +++-- .../clang/lib/Serialization/ASTWriterDecl.cpp | 121 +- .../clang/lib/Serialization/ASTWriterStmt.cpp | 50 +- .../Serialization/ChainedIncludesSource.cpp | 52 +- .../clang/lib/Serialization/GeneratePCH.cpp | 34 +- .../tools/clang/lib/Serialization/Module.cpp | 109 + .../clang/lib/Serialization/ModuleManager.cpp | 253 + .../clang/lib/StaticAnalyzer/CMakeLists.txt | 3 - .../Checkers/AdjustedReturnValueChecker.cpp | 2 +- .../Checkers/AnalyzerStatsChecker.cpp | 7 +- .../Checkers/ArrayBoundChecker.cpp | 17 +- .../Checkers/ArrayBoundCheckerV2.cpp | 32 +- .../Checkers/AttrNonNullChecker.cpp | 17 +- .../Checkers/BasicObjCFoundationChecks.cpp | 45 +- .../Checkers/BuiltinFunctionChecker.cpp | 4 +- .../StaticAnalyzer/Checkers/CMakeLists.txt | 70 - .../Checkers/CStringChecker.cpp | 303 +- .../Checkers/CallAndMessageChecker.cpp | 52 +- .../Checkers/CastSizeChecker.cpp | 4 +- .../Checkers/CastToStructChecker.cpp | 2 +- .../Checkers/CheckObjCDealloc.cpp | 68 +- .../Checkers/CheckObjCInstMethSignature.cpp | 28 +- .../Checkers/CheckSecuritySyntaxOnly.cpp | 103 +- .../Checkers/CheckSizeofPointer.cpp | 12 +- .../lib/StaticAnalyzer/Checkers/Checkers.td | 40 +- .../StaticAnalyzer/Checkers/ChrootChecker.cpp | 20 +- .../StaticAnalyzer/Checkers/ClangCheckers.cpp | 32 + .../Checkers/ClangSACheckerProvider.cpp | 289 -- .../Checkers/ClangSACheckerProvider.h | 29 - .../StaticAnalyzer/Checkers/ClangSACheckers.h | 1 + .../Checkers/DeadStoresChecker.cpp | 120 +- .../StaticAnalyzer/Checkers/DebugCheckers.cpp | 2 +- .../Checkers/DereferenceChecker.cpp | 38 +- .../Checkers/DivZeroChecker.cpp | 10 +- .../Checkers/FixedAddressChecker.cpp | 4 +- .../Checkers/IdempotentOperationChecker.cpp | 21 +- .../Checkers/IteratorsChecker.cpp | 74 +- .../Checkers/LLVMConventionsChecker.cpp | 25 +- .../Checkers/MacOSKeychainAPIChecker.cpp | 632 +++ .../Checkers/MacOSXAPIChecker.cpp | 8 +- .../lib/StaticAnalyzer/Checkers/Makefile | 24 - .../StaticAnalyzer/Checkers/MallocChecker.cpp | 140 +- .../MallocOverflowSecurityChecker.cpp | 268 + .../Checkers/NSAutoreleasePoolChecker.cpp | 17 +- .../Checkers/NSErrorChecker.cpp | 30 +- .../Checkers/NoReturnFunctionChecker.cpp | 73 +- .../Checkers/OSAtomicChecker.cpp | 101 +- .../Checkers/ObjCAtSyncChecker.cpp | 17 +- .../Checkers/ObjCSelfInitChecker.cpp | 35 +- .../Checkers/ObjCUnusedIVarsChecker.cpp | 18 +- .../Checkers/PointerArithChecker.cpp | 4 +- .../Checkers/PointerSubChecker.cpp | 4 +- .../Checkers/PthreadLockChecker.cpp | 185 +- .../RetainCountChecker.cpp} | 2929 ++++++----- .../Checkers/ReturnPointerRangeChecker.cpp | 10 +- .../Checkers/ReturnUndefChecker.cpp | 6 +- .../Checkers/StackAddrEscapeChecker.cpp | 33 +- .../StaticAnalyzer/Checkers/StreamChecker.cpp | 58 +- .../Checkers/UndefBranchChecker.cpp | 33 +- .../Checkers/UndefCapturedBlockVarChecker.cpp | 9 +- .../Checkers/UndefResultChecker.cpp | 8 +- .../UndefinedArraySubscriptChecker.cpp | 6 +- .../Checkers/UndefinedAssignmentChecker.cpp | 13 +- .../Checkers/UnixAPIChecker.cpp | 29 +- .../Checkers/UnreachableCodeChecker.cpp | 29 +- .../Checkers/VLASizeChecker.cpp | 20 +- .../StaticAnalyzer/Core/AggExprVisitor.cpp | 2 +- .../StaticAnalyzer/Core/AnalysisManager.cpp | 52 + .../Core/BasicConstraintManager.cpp | 179 +- .../lib/StaticAnalyzer/Core/BasicStore.cpp | 605 --- .../StaticAnalyzer/Core/BasicValueFactory.cpp | 14 +- .../lib/StaticAnalyzer/Core/BlockCounter.cpp | 4 +- .../lib/StaticAnalyzer/Core/BugReporter.cpp | 580 ++- .../Core/BugReporterVisitors.cpp | 746 ++- .../lib/StaticAnalyzer/Core/CMakeLists.txt | 41 - .../clang/lib/StaticAnalyzer/Core/Checker.cpp | 22 + .../StaticAnalyzer/Core/CheckerContext.cpp | 4 +- .../StaticAnalyzer/Core/CheckerManager.cpp | 136 +- .../StaticAnalyzer/Core/CheckerRegistry.cpp | 149 + .../lib/StaticAnalyzer/Core/CoreEngine.cpp | 239 +- .../lib/StaticAnalyzer/Core/Environment.cpp | 76 +- .../lib/StaticAnalyzer/Core/ExplodedGraph.cpp | 31 +- .../lib/StaticAnalyzer/Core/ExprEngine.cpp | 1961 ++----- .../lib/StaticAnalyzer/Core/ExprEngineC.cpp | 752 +++ .../{CXXExprEngine.cpp => ExprEngineCXX.cpp} | 87 +- .../Core/ExprEngineCallAndReturn.cpp | 253 + .../StaticAnalyzer/Core/ExprEngineObjC.cpp | 279 + .../lib/StaticAnalyzer/Core/FlatStore.cpp | 217 - .../StaticAnalyzer/Core/HTMLDiagnostics.cpp | 62 +- .../clang/lib/StaticAnalyzer/Core/Makefile | 17 - .../lib/StaticAnalyzer/Core/MemRegion.cpp | 77 +- .../lib/StaticAnalyzer/Core/ObjCMessage.cpp | 52 +- .../StaticAnalyzer/Core/PathDiagnostic.cpp | 225 +- .../StaticAnalyzer/Core/PlistDiagnostics.cpp | 79 +- .../Core/{GRState.cpp => ProgramState.cpp} | 297 +- .../Core/RangeConstraintManager.cpp | 73 +- .../lib/StaticAnalyzer/Core/RegionStore.cpp | 162 +- .../lib/StaticAnalyzer/Core/SValBuilder.cpp | 21 +- .../clang/lib/StaticAnalyzer/Core/SVals.cpp | 18 +- .../Core/SimpleConstraintManager.cpp | 20 +- .../Core/SimpleConstraintManager.h | 26 +- .../StaticAnalyzer/Core/SimpleSValBuilder.cpp | 43 +- .../clang/lib/StaticAnalyzer/Core/Store.cpp | 28 +- .../lib/StaticAnalyzer/Core/SymbolManager.cpp | 153 +- .../Core/TextPathDiagnostics.cpp | 20 +- .../Frontend/AnalysisConsumer.cpp | 245 +- .../Frontend/AnalysisConsumer.h | 6 +- .../StaticAnalyzer/Frontend/CMakeLists.txt | 20 - .../Frontend/CheckerRegistration.cpp | 108 +- .../Frontend/FrontendActions.cpp | 5 +- .../lib/StaticAnalyzer/Frontend/Makefile | 19 - .../tools/clang/lib/StaticAnalyzer/Makefile | 18 - .../tools/clang/lib/StaticAnalyzer/README.txt | 139 - .../tools/clang/tools/driver/cc1_main.cpp | 17 +- .../tools/clang/tools/driver/cc1as_main.cpp | 94 +- .../llvm/tools/clang/tools/driver/driver.cpp | 71 +- .../tools/clang/utils/TableGen/CMakeLists.txt | 12 + .../utils/TableGen/ClangASTNodesEmitter.cpp | 0 .../utils/TableGen/ClangASTNodesEmitter.h | 4 +- .../utils/TableGen/ClangAttrEmitter.cpp | 56 +- .../clang}/utils/TableGen/ClangAttrEmitter.h | 15 +- .../TableGen/ClangDiagnosticsEmitter.cpp | 20 +- .../utils/TableGen/ClangDiagnosticsEmitter.h | 2 +- .../utils/TableGen/ClangSACheckersEmitter.cpp | 2 +- .../utils/TableGen/ClangSACheckersEmitter.h | 2 +- .../clang/utils/TableGen}/Makefile | 11 +- .../clang}/utils/TableGen/NeonEmitter.cpp | 27 +- .../clang}/utils/TableGen/NeonEmitter.h | 4 +- .../utils/TableGen/OptParserEmitter.cpp | 2 +- .../clang}/utils/TableGen/OptParserEmitter.h | 2 +- .../tools/clang/utils/TableGen/TableGen.cpp | 176 + .../llvm/utils/TableGen/ARMDecoderEmitter.cpp | 20 +- .../llvm/utils/TableGen/ARMDecoderEmitter.h | 3 +- .../llvm/utils/TableGen/AsmMatcherEmitter.cpp | 69 +- .../llvm/utils/TableGen/AsmMatcherEmitter.h | 2 +- .../llvm/utils/TableGen/AsmWriterEmitter.cpp | 14 +- .../llvm/utils/TableGen/AsmWriterEmitter.h | 2 +- contrib/llvm/utils/TableGen/AsmWriterInst.cpp | 2 +- .../utils/TableGen/CallingConvEmitter.cpp | 2 +- .../llvm/utils/TableGen/CallingConvEmitter.h | 2 +- .../llvm/utils/TableGen/CodeEmitterGen.cpp | 14 +- contrib/llvm/utils/TableGen/CodeEmitterGen.h | 2 +- .../utils/TableGen/CodeGenDAGPatterns.cpp | 25 +- .../utils/TableGen/CodeGenInstruction.cpp | 21 +- .../llvm/utils/TableGen/CodeGenInstruction.h | 1 + .../llvm/utils/TableGen/CodeGenRegisters.cpp | 294 +- .../llvm/utils/TableGen/CodeGenRegisters.h | 112 +- contrib/llvm/utils/TableGen/CodeGenTarget.cpp | 12 +- contrib/llvm/utils/TableGen/CodeGenTarget.h | 6 +- .../llvm/utils/TableGen/DAGISelEmitter.cpp | 2 +- contrib/llvm/utils/TableGen/DAGISelEmitter.h | 2 +- .../llvm/utils/TableGen/DAGISelMatcher.cpp | 2 +- .../utils/TableGen/DAGISelMatcherEmitter.cpp | 2 +- .../llvm/utils/TableGen/DAGISelMatcherGen.cpp | 6 +- .../utils/TableGen/DisassemblerEmitter.cpp | 20 +- .../llvm/utils/TableGen/DisassemblerEmitter.h | 2 +- contrib/llvm/utils/TableGen/EDEmitter.cpp | 76 +- contrib/llvm/utils/TableGen/EDEmitter.h | 2 +- .../llvm/utils/TableGen/FastISelEmitter.cpp | 6 +- contrib/llvm/utils/TableGen/FastISelEmitter.h | 2 +- .../utils/TableGen/FixedLenDecoderEmitter.cpp | 492 +- .../utils/TableGen/FixedLenDecoderEmitter.h | 47 +- .../llvm/utils/TableGen/InstrEnumEmitter.cpp | 2 +- .../llvm/utils/TableGen/InstrEnumEmitter.h | 2 +- .../llvm/utils/TableGen/InstrInfoEmitter.cpp | 4 +- .../llvm/utils/TableGen/InstrInfoEmitter.h | 2 +- .../llvm/utils/TableGen/IntrinsicEmitter.cpp | 2 +- .../llvm/utils/TableGen/IntrinsicEmitter.h | 2 +- .../TableGen/LLVMCConfigurationEmitter.cpp | 3134 ------------ .../TableGen/LLVMCConfigurationEmitter.h | 34 - .../utils/TableGen/PseudoLoweringEmitter.cpp | 4 +- .../utils/TableGen/PseudoLoweringEmitter.h | 2 +- .../utils/TableGen/RegisterInfoEmitter.cpp | 566 ++- .../llvm/utils/TableGen/RegisterInfoEmitter.h | 9 +- contrib/llvm/utils/TableGen/SetTheory.cpp | 4 +- .../llvm/utils/TableGen/SubtargetEmitter.cpp | 2 +- .../llvm/utils/TableGen/SubtargetEmitter.h | 2 +- contrib/llvm/utils/TableGen/TableGen.cpp | 289 +- .../utils/TableGen/X86DisassemblerTables.cpp | 93 +- .../utils/TableGen/X86DisassemblerTables.h | 6 +- .../utils/TableGen/X86RecognizableInstr.cpp | 100 +- .../utils/TableGen/X86RecognizableInstr.h | 8 +- lib/clang/Makefile | 1 + lib/clang/clang.build.mk | 42 +- lib/clang/include/ARMGenDecoderTables.inc | 2 - .../include/ARMGenDisassemblerTables.inc | 2 + lib/clang/include/clang/Basic/Version.inc | 4 +- .../include/clang/Parse/AttrLateParsed.inc | 2 + lib/clang/include/llvm/Config/config.h | 27 +- lib/clang/include/llvm/Config/llvm-config.h | 25 +- lib/clang/libclanganalysis/Makefile | 2 + lib/clang/libclangarcmigrate/Makefile | 2 + lib/clang/libclangast/Makefile | 5 +- lib/clang/libclangbasic/Makefile | 1 + lib/clang/libclangcodegen/Makefile | 3 + lib/clang/libclangfrontend/Makefile | 2 +- lib/clang/libclangparse/Makefile | 3 +- lib/clang/libclangsema/Makefile | 4 +- lib/clang/libclangserialization/Makefile | 4 +- .../libclangstaticanalyzercheckers/Makefile | 5 +- lib/clang/libclangstaticanalyzercore/Makefile | 12 +- lib/clang/libllvmarmcodegen/Makefile | 7 +- lib/clang/libllvmarmdesc/Makefile | 8 +- lib/clang/libllvmarmdisassembler/Makefile | 4 +- lib/clang/libllvmcodegen/Makefile | 6 +- lib/clang/libllvmipo/Makefile | 2 +- lib/clang/libllvmmc/Makefile | 6 +- lib/clang/libllvmmcparser/Makefile | 2 +- lib/clang/libllvmmipscodegen/Makefile | 2 + lib/clang/libllvmmipsdesc/Makefile | 5 +- lib/clang/libllvmpowerpccodegen/Makefile | 5 +- lib/clang/libllvmpowerpcdesc/Makefile | 9 +- lib/clang/libllvmscalaropts/Makefile | 1 - lib/clang/libllvmtablegen/Makefile | 14 + lib/clang/libllvmtarget/Makefile | 2 - lib/clang/libllvmtransformutils/Makefile | 1 + lib/clang/libllvmx86codegen/Makefile | 9 +- lib/clang/libllvmx86desc/Makefile | 6 +- lib/clang/libllvmx86disassembler/Makefile | 1 + usr.bin/clang/Makefile | 2 +- usr.bin/clang/clang-tblgen/Makefile | 18 + usr.bin/clang/clang/clang.1 | 9 +- usr.bin/clang/tblgen/Makefile | 14 +- 1744 files changed, 130532 insertions(+), 80628 deletions(-) create mode 100644 contrib/llvm/include/llvm-c/Transforms/PassManagerBuilder.h create mode 100644 contrib/llvm/include/llvm/ADT/TinyPtrVector.h rename contrib/llvm/include/llvm/Analysis/{BlockFrequency.h => BlockFrequencyInfo.h} (58%) create mode 100644 contrib/llvm/include/llvm/Analysis/LoopIterator.h create mode 100644 contrib/llvm/include/llvm/CodeGen/LexicalScopes.h rename contrib/llvm/include/llvm/CodeGen/{MachineBlockFrequency.h => MachineBlockFrequencyInfo.h} (60%) delete mode 100644 contrib/llvm/include/llvm/CompilerDriver/Action.h delete mode 100644 contrib/llvm/include/llvm/CompilerDriver/AutoGenerated.h delete mode 100644 contrib/llvm/include/llvm/CompilerDriver/BuiltinOptions.h delete mode 100644 contrib/llvm/include/llvm/CompilerDriver/Common.td delete mode 100644 contrib/llvm/include/llvm/CompilerDriver/CompilationGraph.h delete mode 100644 contrib/llvm/include/llvm/CompilerDriver/Error.h delete mode 100644 contrib/llvm/include/llvm/CompilerDriver/Main.h delete mode 100644 contrib/llvm/include/llvm/CompilerDriver/Main.inc delete mode 100644 contrib/llvm/include/llvm/CompilerDriver/Tool.h create mode 100644 contrib/llvm/include/llvm/DebugInfo/DIContext.h rename contrib/llvm/include/llvm/{Target/TargetAsmBackend.h => MC/MCAsmBackend.h} (90%) create mode 100644 contrib/llvm/include/llvm/MC/MCAtom.h create mode 100644 contrib/llvm/include/llvm/MC/MCCodeGenInfo.h create mode 100644 contrib/llvm/include/llvm/MC/MCInstrAnalysis.h create mode 100644 contrib/llvm/include/llvm/MC/MCModule.h create mode 100644 contrib/llvm/include/llvm/MC/MCObjectFileInfo.h rename contrib/llvm/include/llvm/{Target/TargetAsmLexer.h => MC/MCTargetAsmLexer.h} (81%) rename contrib/llvm/include/llvm/{Target/TargetAsmParser.h => MC/MCTargetAsmParser.h} (75%) rename contrib/llvm/include/llvm/{CodeGen => MC}/MachineLocation.h (91%) create mode 100644 contrib/llvm/include/llvm/Object/Archive.h create mode 100644 contrib/llvm/include/llvm/Object/MachO.h create mode 100644 contrib/llvm/include/llvm/Support/BlockFrequency.h create mode 100644 contrib/llvm/include/llvm/Support/Capacity.h create mode 100644 contrib/llvm/include/llvm/Support/CodeGen.h create mode 100644 contrib/llvm/include/llvm/Support/DataExtractor.h create mode 100644 contrib/llvm/include/llvm/Support/GCOV.h delete mode 100644 contrib/llvm/include/llvm/Support/PassManagerBuilder.h rename contrib/llvm/include/llvm/{Target => Support}/TargetRegistry.h (66%) rename contrib/llvm/include/llvm/{Target => Support}/TargetSelect.h (75%) rename contrib/llvm/{utils => include/llvm}/TableGen/Error.h (89%) create mode 100644 contrib/llvm/include/llvm/TableGen/Main.h rename contrib/llvm/{utils => include/llvm}/TableGen/Record.h (80%) create mode 100644 contrib/llvm/include/llvm/TableGen/TableGenAction.h rename contrib/llvm/{utils => include/llvm}/TableGen/TableGenBackend.h (88%) delete mode 100644 contrib/llvm/include/llvm/Target/TargetAsmInfo.h create mode 100644 contrib/llvm/include/llvm/Transforms/IPO/PassManagerBuilder.h create mode 100644 contrib/llvm/include/llvm/Transforms/Utils/SimplifyIndVar.h delete mode 100644 contrib/llvm/lib/Analysis/BlockFrequency.cpp create mode 100644 contrib/llvm/lib/Analysis/BlockFrequencyInfo.cpp rename contrib/llvm/lib/{Target/X86/SSEDomainFix.cpp => CodeGen/ExecutionDepsFix.cpp} (84%) rename contrib/llvm/lib/CodeGen/{LowerSubregs.cpp => ExpandPostRAPseudos.cpp} (69%) create mode 100644 contrib/llvm/lib/CodeGen/LexicalScopes.cpp create mode 100644 contrib/llvm/lib/CodeGen/LiveRangeCalc.cpp create mode 100644 contrib/llvm/lib/CodeGen/LiveRangeCalc.h rename contrib/llvm/lib/CodeGen/{MachineBlockFrequency.cpp => MachineBlockFrequencyInfo.cpp} (51%) delete mode 100644 contrib/llvm/lib/CompilerDriver/Action.cpp delete mode 100644 contrib/llvm/lib/CompilerDriver/BuiltinOptions.cpp delete mode 100644 contrib/llvm/lib/CompilerDriver/CompilationGraph.cpp delete mode 100644 contrib/llvm/lib/CompilerDriver/Main.cpp delete mode 100644 contrib/llvm/lib/CompilerDriver/Tool.cpp create mode 100644 contrib/llvm/lib/DebugInfo/DIContext.cpp create mode 100644 contrib/llvm/lib/DebugInfo/DWARFAbbreviationDeclaration.cpp create mode 100644 contrib/llvm/lib/DebugInfo/DWARFAbbreviationDeclaration.h create mode 100644 contrib/llvm/lib/DebugInfo/DWARFAttribute.h create mode 100644 contrib/llvm/lib/DebugInfo/DWARFCompileUnit.cpp create mode 100644 contrib/llvm/lib/DebugInfo/DWARFCompileUnit.h create mode 100644 contrib/llvm/lib/DebugInfo/DWARFContext.cpp create mode 100644 contrib/llvm/lib/DebugInfo/DWARFContext.h create mode 100644 contrib/llvm/lib/DebugInfo/DWARFDebugAbbrev.cpp create mode 100644 contrib/llvm/lib/DebugInfo/DWARFDebugAbbrev.h create mode 100644 contrib/llvm/lib/DebugInfo/DWARFDebugArangeSet.cpp create mode 100644 contrib/llvm/lib/DebugInfo/DWARFDebugArangeSet.h create mode 100644 contrib/llvm/lib/DebugInfo/DWARFDebugAranges.cpp create mode 100644 contrib/llvm/lib/DebugInfo/DWARFDebugAranges.h create mode 100644 contrib/llvm/lib/DebugInfo/DWARFDebugInfoEntry.cpp create mode 100644 contrib/llvm/lib/DebugInfo/DWARFDebugInfoEntry.h create mode 100644 contrib/llvm/lib/DebugInfo/DWARFDebugLine.cpp create mode 100644 contrib/llvm/lib/DebugInfo/DWARFDebugLine.h create mode 100644 contrib/llvm/lib/DebugInfo/DWARFFormValue.cpp create mode 100644 contrib/llvm/lib/DebugInfo/DWARFFormValue.h delete mode 100644 contrib/llvm/lib/ExecutionEngine/MCJIT/CMakeLists.txt delete mode 100644 contrib/llvm/lib/ExecutionEngine/MCJIT/Makefile delete mode 100644 contrib/llvm/lib/ExecutionEngine/RuntimeDyld/CMakeLists.txt delete mode 100644 contrib/llvm/lib/ExecutionEngine/RuntimeDyld/Makefile rename contrib/llvm/lib/MC/{TargetAsmBackend.cpp => MCAsmBackend.cpp} (78%) create mode 100644 contrib/llvm/lib/MC/MCAtom.cpp create mode 100644 contrib/llvm/lib/MC/MCCodeGenInfo.cpp create mode 100644 contrib/llvm/lib/MC/MCInstrAnalysis.cpp create mode 100644 contrib/llvm/lib/MC/MCModule.cpp create mode 100644 contrib/llvm/lib/MC/MCObjectFileInfo.cpp rename contrib/llvm/lib/MC/MCParser/{TargetAsmParser.cpp => MCTargetAsmParser.cpp} (64%) rename contrib/llvm/lib/{Target/TargetAsmLexer.cpp => MC/MCTargetAsmLexer.cpp} (56%) create mode 100644 contrib/llvm/lib/Object/Archive.cpp delete mode 100644 contrib/llvm/lib/Object/CMakeLists.txt delete mode 100644 contrib/llvm/lib/Object/Makefile create mode 100644 contrib/llvm/lib/Support/BlockFrequency.cpp create mode 100644 contrib/llvm/lib/Support/DataExtractor.cpp rename contrib/llvm/{utils => lib}/TableGen/Error.cpp (96%) create mode 100644 contrib/llvm/lib/TableGen/Main.cpp rename contrib/llvm/{utils => lib}/TableGen/Record.cpp (68%) rename contrib/llvm/{utils => lib}/TableGen/TGLexer.cpp (90%) rename contrib/llvm/{utils => lib}/TableGen/TGLexer.h (100%) rename contrib/llvm/{utils => lib}/TableGen/TGParser.cpp (88%) rename contrib/llvm/{utils => lib}/TableGen/TGParser.h (82%) rename contrib/llvm/{utils => lib}/TableGen/TableGenBackend.cpp (92%) delete mode 100644 contrib/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.h delete mode 100644 contrib/llvm/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp delete mode 100644 contrib/llvm/lib/Target/ARM/Disassembler/ARMDisassemblerCore.h delete mode 100644 contrib/llvm/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h delete mode 100644 contrib/llvm/lib/Target/ARM/InstPrinter/CMakeLists.txt delete mode 100644 contrib/llvm/lib/Target/ARM/InstPrinter/Makefile rename contrib/llvm/lib/Target/ARM/{ => MCTargetDesc}/ARMAddressingModes.h (87%) rename contrib/llvm/lib/Target/ARM/{ => MCTargetDesc}/ARMAsmBackend.cpp (88%) rename contrib/llvm/lib/Target/ARM/{ => MCTargetDesc}/ARMBaseInfo.h (65%) rename contrib/llvm/lib/Target/ARM/{ => MCTargetDesc}/ARMFixupKinds.h (100%) rename contrib/llvm/lib/Target/ARM/{ => MCTargetDesc}/ARMMCCodeEmitter.cpp (82%) rename contrib/llvm/lib/Target/ARM/{ => MCTargetDesc}/ARMMCExpr.cpp (100%) rename contrib/llvm/lib/Target/ARM/{ => MCTargetDesc}/ARMMCExpr.h (100%) rename contrib/llvm/lib/Target/ARM/{ => MCTargetDesc}/ARMMachObjectWriter.cpp (99%) delete mode 100644 contrib/llvm/lib/Target/ARM/MCTargetDesc/CMakeLists.txt delete mode 100644 contrib/llvm/lib/Target/ARM/NEONMoveFix.cpp delete mode 100644 contrib/llvm/lib/Target/Alpha/MCTargetDesc/CMakeLists.txt delete mode 100644 contrib/llvm/lib/Target/Alpha/MCTargetDesc/Makefile delete mode 100644 contrib/llvm/lib/Target/Blackfin/MCTargetDesc/CMakeLists.txt delete mode 100644 contrib/llvm/lib/Target/Blackfin/MCTargetDesc/Makefile delete mode 100644 contrib/llvm/lib/Target/CellSPU/MCTargetDesc/CMakeLists.txt delete mode 100644 contrib/llvm/lib/Target/CellSPU/MCTargetDesc/Makefile delete mode 100644 contrib/llvm/lib/Target/MBlaze/AsmParser/CMakeLists.txt delete mode 100644 contrib/llvm/lib/Target/MBlaze/AsmParser/Makefile delete mode 100644 contrib/llvm/lib/Target/MBlaze/Disassembler/CMakeLists.txt delete mode 100644 contrib/llvm/lib/Target/MBlaze/Disassembler/Makefile delete mode 100644 contrib/llvm/lib/Target/MBlaze/InstPrinter/CMakeLists.txt delete mode 100644 contrib/llvm/lib/Target/MBlaze/InstPrinter/Makefile delete mode 100644 contrib/llvm/lib/Target/MBlaze/MCTargetDesc/CMakeLists.txt rename contrib/llvm/lib/Target/MBlaze/{ => MCTargetDesc}/MBlazeAsmBackend.cpp (91%) create mode 100644 contrib/llvm/lib/Target/MBlaze/MCTargetDesc/MBlazeBaseInfo.h rename contrib/llvm/lib/Target/MBlaze/{ => MCTargetDesc}/MBlazeMCCodeEmitter.cpp (97%) delete mode 100644 contrib/llvm/lib/Target/MBlaze/MCTargetDesc/Makefile delete mode 100644 contrib/llvm/lib/Target/MSP430/InstPrinter/CMakeLists.txt delete mode 100644 contrib/llvm/lib/Target/MSP430/InstPrinter/Makefile delete mode 100644 contrib/llvm/lib/Target/MSP430/MCTargetDesc/CMakeLists.txt delete mode 100644 contrib/llvm/lib/Target/MSP430/MCTargetDesc/Makefile delete mode 100644 contrib/llvm/lib/Target/Mips/InstPrinter/CMakeLists.txt delete mode 100644 contrib/llvm/lib/Target/Mips/InstPrinter/Makefile delete mode 100644 contrib/llvm/lib/Target/Mips/MCTargetDesc/CMakeLists.txt delete mode 100644 contrib/llvm/lib/Target/Mips/MCTargetDesc/Makefile create mode 100644 contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp create mode 100644 contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h create mode 100644 contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h create mode 100644 contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp create mode 100644 contrib/llvm/lib/Target/Mips/Mips64InstrInfo.td create mode 100644 contrib/llvm/lib/Target/Mips/MipsCodeEmitter.cpp create mode 100644 contrib/llvm/lib/Target/Mips/MipsJITInfo.cpp create mode 100644 contrib/llvm/lib/Target/Mips/MipsJITInfo.h create mode 100644 contrib/llvm/lib/Target/Mips/MipsRelocations.h delete mode 100644 contrib/llvm/lib/Target/PTX/CMakeLists.txt create mode 100644 contrib/llvm/lib/Target/PTX/InstPrinter/PTXInstPrinter.cpp create mode 100644 contrib/llvm/lib/Target/PTX/InstPrinter/PTXInstPrinter.h delete mode 100644 contrib/llvm/lib/Target/PTX/MCTargetDesc/CMakeLists.txt delete mode 100644 contrib/llvm/lib/Target/PTX/MCTargetDesc/Makefile create mode 100644 contrib/llvm/lib/Target/PTX/MCTargetDesc/PTXBaseInfo.h create mode 100644 contrib/llvm/lib/Target/PTX/PTXAsmPrinter.h delete mode 100644 contrib/llvm/lib/Target/PTX/PTXCallingConv.td create mode 100644 contrib/llvm/lib/Target/PTX/PTXFPRoundingModePass.cpp create mode 100644 contrib/llvm/lib/Target/PTX/PTXInstrLoadStore.td create mode 100644 contrib/llvm/lib/Target/PTX/PTXMCInstLower.cpp create mode 100644 contrib/llvm/lib/Target/PTX/PTXParamManager.cpp create mode 100644 contrib/llvm/lib/Target/PTX/PTXParamManager.h create mode 100644 contrib/llvm/lib/Target/PTX/PTXRegAlloc.cpp create mode 100644 contrib/llvm/lib/Target/PTX/PTXSelectionDAGInfo.cpp create mode 100644 contrib/llvm/lib/Target/PTX/PTXSelectionDAGInfo.h delete mode 100644 contrib/llvm/lib/Target/PTX/TargetInfo/CMakeLists.txt delete mode 100644 contrib/llvm/lib/Target/PTX/TargetInfo/Makefile delete mode 100755 contrib/llvm/lib/Target/PTX/generate-register-td.py delete mode 100644 contrib/llvm/lib/Target/PowerPC/InstPrinter/CMakeLists.txt delete mode 100644 contrib/llvm/lib/Target/PowerPC/InstPrinter/Makefile delete mode 100644 contrib/llvm/lib/Target/PowerPC/MCTargetDesc/CMakeLists.txt delete mode 100644 contrib/llvm/lib/Target/PowerPC/MCTargetDesc/Makefile rename contrib/llvm/lib/Target/PowerPC/{ => MCTargetDesc}/PPCAsmBackend.cpp (56%) create mode 100644 contrib/llvm/lib/Target/PowerPC/MCTargetDesc/PPCBaseInfo.h rename contrib/llvm/lib/Target/PowerPC/{ => MCTargetDesc}/PPCFixupKinds.h (100%) rename contrib/llvm/lib/Target/PowerPC/{ => MCTargetDesc}/PPCMCCodeEmitter.cpp (97%) rename contrib/llvm/lib/Target/PowerPC/{ => MCTargetDesc}/PPCPredicates.cpp (100%) rename contrib/llvm/lib/Target/PowerPC/{ => MCTargetDesc}/PPCPredicates.h (98%) delete mode 100644 contrib/llvm/lib/Target/Sparc/MCTargetDesc/CMakeLists.txt delete mode 100644 contrib/llvm/lib/Target/Sparc/MCTargetDesc/Makefile delete mode 100644 contrib/llvm/lib/Target/SystemZ/MCTargetDesc/CMakeLists.txt delete mode 100644 contrib/llvm/lib/Target/SystemZ/MCTargetDesc/Makefile delete mode 100644 contrib/llvm/lib/Target/TargetAsmInfo.cpp delete mode 100644 contrib/llvm/lib/Target/X86/InstPrinter/CMakeLists.txt delete mode 100644 contrib/llvm/lib/Target/X86/InstPrinter/Makefile delete mode 100644 contrib/llvm/lib/Target/X86/MCTargetDesc/CMakeLists.txt delete mode 100644 contrib/llvm/lib/Target/X86/MCTargetDesc/Makefile rename contrib/llvm/lib/Target/X86/{ => MCTargetDesc}/X86AsmBackend.cpp (94%) create mode 100644 contrib/llvm/lib/Target/X86/MCTargetDesc/X86BaseInfo.h rename contrib/llvm/lib/Target/X86/{ => MCTargetDesc}/X86FixupKinds.h (100%) rename contrib/llvm/lib/Target/X86/{ => MCTargetDesc}/X86MCCodeEmitter.cpp (89%) rename contrib/llvm/lib/Target/X86/{ => MCTargetDesc}/X86MachObjectWriter.cpp (99%) delete mode 100644 contrib/llvm/lib/Target/X86/Utils/CMakeLists.txt delete mode 100644 contrib/llvm/lib/Target/X86/Utils/Makefile create mode 100644 contrib/llvm/lib/Target/X86/X86VZeroUpper.cpp delete mode 100644 contrib/llvm/lib/Target/XCore/MCTargetDesc/CMakeLists.txt delete mode 100644 contrib/llvm/lib/Target/XCore/MCTargetDesc/Makefile delete mode 100644 contrib/llvm/lib/Transforms/IPO/LowerSetJmp.cpp create mode 100644 contrib/llvm/lib/Transforms/IPO/PassManagerBuilder.cpp delete mode 100644 contrib/llvm/lib/Transforms/Scalar/TailDuplication.cpp create mode 100644 contrib/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp create mode 100644 contrib/llvm/lib/VMCore/GCOV.cpp create mode 100644 contrib/llvm/tools/clang/include/clang/AST/BaseSubobject.h create mode 100644 contrib/llvm/tools/clang/include/clang/AST/SelectorLocationsKind.h create mode 100644 contrib/llvm/tools/clang/include/clang/AST/VTTBuilder.h create mode 100644 contrib/llvm/tools/clang/include/clang/AST/VTableBuilder.h create mode 100644 contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafety.h create mode 100644 contrib/llvm/tools/clang/include/clang/Basic/LLVM.h create mode 100644 contrib/llvm/tools/clang/include/clang/Basic/LangOptions.def delete mode 100644 contrib/llvm/tools/clang/include/clang/Config/config.h.cmake rename contrib/llvm/tools/clang/include/clang/Frontend/{ChainedDiagnosticClient.h => ChainedDiagnosticConsumer.h} (57%) rename contrib/llvm/tools/clang/include/clang/Frontend/{VerifyDiagnosticsClient.h => VerifyDiagnosticConsumer.h} (74%) create mode 100644 contrib/llvm/tools/clang/include/clang/Lex/ModuleLoader.h create mode 100644 contrib/llvm/tools/clang/include/clang/Sema/MultiInitializer.h create mode 100644 contrib/llvm/tools/clang/include/clang/Sema/SemaFixItUtils.h create mode 100644 contrib/llvm/tools/clang/include/clang/Sema/Weak.h delete mode 100644 contrib/llvm/tools/clang/include/clang/Serialization/ASTSerializationListener.h create mode 100644 contrib/llvm/tools/clang/include/clang/Serialization/ContinuousRangeMap.h create mode 100644 contrib/llvm/tools/clang/include/clang/Serialization/Module.h create mode 100644 contrib/llvm/tools/clang/include/clang/Serialization/ModuleManager.h create mode 100644 contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Checkers/ClangCheckers.h create mode 100644 contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h create mode 100644 contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerOptInfo.h delete mode 100644 contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerProvider.h create mode 100644 contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerRegistry.h rename contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/{PathDiagnosticClients.h => PathDiagnosticConsumers.h} (62%) rename contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/{GRState.h => ProgramState.h} (56%) rename contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/{GRStateTrait.h => ProgramStateTrait.h} (70%) delete mode 100644 contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/TransferFuncs.h delete mode 100644 contrib/llvm/tools/clang/lib/ARCMigrate/CMakeLists.txt delete mode 100644 contrib/llvm/tools/clang/lib/ARCMigrate/Makefile create mode 100644 contrib/llvm/tools/clang/lib/ARCMigrate/PlistReporter.cpp create mode 100644 contrib/llvm/tools/clang/lib/ARCMigrate/TransAPIUses.cpp create mode 100644 contrib/llvm/tools/clang/lib/AST/SelectorLocationsKind.cpp create mode 100644 contrib/llvm/tools/clang/lib/AST/VTTBuilder.cpp create mode 100644 contrib/llvm/tools/clang/lib/AST/VTableBuilder.cpp create mode 100644 contrib/llvm/tools/clang/lib/Analysis/ProgramPoint.cpp create mode 100644 contrib/llvm/tools/clang/lib/Analysis/ThreadSafety.cpp create mode 100644 contrib/llvm/tools/clang/lib/Basic/LangOptions.cpp create mode 100644 contrib/llvm/tools/clang/lib/CodeGen/CGCUDANV.cpp create mode 100644 contrib/llvm/tools/clang/lib/CodeGen/CGCUDARuntime.cpp create mode 100644 contrib/llvm/tools/clang/lib/CodeGen/CGCUDARuntime.h create mode 100644 contrib/llvm/tools/clang/lib/CodeGen/CGOpenCLRuntime.cpp create mode 100644 contrib/llvm/tools/clang/lib/CodeGen/CGOpenCLRuntime.h rename contrib/llvm/tools/clang/lib/Frontend/{VerifyDiagnosticsClient.cpp => VerifyDiagnosticConsumer.cpp} (81%) create mode 100644 contrib/llvm/tools/clang/lib/Headers/stdalign.h create mode 100644 contrib/llvm/tools/clang/lib/Sema/MultiInitializer.cpp rename contrib/llvm/tools/clang/lib/Sema/{SemaCXXCast.cpp => SemaCast.cpp} (78%) create mode 100644 contrib/llvm/tools/clang/lib/Sema/SemaFixItUtils.cpp create mode 100644 contrib/llvm/tools/clang/lib/Serialization/ASTReaderInternals.h create mode 100644 contrib/llvm/tools/clang/lib/Serialization/Module.cpp create mode 100644 contrib/llvm/tools/clang/lib/Serialization/ModuleManager.cpp delete mode 100644 contrib/llvm/tools/clang/lib/StaticAnalyzer/CMakeLists.txt delete mode 100644 contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt create mode 100644 contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ClangCheckers.cpp delete mode 100644 contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ClangSACheckerProvider.cpp delete mode 100644 contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ClangSACheckerProvider.h create mode 100644 contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp delete mode 100644 contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/Makefile create mode 100644 contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/MallocOverflowSecurityChecker.cpp rename contrib/llvm/tools/clang/lib/StaticAnalyzer/{Core/CFRefCount.cpp => Checkers/RetainCountChecker.cpp} (59%) delete mode 100644 contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/BasicStore.cpp delete mode 100644 contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CMakeLists.txt create mode 100644 contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Checker.cpp create mode 100644 contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerRegistry.cpp create mode 100644 contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp rename contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/{CXXExprEngine.cpp => ExprEngineCXX.cpp} (78%) create mode 100644 contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp create mode 100644 contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp delete mode 100644 contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/FlatStore.cpp delete mode 100644 contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/Makefile rename contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/{GRState.cpp => ProgramState.cpp} (65%) delete mode 100644 contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/CMakeLists.txt delete mode 100644 contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/Makefile delete mode 100644 contrib/llvm/tools/clang/lib/StaticAnalyzer/Makefile delete mode 100644 contrib/llvm/tools/clang/lib/StaticAnalyzer/README.txt create mode 100644 contrib/llvm/tools/clang/utils/TableGen/CMakeLists.txt rename contrib/llvm/{ => tools/clang}/utils/TableGen/ClangASTNodesEmitter.cpp (100%) rename contrib/llvm/{ => tools/clang}/utils/TableGen/ClangASTNodesEmitter.h (96%) rename contrib/llvm/{ => tools/clang}/utils/TableGen/ClangAttrEmitter.cpp (93%) rename contrib/llvm/{ => tools/clang}/utils/TableGen/ClangAttrEmitter.h (87%) rename contrib/llvm/{ => tools/clang}/utils/TableGen/ClangDiagnosticsEmitter.cpp (96%) rename contrib/llvm/{ => tools/clang}/utils/TableGen/ClangDiagnosticsEmitter.h (97%) rename contrib/llvm/{ => tools/clang}/utils/TableGen/ClangSACheckersEmitter.cpp (99%) rename contrib/llvm/{ => tools/clang}/utils/TableGen/ClangSACheckersEmitter.h (94%) rename contrib/llvm/{lib/Target/ARM/MCTargetDesc => tools/clang/utils/TableGen}/Makefile (58%) rename contrib/llvm/{ => tools/clang}/utils/TableGen/NeonEmitter.cpp (98%) rename contrib/llvm/{ => tools/clang}/utils/TableGen/NeonEmitter.h (98%) rename contrib/llvm/{ => tools/clang}/utils/TableGen/OptParserEmitter.cpp (99%) rename contrib/llvm/{ => tools/clang}/utils/TableGen/OptParserEmitter.h (96%) create mode 100644 contrib/llvm/tools/clang/utils/TableGen/TableGen.cpp delete mode 100644 contrib/llvm/utils/TableGen/LLVMCConfigurationEmitter.cpp delete mode 100644 contrib/llvm/utils/TableGen/LLVMCConfigurationEmitter.h delete mode 100644 lib/clang/include/ARMGenDecoderTables.inc create mode 100644 lib/clang/include/ARMGenDisassemblerTables.inc create mode 100644 lib/clang/include/clang/Parse/AttrLateParsed.inc create mode 100644 lib/clang/libllvmtablegen/Makefile create mode 100644 usr.bin/clang/clang-tblgen/Makefile diff --git a/Makefile.inc1 b/Makefile.inc1 index a59405095..45639b2b6 100644 --- a/Makefile.inc1 +++ b/Makefile.inc1 @@ -1030,7 +1030,9 @@ _crunchgen= usr.sbin/crunch/crunchgen .if ${MK_CLANG} != "no" _clang_tblgen= \ lib/clang/libllvmsupport \ - usr.bin/clang/tblgen + lib/clang/libllvmtablegen \ + usr.bin/clang/tblgen \ + usr.bin/clang/clang-tblgen .endif .if ${MK_CDDL} != "no" && \ diff --git a/contrib/llvm/include/llvm-c/Core.h b/contrib/llvm/include/llvm-c/Core.h index a4456dd13..d23b91c4e 100644 --- a/contrib/llvm/include/llvm-c/Core.h +++ b/contrib/llvm/include/llvm-c/Core.h @@ -115,7 +115,10 @@ typedef enum { LLVMNoImplicitFloatAttribute = 1<<23, LLVMNakedAttribute = 1<<24, LLVMInlineHintAttribute = 1<<25, - LLVMStackAlignment = 7<<26 + LLVMStackAlignment = 7<<26, + LLVMReturnsTwice = 1 << 29, + LLVMUWTable = 1 << 30, + LLVMNonLazyBind = 1 << 31 } LLVMAttribute; typedef enum { @@ -125,7 +128,7 @@ typedef enum { LLVMSwitch = 3, LLVMIndirectBr = 4, LLVMInvoke = 5, - LLVMUnwind = 6, + /* removed 6 due to API changes */ LLVMUnreachable = 7, /* Standard Binary Operators */ @@ -176,14 +179,26 @@ typedef enum { LLVMPHI = 44, LLVMCall = 45, LLVMSelect = 46, - /* UserOp1 */ - /* UserOp2 */ + LLVMUserOp1 = 47, + LLVMUserOp2 = 48, LLVMVAArg = 49, LLVMExtractElement = 50, LLVMInsertElement = 51, LLVMShuffleVector = 52, LLVMExtractValue = 53, - LLVMInsertValue = 54 + LLVMInsertValue = 54, + + /* Atomic operators */ + LLVMFence = 55, + LLVMAtomicCmpXchg = 56, + LLVMAtomicRMW = 57, + + /* Exception Handling Operators */ + LLVMResume = 58, + LLVMLandingPad = 59, + LLVMUnwind = 60 + + } LLVMOpcode; typedef enum { @@ -274,6 +289,11 @@ typedef enum { LLVMRealPredicateTrue /**< Always true (always folded) */ } LLVMRealPredicate; +typedef enum { + LLVMLandingPadCatch, /**< A catch clause */ + LLVMLandingPadFilter /**< A filter clause */ +} LLVMLandingPadClauseTy; + void LLVMInitializeCore(LLVMPassRegistryRef R); @@ -340,6 +360,7 @@ LLVMContextRef LLVMGetModuleContext(LLVMModuleRef M); /** See llvm::LLVMTypeKind::getTypeID. */ LLVMTypeKind LLVMGetTypeKind(LLVMTypeRef Ty); +LLVMBool LLVMTypeIsSized(LLVMTypeRef Ty); /** See llvm::LLVMType::getContext. */ LLVMContextRef LLVMGetTypeContext(LLVMTypeRef Ty); @@ -388,6 +409,7 @@ LLVMTypeRef LLVMStructTypeInContext(LLVMContextRef C, LLVMTypeRef *ElementTypes, LLVMTypeRef LLVMStructType(LLVMTypeRef *ElementTypes, unsigned ElementCount, LLVMBool Packed); LLVMTypeRef LLVMStructCreateNamed(LLVMContextRef C, const char *Name); +const char *LLVMGetStructName(LLVMTypeRef Ty); void LLVMStructSetBody(LLVMTypeRef StructTy, LLVMTypeRef *ElementTypes, unsigned ElementCount, LLVMBool Packed); @@ -427,8 +449,11 @@ LLVMTypeRef LLVMX86MMXType(void); macro(Argument) \ macro(BasicBlock) \ macro(InlineAsm) \ + macro(MDNode) \ + macro(MDString) \ macro(User) \ macro(Constant) \ + macro(BlockAddress) \ macro(ConstantAggregateZero) \ macro(ConstantArray) \ macro(ConstantExpr) \ @@ -448,29 +473,32 @@ LLVMTypeRef LLVMX86MMXType(void); macro(IntrinsicInst) \ macro(DbgInfoIntrinsic) \ macro(DbgDeclareInst) \ + macro(EHExceptionInst) \ macro(EHSelectorInst) \ macro(MemIntrinsic) \ macro(MemCpyInst) \ macro(MemMoveInst) \ macro(MemSetInst) \ macro(CmpInst) \ - macro(FCmpInst) \ - macro(ICmpInst) \ + macro(FCmpInst) \ + macro(ICmpInst) \ macro(ExtractElementInst) \ macro(GetElementPtrInst) \ macro(InsertElementInst) \ macro(InsertValueInst) \ + macro(LandingPadInst) \ macro(PHINode) \ macro(SelectInst) \ macro(ShuffleVectorInst) \ macro(StoreInst) \ macro(TerminatorInst) \ macro(BranchInst) \ + macro(IndirectBrInst) \ macro(InvokeInst) \ macro(ReturnInst) \ macro(SwitchInst) \ macro(UnreachableInst) \ - macro(UnwindInst) \ + macro(ResumeInst) \ macro(UnaryInstruction) \ macro(AllocaInst) \ macro(CastInst) \ @@ -533,6 +561,11 @@ LLVMValueRef LLVMMDString(const char *Str, unsigned SLen); LLVMValueRef LLVMMDNodeInContext(LLVMContextRef C, LLVMValueRef *Vals, unsigned Count); LLVMValueRef LLVMMDNode(LLVMValueRef *Vals, unsigned Count); +const char *LLVMGetMDString(LLVMValueRef V, unsigned* Len); +int LLVMGetMDNodeNumOperands(LLVMValueRef V); +LLVMValueRef *LLVMGetMDNodeOperand(LLVMValueRef V, unsigned i); +unsigned LLVMGetNamedMetadataNumOperands(LLVMModuleRef M, const char* name); +void LLVMGetNamedMetadataOperands(LLVMModuleRef M, const char* name, LLVMValueRef *Dest); /* Operations on scalar constants */ LLVMValueRef LLVMConstInt(LLVMTypeRef IntTy, unsigned long long N, @@ -728,6 +761,7 @@ LLVMValueRef LLVMBasicBlockAsValue(LLVMBasicBlockRef BB); LLVMBool LLVMValueIsBasicBlock(LLVMValueRef Val); LLVMBasicBlockRef LLVMValueAsBasicBlock(LLVMValueRef Val); LLVMValueRef LLVMGetBasicBlockParent(LLVMBasicBlockRef BB); +LLVMValueRef LLVMGetBasicBlockTerminator(LLVMBasicBlockRef BB); unsigned LLVMCountBasicBlocks(LLVMValueRef Fn); void LLVMGetBasicBlocks(LLVMValueRef Fn, LLVMBasicBlockRef *BasicBlocks); LLVMBasicBlockRef LLVMGetFirstBasicBlock(LLVMValueRef Fn); @@ -747,16 +781,21 @@ LLVMBasicBlockRef LLVMAppendBasicBlock(LLVMValueRef Fn, const char *Name); LLVMBasicBlockRef LLVMInsertBasicBlock(LLVMBasicBlockRef InsertBeforeBB, const char *Name); void LLVMDeleteBasicBlock(LLVMBasicBlockRef BB); +void LLVMRemoveBasicBlockFromParent(LLVMBasicBlockRef BB); void LLVMMoveBasicBlockBefore(LLVMBasicBlockRef BB, LLVMBasicBlockRef MovePos); void LLVMMoveBasicBlockAfter(LLVMBasicBlockRef BB, LLVMBasicBlockRef MovePos); -/* Operations on instructions */ -LLVMBasicBlockRef LLVMGetInstructionParent(LLVMValueRef Inst); LLVMValueRef LLVMGetFirstInstruction(LLVMBasicBlockRef BB); LLVMValueRef LLVMGetLastInstruction(LLVMBasicBlockRef BB); + +/* Operations on instructions */ +LLVMBasicBlockRef LLVMGetInstructionParent(LLVMValueRef Inst); LLVMValueRef LLVMGetNextInstruction(LLVMValueRef Inst); LLVMValueRef LLVMGetPreviousInstruction(LLVMValueRef Inst); +void LLVMInstructionEraseFromParent(LLVMValueRef Inst); +LLVMOpcode LLVMGetInstructionOpcode(LLVMValueRef Inst); +LLVMIntPredicate LLVMGetICmpPredicate(LLVMValueRef Inst); /* Operations on call sites */ void LLVMSetInstructionCallConv(LLVMValueRef Instr, unsigned CC); @@ -771,6 +810,9 @@ void LLVMSetInstrParamAlignment(LLVMValueRef Instr, unsigned index, LLVMBool LLVMIsTailCall(LLVMValueRef CallInst); void LLVMSetTailCall(LLVMValueRef CallInst, LLVMBool IsTailCall); +/* Operations on switch instructions (only) */ +LLVMBasicBlockRef LLVMGetSwitchDefaultDest(LLVMValueRef SwitchInstr); + /* Operations on phi nodes */ void LLVMAddIncoming(LLVMValueRef PhiNode, LLVMValueRef *IncomingValues, LLVMBasicBlockRef *IncomingBlocks, unsigned Count); @@ -818,7 +860,10 @@ LLVMValueRef LLVMBuildInvoke(LLVMBuilderRef, LLVMValueRef Fn, LLVMValueRef *Args, unsigned NumArgs, LLVMBasicBlockRef Then, LLVMBasicBlockRef Catch, const char *Name); -LLVMValueRef LLVMBuildUnwind(LLVMBuilderRef); +LLVMValueRef LLVMBuildLandingPad(LLVMBuilderRef B, LLVMTypeRef Ty, + LLVMValueRef PersFn, unsigned NumClauses, + const char *Name); +LLVMValueRef LLVMBuildResume(LLVMBuilderRef B, LLVMValueRef Exn); LLVMValueRef LLVMBuildUnreachable(LLVMBuilderRef); /* Add a case to the switch instruction */ @@ -828,6 +873,12 @@ void LLVMAddCase(LLVMValueRef Switch, LLVMValueRef OnVal, /* Add a destination to the indirectbr instruction */ void LLVMAddDestination(LLVMValueRef IndirectBr, LLVMBasicBlockRef Dest); +/* Add a catch or filter clause to the landingpad instruction */ +void LLVMAddClause(LLVMValueRef LandingPad, LLVMValueRef ClauseVal); + +/* Set the 'cleanup' flag in the landingpad instruction */ +void LLVMSetCleanup(LLVMValueRef LandingPad, LLVMBool Val); + /* Arithmetic */ LLVMValueRef LLVMBuildAdd(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, const char *Name); @@ -1136,7 +1187,7 @@ namespace llvm { return reinterpret_cast(Tys); } - inline LLVMTypeRef *wrap(const Type **Tys) { + inline LLVMTypeRef *wrap(Type **Tys) { return reinterpret_cast(const_cast(Tys)); } diff --git a/contrib/llvm/include/llvm-c/Disassembler.h b/contrib/llvm/include/llvm-c/Disassembler.h index 3a3eb235e..bf2f2767c 100644 --- a/contrib/llvm/include/llvm-c/Disassembler.h +++ b/contrib/llvm/include/llvm-c/Disassembler.h @@ -66,7 +66,7 @@ typedef int (*LLVMOpInfoCallback)(void *DisInfo, uint64_t PC, */ struct LLVMOpInfoSymbol1 { uint64_t Present; /* 1 if this symbol is present */ - char *Name; /* symbol name if not NULL */ + const char *Name; /* symbol name if not NULL */ uint64_t Value; /* symbol value if name is NULL */ }; @@ -93,11 +93,35 @@ struct LLVMOpInfo1 { * disassembler for things like adding a comment for a PC plus a constant * offset load instruction to use a symbol name instead of a load address value. * It is passed the block information is saved when the disassembler context is - * created and a value of a symbol to look up. If no symbol is found NULL is - * returned. + * created and the ReferenceValue to look up as a symbol. If no symbol is found + * for the ReferenceValue NULL is returned. The ReferenceType of the + * instruction is passed indirectly as is the PC of the instruction in + * ReferencePC. If the output reference can be determined its type is returned + * indirectly in ReferenceType along with ReferenceName if any, or that is set + * to NULL. */ typedef const char *(*LLVMSymbolLookupCallback)(void *DisInfo, - uint64_t SymbolValue); + uint64_t ReferenceValue, + uint64_t *ReferenceType, + uint64_t ReferencePC, + const char **ReferenceName); +/** + * The reference types on input and output. + */ +/* No input reference type or no output reference type. */ +#define LLVMDisassembler_ReferenceType_InOut_None 0 + +/* The input reference is from a branch instruction. */ +#define LLVMDisassembler_ReferenceType_In_Branch 1 +/* The input reference is from a PC relative load instruction. */ +#define LLVMDisassembler_ReferenceType_In_PCrel_Load 2 + +/* The output reference is to as symbol stub. */ +#define LLVMDisassembler_ReferenceType_Out_SymbolStub 1 +/* The output reference is to a symbol address in a literal pool. */ +#define LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr 2 +/* The output reference is to a cstring address in a literal pool. */ +#define LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr 3 #ifdef __cplusplus extern "C" { diff --git a/contrib/llvm/include/llvm-c/Object.h b/contrib/llvm/include/llvm-c/Object.h index 6e72b5946..7b1cf717f 100644 --- a/contrib/llvm/include/llvm-c/Object.h +++ b/contrib/llvm/include/llvm-c/Object.h @@ -59,14 +59,14 @@ namespace llvm { return reinterpret_cast(const_cast(OF)); } - inline ObjectFile::section_iterator *unwrap(LLVMSectionIteratorRef SI) { - return reinterpret_cast(SI); + inline section_iterator *unwrap(LLVMSectionIteratorRef SI) { + return reinterpret_cast(SI); } inline LLVMSectionIteratorRef - wrap(const ObjectFile::section_iterator *SI) { + wrap(const section_iterator *SI) { return reinterpret_cast - (const_cast(SI)); + (const_cast(SI)); } } } diff --git a/contrib/llvm/include/llvm-c/Target.h b/contrib/llvm/include/llvm-c/Target.h index d21644011..7afaef15c 100644 --- a/contrib/llvm/include/llvm-c/Target.h +++ b/contrib/llvm/include/llvm-c/Target.h @@ -29,6 +29,7 @@ extern "C" { 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. */ @@ -42,7 +43,7 @@ typedef struct LLVMStructLayout *LLVMStructLayoutRef; #undef LLVM_TARGET /* Explicit undef to make SWIG happier */ #define LLVM_TARGET(TargetName) \ - void LLVMInitialize##TargetName##MCAsmInfo(void); + void LLVMInitialize##TargetName##TargetMC(void); #include "llvm/Config/Targets.def" #undef LLVM_TARGET /* Explicit undef to make SWIG happier */ @@ -72,7 +73,7 @@ static inline LLVMBool LLVMInitializeNativeTarget(void) { #ifdef LLVM_NATIVE_TARGET LLVM_NATIVE_TARGETINFO(); LLVM_NATIVE_TARGET(); - LLVM_NATIVE_MCASMINFO(); + LLVM_NATIVE_TARGETMC(); return 0; #else return 1; @@ -90,6 +91,11 @@ LLVMTargetDataRef LLVMCreateTargetData(const char *StringRep); See the method llvm::PassManagerBase::add. */ void LLVMAddTargetData(LLVMTargetDataRef, LLVMPassManagerRef); +/** 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); + /** Converts target data to a target layout string. The string must be disposed with LLVMDisposeMessage. See the constructor llvm::TargetData::TargetData. */ @@ -157,6 +163,7 @@ void LLVMDisposeTargetData(LLVMTargetDataRef); namespace llvm { class TargetData; + class TargetLibraryInfo; inline TargetData *unwrap(LLVMTargetDataRef P) { return reinterpret_cast(P); @@ -165,6 +172,15 @@ namespace llvm { inline LLVMTargetDataRef wrap(const TargetData *P) { return reinterpret_cast(const_cast(P)); } + + inline TargetLibraryInfo *unwrap(LLVMTargetLibraryInfoRef P) { + return reinterpret_cast(P); + } + + inline LLVMTargetLibraryInfoRef wrap(const TargetLibraryInfo *P) { + TargetLibraryInfo *X = const_cast(P); + return reinterpret_cast(X); + } } #endif /* defined(__cplusplus) */ diff --git a/contrib/llvm/include/llvm-c/Transforms/IPO.h b/contrib/llvm/include/llvm-c/Transforms/IPO.h index 89b129869..710bebe59 100644 --- a/contrib/llvm/include/llvm-c/Transforms/IPO.h +++ b/contrib/llvm/include/llvm-c/Transforms/IPO.h @@ -36,6 +36,9 @@ void LLVMAddFunctionAttrsPass(LLVMPassManagerRef PM); /** See llvm::createFunctionInliningPass function. */ void LLVMAddFunctionInliningPass(LLVMPassManagerRef PM); +/** See llvm::createAlwaysInlinerPass function. */ +void LLVMAddAlwaysInlinerPass(LLVMPassManagerRef PM); + /** See llvm::createGlobalDCEPass function. */ void LLVMAddGlobalDCEPass(LLVMPassManagerRef PM); @@ -45,9 +48,6 @@ void LLVMAddGlobalOptimizerPass(LLVMPassManagerRef PM); /** See llvm::createIPConstantPropagationPass function. */ void LLVMAddIPConstantPropagationPass(LLVMPassManagerRef PM); -/** See llvm::createLowerSetJmpPass function. */ -void LLVMAddLowerSetJmpPass(LLVMPassManagerRef PM); - /** See llvm::createPruneEHPass function. */ void LLVMAddPruneEHPass(LLVMPassManagerRef PM); @@ -57,9 +57,6 @@ void LLVMAddIPSCCPPass(LLVMPassManagerRef PM); /** See llvm::createInternalizePass function. */ void LLVMAddInternalizePass(LLVMPassManagerRef, unsigned AllButMain); -// FIXME: Remove in LLVM 3.0. -void LLVMAddRaiseAllocationsPass(LLVMPassManagerRef PM); - /** See llvm::createStripDeadPrototypesPass function. */ void LLVMAddStripDeadPrototypesPass(LLVMPassManagerRef PM); diff --git a/contrib/llvm/include/llvm-c/Transforms/PassManagerBuilder.h b/contrib/llvm/include/llvm-c/Transforms/PassManagerBuilder.h new file mode 100644 index 000000000..fa722c958 --- /dev/null +++ b/contrib/llvm/include/llvm-c/Transforms/PassManagerBuilder.h @@ -0,0 +1,90 @@ +/*===-- llvm-c/Transform/PassManagerBuilder.h - PMB 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 header declares the C interface to the PassManagerBuilder class. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_C_PASSMANAGERBUILDER +#define LLVM_C_PASSMANAGERBUILDER + +#include "llvm-c/Core.h" + +typedef struct LLVMOpaquePassManagerBuilder *LLVMPassManagerBuilderRef; + +#ifdef __cplusplus +#include "llvm/Transforms/IPO/PassManagerBuilder.h" +extern "C" { +#endif + +/** See llvm::PassManagerBuilder. */ +LLVMPassManagerBuilderRef LLVMPassManagerBuilderCreate(void); +void LLVMPassManagerBuilderDispose(LLVMPassManagerBuilderRef PMB); + +/** See llvm::PassManagerBuilder::OptLevel. */ +void +LLVMPassManagerBuilderSetOptLevel(LLVMPassManagerBuilderRef PMB, + unsigned OptLevel); + +/** See llvm::PassManagerBuilder::SizeLevel. */ +void +LLVMPassManagerBuilderSetSizeLevel(LLVMPassManagerBuilderRef PMB, + unsigned SizeLevel); + +/** See llvm::PassManagerBuilder::DisableUnitAtATime. */ +void +LLVMPassManagerBuilderSetDisableUnitAtATime(LLVMPassManagerBuilderRef PMB, + LLVMBool Value); + +/** See llvm::PassManagerBuilder::DisableUnrollLoops. */ +void +LLVMPassManagerBuilderSetDisableUnrollLoops(LLVMPassManagerBuilderRef PMB, + LLVMBool Value); + +/** See llvm::PassManagerBuilder::DisableSimplifyLibCalls */ +void +LLVMPassManagerBuilderSetDisableSimplifyLibCalls(LLVMPassManagerBuilderRef PMB, + LLVMBool Value); + +/** See llvm::PassManagerBuilder::Inliner. */ +void +LLVMPassManagerBuilderUseInlinerWithThreshold(LLVMPassManagerBuilderRef PMB, + unsigned Threshold); + +/** See llvm::PassManagerBuilder::populateFunctionPassManager. */ +void +LLVMPassManagerBuilderPopulateFunctionPassManager(LLVMPassManagerBuilderRef PMB, + LLVMPassManagerRef PM); + +/** See llvm::PassManagerBuilder::populateModulePassManager. */ +void +LLVMPassManagerBuilderPopulateModulePassManager(LLVMPassManagerBuilderRef PMB, + LLVMPassManagerRef PM); + +/** See llvm::PassManagerBuilder::populateLTOPassManager. */ +void LLVMPassManagerBuilderPopulateLTOPassManager(LLVMPassManagerBuilderRef PMB, + LLVMPassManagerRef PM, + bool Internalize, + bool RunInliner); + +#ifdef __cplusplus +} + +namespace llvm { + inline PassManagerBuilder *unwrap(LLVMPassManagerBuilderRef P) { + return reinterpret_cast(P); + } + + inline LLVMPassManagerBuilderRef wrap(PassManagerBuilder *P) { + return reinterpret_cast(P); + } +} +#endif + +#endif diff --git a/contrib/llvm/include/llvm-c/Transforms/Scalar.h b/contrib/llvm/include/llvm-c/Transforms/Scalar.h index cf8d71f5d..6015ef90e 100644 --- a/contrib/llvm/include/llvm-c/Transforms/Scalar.h +++ b/contrib/llvm/include/llvm-c/Transforms/Scalar.h @@ -107,6 +107,9 @@ void LLVMAddCorrelatedValuePropagationPass(LLVMPassManagerRef PM); /** See llvm::createEarlyCSEPass function */ void LLVMAddEarlyCSEPass(LLVMPassManagerRef PM); +/** See llvm::createLowerExpectIntrinsicPass function */ +void LLVMAddLowerExpectIntrinsicPass(LLVMPassManagerRef PM); + /** See llvm::createTypeBasedAliasAnalysisPass function */ void LLVMAddTypeBasedAliasAnalysisPass(LLVMPassManagerRef PM); diff --git a/contrib/llvm/include/llvm/ADT/APInt.h b/contrib/llvm/include/llvm/ADT/APInt.h index e68e579cd..707e0dbb6 100644 --- a/contrib/llvm/include/llvm/ADT/APInt.h +++ b/contrib/llvm/include/llvm/ADT/APInt.h @@ -15,6 +15,7 @@ #ifndef LLVM_APINT_H #define LLVM_APINT_H +#include "llvm/ADT/ArrayRef.h" #include "llvm/Support/MathExtras.h" #include #include @@ -160,7 +161,7 @@ class APInt { /// not assume that the string is well-formed and (2) grows the /// result to hold the input. /// - /// @param radix 2, 8, 10, or 16 + /// @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); @@ -176,6 +177,9 @@ class APInt { /// out-of-line slow case for inline constructor void initSlowCase(unsigned numBits, uint64_t val, bool isSigned); + /// shared code between two array constructors + void initFromArray(ArrayRef array); + /// out-of-line slow case for inline copy constructor void initSlowCase(const APInt& that); @@ -230,19 +234,26 @@ public: clearUnusedBits(); } - /// Note that numWords can be smaller or larger than the corresponding bit - /// width but any extraneous bits will be dropped. + /// 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 numWords the number of words in bigVal /// @param bigVal a sequence of words to form the initial value of the APInt /// @brief Construct an APInt of numBits width, initialized as bigVal[]. + 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. + /// + /// If this overload is ever deleted, care should be taken to prevent calls + /// from being incorrectly captured by the APInt(unsigned, uint64_t, bool) + /// constructor. APInt(unsigned numBits, unsigned numWords, const uint64_t bigVal[]); /// This constructor interprets the string \arg 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 and 16. It is an error for the value implied by the string to - /// require more bits than numBits. + /// 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 @@ -342,7 +353,8 @@ public: if (isSingleWord()) return isUIntN(N, VAL); - return APInt(N, getNumWords(), pVal).zext(getBitWidth()) == (*this); + return APInt(N, makeArrayRef(pVal, getNumWords())).zext(getBitWidth()) + == (*this); } /// @brief Check if this APInt has an N-bits signed integer value. @@ -1245,13 +1257,13 @@ public: bool formatAsCLiteral = false) const; /// Considers the APInt to be unsigned and converts it into a string in the - /// radix given. The radix can be 2, 8, 10 or 16. + /// radix given. The radix can be 2, 8, 10 16, or 36. void toStringUnsigned(SmallVectorImpl &Str, unsigned Radix = 10) const { toString(Str, Radix, false, false); } /// Considers the APInt to be signed and converts it into a string in the - /// radix given. The radix can be 2, 8, 10 or 16. + /// radix given. The radix can be 2, 8, 10, 16, or 36. void toStringSigned(SmallVectorImpl &Str, unsigned Radix = 10) const { toString(Str, Radix, true, false); } diff --git a/contrib/llvm/include/llvm/ADT/ArrayRef.h b/contrib/llvm/include/llvm/ADT/ArrayRef.h index 6db866e8c..33a8c651b 100644 --- a/contrib/llvm/include/llvm/ADT/ArrayRef.h +++ b/contrib/llvm/include/llvm/ADT/ArrayRef.h @@ -147,7 +147,53 @@ namespace llvm { /// @} }; - + + /// @name ArrayRef Convenience constructors + /// @{ + + /// Construct an ArrayRef from a single element. + template + ArrayRef makeArrayRef(const T &OneElt) { + return OneElt; + } + + /// Construct an ArrayRef from a pointer and length. + template + ArrayRef makeArrayRef(const T *data, size_t length) { + return ArrayRef(data, length); + } + + /// Construct an ArrayRef from a range. + template + ArrayRef makeArrayRef(const T *begin, const T *end) { + return ArrayRef(begin, end); + } + + /// Construct an ArrayRef from a SmallVector. + template + ArrayRef makeArrayRef(const SmallVectorImpl &Vec) { + return Vec; + } + + /// Construct an ArrayRef from a SmallVector. + template + ArrayRef makeArrayRef(const SmallVector &Vec) { + return Vec; + } + + /// Construct an ArrayRef from a std::vector. + template + ArrayRef makeArrayRef(const std::vector &Vec) { + return Vec; + } + + /// Construct an ArrayRef from a C array. + template + ArrayRef makeArrayRef(const T (&Arr)[N]) { + return ArrayRef(Arr); + } + + /// @} /// @name ArrayRef Comparison Operators /// @{ diff --git a/contrib/llvm/include/llvm/ADT/DenseMap.h b/contrib/llvm/include/llvm/ADT/DenseMap.h index 0f1cfebc3..e70cacf3c 100644 --- a/contrib/llvm/include/llvm/ADT/DenseMap.h +++ b/contrib/llvm/include/llvm/ADT/DenseMap.h @@ -540,6 +540,12 @@ private: ++Ptr; } }; + +template +static inline size_t +capacity_in_bytes(const DenseMap &X) { + return X.getMemorySize(); +} } // end namespace llvm diff --git a/contrib/llvm/include/llvm/ADT/DenseMapInfo.h b/contrib/llvm/include/llvm/ADT/DenseMapInfo.h index 744b6f4ae..df4084e6f 100644 --- a/contrib/llvm/include/llvm/ADT/DenseMapInfo.h +++ b/contrib/llvm/include/llvm/ADT/DenseMapInfo.h @@ -51,7 +51,7 @@ struct DenseMapInfo { template<> struct DenseMapInfo { static inline char getEmptyKey() { return ~0; } static inline char getTombstoneKey() { return ~0 - 1; } - static unsigned getHashValue(const char& Val) { return Val * 37; } + static unsigned getHashValue(const char& Val) { return Val * 37U; } static bool isEqual(const char &LHS, const char &RHS) { return LHS == RHS; } @@ -61,7 +61,7 @@ template<> struct DenseMapInfo { template<> struct DenseMapInfo { static inline unsigned getEmptyKey() { return ~0; } static inline unsigned getTombstoneKey() { return ~0U - 1; } - static unsigned getHashValue(const unsigned& Val) { return Val * 37; } + static unsigned getHashValue(const unsigned& Val) { return Val * 37U; } static bool isEqual(const unsigned& LHS, const unsigned& RHS) { return LHS == RHS; } @@ -96,7 +96,7 @@ template<> struct DenseMapInfo { template<> struct DenseMapInfo { static inline int getEmptyKey() { return 0x7fffffff; } static inline int getTombstoneKey() { return -0x7fffffff - 1; } - static unsigned getHashValue(const int& Val) { return (unsigned)(Val * 37); } + static unsigned getHashValue(const int& Val) { return (unsigned)(Val * 37U); } static bool isEqual(const int& LHS, const int& RHS) { return LHS == RHS; } @@ -109,7 +109,7 @@ template<> struct DenseMapInfo { } static inline long getTombstoneKey() { return getEmptyKey() - 1L; } static unsigned getHashValue(const long& Val) { - return (unsigned)(Val * 37L); + return (unsigned)(Val * 37UL); } static bool isEqual(const long& LHS, const long& RHS) { return LHS == RHS; @@ -121,7 +121,7 @@ template<> struct DenseMapInfo { static inline long long getEmptyKey() { return 0x7fffffffffffffffLL; } static inline long long getTombstoneKey() { return -0x7fffffffffffffffLL-1; } static unsigned getHashValue(const long long& Val) { - return (unsigned)(Val * 37LL); + return (unsigned)(Val * 37ULL); } static bool isEqual(const long long& LHS, const long long& RHS) { @@ -142,7 +142,7 @@ struct DenseMapInfo > { } static inline Pair getTombstoneKey() { return std::make_pair(FirstInfo::getTombstoneKey(), - SecondInfo::getEmptyKey()); + SecondInfo::getTombstoneKey()); } static unsigned getHashValue(const Pair& PairVal) { uint64_t key = (uint64_t)FirstInfo::getHashValue(PairVal.first) << 32 @@ -158,7 +158,7 @@ struct DenseMapInfo > { return (unsigned)key; } static bool isEqual(const Pair &LHS, const Pair &RHS) { - return FirstInfo::isEqual(LHS.first, RHS.first) && + return FirstInfo::isEqual(LHS.first, RHS.first) && SecondInfo::isEqual(LHS.second, RHS.second); } }; diff --git a/contrib/llvm/include/llvm/ADT/DenseSet.h b/contrib/llvm/include/llvm/ADT/DenseSet.h index 67321f539..8ab9a3320 100644 --- a/contrib/llvm/include/llvm/ADT/DenseSet.h +++ b/contrib/llvm/include/llvm/ADT/DenseSet.h @@ -28,7 +28,7 @@ class DenseSet { MapTy TheMap; public: DenseSet(const DenseSet &Other) : TheMap(Other.TheMap) {} - explicit DenseSet(unsigned NumInitBuckets = 64) : TheMap(NumInitBuckets) {} + explicit DenseSet(unsigned NumInitBuckets = 0) : TheMap(NumInitBuckets) {} bool empty() const { return TheMap.empty(); } unsigned size() const { return TheMap.size(); } diff --git a/contrib/llvm/include/llvm/ADT/ImmutableMap.h b/contrib/llvm/include/llvm/ADT/ImmutableMap.h index d6cce7ccf..8346ffabf 100644 --- a/contrib/llvm/include/llvm/ADT/ImmutableMap.h +++ b/contrib/llvm/include/llvm/ADT/ImmutableMap.h @@ -117,6 +117,10 @@ public: return ImmutableMap(Canonicalize ? F.getCanonicalTree(T): T); } + typename TreeTy::Factory *getTreeFactory() const { + return const_cast(&F); + } + private: Factory(const Factory& RHS); // DO NOT IMPLEMENT void operator=(const Factory& RHS); // DO NOT IMPLEMENT @@ -256,6 +260,159 @@ public: } }; +// NOTE: This will possibly become the new implementation of ImmutableMap some day. +template > +class ImmutableMapRef { +public: + typedef typename ValInfo::value_type value_type; + typedef typename ValInfo::value_type_ref value_type_ref; + typedef typename ValInfo::key_type key_type; + typedef typename ValInfo::key_type_ref key_type_ref; + typedef typename ValInfo::data_type data_type; + typedef typename ValInfo::data_type_ref data_type_ref; + typedef ImutAVLTree TreeTy; + typedef typename TreeTy::Factory FactoryTy; + +protected: + TreeTy *Root; + FactoryTy *Factory; + +public: + /// Constructs a map from a pointer to a tree root. In general one + /// should use a Factory object to create maps instead of directly + /// invoking the constructor, but there are cases where make this + /// constructor public is useful. + explicit ImmutableMapRef(const TreeTy* R, FactoryTy *F) + : Root(const_cast(R)), + Factory(F) { + if (Root) { Root->retain(); } + } + + ImmutableMapRef(const ImmutableMapRef &X) + : Root(X.Root), + Factory(X.Factory) { + if (Root) { Root->retain(); } + } + + ImmutableMapRef &operator=(const ImmutableMapRef &X) { + if (Root != X.Root) { + if (X.Root) + X.Root->retain(); + + if (Root) + Root->release(); + + Root = X.Root; + Factory = X.Factory; + } + return *this; + } + + ~ImmutableMapRef() { + if (Root) + Root->release(); + } + + static inline ImmutableMapRef getEmptyMap(FactoryTy *F) { + return ImmutableMapRef(0, F); + } + + ImmutableMapRef add(key_type_ref K, data_type_ref D) { + TreeTy *NewT = Factory->add(Root, std::pair(K, D)); + return ImmutableMapRef(NewT, Factory); + } + + ImmutableMapRef remove(key_type_ref K) { + TreeTy *NewT = Factory->remove(Root, K); + return ImmutableMapRef(NewT, Factory); + } + + bool contains(key_type_ref K) const { + return Root ? Root->contains(K) : false; + } + + ImmutableMap asImmutableMap() const { + return ImmutableMap(Factory->getCanonicalTree(Root)); + } + + bool operator==(const ImmutableMapRef &RHS) const { + return Root && RHS.Root ? Root->isEqual(*RHS.Root) : Root == RHS.Root; + } + + bool operator!=(const ImmutableMapRef &RHS) const { + return Root && RHS.Root ? Root->isNotEqual(*RHS.Root) : Root != RHS.Root; + } + + bool isEmpty() const { return !Root; } + + //===--------------------------------------------------===// + // For testing. + //===--------------------------------------------------===// + + void verify() const { if (Root) Root->verify(); } + + //===--------------------------------------------------===// + // Iterators. + //===--------------------------------------------------===// + + class iterator { + typename TreeTy::iterator itr; + + iterator() {} + iterator(TreeTy* t) : itr(t) {} + friend class ImmutableMapRef; + + public: + value_type_ref operator*() const { return itr->getValue(); } + value_type* operator->() const { return &itr->getValue(); } + + key_type_ref getKey() const { return itr->getValue().first; } + data_type_ref getData() const { return itr->getValue().second; } + + + iterator& operator++() { ++itr; return *this; } + iterator operator++(int) { iterator tmp(*this); ++itr; return tmp; } + iterator& operator--() { --itr; return *this; } + iterator operator--(int) { iterator tmp(*this); --itr; return tmp; } + bool operator==(const iterator& RHS) const { return RHS.itr == itr; } + bool operator!=(const iterator& RHS) const { return RHS.itr != itr; } + }; + + iterator begin() const { return iterator(Root); } + iterator end() const { return iterator(); } + + data_type* lookup(key_type_ref K) const { + if (Root) { + TreeTy* T = Root->find(K); + if (T) return &T->getValue().second; + } + + return 0; + } + + /// getMaxElement - Returns the pair in the ImmutableMap for + /// which key is the highest in the ordering of keys in the map. This + /// method returns NULL if the map is empty. + value_type* getMaxElement() const { + return Root ? &(Root->getMaxElement()->getValue()) : 0; + } + + //===--------------------------------------------------===// + // Utility methods. + //===--------------------------------------------------===// + + unsigned getHeight() const { return Root ? Root->getHeight() : 0; } + + static inline void Profile(FoldingSetNodeID& ID, const ImmutableMapRef &M) { + ID.AddPointer(M.Root); + } + + inline void Profile(FoldingSetNodeID& ID) const { + return Profile(ID, *this); + } +}; + } // end namespace llvm #endif diff --git a/contrib/llvm/include/llvm/ADT/ImmutableSet.h b/contrib/llvm/include/llvm/ADT/ImmutableSet.h index 3ca910ce9..d597a7c9b 100644 --- a/contrib/llvm/include/llvm/ADT/ImmutableSet.h +++ b/contrib/llvm/include/llvm/ADT/ImmutableSet.h @@ -997,6 +997,10 @@ public: BumpPtrAllocator& getAllocator() { return F.getAllocator(); } + typename TreeTy::Factory *getTreeFactory() const { + return const_cast(&F); + } + private: Factory(const Factory& RHS); // DO NOT IMPLEMENT void operator=(const Factory& RHS); // DO NOT IMPLEMENT @@ -1021,6 +1025,10 @@ public: if (Root) { Root->retain(); } return Root; } + + TreeTy *getRootWithoutRetain() const { + return Root; + } /// isEmpty - Return true if the set contains no elements. bool isEmpty() const { return !Root; } @@ -1078,6 +1086,132 @@ public: void validateTree() const { if (Root) Root->validateTree(); } }; + +// NOTE: This may some day replace the current ImmutableSet. +template > +class ImmutableSetRef { +public: + typedef typename ValInfo::value_type value_type; + typedef typename ValInfo::value_type_ref value_type_ref; + typedef ImutAVLTree TreeTy; + typedef typename TreeTy::Factory FactoryTy; + +private: + TreeTy *Root; + FactoryTy *Factory; + +public: + /// Constructs a set from a pointer to a tree root. In general one + /// should use a Factory object to create sets instead of directly + /// invoking the constructor, but there are cases where make this + /// constructor public is useful. + explicit ImmutableSetRef(TreeTy* R, FactoryTy *F) + : Root(R), + Factory(F) { + if (Root) { Root->retain(); } + } + ImmutableSetRef(const ImmutableSetRef &X) + : Root(X.Root), + Factory(X.Factory) { + if (Root) { Root->retain(); } + } + ImmutableSetRef &operator=(const ImmutableSetRef &X) { + if (Root != X.Root) { + if (X.Root) { X.Root->retain(); } + if (Root) { Root->release(); } + Root = X.Root; + Factory = X.Factory; + } + return *this; + } + ~ImmutableSetRef() { + if (Root) { Root->release(); } + } + + static inline ImmutableSetRef getEmptySet(FactoryTy *F) { + return ImmutableSetRef(0, F); + } + + ImmutableSetRef add(value_type_ref V) { + return ImmutableSetRef(Factory->add(Root, V), Factory); + } + + ImmutableSetRef remove(value_type_ref V) { + return ImmutableSetRef(Factory->remove(Root, V), Factory); + } + + /// Returns true if the set contains the specified value. + bool contains(value_type_ref V) const { + return Root ? Root->contains(V) : false; + } + + ImmutableSet asImmutableSet(bool canonicalize = true) const { + return ImmutableSet(canonicalize ? + Factory->getCanonicalTree(Root) : Root); + } + + TreeTy *getRootWithoutRetain() const { + return Root; + } + + bool operator==(const ImmutableSetRef &RHS) const { + return Root && RHS.Root ? Root->isEqual(*RHS.Root) : Root == RHS.Root; + } + + bool operator!=(const ImmutableSetRef &RHS) const { + return Root && RHS.Root ? Root->isNotEqual(*RHS.Root) : Root != RHS.Root; + } + + /// isEmpty - Return true if the set contains no elements. + bool isEmpty() const { return !Root; } + + /// isSingleton - Return true if the set contains exactly one element. + /// This method runs in constant time. + bool isSingleton() const { return getHeight() == 1; } + + //===--------------------------------------------------===// + // Iterators. + //===--------------------------------------------------===// + + class iterator { + typename TreeTy::iterator itr; + iterator(TreeTy* t) : itr(t) {} + friend class ImmutableSetRef; + public: + iterator() {} + inline value_type_ref operator*() const { return itr->getValue(); } + inline iterator& operator++() { ++itr; return *this; } + inline iterator operator++(int) { iterator tmp(*this); ++itr; return tmp; } + inline iterator& operator--() { --itr; return *this; } + inline iterator operator--(int) { iterator tmp(*this); --itr; return tmp; } + inline bool operator==(const iterator& RHS) const { return RHS.itr == itr; } + inline bool operator!=(const iterator& RHS) const { return RHS.itr != itr; } + inline value_type *operator->() const { return &(operator*()); } + }; + + iterator begin() const { return iterator(Root); } + iterator end() const { return iterator(); } + + //===--------------------------------------------------===// + // Utility methods. + //===--------------------------------------------------===// + + unsigned getHeight() const { return Root ? Root->getHeight() : 0; } + + static inline void Profile(FoldingSetNodeID& ID, const ImmutableSetRef& S) { + ID.AddPointer(S.Root); + } + + inline void Profile(FoldingSetNodeID& ID) const { + return Profile(ID,*this); + } + + //===--------------------------------------------------===// + // For testing. + //===--------------------------------------------------===// + + void validateTree() const { if (Root) Root->validateTree(); } +}; } // end namespace llvm diff --git a/contrib/llvm/include/llvm/ADT/IntervalMap.h b/contrib/llvm/include/llvm/ADT/IntervalMap.h index f28ebf3b9..1230e8f5f 100644 --- a/contrib/llvm/include/llvm/ADT/IntervalMap.h +++ b/contrib/llvm/include/llvm/ADT/IntervalMap.h @@ -1335,6 +1335,9 @@ public: /// valid - Return true if the current position is valid, false for end(). bool valid() const { return path.valid(); } + /// atBegin - Return true if the current position is the first map entry. + bool atBegin() const { return path.atBegin(); } + /// start - Return the beginning of the current interval. const KeyT &start() const { return unsafeStart(); } diff --git a/contrib/llvm/include/llvm/ADT/PointerUnion.h b/contrib/llvm/include/llvm/ADT/PointerUnion.h index 13b98cef0..487096a17 100644 --- a/contrib/llvm/include/llvm/ADT/PointerUnion.h +++ b/contrib/llvm/include/llvm/ADT/PointerUnion.h @@ -108,7 +108,11 @@ 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.getPointer() == 0; } + bool isNull() const { + // Convert from the void* to one of the pointer types, to make sure that + // we recursively strip off low bits if we have a nested PointerUnion. + return !PointerLikeTypeTraits::getFromVoidPointer(Val.getPointer()); + } operator bool() const { return !isNull(); } /// is() return true if the Union currently holds the type matching T. diff --git a/contrib/llvm/include/llvm/ADT/PostOrderIterator.h b/contrib/llvm/include/llvm/ADT/PostOrderIterator.h index e3b499488..63a2b5219 100644 --- a/contrib/llvm/include/llvm/ADT/PostOrderIterator.h +++ b/contrib/llvm/include/llvm/ADT/PostOrderIterator.h @@ -29,6 +29,14 @@ public: SetType Visited; }; +/// DFSetTraits - Allow the SetType used to record depth-first search results to +/// optionally record node postorder. +template +struct DFSetTraits { + static void finishPostorder( + typename SetType::iterator::value_type, SetType &) {} +}; + template class po_iterator_storage { public: @@ -109,6 +117,8 @@ public: inline NodeType *operator->() const { return operator*(); } inline _Self& operator++() { // Preincrement + DFSetTraits::finishPostorder(VisitStack.back().first, + this->Visited); VisitStack.pop_back(); if (!VisitStack.empty()) traverseChild(); diff --git a/contrib/llvm/include/llvm/ADT/SCCIterator.h b/contrib/llvm/include/llvm/ADT/SCCIterator.h index 3e93cfe91..48436c667 100644 --- a/contrib/llvm/include/llvm/ADT/SCCIterator.h +++ b/contrib/llvm/include/llvm/ADT/SCCIterator.h @@ -1,4 +1,4 @@ -//===-- Support/SCCIterator.h - Strongly Connected Comp. Iter. --*- C++ -*-===// +//===---- ADT/SCCIterator.h - Strongly Connected Comp. Iter. ----*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -87,7 +87,7 @@ class scc_iterator DFSVisitOne(childN); continue; } - + unsigned childNum = nodeVisitNumbers[childN]; if (MinVisitNumStack.back() > childNum) MinVisitNumStack.back() = childNum; @@ -114,7 +114,7 @@ class scc_iterator if (minVisitNum != nodeVisitNumbers[visitingN]) continue; - + // A full SCC is on the SCCNodeStack! It includes all nodes below // visitingN on the stack. Copy those nodes to CurrentSCC, // reset their minVisit values, and return (this suspends @@ -139,7 +139,7 @@ public: // Provide static "constructors"... static inline _Self begin(const GraphT &G){return _Self(GT::getEntryNode(G));} - static inline _Self end (const GraphT &G) { return _Self(); } + static inline _Self end (const GraphT &) { return _Self(); } // Direct loop termination test: I.isAtEnd() is more efficient than I == end() inline bool isAtEnd() const { @@ -183,7 +183,7 @@ public: return true; return false; } - + /// ReplaceNode - This informs the scc_iterator that the specified Old node /// has been deleted, and New is to be used in its place. void ReplaceNode(NodeType *Old, NodeType *New) { diff --git a/contrib/llvm/include/llvm/ADT/STLExtras.h b/contrib/llvm/include/llvm/ADT/STLExtras.h index 0b0346be2..5da906dc8 100644 --- a/contrib/llvm/include/llvm/ADT/STLExtras.h +++ b/contrib/llvm/include/llvm/ADT/STLExtras.h @@ -186,25 +186,21 @@ inline ItTy prior(ItTy it) // // do stuff // else // // do other stuff - -namespace -{ - template - struct tier { - typedef T1 &first_type; - typedef T2 &second_type; - - first_type first; - second_type second; - - tier(first_type f, second_type s) : first(f), second(s) { } - tier& operator=(const std::pair& p) { - first = p.first; - second = p.second; - return *this; - } - }; -} +template +struct tier { + typedef T1 &first_type; + typedef T2 &second_type; + + first_type first; + second_type second; + + tier(first_type f, second_type s) : first(f), second(s) { } + tier& operator=(const std::pair& p) { + first = p.first; + second = p.second; + return *this; + } +}; template inline tier tie(T1& f, T2& s) { diff --git a/contrib/llvm/include/llvm/ADT/SmallVector.h b/contrib/llvm/include/llvm/ADT/SmallVector.h index 5f0a55bec..1c42f2977 100644 --- a/contrib/llvm/include/llvm/ADT/SmallVector.h +++ b/contrib/llvm/include/llvm/ADT/SmallVector.h @@ -78,21 +78,21 @@ protected: return BeginX == static_cast(&FirstEl); } + /// grow_pod - This is an implementation of the grow() method which only works + /// on POD-like data types and is out of line to reduce code duplication. + void grow_pod(size_t MinSizeInBytes, size_t TSize); + +public: /// size_in_bytes - This returns size()*sizeof(T). size_t size_in_bytes() const { return size_t((char*)EndX - (char*)BeginX); } - + /// capacity_in_bytes - This returns capacity()*sizeof(T). size_t capacity_in_bytes() const { return size_t((char*)CapacityX - (char*)BeginX); } - /// grow_pod - This is an implementation of the grow() method which only works - /// on POD-like data types and is out of line to reduce code duplication. - void grow_pod(size_t MinSizeInBytes, size_t TSize); - -public: bool empty() const { return BeginX == EndX; } }; @@ -738,6 +738,11 @@ public: }; +template +static inline size_t capacity_in_bytes(const SmallVector &X) { + return X.capacity_in_bytes(); +} + } // End llvm namespace namespace std { diff --git a/contrib/llvm/include/llvm/ADT/Statistic.h b/contrib/llvm/include/llvm/ADT/Statistic.h index fda99c6ed..b8a1a2f5c 100644 --- a/contrib/llvm/include/llvm/ADT/Statistic.h +++ b/contrib/llvm/include/llvm/ADT/Statistic.h @@ -54,7 +54,7 @@ public: Value = Val; return init(); } - + const Statistic &operator++() { // FIXME: This function and all those that follow carefully use an // atomic operation to update the value safely in the presence of @@ -63,41 +63,43 @@ public: sys::AtomicIncrement(&Value); return init(); } - + unsigned operator++(int) { init(); unsigned OldValue = Value; sys::AtomicIncrement(&Value); return OldValue; } - + const Statistic &operator--() { sys::AtomicDecrement(&Value); return init(); } - + unsigned operator--(int) { init(); unsigned OldValue = Value; sys::AtomicDecrement(&Value); return OldValue; } - + const Statistic &operator+=(const unsigned &V) { + if (!V) return *this; sys::AtomicAdd(&Value, V); return init(); } - + const Statistic &operator-=(const unsigned &V) { + if (!V) return *this; sys::AtomicAdd(&Value, -V); return init(); } - + const Statistic &operator*=(const unsigned &V) { sys::AtomicMul(&Value, V); return init(); } - + const Statistic &operator/=(const unsigned &V) { sys::AtomicDiv(&Value, V); return init(); diff --git a/contrib/llvm/include/llvm/ADT/StringExtras.h b/contrib/llvm/include/llvm/ADT/StringExtras.h index 5f5c04187..d01d3e1d6 100644 --- a/contrib/llvm/include/llvm/ADT/StringExtras.h +++ b/contrib/llvm/include/llvm/ADT/StringExtras.h @@ -16,6 +16,7 @@ #include "llvm/Support/DataTypes.h" #include "llvm/ADT/APFloat.h" +#include "llvm/ADT/DenseMapInfo.h" #include "llvm/ADT/StringRef.h" #include #include diff --git a/contrib/llvm/include/llvm/ADT/TinyPtrVector.h b/contrib/llvm/include/llvm/ADT/TinyPtrVector.h new file mode 100644 index 000000000..ee86d8bdf --- /dev/null +++ b/contrib/llvm/include/llvm/ADT/TinyPtrVector.h @@ -0,0 +1,133 @@ +//===- llvm/ADT/TinyPtrVector.h - 'Normally tiny' vectors -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_TINYPTRVECTOR_H +#define LLVM_ADT_TINYPTRVECTOR_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/PointerUnion.h" + +namespace llvm { + +/// TinyPtrVector - This class is specialized for cases where there are +/// normally 0 or 1 element in a vector, but is general enough to go beyond that +/// when required. +/// +/// NOTE: This container doesn't allow you to store a null pointer into it. +/// +template +class TinyPtrVector { +public: + typedef llvm::SmallVector VecTy; + llvm::PointerUnion Val; + + TinyPtrVector() {} + TinyPtrVector(const TinyPtrVector &RHS) : Val(RHS.Val) { + if (VecTy *V = Val.template dyn_cast()) + Val = new VecTy(*V); + } + ~TinyPtrVector() { + if (VecTy *V = Val.template dyn_cast()) + delete V; + } + + bool empty() const { + // This vector can be empty if it contains no element, or if it + // contains a pointer to an empty vector. + if (Val.isNull()) return true; + if (VecTy *Vec = Val.template dyn_cast()) + return Vec->empty(); + return false; + } + + unsigned size() const { + if (empty()) + return 0; + if (Val.template is()) + return 1; + return Val.template get()->size(); + } + + typedef const EltTy *iterator; + iterator begin() const { + if (empty()) + return 0; + + if (Val.template is()) + return Val.template getAddrOf(); + + return Val.template get()->begin(); + + } + iterator end() const { + if (empty()) + return 0; + + if (Val.template is()) + return begin() + 1; + + return Val.template get()->end(); + } + + + EltTy operator[](unsigned i) const { + assert(!Val.isNull() && "can't index into an empty vector"); + if (EltTy V = Val.template dyn_cast()) { + assert(i == 0 && "tinyvector index out of range"); + return V; + } + + assert(i < Val.template get()->size() && + "tinyvector index out of range"); + return (*Val.template get())[i]; + } + + EltTy front() const { + assert(!empty() && "vector empty"); + if (EltTy V = Val.template dyn_cast()) + return V; + return Val.template get()->front(); + } + + void push_back(EltTy NewVal) { + assert(NewVal != 0 && "Can't add a null value"); + + // If we have nothing, add something. + if (Val.isNull()) { + Val = NewVal; + return; + } + + // If we have a single value, convert to a vector. + if (EltTy V = Val.template dyn_cast()) { + Val = new VecTy(); + Val.template get()->push_back(V); + } + + // Add the new value, we know we have a vector. + Val.template get()->push_back(NewVal); + } + + void clear() { + // If we have a single value, convert to empty. + if (Val.template is()) { + Val = (EltTy)0; + } else if (VecTy *Vec = Val.template dyn_cast()) { + // If we have a vector form, just clear it. + Vec->clear(); + } + // Otherwise, we're already empty. + } + +private: + void operator=(const TinyPtrVector&); // NOT IMPLEMENTED YET. +}; +} // end namespace llvm + +#endif diff --git a/contrib/llvm/include/llvm/ADT/Triple.h b/contrib/llvm/include/llvm/ADT/Triple.h index fd23608a7..3503c0f22 100644 --- a/contrib/llvm/include/llvm/ADT/Triple.h +++ b/contrib/llvm/include/llvm/ADT/Triple.h @@ -10,8 +10,7 @@ #ifndef LLVM_ADT_TRIPLE_H #define LLVM_ADT_TRIPLE_H -#include "llvm/ADT/StringRef.h" -#include +#include "llvm/ADT/Twine.h" // Some system headers or GCC predefined macros conflict with identifiers in // this file. Undefine them here. @@ -19,8 +18,6 @@ #undef sparc namespace llvm { -class StringRef; -class Twine; /// Triple - Helper class for working with target triples. /// @@ -52,6 +49,8 @@ public: cellspu, // CellSPU: spu, cellspu mips, // MIPS: mips, mipsallegrex mipsel, // MIPSEL: mipsel, mipsallegrexel, psp + mips64, // MIPS64: mips64 + mips64el,// MIPS64EL: mips64el msp430, // MSP430: msp430 ppc, // PPC: powerpc ppc64, // PPC64: powerpc64, ppu @@ -66,6 +65,8 @@ public: mblaze, // MBlaze: mblaze ptx32, // PTX: ptx (32-bit) ptx64, // PTX: ptx (64-bit) + le32, // le32: generic little-endian 32-bit CPU (PNaCl / Emscripten) + amdil, // amdil: amd IL InvalidArch }; @@ -85,6 +86,7 @@ public: DragonFly, FreeBSD, IOS, + KFreeBSD, Linux, Lv2, // PS3 MacOSX, @@ -96,7 +98,8 @@ public: Win32, Haiku, Minix, - RTEMS + RTEMS, + NativeClient }; enum EnvironmentType { UnknownEnvironment, @@ -134,24 +137,16 @@ public: /// @{ Triple() : Data(), Arch(InvalidArch) {} - explicit Triple(StringRef Str) : Data(Str), Arch(InvalidArch) {} - explicit Triple(StringRef ArchStr, StringRef VendorStr, StringRef OSStr) - : Data(ArchStr), Arch(InvalidArch) { - Data += '-'; - Data += VendorStr; - Data += '-'; - Data += OSStr; + explicit Triple(const Twine &Str) : Data(Str.str()), Arch(InvalidArch) {} + Triple(const Twine &ArchStr, const Twine &VendorStr, const Twine &OSStr) + : Data((ArchStr + Twine('-') + VendorStr + Twine('-') + OSStr).str()), + Arch(InvalidArch) { } - explicit Triple(StringRef ArchStr, StringRef VendorStr, StringRef OSStr, - StringRef EnvironmentStr) - : Data(ArchStr), Arch(InvalidArch) { - Data += '-'; - Data += VendorStr; - Data += '-'; - Data += OSStr; - Data += '-'; - Data += EnvironmentStr; + Triple(const Twine &ArchStr, const Twine &VendorStr, const Twine &OSStr, + const Twine &EnvironmentStr) + : Data((ArchStr + Twine('-') + VendorStr + Twine('-') + OSStr + Twine('-') + + EnvironmentStr).str()), Arch(InvalidArch) { } /// @} diff --git a/contrib/llvm/include/llvm/ADT/Twine.h b/contrib/llvm/include/llvm/ADT/Twine.h index ab8d3653e..3a60cab77 100644 --- a/contrib/llvm/include/llvm/ADT/Twine.h +++ b/contrib/llvm/include/llvm/ADT/Twine.h @@ -99,6 +99,9 @@ namespace llvm { /// A pointer to a StringRef instance. StringRefKind, + /// A char value reinterpreted as a pointer, to render as a character. + CharKind, + /// An unsigned int value reinterpreted as a pointer, to render as an /// unsigned decimal integer. DecUIKind, @@ -126,13 +129,31 @@ namespace llvm { UHexKind }; + union Child + { + const Twine *twine; + const char *cString; + const std::string *stdString; + const StringRef *stringRef; + char character; + unsigned int decUI; + int decI; + const unsigned long *decUL; + const long *decL; + const unsigned long long *decULL; + const long long *decLL; + const uint64_t *uHex; + }; + private: /// LHS - The prefix in the concatenation, which may be uninitialized for /// Null or Empty kinds. - const void *LHS; + Child LHS; /// RHS - The suffix in the concatenation, which may be uninitialized for /// Null or Empty kinds. - const void *RHS; + Child RHS; + // enums stored as unsigned chars to save on space while some compilers + // don't support specifying the backing type for an enum /// LHSKind - The NodeKind of the left hand side, \see getLHSKind(). unsigned char LHSKind; /// RHSKind - The NodeKind of the left hand side, \see getLHSKind(). @@ -147,13 +168,15 @@ namespace llvm { /// Construct a binary twine. explicit Twine(const Twine &_LHS, const Twine &_RHS) - : LHS(&_LHS), RHS(&_RHS), LHSKind(TwineKind), RHSKind(TwineKind) { + : LHSKind(TwineKind), RHSKind(TwineKind) { + LHS.twine = &_LHS; + RHS.twine = &_RHS; assert(isValid() && "Invalid twine!"); } /// Construct a twine from explicit values. - explicit Twine(const void *_LHS, NodeKind _LHSKind, - const void *_RHS, NodeKind _RHSKind) + explicit Twine(Child _LHS, NodeKind _LHSKind, + Child _RHS, NodeKind _RHSKind) : LHS(_LHS), RHS(_RHS), LHSKind(_LHSKind), RHSKind(_RHSKind) { assert(isValid() && "Invalid twine!"); } @@ -200,10 +223,10 @@ namespace llvm { // A twine child should always be binary. if (getLHSKind() == TwineKind && - !static_cast(LHS)->isBinary()) + !LHS.twine->isBinary()) return false; if (getRHSKind() == TwineKind && - !static_cast(RHS)->isBinary()) + !RHS.twine->isBinary()) return false; return true; @@ -216,10 +239,10 @@ namespace llvm { NodeKind getRHSKind() const { return (NodeKind) RHSKind; } /// printOneChild - Print one child from a twine. - void printOneChild(raw_ostream &OS, const void *Ptr, NodeKind Kind) const; + void printOneChild(raw_ostream &OS, Child Ptr, NodeKind Kind) const; /// printOneChildRepr - Print the representation of one child from a twine. - void printOneChildRepr(raw_ostream &OS, const void *Ptr, + void printOneChildRepr(raw_ostream &OS, Child Ptr, NodeKind Kind) const; public: @@ -239,7 +262,7 @@ namespace llvm { /*implicit*/ Twine(const char *Str) : RHSKind(EmptyKind) { if (Str[0] != '\0') { - LHS = Str; + LHS.cString = Str; LHSKind = CStringKind; } else LHSKind = EmptyKind; @@ -249,44 +272,70 @@ namespace llvm { /// Construct from an std::string. /*implicit*/ Twine(const std::string &Str) - : LHS(&Str), LHSKind(StdStringKind), RHSKind(EmptyKind) { + : LHSKind(StdStringKind), RHSKind(EmptyKind) { + LHS.stdString = &Str; assert(isValid() && "Invalid twine!"); } /// Construct from a StringRef. /*implicit*/ Twine(const StringRef &Str) - : LHS(&Str), LHSKind(StringRefKind), RHSKind(EmptyKind) { + : LHSKind(StringRefKind), RHSKind(EmptyKind) { + LHS.stringRef = &Str; assert(isValid() && "Invalid twine!"); } + /// Construct from a char. + explicit Twine(char Val) + : LHSKind(CharKind), RHSKind(EmptyKind) { + LHS.character = Val; + } + + /// Construct from a signed char. + explicit Twine(signed char Val) + : LHSKind(CharKind), RHSKind(EmptyKind) { + LHS.character = static_cast(Val); + } + + /// Construct from an unsigned char. + explicit Twine(unsigned char Val) + : LHSKind(CharKind), RHSKind(EmptyKind) { + LHS.character = static_cast(Val); + } + /// Construct a twine to print \arg Val as an unsigned decimal integer. explicit Twine(unsigned Val) - : LHS((void*)(intptr_t)Val), LHSKind(DecUIKind), RHSKind(EmptyKind) { + : LHSKind(DecUIKind), RHSKind(EmptyKind) { + LHS.decUI = Val; } /// Construct a twine to print \arg Val as a signed decimal integer. explicit Twine(int Val) - : LHS((void*)(intptr_t)Val), LHSKind(DecIKind), RHSKind(EmptyKind) { + : LHSKind(DecIKind), RHSKind(EmptyKind) { + LHS.decI = Val; } /// Construct a twine to print \arg Val as an unsigned decimal integer. explicit Twine(const unsigned long &Val) - : LHS(&Val), LHSKind(DecULKind), RHSKind(EmptyKind) { + : LHSKind(DecULKind), RHSKind(EmptyKind) { + LHS.decUL = &Val; } /// Construct a twine to print \arg Val as a signed decimal integer. explicit Twine(const long &Val) - : LHS(&Val), LHSKind(DecLKind), RHSKind(EmptyKind) { + : LHSKind(DecLKind), RHSKind(EmptyKind) { + LHS.decL = &Val; } /// Construct a twine to print \arg Val as an unsigned decimal integer. explicit Twine(const unsigned long long &Val) - : LHS(&Val), LHSKind(DecULLKind), RHSKind(EmptyKind) { + : LHSKind(DecULLKind), RHSKind(EmptyKind) { + LHS.decULL = &Val; } /// Construct a twine to print \arg Val as a signed decimal integer. explicit Twine(const long long &Val) - : LHS(&Val), LHSKind(DecLLKind), RHSKind(EmptyKind) { + : LHSKind(DecLLKind), RHSKind(EmptyKind) { + LHS.decLL = &Val; } // FIXME: Unfortunately, to make sure this is as efficient as possible we @@ -296,13 +345,17 @@ namespace llvm { /// Construct as the concatenation of a C string and a StringRef. /*implicit*/ Twine(const char *_LHS, const StringRef &_RHS) - : LHS(_LHS), RHS(&_RHS), LHSKind(CStringKind), RHSKind(StringRefKind) { + : LHSKind(CStringKind), RHSKind(StringRefKind) { + LHS.cString = _LHS; + RHS.stringRef = &_RHS; assert(isValid() && "Invalid twine!"); } /// Construct as the concatenation of a StringRef and a C string. /*implicit*/ Twine(const StringRef &_LHS, const char *_RHS) - : LHS(&_LHS), RHS(_RHS), LHSKind(StringRefKind), RHSKind(CStringKind) { + : LHSKind(StringRefKind), RHSKind(CStringKind) { + LHS.stringRef = &_LHS; + RHS.cString = _RHS; assert(isValid() && "Invalid twine!"); } @@ -318,7 +371,10 @@ namespace llvm { // Construct a twine to print \arg Val as an unsigned hexadecimal integer. static Twine utohexstr(const uint64_t &Val) { - return Twine(&Val, UHexKind, 0, EmptyKind); + Child LHS, RHS; + LHS.uHex = &Val; + RHS.twine = 0; + return Twine(LHS, UHexKind, RHS, EmptyKind); } /// @} @@ -371,9 +427,9 @@ namespace llvm { switch (getLHSKind()) { default: assert(0 && "Out of sync with isSingleStringRef"); case EmptyKind: return StringRef(); - case CStringKind: return StringRef((const char*)LHS); - case StdStringKind: return StringRef(*(const std::string*)LHS); - case StringRefKind: return *(const StringRef*)LHS; + case CStringKind: return StringRef(LHS.cString); + case StdStringKind: return StringRef(*LHS.stdString); + case StringRefKind: return *LHS.stringRef; } } @@ -422,7 +478,9 @@ namespace llvm { // Otherwise we need to create a new node, taking care to fold in unary // twines. - const void *NewLHS = this, *NewRHS = &Suffix; + Child NewLHS, NewRHS; + NewLHS.twine = this; + NewRHS.twine = &Suffix; NodeKind NewLHSKind = TwineKind, NewRHSKind = TwineKind; if (isUnary()) { NewLHS = LHS; diff --git a/contrib/llvm/include/llvm/Analysis/AliasAnalysis.h b/contrib/llvm/include/llvm/Analysis/AliasAnalysis.h index 5d8edd1bf..d71ba208a 100644 --- a/contrib/llvm/include/llvm/Analysis/AliasAnalysis.h +++ b/contrib/llvm/include/llvm/Analysis/AliasAnalysis.h @@ -88,7 +88,7 @@ public: /// getTypeStoreSize - Return the TargetData store size for the given type, /// if known, or a conservative value otherwise. /// - uint64_t getTypeStoreSize(const Type *Ty); + uint64_t getTypeStoreSize(Type *Ty); //===--------------------------------------------------------------------===// /// Alias Queries... @@ -136,6 +136,8 @@ public: Location getLocation(const LoadInst *LI); Location getLocation(const StoreInst *SI); Location getLocation(const VAArgInst *VI); + Location getLocation(const AtomicCmpXchgInst *CXI); + Location getLocation(const AtomicRMWInst *RMWI); static Location getLocationForSource(const MemTransferInst *MTI); static Location getLocationForDest(const MemIntrinsic *MI); @@ -341,6 +343,11 @@ public: case Instruction::VAArg: return getModRefInfo((const VAArgInst*)I, Loc); case Instruction::Load: return getModRefInfo((const LoadInst*)I, Loc); case Instruction::Store: return getModRefInfo((const StoreInst*)I, Loc); + case Instruction::Fence: return getModRefInfo((const FenceInst*)I, Loc); + case Instruction::AtomicCmpXchg: + return getModRefInfo((const AtomicCmpXchgInst*)I, Loc); + case Instruction::AtomicRMW: + return getModRefInfo((const AtomicRMWInst*)I, Loc); case Instruction::Call: return getModRefInfo((const CallInst*)I, Loc); case Instruction::Invoke: return getModRefInfo((const InvokeInst*)I,Loc); default: return NoModRef; @@ -406,6 +413,39 @@ public: return getModRefInfo(S, Location(P, Size)); } + /// getModRefInfo (for fences) - Return whether information about whether + /// a particular store modifies or reads the specified memory location. + ModRefResult getModRefInfo(const FenceInst *S, const Location &Loc) { + // Conservatively correct. (We could possibly be a bit smarter if + // Loc is a alloca that doesn't escape.) + return ModRef; + } + + /// getModRefInfo (for fences) - A convenience wrapper. + ModRefResult getModRefInfo(const FenceInst *S, const Value *P, uint64_t Size){ + return getModRefInfo(S, Location(P, Size)); + } + + /// getModRefInfo (for cmpxchges) - Return whether information about whether + /// a particular cmpxchg modifies or reads the specified memory location. + ModRefResult getModRefInfo(const AtomicCmpXchgInst *CX, const Location &Loc); + + /// getModRefInfo (for cmpxchges) - A convenience wrapper. + ModRefResult getModRefInfo(const AtomicCmpXchgInst *CX, + const Value *P, unsigned Size) { + return getModRefInfo(CX, Location(P, Size)); + } + + /// getModRefInfo (for atomicrmws) - Return whether information about whether + /// a particular atomicrmw modifies or reads the specified memory location. + ModRefResult getModRefInfo(const AtomicRMWInst *RMW, const Location &Loc); + + /// getModRefInfo (for atomicrmws) - A convenience wrapper. + ModRefResult getModRefInfo(const AtomicRMWInst *RMW, + const Value *P, unsigned Size) { + return getModRefInfo(RMW, Location(P, Size)); + } + /// getModRefInfo (for va_args) - Return whether information about whether /// a particular va_arg modifies or reads the specified memory location. ModRefResult getModRefInfo(const VAArgInst* I, const Location &Loc); diff --git a/contrib/llvm/include/llvm/Analysis/AliasSetTracker.h b/contrib/llvm/include/llvm/Analysis/AliasSetTracker.h index 03149c662..c4ebe4015 100644 --- a/contrib/llvm/include/llvm/Analysis/AliasSetTracker.h +++ b/contrib/llvm/include/llvm/Analysis/AliasSetTracker.h @@ -111,8 +111,8 @@ class AliasSet : public ilist_node { AliasSet *Forward; // Forwarding pointer. AliasSet *Next, *Prev; // Doubly linked list of AliasSets. - // All calls & invokes in this alias set. - std::vector > CallSites; + // All instructions without a specific address in this alias set. + std::vector > UnknownInsts; // RefCount - Number of nodes pointing to this AliasSet plus the number of // AliasSets forwarding to it. @@ -147,9 +147,9 @@ class AliasSet : public ilist_node { removeFromTracker(AST); } - CallSite getCallSite(unsigned i) const { - assert(i < CallSites.size()); - return CallSite(CallSites[i]); + Instruction *getUnknownInst(unsigned i) const { + assert(i < UnknownInsts.size()); + return UnknownInsts[i]; } public: @@ -253,12 +253,12 @@ private: void addPointer(AliasSetTracker &AST, PointerRec &Entry, uint64_t Size, const MDNode *TBAAInfo, bool KnownMustAlias = false); - void addCallSite(CallSite CS, AliasAnalysis &AA); - void removeCallSite(CallSite CS) { - for (size_t i = 0, e = CallSites.size(); i != e; ++i) - if (CallSites[i] == CS.getInstruction()) { - CallSites[i] = CallSites.back(); - CallSites.pop_back(); + void addUnknownInst(Instruction *I, AliasAnalysis &AA); + void removeUnknownInst(Instruction *I) { + for (size_t i = 0, e = UnknownInsts.size(); i != e; ++i) + if (UnknownInsts[i] == I) { + UnknownInsts[i] = UnknownInsts.back(); + UnknownInsts.pop_back(); --i; --e; // Revisit the moved entry. } } @@ -269,7 +269,7 @@ private: /// bool aliasesPointer(const Value *Ptr, uint64_t Size, const MDNode *TBAAInfo, AliasAnalysis &AA) const; - bool aliasesCallSite(CallSite CS, AliasAnalysis &AA) const; + bool aliasesUnknownInst(Instruction *Inst, AliasAnalysis &AA) const; }; inline raw_ostream& operator<<(raw_ostream &OS, const AliasSet &AS) { @@ -326,12 +326,10 @@ public: bool add(LoadInst *LI); bool add(StoreInst *SI); bool add(VAArgInst *VAAI); - bool add(CallSite CS); // Call/Invoke instructions - bool add(CallInst *CI) { return add(CallSite(CI)); } - bool add(InvokeInst *II) { return add(CallSite(II)); } bool add(Instruction *I); // Dispatch to one of the other add methods... void add(BasicBlock &BB); // Add all instructions in basic block void add(const AliasSetTracker &AST); // Add alias relations from another AST + bool addUnknown(Instruction *I); /// remove methods - These methods are used to remove all entries that might /// be aliased by the specified instruction. These methods return true if any @@ -341,11 +339,9 @@ public: bool remove(LoadInst *LI); bool remove(StoreInst *SI); bool remove(VAArgInst *VAAI); - bool remove(CallSite CS); - bool remove(CallInst *CI) { return remove(CallSite(CI)); } - bool remove(InvokeInst *II) { return remove(CallSite(II)); } bool remove(Instruction *I); void remove(AliasSet &AS); + bool removeUnknown(Instruction *I); void clear(); @@ -429,7 +425,7 @@ private: AliasSet *findAliasSetForPointer(const Value *Ptr, uint64_t Size, const MDNode *TBAAInfo); - AliasSet *findAliasSetForCallSite(CallSite CS); + AliasSet *findAliasSetForUnknownInst(Instruction *Inst); }; inline raw_ostream& operator<<(raw_ostream &OS, const AliasSetTracker &AST) { diff --git a/contrib/llvm/include/llvm/Analysis/BlockFrequencyImpl.h b/contrib/llvm/include/llvm/Analysis/BlockFrequencyImpl.h index 6580fd1e4..0fb2bd7db 100644 --- a/contrib/llvm/include/llvm/Analysis/BlockFrequencyImpl.h +++ b/contrib/llvm/include/llvm/Analysis/BlockFrequencyImpl.h @@ -19,6 +19,7 @@ #include "llvm/ADT/PostOrderIterator.h" #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/MachineFunction.h" +#include "llvm/Support/BlockFrequency.h" #include "llvm/Support/BranchProbability.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" @@ -29,8 +30,8 @@ namespace llvm { -class BlockFrequency; -class MachineBlockFrequency; +class BlockFrequencyInfo; +class MachineBlockFrequencyInfo; /// BlockFrequencyImpl implements block frequency algorithm for IR and /// Machine Instructions. Algorithm starts with value 1024 (START_FREQ) @@ -40,7 +41,7 @@ class MachineBlockFrequency; template class BlockFrequencyImpl { - DenseMap Freqs; + DenseMap Freqs; BlockProbInfoT *BPI; @@ -48,7 +49,7 @@ class BlockFrequencyImpl { typedef GraphTraits< Inverse > GT; - static const uint32_t START_FREQ = 1024; + const uint32_t EntryFreq; std::string getBlockName(BasicBlock *BB) const { return BB->getNameStr(); @@ -64,26 +65,21 @@ class BlockFrequencyImpl { return ss.str(); } - void setBlockFreq(BlockT *BB, uint32_t Freq) { + void setBlockFreq(BlockT *BB, BlockFrequency Freq) { Freqs[BB] = Freq; DEBUG(dbgs() << "Frequency(" << getBlockName(BB) << ") = " << Freq << "\n"); } /// getEdgeFreq - Return edge frequency based on SRC frequency and Src -> Dst /// edge probability. - uint32_t getEdgeFreq(BlockT *Src, BlockT *Dst) const { + BlockFrequency getEdgeFreq(BlockT *Src, BlockT *Dst) const { BranchProbability Prob = BPI->getEdgeProbability(Src, Dst); - uint64_t N = Prob.getNumerator(); - uint64_t D = Prob.getDenominator(); - uint64_t Res = (N * getBlockFreq(Src)) / D; - - assert(Res <= UINT32_MAX); - return (uint32_t) Res; + return getBlockFreq(Src) * Prob; } /// incBlockFreq - Increase BB block frequency by FREQ. /// - void incBlockFreq(BlockT *BB, uint32_t Freq) { + void incBlockFreq(BlockT *BB, BlockFrequency Freq) { Freqs[BB] += Freq; DEBUG(dbgs() << "Frequency(" << getBlockName(BB) << ") += " << Freq << " --> " << Freqs[BB] << "\n"); @@ -95,13 +91,13 @@ class BlockFrequencyImpl { uint64_t N = Prob.getNumerator(); assert(N && "Illegal division by zero!"); uint64_t D = Prob.getDenominator(); - uint64_t Freq = (Freqs[BB] * D) / N; + uint64_t Freq = (Freqs[BB].getFrequency() * D) / N; // Should we assert it? if (Freq > UINT32_MAX) Freq = UINT32_MAX; - Freqs[BB] = (uint32_t) Freq; + Freqs[BB] = BlockFrequency(Freq); DEBUG(dbgs() << "Frequency(" << getBlockName(BB) << ") /= (" << Prob << ") --> " << Freqs[BB] << "\n"); } @@ -136,15 +132,6 @@ class BlockFrequencyImpl { } - /// Return a probability of getting to the DST block through SRC->DST edge. - /// - BranchProbability getBackEdgeProbability(BlockT *Src, BlockT *Dst) const { - uint32_t N = getEdgeFreq(Src, Dst); - uint32_t D = getBlockFreq(Dst); - - return BranchProbability(N, D); - } - /// isReachable - Returns if BB block is reachable from the entry. /// bool isReachable(BlockT *BB) { @@ -160,7 +147,7 @@ class BlockFrequencyImpl { unsigned a = RPO[Src]; unsigned b = RPO[Dst]; - return a > b; + return a >= b; } /// getSingleBlockPred - return single BB block predecessor or NULL if @@ -189,7 +176,7 @@ class BlockFrequencyImpl { setBlockFreq(BB, 0); if (BB == LoopHead) { - setBlockFreq(BB, START_FREQ); + setBlockFreq(BB, EntryFreq); return; } @@ -224,10 +211,10 @@ class BlockFrequencyImpl { if (!isLoopHead) return; - assert(START_FREQ >= CycleProb[BB]); + assert(EntryFreq >= CycleProb[BB]); uint32_t CProb = CycleProb[BB]; - uint32_t Numerator = START_FREQ - CProb ? START_FREQ - CProb : 1; - divBlockFreq(BB, BranchProbability(Numerator, START_FREQ)); + uint32_t Numerator = EntryFreq - CProb ? EntryFreq - CProb : 1; + divBlockFreq(BB, BranchProbability(Numerator, EntryFreq)); } /// doLoop - Propagate block frequency down throught the loop. @@ -237,11 +224,13 @@ class BlockFrequencyImpl { SmallPtrSet BlocksInLoop; - for (rpot_iterator I = rpot_at(Head), E = rpot_end(); I != E; ++I) { + for (rpot_iterator I = rpot_at(Head), E = rpot_at(Tail); ; ++I) { BlockT *BB = *I; doBlock(BB, Head, BlocksInLoop); BlocksInLoop.insert(BB); + if (I == E) + break; } // Compute loop's cyclic probability using backedges probabilities. @@ -252,19 +241,23 @@ class BlockFrequencyImpl { BlockT *Pred = *PI; assert(Pred); if (isReachable(Pred) && isBackedge(Pred, Head)) { - BranchProbability Prob = getBackEdgeProbability(Pred, Head); - uint64_t N = Prob.getNumerator(); - uint64_t D = Prob.getDenominator(); - uint64_t Res = (N * START_FREQ) / D; + 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"); } } } - friend class BlockFrequency; - friend class MachineBlockFrequency; + friend class BlockFrequencyInfo; + friend class MachineBlockFrequencyInfo; + + BlockFrequencyImpl() : EntryFreq(BlockFrequency::getEntryFrequency()) { } void doFunction(FunctionT *fn, BlockProbInfoT *bpi) { Fn = fn; @@ -314,13 +307,12 @@ class BlockFrequencyImpl { } public: - /// getBlockFreq - Return block frequency. Never return 0, value must be - /// positive. - uint32_t getBlockFreq(BlockT *BB) const { - typename DenseMap::const_iterator I = Freqs.find(BB); + /// getBlockFreq - Return block frequency. Return 0 if we don't have it. + BlockFrequency getBlockFreq(BlockT *BB) const { + typename DenseMap::const_iterator I = Freqs.find(BB); if (I != Freqs.end()) - return I->second ? I->second : 1; - return 1; + return I->second; + return 0; } void print(raw_ostream &OS) const { diff --git a/contrib/llvm/include/llvm/Analysis/BlockFrequency.h b/contrib/llvm/include/llvm/Analysis/BlockFrequencyInfo.h similarity index 58% rename from contrib/llvm/include/llvm/Analysis/BlockFrequency.h rename to contrib/llvm/include/llvm/Analysis/BlockFrequencyInfo.h index c4b1e087a..9e698a9f4 100644 --- a/contrib/llvm/include/llvm/Analysis/BlockFrequency.h +++ b/contrib/llvm/include/llvm/Analysis/BlockFrequencyInfo.h @@ -1,4 +1,4 @@ -//========-------- BlockFrequency.h - Block Frequency Analysis -------========// +//========-------- BlockFrequencyInfo.h - Block Frequency Analysis -------========// // // The LLVM Compiler Infrastructure // @@ -11,10 +11,11 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_ANALYSIS_BLOCKFREQUENCY_H -#define LLVM_ANALYSIS_BLOCKFREQUENCY_H +#ifndef LLVM_ANALYSIS_BLOCKFREQUENCYINFO_H +#define LLVM_ANALYSIS_BLOCKFREQUENCYINFO_H #include "llvm/Pass.h" +#include "llvm/Support/BlockFrequency.h" #include namespace llvm { @@ -23,29 +24,30 @@ class BranchProbabilityInfo; template class BlockFrequencyImpl; -/// BlockFrequency pass uses BlockFrequencyImpl implementation to estimate +/// BlockFrequencyInfo pass uses BlockFrequencyImpl implementation to estimate /// IR basic block frequencies. -class BlockFrequency : public FunctionPass { +class BlockFrequencyInfo : public FunctionPass { BlockFrequencyImpl *BFI; public: static char ID; - BlockFrequency(); + BlockFrequencyInfo(); - ~BlockFrequency(); + ~BlockFrequencyInfo(); void getAnalysisUsage(AnalysisUsage &AU) const; bool runOnFunction(Function &F); + void print(raw_ostream &O, const Module *M) const; - /// getblockFreq - Return block frequency. Never return 0, value must be - /// positive. Please note that initial frequency is equal to 1024. It means + /// 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 the floating - /// points. - uint32_t getBlockFreq(BasicBlock *BB); + /// the other block frequencies. We do this to avoid using of floating points. + /// + BlockFrequency getBlockFreq(BasicBlock *BB) const; }; } diff --git a/contrib/llvm/include/llvm/Analysis/BranchProbabilityInfo.h b/contrib/llvm/include/llvm/Analysis/BranchProbabilityInfo.h index 02ead9832..a2c12ab9e 100644 --- a/contrib/llvm/include/llvm/Analysis/BranchProbabilityInfo.h +++ b/contrib/llvm/include/llvm/Analysis/BranchProbabilityInfo.h @@ -33,12 +33,12 @@ class BranchProbabilityInfo : public FunctionPass { // weight to just "inherit" the non-zero weight of an adjacent successor. static const uint32_t DEFAULT_WEIGHT = 16; - typedef std::pair Edge; + typedef std::pair Edge; DenseMap Weights; // Get sum of the block successors' weights. - uint32_t getSumForBlock(BasicBlock *BB) const; + uint32_t getSumForBlock(const BasicBlock *BB) const; public: static char ID; @@ -53,13 +53,14 @@ public: // Returned value is between 1 and UINT32_MAX. Look at // BranchProbabilityInfo.cpp for details. - uint32_t getEdgeWeight(BasicBlock *Src, BasicBlock *Dst) const; + uint32_t getEdgeWeight(const BasicBlock *Src, const BasicBlock *Dst) const; // Look at BranchProbabilityInfo.cpp for details. Use it with caution! - void setEdgeWeight(BasicBlock *Src, BasicBlock *Dst, uint32_t Weight); + void setEdgeWeight(const BasicBlock *Src, const BasicBlock *Dst, + uint32_t Weight); // A 'Hot' edge is an edge which probability is >= 80%. - bool isEdgeHot(BasicBlock *Src, BasicBlock *Dst) const; + bool isEdgeHot(const BasicBlock *Src, const BasicBlock *Dst) const; // Return a hot successor for the block BB or null if there isn't one. BasicBlock *getHotSucc(BasicBlock *BB) const; @@ -67,7 +68,8 @@ public: // Return a probability as a fraction between 0 (0% probability) and // 1 (100% probability), however the value is never equal to 0, and can be 1 // only iff SRC block has only one successor. - BranchProbability getEdgeProbability(BasicBlock *Src, BasicBlock *Dst) const; + BranchProbability getEdgeProbability(const BasicBlock *Src, + const BasicBlock *Dst) const; // Print value between 0 (0% probability) and 1 (100% probability), // however the value is never equal to 0, and can be 1 only iff SRC block diff --git a/contrib/llvm/include/llvm/Analysis/CodeMetrics.h b/contrib/llvm/include/llvm/Analysis/CodeMetrics.h index 75edfbbed..d96dd82b3 100644 --- a/contrib/llvm/include/llvm/Analysis/CodeMetrics.h +++ b/contrib/llvm/include/llvm/Analysis/CodeMetrics.h @@ -18,6 +18,9 @@ #include "llvm/ADT/DenseMap.h" namespace llvm { + + class TargetData; + // CodeMetrics - Calculate size and a few similar metrics for a set of // basic blocks. struct CodeMetrics { @@ -46,7 +49,7 @@ namespace llvm { /// NumCalls - Keep track of the number of calls to 'big' functions. unsigned NumCalls; - + /// NumInlineCandidates - Keep track of the number of calls to internal /// functions with only a single caller. These are likely targets for /// future inlining, likely exposed by interleaved devirtualization. @@ -61,24 +64,24 @@ namespace llvm { unsigned NumRets; CodeMetrics() : callsSetJmp(false), isRecursive(false), - containsIndirectBr(false), usesDynamicAlloca(false), + containsIndirectBr(false), usesDynamicAlloca(false), NumInsts(0), NumBlocks(0), NumCalls(0), - NumInlineCandidates(0), NumVectorInsts(0), + NumInlineCandidates(0), NumVectorInsts(0), NumRets(0) {} /// analyzeBasicBlock - Add information about the specified basic block /// to the current structure. - void analyzeBasicBlock(const BasicBlock *BB); + void analyzeBasicBlock(const BasicBlock *BB, const TargetData *TD = 0); /// analyzeFunction - Add information about the specified function /// to the current structure. - void analyzeFunction(Function *F); - + void analyzeFunction(Function *F, const TargetData *TD = 0); + /// CountCodeReductionForConstant - Figure out an approximation for how /// many instructions will be constant folded if the specified value is /// constant. unsigned CountCodeReductionForConstant(Value *V); - + /// CountBonusForConstant - Figure out an approximation for how much /// per-call performance boost we can expect if the specified value is /// constant. diff --git a/contrib/llvm/include/llvm/Analysis/ConstantFolding.h b/contrib/llvm/include/llvm/Analysis/ConstantFolding.h index f6b1f5ab9..05018fa16 100644 --- a/contrib/llvm/include/llvm/Analysis/ConstantFolding.h +++ b/contrib/llvm/include/llvm/Analysis/ConstantFolding.h @@ -27,6 +27,8 @@ namespace llvm { class TargetData; class Function; class Type; + template + class ArrayRef; /// ConstantFoldInstruction - Try to constant fold the specified instruction. /// If successful, the constant result is returned, if not, null is returned. @@ -47,8 +49,8 @@ Constant *ConstantFoldConstantExpression(const ConstantExpr *CE, /// fold instructions like loads and stores, which have no constant expression /// form. /// -Constant *ConstantFoldInstOperands(unsigned Opcode, const Type *DestTy, - Constant *const *Ops, unsigned NumOps, +Constant *ConstantFoldInstOperands(unsigned Opcode, Type *DestTy, + ArrayRef Ops, const TargetData *TD = 0); /// ConstantFoldCompareInstOperands - Attempt to constant fold a compare @@ -59,6 +61,12 @@ Constant *ConstantFoldCompareInstOperands(unsigned Predicate, Constant *LHS, Constant *RHS, const TargetData *TD = 0); +/// ConstantFoldInsertValueInstruction - Attempt to constant fold an insertvalue +/// instruction with the specified operands and indices. The constant result is +/// returned if successful; if not, null is returned. +Constant *ConstantFoldInsertValueInstruction(Constant *Agg, Constant *Val, + ArrayRef Idxs); + /// ConstantFoldLoadFromConstPtr - Return the value that a load from C would /// produce if it is constant and determinable. If this is not determinable, /// return null. @@ -76,7 +84,7 @@ bool canConstantFoldCallTo(const Function *F); /// ConstantFoldCall - Attempt to constant fold a call to the specified function /// with the specified arguments, returning null if unsuccessful. Constant * -ConstantFoldCall(Function *F, Constant *const *Operands, unsigned NumOperands); +ConstantFoldCall(Function *F, ArrayRef Operands); } #endif diff --git a/contrib/llvm/include/llvm/Analysis/DIBuilder.h b/contrib/llvm/include/llvm/Analysis/DIBuilder.h index a706cc8f3..ee24226c7 100644 --- a/contrib/llvm/include/llvm/Analysis/DIBuilder.h +++ b/contrib/llvm/include/llvm/Analysis/DIBuilder.h @@ -37,6 +37,7 @@ namespace llvm { class DINameSpace; class DIVariable; class DISubrange; + class DILexicalBlockFile; class DILexicalBlock; class DISubprogram; class DITemplateTypeParameter; @@ -48,9 +49,19 @@ namespace llvm { LLVMContext & VMContext; MDNode *TheCU; + MDNode *TempEnumTypes; + MDNode *TempRetainTypes; + MDNode *TempSubprograms; + MDNode *TempGVs; + Function *DeclareFn; // llvm.dbg.declare Function *ValueFn; // llvm.dbg.value + SmallVector AllEnumTypes; + SmallVector AllRetainTypes; + SmallVector AllSubprograms; + SmallVector AllGVs; + DIBuilder(const DIBuilder &); // DO NOT IMPLEMENT void operator=(const DIBuilder &); // DO NOT IMPLEMENT @@ -59,6 +70,9 @@ namespace llvm { const MDNode *getCU() { return TheCU; } enum ComplexAddrKind { OpPlus=1, OpDeref }; + /// finalize - Construct any deferred debug info descriptors. + void finalize(); + /// createCompileUnit - A CompileUnit provides an anchor for all debugging /// information generated during this instance of compilation. /// @param Lang Source programming language, eg. dwarf::DW_LANG_C99 @@ -84,6 +98,9 @@ namespace llvm { /// createEnumerator - Create a single enumerator value. DIEnumerator createEnumerator(StringRef Name, uint64_t Val); + /// createNullPtrType - Create C++0x nullptr type. + DIType createNullPtrType(StringRef Name); + /// createBasicType - Create debugging information entry for a basic /// type. /// @param Name Type name. @@ -447,6 +464,14 @@ namespace llvm { DIFile File, unsigned LineNo); + /// createLexicalBlockFile - This creates a descriptor for a lexical + /// block with a new file attached. This merely extends the existing + /// lexical block as it crosses a file. + /// @param Scope Lexical block. + /// @param File Source file. + DILexicalBlockFile createLexicalBlockFile(DIDescriptor Scope, + DIFile File); + /// createLexicalBlock - This creates a descriptor for a lexical block /// with the specified parent context. /// @param Scope Parent lexical scope. diff --git a/contrib/llvm/include/llvm/Analysis/DebugInfo.h b/contrib/llvm/include/llvm/Analysis/DebugInfo.h index fbee5a631..9a53c4dad 100644 --- a/contrib/llvm/include/llvm/Analysis/DebugInfo.h +++ b/contrib/llvm/include/llvm/Analysis/DebugInfo.h @@ -40,6 +40,7 @@ namespace llvm { class DIFile; class DISubprogram; class DILexicalBlock; + class DILexicalBlockFile; class DIVariable; class DIType; @@ -84,6 +85,7 @@ namespace llvm { 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); @@ -117,6 +119,7 @@ namespace llvm { bool isFile() const; bool isCompileUnit() const; bool isNameSpace() const; + bool isLexicalBlockFile() const; bool isLexicalBlock() const; bool isSubrange() const; bool isEnumerator() const; @@ -182,6 +185,11 @@ namespace llvm { StringRef getFlags() const { return getStringField(8); } unsigned getRunTimeVersion() const { return getUnsignedField(9); } + DIArray getEnumTypes() const; + DIArray getRetainedTypes() const; + DIArray getSubprograms() const; + DIArray getGlobalVariables() const; + /// Verify - Verify that a compile unit is well formed. bool Verify() const; @@ -201,7 +209,10 @@ namespace llvm { } StringRef getFilename() const { return getStringField(1); } StringRef getDirectory() const { return getStringField(2); } - DICompileUnit getCompileUnit() const{ return getFieldAs(3); } + DICompileUnit getCompileUnit() const{ + assert (getVersion() <= LLVMDebugVersion10 && "Invalid CompileUnit!"); + return getFieldAs(3); + } }; /// DIEnumerator - A wrapper for an enumerator (e.g. X and Y in 'enum {X,Y}'). @@ -237,6 +248,7 @@ namespace llvm { DIScope getContext() const { return getFieldAs(1); } StringRef getName() const { return getStringField(2); } DICompileUnit getCompileUnit() const{ + assert (getVersion() <= LLVMDebugVersion10 && "Invalid getCompileUnit!"); if (getVersion() == llvm::LLVMDebugVersion7) return getFieldAs(3); @@ -291,6 +303,9 @@ namespace llvm { return getFieldAs(3).getFilename(); } + /// 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); @@ -447,6 +462,7 @@ namespace llvm { StringRef getDisplayName() const { return getStringField(4); } StringRef getLinkageName() const { return getStringField(5); } DICompileUnit getCompileUnit() const{ + assert (getVersion() <= LLVMDebugVersion10 && "Invalid getCompileUnit!"); if (getVersion() == llvm::LLVMDebugVersion7) return getFieldAs(6); @@ -545,6 +561,8 @@ namespace llvm { DISubprogram getFunctionDeclaration() const { return getFieldAs(18); } + MDNode *getVariablesNodes() const; + DIArray getVariables() const; }; /// DIGlobalVariable - This is a wrapper for a global variable. @@ -557,12 +575,24 @@ namespace llvm { StringRef getDisplayName() const { return getStringField(4); } StringRef getLinkageName() const { return getStringField(5); } DICompileUnit getCompileUnit() const{ + assert (getVersion() <= LLVMDebugVersion10 && "Invalid getCompileUnit!"); if (getVersion() == llvm::LLVMDebugVersion7) return getFieldAs(6); DIFile F = getFieldAs(6); return F.getCompileUnit(); } + StringRef getFilename() const { + if (getVersion() <= llvm::LLVMDebugVersion10) + return getContext().getFilename(); + return getFieldAs(6).getFilename(); + } + StringRef getDirectory() const { + if (getVersion() <= llvm::LLVMDebugVersion10) + return getContext().getDirectory(); + return getFieldAs(6).getDirectory(); + + } unsigned getLineNumber() const { return getUnsignedField(7); } DIType getType() const { return getFieldAs(8); } @@ -592,6 +622,7 @@ namespace llvm { DIScope getContext() const { return getFieldAs(1); } StringRef getName() const { return getStringField(2); } DICompileUnit getCompileUnit() const{ + assert (getVersion() <= LLVMDebugVersion10 && "Invalid getCompileUnit!"); if (getVersion() == llvm::LLVMDebugVersion7) return getFieldAs(3); @@ -614,6 +645,8 @@ namespace llvm { return (getUnsignedField(6) & FlagArtificial) != 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; @@ -628,7 +661,9 @@ namespace llvm { uint64_t getAddrElement(unsigned Idx) const { if (getVersion() <= llvm::LLVMDebugVersion8) return getUInt64Field(Idx+6); - return getUInt64Field(Idx+7); + if (getVersion() == llvm::LLVMDebugVersion9) + return getUInt64Field(Idx+7); + return getUInt64Field(Idx+8); } /// isBlockByrefVariable - Return true if the variable was declared as @@ -644,6 +679,8 @@ namespace llvm { /// print - print variable. void print(raw_ostream &OS) const; + void printExtendedName(raw_ostream &OS) const; + /// dump - print variable to dbgs() with a newline. void dump() const; }; @@ -665,6 +702,26 @@ namespace llvm { } }; + /// 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 { return getScope().getContext(); } + unsigned getLineNumber() const { return getScope().getLineNumber(); } + unsigned getColumnNumber() const { return getScope().getColumnNumber(); } + StringRef getDirectory() const { + StringRef dir = getFieldAs(2).getDirectory(); + return !dir.empty() ? dir : getContext().getDirectory(); + } + StringRef getFilename() const { + StringRef filename = getFieldAs(2).getFilename(); + assert(!filename.empty() && "Why'd you create this then?"); + return filename; + } + DILexicalBlock getScope() const { return getFieldAs(1); } + }; + /// DINameSpace - A wrapper for a C++ style name space. class DINameSpace : public DIScope { public: @@ -678,6 +735,7 @@ namespace llvm { return getFieldAs(3).getFilename(); } DICompileUnit getCompileUnit() const{ + assert (getVersion() <= LLVMDebugVersion10 && "Invalid getCompileUnit!"); if (getVersion() == llvm::LLVMDebugVersion7) return getFieldAs(3); @@ -708,13 +766,27 @@ namespace llvm { /// 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, StringRef Name); + 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, StringRef Name); + 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: diff --git a/contrib/llvm/include/llvm/Analysis/FindUsedTypes.h b/contrib/llvm/include/llvm/Analysis/FindUsedTypes.h index 3e5da572b..b22cb8813 100644 --- a/contrib/llvm/include/llvm/Analysis/FindUsedTypes.h +++ b/contrib/llvm/include/llvm/Analysis/FindUsedTypes.h @@ -23,7 +23,7 @@ class Type; class Value; class FindUsedTypes : public ModulePass { - SetVector UsedTypes; + SetVector UsedTypes; public: static char ID; // Pass identification, replacement for typeid FindUsedTypes() : ModulePass(ID) { @@ -33,7 +33,7 @@ public: /// getTypes - After the pass has been run, return the set containing all of /// the types used in the module. /// - const SetVector &getTypes() const { return UsedTypes; } + const SetVector &getTypes() const { return UsedTypes; } /// Print the types found in the module. If the optional Module parameter is /// passed in, then the types are printed symbolically if possible, using the @@ -45,7 +45,7 @@ private: /// IncorporateType - Incorporate one type and all of its subtypes into the /// collection of used types. /// - void IncorporateType(const Type *Ty); + void IncorporateType(Type *Ty); /// IncorporateValue - Incorporate all of the types used by this value. /// diff --git a/contrib/llvm/include/llvm/Analysis/IVUsers.h b/contrib/llvm/include/llvm/Analysis/IVUsers.h index e56d24d58..2fb607cc5 100644 --- a/contrib/llvm/include/llvm/Analysis/IVUsers.h +++ b/contrib/llvm/include/llvm/Analysis/IVUsers.h @@ -140,6 +140,8 @@ public: static char ID; // Pass ID, replacement for typeid IVUsers(); + Loop *getLoop() const { return L; } + /// AddUsersIfInteresting - Inspect the specified Instruction. If it is a /// reducible SCEV, recursively add its users to the IVUsesByStride set and /// return true. Otherwise, return false. diff --git a/contrib/llvm/include/llvm/Analysis/InlineCost.h b/contrib/llvm/include/llvm/Analysis/InlineCost.h index a0cce515e..36a16e68d 100644 --- a/contrib/llvm/include/llvm/Analysis/InlineCost.h +++ b/contrib/llvm/include/llvm/Analysis/InlineCost.h @@ -29,6 +29,7 @@ namespace llvm { class CallSite; template class SmallPtrSet; + class TargetData; namespace InlineConstants { // Various magic constants used to adjust heuristics. @@ -113,7 +114,7 @@ namespace llvm { /// analyzeFunction - Add information about the specified function /// to the current structure. - void analyzeFunction(Function *F); + void analyzeFunction(Function *F, const TargetData *TD); /// NeverInline - Returns true if the function should never be /// inlined into any caller. @@ -124,11 +125,17 @@ namespace llvm { // the ValueMap will update itself when this happens. ValueMap CachedFunctionInfo; + // TargetData if available, or null. + const TargetData *TD; + int CountBonusForConstant(Value *V, Constant *C = NULL); int ConstantFunctionBonus(CallSite CS, Constant *C); int getInlineSize(CallSite CS, Function *Callee); int getInlineBonuses(CallSite CS, Function *Callee); public: + InlineCostAnalyzer(): TD(0) {} + + void setTargetData(const TargetData *TData) { TD = TData; } /// getInlineCost - The heuristic used to determine if we should inline the /// function call or not. diff --git a/contrib/llvm/include/llvm/Analysis/InstructionSimplify.h b/contrib/llvm/include/llvm/Analysis/InstructionSimplify.h index bc6e55f54..c1d87d3f7 100644 --- a/contrib/llvm/include/llvm/Analysis/InstructionSimplify.h +++ b/contrib/llvm/include/llvm/Analysis/InstructionSimplify.h @@ -24,6 +24,8 @@ namespace llvm { class Instruction; class Value; class TargetData; + template + class ArrayRef; /// SimplifyAddInst - Given operands for an Add, see if we can /// fold the result. If not, this returns null. @@ -121,9 +123,16 @@ namespace llvm { /// SimplifyGEPInst - Given operands for an GetElementPtrInst, see if we can /// fold the result. If not, this returns null. - Value *SimplifyGEPInst(Value * const *Ops, unsigned NumOps, + Value *SimplifyGEPInst(ArrayRef Ops, const TargetData *TD = 0, const DominatorTree *DT = 0); + /// SimplifyInsertValueInst - Given operands for an InsertValueInst, see if we + /// can fold the result. If not, this returns null. + Value *SimplifyInsertValueInst(Value *Agg, Value *Val, + ArrayRef Idxs, + const TargetData *TD = 0, + const DominatorTree *DT = 0); + //=== Helper functions for higher up the class hierarchy. diff --git a/contrib/llvm/include/llvm/Analysis/LoopInfo.h b/contrib/llvm/include/llvm/Analysis/LoopInfo.h index 392bdad5a..12cb6c5cc 100644 --- a/contrib/llvm/include/llvm/Analysis/LoopInfo.h +++ b/contrib/llvm/include/llvm/Analysis/LoopInfo.h @@ -33,6 +33,7 @@ #include "llvm/Pass.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DenseSet.h" #include "llvm/ADT/DepthFirstIterator.h" #include "llvm/ADT/GraphTraits.h" #include "llvm/ADT/SmallVector.h" @@ -105,7 +106,7 @@ public: if (L == 0) return false; return contains(L->getParentLoop()); } - + /// contains - Return true if the specified basic block is in this loop. /// bool contains(const BlockT *BB) const { @@ -134,6 +135,11 @@ public: block_iterator block_begin() const { return Blocks.begin(); } block_iterator block_end() const { return Blocks.end(); } + /// getNumBlocks - Get the number of blocks in this loop in constant time. + unsigned getNumBlocks() const { + return Blocks.size(); + } + /// isLoopExiting - True if terminator in the block can branch to another /// block that is outside of the current loop. /// @@ -479,12 +485,13 @@ public: } /// verifyLoop - Verify loop structure of this loop and all nested loops. - void verifyLoopNest() const { + void verifyLoopNest(DenseSet *Loops) const { + Loops->insert(static_cast(this)); // Verify this loop. verifyLoop(); // Verify the subloops. for (iterator I = begin(), E = end(); I != E; ++I) - (*I)->verifyLoopNest(); + (*I)->verifyLoopNest(Loops); } void print(raw_ostream &OS, unsigned Depth = 0) const { @@ -527,7 +534,7 @@ public: bool isLoopInvariant(Value *V) const; /// hasLoopInvariantOperands - Return true if all the operands of the - /// specified instruction are loop invariant. + /// specified instruction are loop invariant. bool hasLoopInvariantOperands(Instruction *I) const; /// makeLoopInvariant - If the given value is an instruction inside of the @@ -607,7 +614,7 @@ public: /// has a predecessor that is outside the loop. bool hasDedicatedExits() const; - /// getUniqueExitBlocks - Return all unique successor blocks of this loop. + /// getUniqueExitBlocks - Return all unique successor blocks of this loop. /// These are the blocks _outside of the current loop_ which are branched to. /// This assumes that loop exits are in canonical form. /// @@ -618,7 +625,7 @@ public: BasicBlock *getUniqueExitBlock() const; void dump() const; - + private: friend class LoopInfoBase; explicit Loop(BasicBlock *BB) : LoopBase(BB) {} @@ -635,13 +642,14 @@ class LoopInfoBase { DenseMap BBMap; std::vector TopLevelLoops; friend class LoopBase; + friend class LoopInfo; void operator=(const LoopInfoBase &); // do not implement LoopInfoBase(const LoopInfo &); // do not implement public: LoopInfoBase() { } ~LoopInfoBase() { releaseMemory(); } - + void releaseMemory() { for (typename std::vector::iterator I = TopLevelLoops.begin(), E = TopLevelLoops.end(); I != E; ++I) @@ -650,7 +658,7 @@ public: BBMap.clear(); // Reset internal state of analysis TopLevelLoops.clear(); } - + /// iterator/begin/end - The interface to the top-level loops in the current /// function. /// @@ -658,7 +666,7 @@ public: iterator begin() const { return TopLevelLoops.begin(); } iterator end() const { return TopLevelLoops.end(); } bool empty() const { return TopLevelLoops.empty(); } - + /// getLoopFor - Return the inner most loop that BB lives in. If a basic /// block is in no loop (for example the entry node), null is returned. /// @@ -667,13 +675,13 @@ public: BBMap.find(const_cast(BB)); return I != BBMap.end() ? I->second : 0; } - + /// operator[] - same as getLoopFor... /// const LoopT *operator[](const BlockT *BB) const { return getLoopFor(BB); } - + /// getLoopDepth - Return the loop nesting level of the specified block. A /// depth of 0 means the block is not inside any loop. /// @@ -687,7 +695,7 @@ public: const LoopT *L = getLoopFor(BB); return L && L->getHeader() == BB; } - + /// removeLoop - This removes the specified top-level loop from this loop info /// object. The loop is not deleted, as it will presumably be inserted into /// another loop. @@ -698,16 +706,20 @@ public: TopLevelLoops.erase(TopLevelLoops.begin() + (I-begin())); return L; } - + /// changeLoopFor - Change the top-level loop that contains BB to the /// specified loop. This should be used by transformations that restructure /// the loop hierarchy tree. void changeLoopFor(BlockT *BB, LoopT *L) { - LoopT *&OldLoop = BBMap[BB]; - assert(OldLoop && "Block not in a loop yet!"); - OldLoop = L; + if (!L) { + typename DenseMap::iterator I = BBMap.find(BB); + if (I != BBMap.end()) + BBMap.erase(I); + return; + } + BBMap[BB] = L; } - + /// changeTopLevelLoop - Replace the specified loop in the top-level loops /// list with the indicated loop. void changeTopLevelLoop(LoopT *OldLoop, @@ -719,14 +731,14 @@ public: assert(NewLoop->ParentLoop == 0 && OldLoop->ParentLoop == 0 && "Loops already embedded into a subloop!"); } - + /// addTopLevelLoop - This adds the specified loop to the collection of /// top-level loops. void addTopLevelLoop(LoopT *New) { assert(New->getParentLoop() == 0 && "Loop already in subloop!"); TopLevelLoops.push_back(New); } - + /// removeBlock - This method completely removes BB from all data structures, /// including all of the Loop objects it is nested in and our mapping from /// BasicBlocks to loops. @@ -739,16 +751,16 @@ public: BBMap.erase(I); } } - + // Internals - + static bool isNotAlreadyContainedIn(const LoopT *SubLoop, const LoopT *ParentLoop) { if (SubLoop == 0) return true; if (SubLoop == ParentLoop) return false; return isNotAlreadyContainedIn(SubLoop->getParentLoop(), ParentLoop); } - + void Calculate(DominatorTreeBase &DT) { BlockT *RootNode = DT.getRootNode()->getBlock(); @@ -757,7 +769,7 @@ public: if (LoopT *L = ConsiderForLoop(*NI, DT)) TopLevelLoops.push_back(L); } - + LoopT *ConsiderForLoop(BlockT *BB, DominatorTreeBase &DT) { if (BBMap.find(BB) != BBMap.end()) return 0;// Haven't processed this node? @@ -812,9 +824,9 @@ public: // Normal case, add the block to our loop... L->Blocks.push_back(X); - + typedef GraphTraits > InvBlockTraits; - + // Add all of the predecessors of X to the end of the work stack... TodoStack.insert(TodoStack.end(), InvBlockTraits::child_begin(X), InvBlockTraits::child_end(X)); @@ -878,7 +890,7 @@ public: return L; } - + /// MoveSiblingLoopInto - This method moves the NewChild loop to live inside /// of the NewParent Loop, instead of being a sibling of it. void MoveSiblingLoopInto(LoopT *NewChild, @@ -897,7 +909,7 @@ public: InsertLoopInto(NewChild, NewParent); } - + /// InsertLoopInto - This inserts loop L into the specified parent loop. If /// the parent loop contains a loop which should contain L, the loop gets /// inserted into L instead. @@ -918,9 +930,9 @@ public: Parent->SubLoops.push_back(L); L->ParentLoop = Parent; } - + // Debugging - + void print(raw_ostream &OS) const { for (unsigned i = 0; i < TopLevelLoops.size(); ++i) TopLevelLoops[i]->print(OS); @@ -990,7 +1002,7 @@ public: virtual void releaseMemory() { LI.releaseMemory(); } virtual void print(raw_ostream &O, const Module* M = 0) const; - + virtual void getAnalysisUsage(AnalysisUsage &AU) const; /// removeLoop - This removes the specified top-level loop from this loop info @@ -1024,6 +1036,12 @@ public: LI.removeBlock(BB); } + /// updateUnloop - Update LoopInfo after removing the last backedge from a + /// loop--now the "unloop". This updates the loop forest and parent loops for + /// each block so that Unloop is no longer referenced, but the caller must + /// actually delete the Unloop object. + void updateUnloop(Loop *Unloop); + /// replacementPreservesLCSSAForm - Returns true if replacing From with To /// everywhere is guaranteed to preserve LCSSA form. bool replacementPreservesLCSSAForm(Instruction *From, Value *To) { diff --git a/contrib/llvm/include/llvm/Analysis/LoopIterator.h b/contrib/llvm/include/llvm/Analysis/LoopIterator.h new file mode 100644 index 000000000..269ac8074 --- /dev/null +++ b/contrib/llvm/include/llvm/Analysis/LoopIterator.h @@ -0,0 +1,186 @@ +//===--------- LoopIterator.h - Iterate over loop blocks --------*- 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 iterators to visit the basic blocks within a loop. +// +// These iterators currently visit blocks within subloops as well. +// Unfortunately we have no efficient way of summarizing loop exits which would +// allow skipping subloops during traversal. +// +// If you want to visit all blocks in a loop and don't need an ordered traveral, +// use Loop::block_begin() instead. +// +// This is intentionally designed to work with ill-formed loops in which the +// backedge has been deleted. The only prerequisite is that all blocks +// contained within the loop according to the most recent LoopInfo analysis are +// reachable from the loop header. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_LOOP_ITERATOR_H +#define LLVM_ANALYSIS_LOOP_ITERATOR_H + +#include "llvm/ADT/DepthFirstIterator.h" +#include "llvm/ADT/PostOrderIterator.h" +#include "llvm/Analysis/LoopInfo.h" + +namespace llvm { + +class LoopBlocksTraversal; + +/// Store the result of a depth first search within basic blocks contained by a +/// single loop. +/// +/// TODO: This could be generalized for any CFG region, or the entire CFG. +class LoopBlocksDFS { +public: + /// Postorder list iterators. + typedef std::vector::const_iterator POIterator; + typedef std::vector::const_reverse_iterator RPOIterator; + + friend class LoopBlocksTraversal; + +private: + Loop *L; + + /// Map each block to its postorder number. A block is only mapped after it is + /// preorder visited by DFS. It's postorder number is initially zero and set + /// to nonzero after it is finished by postorder traversal. + DenseMap PostNumbers; + std::vector PostBlocks; + +public: + LoopBlocksDFS(Loop *Container) : + L(Container), PostNumbers(NextPowerOf2(Container->getNumBlocks())) { + PostBlocks.reserve(Container->getNumBlocks()); + } + + Loop *getLoop() const { return L; } + + /// Traverse the loop blocks and store the DFS result. + void perform(LoopInfo *LI); + + /// Return true if postorder numbers are assigned to all loop blocks. + bool isComplete() const { return PostBlocks.size() == L->getNumBlocks(); } + + /// Iterate over the cached postorder blocks. + POIterator beginPostorder() const { + assert(isComplete() && "bad loop DFS"); + return PostBlocks.begin(); + } + POIterator endPostorder() const { return PostBlocks.end(); } + + /// Reverse iterate over the cached postorder blocks. + RPOIterator beginRPO() const { + assert(isComplete() && "bad loop DFS"); + return PostBlocks.rbegin(); + } + RPOIterator endRPO() const { return PostBlocks.rend(); } + + /// Return true if this block has been preorder visited. + bool hasPreorder(BasicBlock *BB) const { return PostNumbers.count(BB); } + + /// Return true if this block has a postorder number. + bool hasPostorder(BasicBlock *BB) const { + DenseMap::const_iterator I = PostNumbers.find(BB); + return I != PostNumbers.end() && I->second; + } + + /// Get a block's postorder number. + unsigned getPostorder(BasicBlock *BB) const { + DenseMap::const_iterator I = PostNumbers.find(BB); + assert(I != PostNumbers.end() && "block not visited by DFS"); + assert(I->second && "block not finished by DFS"); + return I->second; + } + + /// Get a block's reverse postorder number. + unsigned getRPO(BasicBlock *BB) const { + return 1 + PostBlocks.size() - getPostorder(BB); + } + + void clear() { + PostNumbers.clear(); + PostBlocks.clear(); + } +}; + +/// Traverse the blocks in a loop using a depth-first search. +class LoopBlocksTraversal { +public: + /// Graph traversal iterator. + typedef po_iterator POTIterator; + +private: + LoopBlocksDFS &DFS; + LoopInfo *LI; + +public: + LoopBlocksTraversal(LoopBlocksDFS &Storage, LoopInfo *LInfo) : + DFS(Storage), LI(LInfo) {} + + /// Postorder traversal over the graph. This only needs to be done once. + /// po_iterator "automatically" calls back to visitPreorder and + /// finishPostorder to record the DFS result. + POTIterator begin() { + assert(DFS.PostBlocks.empty() && "Need clear DFS result before traversing"); + assert(DFS.L->getNumBlocks() && "po_iterator cannot handle an empty graph"); + return po_ext_begin(DFS.L->getHeader(), *this); + } + POTIterator end() { + // po_ext_end interface requires a basic block, but ignores its value. + return po_ext_end(DFS.L->getHeader(), *this); + } + + /// Called by po_iterator upon reaching a block via a CFG edge. If this block + /// is contained in the loop and has not been visited, then mark it preorder + /// visited and return true. + /// + /// TODO: If anyone is interested, we could record preorder numbers here. + bool visitPreorder(BasicBlock *BB) { + if (!DFS.L->contains(LI->getLoopFor(BB))) + return false; + + return DFS.PostNumbers.insert(std::make_pair(BB, 0)).second; + } + + /// Called by po_iterator each time it advances, indicating a block's + /// postorder. + void finishPostorder(BasicBlock *BB) { + assert(DFS.PostNumbers.count(BB) && "Loop DFS skipped preorder"); + DFS.PostBlocks.push_back(BB); + DFS.PostNumbers[BB] = DFS.PostBlocks.size(); + } + + //===---------------------------------------------------------------------- + // Implement part of the std::set interface for the purpose of driving the + // generic po_iterator. + + /// Return true if the block is outside the loop or has already been visited. + /// Sorry if this is counterintuitive. + bool count(BasicBlock *BB) const { + return !DFS.L->contains(LI->getLoopFor(BB)) || DFS.PostNumbers.count(BB); + } + + /// If this block is contained in the loop and has not been visited, return + /// true and assign a preorder number. This is a proxy for visitPreorder + /// called by POIterator. + bool insert(BasicBlock *BB) { + return visitPreorder(BB); + } +}; + +/// Specialize DFSetTraits to record postorder numbers. +template<> struct DFSetTraits { + static void finishPostorder(BasicBlock *BB, LoopBlocksTraversal& LBT) { + LBT.finishPostorder(BB); + } +}; + +} // End namespace llvm + +#endif diff --git a/contrib/llvm/include/llvm/Analysis/LoopPass.h b/contrib/llvm/include/llvm/Analysis/LoopPass.h index 1603d2ea7..e6ed9bcce 100644 --- a/contrib/llvm/include/llvm/Analysis/LoopPass.h +++ b/contrib/llvm/include/llvm/Analysis/LoopPass.h @@ -84,7 +84,7 @@ public: class LPPassManager : public FunctionPass, public PMDataManager { public: static char ID; - explicit LPPassManager(int Depth); + explicit LPPassManager(); /// 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. diff --git a/contrib/llvm/include/llvm/Analysis/MemoryBuiltins.h b/contrib/llvm/include/llvm/Analysis/MemoryBuiltins.h index 22493f6f8..865d236f6 100644 --- a/contrib/llvm/include/llvm/Analysis/MemoryBuiltins.h +++ b/contrib/llvm/include/llvm/Analysis/MemoryBuiltins.h @@ -51,14 +51,14 @@ const CallInst *isArrayMalloc(const Value *I, const TargetData *TD); /// 0: PointerType is the malloc calls' return type. /// 1: PointerType is the bitcast's result type. /// >1: Unique PointerType cannot be determined, return NULL. -const PointerType *getMallocType(const CallInst *CI); +PointerType *getMallocType(const CallInst *CI); /// getMallocAllocatedType - Returns the Type allocated by malloc call. /// The Type depends on the number of bitcast uses of the malloc call: /// 0: PointerType is the malloc calls' return type. /// 1: PointerType is the bitcast's result type. /// >1: Unique PointerType cannot be determined, return NULL. -const Type *getMallocAllocatedType(const CallInst *CI); +Type *getMallocAllocatedType(const CallInst *CI); /// 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, diff --git a/contrib/llvm/include/llvm/Analysis/MemoryDependenceAnalysis.h b/contrib/llvm/include/llvm/Analysis/MemoryDependenceAnalysis.h index 34860e712..e18d937f6 100644 --- a/contrib/llvm/include/llvm/Analysis/MemoryDependenceAnalysis.h +++ b/contrib/llvm/include/llvm/Analysis/MemoryDependenceAnalysis.h @@ -52,9 +52,6 @@ namespace llvm { /// 1. Loads are clobbered by may-alias stores. /// 2. Loads are considered clobbered by partially-aliased loads. The /// client may choose to analyze deeper into these cases. - /// - /// A dependence query on the first instruction of the entry block will - /// return a clobber(self) result. Clobber, /// Def - This is a dependence on the specified instruction which @@ -76,11 +73,27 @@ namespace llvm { /// operands to the calls are the same. Def, + /// Other - This marker indicates that the query has no known dependency + /// in the specified block. More detailed state info is encoded in the + /// upper part of the pair (i.e. the Instruction*) + Other + }; + /// If DepType is "Other", the upper part of the pair + /// (i.e. the Instruction* part) is instead used to encode more detailed + /// type information as follows + enum OtherType { /// NonLocal - This marker indicates that the query has no dependency in /// the specified block. To find out more, the client should query other /// predecessor blocks. - NonLocal + NonLocal = 0x4, + /// NonFuncLocal - This marker indicates that the query has no + /// dependency in the specified function. + NonFuncLocal = 0x8, + /// Unknown - This marker indicates that the query dependency + /// is unknown. + Unknown = 0xc }; + typedef PointerIntPair PairTy; PairTy Value; explicit MemDepResult(PairTy V) : Value(V) {} @@ -98,19 +111,21 @@ namespace llvm { return MemDepResult(PairTy(Inst, Clobber)); } static MemDepResult getNonLocal() { - return MemDepResult(PairTy(0, NonLocal)); + return MemDepResult( + PairTy(reinterpret_cast(NonLocal), Other)); + } + static MemDepResult getNonFuncLocal() { + return MemDepResult( + PairTy(reinterpret_cast(NonFuncLocal), Other)); } static MemDepResult getUnknown() { - return MemDepResult(PairTy(0, Clobber)); + return MemDepResult( + PairTy(reinterpret_cast(Unknown), Other)); } /// isClobber - Return true if this MemDepResult represents a query that is /// a instruction clobber dependency. - bool isClobber() const { return Value.getInt() == Clobber && getInst(); } - - /// isUnknown - Return true if this MemDepResult represents a query which - /// cannot and/or will not be computed. - bool isUnknown() const { return Value.getInt() == Clobber && !getInst(); } + bool isClobber() const { return Value.getInt() == Clobber; } /// isDef - Return true if this MemDepResult represents a query that is /// a instruction definition dependency. @@ -119,11 +134,31 @@ namespace llvm { /// isNonLocal - Return true if this MemDepResult represents a query that /// is transparent to the start of the block, but where a non-local hasn't /// been done. - bool isNonLocal() const { return Value.getInt() == NonLocal; } + bool isNonLocal() const { + return Value.getInt() == Other + && Value.getPointer() == reinterpret_cast(NonLocal); + } + + /// isNonFuncLocal - Return true if this MemDepResult represents a query + /// that is transparent to the start of the function. + bool isNonFuncLocal() const { + return Value.getInt() == Other + && Value.getPointer() == reinterpret_cast(NonFuncLocal); + } + /// isUnknown - Return true if this MemDepResult represents a query which + /// cannot and/or will not be computed. + bool isUnknown() const { + return Value.getInt() == Other + && Value.getPointer() == reinterpret_cast(Unknown); + } + /// getInst() - If this is a normal dependency, return the instruction that /// is depended on. Otherwise, return null. - Instruction *getInst() const { return Value.getPointer(); } + Instruction *getInst() const { + if (Value.getInt() == Other) return NULL; + return Value.getPointer(); + } bool operator==(const MemDepResult &M) const { return Value == M.Value; } bool operator!=(const MemDepResult &M) const { return Value != M.Value; } diff --git a/contrib/llvm/include/llvm/Analysis/RegionPass.h b/contrib/llvm/include/llvm/Analysis/RegionPass.h index 1a93859ba..68f12012b 100644 --- a/contrib/llvm/include/llvm/Analysis/RegionPass.h +++ b/contrib/llvm/include/llvm/Analysis/RegionPass.h @@ -88,7 +88,7 @@ class RGPassManager : public FunctionPass, public PMDataManager { public: static char ID; - explicit RGPassManager(int Depth); + explicit RGPassManager(); /// @brief Execute all of the passes scheduled for execution. /// diff --git a/contrib/llvm/include/llvm/Analysis/ScalarEvolution.h b/contrib/llvm/include/llvm/Analysis/ScalarEvolution.h index 554524a12..10d933e68 100644 --- a/contrib/llvm/include/llvm/Analysis/ScalarEvolution.h +++ b/contrib/llvm/include/llvm/Analysis/ScalarEvolution.h @@ -103,7 +103,7 @@ namespace llvm { /// getType - Return the LLVM type of this SCEV expression. /// - const Type *getType() const; + Type *getType() const; /// isZero - Return true if the expression is a constant zero. /// @@ -241,31 +241,94 @@ namespace llvm { /// ValueExprMapType ValueExprMap; + /// ExitLimit - Information about the number of loop iterations for + /// which a loop exit's branch condition evaluates to the not-taken path. + /// This is a temporary pair of exact and max expressions that are + /// eventually summarized in ExitNotTakenInfo and BackedgeTakenInfo. + struct ExitLimit { + const SCEV *Exact; + const SCEV *Max; + + /*implicit*/ ExitLimit(const SCEV *E) : Exact(E), Max(E) {} + + ExitLimit(const SCEV *E, const SCEV *M) : Exact(E), Max(M) {} + + /// hasAnyInfo - Test whether this ExitLimit contains any computed + /// information, or whether it's all SCEVCouldNotCompute values. + bool hasAnyInfo() const { + return !isa(Exact) || + !isa(Max); + } + }; + + /// ExitNotTakenInfo - Information about the number of times a particular + /// loop exit may be reached before exiting the loop. + struct ExitNotTakenInfo { + AssertingVH ExitingBlock; + const SCEV *ExactNotTaken; + PointerIntPair NextExit; + + ExitNotTakenInfo() : ExitingBlock(0), ExactNotTaken(0) {} + + /// isCompleteList - Return true if all loop exits are computable. + bool isCompleteList() const { + return NextExit.getInt() == 0; + } + + void setIncomplete() { NextExit.setInt(1); } + + /// getNextExit - Return a pointer to the next exit's not-taken info. + ExitNotTakenInfo *getNextExit() const { + return NextExit.getPointer(); + } + + void setNextExit(ExitNotTakenInfo *ENT) { NextExit.setPointer(ENT); } + }; + /// BackedgeTakenInfo - Information about the backedge-taken count /// of a loop. This currently includes an exact count and a maximum count. /// - struct BackedgeTakenInfo { - /// Exact - An expression indicating the exact backedge-taken count of - /// the loop if it is known, or a SCEVCouldNotCompute otherwise. - const SCEV *Exact; + class BackedgeTakenInfo { + /// ExitNotTaken - A list of computable exits and their not-taken counts. + /// Loops almost never have more than one computable exit. + ExitNotTakenInfo ExitNotTaken; /// Max - An expression indicating the least maximum backedge-taken /// count of the loop that is known, or a SCEVCouldNotCompute. const SCEV *Max; - /*implicit*/ BackedgeTakenInfo(const SCEV *exact) : - Exact(exact), Max(exact) {} + public: + BackedgeTakenInfo() : Max(0) {} - BackedgeTakenInfo(const SCEV *exact, const SCEV *max) : - Exact(exact), Max(max) {} + /// Initialize BackedgeTakenInfo from a list of exact exit counts. + BackedgeTakenInfo( + SmallVectorImpl< std::pair > &ExitCounts, + bool Complete, const SCEV *MaxCount); /// hasAnyInfo - Test whether this BackedgeTakenInfo contains any /// computed information, or whether it's all SCEVCouldNotCompute /// values. bool hasAnyInfo() const { - return !isa(Exact) || - !isa(Max); + return ExitNotTaken.ExitingBlock || !isa(Max); } + + /// getExact - Return an expression indicating the exact backedge-taken + /// count of the loop if it is known, or SCEVCouldNotCompute + /// otherwise. This is the number of times the loop header can be + /// guaranteed to execute, minus one. + const SCEV *getExact(ScalarEvolution *SE) const; + + /// getExact - Return the number of times this loop exit may fall through + /// to the back edge, or SCEVCouldNotCompute. The loop is guaranteed not + /// to exit via this block before this number of iterations, but may exit + /// via another block. + const SCEV *getExact(BasicBlock *ExitingBlock, ScalarEvolution *SE) const; + + /// getMax - Get the max backedge taken count for the loop. + const SCEV *getMax(ScalarEvolution *SE) const; + + /// clear - Invalidate this result and free associated memory. + void clear(); }; /// BackedgeTakenCounts - Cache the backedge-taken count of the loops for @@ -365,64 +428,59 @@ namespace llvm { /// loop will iterate. BackedgeTakenInfo ComputeBackedgeTakenCount(const Loop *L); - /// ComputeBackedgeTakenCountFromExit - Compute the number of times the - /// backedge of the specified loop will execute if it exits via the - /// specified block. - BackedgeTakenInfo ComputeBackedgeTakenCountFromExit(const Loop *L, - BasicBlock *ExitingBlock); - - /// ComputeBackedgeTakenCountFromExitCond - Compute the number of times the - /// backedge of the specified loop will execute if its exit condition - /// were a conditional branch of ExitCond, TBB, and FBB. - BackedgeTakenInfo - ComputeBackedgeTakenCountFromExitCond(const Loop *L, - Value *ExitCond, - BasicBlock *TBB, - BasicBlock *FBB); - - /// ComputeBackedgeTakenCountFromExitCondICmp - Compute the number of - /// times the backedge of the specified loop will execute if its exit - /// condition were a conditional branch of the ICmpInst ExitCond, TBB, - /// and FBB. - BackedgeTakenInfo - ComputeBackedgeTakenCountFromExitCondICmp(const Loop *L, - ICmpInst *ExitCond, - BasicBlock *TBB, - BasicBlock *FBB); - - /// ComputeLoadConstantCompareBackedgeTakenCount - Given an exit condition + /// ComputeExitLimit - Compute the number of times the backedge of the + /// specified loop will execute if it exits via the specified block. + ExitLimit ComputeExitLimit(const Loop *L, BasicBlock *ExitingBlock); + + /// ComputeExitLimitFromCond - Compute the number of times the backedge of + /// the specified loop will execute if its exit condition were a conditional + /// branch of ExitCond, TBB, and FBB. + ExitLimit ComputeExitLimitFromCond(const Loop *L, + Value *ExitCond, + BasicBlock *TBB, + BasicBlock *FBB); + + /// ComputeExitLimitFromICmp - Compute the number of times the backedge of + /// the specified loop will execute if its exit condition were a conditional + /// branch of the ICmpInst ExitCond, TBB, and FBB. + ExitLimit ComputeExitLimitFromICmp(const Loop *L, + ICmpInst *ExitCond, + BasicBlock *TBB, + BasicBlock *FBB); + + /// ComputeLoadConstantCompareExitLimit - Given an exit condition /// of 'icmp op load X, cst', try to see if we can compute the /// backedge-taken count. - BackedgeTakenInfo - ComputeLoadConstantCompareBackedgeTakenCount(LoadInst *LI, - Constant *RHS, - const Loop *L, - ICmpInst::Predicate p); - - /// ComputeBackedgeTakenCountExhaustively - If the loop is known to execute - /// a constant number of times (the condition evolves only from constants), + ExitLimit ComputeLoadConstantCompareExitLimit(LoadInst *LI, + Constant *RHS, + const Loop *L, + ICmpInst::Predicate p); + + /// ComputeExitCountExhaustively - If the loop is known to execute a + /// constant number of times (the condition evolves only from constants), /// try to evaluate a few iterations of the loop until we get the exit /// condition gets a value of ExitWhen (true or false). If we cannot - /// evaluate the backedge-taken count of the loop, return CouldNotCompute. - const SCEV *ComputeBackedgeTakenCountExhaustively(const Loop *L, - Value *Cond, - bool ExitWhen); + /// evaluate the exit count of the loop, return CouldNotCompute. + const SCEV *ComputeExitCountExhaustively(const Loop *L, + Value *Cond, + bool ExitWhen); - /// HowFarToZero - Return the number of times a backedge comparing the - /// specified value to zero will execute. If not computable, return + /// HowFarToZero - Return the number of times an exit condition comparing + /// the specified value to zero will execute. If not computable, return /// CouldNotCompute. - BackedgeTakenInfo HowFarToZero(const SCEV *V, const Loop *L); + ExitLimit HowFarToZero(const SCEV *V, const Loop *L); - /// HowFarToNonZero - Return the number of times a backedge checking the - /// specified value for nonzero will execute. If not computable, return + /// HowFarToNonZero - Return the number of times an exit condition checking + /// the specified value for nonzero will execute. If not computable, return /// CouldNotCompute. - BackedgeTakenInfo HowFarToNonZero(const SCEV *V, const Loop *L); + ExitLimit HowFarToNonZero(const SCEV *V, const Loop *L); - /// HowManyLessThans - Return the number of times a backedge containing the - /// specified less-than comparison will execute. If not computable, return - /// CouldNotCompute. isSigned specifies whether the less-than is signed. - BackedgeTakenInfo HowManyLessThans(const SCEV *LHS, const SCEV *RHS, - const Loop *L, bool isSigned); + /// HowManyLessThans - Return the number of times an exit condition + /// containing the specified less-than comparison will execute. If not + /// computable, return CouldNotCompute. isSigned specifies whether the + /// less-than is signed. + ExitLimit HowManyLessThans(const SCEV *LHS, const SCEV *RHS, + const Loop *L, bool isSigned); /// getPredecessorWithUniqueSuccessorForBB - Return a predecessor of BB /// (which may not be an immediate predecessor) which has exactly one @@ -450,7 +508,8 @@ namespace llvm { /// FoundLHS, and FoundRHS is true. bool isImpliedCondOperandsHelper(ICmpInst::Predicate Pred, const SCEV *LHS, const SCEV *RHS, - const SCEV *FoundLHS, const SCEV *FoundRHS); + const SCEV *FoundLHS, + const SCEV *FoundRHS); /// getConstantEvolutionLoopExitValue - If we know that the specified Phi is /// in the header of its containing loop, we know the loop executes a @@ -479,17 +538,17 @@ namespace llvm { /// the SCEV framework. This primarily includes integer types, and it /// can optionally include pointer types if the ScalarEvolution class /// has access to target-specific information. - bool isSCEVable(const Type *Ty) const; + bool isSCEVable(Type *Ty) const; /// getTypeSizeInBits - Return the size in bits of the specified type, /// for which isSCEVable must return true. - uint64_t getTypeSizeInBits(const Type *Ty) const; + uint64_t getTypeSizeInBits(Type *Ty) const; /// getEffectiveSCEVType - Return a type with the same bitwidth as /// the given type and which represents how SCEV will treat the given /// type, for which isSCEVable must return true. For pointer types, /// this is the pointer-sized integer type. - const Type *getEffectiveSCEVType(const Type *Ty) const; + Type *getEffectiveSCEVType(Type *Ty) const; /// getSCEV - Return a SCEV expression for the full generality of the /// specified expression. @@ -497,11 +556,11 @@ namespace llvm { const SCEV *getConstant(ConstantInt *V); const SCEV *getConstant(const APInt& Val); - const SCEV *getConstant(const Type *Ty, uint64_t V, bool isSigned = false); - const SCEV *getTruncateExpr(const SCEV *Op, const Type *Ty); - const SCEV *getZeroExtendExpr(const SCEV *Op, const Type *Ty); - const SCEV *getSignExtendExpr(const SCEV *Op, const Type *Ty); - const SCEV *getAnyExtendExpr(const SCEV *Op, const Type *Ty); + const SCEV *getConstant(Type *Ty, uint64_t V, bool isSigned = false); + const SCEV *getTruncateExpr(const SCEV *Op, Type *Ty); + const SCEV *getZeroExtendExpr(const SCEV *Op, Type *Ty); + const SCEV *getSignExtendExpr(const SCEV *Op, Type *Ty); + const SCEV *getAnyExtendExpr(const SCEV *Op, Type *Ty); const SCEV *getAddExpr(SmallVectorImpl &Ops, SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap); const SCEV *getAddExpr(const SCEV *LHS, const SCEV *RHS, @@ -529,6 +588,14 @@ namespace llvm { Ops.push_back(RHS); return getMulExpr(Ops, Flags); } + const SCEV *getMulExpr(const SCEV *Op0, const SCEV *Op1, const SCEV *Op2, + SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap) { + SmallVector Ops; + Ops.push_back(Op0); + Ops.push_back(Op1); + Ops.push_back(Op2); + return getMulExpr(Ops, Flags); + } const SCEV *getUDivExpr(const SCEV *LHS, const SCEV *RHS); const SCEV *getAddRecExpr(const SCEV *Start, const SCEV *Step, const Loop *L, SCEV::NoWrapFlags Flags); @@ -550,19 +617,19 @@ namespace llvm { /// getSizeOfExpr - Return an expression for sizeof on the given type. /// - const SCEV *getSizeOfExpr(const Type *AllocTy); + const SCEV *getSizeOfExpr(Type *AllocTy); /// getAlignOfExpr - Return an expression for alignof on the given type. /// - const SCEV *getAlignOfExpr(const Type *AllocTy); + const SCEV *getAlignOfExpr(Type *AllocTy); /// getOffsetOfExpr - Return an expression for offsetof on the given field. /// - const SCEV *getOffsetOfExpr(const StructType *STy, unsigned FieldNo); + const SCEV *getOffsetOfExpr(StructType *STy, unsigned FieldNo); /// getOffsetOfExpr - Return an expression for offsetof on the given field. /// - const SCEV *getOffsetOfExpr(const Type *CTy, Constant *FieldNo); + const SCEV *getOffsetOfExpr(Type *CTy, Constant *FieldNo); /// getNegativeSCEV - Return the SCEV object corresponding to -V. /// @@ -579,33 +646,33 @@ namespace llvm { /// getTruncateOrZeroExtend - Return a SCEV corresponding to a conversion /// of the input value to the specified type. If the type must be /// extended, it is zero extended. - const SCEV *getTruncateOrZeroExtend(const SCEV *V, const Type *Ty); + const SCEV *getTruncateOrZeroExtend(const SCEV *V, Type *Ty); /// getTruncateOrSignExtend - Return a SCEV corresponding to a conversion /// of the input value to the specified type. If the type must be /// extended, it is sign extended. - const SCEV *getTruncateOrSignExtend(const SCEV *V, const Type *Ty); + const SCEV *getTruncateOrSignExtend(const SCEV *V, Type *Ty); /// getNoopOrZeroExtend - Return a SCEV corresponding to a conversion of /// the input value to the specified type. If the type must be extended, /// it is zero extended. The conversion must not be narrowing. - const SCEV *getNoopOrZeroExtend(const SCEV *V, const Type *Ty); + const SCEV *getNoopOrZeroExtend(const SCEV *V, Type *Ty); /// getNoopOrSignExtend - Return a SCEV corresponding to a conversion of /// the input value to the specified type. If the type must be extended, /// it is sign extended. The conversion must not be narrowing. - const SCEV *getNoopOrSignExtend(const SCEV *V, const Type *Ty); + const SCEV *getNoopOrSignExtend(const SCEV *V, Type *Ty); /// getNoopOrAnyExtend - Return a SCEV corresponding to a conversion of /// the input value to the specified type. If the type must be extended, /// it is extended with unspecified bits. The conversion must not be /// narrowing. - const SCEV *getNoopOrAnyExtend(const SCEV *V, const Type *Ty); + const SCEV *getNoopOrAnyExtend(const SCEV *V, Type *Ty); /// getTruncateOrNoop - Return a SCEV corresponding to a conversion of the /// input value to the specified type. The conversion must not be /// widening. - const SCEV *getTruncateOrNoop(const SCEV *V, const Type *Ty); + const SCEV *getTruncateOrNoop(const SCEV *V, Type *Ty); /// getUMaxFromMismatchedTypes - Promote the operands to the wider of /// the types using zero-extension, and then perform a umax operation @@ -653,6 +720,23 @@ namespace llvm { bool isLoopBackedgeGuardedByCond(const Loop *L, ICmpInst::Predicate Pred, const SCEV *LHS, const SCEV *RHS); + /// getSmallConstantTripCount - Returns the maximum trip count of this loop + /// as a normal unsigned value, if possible. Returns 0 if the trip count is + /// unknown or not constant. + unsigned getSmallConstantTripCount(Loop *L, BasicBlock *ExitBlock); + + /// getSmallConstantTripMultiple - Returns the largest constant divisor of + /// the trip count of this loop as a normal unsigned value, if + /// possible. This means that the actual trip count is always a multiple of + /// the returned value (don't forget the trip count could very well be zero + /// as well!). + unsigned getSmallConstantTripMultiple(Loop *L, BasicBlock *ExitBlock); + + // getExitCount - Get the expression for the number of loop iterations for + // which this loop is guaranteed not to exit via ExitingBlock. Otherwise + // return SCEVCouldNotCompute. + const SCEV *getExitCount(Loop *L, BasicBlock *ExitingBlock); + /// getBackedgeTakenCount - If the specified loop has a predictable /// backedge-taken count, return it, otherwise return a SCEVCouldNotCompute /// object. The backedge-taken count is the number of times the loop header diff --git a/contrib/llvm/include/llvm/Analysis/ScalarEvolutionExpander.h b/contrib/llvm/include/llvm/Analysis/ScalarEvolutionExpander.h index a8c03b221..a4ad1451d 100644 --- a/contrib/llvm/include/llvm/Analysis/ScalarEvolutionExpander.h +++ b/contrib/llvm/include/llvm/Analysis/ScalarEvolutionExpander.h @@ -64,16 +64,34 @@ namespace llvm { /// in a more literal form. bool CanonicalMode; + /// When invoked from LSR, the expander is in "strength reduction" mode. The + /// only difference is that phi's are only reused if they are already in + /// "expanded" form. + bool LSRMode; + typedef IRBuilder BuilderType; BuilderType Builder; +#ifndef NDEBUG + const char *DebugType; +#endif + friend struct SCEVVisitor; public: /// SCEVExpander - Construct a SCEVExpander in "canonical" mode. explicit SCEVExpander(ScalarEvolution &se, const char *name) : SE(se), IVName(name), IVIncInsertLoop(0), IVIncInsertPos(0), - CanonicalMode(true), Builder(se.getContext(), TargetFolder(se.TD)) {} + CanonicalMode(true), LSRMode(false), + Builder(se.getContext(), TargetFolder(se.TD)) { +#ifndef NDEBUG + DebugType = ""; +#endif + } + +#ifndef NDEBUG + void setDebugType(const char* s) { DebugType = s; } +#endif /// clear - Erase the contents of the InsertedExpressions map so that users /// trying to expand the same expression into multiple BasicBlocks or @@ -88,13 +106,21 @@ namespace llvm { /// canonical induction variable of the specified type for the specified /// loop (inserting one if there is none). A canonical induction variable /// starts at zero and steps by one on each iteration. - PHINode *getOrInsertCanonicalInductionVariable(const Loop *L, - const Type *Ty); + PHINode *getOrInsertCanonicalInductionVariable(const Loop *L, Type *Ty); + + /// hoistStep - Utility for hoisting an IV increment. + static bool hoistStep(Instruction *IncV, Instruction *InsertPos, + const DominatorTree *DT); + + /// replaceCongruentIVs - replace congruent phis with their most canonical + /// representative. Return the number of phis eliminated. + unsigned replaceCongruentIVs(Loop *L, const DominatorTree *DT, + SmallVectorImpl &DeadInsts); /// expandCodeFor - Insert code to directly compute the specified SCEV /// expression into the program. The inserted code is inserted into the /// specified block. - Value *expandCodeFor(const SCEV *SH, const Type *Ty, Instruction *I); + Value *expandCodeFor(const SCEV *SH, Type *Ty, Instruction *I); /// setIVIncInsertPos - Set the current IV increment loop and position. void setIVIncInsertPos(const Loop *L, Instruction *Pos) { @@ -127,13 +153,14 @@ namespace llvm { /// is useful for late optimization passes. void disableCanonicalMode() { CanonicalMode = false; } + void enableLSRMode() { LSRMode = true; } + /// clearInsertPoint - Clear the current insertion point. This is useful /// if the instruction that had been serving as the insertion point may /// have been deleted. void clearInsertPoint() { Builder.ClearInsertionPoint(); } - private: LLVMContext &getContext() const { return SE.getContext(); } @@ -145,20 +172,20 @@ namespace llvm { /// reusing an existing cast if a suitable one exists, moving an existing /// cast if a suitable one exists but isn't in the right place, or /// or creating a new one. - Value *ReuseOrCreateCast(Value *V, const Type *Ty, + Value *ReuseOrCreateCast(Value *V, Type *Ty, Instruction::CastOps Op, BasicBlock::iterator IP); /// InsertNoopCastOfTo - Insert a cast of V to the specified type, /// which must be possible with a noop cast, doing what we can to /// share the casts. - Value *InsertNoopCastOfTo(Value *V, const Type *Ty); + Value *InsertNoopCastOfTo(Value *V, Type *Ty); /// expandAddToGEP - Expand a SCEVAddExpr with a pointer type into a GEP /// instead of using ptrtoint+arithmetic+inttoptr. Value *expandAddToGEP(const SCEV *const *op_begin, const SCEV *const *op_end, - const PointerType *PTy, const Type *Ty, Value *V); + PointerType *PTy, Type *Ty, Value *V); Value *expand(const SCEV *S); @@ -166,7 +193,7 @@ namespace llvm { /// expression into the program. The inserted code is inserted into the /// SCEVExpander's current insertion point. If a type is specified, the /// result will be expanded to have that type, with a cast if necessary. - Value *expandCodeFor(const SCEV *SH, const Type *Ty = 0); + Value *expandCodeFor(const SCEV *SH, Type *Ty = 0); /// isInsertedInstruction - Return true if the specified instruction was /// inserted by the code rewriter. If so, the client should not modify the @@ -208,11 +235,15 @@ namespace llvm { 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); + Value *expandAddRecExprLiterally(const SCEVAddRecExpr *); PHINode *getAddRecExprPHILiterally(const SCEVAddRecExpr *Normalized, const Loop *L, - const Type *ExpandTy, - const Type *IntTy); + Type *ExpandTy, + Type *IntTy); }; } diff --git a/contrib/llvm/include/llvm/Analysis/ScalarEvolutionExpressions.h b/contrib/llvm/include/llvm/Analysis/ScalarEvolutionExpressions.h index 856d92c97..b6f0ae54c 100644 --- a/contrib/llvm/include/llvm/Analysis/ScalarEvolutionExpressions.h +++ b/contrib/llvm/include/llvm/Analysis/ScalarEvolutionExpressions.h @@ -42,7 +42,7 @@ namespace llvm { public: ConstantInt *getValue() const { return V; } - const Type *getType() const { return V->getType(); } + Type *getType() const { return V->getType(); } /// Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const SCEVConstant *S) { return true; } @@ -57,14 +57,14 @@ namespace llvm { class SCEVCastExpr : public SCEV { protected: const SCEV *Op; - const Type *Ty; + Type *Ty; SCEVCastExpr(const FoldingSetNodeIDRef ID, - unsigned SCEVTy, const SCEV *op, const Type *ty); + unsigned SCEVTy, const SCEV *op, Type *ty); public: const SCEV *getOperand() const { return Op; } - const Type *getType() const { return Ty; } + Type *getType() const { return Ty; } /// Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const SCEVCastExpr *S) { return true; } @@ -83,7 +83,7 @@ namespace llvm { friend class ScalarEvolution; SCEVTruncateExpr(const FoldingSetNodeIDRef ID, - const SCEV *op, const Type *ty); + const SCEV *op, Type *ty); public: /// Methods for support type inquiry through isa, cast, and dyn_cast: @@ -101,7 +101,7 @@ namespace llvm { friend class ScalarEvolution; SCEVZeroExtendExpr(const FoldingSetNodeIDRef ID, - const SCEV *op, const Type *ty); + const SCEV *op, Type *ty); public: /// Methods for support type inquiry through isa, cast, and dyn_cast: @@ -119,7 +119,7 @@ namespace llvm { friend class ScalarEvolution; SCEVSignExtendExpr(const FoldingSetNodeIDRef ID, - const SCEV *op, const Type *ty); + const SCEV *op, Type *ty); public: /// Methods for support type inquiry through isa, cast, and dyn_cast: @@ -158,7 +158,7 @@ namespace llvm { op_iterator op_begin() const { return Operands; } op_iterator op_end() const { return Operands + NumOperands; } - const Type *getType() const { return getOperand(0)->getType(); } + Type *getType() const { return getOperand(0)->getType(); } NoWrapFlags getNoWrapFlags(NoWrapFlags Mask = NoWrapMask) const { return (NoWrapFlags)(SubclassData & Mask); @@ -214,7 +214,7 @@ namespace llvm { } public: - const Type *getType() const { + Type *getType() const { // Use the type of the last operand, which is likely to be a pointer // type, if there is one. This doesn't usually matter, but it can help // reduce casts when the expressions are expanded. @@ -263,7 +263,7 @@ namespace llvm { const SCEV *getLHS() const { return LHS; } const SCEV *getRHS() const { return RHS; } - const Type *getType() const { + Type *getType() const { // In most cases the types of LHS and RHS will be the same, but in some // crazy cases one or the other may be a pointer. ScalarEvolution doesn't // depend on the type for correctness, but handling types carefully can @@ -441,11 +441,11 @@ namespace llvm { /// folded with other operations into something unrecognizable. This /// is mainly only useful for pretty-printing and other situations /// where it isn't absolutely required for these to succeed. - bool isSizeOf(const Type *&AllocTy) const; - bool isAlignOf(const Type *&AllocTy) const; - bool isOffsetOf(const Type *&STy, Constant *&FieldNo) const; + bool isSizeOf(Type *&AllocTy) const; + bool isAlignOf(Type *&AllocTy) const; + bool isOffsetOf(Type *&STy, Constant *&FieldNo) const; - const Type *getType() const { return getValPtr()->getType(); } + Type *getType() const { return getValPtr()->getType(); } /// Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const SCEVUnknown *S) { return true; } diff --git a/contrib/llvm/include/llvm/Argument.h b/contrib/llvm/include/llvm/Argument.h index ff8637881..cd7488266 100644 --- a/contrib/llvm/include/llvm/Argument.h +++ b/contrib/llvm/include/llvm/Argument.h @@ -39,7 +39,7 @@ public: /// Argument ctor - If Function argument is specified, this argument is /// inserted at the end of the argument list for the function. /// - explicit Argument(const Type *Ty, const Twine &Name = "", Function *F = 0); + explicit Argument(Type *Ty, const Twine &Name = "", Function *F = 0); inline const Function *getParent() const { return Parent; } inline Function *getParent() { return Parent; } diff --git a/contrib/llvm/include/llvm/Attributes.h b/contrib/llvm/include/llvm/Attributes.h index 233eab8bf..2d7b33b29 100644 --- a/contrib/llvm/include/llvm/Attributes.h +++ b/contrib/llvm/include/llvm/Attributes.h @@ -65,8 +65,7 @@ const Attributes StackAlignment = 7<<26; ///< Alignment of stack for ///of alignment with +1 bias ///0 means unaligned (different from ///alignstack(1)) -const Attributes Hotpatch = 1<<29; ///< Function should have special - ///'hotpatch' sequence in prologue +const Attributes ReturnsTwice = 1<<29; ///< Function can return twice const Attributes UWTable = 1<<30; ///< Function must be in a unwind ///table const Attributes NonLazyBind = 1U<<31; ///< Function is called early and/or @@ -93,7 +92,7 @@ const Attributes ParameterOnly = ByVal | Nest | StructRet | NoCapture; const Attributes FunctionOnly = NoReturn | NoUnwind | ReadNone | ReadOnly | NoInline | AlwaysInline | OptimizeForSize | StackProtect | StackProtectReq | NoRedZone | NoImplicitFloat | Naked | InlineHint | StackAlignment | - Hotpatch | UWTable | NonLazyBind; + UWTable | NonLazyBind | ReturnsTwice; /// @brief Parameter attributes that do not apply to vararg call arguments. const Attributes VarArgsIncompatible = StructRet; @@ -107,7 +106,7 @@ const Attributes MutuallyIncompatible[4] = { }; /// @brief Which attributes cannot be applied to a type. -Attributes typeIncompatible(const Type *Ty); +Attributes typeIncompatible(Type *Ty); /// This turns an int alignment (a power of 2, normally) into the /// form used internally in Attributes. diff --git a/contrib/llvm/include/llvm/AutoUpgrade.h b/contrib/llvm/include/llvm/AutoUpgrade.h index 5ce20b69e..8ca3548f5 100644 --- a/contrib/llvm/include/llvm/AutoUpgrade.h +++ b/contrib/llvm/include/llvm/AutoUpgrade.h @@ -43,6 +43,10 @@ namespace llvm { /// This function checks debug info intrinsics. If an intrinsic is invalid /// then this function simply removes the intrinsic. void CheckDebugInfoIntrinsics(Module *M); + + /// This function upgrades the old pre-3.0 exception handling system to the + /// new one. N.B. This will be removed in 3.1. + void UpgradeExceptionHandling(Module *M); } // End llvm namespace #endif diff --git a/contrib/llvm/include/llvm/BasicBlock.h b/contrib/llvm/include/llvm/BasicBlock.h index 3b953c06a..1cd8dc55a 100644 --- a/contrib/llvm/include/llvm/BasicBlock.h +++ b/contrib/llvm/include/llvm/BasicBlock.h @@ -22,6 +22,7 @@ namespace llvm { +class LandingPadInst; class TerminatorInst; class LLVMContext; class BlockAddress; @@ -144,6 +145,14 @@ public: return const_cast(this)->getFirstNonPHIOrDbgOrLifetime(); } + /// getFirstInsertionPt - Returns an iterator to the first instruction in this + /// block that is suitable for inserting a non-PHI instruction. In particular, + /// it skips all PHIs and LandingPad instructions. + iterator getFirstInsertionPt(); + const_iterator getFirstInsertionPt() const { + return const_cast(this)->getFirstInsertionPt(); + } + /// removeFromParent - This method unlinks 'this' from the containing /// function, but does not delete it. /// @@ -258,6 +267,14 @@ public: /// to refer to basic block New instead of to us. void replaceSuccessorsPhiUsesWith(BasicBlock *New); + /// isLandingPad - Return true if this basic block is a landing pad. I.e., + /// it's the destination of the 'unwind' edge of an invoke instruction. + bool isLandingPad() const; + + /// getLandingPadInst() - Return the landingpad instruction associated with + /// the landing pad. + LandingPadInst *getLandingPadInst(); + private: /// AdjustBlockAddressRefCount - BasicBlock stores the number of BlockAddress /// objects using it. This is almost always 0, sometimes one, possibly but diff --git a/contrib/llvm/include/llvm/Bitcode/LLVMBitCodes.h b/contrib/llvm/include/llvm/Bitcode/LLVMBitCodes.h index df68bd5dd..4b0dcc362 100644 --- a/contrib/llvm/include/llvm/Bitcode/LLVMBitCodes.h +++ b/contrib/llvm/include/llvm/Bitcode/LLVMBitCodes.h @@ -205,6 +205,23 @@ namespace bitc { BINOP_XOR = 12 }; + /// These are values used in the bitcode files to encode AtomicRMW operations. + /// The values of these enums have no fixed relation to the LLVM IR enum + /// values. Changing these will break compatibility with old files. + enum RMWOperations { + RMW_XCHG = 0, + RMW_ADD = 1, + RMW_SUB = 2, + RMW_AND = 3, + RMW_NAND = 4, + RMW_OR = 5, + RMW_XOR = 6, + RMW_MAX = 7, + RMW_MIN = 8, + RMW_UMAX = 9, + RMW_UMIN = 10 + }; + /// OverflowingBinaryOperatorOptionalFlags - Flags for serializing /// OverflowingBinaryOperator's SubclassOptionalData contents. enum OverflowingBinaryOperatorOptionalFlags { @@ -218,6 +235,23 @@ namespace bitc { PEO_EXACT = 0 }; + /// Encoded AtomicOrdering values. + enum AtomicOrderingCodes { + ORDERING_NOTATOMIC = 0, + ORDERING_UNORDERED = 1, + ORDERING_MONOTONIC = 2, + ORDERING_ACQUIRE = 3, + ORDERING_RELEASE = 4, + ORDERING_ACQREL = 5, + ORDERING_SEQCST = 6 + }; + + /// Encoded SynchronizationScope values. + enum AtomicSynchScopeCodes { + SYNCHSCOPE_SINGLETHREAD = 0, + SYNCHSCOPE_CROSSTHREAD = 1 + }; + // The function body block (FUNCTION_BLOCK_ID) describes function bodies. It // can contain a constant block (CONSTANTS_BLOCK_ID). enum FunctionCodes { @@ -266,7 +300,19 @@ namespace bitc { FUNC_CODE_INST_CALL = 34, // CALL: [attr, fnty, fnid, args...] - FUNC_CODE_DEBUG_LOC = 35 // DEBUG_LOC: [Line,Col,ScopeVal, IAVal] + FUNC_CODE_DEBUG_LOC = 35, // DEBUG_LOC: [Line,Col,ScopeVal, IAVal] + FUNC_CODE_INST_FENCE = 36, // FENCE: [ordering, synchscope] + FUNC_CODE_INST_CMPXCHG = 37, // CMPXCHG: [ptrty,ptr,cmp,new, align, vol, + // ordering, synchscope] + FUNC_CODE_INST_ATOMICRMW = 38, // ATOMICRMW: [ptrty,ptr,val, operation, + // align, vol, + // ordering, synchscope] + FUNC_CODE_INST_RESUME = 39, // RESUME: [opval] + FUNC_CODE_INST_LANDINGPAD = 40, // LANDINGPAD: [ty,val,val,num,id0,val0...] + FUNC_CODE_INST_LOADATOMIC = 41, // LOAD: [opty, op, align, vol, + // ordering, synchscope] + FUNC_CODE_INST_STOREATOMIC = 42 // STORE: [ptrty,ptr,val, align, vol + // ordering, synchscope] }; } // 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 f8a70293c..d8e64071a 100644 --- a/contrib/llvm/include/llvm/CodeGen/Analysis.h +++ b/contrib/llvm/include/llvm/CodeGen/Analysis.h @@ -33,12 +33,12 @@ class SelectionDAG; /// of insertvalue or extractvalue indices that identify a member, return /// the linearized index of the start of the member. /// -unsigned ComputeLinearIndex(const Type *Ty, +unsigned ComputeLinearIndex(Type *Ty, const unsigned *Indices, const unsigned *IndicesEnd, unsigned CurIndex = 0); -inline unsigned ComputeLinearIndex(const Type *Ty, +inline unsigned ComputeLinearIndex(Type *Ty, ArrayRef Indices, unsigned CurIndex = 0) { return ComputeLinearIndex(Ty, Indices.begin(), Indices.end(), CurIndex); @@ -51,7 +51,7 @@ inline unsigned ComputeLinearIndex(const Type *Ty, /// If Offsets is non-null, it points to a vector to be filled in /// with the in-memory offsets of each of the individual values. /// -void ComputeValueVTs(const TargetLowering &TLI, const Type *Ty, +void ComputeValueVTs(const TargetLowering &TLI, Type *Ty, SmallVectorImpl &ValueVTs, SmallVectorImpl *Offsets = 0, uint64_t StartingOffset = 0); diff --git a/contrib/llvm/include/llvm/CodeGen/CalcSpillWeights.h b/contrib/llvm/include/llvm/CodeGen/CalcSpillWeights.h index 60edcc584..2f76a6cc5 100644 --- a/contrib/llvm/include/llvm/CodeGen/CalcSpillWeights.h +++ b/contrib/llvm/include/llvm/CodeGen/CalcSpillWeights.h @@ -49,11 +49,6 @@ namespace llvm { const MachineLoopInfo &loops) : MF(mf), LIS(lis), Loops(loops) {} - /// CalculateRegClass - recompute the register class for reg from its uses. - /// Since the register class can affect the allocation hint, this function - /// should be called before CalculateWeightAndHint if both are called. - void CalculateRegClass(unsigned reg); - /// CalculateWeightAndHint - (re)compute li's spill weight and allocation /// hint. void CalculateWeightAndHint(LiveInterval &li); diff --git a/contrib/llvm/include/llvm/CodeGen/FastISel.h b/contrib/llvm/include/llvm/CodeGen/FastISel.h index 962a4e263..18202d93b 100644 --- a/contrib/llvm/include/llvm/CodeGen/FastISel.h +++ b/contrib/llvm/include/llvm/CodeGen/FastISel.h @@ -54,8 +54,18 @@ protected: const TargetInstrInfo &TII; const TargetLowering &TLI; const TargetRegisterInfo &TRI; + + /// 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) + MachineInstr *EmitStartPt; + public: /// getLastLocalValue - Return the position of the last instruction /// emitted for materializing constants for use in the current block. @@ -63,7 +73,10 @@ public: /// setLastLocalValue - Update the position of the last instruction /// emitted for materializing constants for use in the current block. - void setLastLocalValue(MachineInstr *I) { LastLocalValue = I; } + 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. @@ -358,6 +371,11 @@ private: /// 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. + void flushLocalValueMap(); + /// hasTrivialKill - 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 84bbf4804..09dac8547 100644 --- a/contrib/llvm/include/llvm/CodeGen/FunctionLoweringInfo.h +++ b/contrib/llvm/include/llvm/CodeGen/FunctionLoweringInfo.h @@ -19,6 +19,7 @@ #include "llvm/Instructions.h" #include "llvm/ADT/APInt.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DenseSet.h" #include "llvm/ADT/IndexedMap.h" #include "llvm/ADT/SmallVector.h" #ifndef NDEBUG @@ -139,7 +140,7 @@ public: unsigned CreateReg(EVT VT); - unsigned CreateRegs(const Type *Ty); + unsigned CreateRegs(Type *Ty); unsigned InitializeRegForValue(const Value *V) { unsigned &R = ValueMap[V]; @@ -198,12 +199,12 @@ public: LiveOutRegInfo[Reg].IsValid = false; } - /// setByValArgumentFrameIndex - Record frame index for the byval + /// setArgumentFrameIndex - Record frame index for the byval /// argument. - void setByValArgumentFrameIndex(const Argument *A, int FI); + void setArgumentFrameIndex(const Argument *A, int FI); - /// getByValArgumentFrameIndex - Get frame index for the byval argument. - int getByValArgumentFrameIndex(const Argument *A); + /// getArgumentFrameIndex - Get frame index for the byval argument. + int getArgumentFrameIndex(const Argument *A); private: /// LiveOutRegInfo - Information about live out vregs. @@ -220,6 +221,11 @@ void AddCatchInfo(const CallInst &I, void CopyCatchInfo(const BasicBlock *SuccBB, const BasicBlock *LPad, MachineModuleInfo *MMI, FunctionLoweringInfo &FLI); +/// AddLandingPadInfo - Extract the exception handling information from the +/// landingpad instruction and add them to the specified machine module info. +void AddLandingPadInfo(const LandingPadInst &I, MachineModuleInfo &MMI, + MachineBasicBlock *MBB); + } // end namespace llvm #endif diff --git a/contrib/llvm/include/llvm/CodeGen/ISDOpcodes.h b/contrib/llvm/include/llvm/CodeGen/ISDOpcodes.h index 459cecda2..184e96dc4 100644 --- a/contrib/llvm/include/llvm/CodeGen/ISDOpcodes.h +++ b/contrib/llvm/include/llvm/CodeGen/ISDOpcodes.h @@ -95,7 +95,7 @@ namespace ISD { // execution to HANDLER. Many platform-related details also :) EH_RETURN, - // OUTCHAIN = EH_SJLJ_SETJMP(INCHAIN, buffer) + // RESULT, OUTCHAIN = EH_SJLJ_SETJMP(INCHAIN, buffer) // This corresponds to the eh.sjlj.setjmp intrinsic. // It takes an input chain and a pointer to the jump buffer as inputs // and returns an outchain. @@ -323,6 +323,12 @@ namespace ISD { // i1 then the high bits must conform to getBooleanContents. SELECT, + // Select with a vector condition (op #0) and two vector operands (ops #1 + // and #2), returning a vector result. All vectors have the same length. + // Much like the scalar select and setcc, each bit in the condition selects + // whether the corresponding result element is taken from op #1 or op #2. + VSELECT, + // Select with condition operator - This selects between a true value and // a false value (ops #2 and #3) based on the boolean result of comparing // the lhs and rhs (ops #0 and #1) of a conditional expression with the @@ -333,16 +339,10 @@ namespace ISD { // true. If the result value type is not i1 then the high bits conform // to getBooleanContents. The operands to this are the left and right // operands to compare (ops #0, and #1) and the condition code to compare - // them with (op #2) as a CondCodeSDNode. + // them with (op #2) as a CondCodeSDNode. If the operands are vector types + // then the result type must also be a vector type. SETCC, - // RESULT = VSETCC(LHS, RHS, COND) operator - This evaluates to a vector of - // integer elements with all bits of the result elements set to true if the - // comparison is true or all cleared if the comparison is false. The - // operands to this are the left and right operands to compare (LHS/RHS) and - // the condition code to compare them with (COND) as a CondCodeSDNode. - VSETCC, - // SHL_PARTS/SRA_PARTS/SRL_PARTS - These operators are used for expanded // integer shift operations, just like ADD/SUB_PARTS. The operation // ordering is: @@ -566,14 +566,19 @@ namespace ISD { // HANDLENODE node - Used as a handle for various purposes. HANDLENODE, - // TRAMPOLINE - This corresponds to the init_trampoline intrinsic. - // It takes as input a token chain, the pointer to the trampoline, - // the pointer to the nested function, the pointer to pass for the - // 'nest' parameter, a SRCVALUE for the trampoline and another for - // the nested function (allowing targets to access the original - // Function*). It produces the result of the intrinsic and a token - // chain as output. - TRAMPOLINE, + // INIT_TRAMPOLINE - This corresponds to the init_trampoline intrinsic. It + // takes as input a token chain, the pointer to the trampoline, the pointer + // to the nested function, the pointer to pass for the 'nest' parameter, a + // SRCVALUE for the trampoline and another for the nested function (allowing + // targets to access the original Function*). It produces a token chain as + // output. + INIT_TRAMPOLINE, + + // ADJUST_TRAMPOLINE - This corresponds to the adjust_trampoline intrinsic. + // It takes a pointer to the trampoline and produces a (possibly) new + // pointer to the same trampoline with platform-specific adjustments + // applied. The pointer it returns points to an executable block of code. + ADJUST_TRAMPOLINE, // TRAP - Trapping instruction TRAP, @@ -592,22 +597,27 @@ namespace ISD { // and produces an output chain. MEMBARRIER, + // OUTCHAIN = ATOMIC_FENCE(INCHAIN, ordering, scope) + // This corresponds to the fence instruction. It takes an input chain, and + // two integer constants: an AtomicOrdering and a SynchronizationScope. + ATOMIC_FENCE, + + // Val, OUTCHAIN = ATOMIC_LOAD(INCHAIN, ptr) + // This corresponds to "load atomic" instruction. + ATOMIC_LOAD, + + // OUTCHAIN = ATOMIC_LOAD(INCHAIN, ptr, val) + // This corresponds to "store atomic" instruction. + ATOMIC_STORE, + // Val, OUTCHAIN = ATOMIC_CMP_SWAP(INCHAIN, ptr, cmp, swap) - // this corresponds to the atomic.lcs intrinsic. - // cmp is compared to *ptr, and if equal, swap is stored in *ptr. - // the return is always the original value in *ptr + // This corresponds to the cmpxchg instruction. ATOMIC_CMP_SWAP, // Val, OUTCHAIN = ATOMIC_SWAP(INCHAIN, ptr, amt) - // this corresponds to the atomic.swap intrinsic. - // amt is stored to *ptr atomically. - // the return is always the original value in *ptr - ATOMIC_SWAP, - // Val, OUTCHAIN = ATOMIC_LOAD_[OpName](INCHAIN, ptr, amt) - // this corresponds to the atomic.load.[OpName] intrinsic. - // op(*ptr, amt) is stored to *ptr atomically. - // the return is always the original value in *ptr + // These correspond to the atomicrmw instruction. + ATOMIC_SWAP, ATOMIC_LOAD_ADD, ATOMIC_LOAD_SUB, ATOMIC_LOAD_AND, diff --git a/contrib/llvm/include/llvm/CodeGen/LexicalScopes.h b/contrib/llvm/include/llvm/CodeGen/LexicalScopes.h new file mode 100644 index 000000000..0271c5d85 --- /dev/null +++ b/contrib/llvm/include/llvm/CodeGen/LexicalScopes.h @@ -0,0 +1,248 @@ +//===- LexicalScopes.cpp - Collecting lexical scope info -*- C++ -*--------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements LexicalScopes analysis. +// +// This pass collects lexical scope information and maps machine instructions +// to respective lexical scopes. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_LEXICALSCOPES_H +#define LLVM_CODEGEN_LEXICALSCOPES_H + +#include "llvm/Metadata.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/DebugLoc.h" +#include "llvm/Support/ValueHandle.h" +#include +namespace llvm { + +class MachineInstr; +class MachineBasicBlock; +class MachineFunction; +class LexicalScope; + +//===----------------------------------------------------------------------===// +/// InsnRange - This is used to track range of instructions with identical +/// lexical scope. +/// +typedef std::pair InsnRange; + +//===----------------------------------------------------------------------===// +/// LexicalScopes - This class provides interface to collect and use lexical +/// scoping information from machine instruction. +/// +class LexicalScopes { +public: + LexicalScopes() : MF(NULL), CurrentFnLexicalScope(NULL) { } + virtual ~LexicalScopes(); + + /// initialize - Scan machine function and constuct lexical scope nest. + virtual void initialize(const MachineFunction &); + + /// releaseMemory - release memory. + virtual void releaseMemory(); + + /// empty - Return true if there is any lexical scope information available. + bool empty() { return CurrentFnLexicalScope == NULL; } + + /// isCurrentFunctionScope - Return true if given lexical scope represents + /// current function. + bool isCurrentFunctionScope(const LexicalScope *LS) { + return LS == CurrentFnLexicalScope; + } + + /// getCurrentFunctionScope - Return lexical scope for the current function. + LexicalScope *getCurrentFunctionScope() const { return CurrentFnLexicalScope;} + + /// getMachineBasicBlocks - Populate given set using machine basic blocks + /// which have machine instructions that belong to lexical scope identified by + /// DebugLoc. + void getMachineBasicBlocks(DebugLoc DL, + SmallPtrSet &MBBs); + + /// dominates - Return true if DebugLoc's lexical scope dominates at least one + /// machine instruction's lexical scope in a given machine basic block. + bool dominates(DebugLoc DL, MachineBasicBlock *MBB); + + /// findLexicalScope - Find lexical scope, either regular or inlined, for the + /// given DebugLoc. Return NULL if not found. + LexicalScope *findLexicalScope(DebugLoc DL); + + /// getAbstractScopesList - Return a reference to list of abstract scopes. + ArrayRef getAbstractScopesList() const { + return AbstractScopesList; + } + + /// findAbstractScope - Find an abstract scope or return NULL. + LexicalScope *findAbstractScope(const MDNode *N) { + return AbstractScopeMap.lookup(N); + } + + /// findInlinedScope - Find an inlined scope for the given DebugLoc or return + /// NULL. + LexicalScope *findInlinedScope(DebugLoc DL) { + return InlinedLexicalScopeMap.lookup(DL); + } + + /// findLexicalScope - Find regular lexical scope or return NULL. + LexicalScope *findLexicalScope(const MDNode *N) { + return LexicalScopeMap.lookup(N); + } + + /// dump - Print data structures to dbgs(). + void dump(); + +private: + + /// getOrCreateLexicalScope - Find lexical scope for the given DebugLoc. If + /// not available then create new lexical scope. + LexicalScope *getOrCreateLexicalScope(DebugLoc DL); + + /// getOrCreateRegularScope - Find or create a regular lexical scope. + LexicalScope *getOrCreateRegularScope(MDNode *Scope); + + /// getOrCreateInlinedScope - Find or create an inlined lexical scope. + LexicalScope *getOrCreateInlinedScope(MDNode *Scope, MDNode *InlinedAt); + + /// getOrCreateAbstractScope - Find or create an abstract lexical scope. + LexicalScope *getOrCreateAbstractScope(const MDNode *N); + + /// extractLexicalScopes - Extract instruction ranges for each lexical scopes + /// for the given machine function. + void extractLexicalScopes(SmallVectorImpl &MIRanges, + DenseMap &M); + void constructScopeNest(LexicalScope *Scope); + void assignInstructionRanges(SmallVectorImpl &MIRanges, + DenseMap &M); + +private: + const MachineFunction *MF; + + /// LexicalScopeMap - Tracks the scopes in the current function. Owns the + /// contained LexicalScope*s. + DenseMap LexicalScopeMap; + + /// InlinedLexicalScopeMap - Tracks inlined function scopes in current function. + DenseMap InlinedLexicalScopeMap; + + /// AbstractScopeMap - These scopes are not included LexicalScopeMap. + /// AbstractScopes owns its LexicalScope*s. + DenseMap AbstractScopeMap; + + /// AbstractScopesList - Tracks abstract scopes constructed while processing + /// a function. + SmallVectorAbstractScopesList; + + /// CurrentFnLexicalScope - Top level scope for the current function. + /// + LexicalScope *CurrentFnLexicalScope; +}; + +//===----------------------------------------------------------------------===// +/// LexicalScope - This class is used to track scope information. +/// +class LexicalScope { + +public: + LexicalScope(LexicalScope *P, const MDNode *D, const MDNode *I, bool A) + : Parent(P), Desc(D), InlinedAtLocation(I), AbstractScope(A), + LastInsn(0), FirstInsn(0), DFSIn(0), DFSOut(0), IndentLevel(0) { + if (Parent) + Parent->addChild(this); + } + + 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; } + + /// addChild - Add a child scope. + void addChild(LexicalScope *S) { Children.push_back(S); } + + /// openInsnRange - This scope covers instruction range starting from MI. + void openInsnRange(const MachineInstr *MI) { + if (!FirstInsn) + FirstInsn = MI; + + if (Parent) + Parent->openInsnRange(MI); + } + + /// extendInsnRange - Extend the current instruction range covered by + /// this scope. + void extendInsnRange(const MachineInstr *MI) { + assert (FirstInsn && "MI Range is not open!"); + LastInsn = MI; + if (Parent) + Parent->extendInsnRange(MI); + } + + /// closeInsnRange - Create a range based on FirstInsn and LastInsn collected + /// until now. This is used when a new scope is encountered while walking + /// machine instructions. + void closeInsnRange(LexicalScope *NewScope = NULL) { + assert (LastInsn && "Last insn missing!"); + Ranges.push_back(InsnRange(FirstInsn, LastInsn)); + FirstInsn = NULL; + LastInsn = NULL; + // If Parent dominates NewScope then do not close Parent's instruction + // range. + if (Parent && (!NewScope || !Parent->dominates(NewScope))) + Parent->closeInsnRange(NewScope); + } + + /// dominates - Return true if current scope dominsates given lexical scope. + bool dominates(const LexicalScope *S) const { + if (S == this) + return true; + if (DFSIn < S->getDFSIn() && DFSOut > S->getDFSOut()) + return true; + return false; + } + + // Depth First Search support to walk and manipulate LexicalScope hierarchy. + unsigned getDFSOut() const { return DFSOut; } + void setDFSOut(unsigned O) { DFSOut = O; } + unsigned getDFSIn() const { return DFSIn; } + void setDFSIn(unsigned I) { DFSIn = I; } + + /// dump - print lexical scope. + void dump() const; + +private: + LexicalScope *Parent; // Parent to this scope. + AssertingVH Desc; // Debug info descriptor. + AssertingVH InlinedAtLocation; // Location at which this + // scope is inlined. + bool AbstractScope; // Abstract Scope + SmallVector Children; // Scopes defined in scope. + // Contents not owned. + SmallVector Ranges; + + const MachineInstr *LastInsn; // Last instruction of this scope. + const MachineInstr *FirstInsn; // First instruction of this scope. + unsigned DFSIn, DFSOut; // In & Out Depth use to determine + // scope nesting. + mutable unsigned IndentLevel; // Private state for dump() +}; + +} // end llvm namespace + +#endif diff --git a/contrib/llvm/include/llvm/CodeGen/LiveInterval.h b/contrib/llvm/include/llvm/CodeGen/LiveInterval.h index 5fd4d3df2..2288c1a98 100644 --- a/contrib/llvm/include/llvm/CodeGen/LiveInterval.h +++ b/contrib/llvm/include/llvm/CodeGen/LiveInterval.h @@ -100,6 +100,7 @@ namespace llvm { bool isDefByCopy() const { return copy != 0; } /// Returns true if one or more kills are PHI nodes. + /// Obsolete, do not use! bool hasPHIKill() const { return flags & HAS_PHI_KILL; } /// Set the PHI kill flag on this value. void setHasPHIKill(bool hasKill) { @@ -313,7 +314,6 @@ namespace llvm { /// RenumberValues - Renumber all values in order of appearance and remove /// unused values. - /// Recalculate phi-kill flags in case any phi-def values were removed. void RenumberValues(LiveIntervals &lis); /// isOnlyLROfValNo - Return true if the specified live range is the only @@ -411,6 +411,14 @@ namespace llvm { return I == end() ? 0 : I->valno; } + /// getVNInfoBefore - Return the VNInfo that is live up to but not + /// 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()); + 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) { @@ -452,10 +460,10 @@ namespace llvm { addRangeFrom(LR, ranges.begin()); } - /// extendInBlock - If this interval is live before UseIdx in the basic - /// block that starts at StartIdx, extend it to be live at UseIdx and return - /// the value. If there is no live range before UseIdx, return NULL. - VNInfo *extendInBlock(SlotIndex StartIdx, SlotIndex UseIdx); + /// extendInBlock - If this interval 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. + 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 diff --git a/contrib/llvm/include/llvm/CodeGen/LiveStackAnalysis.h b/contrib/llvm/include/llvm/CodeGen/LiveStackAnalysis.h index 8a8dcaf57..86c4d7c11 100644 --- a/contrib/llvm/include/llvm/CodeGen/LiveStackAnalysis.h +++ b/contrib/llvm/include/llvm/CodeGen/LiveStackAnalysis.h @@ -25,6 +25,8 @@ namespace llvm { class LiveStacks : public MachineFunctionPass { + const TargetRegisterInfo *TRI; + /// Special pool allocator for VNInfo's (LiveInterval val#). /// VNInfo::Allocator VNInfoAllocator; diff --git a/contrib/llvm/include/llvm/CodeGen/LiveVariables.h b/contrib/llvm/include/llvm/CodeGen/LiveVariables.h index f9b81b1ea..7ba901fc2 100644 --- a/contrib/llvm/include/llvm/CodeGen/LiveVariables.h +++ b/contrib/llvm/include/llvm/CodeGen/LiveVariables.h @@ -231,6 +231,7 @@ public: } assert(Removed && "Register is not used by this instruction!"); + (void)Removed; return true; } @@ -265,6 +266,7 @@ public: } } assert(Removed && "Register is not defined by this instruction!"); + (void)Removed; return true; } diff --git a/contrib/llvm/include/llvm/CodeGen/MachineBasicBlock.h b/contrib/llvm/include/llvm/CodeGen/MachineBasicBlock.h index 397e59ef1..5a20e952b 100644 --- a/contrib/llvm/include/llvm/CodeGen/MachineBasicBlock.h +++ b/contrib/llvm/include/llvm/CodeGen/MachineBasicBlock.h @@ -232,7 +232,7 @@ public: /// setIsLandingPad - Indicates the block is a landing pad. That is /// this basic block is entered via an exception handler. - void setIsLandingPad() { IsLandingPad = true; } + void setIsLandingPad(bool V = true) { IsLandingPad = V; } /// getLandingPadSuccessor - If this block has a successor that is a landing /// pad, return it. Otherwise return NULL. diff --git a/contrib/llvm/include/llvm/CodeGen/MachineBlockFrequency.h b/contrib/llvm/include/llvm/CodeGen/MachineBlockFrequencyInfo.h similarity index 60% rename from contrib/llvm/include/llvm/CodeGen/MachineBlockFrequency.h rename to contrib/llvm/include/llvm/CodeGen/MachineBlockFrequencyInfo.h index 25bf1f08d..416d40bf3 100644 --- a/contrib/llvm/include/llvm/CodeGen/MachineBlockFrequency.h +++ b/contrib/llvm/include/llvm/CodeGen/MachineBlockFrequencyInfo.h @@ -1,4 +1,4 @@ -//====----- MachineBlockFrequency.h - MachineBlock Frequency Analysis ----====// +//====----- MachineBlockFrequencyInfo.h - MachineBlock Frequency Analysis ----====// // // The LLVM Compiler Infrastructure // @@ -11,10 +11,11 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CODEGEN_MACHINEBLOCKFREQUENCY_H -#define LLVM_CODEGEN_MACHINEBLOCKFREQUENCY_H +#ifndef LLVM_CODEGEN_MACHINEBLOCKFREQUENCYINFO_H +#define LLVM_CODEGEN_MACHINEBLOCKFREQUENCYINFO_H #include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/Support/BlockFrequency.h" #include namespace llvm { @@ -23,29 +24,29 @@ class MachineBranchProbabilityInfo; template class BlockFrequencyImpl; -/// MachineBlockFrequency pass uses BlockFrequencyImpl implementation to estimate +/// MachineBlockFrequencyInfo pass uses BlockFrequencyImpl implementation to estimate /// machine basic block frequencies. -class MachineBlockFrequency : public MachineFunctionPass { +class MachineBlockFrequencyInfo : public MachineFunctionPass { BlockFrequencyImpl *MBFI; public: static char ID; - MachineBlockFrequency(); + MachineBlockFrequencyInfo(); - ~MachineBlockFrequency(); + ~MachineBlockFrequencyInfo(); void getAnalysisUsage(AnalysisUsage &AU) const; bool runOnMachineFunction(MachineFunction &F); - /// getblockFreq - Return block frequency. Never return 0, value must be - /// positive. Please note that initial frequency is equal to 1024. It means + /// 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 the floating - /// points. - uint32_t getBlockFreq(MachineBasicBlock *MBB); + /// the other block frequencies. We do this to avoid using of floating points. + /// + BlockFrequency getBlockFreq(MachineBasicBlock *MBB) const; }; } diff --git a/contrib/llvm/include/llvm/CodeGen/MachineConstantPool.h b/contrib/llvm/include/llvm/CodeGen/MachineConstantPool.h index beb16a282..29f4f443b 100644 --- a/contrib/llvm/include/llvm/CodeGen/MachineConstantPool.h +++ b/contrib/llvm/include/llvm/CodeGen/MachineConstantPool.h @@ -34,15 +34,15 @@ class raw_ostream; /// Abstract base class for all machine specific constantpool value subclasses. /// class MachineConstantPoolValue { - const Type *Ty; + Type *Ty; public: - explicit MachineConstantPoolValue(const Type *ty) : Ty(ty) {} + explicit MachineConstantPoolValue(Type *ty) : Ty(ty) {} virtual ~MachineConstantPoolValue() {} /// getType - get type of this MachineConstantPoolValue. /// - const Type *getType() const { return Ty; } + Type *getType() const { return Ty; } /// getRelocationInfo - This method classifies the entry according to @@ -54,7 +54,7 @@ public: virtual int getExistingMachineCPValue(MachineConstantPool *CP, unsigned Alignment) = 0; - virtual void AddSelectionDAGCSEId(FoldingSetNodeID &ID) = 0; + virtual void addSelectionDAGCSEId(FoldingSetNodeID &ID) = 0; /// print - Implement operator<< virtual void print(raw_ostream &O) const = 0; @@ -104,7 +104,7 @@ public: return Alignment & ~(1 << (sizeof(unsigned)*CHAR_BIT-1)); } - const Type *getType() const; + Type *getType() const; /// getRelocationInfo - This method classifies the entry according to /// whether or not it may generate a relocation entry. This must be diff --git a/contrib/llvm/include/llvm/CodeGen/MachineFrameInfo.h b/contrib/llvm/include/llvm/CodeGen/MachineFrameInfo.h index 4ea6aa339..b347ca8e6 100644 --- a/contrib/llvm/include/llvm/CodeGen/MachineFrameInfo.h +++ b/contrib/llvm/include/llvm/CodeGen/MachineFrameInfo.h @@ -174,6 +174,10 @@ class MachineFrameInfo { /// StackProtectorIdx - The frame index for the stack protector. int StackProtectorIdx; + /// FunctionContextIdx - The frame index for the function context. Used for + /// SjLj exceptions. + int FunctionContextIdx; + /// MaxCallFrameSize - This contains the size of the largest call frame if the /// target uses frame setup/destroy pseudo instructions (as defined in the /// TargetFrameInfo class). This information is important for frame pointer @@ -220,6 +224,7 @@ public: AdjustsStack = false; HasCalls = false; StackProtectorIdx = -1; + FunctionContextIdx = -1; MaxCallFrameSize = 0; CSIValid = false; LocalFrameSize = 0; @@ -244,6 +249,11 @@ public: int getStackProtectorIndex() const { return StackProtectorIdx; } void setStackProtectorIndex(int I) { StackProtectorIdx = I; } + /// getFunctionContextIndex/setFunctionContextIndex - Return the index for the + /// function context object. This object is used for SjLj exceptions. + int getFunctionContextIndex() const { return FunctionContextIdx; } + void setFunctionContextIndex(int I) { FunctionContextIdx = I; } + /// isFrameAddressTaken - This method may be called any time after instruction /// selection is complete to determine if there is a call to /// \@llvm.frameaddress in this function. diff --git a/contrib/llvm/include/llvm/CodeGen/MachineInstr.h b/contrib/llvm/include/llvm/CodeGen/MachineInstr.h index 5b3d3ea62..cae38f347 100644 --- a/contrib/llvm/include/llvm/CodeGen/MachineInstr.h +++ b/contrib/llvm/include/llvm/CodeGen/MachineInstr.h @@ -32,6 +32,7 @@ namespace llvm { template class SmallVectorImpl; class AliasAnalysis; class TargetInstrInfo; +class TargetRegisterClass; class TargetRegisterInfo; class MachineFunction; class MachineMemOperand; @@ -58,8 +59,6 @@ public: }; private: const MCInstrDesc *MCID; // Instruction descriptor. - uint16_t NumImplicitOps; // Number of implicit operands (which - // are determined at construction time). uint8_t Flags; // Various bits of additional // information about machine @@ -78,9 +77,6 @@ private: MachineBasicBlock *Parent; // Pointer to the owning basic block. DebugLoc debugLoc; // Source line information. - // OperandComplete - Return true if it's illegal to add a new operand - bool OperandsComplete() const; - MachineInstr(const MachineInstr&); // DO NOT IMPLEMENT void operator=(const MachineInstr&); // DO NOT IMPLEMENT @@ -393,6 +389,30 @@ public: /// none is found. int findFirstPredOperandIdx() const; + /// findInlineAsmFlagIdx() - Find the index of the flag word operand that + /// corresponds to operand OpIdx on an inline asm instruction. Returns -1 if + /// getOperand(OpIdx) does not belong to an inline asm operand group. + /// + /// If GroupNo is not NULL, it will receive the number of the operand group + /// containing OpIdx. + /// + /// The flag operand is an immediate that can be decoded with methods like + /// InlineAsm::hasRegClassConstraint(). + /// + int findInlineAsmFlagIdx(unsigned OpIdx, unsigned *GroupNo = 0) const; + + /// getRegClassConstraint - Compute the static register class constraint for + /// operand OpIdx. For normal instructions, this is derived from the + /// MCInstrDesc. For inline assembly it is derived from the flag words. + /// + /// Returns NULL if the static register classs constraint cannot be + /// determined. + /// + const TargetRegisterClass* + getRegClassConstraint(unsigned OpIdx, + const TargetInstrInfo *TII, + const TargetRegisterInfo *TRI) const; + /// isRegTiedToUseOperand - Given the index of a register def operand, /// check if the register def is tied to a source operand, due to either /// two-address elimination or inline assembly constraints. Returns the diff --git a/contrib/llvm/include/llvm/CodeGen/MachineModuleInfo.h b/contrib/llvm/include/llvm/CodeGen/MachineModuleInfo.h index fa185c46d..2bf7f1788 100644 --- a/contrib/llvm/include/llvm/CodeGen/MachineModuleInfo.h +++ b/contrib/llvm/include/llvm/CodeGen/MachineModuleInfo.h @@ -34,7 +34,7 @@ #include "llvm/Pass.h" #include "llvm/GlobalValue.h" #include "llvm/Metadata.h" -#include "llvm/CodeGen/MachineLocation.h" +#include "llvm/MC/MachineLocation.h" #include "llvm/MC/MCContext.h" #include "llvm/Support/Dwarf.h" #include "llvm/Support/DebugLoc.h" @@ -107,36 +107,42 @@ 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. + /// FrameMoves - List of moves done by a function's prolog. Used to construct + /// frame maps by debug and exception handling consumers. std::vector FrameMoves; - // LandingPads - List of LandingPadInfo describing the landing pad information - // in the current function. + /// CompactUnwindEncoding - If the target supports it, this is the compact + /// unwind encoding. It replaces a function's CIE and FDE. + uint32_t CompactUnwindEncoding; + + /// LandingPads - List of LandingPadInfo describing the landing pad + /// information in the current function. std::vector LandingPads; - // Map of invoke call site index values to associated begin EH_LABEL for - // the current function. + /// LPadToCallSiteMap - Map a landing pad's EH symbol to the call site + /// indexes. + DenseMap > LPadToCallSiteMap; + + /// CallSiteMap - Map of invoke call site index values to associated begin + /// EH_LABEL for the current function. DenseMap CallSiteMap; - // The current call site index being processed, if any. 0 if none. + /// CurCallSite - The current call site index being processed, if any. 0 if + /// none. unsigned CurCallSite; - // TypeInfos - List of C++ TypeInfo used in the current function. - // + /// TypeInfos - List of C++ TypeInfo used in the current function. std::vector TypeInfos; - // FilterIds - List of typeids encoding filters used in the current function. - // + /// FilterIds - List of typeids encoding filters used in the current function. std::vector FilterIds; - // FilterEnds - List of the indices in FilterIds corresponding to filter - // terminators. - // + /// FilterEnds - List of the indices in FilterIds corresponding to filter + /// terminators. std::vector FilterEnds; - // Personalities - Vector of all personality functions ever seen. Used to emit - // common EH frames. + /// Personalities - Vector of all personality functions ever seen. Used to + /// emit common EH frames. std::vector Personalities; /// UsedFunctions - The functions in the @llvm.used list in a more easily @@ -144,7 +150,6 @@ class MachineModuleInfo : public ImmutablePass { /// llvm.compiler.used. SmallPtrSet UsedFunctions; - /// AddrLabelSymbols - This map keeps track of which symbol is being used for /// the specified basic block's address of label. MMIAddrLabelMap *AddrLabelSymbols; @@ -156,8 +161,9 @@ class MachineModuleInfo : public ImmutablePass { /// in this module. bool DbgInfoAvailable; - /// True if this module calls VarArg function with floating point arguments. - /// This is used to emit an undefined reference to fltused on Windows targets. + /// CallsExternalVAFunctionWithFloatingPointArguments - True if this module + /// calls VarArg function with floating point arguments. This is used to emit + /// an undefined reference to fltused on Windows targets. bool CallsExternalVAFunctionWithFloatingPointArguments; public: @@ -170,7 +176,8 @@ public: MachineModuleInfo(); // DUMMY CONSTRUCTOR, DO NOT CALL. // Real constructor. - MachineModuleInfo(const MCAsmInfo &MAI, const TargetAsmInfo *TAI); + MachineModuleInfo(const MCAsmInfo &MAI, const MCRegisterInfo &MRI, + const MCObjectFileInfo *MOFI); ~MachineModuleInfo(); bool doInitialization(); @@ -229,6 +236,15 @@ public: /// handling comsumers. std::vector &getFrameMoves() { return FrameMoves; } + /// getCompactUnwindEncoding - Returns the compact unwind encoding for a + /// function if the target supports the encoding. This encoding replaces a + /// function's CIE and FDE. + uint32_t getCompactUnwindEncoding() const { return CompactUnwindEncoding; } + + /// setCompactUnwindEncoding - Set the compact unwind encoding for a function + /// if the target supports the encoding. + void setCompactUnwindEncoding(uint32_t Enc) { CompactUnwindEncoding = Enc; } + /// getAddrLabelSymbol - Return the symbol to be used for the specified basic /// block when its address is taken. This cannot be its normal LBB label /// because the block may be accessed outside its containing function. @@ -286,12 +302,12 @@ public: /// addCatchTypeInfo - Provide the catch typeinfo for a landing pad. /// void addCatchTypeInfo(MachineBasicBlock *LandingPad, - std::vector &TyInfo); + ArrayRef TyInfo); /// addFilterTypeInfo - Provide the filter typeinfo for a landing pad. /// void addFilterTypeInfo(MachineBasicBlock *LandingPad, - std::vector &TyInfo); + ArrayRef TyInfo); /// addCleanup - Add a cleanup action for a landing pad. /// @@ -315,18 +331,42 @@ public: return LandingPads; } - /// setCallSiteBeginLabel - Map the begin label for a call site + /// setCallSiteLandingPad - Map the landing pad's EH symbol to the call + /// site indexes. + void setCallSiteLandingPad(MCSymbol *Sym, ArrayRef Sites); + + /// getCallSiteLandingPad - Get the call site indexes for a landing pad EH + /// symbol. + SmallVectorImpl &getCallSiteLandingPad(MCSymbol *Sym) { + assert(hasCallSiteLandingPad(Sym) && + "missing call site number for landing pad!"); + return LPadToCallSiteMap[Sym]; + } + + /// hasCallSiteLandingPad - Return true if the landing pad Eh symbol has an + /// associated call site. + bool hasCallSiteLandingPad(MCSymbol *Sym) { + return !LPadToCallSiteMap[Sym].empty(); + } + + /// setCallSiteBeginLabel - Map the begin label for a call site. void setCallSiteBeginLabel(MCSymbol *BeginLabel, unsigned Site) { CallSiteMap[BeginLabel] = Site; } - /// getCallSiteBeginLabel - Get the call site number for a begin label + /// getCallSiteBeginLabel - Get the call site number for a begin label. unsigned getCallSiteBeginLabel(MCSymbol *BeginLabel) { - assert(CallSiteMap.count(BeginLabel) && + assert(hasCallSiteBeginLabel(BeginLabel) && "Missing call site number for EH_LABEL!"); return CallSiteMap[BeginLabel]; } + /// hasCallSiteBeginLabel - Return true if the begin label has a call site + /// number associated with it. + bool hasCallSiteBeginLabel(MCSymbol *BeginLabel) { + return CallSiteMap[BeginLabel] != 0; + } + /// setCurrentCallSite - Set the call site currently being processed. void setCurrentCallSite(unsigned Site) { CurCallSite = Site; } diff --git a/contrib/llvm/include/llvm/CodeGen/MachineOperand.h b/contrib/llvm/include/llvm/CodeGen/MachineOperand.h index fdef574be..5440a636a 100644 --- a/contrib/llvm/include/llvm/CodeGen/MachineOperand.h +++ b/contrib/llvm/include/llvm/CodeGen/MachineOperand.h @@ -83,8 +83,23 @@ private: /// This is only valid on definitions of registers. bool IsDead : 1; - /// IsUndef - True if this is a register def / use of "undef", i.e. register - /// defined by an IMPLICIT_DEF. This is only valid on registers. + /// IsUndef - True if this register operand reads an "undef" value, i.e. the + /// read value doesn't matter. This flag can be set on both use and def + /// operands. On a sub-register def operand, it refers to the part of the + /// register that isn't written. On a full-register def operand, it is a + /// noop. See readsReg(). + /// + /// This is only valid on registers. + /// + /// Note that an instruction may have multiple operands referring to + /// the same register. In that case, the instruction may depend on those + /// operands reading the same dont-care value. For example: + /// + /// %vreg1 = XOR %vreg2, %vreg2 + /// + /// Any register can be used for %vreg2, and its value doesn't matter, but + /// the two operands must be the same register. + /// bool IsUndef : 1; /// IsEarlyClobber - True if this MO_Register 'def' operand is written to @@ -253,6 +268,15 @@ public: return IsDebug; } + /// readsReg - Returns true if this operand reads the previous value of its + /// register. A use operand with the flag set doesn't read its + /// register. A sub-register def implicitly reads the other parts of the + /// register being redefined unless the flag is set. + bool readsReg() const { + assert(isReg() && "Wrong MachineOperand accessor"); + return !isUndef() && (isUse() || getSubReg()); + } + /// getNextOperandForReg - Return the next MachineOperand in the function that /// uses or defines this register. MachineOperand *getNextOperandForReg() const { diff --git a/contrib/llvm/include/llvm/CodeGen/MachineRegisterInfo.h b/contrib/llvm/include/llvm/CodeGen/MachineRegisterInfo.h index 107972636..3866b2650 100644 --- a/contrib/llvm/include/llvm/CodeGen/MachineRegisterInfo.h +++ b/contrib/llvm/include/llvm/CodeGen/MachineRegisterInfo.h @@ -25,6 +25,12 @@ namespace llvm { /// registers, including vreg register classes, use/def chains for registers, /// etc. class MachineRegisterInfo { + const TargetRegisterInfo *const TRI; + + /// IsSSA - True when the machine function is in SSA form and virtual + /// registers have a single def. + bool IsSSA; + /// VRegInfo - Information we keep for each virtual register. /// /// Each element in this list contains the register class of the vreg and the @@ -65,7 +71,23 @@ class MachineRegisterInfo { public: explicit MachineRegisterInfo(const TargetRegisterInfo &TRI); ~MachineRegisterInfo(); - + + //===--------------------------------------------------------------------===// + // Function State + //===--------------------------------------------------------------------===// + + // isSSA - Returns true when the machine function is in SSA form. Early + // passes require the machine function to be in SSA form where every virtual + // register has a single defining instruction. + // + // The TwoAddressInstructionPass and PHIElimination passes take the machine + // function out of SSA form when they introduce multiple defs per virtual + // register. + bool isSSA() const { return IsSSA; } + + // leaveSSA - Indicates that the machine function is no longer in SSA form. + void leaveSSA() { IsSSA = false; } + //===--------------------------------------------------------------------===// // Register Info //===--------------------------------------------------------------------===// @@ -195,12 +217,25 @@ public: void setRegClass(unsigned Reg, const TargetRegisterClass *RC); /// constrainRegClass - Constrain the register class of the specified virtual - /// register to be a common subclass of RC and the current register class. - /// Return the new register class, or NULL if no such class exists. + /// register to be a common subclass of RC and the current register class, + /// but only if the new class has at least MinNumRegs registers. Return the + /// new register class, or NULL if no such class exists. /// This should only be used when the constraint is known to be trivial, like /// GR32 -> GR32_NOSP. Beware of increasing register pressure. + /// const TargetRegisterClass *constrainRegClass(unsigned Reg, - const TargetRegisterClass *RC); + const TargetRegisterClass *RC, + unsigned MinNumRegs = 0); + + /// recomputeRegClass - Try to find a legal super-class of Reg's register + /// class that still satisfies the constraints from the instructions using + /// Reg. Returns true if Reg was upgraded. + /// + /// This method can be used after constraints have been removed from a + /// virtual register, for example after removing instructions or splitting + /// the live range. + /// + bool recomputeRegClass(unsigned Reg, const TargetMachine&); /// createVirtualRegister - Create and return a new virtual register in the /// function with the specified register class. diff --git a/contrib/llvm/include/llvm/CodeGen/Passes.h b/contrib/llvm/include/llvm/CodeGen/Passes.h index e7928cb65..7a03ce905 100644 --- a/contrib/llvm/include/llvm/CodeGen/Passes.h +++ b/contrib/llvm/include/llvm/CodeGen/Passes.h @@ -24,7 +24,7 @@ namespace llvm { class MachineFunctionPass; class PassInfo; class TargetLowering; - class RegisterCoalescer; + class TargetRegisterClass; class raw_ostream; /// createUnreachableBlockEliminationPass - The LLVM code generator does not @@ -81,6 +81,9 @@ namespace llvm { /// register allocators. extern char &TwoAddressInstructionPassID; + /// RegisteCoalescer pass - This pass merges live ranges to eliminate copies. + extern char &RegisterCoalescerPassID; + /// SpillPlacement analysis. Suggest optimal placement of spill code between /// basic blocks. /// @@ -125,21 +128,15 @@ namespace llvm { /// FunctionPass *createDefaultPBQPRegisterAllocator(); - /// RegisterCoalescer Pass - Coalesce all copies possible. Can run - /// independently of the register allocator. - /// - RegisterCoalescer *createRegisterCoalescer(); - /// PrologEpilogCodeInserter Pass - This pass inserts prolog and epilog code, /// and eliminates abstract frame references. /// FunctionPass *createPrologEpilogCodeInserter(); - /// LowerSubregs Pass - This pass lowers subregs to register-register copies - /// which yields suboptimal, but correct code if the register allocator - /// cannot coalesce all subreg operations during allocation. + /// ExpandPostRAPseudos Pass - This pass expands pseudo instructions after + /// register allocation. /// - FunctionPass *createLowerSubregsPass(); + FunctionPass *createExpandPostRAPseudosPass(); /// createPostRAScheduler - This pass performs post register allocation /// scheduling. @@ -229,6 +226,14 @@ namespace llvm { /// FunctionPass *createExpandISelPseudosPass(); + /// createExecutionDependencyFixPass - This pass fixes execution time + /// problems with dependent instructions, such as switching execution + /// domains to match. + /// + /// The pass will examine instructions using and defining registers in RC. + /// + FunctionPass *createExecutionDependencyFixPass(const TargetRegisterClass *RC); + } // End llvm namespace #endif diff --git a/contrib/llvm/include/llvm/CodeGen/SelectionDAG.h b/contrib/llvm/include/llvm/CodeGen/SelectionDAG.h index 3ec5adabe..132983c50 100644 --- a/contrib/llvm/include/llvm/CodeGen/SelectionDAG.h +++ b/contrib/llvm/include/llvm/CodeGen/SelectionDAG.h @@ -450,6 +450,10 @@ public: SDValue getVectorShuffle(EVT VT, DebugLoc 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); + /// 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); @@ -560,17 +564,13 @@ public: /// SDValue getSetCC(DebugLoc 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"); return getNode(ISD::SETCC, DL, VT, LHS, RHS, getCondCode(Cond)); } - /// getVSetCC - Helper function to make it easier to build VSetCC's nodes - /// if you just have an ISD::CondCode instead of an SDValue. - /// - SDValue getVSetCC(DebugLoc DL, EVT VT, SDValue LHS, SDValue RHS, - ISD::CondCode Cond) { - return getNode(ISD::VSETCC, DL, VT, LHS, RHS, getCondCode(Cond)); - } - /// getSelectCC - Helper function to make it easier to build SelectCC's if you /// just have an ISD::CondCode instead of an SDValue. /// @@ -589,19 +589,37 @@ public: /// takes 3 operands SDValue getAtomic(unsigned Opcode, DebugLoc dl, EVT MemVT, SDValue Chain, SDValue Ptr, SDValue Cmp, SDValue Swp, - MachinePointerInfo PtrInfo, unsigned Alignment=0); + MachinePointerInfo PtrInfo, unsigned Alignment, + AtomicOrdering Ordering, + SynchronizationScope SynchScope); SDValue getAtomic(unsigned Opcode, DebugLoc dl, EVT MemVT, SDValue Chain, SDValue Ptr, SDValue Cmp, SDValue Swp, - MachineMemOperand *MMO); + MachineMemOperand *MMO, + AtomicOrdering Ordering, + SynchronizationScope SynchScope); - /// getAtomic - Gets a node for an atomic op, produces result and chain and - /// takes 2 operands. + /// 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 Ptr, SDValue Val, const Value* PtrVal, - unsigned Alignment = 0); + unsigned Alignment, AtomicOrdering Ordering, + SynchronizationScope SynchScope); SDValue getAtomic(unsigned Opcode, DebugLoc dl, EVT MemVT, SDValue Chain, - SDValue Ptr, SDValue Val, - MachineMemOperand *MMO); + 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 Chain, SDValue Ptr, const Value* PtrVal, + unsigned Alignment, + AtomicOrdering Ordering, + SynchronizationScope SynchScope); + SDValue getAtomic(unsigned Opcode, DebugLoc dl, EVT MemVT, EVT VT, + SDValue Chain, SDValue Ptr, 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, diff --git a/contrib/llvm/include/llvm/CodeGen/SelectionDAGNodes.h b/contrib/llvm/include/llvm/CodeGen/SelectionDAGNodes.h index a5c4201ef..6c7be69b4 100644 --- a/contrib/llvm/include/llvm/CodeGen/SelectionDAGNodes.h +++ b/contrib/llvm/include/llvm/CodeGen/SelectionDAGNodes.h @@ -20,6 +20,7 @@ #define LLVM_CODEGEN_SELECTIONDAGNODES_H #include "llvm/Constants.h" +#include "llvm/Instructions.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/GraphTraits.h" #include "llvm/ADT/ilist_node.h" @@ -917,6 +918,13 @@ public: bool isVolatile() const { return (SubclassData >> 5) & 1; } bool isNonTemporal() const { return (SubclassData >> 6) & 1; } + AtomicOrdering getOrdering() const { + return AtomicOrdering((SubclassData >> 7) & 15); + } + SynchronizationScope getSynchScope() const { + return SynchronizationScope((SubclassData >> 11) & 1); + } + /// Returns the SrcValue and offset that describes the location of the access const Value *getSrcValue() const { return MMO->getValue(); } int64_t getSrcValueOffset() const { return MMO->getOffset(); } @@ -968,6 +976,8 @@ public: N->getOpcode() == ISD::ATOMIC_LOAD_MAX || N->getOpcode() == ISD::ATOMIC_LOAD_UMIN || N->getOpcode() == ISD::ATOMIC_LOAD_UMAX || + N->getOpcode() == ISD::ATOMIC_LOAD || + N->getOpcode() == ISD::ATOMIC_STORE || N->isTargetMemoryOpcode(); } }; @@ -977,6 +987,23 @@ public: class AtomicSDNode : public MemSDNode { SDUse Ops[4]; + void InitAtomic(AtomicOrdering Ordering, SynchronizationScope SynchScope) { + // This must match encodeMemSDNodeFlags() in SelectionDAG.cpp. + assert((Ordering & 15) == Ordering && + "Ordering may not require more than 4 bits!"); + assert((SynchScope & 1) == SynchScope && + "SynchScope may not require more than 1 bit!"); + SubclassData |= Ordering << 7; + SubclassData |= SynchScope << 11; + assert(getOrdering() == Ordering && "Ordering encoding error!"); + assert(getSynchScope() == SynchScope && "Synch-scope encoding error!"); + + assert((readMem() || getOrdering() <= Monotonic) && + "Acquire/Release MachineMemOperand must be a load!"); + assert((writeMem() || getOrdering() <= Monotonic) && + "Acquire/Release MachineMemOperand must be a store!"); + } + public: // Opc: opcode for atomic // VTL: value type list @@ -988,20 +1015,28 @@ public: // Align: alignment of memory AtomicSDNode(unsigned Opc, DebugLoc dl, SDVTList VTL, EVT MemVT, SDValue Chain, SDValue Ptr, - SDValue Cmp, SDValue Swp, MachineMemOperand *MMO) + SDValue Cmp, SDValue Swp, MachineMemOperand *MMO, + AtomicOrdering Ordering, SynchronizationScope SynchScope) : MemSDNode(Opc, dl, VTL, MemVT, MMO) { - assert(readMem() && "Atomic MachineMemOperand is not a load!"); - assert(writeMem() && "Atomic MachineMemOperand is not a store!"); + InitAtomic(Ordering, SynchScope); InitOperands(Ops, Chain, Ptr, Cmp, Swp); } AtomicSDNode(unsigned Opc, DebugLoc dl, SDVTList VTL, EVT MemVT, SDValue Chain, SDValue Ptr, - SDValue Val, MachineMemOperand *MMO) + SDValue Val, MachineMemOperand *MMO, + AtomicOrdering Ordering, SynchronizationScope SynchScope) : MemSDNode(Opc, dl, VTL, MemVT, MMO) { - assert(readMem() && "Atomic MachineMemOperand is not a load!"); - assert(writeMem() && "Atomic MachineMemOperand is not a store!"); + InitAtomic(Ordering, SynchScope); InitOperands(Ops, Chain, Ptr, Val); } + AtomicSDNode(unsigned Opc, DebugLoc dl, SDVTList VTL, EVT MemVT, + SDValue Chain, SDValue Ptr, + MachineMemOperand *MMO, + AtomicOrdering Ordering, SynchronizationScope SynchScope) + : MemSDNode(Opc, dl, VTL, MemVT, MMO) { + InitAtomic(Ordering, SynchScope); + InitOperands(Ops, Chain, Ptr); + } const SDValue &getBasePtr() const { return getOperand(1); } const SDValue &getVal() const { return getOperand(2); } @@ -1025,7 +1060,9 @@ public: N->getOpcode() == ISD::ATOMIC_LOAD_MIN || N->getOpcode() == ISD::ATOMIC_LOAD_MAX || N->getOpcode() == ISD::ATOMIC_LOAD_UMIN || - N->getOpcode() == ISD::ATOMIC_LOAD_UMAX; + N->getOpcode() == ISD::ATOMIC_LOAD_UMAX || + N->getOpcode() == ISD::ATOMIC_LOAD || + N->getOpcode() == ISD::ATOMIC_STORE; } }; @@ -1291,7 +1328,7 @@ public: unsigned getAlignment() const { return Alignment; } unsigned char getTargetFlags() const { return TargetFlags; } - const Type *getType() const; + Type *getType() const; static bool classof(const ConstantPoolSDNode *) { return true; } static bool classof(const SDNode *N) { diff --git a/contrib/llvm/include/llvm/CodeGen/SlotIndexes.h b/contrib/llvm/include/llvm/CodeGen/SlotIndexes.h index 6eb318021..2d98864dc 100644 --- a/contrib/llvm/include/llvm/CodeGen/SlotIndexes.h +++ b/contrib/llvm/include/llvm/CodeGen/SlotIndexes.h @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// // -// This file implements SlotIndex and related classes. The purpuse of SlotIndex +// This file implements SlotIndex and related classes. The purpose of SlotIndex // is to describe a position at which a register can become live, or cease to // be live. // diff --git a/contrib/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h b/contrib/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h index 711280e98..ca40ccf85 100644 --- a/contrib/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h +++ b/contrib/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h @@ -33,42 +33,13 @@ namespace llvm { class TargetLoweringObjectFileELF : public TargetLoweringObjectFile { -protected: - /// TLSDataSection - Section directive for Thread Local data. - /// - const MCSection *TLSDataSection; // Defaults to ".tdata". - - /// TLSBSSSection - Section directive for Thread Local uninitialized data. - /// Null if this target doesn't support a BSS section. - /// - const MCSection *TLSBSSSection; // Defaults to ".tbss". - - const MCSection *DataRelSection; - const MCSection *DataRelLocalSection; - const MCSection *DataRelROSection; - const MCSection *DataRelROLocalSection; - - const MCSection *MergeableConst4Section; - const MCSection *MergeableConst8Section; - const MCSection *MergeableConst16Section; public: - TargetLoweringObjectFileELF(); - ~TargetLoweringObjectFileELF() {} - - virtual void Initialize(MCContext &Ctx, const TargetMachine &TM); - - virtual const MCSection *getEHFrameSection() const; - virtual const MCSection *getWin64EHFuncTableSection(StringRef) const { - return NULL; - } - virtual const MCSection *getWin64EHTableSection(StringRef) const{return NULL;} + virtual ~TargetLoweringObjectFileELF() {} virtual void emitPersonalityValue(MCStreamer &Streamer, const TargetMachine &TM, const MCSymbol *Sym) const; - const MCSection *getDataRelSection() const { return DataRelSection; } - /// getSectionForConstant - Given a constant with the SectionKind, return a /// section that it should be placed in. virtual const MCSection *getSectionForConstant(SectionKind Kind) const; @@ -99,48 +70,8 @@ public: class TargetLoweringObjectFileMachO : public TargetLoweringObjectFile { - /// TLSDataSection - Section for thread local data. - /// - const MCSection *TLSDataSection; // Defaults to ".tdata". - - /// TLSBSSSection - Section for thread local uninitialized data. - /// - const MCSection *TLSBSSSection; // Defaults to ".tbss". - - /// TLSTLVSection - Section for thread local structure information. - /// Contains the source code name of the variable, visibility and a pointer - /// to the initial value (.tdata or .tbss). - const MCSection *TLSTLVSection; // Defaults to ".tlv". - - /// TLSThreadInitSection - Section for thread local data initialization - /// functions. - const MCSection *TLSThreadInitSection; // Defaults to ".thread_init_func". - - const MCSection *CStringSection; - const MCSection *UStringSection; - const MCSection *TextCoalSection; - const MCSection *ConstTextCoalSection; - const MCSection *ConstDataSection; - const MCSection *DataCoalSection; - const MCSection *DataCommonSection; - const MCSection *DataBSSSection; - const MCSection *FourByteConstantSection; - const MCSection *EightByteConstantSection; - const MCSection *SixteenByteConstantSection; - - const MCSection *LazySymbolPointerSection; - const MCSection *NonLazySymbolPointerSection; public: - TargetLoweringObjectFileMachO(); - ~TargetLoweringObjectFileMachO() {} - - virtual void Initialize(MCContext &Ctx, const TargetMachine &TM); - - virtual const MCSection *getEHFrameSection() const; - virtual const MCSection *getWin64EHFuncTableSection(StringRef) const { - return NULL; - } - virtual const MCSection *getWin64EHTableSection(StringRef) const{return NULL;} + virtual ~TargetLoweringObjectFileMachO() {} virtual const MCSection * SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, @@ -158,30 +89,6 @@ public: virtual bool shouldEmitUsedDirectiveFor(const GlobalValue *GV, Mangler *) const; - /// getTextCoalSection - Return the "__TEXT,__textcoal_nt" section we put weak - /// text symbols into. - const MCSection *getTextCoalSection() const { - return TextCoalSection; - } - - /// getConstTextCoalSection - Return the "__TEXT,__const_coal" section - /// we put weak read-only symbols into. - const MCSection *getConstTextCoalSection() const { - return ConstTextCoalSection; - } - - /// getLazySymbolPointerSection - Return the section corresponding to - /// the .lazy_symbol_pointer directive. - const MCSection *getLazySymbolPointerSection() const { - return LazySymbolPointerSection; - } - - /// getNonLazySymbolPointerSection - Return the section corresponding to - /// the .non_lazy_symbol_pointer directive. - const MCSection *getNonLazySymbolPointerSection() const { - return NonLazySymbolPointerSection; - } - /// getExprForDwarfGlobalReference - The mach-o version of this method /// defaults to returning a stub reference. virtual const MCExpr * @@ -193,30 +100,13 @@ public: virtual MCSymbol * getCFIPersonalitySymbol(const GlobalValue *GV, Mangler *Mang, MachineModuleInfo *MMI) const; - - virtual unsigned getPersonalityEncoding() const; - virtual unsigned getLSDAEncoding() const; - virtual unsigned getFDEEncoding(bool CFI) const; - virtual unsigned getTTypeEncoding() const; }; class TargetLoweringObjectFileCOFF : public TargetLoweringObjectFile { - const MCSection *DrectveSection; - const MCSection *PDataSection; - const MCSection *XDataSection; public: - TargetLoweringObjectFileCOFF(); - ~TargetLoweringObjectFileCOFF() {} - - virtual void Initialize(MCContext &Ctx, const TargetMachine &TM); - - virtual const MCSection *getEHFrameSection() const; - virtual const MCSection *getWin64EHFuncTableSection(StringRef) const; - virtual const MCSection *getWin64EHTableSection(StringRef) const; - - virtual const MCSection *getDrectveSection() const { return DrectveSection; } + virtual ~TargetLoweringObjectFileCOFF() {} virtual const MCSection * getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind, diff --git a/contrib/llvm/include/llvm/CodeGen/ValueTypes.h b/contrib/llvm/include/llvm/CodeGen/ValueTypes.h index 424721bf6..cae0bcb16 100644 --- a/contrib/llvm/include/llvm/CodeGen/ValueTypes.h +++ b/contrib/llvm/include/llvm/CodeGen/ValueTypes.h @@ -144,14 +144,14 @@ namespace llvm { /// isFloatingPoint - Return true if this is a FP, or a vector FP type. bool isFloatingPoint() const { return ((SimpleTy >= MVT::f32 && SimpleTy <= MVT::ppcf128) || - (SimpleTy >= MVT::v2f32 && SimpleTy <= MVT::v4f64)); + (SimpleTy >= MVT::v2f32 && SimpleTy <= MVT::v4f64)); } /// isInteger - Return true if this is an integer, or a vector integer type. bool isInteger() const { return ((SimpleTy >= MVT::FIRST_INTEGER_VALUETYPE && SimpleTy <= MVT::LAST_INTEGER_VALUETYPE) || - (SimpleTy >= MVT::v2i8 && SimpleTy <= MVT::v8i64)); + (SimpleTy >= MVT::v2i8 && SimpleTy <= MVT::v8i64)); } /// isVector - Return true if this is a vector value type. @@ -380,7 +380,7 @@ namespace llvm { struct EVT { private: MVT V; - const Type *LLVMTy; + Type *LLVMTy; public: EVT() : V((MVT::SimpleValueType)(MVT::INVALID_SIMPLE_VALUE_TYPE)), @@ -438,6 +438,21 @@ namespace llvm { return MVT::INVALID_SIMPLE_VALUE_TYPE; } + /// changeVectorElementTypeToInteger - Return a vector with the same number + /// of elements as this vector, but with the element type converted to an + /// integer type with the same bitwidth. + EVT changeVectorElementTypeToInteger() const { + if (!isSimple()) + return changeExtendedVectorElementTypeToInteger(); + MVT EltTy = getSimpleVT().getVectorElementType(); + unsigned BitWidth = EltTy.getSizeInBits(); + MVT IntTy = MVT::getIntegerVT(BitWidth); + MVT VecTy = MVT::getVectorVT(IntTy, getVectorNumElements()); + assert(VecTy != MVT::INVALID_SIMPLE_VALUE_TYPE && + "Simple vector VT not representable by simple integer vector VT!"); + return VecTy; + } + /// isSimple - Test if the given EVT is simple (as opposed to being /// extended). bool isSimple() const { @@ -645,12 +660,12 @@ namespace llvm { /// getTypeForEVT - This method returns an LLVM type corresponding to the /// specified EVT. For integer types, this returns an unsigned type. Note /// that this will abort for types that cannot be represented. - const Type *getTypeForEVT(LLVMContext &Context) const; + Type *getTypeForEVT(LLVMContext &Context) const; /// getEVT - Return the value type corresponding to the specified type. /// This returns all pointers as iPTR. If HandleUnknown is true, unknown /// types are returned as Other, otherwise they are invalid. - static EVT getEVT(const Type *Ty, bool HandleUnknown = false); + static EVT getEVT(Type *Ty, bool HandleUnknown = false); intptr_t getRawBits() { if (isSimple()) @@ -674,6 +689,7 @@ namespace llvm { // Methods for handling the Extended-type case in functions above. // These are all out-of-line to prevent users of this header file // from having a dependency on Type.h. + EVT changeExtendedVectorElementTypeToInteger() const; static EVT getExtendedIntegerVT(LLVMContext &C, unsigned BitWidth); static EVT getExtendedVectorVT(LLVMContext &C, EVT VT, unsigned NumElements); diff --git a/contrib/llvm/include/llvm/CompilerDriver/Action.h b/contrib/llvm/include/llvm/CompilerDriver/Action.h deleted file mode 100644 index f2b79655f..000000000 --- a/contrib/llvm/include/llvm/CompilerDriver/Action.h +++ /dev/null @@ -1,54 +0,0 @@ -//===--- Action.h - The LLVM Compiler Driver --------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open -// Source License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Action - encapsulates a single shell command. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_INCLUDE_COMPILER_DRIVER_ACTION_H -#define LLVM_INCLUDE_COMPILER_DRIVER_ACTION_H - -#include -#include - -namespace llvmc { - - typedef std::vector StrVector; - - /// Action - A class that encapsulates a single shell command. - class Action { - /// Command_ - The actual command (for example, 'ls'). - std::string Command_; - /// Args_ - Command arguments. Stdout redirection ("> file") is allowed. - std::vector Args_; - /// StopCompilation_ - Should we stop compilation after executing - /// this action? - bool StopCompilation_; - /// OutFile_ - The output file name. - std::string OutFile_; - - public: - void Construct (const std::string& C, const StrVector& A, - bool S, const std::string& O) { - Command_ = C; - Args_ = A; - StopCompilation_ = S; - OutFile_ = O; - } - bool IsConstructed () { return (Command_.size() != 0);} - - /// Execute - Executes the command. Returns -1 on error. - int Execute () const; - bool StopCompilation () const { return StopCompilation_; } - const std::string& OutFile() { return OutFile_; } - }; - -} - -#endif // LLVM_INCLUDE_COMPILER_DRIVER_ACTION_H diff --git a/contrib/llvm/include/llvm/CompilerDriver/AutoGenerated.h b/contrib/llvm/include/llvm/CompilerDriver/AutoGenerated.h deleted file mode 100644 index 7b926c622..000000000 --- a/contrib/llvm/include/llvm/CompilerDriver/AutoGenerated.h +++ /dev/null @@ -1,40 +0,0 @@ -//===--- AutoGenerated.h - The LLVM Compiler Driver -------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open -// Source License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Interface to the autogenerated driver code. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_INCLUDE_COMPILER_DRIVER_AUTOGENERATED_H -#define LLVM_INCLUDE_COMPILER_DRIVER_AUTOGENERATED_H - -namespace llvmc { - class LanguageMap; - class CompilationGraph; - - namespace autogenerated { - - int PreprocessOptions(); - int PopulateLanguageMap(LanguageMap& langMap); - int PopulateCompilationGraph(CompilationGraph& graph); - - inline int RunInitialization (LanguageMap& M, CompilationGraph& G) { - if (int ret = PreprocessOptions()) - return ret; - if (int ret = PopulateLanguageMap(M)) - return ret; - if (int ret = PopulateCompilationGraph(G)) - return ret; - - return 0; - } - } -} - -#endif // LLVM_INCLUDE_COMPILER_DRIVER_AUTOGENERATED_H diff --git a/contrib/llvm/include/llvm/CompilerDriver/BuiltinOptions.h b/contrib/llvm/include/llvm/CompilerDriver/BuiltinOptions.h deleted file mode 100644 index 7b9c15c52..000000000 --- a/contrib/llvm/include/llvm/CompilerDriver/BuiltinOptions.h +++ /dev/null @@ -1,39 +0,0 @@ -//===--- BuiltinOptions.h - The LLVM Compiler Driver ------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open -// Source License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Declarations of all global command-line option variables. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_INCLUDE_COMPILER_DRIVER_BUILTIN_OPTIONS_H -#define LLVM_INCLUDE_COMPILER_DRIVER_BUILTIN_OPTIONS_H - -#include "llvm/Support/CommandLine.h" - -#include - -namespace llvmc { - -namespace SaveTempsEnum { enum Values { Cwd, Obj, Unset }; } - -extern llvm::cl::list InputFilenames; -extern llvm::cl::opt OutputFilename; -extern llvm::cl::opt TempDirname; -extern llvm::cl::list Languages; -extern llvm::cl::opt DryRun; -extern llvm::cl::opt Time; -extern llvm::cl::opt VerboseMode; -extern llvm::cl::opt CheckGraph; -extern llvm::cl::opt ViewGraph; -extern llvm::cl::opt WriteGraph; -extern llvm::cl::opt SaveTemps; - -} // End namespace llvmc. - -#endif // LLVM_INCLUDE_COMPILER_DRIVER_BUILTIN_OPTIONS_H diff --git a/contrib/llvm/include/llvm/CompilerDriver/Common.td b/contrib/llvm/include/llvm/CompilerDriver/Common.td deleted file mode 100644 index 6ba30aaa6..000000000 --- a/contrib/llvm/include/llvm/CompilerDriver/Common.td +++ /dev/null @@ -1,127 +0,0 @@ -//===- Common.td - Common definitions for LLVMC2 ----------*- tablegen -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file contains common definitions used in llvmc tool description files. -// -//===----------------------------------------------------------------------===// - -class Tool l> { - list properties = l; -} - -// Possible Tool properties. - -def in_language; -def out_language; -def output_suffix; -def command; -def out_file_option; -def in_file_option; -def join; -def sink; -def works_on_empty; -def actions; - -// Possible option types. - -def alias_option; -def switch_option; -def switch_list_option; -def parameter_option; -def parameter_list_option; -def prefix_option; -def prefix_list_option; - -// Possible option properties. - -def help; -def hidden; -def init; -def multi_val; -def one_or_more; -def zero_or_more; -def optional; -def really_hidden; -def required; -def comma_separated; -def forward_not_split; - -// The 'case' construct. -def case; - -// Boolean constants. -class Bool { - bit Value = val; -} -def true : Bool<1>; -def false : Bool<0>; - -// Boolean operators. -def and; -def or; -def not; - -// Primitive tests. -def switch_on; -def parameter_equals; -def element_in_list; -def input_languages_contain; -def empty; -def not_empty; -def default; -def single_input_file; -def multiple_input_files; -def any_switch_on; -def any_not_empty; -def any_empty; - -// Possible actions. - -def append_cmd; -def forward; -def forward_as; -def forward_value; -def forward_transformed_value; -def stop_compilation; -def no_out_file; -def unpack_values; -def warning; -def error; -def set_option; -def unset_option; - -// Increase the edge weight. -def inc_weight; - -// Option list - a single place to specify options. -class OptionList l> { - list options = l; -} - -// Option preprocessor - actions taken during plugin loading. -class OptionPreprocessor { - dag preprocessor = d; -} - -// Map from suffixes to language names - -def lang_to_suffixes; - -class LanguageMap l> { - list map = l; -} - -// Compilation graph - -def edge; -def optional_edge; - -class CompilationGraph l> { - list edges = l; -} diff --git a/contrib/llvm/include/llvm/CompilerDriver/CompilationGraph.h b/contrib/llvm/include/llvm/CompilerDriver/CompilationGraph.h deleted file mode 100644 index 951aff6f9..000000000 --- a/contrib/llvm/include/llvm/CompilerDriver/CompilationGraph.h +++ /dev/null @@ -1,330 +0,0 @@ -//===--- CompilationGraph.h - The LLVM Compiler Driver ----------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open -// Source License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Compilation graph - definition. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_INCLUDE_COMPILER_DRIVER_COMPILATION_GRAPH_H -#define LLVM_INCLUDE_COMPILER_DRIVER_COMPILATION_GRAPH_H - -#include "llvm/CompilerDriver/Tool.h" - -#include "llvm/ADT/GraphTraits.h" -#include "llvm/ADT/IntrusiveRefCntPtr.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringMap.h" -#include "llvm/ADT/StringSet.h" -#include "llvm/Support/Path.h" - -#include -#include - -namespace llvmc { - - class CompilationGraph; - typedef llvm::StringSet<> InputLanguagesSet; - - /// LanguageMap - Maps from extensions to language names. - class LanguageMap : public llvm::StringMap { - public: - - /// GetLanguage - Find the language name corresponding to a given file. - const std::string* GetLanguage(const llvm::sys::Path&) const; - }; - - /// Edge - Represents an edge of the compilation graph. - class Edge : public llvm::RefCountedBaseVPTR { - public: - Edge(const std::string& T) : ToolName_(T) {} - virtual ~Edge() {} - - const std::string& ToolName() const { return ToolName_; } - virtual int Weight(const InputLanguagesSet& InLangs) const = 0; - private: - std::string ToolName_; - }; - - /// SimpleEdge - An edge that has no properties. - class SimpleEdge : public Edge { - public: - SimpleEdge(const std::string& T) : Edge(T) {} - int Weight(const InputLanguagesSet&) const { return 1; } - }; - - /// Node - A node (vertex) of the compilation graph. - struct Node { - // A Node holds a list of the outward edges. - typedef llvm::SmallVector, 3> container_type; - typedef container_type::iterator iterator; - typedef container_type::const_iterator const_iterator; - - Node() : OwningGraph(0), InEdges(0) {} - Node(CompilationGraph* G) : OwningGraph(G), InEdges(0) {} - Node(CompilationGraph* G, Tool* T) : - OwningGraph(G), ToolPtr(T), InEdges(0) {} - - bool HasChildren() const { return !OutEdges.empty(); } - const std::string Name() const - { return ToolPtr ? ToolPtr->Name() : "root"; } - - // Iteration. - iterator EdgesBegin() { return OutEdges.begin(); } - const_iterator EdgesBegin() const { return OutEdges.begin(); } - iterator EdgesEnd() { return OutEdges.end(); } - const_iterator EdgesEnd() const { return OutEdges.end(); } - - /// AddEdge - Add an outward edge. Takes ownership of the provided - /// Edge object. - void AddEdge(Edge* E); - - // Inward edge counter. Used to implement topological sort. - void IncrInEdges() { ++InEdges; } - void DecrInEdges() { --InEdges; } - bool HasNoInEdges() const { return InEdges == 0; } - - // Needed to implement NodeChildIterator/GraphTraits - CompilationGraph* OwningGraph; - // The corresponding Tool. - // WARNING: ToolPtr can be NULL (for the root node). - llvm::IntrusiveRefCntPtr ToolPtr; - // Links to children. - container_type OutEdges; - // Inward edge counter. Updated in - // CompilationGraph::insertEdge(). Used for topological sorting. - unsigned InEdges; - }; - - class NodesIterator; - - /// CompilationGraph - The compilation graph itself. - class CompilationGraph { - /// nodes_map_type - The main data structure. - typedef llvm::StringMap nodes_map_type; - /// tools_vector_type, tools_map_type - Data structures used to - /// map from language names to tools. (We can have several tools - /// associated with each language name, hence the need for a - /// vector.) - typedef - llvm::SmallVector, 3> tools_vector_type; - typedef llvm::StringMap tools_map_type; - - /// ToolsMap - Map from language names to lists of tool names. - tools_map_type ToolsMap; - /// NodesMap - Map from tool names to Tool objects. - nodes_map_type NodesMap; - - public: - - typedef nodes_map_type::iterator nodes_iterator; - typedef nodes_map_type::const_iterator const_nodes_iterator; - - CompilationGraph(); - - /// insertNode - Insert a new node into the graph. Takes - /// ownership of the object. - void insertNode(Tool* T); - - /// insertEdge - Insert a new edge into the graph. Takes ownership - /// of the Edge object. Returns non-zero value on error. - int insertEdge(const std::string& A, Edge* E); - - /// Build - Build target(s) from the input file set. Command-line options - /// are passed implicitly as global variables. Returns non-zero value on - /// error (usually the failed program's exit code). - int Build(llvm::sys::Path const& TempDir, const LanguageMap& LangMap); - - /// Check - Check the compilation graph for common errors like cycles, - /// input/output language mismatch and multiple default edges. Prints error - /// messages and in case it finds any errors. - int Check(); - - /// getNode - Return a reference to the node corresponding to the given tool - /// name. Returns 0 on error. - Node* getNode(const std::string& ToolName); - const Node* getNode(const std::string& ToolName) const; - - /// viewGraph - This function is meant for use from the debugger. You can - /// just say 'call G->viewGraph()' and a ghostview window should pop up from - /// the program, displaying the compilation graph. This depends on there - /// being a 'dot' and 'gv' program in your path. - void viewGraph(); - - /// writeGraph - Write Graphviz .dot source file to the current direcotry. - int writeGraph(const std::string& OutputFilename); - - // GraphTraits support. - friend NodesIterator GraphBegin(CompilationGraph*); - friend NodesIterator GraphEnd(CompilationGraph*); - - private: - // Helper functions. - - /// getToolsVector - Return a reference to the list of tool names - /// corresponding to the given language name. Returns 0 on error. - const tools_vector_type* getToolsVector(const std::string& LangName) const; - - /// PassThroughGraph - Pass the input file through the toolchain starting at - /// StartNode. - int PassThroughGraph (const llvm::sys::Path& In, const Node* StartNode, - const InputLanguagesSet& InLangs, - const llvm::sys::Path& TempDir, - const LanguageMap& LangMap) const; - - /// FindToolChain - Find head of the toolchain corresponding to - /// the given file. - const Node* FindToolChain(const llvm::sys::Path& In, - const std::string* ForceLanguage, - InputLanguagesSet& InLangs, - const LanguageMap& LangMap) const; - - /// BuildInitial - Traverse the initial parts of the toolchains. Returns - /// non-zero value on error. - int BuildInitial(InputLanguagesSet& InLangs, - const llvm::sys::Path& TempDir, - const LanguageMap& LangMap); - - /// TopologicalSort - Sort the nodes in topological order. Returns non-zero - /// value on error. - int TopologicalSort(std::vector& Out); - /// TopologicalSortFilterJoinNodes - Call TopologicalSort and filter the - /// resulting list to include only Join nodes. Returns non-zero value on - /// error. - int TopologicalSortFilterJoinNodes(std::vector& Out); - - // Functions used to implement Check(). - - /// CheckLanguageNames - Check that output/input language names match for - /// all nodes. Returns non-zero value on error (number of errors - /// encountered). - int CheckLanguageNames() const; - /// CheckMultipleDefaultEdges - check that there are no multiple default - /// default edges. Returns non-zero value on error (number of errors - /// encountered). - int CheckMultipleDefaultEdges() const; - /// CheckCycles - Check that there are no cycles in the graph. Returns - /// non-zero value on error (number of errors encountered). - int CheckCycles(); - - }; - - // GraphTraits support code. - - /// NodesIterator - Auxiliary class needed to implement GraphTraits - /// support. Can be generalised to something like value_iterator - /// for map-like containers. - class NodesIterator : public CompilationGraph::nodes_iterator { - typedef CompilationGraph::nodes_iterator super; - typedef NodesIterator ThisType; - typedef Node* pointer; - typedef Node& reference; - - public: - NodesIterator(super I) : super(I) {} - - inline reference operator*() const { - return super::operator->()->second; - } - inline pointer operator->() const { - return &super::operator->()->second; - } - }; - - inline NodesIterator GraphBegin(CompilationGraph* G) { - return NodesIterator(G->NodesMap.begin()); - } - - inline NodesIterator GraphEnd(CompilationGraph* G) { - return NodesIterator(G->NodesMap.end()); - } - - - /// NodeChildIterator - Another auxiliary class needed by GraphTraits. - class NodeChildIterator : public - std::iterator { - typedef NodeChildIterator ThisType; - typedef Node::container_type::iterator iterator; - - CompilationGraph* OwningGraph; - iterator EdgeIter; - public: - typedef Node* pointer; - typedef Node& reference; - - NodeChildIterator(Node* N, iterator I) : - OwningGraph(N->OwningGraph), EdgeIter(I) {} - - const ThisType& operator=(const ThisType& I) { - assert(OwningGraph == I.OwningGraph); - EdgeIter = I.EdgeIter; - return *this; - } - - inline bool operator==(const ThisType& I) const { - assert(OwningGraph == I.OwningGraph); - return EdgeIter == I.EdgeIter; - } - inline bool operator!=(const ThisType& I) const { - return !this->operator==(I); - } - - inline pointer operator*() const { - return OwningGraph->getNode((*EdgeIter)->ToolName()); - } - inline pointer operator->() const { - return this->operator*(); - } - - ThisType& operator++() { ++EdgeIter; return *this; } // Preincrement - ThisType operator++(int) { // Postincrement - ThisType tmp = *this; - ++*this; - return tmp; - } - - inline ThisType& operator--() { --EdgeIter; return *this; } // Predecrement - inline ThisType operator--(int) { // Postdecrement - ThisType tmp = *this; - --*this; - return tmp; - } - - }; -} - -namespace llvm { - template <> - struct GraphTraits { - typedef llvmc::CompilationGraph GraphType; - typedef llvmc::Node NodeType; - typedef llvmc::NodeChildIterator ChildIteratorType; - - static NodeType* getEntryNode(GraphType* G) { - return G->getNode("root"); - } - - static ChildIteratorType child_begin(NodeType* N) { - return ChildIteratorType(N, N->OutEdges.begin()); - } - static ChildIteratorType child_end(NodeType* N) { - return ChildIteratorType(N, N->OutEdges.end()); - } - - typedef llvmc::NodesIterator nodes_iterator; - static nodes_iterator nodes_begin(GraphType *G) { - return GraphBegin(G); - } - static nodes_iterator nodes_end(GraphType *G) { - return GraphEnd(G); - } - }; - -} - -#endif // LLVM_INCLUDE_COMPILER_DRIVER_COMPILATION_GRAPH_H diff --git a/contrib/llvm/include/llvm/CompilerDriver/Error.h b/contrib/llvm/include/llvm/CompilerDriver/Error.h deleted file mode 100644 index 013094e5d..000000000 --- a/contrib/llvm/include/llvm/CompilerDriver/Error.h +++ /dev/null @@ -1,29 +0,0 @@ -//===--- Error.h - The LLVM Compiler Driver ---------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open -// Source License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Error handling. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_INCLUDE_COMPILER_DRIVER_ERROR_H -#define LLVM_INCLUDE_COMPILER_DRIVER_ERROR_H - -#include "llvm/ADT/StringRef.h" -#include "llvm/Support/raw_ostream.h" - -namespace llvmc { - - inline void PrintError(llvm::StringRef Err) { - extern const char* ProgramName; - llvm::errs() << ProgramName << ": " << Err << '\n'; - } - -} - -#endif // LLVM_INCLUDE_COMPILER_DRIVER_ERROR_H diff --git a/contrib/llvm/include/llvm/CompilerDriver/Main.h b/contrib/llvm/include/llvm/CompilerDriver/Main.h deleted file mode 100644 index d136a5d2f..000000000 --- a/contrib/llvm/include/llvm/CompilerDriver/Main.h +++ /dev/null @@ -1,21 +0,0 @@ -//===--- Main.h - The LLVM Compiler Driver ----------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open -// Source License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Entry point for the driver executable. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_INCLUDE_COMPILER_DRIVER_MAIN_H -#define LLVM_INCLUDE_COMPILER_DRIVER_MAIN_H - -namespace llvmc { - int Main(int argc, char** argv); -} - -#endif // LLVM_INCLUDE_COMPILER_DRIVER_MAIN_H diff --git a/contrib/llvm/include/llvm/CompilerDriver/Main.inc b/contrib/llvm/include/llvm/CompilerDriver/Main.inc deleted file mode 100644 index 41640437d..000000000 --- a/contrib/llvm/include/llvm/CompilerDriver/Main.inc +++ /dev/null @@ -1,23 +0,0 @@ -//===--- Main.inc - The LLVM Compiler Driver --------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open -// Source License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Default main() for the driver executable. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_INCLUDE_COMPILER_DRIVER_MAIN_INC -#define LLVM_INCLUDE_COMPILER_DRIVER_MAIN_INC - -#include "llvm/CompilerDriver/Main.h" - -int main(int argc, char** argv) { - return llvmc::Main(argc, argv); -} - -#endif // LLVM_INCLUDE_COMPILER_DRIVER_MAIN_INC diff --git a/contrib/llvm/include/llvm/CompilerDriver/Tool.h b/contrib/llvm/include/llvm/CompilerDriver/Tool.h deleted file mode 100644 index 18a2b7679..000000000 --- a/contrib/llvm/include/llvm/CompilerDriver/Tool.h +++ /dev/null @@ -1,100 +0,0 @@ -//===--- Tool.h - The LLVM Compiler Driver ----------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open -// Source License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Tool abstract base class - an interface to tool descriptions. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_INCLUDE_COMPILER_DRIVER_TOOL_H -#define LLVM_INCLUDE_COMPILER_DRIVER_TOOL_H - -#include "llvm/CompilerDriver/Action.h" - -#include "llvm/ADT/IntrusiveRefCntPtr.h" -#include "llvm/ADT/StringSet.h" -#include "llvm/Support/Path.h" - -#include -#include -#include - -namespace llvmc { - - class LanguageMap; - typedef std::vector > ArgsVector; - typedef std::vector PathVector; - typedef std::vector StrVector; - typedef llvm::StringSet<> InputLanguagesSet; - - /// Tool - Represents a single tool. - class Tool : public llvm::RefCountedBaseVPTR { - public: - - virtual ~Tool() {} - - /// GenerateAction - Generate an Action given particular command-line - /// options. Returns non-zero value on error. - virtual int GenerateAction (Action& Out, - const PathVector& inFiles, - const bool HasChildren, - const llvm::sys::Path& TempDir, - const InputLanguagesSet& InLangs, - const LanguageMap& LangMap) const = 0; - - /// GenerateAction - Generate an Action given particular command-line - /// options. Returns non-zero value on error. - virtual int GenerateAction (Action& Out, - const llvm::sys::Path& inFile, - const bool HasChildren, - const llvm::sys::Path& TempDir, - const InputLanguagesSet& InLangs, - const LanguageMap& LangMap) const = 0; - - virtual const char* Name() const = 0; - virtual const char** InputLanguages() const = 0; - virtual const char** OutputLanguages() const = 0; - - virtual bool IsJoin() const = 0; - virtual bool WorksOnEmpty() const = 0; - - protected: - /// OutFileName - Generate the output file name. - llvm::sys::Path OutFilename(const llvm::sys::Path& In, - const llvm::sys::Path& TempDir, - bool StopCompilation, - const char* OutputSuffix) const; - - StrVector SortArgs(ArgsVector& Args) const; - }; - - /// JoinTool - A Tool that has an associated input file list. - class JoinTool : public Tool { - public: - void AddToJoinList(const llvm::sys::Path& P) { JoinList_.push_back(P); } - void ClearJoinList() { JoinList_.clear(); } - bool JoinListEmpty() const { return JoinList_.empty(); } - - int GenerateAction(Action& Out, - const bool HasChildren, - const llvm::sys::Path& TempDir, - const InputLanguagesSet& InLangs, - const LanguageMap& LangMap) const { - return GenerateAction(Out, JoinList_, HasChildren, TempDir, InLangs, - LangMap); - } - // We shouldn't shadow base class's version of GenerateAction. - using Tool::GenerateAction; - - private: - PathVector JoinList_; - }; - -} - -#endif // LLVM_INCLUDE_COMPILER_DRIVER_TOOL_H diff --git a/contrib/llvm/include/llvm/Constant.h b/contrib/llvm/include/llvm/Constant.h index 5e351c4ec..ecc1fe70c 100644 --- a/contrib/llvm/include/llvm/Constant.h +++ b/contrib/llvm/include/llvm/Constant.h @@ -43,7 +43,7 @@ class Constant : public User { Constant(const Constant &); // Do not implement protected: - Constant(const Type *ty, ValueTy vty, Use *Ops, unsigned NumOps) + Constant(Type *ty, ValueTy vty, Use *Ops, unsigned NumOps) : User(ty, vty, Ops, NumOps) {} void destroyConstantImpl(); @@ -52,6 +52,10 @@ public: /// getNullValue. bool isNullValue() const; + /// isAllOnesValue - Return true if this is the value that would be returned by + /// getAllOnesValue. + bool isAllOnesValue() const; + /// isNegativeZeroValue - Return true if the value is what would be returned /// by getZeroValueForNegation. bool isNegativeZeroValue() const; @@ -128,16 +132,16 @@ public: assert(0 && "Constants that do not have operands cannot be using 'From'!"); } - static Constant *getNullValue(const Type* Ty); + static Constant *getNullValue(Type* Ty); /// @returns the value for an integer constant of the given type that has all /// its bits set to true. /// @brief Get the all ones value - static Constant *getAllOnesValue(const Type* Ty); + static Constant *getAllOnesValue(Type* Ty); /// getIntegerValue - Return the value for an integer or pointer constant, /// or a vector thereof, with the given scalar value. - static Constant *getIntegerValue(const Type* Ty, const APInt &V); + static Constant *getIntegerValue(Type* Ty, const APInt &V); /// removeDeadConstantUsers - If there are any dead constant users dangling /// off of this constant, remove them. This method is useful for clients diff --git a/contrib/llvm/include/llvm/Constants.h b/contrib/llvm/include/llvm/Constants.h index 01fca2918..6545a3fed 100644 --- a/contrib/llvm/include/llvm/Constants.h +++ b/contrib/llvm/include/llvm/Constants.h @@ -47,7 +47,7 @@ struct ConvertConstantType; class ConstantInt : public Constant { void *operator new(size_t, unsigned); // DO NOT IMPLEMENT ConstantInt(const ConstantInt &); // DO NOT IMPLEMENT - ConstantInt(const IntegerType *Ty, const APInt& V); + ConstantInt(IntegerType *Ty, const APInt& V); APInt Val; protected: // allocate space for exactly zero operands @@ -57,12 +57,12 @@ protected: public: static ConstantInt *getTrue(LLVMContext &Context); static ConstantInt *getFalse(LLVMContext &Context); - static Constant *getTrue(const Type *Ty); - static Constant *getFalse(const Type *Ty); + static Constant *getTrue(Type *Ty); + static Constant *getFalse(Type *Ty); /// If Ty is a vector type, return a Constant with a splat of the given /// value. Otherwise return a ConstantInt for the given value. - static Constant *get(const Type *Ty, uint64_t V, bool isSigned = false); + static Constant *get(Type *Ty, uint64_t V, bool isSigned = false); /// Return a ConstantInt with the specified integer value for the specified /// type. If the type is wider than 64 bits, the value will be zero-extended @@ -70,7 +70,7 @@ public: /// be interpreted as a 64-bit signed integer and sign-extended to fit /// the type. /// @brief Get a ConstantInt for a specific value. - static ConstantInt *get(const IntegerType *Ty, uint64_t V, + static ConstantInt *get(IntegerType *Ty, uint64_t V, bool isSigned = false); /// Return a ConstantInt with the specified value for the specified type. The @@ -78,8 +78,8 @@ public: /// either getSExtValue() or getZExtValue() will yield a correctly sized and /// signed value for the type Ty. /// @brief Get a ConstantInt for a specific signed value. - static ConstantInt *getSigned(const IntegerType *Ty, int64_t V); - static Constant *getSigned(const Type *Ty, int64_t V); + static ConstantInt *getSigned(IntegerType *Ty, int64_t V); + static Constant *getSigned(Type *Ty, int64_t V); /// Return a ConstantInt with the specified value and an implied Type. The /// type is the integer type that corresponds to the bit width of the value. @@ -87,12 +87,12 @@ public: /// Return a ConstantInt constructed from the string strStart with the given /// radix. - static ConstantInt *get(const IntegerType *Ty, StringRef Str, + static ConstantInt *get(IntegerType *Ty, StringRef Str, uint8_t radix); /// If Ty is a vector type, return a Constant with a splat of the given /// value. Otherwise return a ConstantInt for the given value. - static Constant *get(const Type* Ty, const APInt& V); + static Constant *get(Type* Ty, const APInt& V); /// Return the constant as an APInt value reference. This allows clients to /// obtain a copy of the value, with all its precision in tact. @@ -133,8 +133,8 @@ public: /// getType - Specialize the getType() method to always return an IntegerType, /// which reduces the amount of casting needed in parts of the compiler. /// - inline const IntegerType *getType() const { - return reinterpret_cast(Value::getType()); + inline IntegerType *getType() const { + return reinterpret_cast(Value::getType()); } /// This static method returns true if the type Ty is big enough to @@ -146,8 +146,8 @@ public: /// to the appropriate unsigned type before calling the method. /// @returns true if V is a valid value for type Ty /// @brief Determine if the value is in range for the given type. - static bool isValueValidForType(const Type *Ty, uint64_t V); - static bool isValueValidForType(const Type *Ty, int64_t V); + static bool isValueValidForType(Type *Ty, uint64_t V); + static bool isValueValidForType(Type *Ty, int64_t V); bool isNegative() const { return Val.isNegative(); } @@ -170,7 +170,7 @@ public: /// to true. /// @returns true iff this constant's bits are all set to true. /// @brief Determine if the value is all ones. - bool isAllOnesValue() const { + bool isMinusOne() const { return Val.isAllOnesValue(); } @@ -203,7 +203,7 @@ public: /// value. /// @returns true iff this constant is greater or equal to the given number. /// @brief Determine if the value is greater or equal to the given number. - bool uge(uint64_t Num) { + bool uge(uint64_t Num) const { return Val.getActiveBits() > 64 || Val.getZExtValue() >= Num; } @@ -233,7 +233,7 @@ class ConstantFP : public Constant { ConstantFP(const ConstantFP &); // DO NOT IMPLEMENT friend class LLVMContextImpl; protected: - ConstantFP(const Type *Ty, const APFloat& V); + ConstantFP(Type *Ty, const APFloat& V); protected: // allocate space for exactly zero operands void *operator new(size_t s) { @@ -243,20 +243,20 @@ public: /// Floating point negation must be implemented with f(x) = -0.0 - x. This /// method returns the negative zero constant for floating point or vector /// floating point types; for all other types, it returns the null value. - static Constant *getZeroValueForNegation(const Type *Ty); + static Constant *getZeroValueForNegation(Type *Ty); /// get() - This returns a ConstantFP, or a vector containing a splat of a /// ConstantFP, for the specified value in the specified type. This should /// only be used for simple constant values like 2.0/1.0 etc, that are /// known-valid both as host double and as the target format. - static Constant *get(const Type* Ty, double V); - static Constant *get(const Type* Ty, StringRef Str); + static Constant *get(Type* Ty, double V); + static Constant *get(Type* Ty, StringRef Str); static ConstantFP *get(LLVMContext &Context, const APFloat &V); - static ConstantFP *getNegativeZero(const Type* Ty); - static ConstantFP *getInfinity(const Type *Ty, bool Negative = false); + static ConstantFP *getNegativeZero(Type* Ty); + static ConstantFP *getInfinity(Type *Ty, bool Negative = false); /// isValueValidForType - return true if Ty is big enough to represent V. - static bool isValueValidForType(const Type *Ty, const APFloat &V); + static bool isValueValidForType(Type *Ty, const APFloat &V); inline const APFloat &getValueAPF() const { return Val; } /// isZero - Return true if the value is positive or negative zero. @@ -300,7 +300,7 @@ class ConstantAggregateZero : public Constant { void *operator new(size_t, unsigned); // DO NOT IMPLEMENT ConstantAggregateZero(const ConstantAggregateZero &); // DO NOT IMPLEMENT protected: - explicit ConstantAggregateZero(const Type *ty) + explicit ConstantAggregateZero(Type *ty) : Constant(ty, ConstantAggregateZeroVal, 0, 0) {} protected: // allocate space for exactly zero operands @@ -308,7 +308,7 @@ protected: return User::operator new(s, 0); } public: - static ConstantAggregateZero* get(const Type *Ty); + static ConstantAggregateZero* get(Type *Ty); virtual void destroyConstant(); @@ -329,10 +329,10 @@ class ConstantArray : public Constant { std::vector >; ConstantArray(const ConstantArray &); // DO NOT IMPLEMENT protected: - ConstantArray(const ArrayType *T, const std::vector &Val); + ConstantArray(ArrayType *T, ArrayRef Val); public: // ConstantArray accessors - static Constant *get(const ArrayType *T, ArrayRef V); + static Constant *get(ArrayType *T, ArrayRef V); /// This method constructs a ConstantArray and initializes it with a text /// string. The default behavior (AddNull==true) causes a null terminator to @@ -349,8 +349,8 @@ public: /// getType - Specialize the getType() method to always return an ArrayType, /// which reduces the amount of casting needed in parts of the compiler. /// - inline const ArrayType *getType() const { - return reinterpret_cast(Value::getType()); + inline ArrayType *getType() const { + return reinterpret_cast(Value::getType()); } /// isString - This method returns true if the array is an array of i8 and @@ -390,7 +390,7 @@ struct OperandTraits : public VariadicOperandTraits { }; -DEFINE_TRANSPARENT_CASTED_OPERAND_ACCESSORS(ConstantArray, Constant) +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantArray, Constant) //===----------------------------------------------------------------------===// // ConstantStruct - Constant Struct Declarations @@ -400,11 +400,11 @@ class ConstantStruct : public Constant { std::vector >; ConstantStruct(const ConstantStruct &); // DO NOT IMPLEMENT protected: - ConstantStruct(const StructType *T, const std::vector &Val); + ConstantStruct(StructType *T, ArrayRef Val); public: // ConstantStruct accessors - static Constant *get(const StructType *T, ArrayRef V); - static Constant *get(const StructType *T, ...) END_WITH_NULL; + static Constant *get(StructType *T, ArrayRef V); + static Constant *get(StructType *T, ...) END_WITH_NULL; /// getAnon - Return an anonymous struct that has the specified /// elements. If the struct is possibly empty, then you must specify a @@ -431,8 +431,8 @@ public: /// getType() specialization - Reduce amount of casting... /// - inline const StructType *getType() const { - return reinterpret_cast(Value::getType()); + inline StructType *getType() const { + return reinterpret_cast(Value::getType()); } virtual void destroyConstant(); @@ -450,7 +450,7 @@ struct OperandTraits : public VariadicOperandTraits { }; -DEFINE_TRANSPARENT_CASTED_OPERAND_ACCESSORS(ConstantStruct, Constant) +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantStruct, Constant) //===----------------------------------------------------------------------===// @@ -461,7 +461,7 @@ class ConstantVector : public Constant { std::vector >; ConstantVector(const ConstantVector &); // DO NOT IMPLEMENT protected: - ConstantVector(const VectorType *T, const std::vector &Val); + ConstantVector(VectorType *T, ArrayRef Val); public: // ConstantVector accessors static Constant *get(ArrayRef V); @@ -472,8 +472,8 @@ public: /// getType - Specialize the getType() method to always return a VectorType, /// which reduces the amount of casting needed in parts of the compiler. /// - inline const VectorType *getType() const { - return reinterpret_cast(Value::getType()); + inline VectorType *getType() const { + return reinterpret_cast(Value::getType()); } /// This function will return true iff every element in this vector constant @@ -501,7 +501,7 @@ struct OperandTraits : public VariadicOperandTraits { }; -DEFINE_TRANSPARENT_CASTED_OPERAND_ACCESSORS(ConstantVector, Constant) +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantVector, Constant) //===----------------------------------------------------------------------===// /// ConstantPointerNull - a constant pointer value that points to null @@ -511,8 +511,8 @@ class ConstantPointerNull : public Constant { void *operator new(size_t, unsigned); // DO NOT IMPLEMENT ConstantPointerNull(const ConstantPointerNull &); // DO NOT IMPLEMENT protected: - explicit ConstantPointerNull(const PointerType *T) - : Constant(reinterpret_cast(T), + explicit ConstantPointerNull(PointerType *T) + : Constant(reinterpret_cast(T), Value::ConstantPointerNullVal, 0, 0) {} protected: @@ -522,15 +522,15 @@ protected: } public: /// get() - Static factory methods - Return objects of the specified value - static ConstantPointerNull *get(const PointerType *T); + static ConstantPointerNull *get(PointerType *T); virtual void destroyConstant(); /// getType - Specialize the getType() method to always return an PointerType, /// which reduces the amount of casting needed in parts of the compiler. /// - inline const PointerType *getType() const { - return reinterpret_cast(Value::getType()); + inline PointerType *getType() const { + return reinterpret_cast(Value::getType()); } /// Methods for support type inquiry through isa, cast, and dyn_cast: @@ -575,7 +575,7 @@ struct OperandTraits : public FixedNumOperandTraits { }; -DEFINE_TRANSPARENT_CASTED_OPERAND_ACCESSORS(BlockAddress, Value) +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(BlockAddress, Value) //===----------------------------------------------------------------------===// @@ -591,7 +591,7 @@ class ConstantExpr : public Constant { friend struct ConvertConstantType; protected: - ConstantExpr(const Type *ty, unsigned Opcode, Use *Ops, unsigned NumOps) + ConstantExpr(Type *ty, unsigned Opcode, Use *Ops, unsigned NumOps) : Constant(ty, ConstantExprVal, Ops, NumOps) { // Operation type (an Instruction opcode) is stored as the SubclassData. setValueSubclassData(Opcode); @@ -605,23 +605,23 @@ public: /// getAlignOf constant expr - computes the alignment of a type in a target /// independent way (Note: the return type is an i64). - static Constant *getAlignOf(const Type *Ty); + static Constant *getAlignOf(Type *Ty); /// getSizeOf constant expr - computes the (alloc) size of a type (in /// address-units, not bits) in a target independent way (Note: the return /// type is an i64). /// - static Constant *getSizeOf(const Type *Ty); + static Constant *getSizeOf(Type *Ty); /// getOffsetOf constant expr - computes the offset of a struct field in a /// target independent way (Note: the return type is an i64). /// - static Constant *getOffsetOf(const StructType *STy, unsigned FieldNo); + static Constant *getOffsetOf(StructType *STy, unsigned FieldNo); /// getOffsetOf constant expr - This is a generalized form of getOffsetOf, /// which supports any aggregate type, and any Constant index. /// - static Constant *getOffsetOf(const Type *Ty, Constant *FieldNo); + static Constant *getOffsetOf(Type *Ty, Constant *FieldNo); static Constant *getNeg(Constant *C, bool HasNUW = false, bool HasNSW =false); static Constant *getFNeg(Constant *C); @@ -648,18 +648,18 @@ public: bool HasNUW = false, bool HasNSW = false); static Constant *getLShr(Constant *C1, Constant *C2, bool isExact = false); static Constant *getAShr(Constant *C1, Constant *C2, bool isExact = false); - static Constant *getTrunc (Constant *C, const Type *Ty); - static Constant *getSExt (Constant *C, const Type *Ty); - static Constant *getZExt (Constant *C, const Type *Ty); - static Constant *getFPTrunc (Constant *C, const Type *Ty); - static Constant *getFPExtend(Constant *C, const Type *Ty); - static Constant *getUIToFP (Constant *C, const Type *Ty); - static Constant *getSIToFP (Constant *C, const Type *Ty); - static Constant *getFPToUI (Constant *C, const Type *Ty); - static Constant *getFPToSI (Constant *C, const Type *Ty); - static Constant *getPtrToInt(Constant *C, const Type *Ty); - static Constant *getIntToPtr(Constant *C, const Type *Ty); - static Constant *getBitCast (Constant *C, const Type *Ty); + static Constant *getTrunc (Constant *C, Type *Ty); + static Constant *getSExt (Constant *C, Type *Ty); + static Constant *getZExt (Constant *C, Type *Ty); + static Constant *getFPTrunc (Constant *C, Type *Ty); + static Constant *getFPExtend(Constant *C, Type *Ty); + static Constant *getUIToFP (Constant *C, Type *Ty); + static Constant *getSIToFP (Constant *C, Type *Ty); + static Constant *getFPToUI (Constant *C, Type *Ty); + static Constant *getFPToSI (Constant *C, Type *Ty); + static Constant *getPtrToInt(Constant *C, Type *Ty); + static Constant *getIntToPtr(Constant *C, Type *Ty); + static Constant *getBitCast (Constant *C, Type *Ty); static Constant *getNSWNeg(Constant *C) { return getNeg(C, false, true); } static Constant *getNUWNeg(Constant *C) { return getNeg(C, true, false); } @@ -708,44 +708,44 @@ public: static Constant *getCast( unsigned ops, ///< The opcode for the conversion Constant *C, ///< The constant to be converted - const Type *Ty ///< The type to which the constant is converted + Type *Ty ///< The type to which the constant is converted ); // @brief Create a ZExt or BitCast cast constant expression static Constant *getZExtOrBitCast( Constant *C, ///< The constant to zext or bitcast - const Type *Ty ///< The type to zext or bitcast C to + Type *Ty ///< The type to zext or bitcast C to ); // @brief Create a SExt or BitCast cast constant expression static Constant *getSExtOrBitCast( Constant *C, ///< The constant to sext or bitcast - const Type *Ty ///< The type to sext or bitcast C to + Type *Ty ///< The type to sext or bitcast C to ); // @brief Create a Trunc or BitCast cast constant expression static Constant *getTruncOrBitCast( Constant *C, ///< The constant to trunc or bitcast - const Type *Ty ///< The type to trunc or bitcast C to + Type *Ty ///< The type to trunc or bitcast C to ); /// @brief Create a BitCast or a PtrToInt cast constant expression static Constant *getPointerCast( Constant *C, ///< The pointer value to be casted (operand 0) - const Type *Ty ///< The type to which cast should be made + Type *Ty ///< The type to which cast should be made ); /// @brief Create a ZExt, Bitcast or Trunc for integer -> integer casts static Constant *getIntegerCast( Constant *C, ///< The integer constant to be casted - const Type *Ty, ///< The integer type to cast to + Type *Ty, ///< The integer type to cast to bool isSigned ///< Whether C should be treated as signed or not ); /// @brief Create a FPExt, Bitcast or FPTrunc for fp -> fp casts static Constant *getFPCast( Constant *C, ///< The integer constant to be casted - const Type *Ty ///< The integer type to cast to + Type *Ty ///< The integer type to cast to ); /// @brief Return true if this is a convert constant expression @@ -788,25 +788,40 @@ public: /// all elements must be Constant's. /// static Constant *getGetElementPtr(Constant *C, - Constant *const *IdxList, unsigned NumIdx, + ArrayRef IdxList, bool InBounds = false) { - return getGetElementPtr(C, (Value**)IdxList, NumIdx, InBounds); + return getGetElementPtr(C, makeArrayRef((Value * const *)IdxList.data(), + IdxList.size()), + InBounds); } static Constant *getGetElementPtr(Constant *C, - Value *const *IdxList, unsigned NumIdx, + Constant *Idx, + bool InBounds = false) { + // This form of the function only exists to avoid ambiguous overload + // warnings about whether to convert Idx to ArrayRef or + // ArrayRef. + return getGetElementPtr(C, cast(Idx), InBounds); + } + static Constant *getGetElementPtr(Constant *C, + ArrayRef IdxList, bool InBounds = false); /// Create an "inbounds" getelementptr. See the documentation for the /// "inbounds" flag in LangRef.html for details. static Constant *getInBoundsGetElementPtr(Constant *C, - Constant *const *IdxList, - unsigned NumIdx) { - return getGetElementPtr(C, IdxList, NumIdx, true); + ArrayRef IdxList) { + return getGetElementPtr(C, IdxList, true); + } + static Constant *getInBoundsGetElementPtr(Constant *C, + Constant *Idx) { + // This form of the function only exists to avoid ambiguous overload + // warnings about whether to convert Idx to ArrayRef or + // ArrayRef. + return getGetElementPtr(C, Idx, true); } static Constant *getInBoundsGetElementPtr(Constant *C, - Value* const *IdxList, - unsigned NumIdx) { - return getGetElementPtr(C, IdxList, NumIdx, true); + ArrayRef IdxList) { + return getGetElementPtr(C, IdxList, true); } static Constant *getExtractElement(Constant *Vec, Constant *Idx); @@ -845,7 +860,7 @@ public: /// operands replaced with the specified values and with the specified result /// type. The specified array must have the same number of operands as our /// current one. - Constant *getWithOperands(ArrayRef Ops, const Type *Ty) const; + Constant *getWithOperands(ArrayRef Ops, Type *Ty) const; virtual void destroyConstant(); virtual void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U); @@ -869,7 +884,7 @@ struct OperandTraits : public VariadicOperandTraits { }; -DEFINE_TRANSPARENT_CASTED_OPERAND_ACCESSORS(ConstantExpr, Constant) +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantExpr, Constant) //===----------------------------------------------------------------------===// /// UndefValue - 'undef' values are things that do not have specified contents. @@ -886,7 +901,7 @@ class UndefValue : public Constant { void *operator new(size_t, unsigned); // DO NOT IMPLEMENT UndefValue(const UndefValue &); // DO NOT IMPLEMENT protected: - explicit UndefValue(const Type *T) : Constant(T, UndefValueVal, 0, 0) {} + explicit UndefValue(Type *T) : Constant(T, UndefValueVal, 0, 0) {} protected: // allocate space for exactly zero operands void *operator new(size_t s) { @@ -896,7 +911,7 @@ public: /// get() - Static factory methods - Return an 'undef' object of the specified /// type. /// - static UndefValue *get(const Type *T); + static UndefValue *get(Type *T); virtual void destroyConstant(); diff --git a/contrib/llvm/include/llvm/DebugInfo/DIContext.h b/contrib/llvm/include/llvm/DebugInfo/DIContext.h new file mode 100644 index 000000000..64f80c506 --- /dev/null +++ b/contrib/llvm/include/llvm/DebugInfo/DIContext.h @@ -0,0 +1,68 @@ +//===-- DIContext.h ---------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines DIContext, an abstract data structure that holds +// debug information data. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_DICONTEXT_H +#define LLVM_DEBUGINFO_DICONTEXT_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/DataTypes.h" +#include + +namespace llvm { + +class raw_ostream; + +/// DILineInfo - a format-neutral container for source line information. +class DILineInfo { + const char *FileName; + uint32_t Line; + uint32_t Column; +public: + DILineInfo() : FileName(""), Line(0), Column(0) {} + DILineInfo(const char *fileName, uint32_t line, uint32_t column) + : FileName(fileName), Line(line), Column(column) {} + + const char *getFileName() const { return FileName; } + uint32_t getLine() const { return Line; } + uint32_t getColumn() const { return Column; } + + bool operator==(const DILineInfo &RHS) const { + return Line == RHS.Line && Column == RHS.Column && + std::strcmp(FileName, RHS.FileName) == 0; + } + bool operator!=(const DILineInfo &RHS) const { + return !(*this == RHS); + } +}; + +class DIContext { +public: + virtual ~DIContext(); + + /// getDWARFContext - get a context for binary DWARF data. + static DIContext *getDWARFContext(bool isLittleEndian, + StringRef infoSection, + StringRef abbrevSection, + StringRef aRangeSection = StringRef(), + StringRef lineSection = StringRef(), + StringRef stringSection = StringRef()); + + virtual void dump(raw_ostream &OS) = 0; + + virtual DILineInfo getLineInfoForAddress(uint64_t address) = 0; +}; + +} + +#endif diff --git a/contrib/llvm/include/llvm/DerivedTypes.h b/contrib/llvm/include/llvm/DerivedTypes.h index acb28dead..445c3deb7 100644 --- a/contrib/llvm/include/llvm/DerivedTypes.h +++ b/contrib/llvm/include/llvm/DerivedTypes.h @@ -96,26 +96,26 @@ public: class FunctionType : public Type { FunctionType(const FunctionType &); // Do not implement const FunctionType &operator=(const FunctionType &); // Do not implement - FunctionType(const Type *Result, ArrayRef Params, bool IsVarArgs); + FunctionType(Type *Result, ArrayRef Params, bool IsVarArgs); public: /// FunctionType::get - This static method is the primary way of constructing /// a FunctionType. /// - static FunctionType *get(const Type *Result, + static FunctionType *get(Type *Result, ArrayRef Params, bool isVarArg); /// FunctionType::get - Create a FunctionType taking no parameters. /// - static FunctionType *get(const Type *Result, bool isVarArg); + static FunctionType *get(Type *Result, bool isVarArg); /// isValidReturnType - Return true if the specified type is valid as a return /// type. - static bool isValidReturnType(const Type *RetTy); + static bool isValidReturnType(Type *RetTy); /// isValidArgumentType - Return true if the specified type is valid as an /// argument type. - static bool isValidArgumentType(const Type *ArgTy); + static bool isValidArgumentType(Type *ArgTy); bool isVarArg() const { return getSubclassData(); } Type *getReturnType() const { return ContainedTys[0]; } @@ -150,8 +150,8 @@ public: /// getTypeAtIndex - Given an index value into the type, return the type of /// the element. /// - Type *getTypeAtIndex(const Value *V) const; - Type *getTypeAtIndex(unsigned Idx) const; + Type *getTypeAtIndex(const Value *V); + Type *getTypeAtIndex(unsigned Idx); bool indexValid(const Value *V) const; bool indexValid(unsigned Idx) const; @@ -166,10 +166,25 @@ public: }; -/// StructType - Class to represent struct types, both normal and packed. -/// Besides being optionally packed, structs can be either "anonymous" or may -/// have an identity. Anonymous structs are uniqued by structural equivalence, -/// but types are each unique when created, and optionally have a name. +/// StructType - Class to represent struct types. There are two different kinds +/// of struct types: Literal structs and Identified structs. +/// +/// Literal struct types (e.g. { i32, i32 }) are uniqued structurally, and must +/// always have a body when created. You can get one of these by using one of +/// the StructType::get() forms. +/// +/// Identified structs (e.g. %foo or %42) may optionally have a name and are not +/// uniqued. The names for identified structs are managed at the LLVMContext +/// level, so there can only be a single identified struct with a given name in +/// a particular LLVMContext. Identified structs may also optionally be opaque +/// (have no body specified). You get one of these by using one of the +/// StructType::create() forms. +/// +/// Independent of what kind of struct you have, the body of a struct type are +/// laid out in memory consequtively with the elements directly one after the +/// other (if the struct is packed) or (if not packed) with padding between the +/// elements as defined by TargetData (which is required to match what the code +/// generator for a target expects). /// class StructType : public CompositeType { StructType(const StructType &); // Do not implement @@ -180,13 +195,13 @@ class StructType : public CompositeType { // This is the contents of the SubClassData field. SCDB_HasBody = 1, SCDB_Packed = 2, - SCDB_IsAnonymous = 4 + SCDB_IsLiteral = 4 }; /// SymbolTableEntry - For a named struct that actually has a name, this is a /// pointer to the symbol table entry (maintained by LLVMContext) for the - /// struct. This is null if the type is an anonymous struct or if it is - /// a named type that has an empty name. + /// struct. This is null if the type is an literal struct or if it is + /// a identified type that has an empty name. /// void *SymbolTableEntry; public: @@ -194,20 +209,23 @@ public: delete [] ContainedTys; // Delete the body. } - /// StructType::createNamed - This creates a named struct with no body - /// specified. If the name is empty, it creates an unnamed struct, which has - /// a unique identity but no actual name. - static StructType *createNamed(LLVMContext &Context, StringRef Name); + /// StructType::create - This creates an identified struct. + static StructType *create(LLVMContext &Context, StringRef Name); + static StructType *create(LLVMContext &Context); - static StructType *createNamed(StringRef Name, ArrayRef Elements, - bool isPacked = false); - static StructType *createNamed(LLVMContext &Context, StringRef Name, - ArrayRef Elements, - bool isPacked = false); - static StructType *createNamed(StringRef Name, Type *elt1, ...) END_WITH_NULL; + static StructType *create(ArrayRef Elements, + StringRef Name, + bool isPacked = false); + static StructType *create(ArrayRef Elements); + static StructType *create(LLVMContext &Context, + ArrayRef Elements, + StringRef Name, + bool isPacked = false); + static StructType *create(LLVMContext &Context, ArrayRef Elements); + static StructType *create(StringRef Name, Type *elt1, ...) END_WITH_NULL; /// StructType::get - This static method is the primary way to create a - /// StructType. + /// literal StructType. static StructType *get(LLVMContext &Context, ArrayRef Elements, bool isPacked = false); @@ -223,9 +241,9 @@ public: bool isPacked() const { return (getSubclassData() & SCDB_Packed) != 0; } - /// isAnonymous - Return true if this type is uniqued by structural - /// equivalence, false if it has an identity. - bool isAnonymous() const {return (getSubclassData() & SCDB_IsAnonymous) != 0;} + /// isLiteral - Return true if this type is uniqued by structural + /// equivalence, false if it is a struct definition. + bool isLiteral() const { return (getSubclassData() & SCDB_IsLiteral) != 0; } /// isOpaque - Return true if this is a type with an identity that has no body /// specified yet. These prints as 'opaque' in .ll files. @@ -236,21 +254,21 @@ public: /// getName - Return the name for this struct type if it has an identity. /// This may return an empty string for an unnamed struct type. Do not call - /// this on an anonymous type. + /// this on an literal type. StringRef getName() const; /// setName - Change the name of this type to the specified name, or to a name - /// with a suffix if there is a collision. Do not call this on an anonymous + /// with a suffix if there is a collision. Do not call this on an literal /// type. void setName(StringRef Name); - /// setBody - Specify a body for an opaque type. + /// setBody - Specify a body for an opaque identified type. void setBody(ArrayRef Elements, bool isPacked = false); void setBody(Type *elt1, ...) END_WITH_NULL; /// isValidElementType - Return true if the specified type is valid as a /// element type. - static bool isValidElementType(const Type *ElemTy); + static bool isValidElementType(Type *ElemTy); // Iterator access to the elements. @@ -260,7 +278,7 @@ public: /// isLayoutIdentical - Return true if this is layout identical to the /// specified struct. - bool isLayoutIdentical(const StructType *Other) const; + bool isLayoutIdentical(StructType *Other) const; // Random access to the elements unsigned getNumElements() const { return NumContainedTys; } @@ -321,11 +339,11 @@ public: /// ArrayType::get - This static method is the primary way to construct an /// ArrayType /// - static ArrayType *get(const Type *ElementType, uint64_t NumElements); + static ArrayType *get(Type *ElementType, uint64_t NumElements); /// isValidElementType - Return true if the specified type is valid as a /// element type. - static bool isValidElementType(const Type *ElemTy); + static bool isValidElementType(Type *ElemTy); uint64_t getNumElements() const { return NumElements; } @@ -348,13 +366,13 @@ public: /// VectorType::get - This static method is the primary way to construct an /// VectorType. /// - static VectorType *get(const Type *ElementType, unsigned NumElements); + static VectorType *get(Type *ElementType, unsigned NumElements); /// VectorType::getInteger - This static method gets a VectorType with the /// same number of elements as the input type, and the element type is an /// integer type of the same width as the input element type. /// - static VectorType *getInteger(const VectorType *VTy) { + static VectorType *getInteger(VectorType *VTy) { unsigned EltBits = VTy->getElementType()->getPrimitiveSizeInBits(); Type *EltTy = IntegerType::get(VTy->getContext(), EltBits); return VectorType::get(EltTy, VTy->getNumElements()); @@ -364,7 +382,7 @@ public: /// getInteger except that the element types are twice as wide as the /// elements in the input type. /// - static VectorType *getExtendedElementVectorType(const VectorType *VTy) { + static VectorType *getExtendedElementVectorType(VectorType *VTy) { unsigned EltBits = VTy->getElementType()->getPrimitiveSizeInBits(); Type *EltTy = IntegerType::get(VTy->getContext(), EltBits * 2); return VectorType::get(EltTy, VTy->getNumElements()); @@ -374,7 +392,7 @@ public: /// getInteger except that the element types are half as wide as the /// elements in the input type. /// - static VectorType *getTruncatedElementVectorType(const VectorType *VTy) { + static VectorType *getTruncatedElementVectorType(VectorType *VTy) { unsigned EltBits = VTy->getElementType()->getPrimitiveSizeInBits(); assert((EltBits & 1) == 0 && "Cannot truncate vector element with odd bit-width"); @@ -384,7 +402,7 @@ public: /// isValidElementType - Return true if the specified type is valid as a /// element type. - static bool isValidElementType(const Type *ElemTy); + static bool isValidElementType(Type *ElemTy); /// @brief Return the number of elements in the Vector type. unsigned getNumElements() const { return NumElements; } @@ -411,17 +429,17 @@ class PointerType : public SequentialType { public: /// PointerType::get - This constructs a pointer to an object of the specified /// type in a numbered address space. - static PointerType *get(const Type *ElementType, unsigned AddressSpace); + static PointerType *get(Type *ElementType, unsigned AddressSpace); /// PointerType::getUnqual - This constructs a pointer to an object of the /// specified type in the generic address space (address space zero). - static PointerType *getUnqual(const Type *ElementType) { + static PointerType *getUnqual(Type *ElementType) { return PointerType::get(ElementType, 0); } /// isValidElementType - Return true if the specified type is valid as a /// element type. - static bool isValidElementType(const Type *ElemTy); + static bool isValidElementType(Type *ElemTy); /// @brief Return the address space of the Pointer type. inline unsigned getAddressSpace() const { return getSubclassData(); } diff --git a/contrib/llvm/include/llvm/ExecutionEngine/ExecutionEngine.h b/contrib/llvm/include/llvm/ExecutionEngine/ExecutionEngine.h index 88b21cd4d..cf85671eb 100644 --- a/contrib/llvm/include/llvm/ExecutionEngine/ExecutionEngine.h +++ b/contrib/llvm/include/llvm/ExecutionEngine/ExecutionEngine.h @@ -18,6 +18,7 @@ #include #include #include +#include "llvm/MC/MCCodeGenInfo.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/ValueMap.h" @@ -119,9 +120,7 @@ protected: /// optimize for the case where there is only one module. SmallVector Modules; - void setTargetData(const TargetData *td) { - TD = td; - } + void setTargetData(const TargetData *td) { TD = td; } /// getMemoryforGV - Allocate memory for a global variable. virtual char *getMemoryForGV(const GlobalVariable *GV); @@ -143,8 +142,7 @@ protected: CodeGenOpt::Level OptLevel, bool GVsWithCode, TargetMachine *TM); - static ExecutionEngine *(*InterpCtor)(Module *M, - std::string *ErrorStr); + static ExecutionEngine *(*InterpCtor)(Module *M, std::string *ErrorStr); /// LazyFunctionCreator - If an unknown function is needed, this function /// pointer is invoked to create it. If this returns null, the JIT will @@ -186,7 +184,7 @@ public: bool ForceInterpreter = false, std::string *ErrorStr = 0, CodeGenOpt::Level OptLevel = - CodeGenOpt::Default, + CodeGenOpt::Default, bool GVsWithCode = true); /// createJIT - This is the factory method for creating a JIT for the current @@ -199,10 +197,11 @@ public: std::string *ErrorStr = 0, JITMemoryManager *JMM = 0, CodeGenOpt::Level OptLevel = - CodeGenOpt::Default, + CodeGenOpt::Default, bool GVsWithCode = true, + Reloc::Model RM = Reloc::Default, CodeModel::Model CMM = - CodeModel::Default); + CodeModel::JITDefault); /// addModule - Add a Module to the list of modules that we can JIT from. /// Note that this takes ownership of the Module: when the ExecutionEngine is @@ -314,7 +313,7 @@ public: /// GenericValue *. It is not a pointer to a GenericValue containing the /// address at which to store Val. void StoreValueToMemory(const GenericValue &Val, GenericValue *Ptr, - const Type *Ty); + Type *Ty); void InitializeMemory(const Constant *Init, void *Addr); @@ -440,7 +439,7 @@ protected: GenericValue getConstantValue(const Constant *C); void LoadValueFromMemory(GenericValue &Result, GenericValue *Ptr, - const Type *Ty); + Type *Ty); }; namespace EngineKind { @@ -463,6 +462,7 @@ private: CodeGenOpt::Level OptLevel; JITMemoryManager *JMM; bool AllocateGVsWithCode; + Reloc::Model RelocModel; CodeModel::Model CMModel; std::string MArch; std::string MCPU; @@ -476,7 +476,8 @@ private: OptLevel = CodeGenOpt::Default; JMM = NULL; AllocateGVsWithCode = false; - CMModel = CodeModel::Default; + RelocModel = Reloc::Default; + CMModel = CodeModel::JITDefault; UseMCJIT = false; } @@ -517,8 +518,16 @@ public: return *this; } + /// setRelocationModel - Set the relocation model that the ExecutionEngine + /// target is using. Defaults to target specific default "Reloc::Default". + EngineBuilder &setRelocationModel(Reloc::Model RM) { + RelocModel = RM; + return *this; + } + /// setCodeModel - Set the CodeModel that the ExecutionEngine target - /// data is using. Defaults to target specific default "CodeModel::Default". + /// data is using. Defaults to target specific default + /// "CodeModel::JITDefault". EngineBuilder &setCodeModel(CodeModel::Model M) { CMModel = M; return *this; @@ -569,6 +578,8 @@ public: StringRef MArch, StringRef MCPU, const SmallVectorImpl& MAttrs, + Reloc::Model RM, + CodeModel::Model CM, std::string *Err); ExecutionEngine *create(); diff --git a/contrib/llvm/include/llvm/Function.h b/contrib/llvm/include/llvm/Function.h index 0aa5b2a9f..678651bbf 100644 --- a/contrib/llvm/include/llvm/Function.h +++ b/contrib/llvm/include/llvm/Function.h @@ -117,11 +117,11 @@ private: /// function is automatically inserted into the end of the function list for /// the module. /// - Function(const FunctionType *Ty, LinkageTypes Linkage, + Function(FunctionType *Ty, LinkageTypes Linkage, const Twine &N = "", Module *M = 0); public: - static Function *Create(const FunctionType *Ty, LinkageTypes Linkage, + static Function *Create(FunctionType *Ty, LinkageTypes Linkage, const Twine &N = "", Module *M = 0) { return new(0) Function(Ty, Linkage, N, M); } diff --git a/contrib/llvm/include/llvm/GlobalAlias.h b/contrib/llvm/include/llvm/GlobalAlias.h index c3d3c38bd..164d97658 100644 --- a/contrib/llvm/include/llvm/GlobalAlias.h +++ b/contrib/llvm/include/llvm/GlobalAlias.h @@ -23,7 +23,6 @@ namespace llvm { class Module; -class Constant; template class SymbolTableListTraits; @@ -41,11 +40,11 @@ public: } /// GlobalAlias ctor - If a parent module is specified, the alias is /// automatically inserted into the end of the specified module's alias list. - GlobalAlias(const Type *Ty, LinkageTypes Linkage, const Twine &Name = "", + GlobalAlias(Type *Ty, LinkageTypes Linkage, const Twine &Name = "", Constant* Aliasee = 0, Module *Parent = 0); /// Provide fast operand accessors - DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant); /// removeFromParent - This method unlinks 'this' from the containing module, /// but does not delete it. @@ -60,10 +59,10 @@ public: /// set/getAliasee - These methods retrive and set alias target. void setAliasee(Constant *GV); const Constant *getAliasee() const { - return cast_or_null(getOperand(0)); + return getOperand(0); } Constant *getAliasee() { - return cast_or_null(getOperand(0)); + return getOperand(0); } /// getAliasedGlobal() - Aliasee can be either global or bitcast of /// global. This method retrives the global for both aliasee flavours. @@ -88,7 +87,7 @@ struct OperandTraits : public FixedNumOperandTraits { }; -DEFINE_TRANSPARENT_OPERAND_ACCESSORS(GlobalAlias, Value) +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(GlobalAlias, Constant) } // End llvm namespace diff --git a/contrib/llvm/include/llvm/GlobalValue.h b/contrib/llvm/include/llvm/GlobalValue.h index d0f0888a2..63dc4ab6b 100644 --- a/contrib/llvm/include/llvm/GlobalValue.h +++ b/contrib/llvm/include/llvm/GlobalValue.h @@ -57,7 +57,7 @@ public: }; protected: - GlobalValue(const Type *ty, ValueTy vty, Use *Ops, unsigned NumOps, + GlobalValue(Type *ty, ValueTy vty, Use *Ops, unsigned NumOps, LinkageTypes linkage, const Twine &Name) : Constant(ty, vty, Ops, NumOps), Parent(0), Linkage(linkage), Visibility(DefaultVisibility), Alignment(0), diff --git a/contrib/llvm/include/llvm/GlobalVariable.h b/contrib/llvm/include/llvm/GlobalVariable.h index bbc09c177..034ade1fb 100644 --- a/contrib/llvm/include/llvm/GlobalVariable.h +++ b/contrib/llvm/include/llvm/GlobalVariable.h @@ -50,12 +50,12 @@ public: } /// GlobalVariable ctor - If a parent module is specified, the global is /// automatically inserted into the end of the specified modules global list. - GlobalVariable(const Type *Ty, bool isConstant, LinkageTypes Linkage, + GlobalVariable(Type *Ty, bool isConstant, LinkageTypes Linkage, Constant *Initializer = 0, const Twine &Name = "", bool ThreadLocal = false, unsigned AddressSpace = 0); /// GlobalVariable ctor - This creates a global and inserts it before the /// specified other global. - GlobalVariable(Module &M, const Type *Ty, bool isConstant, + GlobalVariable(Module &M, Type *Ty, bool isConstant, LinkageTypes Linkage, Constant *Initializer, const Twine &Name, GlobalVariable *InsertBefore = 0, bool ThreadLocal = false, diff --git a/contrib/llvm/include/llvm/InitializePasses.h b/contrib/llvm/include/llvm/InitializePasses.h index 4caf8f1b4..c91fbf8de 100644 --- a/contrib/llvm/include/llvm/InitializePasses.h +++ b/contrib/llvm/include/llvm/InitializePasses.h @@ -65,7 +65,7 @@ void initializeArgPromotionPass(PassRegistry&); void initializeBasicAliasAnalysisPass(PassRegistry&); void initializeBasicCallGraphPass(PassRegistry&); void initializeBlockExtractorPassPass(PassRegistry&); -void initializeBlockFrequencyPass(PassRegistry&); +void initializeBlockFrequencyInfoPass(PassRegistry&); void initializeBlockPlacementPass(PassRegistry&); void initializeBranchProbabilityInfoPass(PassRegistry&); void initializeBreakCriticalEdgesPass(PassRegistry&); @@ -143,9 +143,8 @@ void initializeLowerAtomicPass(PassRegistry&); void initializeLowerExpectIntrinsicPass(PassRegistry&); void initializeLowerIntrinsicsPass(PassRegistry&); void initializeLowerInvokePass(PassRegistry&); -void initializeLowerSetJmpPass(PassRegistry&); void initializeLowerSwitchPass(PassRegistry&); -void initializeMachineBlockFrequencyPass(PassRegistry&); +void initializeMachineBlockFrequencyInfoPass(PassRegistry&); void initializeMachineBranchProbabilityInfoPass(PassRegistry&); void initializeMachineCSEPass(PassRegistry&); void initializeMachineDominatorTreePass(PassRegistry&); @@ -220,7 +219,6 @@ void initializeStripNonDebugSymbolsPass(PassRegistry&); void initializeStripSymbolsPass(PassRegistry&); void initializeStrongPHIEliminationPass(PassRegistry&); void initializeTailCallElimPass(PassRegistry&); -void initializeTailDupPass(PassRegistry&); void initializeTargetDataPass(PassRegistry&); void initializeTargetLibraryInfoPass(PassRegistry&); void initializeTwoAddressInstructionPassPass(PassRegistry&); diff --git a/contrib/llvm/include/llvm/InlineAsm.h b/contrib/llvm/include/llvm/InlineAsm.h index a98aff178..de5ce4eca 100644 --- a/contrib/llvm/include/llvm/InlineAsm.h +++ b/contrib/llvm/include/llvm/InlineAsm.h @@ -43,7 +43,7 @@ class InlineAsm : public Value { bool HasSideEffects; bool IsAlignStack; - InlineAsm(const PointerType *Ty, const std::string &AsmString, + InlineAsm(PointerType *Ty, const std::string &AsmString, const std::string &Constraints, bool hasSideEffects, bool isAlignStack); virtual ~InlineAsm(); @@ -55,7 +55,7 @@ public: /// InlineAsm::get - Return the specified uniqued inline asm string. /// - static InlineAsm *get(const FunctionType *Ty, StringRef AsmString, + static InlineAsm *get(FunctionType *Ty, StringRef AsmString, StringRef Constraints, bool hasSideEffects, bool isAlignStack = false); @@ -79,7 +79,7 @@ public: /// the specified constraint string is legal for the type. This returns true /// if legal, false if not. /// - static bool Verify(const FunctionType *Ty, StringRef Constraints); + static bool Verify(FunctionType *Ty, StringRef Constraints); // Constraint String Parsing enum ConstraintPrefix { @@ -219,6 +219,7 @@ public: static unsigned getFlagWord(unsigned Kind, unsigned NumOps) { assert(((NumOps << 3) & ~0xffff) == 0 && "Too many inline asm operands!"); + assert(Kind >= Kind_RegUse && Kind <= Kind_Mem && "Invalid Kind"); return Kind | (NumOps << 3); } @@ -227,9 +228,24 @@ public: /// to a previous output operand. static unsigned getFlagWordForMatchingOp(unsigned InputFlag, unsigned MatchedOperandNo) { + assert(MatchedOperandNo <= 0x7fff && "Too big matched operand"); + assert((InputFlag & ~0xffff) == 0 && "High bits already contain data"); return InputFlag | Flag_MatchingOperand | (MatchedOperandNo << 16); } + /// getFlagWordForRegClass - Augment an existing flag word returned by + /// getFlagWord with the required register class for the following register + /// operands. + /// A tied use operand cannot have a register class, use the register class + /// from the def operand instead. + static unsigned getFlagWordForRegClass(unsigned InputFlag, unsigned RC) { + // Store RC + 1, reserve the value 0 to mean 'no register class'. + ++RC; + assert(RC <= 0x7fff && "Too large register class ID"); + assert((InputFlag & ~0xffff) == 0 && "High bits already contain data"); + return InputFlag | (RC << 16); + } + static unsigned getKind(unsigned Flags) { return Flags & 7; } @@ -259,6 +275,19 @@ public: return true; } + /// hasRegClassConstraint - Returns true if the flag contains a register + /// class constraint. Sets RC to the register class ID. + static bool hasRegClassConstraint(unsigned Flag, unsigned &RC) { + if (Flag & Flag_MatchingOperand) + return false; + unsigned High = Flag >> 16; + // getFlagWordForRegClass() uses 0 to mean no register class, and otherwise + // stores RC + 1. + if (!High) + return false; + RC = High - 1; + return true; + } }; diff --git a/contrib/llvm/include/llvm/InstrTypes.h b/contrib/llvm/include/llvm/InstrTypes.h index cc9ec3ac7..a1492f3c1 100644 --- a/contrib/llvm/include/llvm/InstrTypes.h +++ b/contrib/llvm/include/llvm/InstrTypes.h @@ -34,12 +34,12 @@ class LLVMContext; /// class TerminatorInst : public Instruction { protected: - TerminatorInst(const Type *Ty, Instruction::TermOps iType, + TerminatorInst(Type *Ty, Instruction::TermOps iType, Use *Ops, unsigned NumOps, Instruction *InsertBefore = 0) : Instruction(Ty, iType, Ops, NumOps, InsertBefore) {} - TerminatorInst(const Type *Ty, Instruction::TermOps iType, + TerminatorInst(Type *Ty, Instruction::TermOps iType, Use *Ops, unsigned NumOps, BasicBlock *InsertAtEnd) : Instruction(Ty, iType, Ops, NumOps, InsertAtEnd) {} @@ -91,12 +91,12 @@ class UnaryInstruction : public Instruction { void *operator new(size_t, unsigned); // Do not implement protected: - UnaryInstruction(const Type *Ty, unsigned iType, Value *V, + UnaryInstruction(Type *Ty, unsigned iType, Value *V, Instruction *IB = 0) : Instruction(Ty, iType, &Op<0>(), 1, IB) { Op<0>() = V; } - UnaryInstruction(const Type *Ty, unsigned iType, Value *V, BasicBlock *IAE) + UnaryInstruction(Type *Ty, unsigned iType, Value *V, BasicBlock *IAE) : Instruction(Ty, iType, &Op<0>(), 1, IAE) { Op<0>() = V; } @@ -141,9 +141,9 @@ class BinaryOperator : public Instruction { void *operator new(size_t, unsigned); // Do not implement protected: void init(BinaryOps iType); - BinaryOperator(BinaryOps iType, Value *S1, Value *S2, const Type *Ty, + BinaryOperator(BinaryOps iType, Value *S1, Value *S2, Type *Ty, const Twine &Name, Instruction *InsertBefore); - BinaryOperator(BinaryOps iType, Value *S1, Value *S2, const Type *Ty, + BinaryOperator(BinaryOps iType, Value *S1, Value *S2, Type *Ty, const Twine &Name, BasicBlock *InsertAtEnd); virtual BinaryOperator *clone_impl() const; public: @@ -390,13 +390,13 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(BinaryOperator, Value) class CastInst : public UnaryInstruction { protected: /// @brief Constructor with insert-before-instruction semantics for subclasses - CastInst(const Type *Ty, unsigned iType, Value *S, + CastInst(Type *Ty, unsigned iType, Value *S, const Twine &NameStr = "", Instruction *InsertBefore = 0) : UnaryInstruction(Ty, iType, S, InsertBefore) { setName(NameStr); } /// @brief Constructor with insert-at-end-of-block semantics for subclasses - CastInst(const Type *Ty, unsigned iType, Value *S, + CastInst(Type *Ty, unsigned iType, Value *S, const Twine &NameStr, BasicBlock *InsertAtEnd) : UnaryInstruction(Ty, iType, S, InsertAtEnd) { setName(NameStr); @@ -411,7 +411,7 @@ public: static CastInst *Create( Instruction::CastOps, ///< The opcode of the cast instruction Value *S, ///< The value to be casted (operand 0) - const Type *Ty, ///< The type to which cast should be made + Type *Ty, ///< The type to which cast should be made const Twine &Name = "", ///< Name for the instruction Instruction *InsertBefore = 0 ///< Place to insert the instruction ); @@ -424,7 +424,7 @@ public: static CastInst *Create( Instruction::CastOps, ///< The opcode for the cast instruction Value *S, ///< The value to be casted (operand 0) - const Type *Ty, ///< The type to which operand is casted + Type *Ty, ///< The type to which operand is casted const Twine &Name, ///< The name for the instruction BasicBlock *InsertAtEnd ///< The block to insert the instruction into ); @@ -432,7 +432,7 @@ public: /// @brief Create a ZExt or BitCast cast instruction static CastInst *CreateZExtOrBitCast( Value *S, ///< The value to be casted (operand 0) - const Type *Ty, ///< The type to which cast should be made + Type *Ty, ///< The type to which cast should be made const Twine &Name = "", ///< Name for the instruction Instruction *InsertBefore = 0 ///< Place to insert the instruction ); @@ -440,7 +440,7 @@ public: /// @brief Create a ZExt or BitCast cast instruction static CastInst *CreateZExtOrBitCast( Value *S, ///< The value to be casted (operand 0) - const Type *Ty, ///< The type to which operand is casted + Type *Ty, ///< The type to which operand is casted const Twine &Name, ///< The name for the instruction BasicBlock *InsertAtEnd ///< The block to insert the instruction into ); @@ -448,7 +448,7 @@ public: /// @brief Create a SExt or BitCast cast instruction static CastInst *CreateSExtOrBitCast( Value *S, ///< The value to be casted (operand 0) - const Type *Ty, ///< The type to which cast should be made + Type *Ty, ///< The type to which cast should be made const Twine &Name = "", ///< Name for the instruction Instruction *InsertBefore = 0 ///< Place to insert the instruction ); @@ -456,7 +456,7 @@ public: /// @brief Create a SExt or BitCast cast instruction static CastInst *CreateSExtOrBitCast( Value *S, ///< The value to be casted (operand 0) - const Type *Ty, ///< The type to which operand is casted + Type *Ty, ///< The type to which operand is casted const Twine &Name, ///< The name for the instruction BasicBlock *InsertAtEnd ///< The block to insert the instruction into ); @@ -464,7 +464,7 @@ public: /// @brief Create a BitCast or a PtrToInt cast instruction static CastInst *CreatePointerCast( Value *S, ///< The pointer value to be casted (operand 0) - const Type *Ty, ///< The type to which operand is casted + Type *Ty, ///< The type to which operand is casted const Twine &Name, ///< The name for the instruction BasicBlock *InsertAtEnd ///< The block to insert the instruction into ); @@ -472,7 +472,7 @@ public: /// @brief Create a BitCast or a PtrToInt cast instruction static CastInst *CreatePointerCast( Value *S, ///< The pointer value to be casted (operand 0) - const Type *Ty, ///< The type to which cast should be made + Type *Ty, ///< The type to which cast should be made const Twine &Name = "", ///< Name for the instruction Instruction *InsertBefore = 0 ///< Place to insert the instruction ); @@ -480,7 +480,7 @@ public: /// @brief Create a ZExt, BitCast, or Trunc for int -> int casts. static CastInst *CreateIntegerCast( Value *S, ///< The pointer value to be casted (operand 0) - const Type *Ty, ///< The type to which cast should be made + Type *Ty, ///< The type to which cast should be made bool isSigned, ///< Whether to regard S as signed or not const Twine &Name = "", ///< Name for the instruction Instruction *InsertBefore = 0 ///< Place to insert the instruction @@ -489,7 +489,7 @@ public: /// @brief Create a ZExt, BitCast, or Trunc for int -> int casts. static CastInst *CreateIntegerCast( Value *S, ///< The integer value to be casted (operand 0) - const Type *Ty, ///< The integer type to which operand is casted + Type *Ty, ///< The integer type to which operand is casted bool isSigned, ///< Whether to regard S as signed or not const Twine &Name, ///< The name for the instruction BasicBlock *InsertAtEnd ///< The block to insert the instruction into @@ -498,7 +498,7 @@ public: /// @brief Create an FPExt, BitCast, or FPTrunc for fp -> fp casts static CastInst *CreateFPCast( Value *S, ///< The floating point value to be casted - const Type *Ty, ///< The floating point type to cast to + Type *Ty, ///< The floating point type to cast to const Twine &Name = "", ///< Name for the instruction Instruction *InsertBefore = 0 ///< Place to insert the instruction ); @@ -506,7 +506,7 @@ public: /// @brief Create an FPExt, BitCast, or FPTrunc for fp -> fp casts static CastInst *CreateFPCast( Value *S, ///< The floating point value to be casted - const Type *Ty, ///< The floating point type to cast to + Type *Ty, ///< The floating point type to cast to const Twine &Name, ///< The name for the instruction BasicBlock *InsertAtEnd ///< The block to insert the instruction into ); @@ -514,7 +514,7 @@ public: /// @brief Create a Trunc or BitCast cast instruction static CastInst *CreateTruncOrBitCast( Value *S, ///< The value to be casted (operand 0) - const Type *Ty, ///< The type to which cast should be made + Type *Ty, ///< The type to which cast should be made const Twine &Name = "", ///< Name for the instruction Instruction *InsertBefore = 0 ///< Place to insert the instruction ); @@ -522,15 +522,15 @@ public: /// @brief Create a Trunc or BitCast cast instruction static CastInst *CreateTruncOrBitCast( Value *S, ///< The value to be casted (operand 0) - const Type *Ty, ///< The type to which operand is casted + Type *Ty, ///< The type to which operand is casted const Twine &Name, ///< The name for the instruction BasicBlock *InsertAtEnd ///< The block to insert the instruction into ); /// @brief Check whether it is valid to call getCastOpcode for these types. static bool isCastable( - const Type *SrcTy, ///< The Type from which the value should be cast. - const Type *DestTy ///< The Type to which the value should be cast. + 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 @@ -539,7 +539,7 @@ public: static Instruction::CastOps getCastOpcode( const Value *Val, ///< The value to cast bool SrcIsSigned, ///< Whether to treat the source as signed - const Type *Ty, ///< The Type to which the value should be casted + Type *Ty, ///< The Type to which the value should be casted bool DstIsSigned ///< Whether to treate the dest. as signed ); @@ -568,14 +568,14 @@ public: /// @brief Determine if the described cast is a no-op cast. static bool isNoopCast( Instruction::CastOps Opcode, ///< Opcode of cast - const Type *SrcTy, ///< SrcTy of cast - const Type *DstTy, ///< DstTy of cast - const Type *IntPtrTy ///< Integer type corresponding to Ptr types, or null + Type *SrcTy, ///< SrcTy of cast + Type *DstTy, ///< DstTy of cast + Type *IntPtrTy ///< Integer type corresponding to Ptr types, or null ); /// @brief Determine if this cast is a no-op cast. bool isNoopCast( - const Type *IntPtrTy ///< Integer type corresponding to pointer + Type *IntPtrTy ///< Integer type corresponding to pointer ) const; /// Determine how a pair of casts can be eliminated, if they can be at all. @@ -587,10 +587,10 @@ public: static unsigned isEliminableCastPair( Instruction::CastOps firstOpcode, ///< Opcode of first cast Instruction::CastOps secondOpcode, ///< Opcode of second cast - const Type *SrcTy, ///< SrcTy of 1st cast - const Type *MidTy, ///< DstTy of 1st cast & SrcTy of 2nd cast - const Type *DstTy, ///< DstTy of 2nd cast - const Type *IntPtrTy ///< Integer type corresponding to Ptr types, or null + Type *SrcTy, ///< SrcTy of 1st cast + Type *MidTy, ///< DstTy of 1st cast & SrcTy of 2nd cast + Type *DstTy, ///< DstTy of 2nd cast + Type *IntPtrTy ///< Integer type corresponding to Ptr types, or null ); /// @brief Return the opcode of this CastInst @@ -599,15 +599,15 @@ public: } /// @brief Return the source type, as a convenience - const Type* getSrcTy() const { return getOperand(0)->getType(); } + Type* getSrcTy() const { return getOperand(0)->getType(); } /// @brief Return the destination type, as a convenience - const Type* getDestTy() const { return getType(); } + Type* getDestTy() const { return getType(); } /// This method can be used to determine if a cast from S to DstTy using /// Opcode op is valid or not. /// @returns true iff the proposed cast is valid. /// @brief Determine if a cast is valid without creating one. - static bool castIsValid(Instruction::CastOps op, Value *S, const Type *DstTy); + static bool castIsValid(Instruction::CastOps op, Value *S, Type *DstTy); /// @brief Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const CastInst *) { return true; } @@ -629,11 +629,11 @@ class CmpInst : public Instruction { void *operator new(size_t, unsigned); // DO NOT IMPLEMENT CmpInst(); // do not implement protected: - CmpInst(const Type *ty, Instruction::OtherOps op, unsigned short pred, + CmpInst(Type *ty, Instruction::OtherOps op, unsigned short pred, Value *LHS, Value *RHS, const Twine &Name = "", Instruction *InsertBefore = 0); - CmpInst(const Type *ty, Instruction::OtherOps op, unsigned short pred, + CmpInst(Type *ty, Instruction::OtherOps op, unsigned short pred, Value *LHS, Value *RHS, const Twine &Name, BasicBlock *InsertAtEnd); @@ -825,8 +825,8 @@ public: } /// @brief Create a result type for fcmp/icmp - static const Type* makeCmpResultType(const Type* opnd_type) { - if (const VectorType* vt = dyn_cast(opnd_type)) { + static Type* makeCmpResultType(Type* opnd_type) { + if (VectorType* vt = dyn_cast(opnd_type)) { return VectorType::get(Type::getInt1Ty(opnd_type->getContext()), vt->getNumElements()); } diff --git a/contrib/llvm/include/llvm/Instruction.def b/contrib/llvm/include/llvm/Instruction.def index 205f30313..d36e4be1d 100644 --- a/contrib/llvm/include/llvm/Instruction.def +++ b/contrib/llvm/include/llvm/Instruction.def @@ -100,76 +100,80 @@ HANDLE_TERM_INST ( 3, Switch , SwitchInst) HANDLE_TERM_INST ( 4, IndirectBr , IndirectBrInst) HANDLE_TERM_INST ( 5, Invoke , InvokeInst) HANDLE_TERM_INST ( 6, Unwind , UnwindInst) -HANDLE_TERM_INST ( 7, Unreachable, UnreachableInst) - LAST_TERM_INST ( 7) +HANDLE_TERM_INST ( 7, Resume , ResumeInst) +HANDLE_TERM_INST ( 8, Unreachable, UnreachableInst) + LAST_TERM_INST ( 8) // Standard binary operators... - FIRST_BINARY_INST( 8) -HANDLE_BINARY_INST( 8, Add , BinaryOperator) -HANDLE_BINARY_INST( 9, FAdd , BinaryOperator) -HANDLE_BINARY_INST(10, Sub , BinaryOperator) -HANDLE_BINARY_INST(11, FSub , BinaryOperator) -HANDLE_BINARY_INST(12, Mul , BinaryOperator) -HANDLE_BINARY_INST(13, FMul , BinaryOperator) -HANDLE_BINARY_INST(14, UDiv , BinaryOperator) -HANDLE_BINARY_INST(15, SDiv , BinaryOperator) -HANDLE_BINARY_INST(16, FDiv , BinaryOperator) -HANDLE_BINARY_INST(17, URem , BinaryOperator) -HANDLE_BINARY_INST(18, SRem , BinaryOperator) -HANDLE_BINARY_INST(19, FRem , BinaryOperator) + FIRST_BINARY_INST( 9) +HANDLE_BINARY_INST( 9, Add , BinaryOperator) +HANDLE_BINARY_INST(10, FAdd , BinaryOperator) +HANDLE_BINARY_INST(11, Sub , BinaryOperator) +HANDLE_BINARY_INST(12, FSub , BinaryOperator) +HANDLE_BINARY_INST(13, Mul , BinaryOperator) +HANDLE_BINARY_INST(14, FMul , BinaryOperator) +HANDLE_BINARY_INST(15, UDiv , BinaryOperator) +HANDLE_BINARY_INST(16, SDiv , BinaryOperator) +HANDLE_BINARY_INST(17, FDiv , BinaryOperator) +HANDLE_BINARY_INST(18, URem , BinaryOperator) +HANDLE_BINARY_INST(19, SRem , BinaryOperator) +HANDLE_BINARY_INST(20, FRem , BinaryOperator) // Logical operators (integer operands) -HANDLE_BINARY_INST(20, Shl , BinaryOperator) // Shift left (logical) -HANDLE_BINARY_INST(21, LShr , BinaryOperator) // Shift right (logical) -HANDLE_BINARY_INST(22, AShr , BinaryOperator) // Shift right (arithmetic) -HANDLE_BINARY_INST(23, And , BinaryOperator) -HANDLE_BINARY_INST(24, Or , BinaryOperator) -HANDLE_BINARY_INST(25, Xor , BinaryOperator) - LAST_BINARY_INST(25) +HANDLE_BINARY_INST(21, Shl , BinaryOperator) // Shift left (logical) +HANDLE_BINARY_INST(22, LShr , BinaryOperator) // Shift right (logical) +HANDLE_BINARY_INST(23, AShr , BinaryOperator) // Shift right (arithmetic) +HANDLE_BINARY_INST(24, And , BinaryOperator) +HANDLE_BINARY_INST(25, Or , BinaryOperator) +HANDLE_BINARY_INST(26, Xor , BinaryOperator) + LAST_BINARY_INST(26) // Memory operators... - FIRST_MEMORY_INST(26) -HANDLE_MEMORY_INST(26, Alloca, AllocaInst) // Stack management -HANDLE_MEMORY_INST(27, Load , LoadInst ) // Memory manipulation instrs -HANDLE_MEMORY_INST(28, Store , StoreInst ) -HANDLE_MEMORY_INST(29, GetElementPtr, GetElementPtrInst) - LAST_MEMORY_INST(29) + FIRST_MEMORY_INST(27) +HANDLE_MEMORY_INST(27, Alloca, AllocaInst) // Stack management +HANDLE_MEMORY_INST(28, Load , LoadInst ) // Memory manipulation instrs +HANDLE_MEMORY_INST(29, Store , StoreInst ) +HANDLE_MEMORY_INST(30, GetElementPtr, GetElementPtrInst) +HANDLE_MEMORY_INST(31, Fence , FenceInst ) +HANDLE_MEMORY_INST(32, AtomicCmpXchg , AtomicCmpXchgInst ) +HANDLE_MEMORY_INST(33, AtomicRMW , AtomicRMWInst ) + LAST_MEMORY_INST(33) // Cast operators ... // NOTE: The order matters here because CastInst::isEliminableCastPair // NOTE: (see Instructions.cpp) encodes a table based on this ordering. - FIRST_CAST_INST(30) -HANDLE_CAST_INST(30, Trunc , TruncInst ) // Truncate integers -HANDLE_CAST_INST(31, ZExt , ZExtInst ) // Zero extend integers -HANDLE_CAST_INST(32, SExt , SExtInst ) // Sign extend integers -HANDLE_CAST_INST(33, FPToUI , FPToUIInst ) // floating point -> UInt -HANDLE_CAST_INST(34, FPToSI , FPToSIInst ) // floating point -> SInt -HANDLE_CAST_INST(35, UIToFP , UIToFPInst ) // UInt -> floating point -HANDLE_CAST_INST(36, SIToFP , SIToFPInst ) // SInt -> floating point -HANDLE_CAST_INST(37, FPTrunc , FPTruncInst ) // Truncate floating point -HANDLE_CAST_INST(38, FPExt , FPExtInst ) // Extend floating point -HANDLE_CAST_INST(39, PtrToInt, PtrToIntInst) // Pointer -> Integer -HANDLE_CAST_INST(40, IntToPtr, IntToPtrInst) // Integer -> Pointer -HANDLE_CAST_INST(41, BitCast , BitCastInst ) // Type cast - LAST_CAST_INST(41) + FIRST_CAST_INST(34) +HANDLE_CAST_INST(34, Trunc , TruncInst ) // Truncate integers +HANDLE_CAST_INST(35, ZExt , ZExtInst ) // Zero extend integers +HANDLE_CAST_INST(36, SExt , SExtInst ) // Sign extend integers +HANDLE_CAST_INST(37, FPToUI , FPToUIInst ) // floating point -> UInt +HANDLE_CAST_INST(38, FPToSI , FPToSIInst ) // floating point -> SInt +HANDLE_CAST_INST(39, UIToFP , UIToFPInst ) // UInt -> floating point +HANDLE_CAST_INST(40, SIToFP , SIToFPInst ) // SInt -> floating point +HANDLE_CAST_INST(41, FPTrunc , FPTruncInst ) // Truncate floating point +HANDLE_CAST_INST(42, FPExt , FPExtInst ) // Extend floating point +HANDLE_CAST_INST(43, PtrToInt, PtrToIntInst) // Pointer -> Integer +HANDLE_CAST_INST(44, IntToPtr, IntToPtrInst) // Integer -> Pointer +HANDLE_CAST_INST(45, BitCast , BitCastInst ) // Type cast + LAST_CAST_INST(45) // Other operators... - FIRST_OTHER_INST(42) -HANDLE_OTHER_INST(42, ICmp , ICmpInst ) // Integer comparison instruction -HANDLE_OTHER_INST(43, FCmp , FCmpInst ) // Floating point comparison instr. -HANDLE_OTHER_INST(44, PHI , PHINode ) // PHI node instruction -HANDLE_OTHER_INST(45, Call , CallInst ) // Call a function -HANDLE_OTHER_INST(46, Select , SelectInst ) // select instruction -HANDLE_OTHER_INST(47, UserOp1, Instruction) // May be used internally in a pass -HANDLE_OTHER_INST(48, UserOp2, Instruction) // Internal to passes only -HANDLE_OTHER_INST(49, VAArg , VAArgInst ) // vaarg instruction -HANDLE_OTHER_INST(50, ExtractElement, ExtractElementInst)// extract from vector -HANDLE_OTHER_INST(51, InsertElement, InsertElementInst) // insert into vector -HANDLE_OTHER_INST(52, ShuffleVector, ShuffleVectorInst) // shuffle two vectors. -HANDLE_OTHER_INST(53, ExtractValue, ExtractValueInst)// extract from aggregate -HANDLE_OTHER_INST(54, InsertValue, InsertValueInst) // insert into aggregate - - LAST_OTHER_INST(54) + 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/Instruction.h b/contrib/llvm/include/llvm/Instruction.h index 89bb9fdf4..934e89015 100644 --- a/contrib/llvm/include/llvm/Instruction.h +++ b/contrib/llvm/include/llvm/Instruction.h @@ -223,6 +223,13 @@ public: /// bool mayReadFromMemory() const; + /// mayReadOrWriteMemory - Return true if this instruction may read or + /// write memory. + /// + bool mayReadOrWriteMemory() const { + return mayReadFromMemory() || mayWriteToMemory(); + } + /// mayThrow - Return true if this instruction may throw an exception. /// bool mayThrow() const; @@ -365,9 +372,9 @@ protected: return getSubclassDataFromValue() & ~HasMetadataBit; } - Instruction(const Type *Ty, unsigned iType, Use *Ops, unsigned NumOps, + Instruction(Type *Ty, unsigned iType, Use *Ops, unsigned NumOps, Instruction *InsertBefore = 0); - Instruction(const Type *Ty, unsigned iType, Use *Ops, unsigned NumOps, + Instruction(Type *Ty, unsigned iType, Use *Ops, unsigned NumOps, BasicBlock *InsertAtEnd); virtual Instruction *clone_impl() const = 0; diff --git a/contrib/llvm/include/llvm/Instructions.h b/contrib/llvm/include/llvm/Instructions.h index 0bc9a3b64..3faab35bf 100644 --- a/contrib/llvm/include/llvm/Instructions.h +++ b/contrib/llvm/include/llvm/Instructions.h @@ -22,6 +22,7 @@ #include "llvm/CallingConv.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/Support/ErrorHandling.h" #include namespace llvm { @@ -31,6 +32,22 @@ class ConstantRange; class APInt; class LLVMContext; +enum AtomicOrdering { + NotAtomic = 0, + Unordered = 1, + Monotonic = 2, + // Consume = 3, // Not specified yet. + Acquire = 4, + Release = 5, + AcquireRelease = 6, + SequentiallyConsistent = 7 +}; + +enum SynchronizationScope { + SingleThread = 0, + CrossThread = 1 +}; + //===----------------------------------------------------------------------===// // AllocaInst Class //===----------------------------------------------------------------------===// @@ -41,17 +58,17 @@ class AllocaInst : public UnaryInstruction { protected: virtual AllocaInst *clone_impl() const; public: - explicit AllocaInst(const Type *Ty, Value *ArraySize = 0, + explicit AllocaInst(Type *Ty, Value *ArraySize = 0, const Twine &Name = "", Instruction *InsertBefore = 0); - AllocaInst(const Type *Ty, Value *ArraySize, + AllocaInst(Type *Ty, Value *ArraySize, const Twine &Name, BasicBlock *InsertAtEnd); - AllocaInst(const Type *Ty, const Twine &Name, Instruction *InsertBefore = 0); - AllocaInst(const Type *Ty, const Twine &Name, BasicBlock *InsertAtEnd); + AllocaInst(Type *Ty, const Twine &Name, Instruction *InsertBefore = 0); + AllocaInst(Type *Ty, const Twine &Name, BasicBlock *InsertAtEnd); - AllocaInst(const Type *Ty, Value *ArraySize, unsigned Align, + AllocaInst(Type *Ty, Value *ArraySize, unsigned Align, const Twine &Name = "", Instruction *InsertBefore = 0); - AllocaInst(const Type *Ty, Value *ArraySize, unsigned Align, + AllocaInst(Type *Ty, Value *ArraySize, unsigned Align, const Twine &Name, BasicBlock *InsertAtEnd); // Out of line virtual method, so the vtable, etc. has a home. @@ -70,8 +87,8 @@ public: /// getType - Overload to return most specific pointer type /// - const PointerType *getType() const { - return reinterpret_cast(Instruction::getType()); + PointerType *getType() const { + return reinterpret_cast(Instruction::getType()); } /// getAllocatedType - Return the type that is being allocated by the @@ -125,12 +142,20 @@ public: LoadInst(Value *Ptr, const Twine &NameStr, BasicBlock *InsertAtEnd); LoadInst(Value *Ptr, const Twine &NameStr, bool isVolatile = false, Instruction *InsertBefore = 0); - LoadInst(Value *Ptr, const Twine &NameStr, bool isVolatile, - unsigned Align, Instruction *InsertBefore = 0); LoadInst(Value *Ptr, const Twine &NameStr, bool isVolatile, BasicBlock *InsertAtEnd); + LoadInst(Value *Ptr, const Twine &NameStr, bool isVolatile, + unsigned Align, Instruction *InsertBefore = 0); LoadInst(Value *Ptr, const Twine &NameStr, bool isVolatile, unsigned Align, BasicBlock *InsertAtEnd); + LoadInst(Value *Ptr, const Twine &NameStr, bool isVolatile, + unsigned Align, AtomicOrdering Order, + SynchronizationScope SynchScope = CrossThread, + Instruction *InsertBefore = 0); + LoadInst(Value *Ptr, const Twine &NameStr, bool isVolatile, + unsigned Align, AtomicOrdering Order, + SynchronizationScope SynchScope, + BasicBlock *InsertAtEnd); LoadInst(Value *Ptr, const char *NameStr, Instruction *InsertBefore); LoadInst(Value *Ptr, const char *NameStr, BasicBlock *InsertAtEnd); @@ -154,11 +179,47 @@ public: /// getAlignment - Return the alignment of the access that is being performed /// unsigned getAlignment() const { - return (1 << (getSubclassDataFromInstruction() >> 1)) >> 1; + return (1 << ((getSubclassDataFromInstruction() >> 1) & 31)) >> 1; } void setAlignment(unsigned Align); + /// Returns the ordering effect of this fence. + AtomicOrdering getOrdering() const { + return AtomicOrdering((getSubclassDataFromInstruction() >> 7) & 7); + } + + /// Set the ordering constraint on this load. May not be Release or + /// AcquireRelease. + void setOrdering(AtomicOrdering Ordering) { + setInstructionSubclassData((getSubclassDataFromInstruction() & ~(7 << 7)) | + (Ordering << 7)); + } + + SynchronizationScope getSynchScope() const { + return SynchronizationScope((getSubclassDataFromInstruction() >> 6) & 1); + } + + /// Specify whether this load is ordered with respect to all + /// concurrently executing threads, or only with respect to signal handlers + /// executing in the same thread. + void setSynchScope(SynchronizationScope xthread) { + setInstructionSubclassData((getSubclassDataFromInstruction() & ~(1 << 6)) | + (xthread << 6)); + } + + bool isAtomic() const { return getOrdering() != NotAtomic; } + void setAtomic(AtomicOrdering Ordering, + SynchronizationScope SynchScope = CrossThread) { + setOrdering(Ordering); + setSynchScope(SynchScope); + } + + bool isSimple() const { return !isAtomic() && !isVolatile(); } + bool isUnordered() const { + return getOrdering() <= Unordered && !isVolatile(); + } + Value *getPointerOperand() { return getOperand(0); } const Value *getPointerOperand() const { return getOperand(0); } static unsigned getPointerOperandIndex() { return 0U; } @@ -205,19 +266,27 @@ public: StoreInst(Value *Val, Value *Ptr, BasicBlock *InsertAtEnd); StoreInst(Value *Val, Value *Ptr, bool isVolatile = false, Instruction *InsertBefore = 0); + StoreInst(Value *Val, Value *Ptr, bool isVolatile, BasicBlock *InsertAtEnd); StoreInst(Value *Val, Value *Ptr, bool isVolatile, unsigned Align, Instruction *InsertBefore = 0); - StoreInst(Value *Val, Value *Ptr, bool isVolatile, BasicBlock *InsertAtEnd); StoreInst(Value *Val, Value *Ptr, bool isVolatile, unsigned Align, BasicBlock *InsertAtEnd); + StoreInst(Value *Val, Value *Ptr, bool isVolatile, + unsigned Align, AtomicOrdering Order, + SynchronizationScope SynchScope = CrossThread, + Instruction *InsertBefore = 0); + StoreInst(Value *Val, Value *Ptr, bool isVolatile, + unsigned Align, AtomicOrdering Order, + SynchronizationScope SynchScope, + BasicBlock *InsertAtEnd); + - - /// isVolatile - Return true if this is a load from a volatile memory + /// isVolatile - Return true if this is a store to a volatile memory /// location. /// bool isVolatile() const { return getSubclassDataFromInstruction() & 1; } - /// setVolatile - Specify whether this is a volatile load or not. + /// setVolatile - Specify whether this is a volatile store or not. /// void setVolatile(bool V) { setInstructionSubclassData((getSubclassDataFromInstruction() & ~1) | @@ -230,11 +299,47 @@ public: /// getAlignment - Return the alignment of the access that is being performed /// unsigned getAlignment() const { - return (1 << (getSubclassDataFromInstruction() >> 1)) >> 1; + return (1 << ((getSubclassDataFromInstruction() >> 1) & 31)) >> 1; } void setAlignment(unsigned Align); + /// Returns the ordering effect of this store. + AtomicOrdering getOrdering() const { + return AtomicOrdering((getSubclassDataFromInstruction() >> 7) & 7); + } + + /// Set the ordering constraint on this store. May not be Acquire or + /// AcquireRelease. + void setOrdering(AtomicOrdering Ordering) { + setInstructionSubclassData((getSubclassDataFromInstruction() & ~(7 << 7)) | + (Ordering << 7)); + } + + SynchronizationScope getSynchScope() const { + return SynchronizationScope((getSubclassDataFromInstruction() >> 6) & 1); + } + + /// Specify whether this store instruction is ordered with respect to all + /// concurrently executing threads, or only with respect to signal handlers + /// executing in the same thread. + void setSynchScope(SynchronizationScope xthread) { + setInstructionSubclassData((getSubclassDataFromInstruction() & ~(1 << 6)) | + (xthread << 6)); + } + + bool isAtomic() const { return getOrdering() != NotAtomic; } + void setAtomic(AtomicOrdering Ordering, + SynchronizationScope SynchScope = CrossThread) { + setOrdering(Ordering); + setSynchScope(SynchScope); + } + + bool isSimple() const { return !isAtomic() && !isVolatile(); } + bool isUnordered() const { + return getOrdering() <= Unordered && !isVolatile(); + } + Value *getValueOperand() { return getOperand(0); } const Value *getValueOperand() const { return getOperand(0); } @@ -268,6 +373,325 @@ struct OperandTraits : public FixedNumOperandTraits { DEFINE_TRANSPARENT_OPERAND_ACCESSORS(StoreInst, Value) +//===----------------------------------------------------------------------===// +// FenceInst Class +//===----------------------------------------------------------------------===// + +/// FenceInst - an instruction for ordering other memory operations +/// +class FenceInst : public Instruction { + void *operator new(size_t, unsigned); // DO NOT IMPLEMENT + void Init(AtomicOrdering Ordering, SynchronizationScope SynchScope); +protected: + virtual FenceInst *clone_impl() const; +public: + // allocate space for exactly zero operands + void *operator new(size_t s) { + return User::operator new(s, 0); + } + + // Ordering may only be Acquire, Release, AcquireRelease, or + // SequentiallyConsistent. + FenceInst(LLVMContext &C, AtomicOrdering Ordering, + SynchronizationScope SynchScope = CrossThread, + Instruction *InsertBefore = 0); + FenceInst(LLVMContext &C, AtomicOrdering Ordering, + SynchronizationScope SynchScope, + BasicBlock *InsertAtEnd); + + /// Returns the ordering effect of this fence. + AtomicOrdering getOrdering() const { + return AtomicOrdering(getSubclassDataFromInstruction() >> 1); + } + + /// Set the ordering constraint on this fence. May only be Acquire, Release, + /// AcquireRelease, or SequentiallyConsistent. + void setOrdering(AtomicOrdering Ordering) { + setInstructionSubclassData((getSubclassDataFromInstruction() & 1) | + (Ordering << 1)); + } + + SynchronizationScope getSynchScope() const { + return SynchronizationScope(getSubclassDataFromInstruction() & 1); + } + + /// Specify whether this fence orders other operations with respect to all + /// concurrently executing threads, or only with respect to signal handlers + /// executing in the same thread. + void setSynchScope(SynchronizationScope xthread) { + setInstructionSubclassData((getSubclassDataFromInstruction() & ~1) | + xthread); + } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const FenceInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::Fence; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +private: + // Shadow Instruction::setInstructionSubclassData with a private forwarding + // method so that subclasses cannot accidentally use it. + void setInstructionSubclassData(unsigned short D) { + Instruction::setInstructionSubclassData(D); + } +}; + +//===----------------------------------------------------------------------===// +// AtomicCmpXchgInst Class +//===----------------------------------------------------------------------===// + +/// AtomicCmpXchgInst - an instruction that atomically checks whether a +/// specified value is in a memory location, and, if it is, stores a new value +/// there. Returns the value that was loaded. +/// +class AtomicCmpXchgInst : public Instruction { + void *operator new(size_t, unsigned); // DO NOT IMPLEMENT + void Init(Value *Ptr, Value *Cmp, Value *NewVal, + AtomicOrdering Ordering, SynchronizationScope SynchScope); +protected: + virtual AtomicCmpXchgInst *clone_impl() const; +public: + // allocate space for exactly three operands + void *operator new(size_t s) { + return User::operator new(s, 3); + } + AtomicCmpXchgInst(Value *Ptr, Value *Cmp, Value *NewVal, + AtomicOrdering Ordering, SynchronizationScope SynchScope, + Instruction *InsertBefore = 0); + AtomicCmpXchgInst(Value *Ptr, Value *Cmp, Value *NewVal, + AtomicOrdering Ordering, SynchronizationScope SynchScope, + BasicBlock *InsertAtEnd); + + /// isVolatile - Return true if this is a cmpxchg from a volatile memory + /// location. + /// + bool isVolatile() const { + return getSubclassDataFromInstruction() & 1; + } + + /// setVolatile - Specify whether this is a volatile cmpxchg. + /// + void setVolatile(bool V) { + setInstructionSubclassData((getSubclassDataFromInstruction() & ~1) | + (unsigned)V); + } + + /// Transparently provide more efficient getOperand methods. + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + /// Set the ordering constraint on this cmpxchg. + void setOrdering(AtomicOrdering Ordering) { + assert(Ordering != NotAtomic && + "CmpXchg instructions can only be atomic."); + setInstructionSubclassData((getSubclassDataFromInstruction() & 3) | + (Ordering << 2)); + } + + /// Specify whether this cmpxchg is atomic and orders other operations with + /// respect to all concurrently executing threads, or only with respect to + /// signal handlers executing in the same thread. + void setSynchScope(SynchronizationScope SynchScope) { + setInstructionSubclassData((getSubclassDataFromInstruction() & ~2) | + (SynchScope << 1)); + } + + /// Returns the ordering constraint on this cmpxchg. + AtomicOrdering getOrdering() const { + return AtomicOrdering(getSubclassDataFromInstruction() >> 2); + } + + /// Returns whether this cmpxchg is atomic between threads or only within a + /// single thread. + SynchronizationScope getSynchScope() const { + return SynchronizationScope((getSubclassDataFromInstruction() & 2) >> 1); + } + + Value *getPointerOperand() { return getOperand(0); } + const Value *getPointerOperand() const { return getOperand(0); } + static unsigned getPointerOperandIndex() { return 0U; } + + Value *getCompareOperand() { return getOperand(1); } + const Value *getCompareOperand() const { return getOperand(1); } + + Value *getNewValOperand() { return getOperand(2); } + const Value *getNewValOperand() const { return getOperand(2); } + + unsigned getPointerAddressSpace() const { + return cast(getPointerOperand()->getType())->getAddressSpace(); + } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const AtomicCmpXchgInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::AtomicCmpXchg; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +private: + // Shadow Instruction::setInstructionSubclassData with a private forwarding + // method so that subclasses cannot accidentally use it. + void setInstructionSubclassData(unsigned short D) { + Instruction::setInstructionSubclassData(D); + } +}; + +template <> +struct OperandTraits : + public FixedNumOperandTraits { +}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(AtomicCmpXchgInst, Value) + +//===----------------------------------------------------------------------===// +// AtomicRMWInst Class +//===----------------------------------------------------------------------===// + +/// AtomicRMWInst - an instruction that atomically reads a memory location, +/// combines it with another value, and then stores the result back. Returns +/// the old value. +/// +class AtomicRMWInst : public Instruction { + void *operator new(size_t, unsigned); // DO NOT IMPLEMENT +protected: + virtual AtomicRMWInst *clone_impl() const; +public: + /// This enumeration lists the possible modifications atomicrmw can make. In + /// the descriptions, 'p' is the pointer to the instruction's memory location, + /// 'old' is the initial value of *p, and 'v' is the other value passed to the + /// instruction. These instructions always return 'old'. + enum BinOp { + /// *p = v + Xchg, + /// *p = old + v + Add, + /// *p = old - v + Sub, + /// *p = old & v + And, + /// *p = ~old & v + Nand, + /// *p = old | v + Or, + /// *p = old ^ v + Xor, + /// *p = old >signed v ? old : v + Max, + /// *p = old unsigned v ? old : v + UMax, + /// *p = old (getSubclassDataFromInstruction() >> 5); + } + + void setOperation(BinOp Operation) { + unsigned short SubclassData = getSubclassDataFromInstruction(); + setInstructionSubclassData((SubclassData & 31) | + (Operation << 5)); + } + + /// isVolatile - Return true if this is a RMW on a volatile memory location. + /// + bool isVolatile() const { + return getSubclassDataFromInstruction() & 1; + } + + /// setVolatile - Specify whether this is a volatile RMW or not. + /// + void setVolatile(bool V) { + setInstructionSubclassData((getSubclassDataFromInstruction() & ~1) | + (unsigned)V); + } + + /// Transparently provide more efficient getOperand methods. + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + /// Set the ordering constraint on this RMW. + void setOrdering(AtomicOrdering Ordering) { + assert(Ordering != NotAtomic && + "atomicrmw instructions can only be atomic."); + setInstructionSubclassData((getSubclassDataFromInstruction() & ~(7 << 2)) | + (Ordering << 2)); + } + + /// Specify whether this RMW orders other operations with respect to all + /// concurrently executing threads, or only with respect to signal handlers + /// executing in the same thread. + void setSynchScope(SynchronizationScope SynchScope) { + setInstructionSubclassData((getSubclassDataFromInstruction() & ~2) | + (SynchScope << 1)); + } + + /// Returns the ordering constraint on this RMW. + AtomicOrdering getOrdering() const { + return AtomicOrdering((getSubclassDataFromInstruction() >> 2) & 7); + } + + /// Returns whether this RMW is atomic between threads or only within a + /// single thread. + SynchronizationScope getSynchScope() const { + return SynchronizationScope((getSubclassDataFromInstruction() & 2) >> 1); + } + + Value *getPointerOperand() { return getOperand(0); } + const Value *getPointerOperand() const { return getOperand(0); } + static unsigned getPointerOperandIndex() { return 0U; } + + Value *getValOperand() { return getOperand(1); } + const Value *getValOperand() const { return getOperand(1); } + + unsigned getPointerAddressSpace() const { + return cast(getPointerOperand()->getType())->getAddressSpace(); + } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const AtomicRMWInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::AtomicRMW; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +private: + void Init(BinOp Operation, Value *Ptr, Value *Val, + AtomicOrdering Ordering, SynchronizationScope SynchScope); + // Shadow Instruction::setInstructionSubclassData with a private forwarding + // method so that subclasses cannot accidentally use it. + void setInstructionSubclassData(unsigned short D) { + Instruction::setInstructionSubclassData(D); + } +}; + +template <> +struct OperandTraits + : public FixedNumOperandTraits { +}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(AtomicRMWInst, Value) + //===----------------------------------------------------------------------===// // GetElementPtrInst Class //===----------------------------------------------------------------------===// @@ -275,7 +699,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(StoreInst, Value) // checkGEPType - Simple wrapper function to give a better assertion failure // message on bad indexes for a gep instruction. // -static inline const Type *checkGEPType(const Type *Ty) { +static inline Type *checkGEPType(Type *Ty) { assert(Ty && "Invalid GetElementPtrInst indices for type!"); return Ty; } @@ -285,149 +709,51 @@ static inline const Type *checkGEPType(const Type *Ty) { /// class GetElementPtrInst : public Instruction { GetElementPtrInst(const GetElementPtrInst &GEPI); - void init(Value *Ptr, Value* const *Idx, unsigned NumIdx, - const Twine &NameStr); - void init(Value *Ptr, Value *Idx, const Twine &NameStr); - - template - void init(Value *Ptr, - RandomAccessIterator IdxBegin, - RandomAccessIterator IdxEnd, - const Twine &NameStr, - // This argument ensures that we have an iterator we can - // do arithmetic on in constant time - std::random_access_iterator_tag) { - unsigned NumIdx = static_cast(std::distance(IdxBegin, IdxEnd)); - - if (NumIdx > 0) { - // This requires that the iterator points to contiguous memory. - init(Ptr, &*IdxBegin, NumIdx, NameStr); // FIXME: for the general case - // we have to build an array here - } - else { - init(Ptr, 0, NumIdx, NameStr); - } - } - - /// getIndexedType - Returns the type of the element that would be loaded with - /// a load instruction with the specified parameters. - /// - /// Null is returned if the indices are invalid for the specified - /// pointer type. - /// - template - static Type *getIndexedType(const Type *Ptr, - RandomAccessIterator IdxBegin, - RandomAccessIterator IdxEnd, - // This argument ensures that we - // have an iterator we can do - // arithmetic on in constant time - std::random_access_iterator_tag) { - unsigned NumIdx = static_cast(std::distance(IdxBegin, IdxEnd)); - - if (NumIdx > 0) - // This requires that the iterator points to contiguous memory. - return getIndexedType(Ptr, &*IdxBegin, NumIdx); - else - return getIndexedType(Ptr, (Value *const*)0, NumIdx); - } + void init(Value *Ptr, ArrayRef IdxList, const Twine &NameStr); /// Constructors - Create a getelementptr instruction with a base pointer an /// list of indices. The first ctor can optionally insert before an existing /// instruction, the second appends the new instruction to the specified /// BasicBlock. - template - inline GetElementPtrInst(Value *Ptr, RandomAccessIterator IdxBegin, - RandomAccessIterator IdxEnd, - unsigned Values, - const Twine &NameStr, + inline GetElementPtrInst(Value *Ptr, ArrayRef IdxList, + unsigned Values, const Twine &NameStr, Instruction *InsertBefore); - template - inline GetElementPtrInst(Value *Ptr, - RandomAccessIterator IdxBegin, - RandomAccessIterator IdxEnd, - unsigned Values, - const Twine &NameStr, BasicBlock *InsertAtEnd); - - /// Constructors - These two constructors are convenience methods because one - /// and two index getelementptr instructions are so common. - GetElementPtrInst(Value *Ptr, Value *Idx, const Twine &NameStr = "", - Instruction *InsertBefore = 0); - GetElementPtrInst(Value *Ptr, Value *Idx, - const Twine &NameStr, BasicBlock *InsertAtEnd); + inline GetElementPtrInst(Value *Ptr, ArrayRef IdxList, + unsigned Values, const Twine &NameStr, + BasicBlock *InsertAtEnd); protected: virtual GetElementPtrInst *clone_impl() const; public: - template - static GetElementPtrInst *Create(Value *Ptr, RandomAccessIterator IdxBegin, - RandomAccessIterator IdxEnd, + static GetElementPtrInst *Create(Value *Ptr, ArrayRef IdxList, const Twine &NameStr = "", Instruction *InsertBefore = 0) { - typename std::iterator_traits::difference_type - Values = 1 + std::distance(IdxBegin, IdxEnd); + unsigned Values = 1 + unsigned(IdxList.size()); return new(Values) - GetElementPtrInst(Ptr, IdxBegin, IdxEnd, Values, NameStr, InsertBefore); + GetElementPtrInst(Ptr, IdxList, Values, NameStr, InsertBefore); } - template - static GetElementPtrInst *Create(Value *Ptr, - RandomAccessIterator IdxBegin, - RandomAccessIterator IdxEnd, + static GetElementPtrInst *Create(Value *Ptr, ArrayRef IdxList, const Twine &NameStr, BasicBlock *InsertAtEnd) { - typename std::iterator_traits::difference_type - Values = 1 + std::distance(IdxBegin, IdxEnd); + unsigned Values = 1 + unsigned(IdxList.size()); return new(Values) - GetElementPtrInst(Ptr, IdxBegin, IdxEnd, Values, NameStr, InsertAtEnd); - } - - /// Constructors - These two creators are convenience methods because one - /// index getelementptr instructions are so common. - static GetElementPtrInst *Create(Value *Ptr, Value *Idx, - const Twine &NameStr = "", - Instruction *InsertBefore = 0) { - return new(2) GetElementPtrInst(Ptr, Idx, NameStr, InsertBefore); - } - static GetElementPtrInst *Create(Value *Ptr, Value *Idx, - const Twine &NameStr, - BasicBlock *InsertAtEnd) { - return new(2) GetElementPtrInst(Ptr, Idx, NameStr, InsertAtEnd); + GetElementPtrInst(Ptr, IdxList, Values, NameStr, InsertAtEnd); } /// Create an "inbounds" getelementptr. See the documentation for the /// "inbounds" flag in LangRef.html for details. - template static GetElementPtrInst *CreateInBounds(Value *Ptr, - RandomAccessIterator IdxBegin, - RandomAccessIterator IdxEnd, + ArrayRef IdxList, const Twine &NameStr = "", Instruction *InsertBefore = 0) { - GetElementPtrInst *GEP = Create(Ptr, IdxBegin, IdxEnd, - NameStr, InsertBefore); + GetElementPtrInst *GEP = Create(Ptr, IdxList, NameStr, InsertBefore); GEP->setIsInBounds(true); return GEP; } - template static GetElementPtrInst *CreateInBounds(Value *Ptr, - RandomAccessIterator IdxBegin, - RandomAccessIterator IdxEnd, + ArrayRef IdxList, const Twine &NameStr, BasicBlock *InsertAtEnd) { - GetElementPtrInst *GEP = Create(Ptr, IdxBegin, IdxEnd, - NameStr, InsertAtEnd); - GEP->setIsInBounds(true); - return GEP; - } - static GetElementPtrInst *CreateInBounds(Value *Ptr, Value *Idx, - const Twine &NameStr = "", - Instruction *InsertBefore = 0) { - GetElementPtrInst *GEP = Create(Ptr, Idx, NameStr, InsertBefore); - GEP->setIsInBounds(true); - return GEP; - } - static GetElementPtrInst *CreateInBounds(Value *Ptr, Value *Idx, - const Twine &NameStr, - BasicBlock *InsertAtEnd) { - GetElementPtrInst *GEP = Create(Ptr, Idx, NameStr, InsertAtEnd); + GetElementPtrInst *GEP = Create(Ptr, IdxList, NameStr, InsertAtEnd); GEP->setIsInBounds(true); return GEP; } @@ -436,8 +762,8 @@ public: DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); // getType - Overload to return most specific pointer type... - const PointerType *getType() const { - return reinterpret_cast(Instruction::getType()); + PointerType *getType() const { + return reinterpret_cast(Instruction::getType()); } /// getIndexedType - Returns the type of the element that would be loaded with @@ -446,23 +772,9 @@ public: /// Null is returned if the indices are invalid for the specified /// pointer type. /// - template - static Type *getIndexedType(const Type *Ptr, RandomAccessIterator IdxBegin, - RandomAccessIterator IdxEnd) { - return getIndexedType(Ptr, IdxBegin, IdxEnd, - typename std::iterator_traits:: - iterator_category()); - } - - // FIXME: Use ArrayRef - static Type *getIndexedType(const Type *Ptr, - Value* const *Idx, unsigned NumIdx); - static Type *getIndexedType(const Type *Ptr, - Constant* const *Idx, unsigned NumIdx); - - static Type *getIndexedType(const Type *Ptr, - uint64_t const *Idx, unsigned NumIdx); - static Type *getIndexedType(const Type *Ptr, Value *Idx); + static Type *getIndexedType(Type *Ptr, ArrayRef IdxList); + static Type *getIndexedType(Type *Ptr, ArrayRef IdxList); + static Type *getIndexedType(Type *Ptr, ArrayRef IdxList); inline op_iterator idx_begin() { return op_begin()+1; } inline const_op_iterator idx_begin() const { return op_begin()+1; } @@ -485,8 +797,8 @@ public: /// getPointerOperandType - Method to return the pointer operand as a /// PointerType. - const PointerType *getPointerOperandType() const { - return reinterpret_cast(getPointerOperand()->getType()); + PointerType *getPointerOperandType() const { + return reinterpret_cast(getPointerOperand()->getType()); } @@ -530,43 +842,33 @@ struct OperandTraits : public VariadicOperandTraits { }; -template GetElementPtrInst::GetElementPtrInst(Value *Ptr, - RandomAccessIterator IdxBegin, - RandomAccessIterator IdxEnd, + ArrayRef IdxList, unsigned Values, const Twine &NameStr, Instruction *InsertBefore) : Instruction(PointerType::get(checkGEPType( - getIndexedType(Ptr->getType(), - IdxBegin, IdxEnd)), + getIndexedType(Ptr->getType(), IdxList)), cast(Ptr->getType()) ->getAddressSpace()), GetElementPtr, OperandTraits::op_end(this) - Values, Values, InsertBefore) { - init(Ptr, IdxBegin, IdxEnd, NameStr, - typename std::iterator_traits - ::iterator_category()); + init(Ptr, IdxList, NameStr); } -template GetElementPtrInst::GetElementPtrInst(Value *Ptr, - RandomAccessIterator IdxBegin, - RandomAccessIterator IdxEnd, + ArrayRef IdxList, unsigned Values, const Twine &NameStr, BasicBlock *InsertAtEnd) : Instruction(PointerType::get(checkGEPType( - getIndexedType(Ptr->getType(), - IdxBegin, IdxEnd)), + getIndexedType(Ptr->getType(), IdxList)), cast(Ptr->getType()) ->getAddressSpace()), GetElementPtr, OperandTraits::op_end(this) - Values, Values, InsertAtEnd) { - init(Ptr, IdxBegin, IdxEnd, NameStr, - typename std::iterator_traits - ::iterator_category()); + init(Ptr, IdxList, NameStr); } @@ -893,12 +1195,12 @@ public: /// 2. Call malloc with that argument. /// 3. Bitcast the result of the malloc call to the specified type. static Instruction *CreateMalloc(Instruction *InsertBefore, - const Type *IntPtrTy, const Type *AllocTy, + Type *IntPtrTy, Type *AllocTy, Value *AllocSize, Value *ArraySize = 0, Function* MallocF = 0, const Twine &Name = ""); static Instruction *CreateMalloc(BasicBlock *InsertAtEnd, - const Type *IntPtrTy, const Type *AllocTy, + Type *IntPtrTy, Type *AllocTy, Value *AllocSize, Value *ArraySize = 0, Function* MallocF = 0, const Twine &Name = ""); @@ -965,6 +1267,15 @@ public: else removeAttribute(~0, Attribute::NoInline); } + /// @brief Return true if the call can return twice + bool canReturnTwice() const { + return paramHasAttr(~0, Attribute::ReturnsTwice); + } + void setCanReturnTwice(bool Value = true) { + if (Value) addAttribute(~0, Attribute::ReturnsTwice); + else removeAttribute(~0, Attribute::ReturnsTwice); + } + /// @brief Determine if the call does not access memory. bool doesNotAccessMemory() const { return paramHasAttr(~0, Attribute::ReadNone); @@ -1165,12 +1476,12 @@ protected: virtual VAArgInst *clone_impl() const; public: - VAArgInst(Value *List, const Type *Ty, const Twine &NameStr = "", + VAArgInst(Value *List, Type *Ty, const Twine &NameStr = "", Instruction *InsertBefore = 0) : UnaryInstruction(Ty, VAArg, List, InsertBefore) { setName(NameStr); } - VAArgInst(Value *List, const Type *Ty, const Twine &NameStr, + VAArgInst(Value *List, Type *Ty, const Twine &NameStr, BasicBlock *InsertAtEnd) : UnaryInstruction(Ty, VAArg, List, InsertAtEnd) { setName(NameStr); @@ -1226,8 +1537,8 @@ public: const Value *getVectorOperand() const { return Op<0>(); } const Value *getIndexOperand() const { return Op<1>(); } - const VectorType *getVectorOperandType() const { - return reinterpret_cast(getVectorOperand()->getType()); + VectorType *getVectorOperandType() const { + return reinterpret_cast(getVectorOperand()->getType()); } @@ -1286,8 +1597,8 @@ public: /// getType - Overload to return most specific vector type. /// - const VectorType *getType() const { - return reinterpret_cast(Instruction::getType()); + VectorType *getType() const { + return reinterpret_cast(Instruction::getType()); } /// Transparently provide more efficient getOperand methods. @@ -1339,8 +1650,8 @@ public: /// getType - Overload to return most specific vector type. /// - const VectorType *getType() const { - return reinterpret_cast(Instruction::getType()); + VectorType *getType() const { + return reinterpret_cast(Instruction::getType()); } /// Transparently provide more efficient getOperand methods. @@ -1419,7 +1730,7 @@ public: /// with an extractvalue instruction with the specified parameters. /// /// Null is returned if the indices are invalid for the specified type. - static Type *getIndexedType(const Type *Agg, ArrayRef Idxs); + static Type *getIndexedType(Type *Agg, ArrayRef Idxs); typedef const unsigned* idx_iterator; inline idx_iterator idx_begin() const { return Indices.begin(); } @@ -1625,7 +1936,7 @@ class PHINode : public Instruction { void *operator new(size_t s) { return User::operator new(s, 0); } - explicit PHINode(const Type *Ty, unsigned NumReservedValues, + explicit PHINode(Type *Ty, unsigned NumReservedValues, const Twine &NameStr = "", Instruction *InsertBefore = 0) : Instruction(Ty, Instruction::PHI, 0, 0, InsertBefore), ReservedSpace(NumReservedValues) { @@ -1633,7 +1944,7 @@ class PHINode : public Instruction { OperandList = allocHungoffUses(ReservedSpace); } - PHINode(const Type *Ty, unsigned NumReservedValues, const Twine &NameStr, + PHINode(Type *Ty, unsigned NumReservedValues, const Twine &NameStr, BasicBlock *InsertAtEnd) : Instruction(Ty, Instruction::PHI, 0, 0, InsertAtEnd), ReservedSpace(NumReservedValues) { @@ -1650,12 +1961,12 @@ protected: public: /// Constructors - NumReservedValues is a hint for the number of incoming /// edges that this phi node will have (use 0 if you really have no idea). - static PHINode *Create(const Type *Ty, unsigned NumReservedValues, + static PHINode *Create(Type *Ty, unsigned NumReservedValues, const Twine &NameStr = "", Instruction *InsertBefore = 0) { return new PHINode(Ty, NumReservedValues, NameStr, InsertBefore); } - static PHINode *Create(const Type *Ty, unsigned NumReservedValues, + static PHINode *Create(Type *Ty, unsigned NumReservedValues, const Twine &NameStr, BasicBlock *InsertAtEnd) { return new PHINode(Ty, NumReservedValues, NameStr, InsertAtEnd); } @@ -1804,6 +2115,111 @@ struct OperandTraits : public HungoffOperandTraits<2> { DEFINE_TRANSPARENT_OPERAND_ACCESSORS(PHINode, Value) +//===----------------------------------------------------------------------===// +// LandingPadInst Class +//===----------------------------------------------------------------------===// + +//===--------------------------------------------------------------------------- +/// LandingPadInst - The landingpad instruction holds all of the information +/// necessary to generate correct exception handling. The landingpad instruction +/// cannot be moved from the top of a landing pad block, which itself is +/// accessible only from the 'unwind' edge of an invoke. This uses the +/// SubclassData field in Value to store whether or not the landingpad is a +/// cleanup. +/// +class LandingPadInst : public Instruction { + /// ReservedSpace - The number of operands actually allocated. NumOperands is + /// the number actually in use. + unsigned ReservedSpace; + LandingPadInst(const LandingPadInst &LP); +public: + enum ClauseType { Catch, Filter }; +private: + void *operator new(size_t, unsigned); // DO NOT IMPLEMENT + // Allocate space for exactly zero operands. + void *operator new(size_t s) { + return User::operator new(s, 0); + } + void growOperands(unsigned Size); + void init(Value *PersFn, unsigned NumReservedValues, const Twine &NameStr); + + explicit LandingPadInst(Type *RetTy, Value *PersonalityFn, + unsigned NumReservedValues, const Twine &NameStr, + Instruction *InsertBefore); + explicit LandingPadInst(Type *RetTy, Value *PersonalityFn, + unsigned NumReservedValues, const Twine &NameStr, + BasicBlock *InsertAtEnd); +protected: + virtual LandingPadInst *clone_impl() const; +public: + /// Constructors - NumReservedClauses is a hint for the number of incoming + /// clauses that this landingpad will have (use 0 if you really have no idea). + static LandingPadInst *Create(Type *RetTy, Value *PersonalityFn, + unsigned NumReservedClauses, + const Twine &NameStr = "", + Instruction *InsertBefore = 0); + static LandingPadInst *Create(Type *RetTy, Value *PersonalityFn, + unsigned NumReservedClauses, + const Twine &NameStr, BasicBlock *InsertAtEnd); + ~LandingPadInst(); + + /// Provide fast operand accessors + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + /// getPersonalityFn - Get the personality function associated with this + /// landing pad. + Value *getPersonalityFn() const { return getOperand(0); } + + /// isCleanup - Return 'true' if this landingpad instruction is a + /// cleanup. I.e., it should be run when unwinding even if its landing pad + /// doesn't catch the exception. + bool isCleanup() const { return getSubclassDataFromInstruction() & 1; } + + /// setCleanup - Indicate that this landingpad instruction is a cleanup. + void setCleanup(bool V) { + setInstructionSubclassData((getSubclassDataFromInstruction() & ~1) | + (V ? 1 : 0)); + } + + /// addClause - Add a catch or filter clause to the landing pad. + void addClause(Value *ClauseVal); + + /// getClause - Get the value of the clause at index Idx. Use isCatch/isFilter + /// to determine what type of clause this is. + Value *getClause(unsigned Idx) const { return OperandList[Idx + 1]; } + + /// isCatch - Return 'true' if the clause and index Idx is a catch clause. + bool isCatch(unsigned Idx) const { + return !isa(OperandList[Idx + 1]->getType()); + } + + /// isFilter - Return 'true' if the clause and index Idx is a filter clause. + bool isFilter(unsigned Idx) const { + return isa(OperandList[Idx + 1]->getType()); + } + + /// getNumClauses - Get the number of clauses for this landing pad. + unsigned getNumClauses() const { return getNumOperands() - 1; } + + /// reserveClauses - Grow the size of the operand list to accomodate the new + /// number of clauses. + void reserveClauses(unsigned Size) { growOperands(Size); } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const LandingPadInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::LandingPad; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +}; + +template <> +struct OperandTraits : public HungoffOperandTraits<2> { +}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(LandingPadInst, Value) //===----------------------------------------------------------------------===// // ReturnInst Class @@ -1951,6 +2367,13 @@ public: *(&Op<-1>() - idx) = (Value*)NewSucc; } + /// \brief Swap the successors of this branch instruction. + /// + /// Swaps the successors of the branch instruction. This also swaps any + /// branch weight metadata associated with the instruction so that it + /// continues to map correctly to each operand. + void swapSuccessors(); + // Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const BranchInst *) { return true; } static inline bool classof(const Instruction *I) { @@ -2102,6 +2525,13 @@ public: return reinterpret_cast(getOperand(idx*2)); } + // setSuccessorValue - Updates the value associated with the specified + // successor. + void setSuccessorValue(unsigned idx, ConstantInt* SuccessorValue) { + assert(idx < getNumSuccessors() && "Successor # out of range!"); + setOperand(idx*2, reinterpret_cast(SuccessorValue)); + } + // Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const SwitchInst *) { return true; } static inline bool classof(const Instruction *I) { @@ -2393,6 +2823,10 @@ public: Op<-1>() = reinterpret_cast(B); } + /// getLandingPadInst - Get the landingpad instruction from the landing pad + /// block (the unwind destination). + LandingPadInst *getLandingPadInst() const; + BasicBlock *getSuccessor(unsigned i) const { assert(i < 2 && "Successor # out of range for invoke!"); return i == 0 ? getNormalDest() : getUnwindDest(); @@ -2491,6 +2925,57 @@ private: virtual void setSuccessorV(unsigned idx, BasicBlock *B); }; +//===----------------------------------------------------------------------===// +// ResumeInst Class +//===----------------------------------------------------------------------===// + +//===--------------------------------------------------------------------------- +/// ResumeInst - Resume the propagation of an exception. +/// +class ResumeInst : public TerminatorInst { + ResumeInst(const ResumeInst &RI); + + explicit ResumeInst(Value *Exn, Instruction *InsertBefore=0); + ResumeInst(Value *Exn, BasicBlock *InsertAtEnd); +protected: + virtual ResumeInst *clone_impl() const; +public: + static ResumeInst *Create(Value *Exn, Instruction *InsertBefore = 0) { + return new(1) ResumeInst(Exn, InsertBefore); + } + static ResumeInst *Create(Value *Exn, BasicBlock *InsertAtEnd) { + return new(1) ResumeInst(Exn, InsertAtEnd); + } + + /// Provide fast operand accessors + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + /// Convenience accessor. + Value *getValue() const { return Op<0>(); } + + unsigned getNumSuccessors() const { return 0; } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const ResumeInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::Resume; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +private: + virtual BasicBlock *getSuccessorV(unsigned idx) const; + virtual unsigned getNumSuccessorsV() const; + virtual void setSuccessorV(unsigned idx, BasicBlock *B); +}; + +template <> +struct OperandTraits : + public FixedNumOperandTraits { +}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ResumeInst, Value) + //===----------------------------------------------------------------------===// // UnreachableInst Class //===----------------------------------------------------------------------===// @@ -2543,7 +3028,7 @@ public: /// @brief Constructor with insert-before-instruction semantics TruncInst( Value *S, ///< The value to be truncated - const Type *Ty, ///< The (smaller) type to truncate to + Type *Ty, ///< The (smaller) type to truncate to const Twine &NameStr = "", ///< A name for the new instruction Instruction *InsertBefore = 0 ///< Where to insert the new instruction ); @@ -2551,7 +3036,7 @@ public: /// @brief Constructor with insert-at-end-of-block semantics TruncInst( Value *S, ///< The value to be truncated - const Type *Ty, ///< The (smaller) type to truncate to + Type *Ty, ///< The (smaller) type to truncate to const Twine &NameStr, ///< A name for the new instruction BasicBlock *InsertAtEnd ///< The block to insert the instruction into ); @@ -2580,7 +3065,7 @@ public: /// @brief Constructor with insert-before-instruction semantics ZExtInst( Value *S, ///< The value to be zero extended - const Type *Ty, ///< The type to zero extend to + Type *Ty, ///< The type to zero extend to const Twine &NameStr = "", ///< A name for the new instruction Instruction *InsertBefore = 0 ///< Where to insert the new instruction ); @@ -2588,7 +3073,7 @@ public: /// @brief Constructor with insert-at-end semantics. ZExtInst( Value *S, ///< The value to be zero extended - const Type *Ty, ///< The type to zero extend to + Type *Ty, ///< The type to zero extend to const Twine &NameStr, ///< A name for the new instruction BasicBlock *InsertAtEnd ///< The block to insert the instruction into ); @@ -2617,7 +3102,7 @@ public: /// @brief Constructor with insert-before-instruction semantics SExtInst( Value *S, ///< The value to be sign extended - const Type *Ty, ///< The type to sign extend to + Type *Ty, ///< The type to sign extend to const Twine &NameStr = "", ///< A name for the new instruction Instruction *InsertBefore = 0 ///< Where to insert the new instruction ); @@ -2625,7 +3110,7 @@ public: /// @brief Constructor with insert-at-end-of-block semantics SExtInst( Value *S, ///< The value to be sign extended - const Type *Ty, ///< The type to sign extend to + Type *Ty, ///< The type to sign extend to const Twine &NameStr, ///< A name for the new instruction BasicBlock *InsertAtEnd ///< The block to insert the instruction into ); @@ -2654,7 +3139,7 @@ public: /// @brief Constructor with insert-before-instruction semantics FPTruncInst( Value *S, ///< The value to be truncated - const Type *Ty, ///< The type to truncate to + Type *Ty, ///< The type to truncate to const Twine &NameStr = "", ///< A name for the new instruction Instruction *InsertBefore = 0 ///< Where to insert the new instruction ); @@ -2662,7 +3147,7 @@ public: /// @brief Constructor with insert-before-instruction semantics FPTruncInst( Value *S, ///< The value to be truncated - const Type *Ty, ///< The type to truncate to + Type *Ty, ///< The type to truncate to const Twine &NameStr, ///< A name for the new instruction BasicBlock *InsertAtEnd ///< The block to insert the instruction into ); @@ -2691,7 +3176,7 @@ public: /// @brief Constructor with insert-before-instruction semantics FPExtInst( Value *S, ///< The value to be extended - const Type *Ty, ///< The type to extend to + Type *Ty, ///< The type to extend to const Twine &NameStr = "", ///< A name for the new instruction Instruction *InsertBefore = 0 ///< Where to insert the new instruction ); @@ -2699,7 +3184,7 @@ public: /// @brief Constructor with insert-at-end-of-block semantics FPExtInst( Value *S, ///< The value to be extended - const Type *Ty, ///< The type to extend to + Type *Ty, ///< The type to extend to const Twine &NameStr, ///< A name for the new instruction BasicBlock *InsertAtEnd ///< The block to insert the instruction into ); @@ -2728,7 +3213,7 @@ public: /// @brief Constructor with insert-before-instruction semantics UIToFPInst( Value *S, ///< The value to be converted - const Type *Ty, ///< The type to convert to + Type *Ty, ///< The type to convert to const Twine &NameStr = "", ///< A name for the new instruction Instruction *InsertBefore = 0 ///< Where to insert the new instruction ); @@ -2736,7 +3221,7 @@ public: /// @brief Constructor with insert-at-end-of-block semantics UIToFPInst( Value *S, ///< The value to be converted - const Type *Ty, ///< The type to convert to + Type *Ty, ///< The type to convert to const Twine &NameStr, ///< A name for the new instruction BasicBlock *InsertAtEnd ///< The block to insert the instruction into ); @@ -2765,7 +3250,7 @@ public: /// @brief Constructor with insert-before-instruction semantics SIToFPInst( Value *S, ///< The value to be converted - const Type *Ty, ///< The type to convert to + Type *Ty, ///< The type to convert to const Twine &NameStr = "", ///< A name for the new instruction Instruction *InsertBefore = 0 ///< Where to insert the new instruction ); @@ -2773,7 +3258,7 @@ public: /// @brief Constructor with insert-at-end-of-block semantics SIToFPInst( Value *S, ///< The value to be converted - const Type *Ty, ///< The type to convert to + Type *Ty, ///< The type to convert to const Twine &NameStr, ///< A name for the new instruction BasicBlock *InsertAtEnd ///< The block to insert the instruction into ); @@ -2802,7 +3287,7 @@ public: /// @brief Constructor with insert-before-instruction semantics FPToUIInst( Value *S, ///< The value to be converted - const Type *Ty, ///< The type to convert to + Type *Ty, ///< The type to convert to const Twine &NameStr = "", ///< A name for the new instruction Instruction *InsertBefore = 0 ///< Where to insert the new instruction ); @@ -2810,7 +3295,7 @@ public: /// @brief Constructor with insert-at-end-of-block semantics FPToUIInst( Value *S, ///< The value to be converted - const Type *Ty, ///< The type to convert to + Type *Ty, ///< The type to convert to const Twine &NameStr, ///< A name for the new instruction BasicBlock *InsertAtEnd ///< Where to insert the new instruction ); @@ -2839,7 +3324,7 @@ public: /// @brief Constructor with insert-before-instruction semantics FPToSIInst( Value *S, ///< The value to be converted - const Type *Ty, ///< The type to convert to + Type *Ty, ///< The type to convert to const Twine &NameStr = "", ///< A name for the new instruction Instruction *InsertBefore = 0 ///< Where to insert the new instruction ); @@ -2847,7 +3332,7 @@ public: /// @brief Constructor with insert-at-end-of-block semantics FPToSIInst( Value *S, ///< The value to be converted - const Type *Ty, ///< The type to convert to + Type *Ty, ///< The type to convert to const Twine &NameStr, ///< A name for the new instruction BasicBlock *InsertAtEnd ///< The block to insert the instruction into ); @@ -2872,7 +3357,7 @@ public: /// @brief Constructor with insert-before-instruction semantics IntToPtrInst( Value *S, ///< The value to be converted - const Type *Ty, ///< The type to convert to + Type *Ty, ///< The type to convert to const Twine &NameStr = "", ///< A name for the new instruction Instruction *InsertBefore = 0 ///< Where to insert the new instruction ); @@ -2880,7 +3365,7 @@ public: /// @brief Constructor with insert-at-end-of-block semantics IntToPtrInst( Value *S, ///< The value to be converted - const Type *Ty, ///< The type to convert to + Type *Ty, ///< The type to convert to const Twine &NameStr, ///< A name for the new instruction BasicBlock *InsertAtEnd ///< The block to insert the instruction into ); @@ -2912,7 +3397,7 @@ public: /// @brief Constructor with insert-before-instruction semantics PtrToIntInst( Value *S, ///< The value to be converted - const Type *Ty, ///< The type to convert to + Type *Ty, ///< The type to convert to const Twine &NameStr = "", ///< A name for the new instruction Instruction *InsertBefore = 0 ///< Where to insert the new instruction ); @@ -2920,7 +3405,7 @@ public: /// @brief Constructor with insert-at-end-of-block semantics PtrToIntInst( Value *S, ///< The value to be converted - const Type *Ty, ///< The type to convert to + Type *Ty, ///< The type to convert to const Twine &NameStr, ///< A name for the new instruction BasicBlock *InsertAtEnd ///< The block to insert the instruction into ); @@ -2949,7 +3434,7 @@ public: /// @brief Constructor with insert-before-instruction semantics BitCastInst( Value *S, ///< The value to be casted - const Type *Ty, ///< The type to casted to + 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 ); @@ -2957,7 +3442,7 @@ public: /// @brief Constructor with insert-at-end-of-block semantics BitCastInst( Value *S, ///< The value to be casted - const Type *Ty, ///< The type to casted to + 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 ); diff --git a/contrib/llvm/include/llvm/IntrinsicInst.h b/contrib/llvm/include/llvm/IntrinsicInst.h index 24e5fe784..42862011a 100644 --- a/contrib/llvm/include/llvm/IntrinsicInst.h +++ b/contrib/llvm/include/llvm/IntrinsicInst.h @@ -170,7 +170,7 @@ namespace llvm { setArgOperand(4, V); } - const Type *getAlignmentType() const { + Type *getAlignmentType() const { return getArgOperand(3)->getType(); } diff --git a/contrib/llvm/include/llvm/Intrinsics.h b/contrib/llvm/include/llvm/Intrinsics.h index 46361ca0c..370382560 100644 --- a/contrib/llvm/include/llvm/Intrinsics.h +++ b/contrib/llvm/include/llvm/Intrinsics.h @@ -49,7 +49,7 @@ namespace Intrinsic { /// Intrinsic::getType(ID) - Return the function type for an intrinsic. /// - const FunctionType *getType(LLVMContext &Context, ID id, + FunctionType *getType(LLVMContext &Context, ID id, ArrayRef Tys = ArrayRef()); /// Intrinsic::isOverloaded(ID) - Returns true if the intrinsic can be diff --git a/contrib/llvm/include/llvm/Intrinsics.td b/contrib/llvm/include/llvm/Intrinsics.td index 947cf1be7..d70f9153f 100644 --- a/contrib/llvm/include/llvm/Intrinsics.td +++ b/contrib/llvm/include/llvm/Intrinsics.td @@ -309,7 +309,9 @@ def int_eh_selector : Intrinsic<[llvm_i32_ty], [llvm_ptr_ty, llvm_ptr_ty, llvm_vararg_ty]>; def int_eh_resume : Intrinsic<[], [llvm_ptr_ty, llvm_i32_ty], [Throws]>; -def int_eh_typeid_for : Intrinsic<[llvm_i32_ty], [llvm_ptr_ty]>; +// The result of eh.typeid.for depends on the enclosing function, but inside a +// given function it is 'const' and may be CSE'd etc. +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]>; @@ -320,12 +322,13 @@ def int_eh_unwind_init: Intrinsic<[]>, def int_eh_dwarf_cfa : Intrinsic<[llvm_ptr_ty], [llvm_i32_ty]>; let Properties = [IntrNoMem] in { - def int_eh_sjlj_lsda : Intrinsic<[llvm_ptr_ty]>; - def int_eh_sjlj_callsite: Intrinsic<[], [llvm_i32_ty]>; + def int_eh_sjlj_lsda : Intrinsic<[llvm_ptr_ty]>; + def int_eh_sjlj_callsite : Intrinsic<[], [llvm_i32_ty]>; } -def int_eh_sjlj_dispatch_setup : Intrinsic<[], [llvm_i32_ty]>; -def int_eh_sjlj_setjmp : Intrinsic<[llvm_i32_ty], [llvm_ptr_ty]>; -def int_eh_sjlj_longjmp : Intrinsic<[], [llvm_ptr_ty]>; +def int_eh_sjlj_functioncontext : Intrinsic<[], [llvm_ptr_ty]>; +def int_eh_sjlj_dispatch_setup : Intrinsic<[], [llvm_i32_ty]>; +def int_eh_sjlj_setjmp : Intrinsic<[llvm_i32_ty], [llvm_ptr_ty]>; +def int_eh_sjlj_longjmp : Intrinsic<[], [llvm_ptr_ty]>; //===---------------- Generic Variable Attribute Intrinsics----------------===// // @@ -344,10 +347,14 @@ def int_annotation : Intrinsic<[llvm_anyint_ty], //===------------------------ Trampoline Intrinsics -----------------------===// // -def int_init_trampoline : Intrinsic<[llvm_ptr_ty], +def int_init_trampoline : Intrinsic<[], [llvm_ptr_ty, llvm_ptr_ty, llvm_ptr_ty], - [IntrReadWriteArgMem]>, - GCCBuiltin<"__builtin_init_trampoline">; + [IntrReadWriteArgMem, NoCapture<0>]>, + GCCBuiltin<"__builtin_init_trampoline">; + +def int_adjust_trampoline : Intrinsic<[llvm_ptr_ty], [llvm_ptr_ty], + [IntrReadArgMem]>, + GCCBuiltin<"__builtin_adjust_trampoline">; //===------------------------ Overflow Intrinsics -------------------------===// // @@ -374,74 +381,6 @@ def int_umul_with_overflow : Intrinsic<[llvm_anyint_ty, llvm_i1_ty], [LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem]>; -//===------------------------- Atomic Intrinsics --------------------------===// -// -def int_memory_barrier : Intrinsic<[], - [llvm_i1_ty, llvm_i1_ty, - llvm_i1_ty, llvm_i1_ty, llvm_i1_ty], []>, - GCCBuiltin<"__builtin_llvm_memory_barrier">; - -def int_atomic_cmp_swap : Intrinsic<[llvm_anyint_ty], - [LLVMAnyPointerType>, - LLVMMatchType<0>, LLVMMatchType<0>], - [IntrReadWriteArgMem, NoCapture<0>]>, - GCCBuiltin<"__sync_val_compare_and_swap">; -def int_atomic_load_add : Intrinsic<[llvm_anyint_ty], - [LLVMAnyPointerType>, - LLVMMatchType<0>], - [IntrReadWriteArgMem, NoCapture<0>]>, - GCCBuiltin<"__sync_fetch_and_add">; -def int_atomic_swap : Intrinsic<[llvm_anyint_ty], - [LLVMAnyPointerType>, - LLVMMatchType<0>], - [IntrReadWriteArgMem, NoCapture<0>]>, - GCCBuiltin<"__sync_lock_test_and_set">; -def int_atomic_load_sub : Intrinsic<[llvm_anyint_ty], - [LLVMAnyPointerType>, - LLVMMatchType<0>], - [IntrReadWriteArgMem, NoCapture<0>]>, - GCCBuiltin<"__sync_fetch_and_sub">; -def int_atomic_load_and : Intrinsic<[llvm_anyint_ty], - [LLVMAnyPointerType>, - LLVMMatchType<0>], - [IntrReadWriteArgMem, NoCapture<0>]>, - GCCBuiltin<"__sync_fetch_and_and">; -def int_atomic_load_or : Intrinsic<[llvm_anyint_ty], - [LLVMAnyPointerType>, - LLVMMatchType<0>], - [IntrReadWriteArgMem, NoCapture<0>]>, - GCCBuiltin<"__sync_fetch_and_or">; -def int_atomic_load_xor : Intrinsic<[llvm_anyint_ty], - [LLVMAnyPointerType>, - LLVMMatchType<0>], - [IntrReadWriteArgMem, NoCapture<0>]>, - GCCBuiltin<"__sync_fetch_and_xor">; -def int_atomic_load_nand : Intrinsic<[llvm_anyint_ty], - [LLVMAnyPointerType>, - LLVMMatchType<0>], - [IntrReadWriteArgMem, NoCapture<0>]>, - GCCBuiltin<"__sync_fetch_and_nand">; -def int_atomic_load_min : Intrinsic<[llvm_anyint_ty], - [LLVMAnyPointerType>, - LLVMMatchType<0>], - [IntrReadWriteArgMem, NoCapture<0>]>, - GCCBuiltin<"__sync_fetch_and_min">; -def int_atomic_load_max : Intrinsic<[llvm_anyint_ty], - [LLVMAnyPointerType>, - LLVMMatchType<0>], - [IntrReadWriteArgMem, NoCapture<0>]>, - GCCBuiltin<"__sync_fetch_and_max">; -def int_atomic_load_umin : Intrinsic<[llvm_anyint_ty], - [LLVMAnyPointerType>, - LLVMMatchType<0>], - [IntrReadWriteArgMem, NoCapture<0>]>, - GCCBuiltin<"__sync_fetch_and_umin">; -def int_atomic_load_umax : Intrinsic<[llvm_anyint_ty], - [LLVMAnyPointerType>, - LLVMMatchType<0>], - [IntrReadWriteArgMem, NoCapture<0>]>, - GCCBuiltin<"__sync_fetch_and_umax">; - //===------------------------- Memory Use Markers -------------------------===// // def int_lifetime_start : Intrinsic<[], diff --git a/contrib/llvm/include/llvm/IntrinsicsXCore.td b/contrib/llvm/include/llvm/IntrinsicsXCore.td index a062fc4fc..a4813135d 100644 --- a/contrib/llvm/include/llvm/IntrinsicsXCore.td +++ b/contrib/llvm/include/llvm/IntrinsicsXCore.td @@ -1,6 +1,9 @@ //==- IntrinsicsXCore.td - XCore intrinsics -*- tablegen -*-==// -// -// Copyright (C) 2008 XMOS +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // @@ -17,9 +20,15 @@ let TargetPrefix = "xcore" in { // All intrinsics start with "llvm.xcore.". def int_xcore_crc32 : Intrinsic<[llvm_i32_ty], [llvm_i32_ty,llvm_i32_ty,llvm_i32_ty], [IntrNoMem]>; + def int_xcore_sext : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], + [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_geted : Intrinsic<[llvm_i32_ty],[]>; + def int_xcore_getet : Intrinsic<[llvm_i32_ty],[]>; def int_xcore_setsr : Intrinsic<[],[llvm_i32_ty]>; def int_xcore_clrsr : Intrinsic<[],[llvm_i32_ty]>; @@ -40,6 +49,10 @@ let TargetPrefix = "xcore" in { // All intrinsics start with "llvm.xcore.". [NoCapture<0>]>; def int_xcore_chkct : Intrinsic<[],[llvm_anyptr_ty, llvm_i32_ty], [NoCapture<0>]>; + def int_xcore_testct : Intrinsic<[llvm_i32_ty],[llvm_anyptr_ty], + [NoCapture<0>]>; + def int_xcore_testwct : Intrinsic<[llvm_i32_ty],[llvm_anyptr_ty], + [NoCapture<0>]>; def int_xcore_setd : Intrinsic<[],[llvm_anyptr_ty, llvm_i32_ty], [NoCapture<0>]>; def int_xcore_setc : Intrinsic<[],[llvm_anyptr_ty, llvm_i32_ty], @@ -58,6 +71,8 @@ let TargetPrefix = "xcore" in { // All intrinsics start with "llvm.xcore.". [NoCapture<0>]>; def int_xcore_setv : Intrinsic<[],[llvm_anyptr_ty, llvm_ptr_ty], [NoCapture<0>]>; + def int_xcore_setev : Intrinsic<[],[llvm_anyptr_ty, llvm_ptr_ty], + [NoCapture<0>]>; def int_xcore_eeu : Intrinsic<[],[llvm_anyptr_ty], [NoCapture<0>]>; def int_xcore_setclk : Intrinsic<[],[llvm_anyptr_ty, llvm_anyptr_ty], [NoCapture<0>, NoCapture<1>]>; @@ -65,6 +80,10 @@ let TargetPrefix = "xcore" in { // All intrinsics start with "llvm.xcore.". [NoCapture<0>, NoCapture<1>]>; def int_xcore_setpsc : Intrinsic<[],[llvm_anyptr_ty, llvm_i32_ty], [NoCapture<0>]>; + def int_xcore_peek : Intrinsic<[llvm_i32_ty],[llvm_anyptr_ty], + [NoCapture<0>]>; + def int_xcore_endin : Intrinsic<[llvm_i32_ty],[llvm_anyptr_ty], + [NoCapture<0>]>; // Intrinsics for events. def int_xcore_waitevent : Intrinsic<[llvm_ptr_ty],[], [IntrReadMem]>; diff --git a/contrib/llvm/include/llvm/LinkAllPasses.h b/contrib/llvm/include/llvm/LinkAllPasses.h index 8467d1149..f690d045d 100644 --- a/contrib/llvm/include/llvm/LinkAllPasses.h +++ b/contrib/llvm/include/llvm/LinkAllPasses.h @@ -93,7 +93,6 @@ namespace { (void) llvm::createLoopRotatePass(); (void) llvm::createLowerExpectIntrinsicPass(); (void) llvm::createLowerInvokePass(); - (void) llvm::createLowerSetJmpPass(); (void) llvm::createLowerSwitchPass(); (void) llvm::createNoAAPass(); (void) llvm::createNoProfileInfoPass(); @@ -128,7 +127,6 @@ namespace { (void) llvm::createStripDeadDebugInfoPass(); (void) llvm::createStripDeadPrototypesPass(); (void) llvm::createTailCallEliminationPass(); - (void) llvm::createTailDuplicationPass(); (void) llvm::createJumpThreadingPass(); (void) llvm::createUnifyFunctionExitNodesPass(); (void) llvm::createInstCountPass(); @@ -157,7 +155,7 @@ namespace { (void)new llvm::FindUsedTypes(); (void)new llvm::ScalarEvolution(); ((llvm::Function*)0)->viewCFGOnly(); - llvm::RGPassManager RGM(0); + llvm::RGPassManager RGM; ((llvm::RegionPass*)0)->runOnRegion((llvm::Region*)0, RGM); llvm::AliasSetTracker X(*(llvm::AliasAnalysis*)0); X.add((llvm::Value*)0, 0, 0); // for -print-alias-sets diff --git a/contrib/llvm/include/llvm/Linker.h b/contrib/llvm/include/llvm/Linker.h index b402a6090..88908fbd7 100644 --- a/contrib/llvm/include/llvm/Linker.h +++ b/contrib/llvm/include/llvm/Linker.h @@ -57,7 +57,12 @@ class Linker { QuietWarnings = 2, ///< Don't print warnings to stderr. QuietErrors = 4 ///< Don't print errors to stderr. }; - + + enum LinkerMode { + DestroySource = 0, // Allow source module to be destroyed. + PreserveSource = 1 // Preserve the source module. + }; + /// @} /// @name Constructors /// @{ @@ -245,7 +250,7 @@ class Linker { Module* Src, ///< Module linked into \p Dest std::string* ErrorMsg = 0 /// Error/diagnostic string ) { - return LinkModules(Composite, Src, ErrorMsg ); + return LinkModules(Composite, Src, Linker::DestroySource, ErrorMsg ); } /// This is the heart of the linker. This method will take unconditional @@ -259,7 +264,8 @@ class Linker { /// error. /// @returns True if an error occurs, false otherwise. /// @brief Generically link two modules together. - static bool LinkModules(Module* Dest, Module* Src, std::string* ErrorMsg); + static bool LinkModules(Module* Dest, Module* Src, unsigned Mode, + std::string* ErrorMsg); /// This function looks through the Linker's LibPaths to find a library with /// the name \p Filename. If the library cannot be found, the returned path diff --git a/contrib/llvm/include/llvm/MC/EDInstInfo.h b/contrib/llvm/include/llvm/MC/EDInstInfo.h index 83d9e780f..0b9d3f63f 100644 --- a/contrib/llvm/include/llvm/MC/EDInstInfo.h +++ b/contrib/llvm/include/llvm/MC/EDInstInfo.h @@ -21,7 +21,7 @@ struct EDInstInfo { uint8_t numOperands; uint8_t operandTypes[EDIS_MAX_OPERANDS]; uint8_t operandFlags[EDIS_MAX_OPERANDS]; - const char operandOrders[EDIS_MAX_SYNTAXES][EDIS_MAX_OPERANDS]; + const signed char operandOrders[EDIS_MAX_SYNTAXES][EDIS_MAX_OPERANDS]; }; } // namespace llvm diff --git a/contrib/llvm/include/llvm/Target/TargetAsmBackend.h b/contrib/llvm/include/llvm/MC/MCAsmBackend.h similarity index 90% rename from contrib/llvm/include/llvm/Target/TargetAsmBackend.h rename to contrib/llvm/include/llvm/MC/MCAsmBackend.h index 2111f6b7a..4a0cf37a6 100644 --- a/contrib/llvm/include/llvm/Target/TargetAsmBackend.h +++ b/contrib/llvm/include/llvm/MC/MCAsmBackend.h @@ -1,4 +1,4 @@ -//===-- llvm/Target/TargetAsmBackend.h - Target Asm Backend -----*- C++ -*-===// +//===-- llvm/MC/MCAsmBack.h - MC Asm Backend --------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_TARGET_TARGETASMBACKEND_H -#define LLVM_TARGET_TARGETASMBACKEND_H +#ifndef LLVM_MC_MCASMBACKEND_H +#define LLVM_MC_MCASMBACKEND_H #include "llvm/MC/MCDirectives.h" #include "llvm/MC/MCFixup.h" @@ -25,17 +25,17 @@ template class SmallVectorImpl; class raw_ostream; -/// TargetAsmBackend - Generic interface to target specific assembler backends. -class TargetAsmBackend { - TargetAsmBackend(const TargetAsmBackend &); // DO NOT IMPLEMENT - void operator=(const TargetAsmBackend &); // DO NOT IMPLEMENT +/// MCAsmBackend - Generic interface to target specific assembler backends. +class MCAsmBackend { + MCAsmBackend(const MCAsmBackend &); // DO NOT IMPLEMENT + void operator=(const MCAsmBackend &); // DO NOT IMPLEMENT protected: // Can only create subclasses. - TargetAsmBackend(); + MCAsmBackend(); unsigned HasReliableSymbolDifference : 1; public: - virtual ~TargetAsmBackend(); + virtual ~MCAsmBackend(); /// createObjectWriter - Create a new MCObjectWriter instance for use by the /// assembler backend to emit the final object file. diff --git a/contrib/llvm/include/llvm/MC/MCAsmInfo.h b/contrib/llvm/include/llvm/MC/MCAsmInfo.h index 41c171761..c3c296e23 100644 --- a/contrib/llvm/include/llvm/MC/MCAsmInfo.h +++ b/contrib/llvm/include/llvm/MC/MCAsmInfo.h @@ -16,8 +16,10 @@ #ifndef LLVM_TARGET_ASM_INFO_H #define LLVM_TARGET_ASM_INFO_H +#include "llvm/MC/MachineLocation.h" #include "llvm/MC/MCDirectives.h" #include +#include namespace llvm { class MCExpr; @@ -30,6 +32,14 @@ namespace llvm { enum ExceptionsType { None, DwarfCFI, SjLj, ARM, Win64 }; } + namespace LCOMM { + enum LCOMMType { None, NoAlignment, ByteAlignment }; + } + + namespace Structors { + enum OutputOrder { None, PriorityOrder, ReversePriorityOrder }; + } + /// MCAsmInfo - This class is intended to be used as a base class for asm /// properties and features specific to the target. class MCAsmInfo { @@ -62,6 +72,11 @@ namespace llvm { /// the macho-specific .tbss directive for emitting thread local BSS Symbols bool HasMachoTBSSDirective; // Default is false. + /// StructorOutputOrder - Whether the static ctor/dtor list should be output + /// in no particular order, in order of increasing priority or the reverse: + /// in order of decreasing priority (the default). + Structors::OutputOrder StructorOutputOrder; // Default is reverse order. + /// HasStaticCtorDtorReferenceInStaticMode - True if the compiler should /// emit a ".reference .constructors_used" or ".reference .destructors_used" /// directive after the a static ctor/dtor list. This directive is only @@ -115,6 +130,13 @@ namespace llvm { const char *InlineAsmStart; // Defaults to "#APP\n" const char *InlineAsmEnd; // Defaults to "#NO_APP\n" + /// Code16Directive, Code32Directive, Code64Directive - These are assembly + /// directives that tells the assembler to interpret the following + /// instructions differently. + const char *Code16Directive; // Defaults to ".code16" + const char *Code32Directive; // Defaults to ".code32" + const char *Code64Directive; // Defaults to ".code64" + /// AssemblerDialect - Which dialect of an assembler variant to use. unsigned AssemblerDialect; // Defaults to 0 @@ -155,6 +177,18 @@ namespace llvm { const char *Data32bitsDirective; // Defaults to "\t.long\t" const char *Data64bitsDirective; // Defaults to "\t.quad\t" + /// [Data|Code]Begin - These magic labels are used to marked a region as + /// data or code, and are used to provide additional information for + /// correct disassembly on targets that like to mix data and code within + /// a segment. These labels will be implicitly suffixed by the streamer + /// to give them unique names. + const char *DataBegin; // Defaults to "$d." + const char *CodeBegin; // Defaults to "$a." + const char *JT8Begin; // Defaults to "$a." + const char *JT16Begin; // Defaults to "$a." + const char *JT32Begin; // Defaults to "$a." + bool SupportsDataRegions; + /// GPRel32Directive - if non-null, a directive that is used to emit a word /// which should be relocated as a 32-bit GP-relative offset, e.g. .gpword /// on Mips or .gprel32 on Alpha. @@ -220,9 +254,9 @@ namespace llvm { /// .long a - b bool HasAggressiveSymbolFolding; // Defaults to true. - /// HasLCOMMDirective - This is true if the target supports the .lcomm - /// directive. - bool HasLCOMMDirective; // Defaults to false. + /// LCOMMDirectiveType - Describes if the target supports the .lcomm + /// directive and whether it has an alignment parameter. + LCOMM::LCOMMType LCOMMDirectiveType; // Defaults to LCOMM::None. /// COMMDirectiveAlignmentIsInBytes - True is COMMDirective's optional /// alignment is to be specified in bytes instead of log2(n). @@ -304,6 +338,10 @@ namespace llvm { const char *const *AsmTransCBE; // Defaults to empty + //===--- Prologue State ----------------------------------------------===// + + std::vector InitialFrameState; + public: explicit MCAsmInfo(); virtual ~MCAsmInfo(); @@ -345,6 +383,14 @@ namespace llvm { } const char *getGPRel32Directive() const { return GPRel32Directive; } + /// [Code|Data]Begin label name accessors. + const char *getCodeBeginLabelName() const { return CodeBegin; } + const char *getDataBeginLabelName() const { return DataBegin; } + const char *getJumpTable8BeginLabelName() const { return JT8Begin; } + const char *getJumpTable16BeginLabelName() const { return JT16Begin; } + const char *getJumpTable32BeginLabelName() const { return JT32Begin; } + bool getSupportsDataRegions() const { return SupportsDataRegions; } + /// getNonexecutableStackSection - Targets can implement this method to /// specify a section to switch to if the translation unit doesn't have any /// trampolines that require an executable stack. @@ -378,6 +424,9 @@ namespace llvm { // bool hasMachoZeroFillDirective() const { return HasMachoZeroFillDirective; } bool hasMachoTBSSDirective() const { return HasMachoTBSSDirective; } + Structors::OutputOrder getStructorOutputOrder() const { + return StructorOutputOrder; + } bool hasStaticCtorDtorReferenceInStaticMode() const { return HasStaticCtorDtorReferenceInStaticMode; } @@ -417,6 +466,15 @@ namespace llvm { const char *getInlineAsmEnd() const { return InlineAsmEnd; } + const char *getCode16Directive() const { + return Code16Directive; + } + const char *getCode32Directive() const { + return Code32Directive; + } + const char *getCode64Directive() const { + return Code64Directive; + } unsigned getAssemblerDialect() const { return AssemblerDialect; } @@ -457,7 +515,9 @@ namespace llvm { bool hasAggressiveSymbolFolding() const { return HasAggressiveSymbolFolding; } - bool hasLCOMMDirective() const { return HasLCOMMDirective; } + LCOMM::LCOMMType getLCOMMDirectiveType() const { + return LCOMMDirectiveType; + } bool hasDotTypeDotSizeDirective() const {return HasDotTypeDotSizeDirective;} bool getCOMMDirectiveAlignmentIsInBytes() const { return COMMDirectiveAlignmentIsInBytes; @@ -512,6 +572,14 @@ namespace llvm { const char *const *getAsmCBE() const { return AsmTransCBE; } + + void addInitialFrameState(MCSymbol *label, const MachineLocation &D, + const MachineLocation &S) { + InitialFrameState.push_back(MachineMove(label, D, S)); + } + const std::vector &getInitialFrameState() const { + return InitialFrameState; + } }; } diff --git a/contrib/llvm/include/llvm/MC/MCAsmInfoDarwin.h b/contrib/llvm/include/llvm/MC/MCAsmInfoDarwin.h index c85aa3da9..1f6c49938 100644 --- a/contrib/llvm/include/llvm/MC/MCAsmInfoDarwin.h +++ b/contrib/llvm/include/llvm/MC/MCAsmInfoDarwin.h @@ -18,11 +18,6 @@ #include "llvm/MC/MCAsmInfo.h" namespace llvm { - class GlobalValue; - class GlobalVariable; - class Type; - class Mangler; - struct MCAsmInfoDarwin : public MCAsmInfo { explicit MCAsmInfoDarwin(); }; diff --git a/contrib/llvm/include/llvm/MC/MCAssembler.h b/contrib/llvm/include/llvm/MC/MCAssembler.h index fc919669e..b8f8cc4ce 100644 --- a/contrib/llvm/include/llvm/MC/MCAssembler.h +++ b/contrib/llvm/include/llvm/MC/MCAssembler.h @@ -10,14 +10,14 @@ #ifndef LLVM_MC_MCASSEMBLER_H #define LLVM_MC_MCASSEMBLER_H +#include "llvm/MC/MCFixup.h" +#include "llvm/MC/MCInst.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/ilist.h" #include "llvm/ADT/ilist_node.h" #include "llvm/Support/Casting.h" -#include "llvm/MC/MCFixup.h" -#include "llvm/MC/MCInst.h" #include "llvm/Support/DataTypes.h" #include // FIXME: Shouldn't be needed. @@ -36,7 +36,7 @@ class MCSectionData; class MCSymbol; class MCSymbolData; class MCValue; -class TargetAsmBackend; +class MCAsmBackend; class MCFragment : public ilist_node { friend class MCAsmLayout; @@ -660,7 +660,7 @@ private: MCContext &Context; - TargetAsmBackend &Backend; + MCAsmBackend &Backend; MCCodeEmitter &Emitter; @@ -780,14 +780,14 @@ public: // concrete and require clients to pass in a target like object. The other // option is to make this abstract, and have targets provide concrete // implementations as we do with AsmParser. - MCAssembler(MCContext &Context_, TargetAsmBackend &Backend_, + MCAssembler(MCContext &Context_, MCAsmBackend &Backend_, MCCodeEmitter &Emitter_, MCObjectWriter &Writer_, raw_ostream &OS); ~MCAssembler(); MCContext &getContext() const { return Context; } - TargetAsmBackend &getBackend() const { return Backend; } + MCAsmBackend &getBackend() const { return Backend; } MCCodeEmitter &getEmitter() const { return Emitter; } diff --git a/contrib/llvm/include/llvm/MC/MCAtom.h b/contrib/llvm/include/llvm/MC/MCAtom.h new file mode 100644 index 000000000..682cf7cd7 --- /dev/null +++ b/contrib/llvm/include/llvm/MC/MCAtom.h @@ -0,0 +1,68 @@ +//===-- llvm/MC/MCAtom.h - MCAtom 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 MCAtom class, which is used to +// represent a contiguous region in a decoded object that is uniformly data or +// instructions; +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCATOM_H +#define LLVM_MC_MCATOM_H + +#include "llvm/MC/MCInst.h" +#include "llvm/Support/DataTypes.h" +#include + +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; + +/// MCAtom - 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; + MCModule *Parent; + uint64_t Begin, End; + + std::vector > Text; + std::vector Data; + + // 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) { } + +public: + bool isTextAtom() { return Type == TextAtom; } + bool isDataAtom() { return Type == DataAtom; } + + void addInst(const MCInst &I, uint64_t Address, unsigned Size); + 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); + + /// truncate - Truncates an atom so that TruncPt is the last byte address + /// contained in the atom. + void truncate(uint64_t TruncPt); +}; + +} + +#endif + diff --git a/contrib/llvm/include/llvm/MC/MCCodeGenInfo.h b/contrib/llvm/include/llvm/MC/MCCodeGenInfo.h new file mode 100644 index 000000000..1c54c47e2 --- /dev/null +++ b/contrib/llvm/include/llvm/MC/MCCodeGenInfo.h @@ -0,0 +1,41 @@ +//===-- llvm/MC/MCCodeGenInfo.h - Target CodeGen Info -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file tracks information about the target which can affect codegen, +// asm parsing, and asm printing. For example, relocation model. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCCODEGENINFO_H +#define LLVM_MC_MCCODEGENINFO_H + +#include "llvm/Support/CodeGen.h" + +namespace llvm { + + class MCCodeGenInfo { + /// RelocationModel - Relocation model: statcic, pic, etc. + /// + Reloc::Model RelocationModel; + + /// CMModel - Code model. + /// + CodeModel::Model CMModel; + + public: + void InitMCCodeGenInfo(Reloc::Model RM = Reloc::Default, + CodeModel::Model CM = CodeModel::Default); + + Reloc::Model getRelocationModel() const { return RelocationModel; } + + CodeModel::Model getCodeModel() const { return CMModel; } + }; +} // namespace llvm + +#endif diff --git a/contrib/llvm/include/llvm/MC/MCContext.h b/contrib/llvm/include/llvm/MC/MCContext.h index 43a9ce6cf..a49a35c8d 100644 --- a/contrib/llvm/include/llvm/MC/MCContext.h +++ b/contrib/llvm/include/llvm/MC/MCContext.h @@ -26,10 +26,11 @@ namespace llvm { class MCLabel; class MCDwarfFile; class MCDwarfLoc; + class MCObjectFileInfo; + class MCRegisterInfo; class MCLineSection; class StringRef; class Twine; - class TargetAsmInfo; class MCSectionMachO; class MCSectionELF; @@ -46,7 +47,11 @@ namespace llvm { /// The MCAsmInfo for this target. const MCAsmInfo &MAI; - const TargetAsmInfo *TAI; + /// The MCRegisterInfo for this target. + const MCRegisterInfo &MRI; + + /// The MCObjectFileInfo for this target. + const MCObjectFileInfo *MOFI; /// Allocator - Allocator object used for creating machine code objects. /// @@ -110,12 +115,15 @@ namespace llvm { MCSymbol *CreateSymbol(StringRef Name); public: - explicit MCContext(const MCAsmInfo &MAI, const TargetAsmInfo *TAI); + explicit MCContext(const MCAsmInfo &MAI, const MCRegisterInfo &MRI, + const MCObjectFileInfo *MOFI); ~MCContext(); const MCAsmInfo &getAsmInfo() const { return MAI; } - const TargetAsmInfo &getTargetAsmInfo() const { return *TAI; } + const MCRegisterInfo &getRegisterInfo() const { return MRI; } + + const MCObjectFileInfo *getObjectFileInfo() const { return MOFI; } void setAllowTemporaryLabels(bool Value) { AllowTemporaryLabels = Value; } diff --git a/contrib/llvm/include/llvm/MC/MCDirectives.h b/contrib/llvm/include/llvm/MC/MCDirectives.h index 1df55dc25..9180d1b36 100644 --- a/contrib/llvm/include/llvm/MC/MCDirectives.h +++ b/contrib/llvm/include/llvm/MC/MCDirectives.h @@ -47,8 +47,9 @@ enum MCSymbolAttr { enum MCAssemblerFlag { MCAF_SyntaxUnified, ///< .syntax (ARM/ELF) MCAF_SubsectionsViaSymbols, ///< .subsections_via_symbols (MachO) - MCAF_Code16, ///< .code 16 - MCAF_Code32 ///< .code 32 + MCAF_Code16, ///< .code16 (X86) / .code 16 (ARM) + MCAF_Code32, ///< .code32 (X86) / .code 32 (ARM) + MCAF_Code64 ///< .code64 (X86) }; } // end namespace llvm diff --git a/contrib/llvm/include/llvm/MC/MCDisassembler.h b/contrib/llvm/include/llvm/MC/MCDisassembler.h index ce8759a88..454277d68 100644 --- a/contrib/llvm/include/llvm/MC/MCDisassembler.h +++ b/contrib/llvm/include/llvm/MC/MCDisassembler.h @@ -15,6 +15,7 @@ namespace llvm { class MCInst; +class MCSubtargetInfo; class MemoryObject; class raw_ostream; class MCContext; @@ -25,8 +26,38 @@ struct EDInstInfo; /// and provides an array of assembly instructions. class MCDisassembler { public: + /// Ternary decode status. Most backends will just use Fail and + /// Success, however some have a concept of an instruction with + /// understandable semantics but which is architecturally + /// incorrect. An example of this is ARM UNPREDICTABLE instructions + /// which are disassemblable but cause undefined behaviour. + /// + /// Because it makes sense to disassemble these instructions, there + /// is a "soft fail" failure mode that indicates the MCInst& is + /// valid but architecturally incorrect. + /// + /// The enum numbers are deliberately chosen such that reduction + /// from Success->SoftFail ->Fail can be done with a simple + /// bitwise-AND: + /// + /// LEFT & TOP = | Success Unpredictable Fail + /// --------------+----------------------------------- + /// Success | Success Unpredictable Fail + /// Unpredictable | Unpredictable Unpredictable Fail + /// Fail | Fail Fail Fail + /// + /// An easy way of encoding this is as 0b11, 0b01, 0b00 for + /// Success, SoftFail, Fail respectively. + enum DecodeStatus { + Fail = 0, + SoftFail = 1, + Success = 3 + }; + /// Constructor - Performs initial setup for the disassembler. - MCDisassembler() : GetOpInfo(0), DisInfo(0), Ctx(0) {} + MCDisassembler(const MCSubtargetInfo &STI) : GetOpInfo(0), SymbolLookUp(0), + DisInfo(0), Ctx(0), + STI(STI), CommentStream(0) {} virtual ~MCDisassembler(); @@ -41,12 +72,17 @@ public: /// @param address - The address, in the memory space of region, of the first /// byte of the instruction. /// @param vStream - The stream to print warnings and diagnostic messages on. - /// @return - True if the instruction is valid; false otherwise. - virtual bool getInstruction(MCInst& instr, + /// @param cStream - The stream to print comments and annotations on. + /// @return - MCDisassembler::Success if the instruction is valid, + /// MCDisassembler::SoftFail if the instruction was + /// disassemblable but invalid, + /// MCDisassembler::Fail if the instruction was invalid. + virtual DecodeStatus getInstruction(MCInst& instr, uint64_t& size, const MemoryObject ®ion, uint64_t address, - raw_ostream &vStream) const = 0; + raw_ostream &vStream, + raw_ostream &cStream) const = 0; /// getEDInfo - Returns the enhanced instruction information corresponding to /// the disassembler. @@ -62,23 +98,37 @@ private: // // 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; // 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; public: void setupForSymbolicDisassembly(LLVMOpInfoCallback getOpInfo, + LLVMSymbolLookupCallback symbolLookUp, void *disInfo, MCContext *ctx) { GetOpInfo = getOpInfo; + SymbolLookUp = symbolLookUp; DisInfo = disInfo; Ctx = ctx; } LLVMOpInfoCallback getLLVMOpInfoCallback() const { return GetOpInfo; } + LLVMSymbolLookupCallback getLLVMSymbolLookupCallback() const { + return SymbolLookUp; + } void *getDisInfoBlock() const { return DisInfo; } MCContext *getMCContext() const { return Ctx; } + + // 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; }; } // namespace llvm diff --git a/contrib/llvm/include/llvm/MC/MCDwarf.h b/contrib/llvm/include/llvm/MC/MCDwarf.h index 90c372856..431e3c4da 100644 --- a/contrib/llvm/include/llvm/MC/MCDwarf.h +++ b/contrib/llvm/include/llvm/MC/MCDwarf.h @@ -16,15 +16,13 @@ #define LLVM_MC_MCDWARF_H #include "llvm/ADT/StringRef.h" -#include "llvm/CodeGen/MachineLocation.h" // FIXME +#include "llvm/MC/MachineLocation.h" #include "llvm/MC/MCObjectWriter.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Support/Dwarf.h" #include namespace llvm { - class TargetAsmInfo; - class MachineMove; class MCContext; class MCExpr; class MCSection; @@ -265,7 +263,7 @@ namespace llvm { struct MCDwarfFrameInfo { MCDwarfFrameInfo() : Begin(0), End(0), Personality(0), Lsda(0), Function(0), Instructions(), PersonalityEncoding(), - LsdaEncoding(0) {} + LsdaEncoding(0), CompactUnwindEncoding(0) {} MCSymbol *Begin; MCSymbol *End; const MCSymbol *Personality; @@ -274,6 +272,7 @@ namespace llvm { std::vector Instructions; unsigned PersonalityEncoding; unsigned LsdaEncoding; + uint32_t CompactUnwindEncoding; }; class MCDwarfFrameEmitter { diff --git a/contrib/llvm/include/llvm/MC/MCInst.h b/contrib/llvm/include/llvm/MC/MCInst.h index d6ef7b4c3..d38476477 100644 --- a/contrib/llvm/include/llvm/MC/MCInst.h +++ b/contrib/llvm/include/llvm/MC/MCInst.h @@ -144,6 +144,16 @@ public: Operands.push_back(Op); } + void clear() { Operands.clear(); } + size_t size() { return Operands.size(); } + + typedef SmallVector::iterator iterator; + iterator begin() { return Operands.begin(); } + iterator end() { return Operands.end(); } + iterator insert(iterator I, const MCOperand &Op) { + return Operands.insert(I, Op); + } + void print(raw_ostream &OS, const MCAsmInfo *MAI) const; void dump() const; diff --git a/contrib/llvm/include/llvm/MC/MCInstPrinter.h b/contrib/llvm/include/llvm/MC/MCInstPrinter.h index 39002dabc..01ad2d3f8 100644 --- a/contrib/llvm/include/llvm/MC/MCInstPrinter.h +++ b/contrib/llvm/include/llvm/MC/MCInstPrinter.h @@ -28,6 +28,9 @@ protected: /// The current set of available features. unsigned AvailableFeatures; + + /// Utility function for printing annotations. + void printAnnotation(raw_ostream &OS, StringRef Annot); public: MCInstPrinter(const MCAsmInfo &mai) : CommentStream(0), MAI(mai), AvailableFeatures(0) {} @@ -39,7 +42,8 @@ public: /// printInst - Print the specified MCInst to the specified raw_ostream. /// - virtual void printInst(const MCInst *MI, raw_ostream &OS) = 0; + virtual void printInst(const MCInst *MI, raw_ostream &OS, + StringRef Annot) = 0; /// getOpcodeName - Return the name of the specified opcode enum (e.g. /// "MOV32ri") or empty if we can't resolve it. diff --git a/contrib/llvm/include/llvm/MC/MCInstrAnalysis.h b/contrib/llvm/include/llvm/MC/MCInstrAnalysis.h new file mode 100644 index 000000000..8f3c499b1 --- /dev/null +++ b/contrib/llvm/include/llvm/MC/MCInstrAnalysis.h @@ -0,0 +1,61 @@ +//===-- llvm/MC/MCInstrAnalysis.h - InstrDesc target hooks ------*- 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 MCInstrAnalysis class which the MCTargetDescs can +// derive from to give additional information to MC. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCInstrDesc.h" +#include "llvm/MC/MCInstrInfo.h" + +namespace llvm { + +class MCInstrAnalysis { +protected: + friend class Target; + const MCInstrInfo *Info; + +public: + MCInstrAnalysis(const MCInstrInfo *Info) : Info(Info) {} + + virtual ~MCInstrAnalysis() {} + + virtual bool isBranch(const MCInst &Inst) const { + return Info->get(Inst.getOpcode()).isBranch(); + } + + virtual bool isConditionalBranch(const MCInst &Inst) const { + return Info->get(Inst.getOpcode()).isBranch(); + } + + virtual bool isUnconditionalBranch(const MCInst &Inst) const { + return Info->get(Inst.getOpcode()).isUnconditionalBranch(); + } + + virtual bool isIndirectBranch(const MCInst &Inst) const { + return Info->get(Inst.getOpcode()).isIndirectBranch(); + } + + virtual bool isCall(const MCInst &Inst) const { + return Info->get(Inst.getOpcode()).isCall(); + } + + virtual bool isReturn(const MCInst &Inst) const { + return Info->get(Inst.getOpcode()).isReturn(); + } + + /// 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; +}; + +} diff --git a/contrib/llvm/include/llvm/MC/MCInstrDesc.h b/contrib/llvm/include/llvm/MC/MCInstrDesc.h index 49969143c..aafa800c1 100644 --- a/contrib/llvm/include/llvm/MC/MCInstrDesc.h +++ b/contrib/llvm/include/llvm/MC/MCInstrDesc.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// // // This file defines the MCOperandInfo and MCInstrDesc classes, which -// are used to describe target instructions and their operands. +// are used to describe target instructions and their operands. // //===----------------------------------------------------------------------===// @@ -22,14 +22,14 @@ namespace llvm { //===----------------------------------------------------------------------===// // Machine Operand Flags and Description //===----------------------------------------------------------------------===// - + namespace MCOI { // Operand constraints enum OperandConstraint { TIED_TO = 0, // Must be allocated the same register as. EARLY_CLOBBER // Operand is an early clobber register operand }; - + /// OperandFlags - These are flags set on operands, but should be considered /// private, all access should go through the MCOperandInfo accessors. /// See the accessors for a description of what these are. @@ -54,15 +54,15 @@ namespace MCOI { /// class MCOperandInfo { public: - /// RegClass - This specifies the register class enumeration of the operand + /// RegClass - This specifies the register class enumeration of the operand /// if the operand is a register. If isLookupPtrRegClass is set, then this is /// an index that is passed to TargetRegisterInfo::getPointerRegClass(x) to /// get a dynamic register class. short RegClass; - + /// Flags - These are flags from the MCOI::OperandFlags enum. unsigned short Flags; - + /// Lower 16 bits are used to specify which constraints are set. The higher 16 /// bits are used to specify the value of constraints (4 bits each). unsigned Constraints; @@ -70,21 +70,21 @@ public: /// OperandType - Information about the type of the operand. MCOI::OperandType OperandType; /// Currently no other information. - + /// isLookupPtrRegClass - Set if this operand is a pointer value and it /// requires a callback to look up its register class. - bool isLookupPtrRegClass() const { return Flags&(1 < AtomAllocationTracker; + + /// 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; + + friend class MCAtom; + + /// remap - Update the interval mapping for an MCAtom. + void remap(MCAtom *Atom, uint64_t NewBegin, uint64_t NewEnd); + +public: + MCModule(IntervalMap::Allocator &A) : OffsetMap(A) { } + + /// createAtom - Creates a new MCAtom covering the specified offset range. + MCAtom *createAtom(MCAtom::AtomType Type, uint64_t Begin, uint64_t End); +}; + +} + +#endif + diff --git a/contrib/llvm/include/llvm/MC/MCObjectFileInfo.h b/contrib/llvm/include/llvm/MC/MCObjectFileInfo.h new file mode 100644 index 000000000..060d5085d --- /dev/null +++ b/contrib/llvm/include/llvm/MC/MCObjectFileInfo.h @@ -0,0 +1,294 @@ +//===-- llvm/MC/MCObjectFileInfo.h - Object File Info -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file describes common object file formats. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCBJECTFILEINFO_H +#define LLVM_MC_MCBJECTFILEINFO_H + +#include "llvm/MC/MCCodeGenInfo.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/MC/SectionKind.h" + +namespace llvm { +class MCContext; +class MCSection; +class Triple; + +class MCObjectFileInfo { +protected: + /// CommDirectiveSupportsAlignment - True if .comm supports alignment. This + /// is a hack for as long as we support 10.4 Tiger, whose assembler doesn't + /// support alignment on comm. + bool CommDirectiveSupportsAlignment; + + /// SupportsWeakEmptyEHFrame - True if target object file supports a + /// weak_definition of constant 0 for an omitted EH frame. + bool SupportsWeakOmittedEHFrame; + + /// IsFunctionEHFrameSymbolPrivate - This flag is set to true if the + /// "EH_frame" symbol for EH information should be an assembler temporary (aka + /// private linkage, aka an L or .L label) or false if it should be a normal + /// non-.globl label. This defaults to true. + bool IsFunctionEHFrameSymbolPrivate; + + /// PersonalityEncoding, LSDAEncoding, FDEEncoding, TTypeEncoding - Some + /// encoding values for EH. + unsigned PersonalityEncoding; + unsigned LSDAEncoding; + unsigned FDEEncoding; + unsigned FDECFIEncoding; + unsigned TTypeEncoding; + + /// TextSection - Section directive for standard text. + /// + const MCSection *TextSection; + + /// DataSection - Section directive for standard data. + /// + const MCSection *DataSection; + + /// BSSSection - Section that is default initialized to zero. + const MCSection *BSSSection; + + /// ReadOnlySection - Section that is readonly and can contain arbitrary + /// initialized data. Targets are not required to have a readonly section. + /// If they don't, various bits of code will fall back to using the data + /// section for constants. + const MCSection *ReadOnlySection; + + /// StaticCtorSection - This section contains the static constructor pointer + /// list. + const MCSection *StaticCtorSection; + + /// StaticDtorSection - This section contains the static destructor pointer + /// list. + const MCSection *StaticDtorSection; + + /// LSDASection - If exception handling is supported by the target, this is + /// the section the Language Specific Data Area information is emitted to. + const MCSection *LSDASection; + + /// CompactUnwindSection - If exception handling is supported by the target + /// and the target can support a compact representation of the CIE and FDE, + /// this is the section to emit them into. + const MCSection *CompactUnwindSection; + + // Dwarf sections for debug info. If a target supports debug info, these must + // be set. + const MCSection *DwarfAbbrevSection; + const MCSection *DwarfInfoSection; + const MCSection *DwarfLineSection; + const MCSection *DwarfFrameSection; + const MCSection *DwarfPubNamesSection; + const MCSection *DwarfPubTypesSection; + const MCSection *DwarfDebugInlineSection; + const MCSection *DwarfStrSection; + const MCSection *DwarfLocSection; + const MCSection *DwarfARangesSection; + const MCSection *DwarfRangesSection; + const MCSection *DwarfMacroInfoSection; + + // Extra TLS Variable Data section. If the target needs to put additional + // information for a TLS variable, it'll go here. + const MCSection *TLSExtraDataSection; + + /// TLSDataSection - Section directive for Thread Local data. + /// ELF and MachO only. + const MCSection *TLSDataSection; // Defaults to ".tdata". + + /// TLSBSSSection - Section directive for Thread Local uninitialized data. + /// Null if this target doesn't support a BSS section. + /// ELF and MachO only. + const MCSection *TLSBSSSection; // Defaults to ".tbss". + + + /// EHFrameSection - EH frame section. It is initialized on demand so it + /// can be overwritten (with uniquing). + const MCSection *EHFrameSection; + + /// ELF specific sections. + /// + const MCSection *DataRelSection; + const MCSection *DataRelLocalSection; + const MCSection *DataRelROSection; + const MCSection *DataRelROLocalSection; + const MCSection *MergeableConst4Section; + const MCSection *MergeableConst8Section; + const MCSection *MergeableConst16Section; + + /// MachO specific sections. + /// + + /// TLSTLVSection - Section for thread local structure information. + /// Contains the source code name of the variable, visibility and a pointer + /// to the initial value (.tdata or .tbss). + const MCSection *TLSTLVSection; // Defaults to ".tlv". + + /// TLSThreadInitSection - Section for thread local data initialization + /// functions. + const MCSection *TLSThreadInitSection; // Defaults to ".thread_init_func". + + const MCSection *CStringSection; + const MCSection *UStringSection; + const MCSection *TextCoalSection; + const MCSection *ConstTextCoalSection; + const MCSection *ConstDataSection; + const MCSection *DataCoalSection; + const MCSection *DataCommonSection; + const MCSection *DataBSSSection; + const MCSection *FourByteConstantSection; + const MCSection *EightByteConstantSection; + const MCSection *SixteenByteConstantSection; + const MCSection *LazySymbolPointerSection; + const MCSection *NonLazySymbolPointerSection; + + /// COFF specific sections. + /// + const MCSection *DrectveSection; + const MCSection *PDataSection; + const MCSection *XDataSection; + +public: + void InitMCObjectFileInfo(StringRef TT, Reloc::Model RM, CodeModel::Model CM, + MCContext &ctx); + + bool isFunctionEHFrameSymbolPrivate() const { + return IsFunctionEHFrameSymbolPrivate; + } + bool getSupportsWeakOmittedEHFrame() const { + return SupportsWeakOmittedEHFrame; + } + bool getCommDirectiveSupportsAlignment() const { + return CommDirectiveSupportsAlignment; + } + + unsigned getPersonalityEncoding() const { return PersonalityEncoding; } + unsigned getLSDAEncoding() const { return LSDAEncoding; } + unsigned getFDEEncoding(bool CFI) const { + return CFI ? FDECFIEncoding : FDEEncoding; + } + unsigned getTTypeEncoding() const { return TTypeEncoding; } + + const MCSection *getTextSection() const { return TextSection; } + const MCSection *getDataSection() const { return DataSection; } + const MCSection *getBSSSection() const { return BSSSection; } + const MCSection *getStaticCtorSection() const { return StaticCtorSection; } + const MCSection *getStaticDtorSection() const { return StaticDtorSection; } + const MCSection *getLSDASection() const { return LSDASection; } + const MCSection *getCompactUnwindSection() const{ + return CompactUnwindSection; + } + const MCSection *getDwarfAbbrevSection() const { return DwarfAbbrevSection; } + const MCSection *getDwarfInfoSection() const { return DwarfInfoSection; } + const MCSection *getDwarfLineSection() const { return DwarfLineSection; } + const MCSection *getDwarfFrameSection() const { return DwarfFrameSection; } + const MCSection *getDwarfPubNamesSection() const{return DwarfPubNamesSection;} + const MCSection *getDwarfPubTypesSection() const{return DwarfPubTypesSection;} + const MCSection *getDwarfDebugInlineSection() const { + return DwarfDebugInlineSection; + } + const MCSection *getDwarfStrSection() const { return DwarfStrSection; } + const MCSection *getDwarfLocSection() const { return DwarfLocSection; } + const MCSection *getDwarfARangesSection() const { return DwarfARangesSection;} + const MCSection *getDwarfRangesSection() const { return DwarfRangesSection; } + const MCSection *getDwarfMacroInfoSection() const { + return DwarfMacroInfoSection; + } + const MCSection *getTLSExtraDataSection() const { + return TLSExtraDataSection; + } + const MCSection *getTLSDataSection() const { return TLSDataSection; } + const MCSection *getTLSBSSSection() const { return TLSBSSSection; } + + /// ELF specific sections. + /// + const MCSection *getDataRelSection() const { return DataRelSection; } + const MCSection *getDataRelLocalSection() const { + return DataRelLocalSection; + } + const MCSection *getDataRelROSection() const { return DataRelROSection; } + const MCSection *getDataRelROLocalSection() const { + return DataRelROLocalSection; + } + const MCSection *getMergeableConst4Section() const { + return MergeableConst4Section; + } + const MCSection *getMergeableConst8Section() const { + return MergeableConst8Section; + } + const MCSection *getMergeableConst16Section() const { + return MergeableConst16Section; + } + + /// MachO specific sections. + /// + const MCSection *getTLSTLVSection() const { return TLSTLVSection; } + const MCSection *getTLSThreadInitSection() const { + return TLSThreadInitSection; + } + const MCSection *getCStringSection() const { return CStringSection; } + const MCSection *getUStringSection() const { return UStringSection; } + const MCSection *getTextCoalSection() const { return TextCoalSection; } + const MCSection *getConstTextCoalSection() const { + return ConstTextCoalSection; + } + const MCSection *getConstDataSection() const { return ConstDataSection; } + const MCSection *getDataCoalSection() const { return DataCoalSection; } + const MCSection *getDataCommonSection() const { return DataCommonSection; } + const MCSection *getDataBSSSection() const { return DataBSSSection; } + const MCSection *getFourByteConstantSection() const { + return FourByteConstantSection; + } + const MCSection *getEightByteConstantSection() const { + return EightByteConstantSection; + } + const MCSection *getSixteenByteConstantSection() const { + return SixteenByteConstantSection; + } + const MCSection *getLazySymbolPointerSection() const { + return LazySymbolPointerSection; + } + const MCSection *getNonLazySymbolPointerSection() const { + return NonLazySymbolPointerSection; + } + + /// COFF specific sections. + /// + const MCSection *getDrectveSection() const { return DrectveSection; } + const MCSection *getPDataSection() const { return PDataSection; } + const MCSection *getXDataSection() const { return XDataSection; } + + const MCSection *getEHFrameSection() { + if (!EHFrameSection) + InitEHFrameSection(); + return EHFrameSection; + } + +private: + enum Environment { IsMachO, IsELF, IsCOFF }; + Environment Env; + Reloc::Model RelocM; + CodeModel::Model CMModel; + MCContext *Ctx; + + void InitMachOMCObjectFileInfo(Triple T); + void InitELFMCObjectFileInfo(Triple T); + void InitCOFFMCObjectFileInfo(Triple T); + + /// InitEHFrameSection - Initialize EHFrameSection on demand. + /// + void InitEHFrameSection(); +}; + +} // end namespace llvm + +#endif diff --git a/contrib/llvm/include/llvm/MC/MCObjectStreamer.h b/contrib/llvm/include/llvm/MC/MCObjectStreamer.h index a89933b23..f897e64f4 100644 --- a/contrib/llvm/include/llvm/MC/MCObjectStreamer.h +++ b/contrib/llvm/include/llvm/MC/MCObjectStreamer.h @@ -19,7 +19,7 @@ class MCSectionData; class MCExpr; class MCFragment; class MCDataFragment; -class TargetAsmBackend; +class MCAsmBackend; class raw_ostream; /// \brief Streaming object file generation interface. @@ -36,9 +36,9 @@ class MCObjectStreamer : public MCStreamer { virtual void EmitInstToData(const MCInst &Inst) = 0; protected: - MCObjectStreamer(MCContext &Context, TargetAsmBackend &TAB, + MCObjectStreamer(MCContext &Context, MCAsmBackend &TAB, raw_ostream &_OS, MCCodeEmitter *_Emitter); - MCObjectStreamer(MCContext &Context, TargetAsmBackend &TAB, + MCObjectStreamer(MCContext &Context, MCAsmBackend &TAB, raw_ostream &_OS, MCCodeEmitter *_Emitter, MCAssembler *_Assembler); ~MCObjectStreamer(); diff --git a/contrib/llvm/include/llvm/MC/MCParser/AsmLexer.h b/contrib/llvm/include/llvm/MC/MCParser/AsmLexer.h index ab78799fd..dcecfb6aa 100644 --- a/contrib/llvm/include/llvm/MC/MCParser/AsmLexer.h +++ b/contrib/llvm/include/llvm/MC/MCParser/AsmLexer.h @@ -32,6 +32,7 @@ class AsmLexer : public MCAsmLexer { const char *CurPtr; const MemoryBuffer *CurBuf; + bool isAtStartOfLine; void operator=(const AsmLexer&); // DO NOT IMPLEMENT AsmLexer(const AsmLexer&); // DO NOT IMPLEMENT @@ -47,6 +48,7 @@ public: void setBuffer(const MemoryBuffer *buf, const char *ptr = NULL); virtual StringRef LexUntilEndOfStatement(); + StringRef LexUntilEndOfLine(); bool isAtStartOfComment(char Char); bool isAtStatementSeparator(const char *Ptr); diff --git a/contrib/llvm/include/llvm/MC/MCParser/MCAsmLexer.h b/contrib/llvm/include/llvm/MC/MCParser/MCAsmLexer.h index 47c580f85..9bbb75581 100644 --- a/contrib/llvm/include/llvm/MC/MCParser/MCAsmLexer.h +++ b/contrib/llvm/include/llvm/MC/MCParser/MCAsmLexer.h @@ -17,7 +17,6 @@ namespace llvm { class MCAsmLexer; class MCInst; -class Target; /// AsmToken - Target independent representation for an assembler token. class AsmToken { @@ -36,7 +35,7 @@ public: // Real values. Real, - // Register values (stored in IntVal). Only used by TargetAsmLexer. + // Register values (stored in IntVal). Only used by MCTargetAsmLexer. Register, // No-value. diff --git a/contrib/llvm/include/llvm/MC/MCParser/MCAsmParser.h b/contrib/llvm/include/llvm/MC/MCParser/MCAsmParser.h index 73766930d..6ff175349 100644 --- a/contrib/llvm/include/llvm/MC/MCParser/MCAsmParser.h +++ b/contrib/llvm/include/llvm/MC/MCParser/MCAsmParser.h @@ -20,11 +20,10 @@ class MCAsmParserExtension; class MCContext; class MCExpr; class MCStreamer; +class MCTargetAsmParser; class SMLoc; class SourceMgr; class StringRef; -class Target; -class TargetAsmParser; class Twine; /// MCAsmParser - Generic assembler parser interface, for use by target specific @@ -37,7 +36,7 @@ private: MCAsmParser(const MCAsmParser &); // DO NOT IMPLEMENT void operator=(const MCAsmParser &); // DO NOT IMPLEMENT - TargetAsmParser *TargetParser; + MCTargetAsmParser *TargetParser; unsigned ShowParsedOperands : 1; @@ -60,8 +59,8 @@ public: /// getStreamer - Return the output streamer for the assembler. virtual MCStreamer &getStreamer() = 0; - TargetAsmParser &getTargetParser() const { return *TargetParser; } - void setTargetParser(TargetAsmParser &P); + MCTargetAsmParser &getTargetParser() const { return *TargetParser; } + void setTargetParser(MCTargetAsmParser &P); bool getShowParsedOperands() const { return ShowParsedOperands; } void setShowParsedOperands(bool Value) { ShowParsedOperands = Value; } @@ -131,7 +130,7 @@ public: }; /// \brief Create an MCAsmParser instance. -MCAsmParser *createMCAsmParser(const Target &, SourceMgr &, MCContext &, +MCAsmParser *createMCAsmParser(SourceMgr &, MCContext &, MCStreamer &, const MCAsmInfo &); } // End llvm namespace diff --git a/contrib/llvm/include/llvm/MC/MCRegisterInfo.h b/contrib/llvm/include/llvm/MC/MCRegisterInfo.h index caf98bb89..ada5ae80a 100644 --- a/contrib/llvm/include/llvm/MC/MCRegisterInfo.h +++ b/contrib/llvm/include/llvm/MC/MCRegisterInfo.h @@ -16,10 +16,94 @@ #ifndef LLVM_MC_MCREGISTERINFO_H #define LLVM_MC_MCREGISTERINFO_H +#include "llvm/ADT/DenseMap.h" #include namespace llvm { +/// MCRegisterClass - Base class of TargetRegisterClass. +class MCRegisterClass { +public: + typedef const unsigned* iterator; + typedef const unsigned* const_iterator; +private: + unsigned ID; + const char *Name; + const unsigned RegSize, Alignment; // Size & Alignment of register in bytes + const int CopyCost; + const bool Allocatable; + const iterator RegsBegin, RegsEnd; + const unsigned char *const RegSet; + const unsigned RegSetSize; +public: + MCRegisterClass(unsigned id, const char *name, + unsigned RS, unsigned Al, int CC, bool Allocable, + iterator RB, iterator RE, const unsigned char *Bits, + unsigned NumBytes) + : ID(id), Name(name), RegSize(RS), Alignment(Al), CopyCost(CC), + Allocatable(Allocable), RegsBegin(RB), RegsEnd(RE), RegSet(Bits), + RegSetSize(NumBytes) { + for (iterator i = RegsBegin; i != RegsEnd; ++i) + assert(contains(*i) && "Bit field corrupted."); + } + + /// getID() - Return the register class ID number. + /// + unsigned getID() const { return ID; } + + /// getName() - Return the register class name for debugging. + /// + const char *getName() const { return Name; } + + /// begin/end - Return all of the registers in this class. + /// + iterator begin() const { return RegsBegin; } + iterator end() const { return RegsEnd; } + + /// getNumRegs - Return the number of registers in this class. + /// + unsigned getNumRegs() const { return (unsigned)(RegsEnd-RegsBegin); } + + /// getRegister - Return the specified register in the class. + /// + unsigned getRegister(unsigned i) const { + assert(i < getNumRegs() && "Register number out of range!"); + return RegsBegin[i]; + } + + /// contains - Return true if the specified register is included in this + /// register class. This does not include virtual registers. + bool contains(unsigned Reg) const { + unsigned InByte = Reg % 8; + unsigned Byte = Reg / 8; + if (Byte >= RegSetSize) + return false; + return (RegSet[Byte] & (1 << InByte)) != 0; + } + + /// contains - Return true if both registers are in this class. + bool contains(unsigned Reg1, unsigned Reg2) const { + return contains(Reg1) && contains(Reg2); + } + + /// getSize - Return the size of the register in bytes, which is also the size + /// of a stack slot allocated to hold a spilled copy of this register. + unsigned getSize() const { return RegSize; } + + /// getAlignment - Return the minimum required alignment for a register of + /// this class. + unsigned getAlignment() const { return Alignment; } + + /// getCopyCost - Return the cost of copying a value between two registers in + /// this class. A negative number means the register class is very expensive + /// to copy e.g. status flag register classes. + int getCopyCost() const { return CopyCost; } + + /// isAllocatable - Return true if this register class may be used to create + /// virtual registers. + 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 @@ -50,18 +134,67 @@ struct MCRegisterDesc { /// virtual methods. /// class MCRegisterInfo { +public: + typedef const MCRegisterClass *regclass_iterator; private: - const MCRegisterDesc *Desc; // Pointer to the descriptor array - unsigned NumRegs; // Number of entries in the array + const MCRegisterDesc *Desc; // Pointer to the descriptor array + unsigned NumRegs; // Number of entries in the array + unsigned RAReg; // Return address register + const MCRegisterClass *Classes; // Pointer to the regclass array + unsigned NumClasses; // Number of entries in the array + DenseMap L2DwarfRegs; // LLVM to Dwarf regs mapping + DenseMap EHL2DwarfRegs; // LLVM to Dwarf regs mapping EH + DenseMap Dwarf2LRegs; // Dwarf to LLVM regs mapping + DenseMap EHDwarf2LRegs; // Dwarf to LLVM regs mapping EH + DenseMap L2SEHRegs; // LLVM to SEH regs mapping public: /// InitMCRegisterInfo - Initialize MCRegisterInfo, called by TableGen /// auto-generated routines. *DO NOT USE*. - void InitMCRegisterInfo(const MCRegisterDesc *D, unsigned NR) { + void InitMCRegisterInfo(const MCRegisterDesc *D, unsigned NR, unsigned RA, + const MCRegisterClass *C, unsigned NC) { Desc = D; NumRegs = NR; + RAReg = RA; + Classes = C; + NumClasses = NC; + } + + /// mapLLVMRegToDwarfReg - Used to initialize LLVM register to Dwarf + /// register number mapping. Called by TableGen auto-generated routines. + /// *DO NOT USE*. + void mapLLVMRegToDwarfReg(unsigned LLVMReg, int DwarfReg, bool isEH) { + if (isEH) + EHL2DwarfRegs[LLVMReg] = DwarfReg; + else + L2DwarfRegs[LLVMReg] = DwarfReg; } + /// mapDwarfRegToLLVMReg - Used to initialize Dwarf register to LLVM + /// register number mapping. Called by TableGen auto-generated routines. + /// *DO NOT USE*. + void mapDwarfRegToLLVMReg(unsigned DwarfReg, unsigned LLVMReg, bool isEH) { + if (isEH) + EHDwarf2LRegs[DwarfReg] = LLVMReg; + else + Dwarf2LRegs[DwarfReg] = LLVMReg; + } + + /// mapLLVMRegToSEHReg - Used to initialize LLVM register to SEH register + /// number mapping. By default the SEH register number is just the same + /// as the LLVM register number. + /// FIXME: TableGen these numbers. Currently this requires target specific + /// initialization code. + void mapLLVMRegToSEHReg(unsigned LLVMReg, int SEHReg) { + L2SEHRegs[LLVMReg] = SEHReg; + } + + /// getRARegister - This method should return the register where the return + /// address can be found. + unsigned getRARegister() const { + return RAReg; + } + const MCRegisterDesc &operator[](unsigned RegNo) const { assert(RegNo < NumRegs && "Attempting to access record for invalid register number!"); @@ -122,6 +255,51 @@ public: unsigned getNumRegs() const { return NumRegs; } + + /// getDwarfRegNum - Map a target register to an equivalent dwarf register + /// number. Returns -1 if there is no equivalent value. The second + /// parameter allows targets to use different numberings for EH info and + /// debugging info. + int getDwarfRegNum(unsigned RegNum, bool isEH) const { + const DenseMap &M = isEH ? EHL2DwarfRegs : L2DwarfRegs; + const DenseMap::const_iterator I = M.find(RegNum); + if (I == M.end()) return -1; + return I->second; + } + + /// getLLVMRegNum - Map a dwarf register back to a target register. + /// + int getLLVMRegNum(unsigned RegNum, bool isEH) const { + const DenseMap &M = isEH ? EHDwarf2LRegs : Dwarf2LRegs; + const DenseMap::const_iterator I = M.find(RegNum); + if (I == M.end()) { + assert(0 && "Invalid RegNum"); + return -1; + } + return I->second; + } + + /// getSEHRegNum - Map a target register to an equivalent SEH register + /// number. Returns LLVM register number if there is no equivalent value. + int getSEHRegNum(unsigned RegNum) const { + const DenseMap::const_iterator I = L2SEHRegs.find(RegNum); + if (I == L2SEHRegs.end()) return (int)RegNum; + return I->second; + } + + regclass_iterator regclass_begin() const { return Classes; } + regclass_iterator regclass_end() const { return Classes+NumClasses; } + + unsigned getNumRegClasses() const { + return (unsigned)(regclass_end()-regclass_begin()); + } + + /// getRegClass - Returns the register class associated with the enumeration + /// value. See class MCOperandInfo. + const MCRegisterClass getRegClass(unsigned i) const { + assert(i < getNumRegClasses() && "Register Class ID out of range"); + return Classes[i]; + } }; } // End llvm namespace diff --git a/contrib/llvm/include/llvm/MC/MCStreamer.h b/contrib/llvm/include/llvm/MC/MCStreamer.h index 7bdba5fa5..451efbff6 100644 --- a/contrib/llvm/include/llvm/MC/MCStreamer.h +++ b/contrib/llvm/include/llvm/MC/MCStreamer.h @@ -14,13 +14,15 @@ #ifndef LLVM_MC_MCSTREAMER_H #define LLVM_MC_MCSTREAMER_H -#include "llvm/ADT/SmallVector.h" #include "llvm/Support/DataTypes.h" #include "llvm/MC/MCDirectives.h" #include "llvm/MC/MCDwarf.h" #include "llvm/MC/MCWin64EH.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/SmallVector.h" namespace llvm { + class MCAsmBackend; class MCAsmInfo; class MCCodeEmitter; class MCContext; @@ -30,7 +32,6 @@ namespace llvm { class MCSection; class MCSymbol; class StringRef; - class TargetAsmBackend; class TargetLoweringObjectFile; class Twine; class raw_ostream; @@ -63,14 +64,29 @@ namespace llvm { void setCurrentW64UnwindInfo(MCWin64EHUnwindInfo *Frame); void EnsureValidW64UnwindInfo(); - const MCSymbol* LastNonPrivate; + MCSymbol* LastSymbol; /// SectionStack - This is stack of current and previous section /// values saved by PushSection. SmallVector, 4> SectionStack; + unsigned UniqueCodeBeginSuffix; + unsigned UniqueDataBeginSuffix; + protected: + /// Indicator of whether the previous data-or-code indicator was for + /// code or not. Used to determine when we need to emit a new indicator. + enum DataType { + Data, + Code, + JumpTable8, + JumpTable16, + JumpTable32 + }; + DataType RegionIndicator; + + MCStreamer(MCContext &Ctx); const MCExpr *BuildSymbolDiff(MCContext &Context, const MCSymbol *A, @@ -96,6 +112,10 @@ namespace llvm { return FrameInfos[i]; } + ArrayRef getFrameInfos() { + return FrameInfos; + } + unsigned getNumW64UnwindInfos() { return W64UnwindInfos.size(); } @@ -219,6 +239,41 @@ namespace llvm { /// used in an assignment. virtual void EmitLabel(MCSymbol *Symbol); + /// EmitDataRegion - Emit a label that marks the beginning of a data + /// region. + /// On ELF targets, this corresponds to an assembler statement such as: + /// $d.1: + virtual void EmitDataRegion(); + + /// EmitJumpTable8Region - Emit a label that marks the beginning of a + /// jump table composed of 8-bit offsets. + /// On ELF targets, this corresponds to an assembler statement such as: + /// $d.1: + virtual void EmitJumpTable8Region(); + + /// EmitJumpTable16Region - Emit a label that marks the beginning of a + /// jump table composed of 16-bit offsets. + /// On ELF targets, this corresponds to an assembler statement such as: + /// $d.1: + virtual void EmitJumpTable16Region(); + + /// EmitJumpTable32Region - Emit a label that marks the beginning of a + /// jump table composed of 32-bit offsets. + /// On ELF targets, this corresponds to an assembler statement such as: + /// $d.1: + virtual void EmitJumpTable32Region(); + + /// EmitCodeRegion - Emit a label that marks the beginning of a code + /// region. + /// On ELF targets, this corresponds to an assembler statement such as: + /// $a.1: + virtual void EmitCodeRegion(); + + /// ForceCodeRegion - Forcibly sets the current region mode to code. Used + /// at function entry points. + void ForceCodeRegion() { RegionIndicator = Code; } + + virtual void EmitEHSymAttributes(const MCSymbol *Symbol, MCSymbol *EHSymbol); @@ -299,7 +354,9 @@ namespace llvm { /// /// @param Symbol - The common symbol to emit. /// @param Size - The size of the common symbol. - virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size) = 0; + /// @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. /// @@ -470,6 +527,7 @@ namespace llvm { void EmitDwarfSetLineAddr(int64_t LineDelta, const MCSymbol *Label, int PointerSize); + virtual void EmitCompactUnwindEncoding(uint32_t CompactUnwindEncoding); virtual void EmitCFISections(bool EH, bool Debug); virtual void EmitCFIStartProc(); virtual void EmitCFIEndProc(); @@ -557,14 +615,14 @@ namespace llvm { bool useCFI, MCInstPrinter *InstPrint = 0, MCCodeEmitter *CE = 0, - TargetAsmBackend *TAB = 0, + MCAsmBackend *TAB = 0, bool ShowInst = false); /// createMachOStreamer - Create a machine code streamer which will generate /// Mach-O format object files. /// /// Takes ownership of \arg TAB and \arg CE. - MCStreamer *createMachOStreamer(MCContext &Ctx, TargetAsmBackend &TAB, + MCStreamer *createMachOStreamer(MCContext &Ctx, MCAsmBackend &TAB, raw_ostream &OS, MCCodeEmitter *CE, bool RelaxAll = false); @@ -573,13 +631,13 @@ namespace llvm { /// /// Takes ownership of \arg TAB and \arg CE. MCStreamer *createWinCOFFStreamer(MCContext &Ctx, - TargetAsmBackend &TAB, + 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, TargetAsmBackend &TAB, + MCStreamer *createELFStreamer(MCContext &Ctx, MCAsmBackend &TAB, raw_ostream &OS, MCCodeEmitter *CE, bool RelaxAll, bool NoExecStack); @@ -593,7 +651,7 @@ namespace llvm { /// "pure" MC object files, for use with MC-JIT and testing tools. /// /// Takes ownership of \arg TAB and \arg CE. - MCStreamer *createPureStreamer(MCContext &Ctx, TargetAsmBackend &TAB, + MCStreamer *createPureStreamer(MCContext &Ctx, MCAsmBackend &TAB, raw_ostream &OS, MCCodeEmitter *CE); } // end namespace llvm diff --git a/contrib/llvm/include/llvm/Target/TargetAsmLexer.h b/contrib/llvm/include/llvm/MC/MCTargetAsmLexer.h similarity index 81% rename from contrib/llvm/include/llvm/Target/TargetAsmLexer.h rename to contrib/llvm/include/llvm/MC/MCTargetAsmLexer.h index 9fcf449a8..acb3d4d61 100644 --- a/contrib/llvm/include/llvm/Target/TargetAsmLexer.h +++ b/contrib/llvm/include/llvm/MC/MCTargetAsmLexer.h @@ -1,4 +1,4 @@ -//===-- llvm/Target/TargetAsmLexer.h - Target Assembly Lexer ----*- C++ -*-===// +//===-- llvm/MC/MCTargetAsmLexer.h - Target Assembly Lexer ------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -7,16 +7,16 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_TARGET_TARGETASMLEXER_H -#define LLVM_TARGET_TARGETASMLEXER_H +#ifndef LLVM_MC_MCTARGETASMLEXER_H +#define LLVM_MC_MCTARGETASMLEXER_H #include "llvm/MC/MCParser/MCAsmLexer.h" namespace llvm { class Target; -/// TargetAsmLexer - Generic interface to target specific assembly lexers. -class TargetAsmLexer { +/// MCTargetAsmLexer - Generic interface to target specific assembly lexers. +class MCTargetAsmLexer { /// The current token AsmToken CurTok; @@ -24,10 +24,10 @@ class TargetAsmLexer { SMLoc ErrLoc; std::string Err; - TargetAsmLexer(const TargetAsmLexer &); // DO NOT IMPLEMENT - void operator=(const TargetAsmLexer &); // DO NOT IMPLEMENT + MCTargetAsmLexer(const MCTargetAsmLexer &); // DO NOT IMPLEMENT + void operator=(const MCTargetAsmLexer &); // DO NOT IMPLEMENT protected: // Can only create subclasses. - TargetAsmLexer(const Target &); + MCTargetAsmLexer(const Target &); virtual AsmToken LexToken() = 0; @@ -41,7 +41,7 @@ protected: // Can only create subclasses. MCAsmLexer *Lexer; public: - virtual ~TargetAsmLexer(); + virtual ~MCTargetAsmLexer(); const Target &getTarget() const { return TheTarget; } diff --git a/contrib/llvm/include/llvm/Target/TargetAsmParser.h b/contrib/llvm/include/llvm/MC/MCTargetAsmParser.h similarity index 75% rename from contrib/llvm/include/llvm/Target/TargetAsmParser.h rename to contrib/llvm/include/llvm/MC/MCTargetAsmParser.h index df84231ee..4e3fd0d3a 100644 --- a/contrib/llvm/include/llvm/Target/TargetAsmParser.h +++ b/contrib/llvm/include/llvm/MC/MCTargetAsmParser.h @@ -1,4 +1,4 @@ -//===-- llvm/Target/TargetAsmParser.h - Target Assembly Parser --*- C++ -*-===// +//===-- llvm/MC/MCTargetAsmParser.h - Target Assembly Parser ----*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_TARGET_TARGETPARSER_H -#define LLVM_TARGET_TARGETPARSER_H +#ifndef LLVM_MC_TARGETPARSER_H +#define LLVM_MC_TARGETPARSER_H #include "llvm/MC/MCParser/MCAsmParserExtension.h" @@ -18,20 +18,32 @@ class StringRef; class SMLoc; class AsmToken; class MCParsedAsmOperand; +class MCInst; template class SmallVectorImpl; -/// TargetAsmParser - Generic interface to target specific assembly parsers. -class TargetAsmParser : public MCAsmParserExtension { - TargetAsmParser(const TargetAsmParser &); // DO NOT IMPLEMENT - void operator=(const TargetAsmParser &); // DO NOT IMPLEMENT +/// MCTargetAsmParser - Generic interface to target specific assembly parsers. +class MCTargetAsmParser : public MCAsmParserExtension { +public: + enum MatchResultTy { + Match_ConversionFail, + Match_InvalidOperand, + Match_MissingFeature, + Match_MnemonicFail, + Match_Success, + FIRST_TARGET_MATCH_RESULT_TY + }; + +private: + MCTargetAsmParser(const MCTargetAsmParser &); // DO NOT IMPLEMENT + void operator=(const MCTargetAsmParser &); // DO NOT IMPLEMENT protected: // Can only create subclasses. - TargetAsmParser(); - + MCTargetAsmParser(); + /// AvailableFeatures - The current set of available features. unsigned AvailableFeatures; public: - virtual ~TargetAsmParser(); + virtual ~MCTargetAsmParser(); unsigned getAvailableFeatures() const { return AvailableFeatures; } void setAvailableFeatures(unsigned Value) { AvailableFeatures = Value; } @@ -66,18 +78,24 @@ public: /// /// \param DirectiveID - the identifier token of the directive. virtual bool ParseDirective(AsmToken DirectiveID) = 0; - + /// MatchAndEmitInstruction - Recognize a series of operands of a parsed /// instruction as an actual MCInst and emit it to the specified MCStreamer. /// This returns false on success and returns true on failure to match. /// /// On failure, the target parser is responsible for emitting a diagnostic /// explaining the match failure. - virtual bool + virtual bool MatchAndEmitInstruction(SMLoc IDLoc, SmallVectorImpl &Operands, MCStreamer &Out) = 0; - + + /// checkTargetMatchPredicate - Validate the instruction match against + /// any complex target predicates not expressible via match classes. + virtual unsigned checkTargetMatchPredicate(MCInst &Inst) { + return Match_Success; + } + }; } // End llvm namespace diff --git a/contrib/llvm/include/llvm/MC/MCValue.h b/contrib/llvm/include/llvm/MC/MCValue.h index df8dbd930..8352ed183 100644 --- a/contrib/llvm/include/llvm/MC/MCValue.h +++ b/contrib/llvm/include/llvm/MC/MCValue.h @@ -46,16 +46,6 @@ public: /// isAbsolute - Is this an absolute (as opposed to relocatable) value. bool isAbsolute() const { return !SymA && !SymB; } - /// getAssociatedSection - For relocatable values, return the section the - /// value is associated with. - /// - /// @result - The value's associated section, or null for external or constant - /// values. - // - // FIXME: Switch to a tagged section, so this can return the tagged section - // value. - const MCSection *getAssociatedSection() const; - /// print - Print the value to the stream \arg OS. void print(raw_ostream &OS, const MCAsmInfo *MAI) const; diff --git a/contrib/llvm/include/llvm/CodeGen/MachineLocation.h b/contrib/llvm/include/llvm/MC/MachineLocation.h similarity index 91% rename from contrib/llvm/include/llvm/CodeGen/MachineLocation.h rename to contrib/llvm/include/llvm/MC/MachineLocation.h index 21951b668..8ddfdbcec 100644 --- a/contrib/llvm/include/llvm/CodeGen/MachineLocation.h +++ b/contrib/llvm/include/llvm/MC/MachineLocation.h @@ -1,4 +1,4 @@ -//===-- llvm/CodeGen/MachineLocation.h --------------------------*- C++ -*-===// +//===-- llvm/MC/MachineLocation.h -------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -18,8 +18,8 @@ //===----------------------------------------------------------------------===// -#ifndef LLVM_CODEGEN_MACHINELOCATION_H -#define LLVM_CODEGEN_MACHINELOCATION_H +#ifndef LLVM_MC_MACHINELOCATION_H +#define LLVM_MC_MACHINELOCATION_H namespace llvm { class MCSymbol; @@ -36,11 +36,11 @@ public: VirtualFP = ~0U }; MachineLocation() - : IsRegister(false), Register(0), Offset(0) {} + : IsRegister(false), Register(0), Offset(0) {} explicit MachineLocation(unsigned R) - : IsRegister(true), Register(R), Offset(0) {} + : IsRegister(true), Register(R), Offset(0) {} MachineLocation(unsigned R, int O) - : IsRegister(false), Register(R), Offset(O) {} + : IsRegister(false), Register(R), Offset(O) {} bool operator==(const MachineLocation &Other) const { return IsRegister == Other.IsRegister && Register == Other.Register && diff --git a/contrib/llvm/include/llvm/Module.h b/contrib/llvm/include/llvm/Module.h index 47d23f36c..8ce5ec4f1 100644 --- a/contrib/llvm/include/llvm/Module.h +++ b/contrib/llvm/include/llvm/Module.h @@ -50,17 +50,35 @@ template<> struct ilist_traits private: mutable ilist_node Sentinel; }; + template<> struct ilist_traits : public SymbolTableListTraits { // createSentinel is used to create a node that marks the end of the list. - static GlobalVariable *createSentinel(); - static void destroySentinel(GlobalVariable *GV) { delete GV; } + GlobalVariable *createSentinel() const { + return static_cast(&Sentinel); + } + static void destroySentinel(GlobalVariable*) {} + + GlobalVariable *provideInitialHead() const { return createSentinel(); } + GlobalVariable *ensureHead(GlobalVariable*) const { return createSentinel(); } + static void noteHead(GlobalVariable*, GlobalVariable*) {} +private: + mutable ilist_node Sentinel; }; + template<> struct ilist_traits : public SymbolTableListTraits { // createSentinel is used to create a node that marks the end of the list. - static GlobalAlias *createSentinel(); - static void destroySentinel(GlobalAlias *GA) { delete GA; } + GlobalAlias *createSentinel() const { + return static_cast(&Sentinel); + } + static void destroySentinel(GlobalAlias*) {} + + GlobalAlias *provideInitialHead() const { return createSentinel(); } + GlobalAlias *ensureHead(GlobalAlias*) const { return createSentinel(); } + static void noteHead(GlobalAlias*, GlobalAlias*) {} +private: + mutable ilist_node Sentinel; }; template<> struct ilist_traits @@ -272,10 +290,10 @@ public: /// the existing function. /// 4. Finally, the function exists but has the wrong prototype: return the /// function with a constantexpr cast to the right prototype. - Constant *getOrInsertFunction(StringRef Name, const FunctionType *T, + Constant *getOrInsertFunction(StringRef Name, FunctionType *T, AttrListPtr AttributeList); - Constant *getOrInsertFunction(StringRef Name, const FunctionType *T); + Constant *getOrInsertFunction(StringRef Name, FunctionType *T); /// getOrInsertFunction - Look up the specified function in the module symbol /// table. If it does not exist, add a prototype for the function and return @@ -286,14 +304,14 @@ public: /// clients to use. Constant *getOrInsertFunction(StringRef Name, AttrListPtr AttributeList, - const Type *RetTy, ...) END_WITH_NULL; + Type *RetTy, ...) END_WITH_NULL; /// getOrInsertFunction - Same as above, but without the attributes. - Constant *getOrInsertFunction(StringRef Name, const Type *RetTy, ...) + Constant *getOrInsertFunction(StringRef Name, Type *RetTy, ...) END_WITH_NULL; Constant *getOrInsertTargetIntrinsic(StringRef Name, - const FunctionType *Ty, + FunctionType *Ty, AttrListPtr AttributeList); /// getFunction - Look up the specified function in the module symbol table. @@ -325,7 +343,7 @@ public: /// with a constantexpr cast to the right type. /// 3. Finally, if the existing global is the correct declaration, return /// the existing global. - Constant *getOrInsertGlobal(StringRef Name, const Type *Ty); + Constant *getOrInsertGlobal(StringRef Name, Type *Ty); /// @} /// @name Global Alias Accessors diff --git a/contrib/llvm/include/llvm/Object/Archive.h b/contrib/llvm/include/llvm/Object/Archive.h new file mode 100644 index 000000000..4f081206c --- /dev/null +++ b/contrib/llvm/include/llvm/Object/Archive.h @@ -0,0 +1,90 @@ +//===- Archive.h - ar archive file format -----------------------*- 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 ar archive file format class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_ARCHIVE_H +#define LLVM_OBJECT_ARCHIVE_H + +#include "llvm/Object/Binary.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/DataTypes.h" + +namespace llvm { +namespace object { + +class Archive : public Binary { +public: + class Child { + const Archive *Parent; + StringRef Data; + + public: + Child(const Archive *p, StringRef d) : Parent(p), Data(d) {} + + bool operator ==(const Child &other) const { + return (Parent == other.Parent) && (Data.begin() == other.Data.begin()); + } + + Child getNext() const; + error_code getName(StringRef &Result) const; + int getLastModified() const; + int getUID() const; + int getGID() const; + int getAccessMode() const; + ///! Return the size of the archive member without the header or padding. + uint64_t getSize() const; + + MemoryBuffer *getBuffer() const; + error_code getAsBinary(OwningPtr &Result) const; + }; + + class child_iterator { + Child child; + public: + child_iterator(const Child &c) : child(c) {} + const Child* operator->() const { + return &child; + } + + bool operator==(const child_iterator &other) const { + return child == other.child; + } + + bool operator!=(const child_iterator &other) const { + return !(*this == other); + } + + child_iterator& operator++() { // Preincrement + child = child.getNext(); + return *this; + } + }; + + Archive(MemoryBuffer *source, error_code &ec); + + child_iterator begin_children() const; + child_iterator end_children() const; + + // Cast methods. + static inline bool classof(Archive const *v) { return true; } + static inline bool classof(Binary const *v) { + return v->getType() == Binary::isArchive; + } + +private: + child_iterator StringTable; +}; + +} +} + +#endif diff --git a/contrib/llvm/include/llvm/Object/COFF.h b/contrib/llvm/include/llvm/Object/COFF.h index 121f9e850..067bcd471 100644 --- a/contrib/llvm/include/llvm/Object/COFF.h +++ b/contrib/llvm/include/llvm/Object/COFF.h @@ -67,6 +67,12 @@ struct coff_section { support::ulittle32_t Characteristics; }; +struct coff_relocation { + support::ulittle32_t VirtualAddress; + support::ulittle32_t SymbolTableIndex; + support::ulittle16_t Type; +}; + class COFFObjectFile : public ObjectFile { private: const coff_file_header *Header; @@ -78,26 +84,52 @@ private: error_code getSection(int32_t index, const coff_section *&Res) const; error_code getString(uint32_t offset, StringRef &Res) const; + error_code getSymbol(uint32_t index, + const coff_symbol *&Res) const; const coff_symbol *toSymb(DataRefImpl Symb) const; const coff_section *toSec(DataRefImpl Sec) const; + const coff_relocation *toRel(DataRefImpl Rel) const; protected: virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const; virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const; + virtual error_code getSymbolOffset(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 isSymbolInternal(DataRefImpl Symb, bool &Res) const; + virtual error_code isSymbolGlobal(DataRefImpl Symb, bool &Res) const; + virtual error_code getSymbolType(DataRefImpl Symb, SymbolRef::SymbolType &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 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 getRelocationSymbol(DataRefImpl Rel, + SymbolRef &Res) const; + virtual error_code getRelocationType(DataRefImpl Rel, + uint32_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; public: COFFObjectFile(MemoryBuffer *Object, error_code &ec); diff --git a/contrib/llvm/include/llvm/Object/MachO.h b/contrib/llvm/include/llvm/Object/MachO.h new file mode 100644 index 000000000..f5e7461a4 --- /dev/null +++ b/contrib/llvm/include/llvm/Object/MachO.h @@ -0,0 +1,106 @@ +//===- MachO.h - MachO 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 MachOObjectFile class, which binds the MachOObject +// class to the generic ObjectFile wrapper. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_MACHO_H +#define LLVM_OBJECT_MACHO_H + +#include "llvm/Object/ObjectFile.h" +#include "llvm/Object/MachOObject.h" +#include "llvm/Support/MachO.h" +#include "llvm/ADT/SmallVector.h" + +namespace llvm { +namespace object { + +typedef MachOObject::LoadCommandInfo LoadCommandInfo; + +class MachOObjectFile : public ObjectFile { +public: + MachOObjectFile(MemoryBuffer *Object, MachOObject *MOO, error_code &ec); + + virtual symbol_iterator begin_symbols() const; + virtual symbol_iterator end_symbols() const; + virtual section_iterator begin_sections() const; + virtual section_iterator end_sections() const; + + virtual uint8_t getBytesInAddress() const; + virtual StringRef getFileFormatName() const; + virtual unsigned getArch() const; + +protected: + virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const; + virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const; + virtual error_code getSymbolOffset(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 isSymbolInternal(DataRefImpl Symb, bool &Res) const; + virtual error_code isSymbolGlobal(DataRefImpl Symb, bool &Res) const; + virtual error_code getSymbolType(DataRefImpl Symb, SymbolRef::SymbolType &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 sectionContainsSymbol(DataRefImpl DRI, DataRefImpl S, + 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 getRelocationSymbol(DataRefImpl Rel, + SymbolRef &Res) const; + virtual error_code getRelocationType(DataRefImpl Rel, + uint32_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; + +private: + MachOObject *MachOObj; + mutable uint32_t RegisteredStringTable; + typedef SmallVector SectionList; + SectionList Sections; + + + void moveToNextSection(DataRefImpl &DRI) const; + void getSymbolTableEntry(DataRefImpl DRI, + InMemoryStruct &Res) const; + void getSymbol64TableEntry(DataRefImpl DRI, + InMemoryStruct &Res) const; + void moveToNextSymbol(DataRefImpl &DRI) const; + void getSection(DataRefImpl DRI, InMemoryStruct &Res) const; + void getSection64(DataRefImpl DRI, + InMemoryStruct &Res) const; + void getRelocation(DataRefImpl Rel, + InMemoryStruct &Res) const; + std::size_t getSectionIndex(DataRefImpl Sec) const; +}; + +} +} + +#endif + diff --git a/contrib/llvm/include/llvm/Object/MachOFormat.h b/contrib/llvm/include/llvm/Object/MachOFormat.h index 31cd523ea..089cde92a 100644 --- a/contrib/llvm/include/llvm/Object/MachOFormat.h +++ b/contrib/llvm/include/llvm/Object/MachOFormat.h @@ -137,7 +137,10 @@ namespace macho { LCT_Symtab = 0x2, LCT_Dysymtab = 0xb, LCT_Segment64 = 0x19, - LCT_UUID = 0x1b + LCT_UUID = 0x1b, + LCT_CodeSignature = 0x1d, + LCT_SegmentSplitInfo = 0x1e, + LCT_FunctionStarts = 0x26 }; /// \brief Load command structure. @@ -218,6 +221,13 @@ namespace macho { uint32_t NumLocalRelocationTableEntries; }; + struct LinkeditDataLoadCommand { + uint32_t Type; + uint32_t Size; + uint32_t DataOffset; + uint32_t DataSize; + }; + /// @} /// @name Section Data /// @{ diff --git a/contrib/llvm/include/llvm/Object/MachOObject.h b/contrib/llvm/include/llvm/Object/MachOObject.h index 19a399e62..51be84785 100644 --- a/contrib/llvm/include/llvm/Object/MachOObject.h +++ b/contrib/llvm/include/llvm/Object/MachOObject.h @@ -150,6 +150,9 @@ public: void ReadDysymtabLoadCommand( const LoadCommandInfo &LCI, InMemoryStruct &Res) const; + void ReadLinkeditDataLoadCommand( + const LoadCommandInfo &LCI, + InMemoryStruct &Res) const; void ReadIndirectSymbolTableEntry( const macho::DysymtabLoadCommand &DLC, unsigned Index, @@ -171,6 +174,7 @@ public: void ReadSymbol64TableEntry( uint64_t SymbolTableOffset, unsigned Index, InMemoryStruct &Res) const; + void ReadULEB128s(uint64_t Index, SmallVectorImpl &Out) const; /// @} diff --git a/contrib/llvm/include/llvm/Object/ObjectFile.h b/contrib/llvm/include/llvm/Object/ObjectFile.h index 98ac06727..83854a0d6 100644 --- a/contrib/llvm/include/llvm/Object/ObjectFile.h +++ b/contrib/llvm/include/llvm/Object/ObjectFile.h @@ -27,34 +27,57 @@ 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; struct { uint32_t a, b; } d; uintptr_t p; }; -static bool operator ==(const DataRefImpl &a, const DataRefImpl &b) { - // Check bitwise identical. This is the only legal way to compare a union w/o - // knowing which member is in use. - return std::memcmp(&a, &b, sizeof(DataRefImpl)) == 0; -} +template +class content_iterator { + content_type Current; +public: + content_iterator(content_type symb) + : Current(symb) {} -class RelocationRef { - DataRefImpl RelocationPimpl; - const ObjectFile *OwningObject; + const content_type* operator->() const { + return &Current; + } -public: - RelocationRef() : OwningObject(NULL) { - std::memset(&RelocationPimpl, 0, sizeof(RelocationPimpl)); + const content_type &operator*() const { + return Current; } - RelocationRef(DataRefImpl RelocationP, const ObjectFile *Owner); + bool operator==(const content_iterator &other) const { + return Current == other.Current; + } - bool operator==(const RelocationRef &Other) const; + bool operator!=(const content_iterator &other) const { + return !(*this == other); + } - error_code getNext(RelocationRef &Result); + content_iterator& increment(error_code &err) { + content_type next; + if (error_code ec = Current.getNext(next)) + err = ec; + else + Current = next; + return *this; + } }; +static bool operator ==(const DataRefImpl &a, const DataRefImpl &b) { + // Check bitwise identical. This is the only legal way to compare a union w/o + // knowing which member is in use. + return std::memcmp(&a, &b, sizeof(DataRefImpl)) == 0; +} + /// SymbolRef - This is a value type class that represents a single symbol in /// the list of symbols in the object file. class SymbolRef { @@ -67,6 +90,13 @@ public: std::memset(&SymbolPimpl, 0, sizeof(SymbolPimpl)); } + enum SymbolType { + ST_Function, + ST_Data, + ST_External, // Defined in another object file + ST_Other + }; + SymbolRef(DataRefImpl SymbolP, const ObjectFile *Owner); bool operator==(const SymbolRef &Other) const; @@ -75,7 +105,9 @@ public: error_code getName(StringRef &Result) const; error_code getAddress(uint64_t &Result) const; + error_code getOffset(uint64_t &Result) const; error_code getSize(uint64_t &Result) const; + error_code getSymbolType(SymbolRef::SymbolType &Result) const; /// Returns the ascii char that should be displayed in a symbol table dump via /// nm for this symbol. @@ -84,7 +116,49 @@ public: /// Returns true for symbols that are internal to the object file format such /// as section symbols. error_code isInternal(bool &Result) const; + + /// Returns true for symbols that can be used in another objects, + /// such as library functions + error_code isGlobal(bool &Result) const; + + DataRefImpl getRawDataRefImpl() const; }; +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. +class RelocationRef { + DataRefImpl RelocationPimpl; + const ObjectFile *OwningObject; + +public: + RelocationRef() : OwningObject(NULL) { + std::memset(&RelocationPimpl, 0, sizeof(RelocationPimpl)); + } + + RelocationRef(DataRefImpl RelocationP, const ObjectFile *Owner); + + bool operator==(const RelocationRef &Other) const; + + error_code getNext(RelocationRef &Result) const; + + error_code getAddress(uint64_t &Result) const; + error_code getSymbol(SymbolRef &Result) const; + error_code getType(uint32_t &Result) const; + + /// @brief Get a string that represents the type of this relocation. + /// + /// 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. + /// + /// This is for display purposes only. + error_code getValueString(SmallVectorImpl &Result) 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. @@ -109,11 +183,20 @@ public: error_code getSize(uint64_t &Result) const; error_code getContents(StringRef &Result) const; + /// @brief Get the alignment of this section as the actual value (not log 2). + error_code getAlignment(uint64_t &Result) const; + // FIXME: Move to the normalization layer when it's created. error_code isText(bool &Result) const; + error_code isData(bool &Result) const; + error_code isBSS(bool &Result) const; error_code containsSymbol(SymbolRef S, bool &Result) const; + + relocation_iterator begin_relocations() const; + relocation_iterator end_relocations() const; }; +typedef content_iterator section_iterator; const uint64_t UnknownAddressOrSize = ~0ULL; @@ -144,9 +227,12 @@ protected: virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const = 0; virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const = 0; virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const =0; + virtual error_code getSymbolOffset(DataRefImpl Symb, uint64_t &Res) const =0; virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const = 0; virtual error_code getSymbolNMTypeChar(DataRefImpl Symb, char &Res) const = 0; virtual error_code isSymbolInternal(DataRefImpl Symb, bool &Res) const = 0; + virtual error_code isSymbolGlobal(DataRefImpl Symb, bool &Res) const = 0; + virtual error_code getSymbolType(DataRefImpl Symb, SymbolRef::SymbolType &Res) const = 0; // Same as above for SectionRef. friend class SectionRef; @@ -155,47 +241,34 @@ protected: virtual error_code getSectionAddress(DataRefImpl Sec, uint64_t &Res) const =0; virtual error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const = 0; virtual error_code getSectionContents(DataRefImpl Sec, StringRef &Res)const=0; + virtual error_code getSectionAlignment(DataRefImpl Sec, uint64_t &Res)const=0; virtual error_code isSectionText(DataRefImpl Sec, bool &Res) const = 0; + virtual error_code isSectionData(DataRefImpl Sec, bool &Res) const = 0; + virtual error_code isSectionBSS(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; + + + // Same as above for RelocationRef. + friend class RelocationRef; + virtual error_code getRelocationNext(DataRefImpl Rel, + RelocationRef &Res) const = 0; + virtual error_code getRelocationAddress(DataRefImpl Rel, + uint64_t &Res) const =0; + virtual error_code getRelocationSymbol(DataRefImpl Rel, + SymbolRef &Res) const = 0; + virtual error_code getRelocationType(DataRefImpl Rel, + uint32_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; public: - template - class content_iterator { - content_type Current; - public: - content_iterator(content_type symb) - : Current(symb) {} - - const content_type* operator->() const { - return &Current; - } - - const content_type &operator*() const { - return Current; - } - - bool operator==(const content_iterator &other) const { - return Current == other.Current; - } - - bool operator!=(const content_iterator &other) const { - return !(*this == other); - } - - content_iterator& increment(error_code &err) { - content_type next; - if (error_code ec = Current.getNext(next)) - err = ec; - else - Current = next; - return *this; - } - }; - - typedef content_iterator symbol_iterator; - typedef content_iterator section_iterator; virtual symbol_iterator begin_symbols() const = 0; virtual symbol_iterator end_symbols() const = 0; @@ -250,6 +323,10 @@ inline error_code SymbolRef::getAddress(uint64_t &Result) const { return OwningObject->getSymbolAddress(SymbolPimpl, Result); } +inline error_code SymbolRef::getOffset(uint64_t &Result) const { + return OwningObject->getSymbolOffset(SymbolPimpl, Result); +} + inline error_code SymbolRef::getSize(uint64_t &Result) const { return OwningObject->getSymbolSize(SymbolPimpl, Result); } @@ -262,6 +339,18 @@ inline error_code SymbolRef::isInternal(bool &Result) const { return OwningObject->isSymbolInternal(SymbolPimpl, Result); } +inline error_code SymbolRef::isGlobal(bool &Result) const { + return OwningObject->isSymbolGlobal(SymbolPimpl, Result); +} + +inline error_code SymbolRef::getSymbolType(SymbolRef::SymbolType &Result) const { + return OwningObject->getSymbolType(SymbolPimpl, Result); +} + +inline DataRefImpl SymbolRef::getRawDataRefImpl() const { + return SymbolPimpl; +} + /// SectionRef inline SectionRef::SectionRef(DataRefImpl SectionP, @@ -293,15 +382,76 @@ inline error_code SectionRef::getContents(StringRef &Result) const { return OwningObject->getSectionContents(SectionPimpl, Result); } +inline error_code SectionRef::getAlignment(uint64_t &Result) const { + return OwningObject->getSectionAlignment(SectionPimpl, Result); +} + inline error_code SectionRef::isText(bool &Result) const { return OwningObject->isSectionText(SectionPimpl, Result); } +inline error_code SectionRef::isData(bool &Result) const { + return OwningObject->isSectionData(SectionPimpl, Result); +} + +inline error_code SectionRef::isBSS(bool &Result) const { + return OwningObject->isSectionBSS(SectionPimpl, Result); +} + inline error_code SectionRef::containsSymbol(SymbolRef S, bool &Result) const { return OwningObject->sectionContainsSymbol(SectionPimpl, S.SymbolPimpl, Result); } +inline relocation_iterator SectionRef::begin_relocations() const { + return OwningObject->getSectionRelBegin(SectionPimpl); +} + +inline relocation_iterator SectionRef::end_relocations() const { + return OwningObject->getSectionRelEnd(SectionPimpl); +} + + +/// RelocationRef +inline RelocationRef::RelocationRef(DataRefImpl RelocationP, + const ObjectFile *Owner) + : RelocationPimpl(RelocationP) + , OwningObject(Owner) {} + +inline bool RelocationRef::operator==(const RelocationRef &Other) const { + return RelocationPimpl == Other.RelocationPimpl; +} + +inline error_code RelocationRef::getNext(RelocationRef &Result) const { + return OwningObject->getRelocationNext(RelocationPimpl, Result); +} + +inline error_code RelocationRef::getAddress(uint64_t &Result) const { + return OwningObject->getRelocationAddress(RelocationPimpl, Result); +} + +inline error_code RelocationRef::getSymbol(SymbolRef &Result) const { + return OwningObject->getRelocationSymbol(RelocationPimpl, Result); +} + +inline error_code RelocationRef::getType(uint32_t &Result) const { + return OwningObject->getRelocationType(RelocationPimpl, Result); +} + +inline error_code RelocationRef::getTypeName(SmallVectorImpl &Result) + const { + 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); +} + } // end namespace object } // end namespace llvm diff --git a/contrib/llvm/include/llvm/OperandTraits.h b/contrib/llvm/include/llvm/OperandTraits.h index f0df5fa9b..3d8dc329b 100644 --- a/contrib/llvm/include/llvm/OperandTraits.h +++ b/contrib/llvm/include/llvm/OperandTraits.h @@ -136,45 +136,8 @@ CLASS::const_op_iterator CLASS::op_end() const { \ VALUECLASS *CLASS::getOperand(unsigned i_nocapture) const { \ assert(i_nocapture < OperandTraits::operands(this) \ && "getOperand() out of range!"); \ - return static_cast( \ - OperandTraits::op_begin(const_cast(this))[i_nocapture]); \ -} \ -void CLASS::setOperand(unsigned i_nocapture, VALUECLASS *Val_nocapture) { \ - assert(i_nocapture < OperandTraits::operands(this) \ - && "setOperand() out of range!"); \ - OperandTraits::op_begin(this)[i_nocapture] = Val_nocapture; \ -} \ -unsigned CLASS::getNumOperands() const { \ - return OperandTraits::operands(this); \ -} \ -template Use &CLASS::Op() { \ - return this->OpFrom(this); \ -} \ -template const Use &CLASS::Op() const { \ - return this->OpFrom(this); \ -} - - -/// Macro for generating out-of-class operand accessor -/// definitions with casted result -#define DEFINE_TRANSPARENT_CASTED_OPERAND_ACCESSORS(CLASS, VALUECLASS) \ -CLASS::op_iterator CLASS::op_begin() { \ - return OperandTraits::op_begin(this); \ -} \ -CLASS::const_op_iterator CLASS::op_begin() const { \ - return OperandTraits::op_begin(const_cast(this)); \ -} \ -CLASS::op_iterator CLASS::op_end() { \ - return OperandTraits::op_end(this); \ -} \ -CLASS::const_op_iterator CLASS::op_end() const { \ - return OperandTraits::op_end(const_cast(this)); \ -} \ -VALUECLASS *CLASS::getOperand(unsigned i_nocapture) const { \ - assert(i_nocapture < OperandTraits::operands(this) \ - && "getOperand() out of range!"); \ - return cast( \ - OperandTraits::op_begin(const_cast(this))[i_nocapture]); \ + return cast_or_null( \ + OperandTraits::op_begin(const_cast(this))[i_nocapture].get()); \ } \ void CLASS::setOperand(unsigned i_nocapture, VALUECLASS *Val_nocapture) { \ assert(i_nocapture < OperandTraits::operands(this) \ diff --git a/contrib/llvm/include/llvm/Operator.h b/contrib/llvm/include/llvm/Operator.h index e9aa4997f..48a579638 100644 --- a/contrib/llvm/include/llvm/Operator.h +++ b/contrib/llvm/include/llvm/Operator.h @@ -261,8 +261,8 @@ public: /// getPointerOperandType - Method to return the pointer operand as a /// PointerType. - const PointerType *getPointerOperandType() const { - return reinterpret_cast(getPointerOperand()->getType()); + PointerType *getPointerOperandType() const { + return reinterpret_cast(getPointerOperand()->getType()); } unsigned getNumIndices() const { // Note: always non-negative diff --git a/contrib/llvm/include/llvm/PassManagers.h b/contrib/llvm/include/llvm/PassManagers.h index c4f409ef5..c05347da7 100644 --- a/contrib/llvm/include/llvm/PassManagers.h +++ b/contrib/llvm/include/llvm/PassManagers.h @@ -263,7 +263,7 @@ private: class PMDataManager { public: - explicit PMDataManager(int Depth) : TPM(NULL), Depth(Depth) { + explicit PMDataManager() : TPM(NULL), Depth(0) { initializeAnalysisInfo(); } @@ -333,6 +333,7 @@ public: void setTopLevelManager(PMTopLevelManager *T) { TPM = T; } unsigned getDepth() const { return Depth; } + void setDepth(unsigned newDepth) { Depth = newDepth; } // Print routines used by debug-pass void dumpLastUses(Pass *P, unsigned Offset) const; @@ -408,8 +409,8 @@ private: class FPPassManager : public ModulePass, public PMDataManager { public: static char ID; - explicit FPPassManager(int Depth) - : ModulePass(ID), PMDataManager(Depth) { } + explicit FPPassManager() + : ModulePass(ID), PMDataManager() { } /// 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. diff --git a/contrib/llvm/include/llvm/Support/BlockFrequency.h b/contrib/llvm/include/llvm/Support/BlockFrequency.h new file mode 100644 index 000000000..554b78456 --- /dev/null +++ b/contrib/llvm/include/llvm/Support/BlockFrequency.h @@ -0,0 +1,63 @@ +//===-------- BlockFrequency.h - Block Frequency Wrapper --------*- 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 Block Frequency class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_BLOCKFREQUENCY_H +#define LLVM_SUPPORT_BLOCKFREQUENCY_H + +namespace llvm { + +class raw_ostream; +class BranchProbability; + +// This class represents Block Frequency as a 64-bit value. +class BlockFrequency { + + uint64_t Frequency; + static const int64_t ENTRY_FREQ = 1024; + +public: + BlockFrequency(uint64_t Freq = 0) : Frequency(Freq) { } + + static uint64_t getEntryFrequency() { return ENTRY_FREQ; } + uint64_t getFrequency() const { return Frequency; } + + BlockFrequency &operator*=(const BranchProbability &Prob); + const BlockFrequency operator*(const BranchProbability &Prob) const; + + BlockFrequency &operator+=(const BlockFrequency &Freq); + const BlockFrequency operator+(const BlockFrequency &Freq) const; + + bool operator<(const BlockFrequency &RHS) const { + return Frequency < RHS.Frequency; + } + + bool operator<=(const BlockFrequency &RHS) const { + return Frequency <= RHS.Frequency; + } + + bool operator>(const BlockFrequency &RHS) const { + return Frequency > RHS.Frequency; + } + + bool operator>=(const BlockFrequency &RHS) const { + return Frequency >= RHS.Frequency; + } + + void print(raw_ostream &OS) const; +}; + +raw_ostream &operator<<(raw_ostream &OS, const BlockFrequency &Freq); + +} + +#endif diff --git a/contrib/llvm/include/llvm/Support/BranchProbability.h b/contrib/llvm/include/llvm/Support/BranchProbability.h index 2e81490eb..05c24d4fc 100644 --- a/contrib/llvm/include/llvm/Support/BranchProbability.h +++ b/contrib/llvm/include/llvm/Support/BranchProbability.h @@ -1,4 +1,4 @@ -//===- BranchProbability.h - Branch Probability Analysis --------*- C++ -*-===// +//===- BranchProbability.h - Branch Probability Wrapper ---------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -34,13 +34,13 @@ public: uint32_t getNumerator() const { return N; } uint32_t getDenominator() const { return D; } - + // Return (1 - Probability). BranchProbability getCompl() { return BranchProbability(D - N, D); } - raw_ostream &print(raw_ostream &OS) const; + void print(raw_ostream &OS) const; void dump() const; }; diff --git a/contrib/llvm/include/llvm/Support/CallSite.h b/contrib/llvm/include/llvm/Support/CallSite.h index 8a998a8cd..04b8c4e69 100644 --- a/contrib/llvm/include/llvm/Support/CallSite.h +++ b/contrib/llvm/include/llvm/Support/CallSite.h @@ -147,7 +147,7 @@ public: /// getType - Return the type of the instruction that generated this call site /// - const Type *getType() const { return (*this)->getType(); } + Type *getType() const { return (*this)->getType(); } /// getCaller - Return the caller function for this call site /// diff --git a/contrib/llvm/include/llvm/Support/Capacity.h b/contrib/llvm/include/llvm/Support/Capacity.h new file mode 100644 index 000000000..d8cda43b3 --- /dev/null +++ b/contrib/llvm/include/llvm/Support/Capacity.h @@ -0,0 +1,30 @@ +//===--- Capacity.h - Generic computation of ADT memory use -----*- 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 capacity function that computes the amount of +// memory used by an ADT. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_CAPACITY_H +#define LLVM_SUPPORT_CAPACITY_H + +namespace llvm { + +template +static inline size_t capacity_in_bytes(const T &x) { + // This default definition of capacity should work for things like std::vector + // and friends. More specialized versions will work for others. + return x.capacity() * sizeof(typename T::value_type); +} + +} // end namespace llvm + +#endif + diff --git a/contrib/llvm/include/llvm/Support/CodeGen.h b/contrib/llvm/include/llvm/Support/CodeGen.h new file mode 100644 index 000000000..41351dc73 --- /dev/null +++ b/contrib/llvm/include/llvm/Support/CodeGen.h @@ -0,0 +1,32 @@ +//===-- llvm/Support/CodeGen.h - CodeGen Concepts ---------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file define some types which define code generation concepts. For +// example, relocation model. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_CODEGEN_H +#define LLVM_SUPPORT_CODEGEN_H + +namespace llvm { + + // Relocation model types. + namespace Reloc { + enum Model { Default, Static, PIC_, DynamicNoPIC }; + } + + // Code model types. + namespace CodeModel { + enum Model { Default, JITDefault, Small, Kernel, Medium, Large }; + } + +} // end llvm namespace + +#endif diff --git a/contrib/llvm/include/llvm/Support/CommandLine.h b/contrib/llvm/include/llvm/Support/CommandLine.h index d6098711a..c6b62a8df 100644 --- a/contrib/llvm/include/llvm/Support/CommandLine.h +++ b/contrib/llvm/include/llvm/Support/CommandLine.h @@ -59,6 +59,15 @@ void ParseEnvironmentOptions(const char *progName, const char *envvar, /// CommandLine utilities to print their own version string. void SetVersionPrinter(void (*func)()); +///===---------------------------------------------------------------------===// +/// AddExtraVersionPrinter - Add an extra printer to use in addition to the +/// default one. This can be called multiple times, +/// and each time it adds a new function to the list +/// which will be called after the basic LLVM version +/// printing is complete. Each can then add additional +/// information specific to the tool. +void AddExtraVersionPrinter(void (*func)()); + // PrintOptionValues - Print option values. // With -print-options print the difference between option values and defaults. @@ -796,6 +805,28 @@ public: EXTERN_TEMPLATE_INSTANTIATION(class basic_parser); +//-------------------------------------------------- +// parser +// +template<> +class parser : public basic_parser { +public: + // parse - Return true on error. + bool parse(Option &O, StringRef ArgName, StringRef Arg, + unsigned long long &Val); + + // getValueName - Overload in subclass to provide a better default value. + virtual const char *getValueName() const { return "uint"; } + + void printOptionDiff(const Option &O, unsigned long long V, OptVal Default, + size_t GlobalWidth) const; + + // An out-of-line virtual method to provide a 'home' for this class. + virtual void anchor(); +}; + +EXTERN_TEMPLATE_INSTANTIATION(class basic_parser); + //-------------------------------------------------- // parser // diff --git a/contrib/llvm/include/llvm/Support/ConstantFolder.h b/contrib/llvm/include/llvm/Support/ConstantFolder.h index 733023566..93aa3436d 100644 --- a/contrib/llvm/include/llvm/Support/ConstantFolder.h +++ b/contrib/llvm/include/llvm/Support/ConstantFolder.h @@ -118,22 +118,34 @@ public: // Memory Instructions //===--------------------------------------------------------------------===// - Constant *CreateGetElementPtr(Constant *C, Constant* const *IdxList, - unsigned NumIdx) const { - return ConstantExpr::getGetElementPtr(C, IdxList, NumIdx); + Constant *CreateGetElementPtr(Constant *C, + ArrayRef IdxList) const { + return ConstantExpr::getGetElementPtr(C, IdxList); } - Constant *CreateGetElementPtr(Constant *C, Value* const *IdxList, - unsigned NumIdx) const { - return ConstantExpr::getGetElementPtr(C, IdxList, NumIdx); + Constant *CreateGetElementPtr(Constant *C, Constant *Idx) const { + // This form of the function only exists to avoid ambiguous overload + // warnings about whether to convert Idx to ArrayRef or + // ArrayRef. + return ConstantExpr::getGetElementPtr(C, Idx); + } + Constant *CreateGetElementPtr(Constant *C, + ArrayRef IdxList) const { + return ConstantExpr::getGetElementPtr(C, IdxList); } - Constant *CreateInBoundsGetElementPtr(Constant *C, Constant* const *IdxList, - unsigned NumIdx) const { - return ConstantExpr::getInBoundsGetElementPtr(C, IdxList, NumIdx); + Constant *CreateInBoundsGetElementPtr(Constant *C, + ArrayRef IdxList) const { + return ConstantExpr::getInBoundsGetElementPtr(C, IdxList); + } + Constant *CreateInBoundsGetElementPtr(Constant *C, Constant *Idx) const { + // This form of the function only exists to avoid ambiguous overload + // warnings about whether to convert Idx to ArrayRef or + // ArrayRef. + return ConstantExpr::getInBoundsGetElementPtr(C, Idx); } - Constant *CreateInBoundsGetElementPtr(Constant *C, Value* const *IdxList, - unsigned NumIdx) const { - return ConstantExpr::getInBoundsGetElementPtr(C, IdxList, NumIdx); + Constant *CreateInBoundsGetElementPtr(Constant *C, + ArrayRef IdxList) const { + return ConstantExpr::getInBoundsGetElementPtr(C, IdxList); } //===--------------------------------------------------------------------===// @@ -141,37 +153,37 @@ public: //===--------------------------------------------------------------------===// Constant *CreateCast(Instruction::CastOps Op, Constant *C, - const Type *DestTy) const { + Type *DestTy) const { return ConstantExpr::getCast(Op, C, DestTy); } - Constant *CreatePointerCast(Constant *C, const Type *DestTy) const { + Constant *CreatePointerCast(Constant *C, Type *DestTy) const { return ConstantExpr::getPointerCast(C, DestTy); } - Constant *CreateIntCast(Constant *C, const Type *DestTy, + Constant *CreateIntCast(Constant *C, Type *DestTy, bool isSigned) const { return ConstantExpr::getIntegerCast(C, DestTy, isSigned); } - Constant *CreateFPCast(Constant *C, const Type *DestTy) const { + Constant *CreateFPCast(Constant *C, Type *DestTy) const { return ConstantExpr::getFPCast(C, DestTy); } - Constant *CreateBitCast(Constant *C, const Type *DestTy) const { + Constant *CreateBitCast(Constant *C, Type *DestTy) const { return CreateCast(Instruction::BitCast, C, DestTy); } - Constant *CreateIntToPtr(Constant *C, const Type *DestTy) const { + Constant *CreateIntToPtr(Constant *C, Type *DestTy) const { return CreateCast(Instruction::IntToPtr, C, DestTy); } - Constant *CreatePtrToInt(Constant *C, const Type *DestTy) const { + Constant *CreatePtrToInt(Constant *C, Type *DestTy) const { return CreateCast(Instruction::PtrToInt, C, DestTy); } - Constant *CreateZExtOrBitCast(Constant *C, const Type *DestTy) const { + Constant *CreateZExtOrBitCast(Constant *C, Type *DestTy) const { return ConstantExpr::getZExtOrBitCast(C, DestTy); } - Constant *CreateSExtOrBitCast(Constant *C, const Type *DestTy) const { + Constant *CreateSExtOrBitCast(Constant *C, Type *DestTy) const { return ConstantExpr::getSExtOrBitCast(C, DestTy); } - Constant *CreateTruncOrBitCast(Constant *C, const Type *DestTy) const { + Constant *CreateTruncOrBitCast(Constant *C, Type *DestTy) const { return ConstantExpr::getTruncOrBitCast(C, DestTy); } diff --git a/contrib/llvm/include/llvm/Support/DataExtractor.h b/contrib/llvm/include/llvm/Support/DataExtractor.h new file mode 100644 index 000000000..506ec9693 --- /dev/null +++ b/contrib/llvm/include/llvm/Support/DataExtractor.h @@ -0,0 +1,352 @@ +//===-- DataExtractor.h -----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_DATAEXTRACTOR_H +#define LLVM_SUPPORT_DATAEXTRACTOR_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/DataTypes.h" + +namespace llvm { +class DataExtractor { + StringRef Data; + uint8_t IsLittleEndian; + uint8_t PointerSize; +public: + /// Construct with a buffer that is owned by the caller. + /// + /// This constructor allows us to use data that is owned by the + /// caller. The data must stay around as long as this object is + /// valid. + DataExtractor(StringRef Data, bool IsLittleEndian, uint8_t PointerSize) + : Data(Data), IsLittleEndian(IsLittleEndian), PointerSize(PointerSize) {} + + /// getData - Get the data pointed to by this extractor. + StringRef getData() const { return Data; } + /// isLittleEndian - Get the endianess for this extractor. + bool isLittleEndian() const { return IsLittleEndian; } + /// getAddressSize - Get the address size for this extractor. + uint8_t getAddressSize() const { return PointerSize; } + + /// Extract a C string from \a *offset_ptr. + /// + /// Returns a pointer to a C String from the data at the offset + /// pointed to by \a offset_ptr. A variable length NULL terminated C + /// string will be extracted and the \a offset_ptr will be + /// updated with the offset of the byte that follows the NULL + /// terminator byte. + /// + /// @param[in,out] offset_ptr + /// A pointer to an offset within the data that will be advanced + /// by the appropriate number of bytes if the value is extracted + /// correctly. If the offset is out of bounds or there are not + /// enough bytes to extract this value, the offset will be left + /// unmodified. + /// + /// @return + /// A pointer to the C string value in the data. If the offset + /// pointed to by \a offset_ptr is out of bounds, or if the + /// offset plus the length of the C string is out of bounds, + /// NULL will be returned. + const char *getCStr(uint32_t *offset_ptr) const; + + /// Extract an unsigned integer of size \a byte_size from \a + /// *offset_ptr. + /// + /// Extract a single unsigned integer value and update the offset + /// pointed to by \a offset_ptr. The size of the extracted integer + /// is specified by the \a byte_size argument. \a byte_size should + /// have a value greater than or equal to one and less than or equal + /// to eight since the return value is 64 bits wide. Any + /// \a byte_size values less than 1 or greater than 8 will result in + /// nothing being extracted, and zero being returned. + /// + /// @param[in,out] offset_ptr + /// A pointer to an offset within the data that will be advanced + /// by the appropriate number of bytes if the value is extracted + /// correctly. If the offset is out of bounds or there are not + /// enough bytes to extract this value, the offset will be left + /// unmodified. + /// + /// @param[in] byte_size + /// The size in byte of the integer to extract. + /// + /// @return + /// The unsigned integer value that was extracted, or zero on + /// failure. + uint64_t getUnsigned(uint32_t *offset_ptr, uint32_t byte_size) const; + + /// Extract an signed integer of size \a byte_size from \a *offset_ptr. + /// + /// Extract a single signed integer value (sign extending if required) + /// and update the offset pointed to by \a offset_ptr. The size of + /// the extracted integer is specified by the \a byte_size argument. + /// \a byte_size should have a value greater than or equal to one + /// and less than or equal to eight since the return value is 64 + /// bits wide. Any \a byte_size values less than 1 or greater than + /// 8 will result in nothing being extracted, and zero being returned. + /// + /// @param[in,out] offset_ptr + /// A pointer to an offset within the data that will be advanced + /// by the appropriate number of bytes if the value is extracted + /// correctly. If the offset is out of bounds or there are not + /// enough bytes to extract this value, the offset will be left + /// unmodified. + /// + /// @param[in] byte_size + /// The size in byte of the integer to extract. + /// + /// @return + /// The sign extended signed integer value that was extracted, + /// or zero on failure. + int64_t getSigned(uint32_t *offset_ptr, uint32_t size) const; + + //------------------------------------------------------------------ + /// Extract an pointer from \a *offset_ptr. + /// + /// Extract a single pointer from the data and update the offset + /// pointed to by \a offset_ptr. The size of the extracted pointer + /// comes from the \a m_addr_size member variable and should be + /// set correctly prior to extracting any pointer values. + /// + /// @param[in,out] offset_ptr + /// A pointer to an offset within the data that will be advanced + /// by the appropriate number of bytes if the value is extracted + /// correctly. If the offset is out of bounds or there are not + /// enough bytes to extract this value, the offset will be left + /// unmodified. + /// + /// @return + /// The extracted pointer value as a 64 integer. + uint64_t getAddress(uint32_t *offset_ptr) const { + return getUnsigned(offset_ptr, PointerSize); + } + + /// Extract a uint8_t value from \a *offset_ptr. + /// + /// Extract a single uint8_t from the binary data at the offset + /// pointed to by \a offset_ptr, and advance the offset on success. + /// + /// @param[in,out] offset_ptr + /// A pointer to an offset within the data that will be advanced + /// by the appropriate number of bytes if the value is extracted + /// correctly. If the offset is out of bounds or there are not + /// enough bytes to extract this value, the offset will be left + /// unmodified. + /// + /// @return + /// The extracted uint8_t value. + uint8_t getU8(uint32_t *offset_ptr) const; + + /// Extract \a count uint8_t values from \a *offset_ptr. + /// + /// Extract \a count uint8_t values from the binary data at the + /// offset pointed to by \a offset_ptr, and advance the offset on + /// success. The extracted values are copied into \a dst. + /// + /// @param[in,out] offset_ptr + /// A pointer to an offset within the data that will be advanced + /// by the appropriate number of bytes if the value is extracted + /// correctly. If the offset is out of bounds or there are not + /// enough bytes to extract this value, the offset will be left + /// unmodified. + /// + /// @param[out] dst + /// A buffer to copy \a count uint8_t values into. \a dst must + /// be large enough to hold all requested data. + /// + /// @param[in] count + /// The number of uint8_t values to extract. + /// + /// @return + /// \a dst if all values were properly extracted and copied, + /// NULL otherise. + uint8_t *getU8(uint32_t *offset_ptr, uint8_t *dst, uint32_t count) const; + + //------------------------------------------------------------------ + /// Extract a uint16_t value from \a *offset_ptr. + /// + /// Extract a single uint16_t from the binary data at the offset + /// pointed to by \a offset_ptr, and update the offset on success. + /// + /// @param[in,out] offset_ptr + /// A pointer to an offset within the data that will be advanced + /// by the appropriate number of bytes if the value is extracted + /// correctly. If the offset is out of bounds or there are not + /// enough bytes to extract this value, the offset will be left + /// unmodified. + /// + /// @return + /// The extracted uint16_t value. + //------------------------------------------------------------------ + uint16_t getU16(uint32_t *offset_ptr) const; + + /// Extract \a count uint16_t values from \a *offset_ptr. + /// + /// Extract \a count uint16_t values from the binary data at the + /// offset pointed to by \a offset_ptr, and advance the offset on + /// success. The extracted values are copied into \a dst. + /// + /// @param[in,out] offset_ptr + /// A pointer to an offset within the data that will be advanced + /// by the appropriate number of bytes if the value is extracted + /// correctly. If the offset is out of bounds or there are not + /// enough bytes to extract this value, the offset will be left + /// unmodified. + /// + /// @param[out] dst + /// A buffer to copy \a count uint16_t values into. \a dst must + /// be large enough to hold all requested data. + /// + /// @param[in] count + /// The number of uint16_t values to extract. + /// + /// @return + /// \a dst if all values were properly extracted and copied, + /// NULL otherise. + uint16_t *getU16(uint32_t *offset_ptr, uint16_t *dst, uint32_t count) const; + + /// Extract a uint32_t value from \a *offset_ptr. + /// + /// Extract a single uint32_t from the binary data at the offset + /// pointed to by \a offset_ptr, and update the offset on success. + /// + /// @param[in,out] offset_ptr + /// A pointer to an offset within the data that will be advanced + /// by the appropriate number of bytes if the value is extracted + /// correctly. If the offset is out of bounds or there are not + /// enough bytes to extract this value, the offset will be left + /// unmodified. + /// + /// @return + /// The extracted uint32_t value. + uint32_t getU32(uint32_t *offset_ptr) const; + + /// Extract \a count uint32_t values from \a *offset_ptr. + /// + /// Extract \a count uint32_t values from the binary data at the + /// offset pointed to by \a offset_ptr, and advance the offset on + /// success. The extracted values are copied into \a dst. + /// + /// @param[in,out] offset_ptr + /// A pointer to an offset within the data that will be advanced + /// by the appropriate number of bytes if the value is extracted + /// correctly. If the offset is out of bounds or there are not + /// enough bytes to extract this value, the offset will be left + /// unmodified. + /// + /// @param[out] dst + /// A buffer to copy \a count uint32_t values into. \a dst must + /// be large enough to hold all requested data. + /// + /// @param[in] count + /// The number of uint32_t values to extract. + /// + /// @return + /// \a dst if all values were properly extracted and copied, + /// NULL otherise. + uint32_t *getU32(uint32_t *offset_ptr, uint32_t *dst, uint32_t count) const; + + /// Extract a uint64_t value from \a *offset_ptr. + /// + /// Extract a single uint64_t from the binary data at the offset + /// pointed to by \a offset_ptr, and update the offset on success. + /// + /// @param[in,out] offset_ptr + /// A pointer to an offset within the data that will be advanced + /// by the appropriate number of bytes if the value is extracted + /// correctly. If the offset is out of bounds or there are not + /// enough bytes to extract this value, the offset will be left + /// unmodified. + /// + /// @return + /// The extracted uint64_t value. + uint64_t getU64(uint32_t *offset_ptr) const; + + /// Extract \a count uint64_t values from \a *offset_ptr. + /// + /// Extract \a count uint64_t values from the binary data at the + /// offset pointed to by \a offset_ptr, and advance the offset on + /// success. The extracted values are copied into \a dst. + /// + /// @param[in,out] offset_ptr + /// A pointer to an offset within the data that will be advanced + /// by the appropriate number of bytes if the value is extracted + /// correctly. If the offset is out of bounds or there are not + /// enough bytes to extract this value, the offset will be left + /// unmodified. + /// + /// @param[out] dst + /// A buffer to copy \a count uint64_t values into. \a dst must + /// be large enough to hold all requested data. + /// + /// @param[in] count + /// The number of uint64_t values to extract. + /// + /// @return + /// \a dst if all values were properly extracted and copied, + /// NULL otherise. + uint64_t *getU64(uint32_t *offset_ptr, uint64_t *dst, uint32_t count) const; + + /// Extract a signed LEB128 value from \a *offset_ptr. + /// + /// Extracts an signed LEB128 number from this object's data + /// starting at the offset pointed to by \a offset_ptr. The offset + /// pointed to by \a offset_ptr will be updated with the offset of + /// the byte following the last extracted byte. + /// + /// @param[in,out] offset_ptr + /// A pointer to an offset within the data that will be advanced + /// by the appropriate number of bytes if the value is extracted + /// correctly. If the offset is out of bounds or there are not + /// enough bytes to extract this value, the offset will be left + /// unmodified. + /// + /// @return + /// The extracted signed integer value. + int64_t getSLEB128(uint32_t *offset_ptr) const; + + /// Extract a unsigned LEB128 value from \a *offset_ptr. + /// + /// Extracts an unsigned LEB128 number from this object's data + /// starting at the offset pointed to by \a offset_ptr. The offset + /// pointed to by \a offset_ptr will be updated with the offset of + /// the byte following the last extracted byte. + /// + /// @param[in,out] offset_ptr + /// A pointer to an offset within the data that will be advanced + /// by the appropriate number of bytes if the value is extracted + /// correctly. If the offset is out of bounds or there are not + /// enough bytes to extract this value, the offset will be left + /// unmodified. + /// + /// @return + /// The extracted unsigned integer value. + uint64_t getULEB128(uint32_t *offset_ptr) const; + + /// Test the validity of \a offset. + /// + /// @return + /// \b true if \a offset is a valid offset into the data in this + /// object, \b false otherwise. + bool isValidOffset(uint32_t offset) const { return Data.size() > offset; } + + /// Test the availability of \a length bytes of data from \a offset. + /// + /// @return + /// \b true if \a offset is a valid offset and there are \a + /// length bytes available at that offset, \b false otherwise. + bool isValidOffsetForDataOfSize(uint32_t offset, uint32_t length) const { + return offset + length >= offset && isValidOffset(offset + length - 1); + } +}; + +} // namespace llvm + +#endif diff --git a/contrib/llvm/include/llvm/Support/DataTypes.h.in b/contrib/llvm/include/llvm/Support/DataTypes.h.in index 5965e8c0b..425805a16 100644 --- a/contrib/llvm/include/llvm/Support/DataTypes.h.in +++ b/contrib/llvm/include/llvm/Support/DataTypes.h.in @@ -1,4 +1,4 @@ -/*===-- include/System/DataTypes.h - Define fixed size types -----*- C -*-===*\ +/*===-- include/Support/DataTypes.h - Define fixed size types -----*- C -*-===*\ |* *| |* The LLVM Compiler Infrastructure *| |* *| @@ -21,6 +21,8 @@ /* Please leave this file C-compatible. */ +/* Please keep this file in sync with DataTypes.h.cmake */ + #ifndef SUPPORT_DATATYPES_H #define SUPPORT_DATATYPES_H @@ -36,17 +38,19 @@ #include #endif +#ifndef _MSC_VER + /* Note that this header's correct operation depends on __STDC_LIMIT_MACROS being defined. We would define it here, but in order to prevent Bad Things happening when system headers or C++ STL headers include stdint.h before we define it here, we define it on the g++ command line (in Makefile.rules). */ #if !defined(__STDC_LIMIT_MACROS) -# error "Must #define __STDC_LIMIT_MACROS before #including System/DataTypes.h" +# error "Must #define __STDC_LIMIT_MACROS before #including Support/DataTypes.h" #endif #if !defined(__STDC_CONSTANT_MACROS) # error "Must #define __STDC_CONSTANT_MACROS before " \ - "#including System/DataTypes.h" + "#including Support/DataTypes.h" #endif /* Note that includes , if this is a C99 system. */ @@ -87,6 +91,88 @@ typedef u_int64_t uint64_t; #define UINT32_MAX 4294967295U #endif +#else /* _MSC_VER */ +/* Visual C++ doesn't provide standard integer headers, but it does provide + built-in data types. */ +#include +#include +#include +#ifdef __cplusplus +#include +#else +#include +#endif +typedef __int64 int64_t; +typedef unsigned __int64 uint64_t; +typedef signed int int32_t; +typedef unsigned int uint32_t; +typedef short int16_t; +typedef unsigned short uint16_t; +typedef signed char int8_t; +typedef unsigned char uint8_t; +typedef signed int ssize_t; +#ifndef INT8_MAX +# define INT8_MAX 127 +#endif +#ifndef INT8_MIN +# define INT8_MIN -128 +#endif +#ifndef UINT8_MAX +# define UINT8_MAX 255 +#endif +#ifndef INT16_MAX +# define INT16_MAX 32767 +#endif +#ifndef INT16_MIN +# define INT16_MIN -32768 +#endif +#ifndef UINT16_MAX +# define UINT16_MAX 65535 +#endif +#ifndef INT32_MAX +# define INT32_MAX 2147483647 +#endif +#ifndef INT32_MIN +/* MSC treats -2147483648 as -(2147483648U). */ +# define INT32_MIN (-INT32_MAX - 1) +#endif +#ifndef UINT32_MAX +# define UINT32_MAX 4294967295U +#endif +/* Certain compatibility updates to VC++ introduce the `cstdint' + * header, which defines the INT*_C macros. On default installs they + * are absent. */ +#ifndef INT8_C +# define INT8_C(C) C##i8 +#endif +#ifndef UINT8_C +# define UINT8_C(C) C##ui8 +#endif +#ifndef INT16_C +# define INT16_C(C) C##i16 +#endif +#ifndef UINT16_C +# define UINT16_C(C) C##ui16 +#endif +#ifndef INT32_C +# define INT32_C(C) C##i32 +#endif +#ifndef UINT32_C +# define UINT32_C(C) C##ui32 +#endif +#ifndef INT64_C +# define INT64_C(C) C##i64 +#endif +#ifndef UINT64_C +# define UINT64_C(C) C##ui64 +#endif + +#ifndef PRIx64 +# define PRIx64 "I64x" +#endif + +#endif /* _MSC_VER */ + /* Set defaults for constants which we cannot find. */ #if !defined(INT64_MAX) # define INT64_MAX 9223372036854775807LL diff --git a/contrib/llvm/include/llvm/Support/Dwarf.h b/contrib/llvm/include/llvm/Support/Dwarf.h index 70bac0c9f..30f91874d 100644 --- a/contrib/llvm/include/llvm/Support/Dwarf.h +++ b/contrib/llvm/include/llvm/Support/Dwarf.h @@ -22,8 +22,10 @@ namespace llvm { // Debug info constants. enum { - LLVMDebugVersion = (9 << 16), // Current version of debug information. - LLVMDebugVersion8 = (8 << 16), // Cconstant for version 8. + LLVMDebugVersion = (11 << 16), // Current version of debug information. + LLVMDebugVersion10 = (10 << 16), // Constant for version 10. + LLVMDebugVersion9 = (9 << 16), // Constant for version 9. + LLVMDebugVersion8 = (8 << 16), // Constant for version 8. LLVMDebugVersion7 = (7 << 16), // Constant for version 7. LLVMDebugVersion6 = (6 << 16), // Constant for version 6. LLVMDebugVersion5 = (5 << 16), // Constant for version 5. @@ -117,7 +119,16 @@ enum dwarf_constants { DW_TAG_imported_unit = 0x3d, DW_TAG_condition = 0x3f, DW_TAG_shared_type = 0x40, - DW_TAG_rvalue_reference_type = 0x41, + DW_TAG_type_unit = 0x41, + DW_TAG_rvalue_reference_type = 0x42, + DW_TAG_template_alias = 0x43, + DW_TAG_MIPS_loop = 0x4081, + DW_TAG_format_label = 0x4101, + DW_TAG_function_template = 0x4102, + DW_TAG_class_template = 0x4103, + DW_TAG_GNU_template_template_param = 0x4106, + DW_TAG_GNU_template_parameter_pack = 0x4107, + DW_TAG_GNU_formal_parameter_pack = 0x4108, DW_TAG_lo_user = 0x4080, DW_TAG_hi_user = 0xffff, @@ -212,14 +223,36 @@ enum dwarf_constants { DW_AT_elemental = 0x66, DW_AT_pure = 0x67, DW_AT_recursive = 0x68, + DW_AT_signature = 0x69, + DW_AT_main_subprogram = 0x6a, + DW_AT_data_bit_offset = 0x6b, + DW_AT_const_expr = 0x6c, + DW_AT_enum_class = 0x6d, + DW_AT_linkage_name = 0x6e, + DW_AT_MIPS_loop_begin = 0x2002, + DW_AT_MIPS_tail_loop_begin = 0x2003, + DW_AT_MIPS_epilog_begin = 0x2004, + DW_AT_MIPS_loop_unroll_factor = 0x2005, + DW_AT_MIPS_software_pipeline_depth = 0x2006, DW_AT_MIPS_linkage_name = 0x2007, - DW_AT_sf_names = 0x2101, + DW_AT_MIPS_stride = 0x2008, + DW_AT_MIPS_abstract_name = 0x2009, + DW_AT_MIPS_clone_origin = 0x200a, + DW_AT_MIPS_has_inlines = 0x200b, + DW_AT_MIPS_stride_byte = 0x200c, + DW_AT_MIPS_stride_elem = 0x200d, + DW_AT_MIPS_ptr_dopetype = 0x200e, + DW_AT_MIPS_allocatable_dopetype = 0x200f, + DW_AT_MIPS_assumed_shape_dopetype = 0x2010, + DW_AT_sf_names = 0x2101, DW_AT_src_info = 0x2102, DW_AT_mac_info = 0x2103, DW_AT_src_coords = 0x2104, DW_AT_body_begin = 0x2105, DW_AT_body_end = 0x2106, DW_AT_GNU_vector = 0x2107, + DW_AT_GNU_template_name = 0x2110, + DW_AT_MIPS_assumed_size = 0x2011, DW_AT_lo_user = 0x2000, DW_AT_hi_user = 0x3fff, @@ -259,6 +292,10 @@ enum dwarf_constants { DW_FORM_ref8 = 0x14, DW_FORM_ref_udata = 0x15, DW_FORM_indirect = 0x16, + DW_FORM_sec_offset = 0x17, + DW_FORM_exprloc = 0x18, + DW_FORM_flag_present = 0x19, + DW_FORM_ref_sig8 = 0x20, // Operation encodings DW_OP_addr = 0x03, @@ -413,6 +450,8 @@ enum dwarf_constants { DW_OP_form_tls_address = 0x9b, DW_OP_call_frame_cfa = 0x9c, DW_OP_bit_piece = 0x9d, + DW_OP_implicit_value = 0x9e, + DW_OP_stack_value = 0x9f, DW_OP_lo_user = 0xe0, DW_OP_hi_user = 0xff, @@ -432,6 +471,7 @@ enum dwarf_constants { DW_ATE_signed_fixed = 0x0d, DW_ATE_unsigned_fixed = 0x0e, DW_ATE_decimal_float = 0x0f, + DW_ATE_UTF = 0x10, DW_ATE_lo_user = 0x80, DW_ATE_hi_user = 0xff, @@ -484,6 +524,7 @@ enum dwarf_constants { DW_LANG_ObjC_plus_plus = 0x0011, DW_LANG_UPC = 0x0012, DW_LANG_D = 0x0013, + DW_LANG_Python = 0x0014, DW_LANG_lo_user = 0x8000, DW_LANG_hi_user = 0xffff, @@ -533,6 +574,7 @@ enum dwarf_constants { DW_LNE_end_sequence = 0x01, DW_LNE_set_address = 0x02, DW_LNE_define_file = 0x03, + DW_LNE_set_discriminator = 0x04, DW_LNE_lo_user = 0x80, DW_LNE_hi_user = 0xff, @@ -571,6 +613,9 @@ enum dwarf_constants { DW_CFA_val_offset = 0x14, DW_CFA_val_offset_sf = 0x15, DW_CFA_val_expression = 0x16, + DW_CFA_MIPS_advance_loc8 = 0x1d, + DW_CFA_GNU_window_save = 0x2d, + DW_CFA_GNU_args_size = 0x2e, DW_CFA_lo_user = 0x1c, DW_CFA_hi_user = 0x3f, diff --git a/contrib/llvm/include/llvm/Support/DynamicLibrary.h b/contrib/llvm/include/llvm/Support/DynamicLibrary.h index e6d9ff57a..288936bc0 100644 --- a/contrib/llvm/include/llvm/Support/DynamicLibrary.h +++ b/contrib/llvm/include/llvm/Support/DynamicLibrary.h @@ -28,36 +28,62 @@ namespace sys { /// It also allows for symbols to be defined which don't live in any library, /// but rather the main program itself, useful on Windows where the main /// executable cannot be searched. + /// + /// Note: there is currently no interface for temporarily loading a library, + /// or for unloading libraries when the LLVM library is unloaded. class DynamicLibrary { - DynamicLibrary(); // DO NOT IMPLEMENT + // Placeholder whose address represents an invalid library. + // We use this instead of NULL or a pointer-int pair because the OS library + // might define 0 or 1 to be "special" handles, such as "search all". + static char Invalid; + + // Opaque data used to interface with OS-specific dynamic library handling. + void *Data; + + explicit DynamicLibrary(void *data = &Invalid) : Data(data) {} public: - /// This function allows a library to be loaded without instantiating a - /// DynamicLibrary object. Consequently, it is marked as being permanent - /// and will only be unloaded when the program terminates. This returns - /// false on success or returns true and fills in *ErrMsg on failure. - /// @brief Open a dynamic library permanently. + /// Returns true if the object refers to a valid library. + bool isValid() { return Data != &Invalid; } + + /// Searches through the library for the symbol \p symbolName. If it is + /// found, the address of that symbol is returned. If not, NULL is returned. + /// Note that NULL will also be returned if the library failed to load. + /// Use isValid() to distinguish these cases if it is important. + /// Note that this will \e not search symbols explicitly registered by + /// AddSymbol(). + void *getAddressOfSymbol(const char *symbolName); + + /// This function permanently loads the dynamic library at the given path. + /// The library will only be unloaded when the program terminates. + /// This returns a valid DynamicLibrary instance on success and an invalid + /// instance on failure (see isValid()). \p *errMsg will only be modified + /// if the library fails to load. /// - /// NOTE: This function is not thread safe. + /// It is safe to call this function multiple times for the same library. + /// @brief Open a dynamic library permanently. + static DynamicLibrary getPermanentLibrary(const char *filename, + std::string *errMsg = 0); + + /// This function permanently loads the dynamic library at the given path. + /// Use this instead of getPermanentLibrary() when you won't need to get + /// symbols from the library itself. /// - static bool LoadLibraryPermanently(const char *filename, - std::string *ErrMsg = 0); + /// It is safe to call this function multiple times for the same library. + static bool LoadLibraryPermanently(const char *Filename, + std::string *ErrMsg = 0) { + return !getPermanentLibrary(Filename, ErrMsg).isValid(); + } /// This function will search through all previously loaded dynamic - /// libraries for the symbol \p symbolName. If it is found, the addressof + /// libraries for the symbol \p symbolName. If it is found, the address of /// that symbol is returned. If not, null is returned. Note that this will - /// search permanently loaded libraries (LoadLibraryPermanently) as well - /// as ephemerally loaded libraries (constructors). + /// search permanently loaded libraries (getPermanentLibrary()) as well + /// as explicitly registered symbols (AddSymbol()). /// @throws std::string on error. /// @brief Search through libraries for address of a symbol - /// - /// NOTE: This function is not thread safe. - /// static void *SearchForAddressOfSymbol(const char *symbolName); /// @brief Convenience function for C++ophiles. - /// - /// NOTE: This function is not thread safe. - /// static void *SearchForAddressOfSymbol(const std::string &symbolName) { return SearchForAddressOfSymbol(symbolName.c_str()); } @@ -66,18 +92,7 @@ namespace sys { /// value \p symbolValue. These symbols are searched before any /// libraries. /// @brief Add searchable symbol/value pair. - /// - /// NOTE: This function is not thread safe. - /// - static void AddSymbol(const char *symbolName, void *symbolValue); - - /// @brief Convenience function for C++ophiles. - /// - /// NOTE: This function is not thread safe. - /// - static void AddSymbol(const std::string &symbolName, void *symbolValue) { - AddSymbol(symbolName.c_str(), symbolValue); - } + static void AddSymbol(StringRef symbolName, void *symbolValue); }; } // End sys namespace diff --git a/contrib/llvm/include/llvm/Support/ELF.h b/contrib/llvm/include/llvm/Support/ELF.h index be48112a9..c5b85e2e6 100644 --- a/contrib/llvm/include/llvm/Support/ELF.h +++ b/contrib/llvm/include/llvm/Support/ELF.h @@ -28,20 +28,18 @@ namespace llvm { namespace ELF { typedef uint32_t Elf32_Addr; // Program address -typedef uint16_t Elf32_Half; typedef uint32_t Elf32_Off; // File offset -typedef int32_t Elf32_Sword; +typedef uint16_t Elf32_Half; typedef uint32_t Elf32_Word; +typedef int32_t Elf32_Sword; typedef uint64_t Elf64_Addr; typedef uint64_t Elf64_Off; -typedef int32_t Elf64_Shalf; -typedef int32_t Elf64_Sword; +typedef uint16_t Elf64_Half; typedef uint32_t Elf64_Word; -typedef int64_t Elf64_Sxword; +typedef int32_t Elf64_Sword; typedef uint64_t Elf64_Xword; -typedef uint32_t Elf64_Half; -typedef uint16_t Elf64_Quarter; +typedef int64_t Elf64_Sxword; // Object file magic string. static const char ElfMagic[] = { 0x7f, 'E', 'L', 'F', '\0' }; @@ -87,19 +85,19 @@ struct Elf32_Ehdr { // types (see above). struct Elf64_Ehdr { unsigned char e_ident[EI_NIDENT]; - Elf64_Quarter e_type; - Elf64_Quarter e_machine; - Elf64_Half e_version; + Elf64_Half e_type; + Elf64_Half e_machine; + Elf64_Word e_version; Elf64_Addr e_entry; Elf64_Off e_phoff; Elf64_Off e_shoff; - Elf64_Half e_flags; - Elf64_Quarter e_ehsize; - Elf64_Quarter e_phentsize; - Elf64_Quarter e_phnum; - Elf64_Quarter e_shentsize; - Elf64_Quarter e_shnum; - Elf64_Quarter e_shstrndx; + Elf64_Word e_flags; + Elf64_Half e_ehsize; + Elf64_Half e_phentsize; + Elf64_Half e_phnum; + Elf64_Half e_shentsize; + Elf64_Half e_shnum; + Elf64_Half e_shstrndx; bool checkMagic() const { return (memcmp(e_ident, ElfMagic, strlen(ElfMagic))) == 0; } @@ -126,22 +124,170 @@ enum { // Machine architectures enum { - EM_NONE = 0, // No machine - EM_M32 = 1, // AT&T WE 32100 - EM_SPARC = 2, // SPARC - EM_386 = 3, // Intel 386 - EM_68K = 4, // Motorola 68000 - EM_88K = 5, // Motorola 88000 - EM_486 = 6, // Intel 486 (deprecated) - EM_860 = 7, // Intel 80860 - EM_MIPS = 8, // MIPS R3000 - EM_PPC = 20, // PowerPC - EM_PPC64 = 21, // PowerPC64 - EM_ARM = 40, // ARM - EM_ALPHA = 41, // DEC Alpha - EM_SPARCV9 = 43, // SPARC V9 - EM_X86_64 = 62, // AMD64 - EM_MBLAZE = 47787 // Xilinx MicroBlaze + EM_NONE = 0, // No machine + EM_M32 = 1, // AT&T WE 32100 + EM_SPARC = 2, // SPARC + EM_386 = 3, // Intel 386 + EM_68K = 4, // Motorola 68000 + EM_88K = 5, // Motorola 88000 + EM_486 = 6, // Intel 486 (deprecated) + EM_860 = 7, // Intel 80860 + EM_MIPS = 8, // MIPS R3000 + EM_S370 = 9, // IBM System/370 + EM_MIPS_RS3_LE = 10, // MIPS RS3000 Little-endian + EM_PARISC = 15, // Hewlett-Packard PA-RISC + EM_VPP500 = 17, // Fujitsu VPP500 + EM_SPARC32PLUS = 18, // Enhanced instruction set SPARC + EM_960 = 19, // Intel 80960 + EM_PPC = 20, // PowerPC + EM_PPC64 = 21, // PowerPC64 + EM_S390 = 22, // IBM System/390 + EM_SPU = 23, // IBM SPU/SPC + EM_V800 = 36, // NEC V800 + EM_FR20 = 37, // Fujitsu FR20 + EM_RH32 = 38, // TRW RH-32 + EM_RCE = 39, // Motorola RCE + EM_ARM = 40, // ARM + EM_ALPHA = 41, // DEC Alpha + EM_SH = 42, // Hitachi SH + EM_SPARCV9 = 43, // SPARC V9 + EM_TRICORE = 44, // Siemens TriCore + EM_ARC = 45, // Argonaut RISC Core + EM_H8_300 = 46, // Hitachi H8/300 + EM_H8_300H = 47, // Hitachi H8/300H + EM_H8S = 48, // Hitachi H8S + EM_H8_500 = 49, // Hitachi H8/500 + EM_IA_64 = 50, // Intel IA-64 processor architecture + EM_MIPS_X = 51, // Stanford MIPS-X + EM_COLDFIRE = 52, // Motorola ColdFire + EM_68HC12 = 53, // Motorola M68HC12 + EM_MMA = 54, // Fujitsu MMA Multimedia Accelerator + EM_PCP = 55, // Siemens PCP + EM_NCPU = 56, // Sony nCPU embedded RISC processor + EM_NDR1 = 57, // Denso NDR1 microprocessor + EM_STARCORE = 58, // Motorola Star*Core processor + EM_ME16 = 59, // Toyota ME16 processor + EM_ST100 = 60, // STMicroelectronics ST100 processor + EM_TINYJ = 61, // Advanced Logic Corp. TinyJ embedded processor family + EM_X86_64 = 62, // AMD x86-64 architecture + EM_PDSP = 63, // Sony DSP Processor + EM_PDP10 = 64, // Digital Equipment Corp. PDP-10 + EM_PDP11 = 65, // Digital Equipment Corp. PDP-11 + EM_FX66 = 66, // Siemens FX66 microcontroller + EM_ST9PLUS = 67, // STMicroelectronics ST9+ 8/16 bit microcontroller + EM_ST7 = 68, // STMicroelectronics ST7 8-bit microcontroller + EM_68HC16 = 69, // Motorola MC68HC16 Microcontroller + EM_68HC11 = 70, // Motorola MC68HC11 Microcontroller + EM_68HC08 = 71, // Motorola MC68HC08 Microcontroller + EM_68HC05 = 72, // Motorola MC68HC05 Microcontroller + EM_SVX = 73, // Silicon Graphics SVx + EM_ST19 = 74, // STMicroelectronics ST19 8-bit microcontroller + EM_VAX = 75, // Digital VAX + EM_CRIS = 76, // Axis Communications 32-bit embedded processor + EM_JAVELIN = 77, // Infineon Technologies 32-bit embedded processor + EM_FIREPATH = 78, // Element 14 64-bit DSP Processor + EM_ZSP = 79, // LSI Logic 16-bit DSP Processor + EM_MMIX = 80, // Donald Knuth's educational 64-bit processor + EM_HUANY = 81, // Harvard University machine-independent object files + EM_PRISM = 82, // SiTera Prism + EM_AVR = 83, // Atmel AVR 8-bit microcontroller + EM_FR30 = 84, // Fujitsu FR30 + EM_D10V = 85, // Mitsubishi D10V + EM_D30V = 86, // Mitsubishi D30V + EM_V850 = 87, // NEC v850 + EM_M32R = 88, // Mitsubishi M32R + EM_MN10300 = 89, // Matsushita MN10300 + EM_MN10200 = 90, // Matsushita MN10200 + EM_PJ = 91, // picoJava + EM_OPENRISC = 92, // OpenRISC 32-bit embedded processor + EM_ARC_COMPACT = 93, // ARC International ARCompact processor (old + // spelling/synonym: EM_ARC_A5) + EM_XTENSA = 94, // Tensilica Xtensa Architecture + EM_VIDEOCORE = 95, // Alphamosaic VideoCore processor + EM_TMM_GPP = 96, // Thompson Multimedia General Purpose Processor + EM_NS32K = 97, // National Semiconductor 32000 series + EM_TPC = 98, // Tenor Network TPC processor + EM_SNP1K = 99, // Trebia SNP 1000 processor + EM_ST200 = 100, // STMicroelectronics (www.st.com) ST200 + EM_IP2K = 101, // Ubicom IP2xxx microcontroller family + EM_MAX = 102, // MAX Processor + EM_CR = 103, // National Semiconductor CompactRISC microprocessor + EM_F2MC16 = 104, // Fujitsu F2MC16 + EM_MSP430 = 105, // Texas Instruments embedded microcontroller msp430 + EM_BLACKFIN = 106, // Analog Devices Blackfin (DSP) processor + EM_SE_C33 = 107, // S1C33 Family of Seiko Epson processors + EM_SEP = 108, // Sharp embedded microprocessor + EM_ARCA = 109, // Arca RISC Microprocessor + EM_UNICORE = 110, // Microprocessor series from PKU-Unity Ltd. and MPRC + // of Peking University + EM_EXCESS = 111, // eXcess: 16/32/64-bit configurable embedded CPU + EM_DXP = 112, // Icera Semiconductor Inc. Deep Execution Processor + EM_ALTERA_NIOS2 = 113, // Altera Nios II soft-core processor + EM_CRX = 114, // National Semiconductor CompactRISC CRX + EM_XGATE = 115, // Motorola XGATE embedded processor + EM_C166 = 116, // Infineon C16x/XC16x processor + EM_M16C = 117, // Renesas M16C series microprocessors + EM_DSPIC30F = 118, // Microchip Technology dsPIC30F Digital Signal + // Controller + EM_CE = 119, // Freescale Communication Engine RISC core + EM_M32C = 120, // Renesas M32C series microprocessors + EM_TSK3000 = 131, // Altium TSK3000 core + EM_RS08 = 132, // Freescale RS08 embedded processor + EM_SHARC = 133, // Analog Devices SHARC family of 32-bit DSP + // processors + EM_ECOG2 = 134, // Cyan Technology eCOG2 microprocessor + EM_SCORE7 = 135, // Sunplus S+core7 RISC processor + EM_DSP24 = 136, // New Japan Radio (NJR) 24-bit DSP Processor + EM_VIDEOCORE3 = 137, // Broadcom VideoCore III processor + EM_LATTICEMICO32 = 138, // RISC processor for Lattice FPGA architecture + EM_SE_C17 = 139, // Seiko Epson C17 family + EM_TI_C6000 = 140, // The Texas Instruments TMS320C6000 DSP family + EM_TI_C2000 = 141, // The Texas Instruments TMS320C2000 DSP family + EM_TI_C5500 = 142, // The Texas Instruments TMS320C55x DSP family + EM_MMDSP_PLUS = 160, // STMicroelectronics 64bit VLIW Data Signal Processor + EM_CYPRESS_M8C = 161, // Cypress M8C microprocessor + EM_R32C = 162, // Renesas R32C series microprocessors + EM_TRIMEDIA = 163, // NXP Semiconductors TriMedia architecture family + EM_QDSP6 = 164, // QUALCOMM DSP6 Processor + EM_8051 = 165, // Intel 8051 and variants + EM_STXP7X = 166, // STMicroelectronics STxP7x family of configurable + // and extensible RISC processors + EM_NDS32 = 167, // Andes Technology compact code size embedded RISC + // processor family + EM_ECOG1 = 168, // Cyan Technology eCOG1X family + EM_ECOG1X = 168, // Cyan Technology eCOG1X family + EM_MAXQ30 = 169, // Dallas Semiconductor MAXQ30 Core Micro-controllers + EM_XIMO16 = 170, // New Japan Radio (NJR) 16-bit DSP Processor + EM_MANIK = 171, // M2000 Reconfigurable RISC Microprocessor + EM_CRAYNV2 = 172, // Cray Inc. NV2 vector architecture + EM_RX = 173, // Renesas RX family + EM_METAG = 174, // Imagination Technologies META processor + // architecture + EM_MCST_ELBRUS = 175, // MCST Elbrus general purpose hardware architecture + EM_ECOG16 = 176, // Cyan Technology eCOG16 family + EM_CR16 = 177, // National Semiconductor CompactRISC CR16 16-bit + // microprocessor + EM_ETPU = 178, // Freescale Extended Time Processing Unit + EM_SLE9X = 179, // Infineon Technologies SLE9X core + EM_L10M = 180, // Intel L10M + EM_K10M = 181, // Intel K10M + EM_AVR32 = 185, // Atmel Corporation 32-bit microprocessor family + EM_STM8 = 186, // STMicroeletronics STM8 8-bit microcontroller + EM_TILE64 = 187, // Tilera TILE64 multicore architecture family + EM_TILEPRO = 188, // Tilera TILEPro multicore architecture family + EM_MICROBLAZE = 189, // Xilinx MicroBlaze 32-bit RISC soft processor core + EM_CUDA = 190, // NVIDIA CUDA architecture + EM_TILEGX = 191, // Tilera TILE-Gx multicore architecture family + EM_CLOUDSHIELD = 192, // CloudShield architecture family + EM_COREA_1ST = 193, // KIPO-KAIST Core-A 1st generation processor family + EM_COREA_2ND = 194, // KIPO-KAIST Core-A 2nd generation processor family + EM_ARC_COMPACT2 = 195, // Synopsys ARCompact V2 + EM_OPEN8 = 196, // Open8 8-bit RISC soft processor core + EM_RL78 = 197, // Renesas RL78 family + EM_VIDEOCORE5 = 198, // Broadcom VideoCore V processor + EM_78KOR = 199, // Renesas 78KOR family + EM_56800EX = 200, // Freescale 56800EX Digital Signal Controller (DSC) + EM_MBLAZE = 47787 // Xilinx MicroBlaze }; // Object file classes. @@ -211,6 +357,11 @@ enum { R_X86_64_PC64 = 24, R_X86_64_GOTOFF64 = 25, R_X86_64_GOTPC32 = 26, + R_X86_64_GOT64 = 27, + R_X86_64_GOTPCREL64 = 28, + R_X86_64_GOTPC64 = 29, + R_X86_64_GOTPLT64 = 30, + R_X86_64_PLTOFF64 = 31, R_X86_64_SIZE32 = 32, R_X86_64_SIZE64 = 33, R_X86_64_GOTPC32_TLSDESC = 34, @@ -290,6 +441,23 @@ enum { R_MICROBLAZE_COPY = 21 }; +enum { + R_PPC_NONE = 0, /* No relocation. */ + R_PPC_ADDR32 = 1, + R_PPC_ADDR24 = 2, + R_PPC_ADDR16 = 3, + R_PPC_ADDR16_LO = 4, + R_PPC_ADDR16_HI = 5, + R_PPC_ADDR16_HA = 6, + R_PPC_ADDR14 = 7, + R_PPC_ADDR14_BRTAKEN = 8, + R_PPC_ADDR14_BRNTAKEN = 9, + R_PPC_REL24 = 10, + R_PPC_REL14 = 11, + R_PPC_REL14_BRTAKEN = 12, + R_PPC_REL14_BRNTAKEN = 13, + R_PPC_REL32 = 26 +}; // ARM Specific e_flags enum { EF_ARM_EABIMASK = 0xFF000000U }; @@ -431,7 +599,61 @@ enum { R_ARM_THM_TLS_DESCSEQ32 = 0x82 }; - +// ELF Relocation types for Mips +enum { + R_MIPS_NONE = 0, + R_MIPS_16 = 1, + R_MIPS_32 = 2, + R_MIPS_REL32 = 3, + R_MIPS_26 = 4, + R_MIPS_HI16 = 5, + R_MIPS_LO16 = 6, + R_MIPS_GPREL16 = 7, + R_MIPS_LITERAL = 8, + R_MIPS_GOT16 = 9, + R_MIPS_PC16 = 10, + R_MIPS_CALL16 = 11, + R_MIPS_GPREL32 = 12, + R_MIPS_SHIFT5 = 16, + R_MIPS_SHIFT6 = 17, + R_MIPS_64 = 18, + R_MIPS_GOT_DISP = 19, + R_MIPS_GOT_PAGE = 20, + R_MIPS_GOT_OFST = 21, + R_MIPS_GOT_HI16 = 22, + R_MIPS_GOT_LO16 = 23, + R_MIPS_SUB = 24, + R_MIPS_INSERT_A = 25, + R_MIPS_INSERT_B = 26, + R_MIPS_DELETE = 27, + R_MIPS_HIGHER = 28, + R_MIPS_HIGHEST = 29, + R_MIPS_CALL_HI16 = 30, + R_MIPS_CALL_LO16 = 31, + R_MIPS_SCN_DISP = 32, + R_MIPS_REL16 = 33, + R_MIPS_ADD_IMMEDIATE = 34, + R_MIPS_PJUMP = 35, + R_MIPS_RELGOT = 36, + R_MIPS_JALR = 37, + R_MIPS_TLS_DTPMOD32 = 38, + R_MIPS_TLS_DTPREL32 = 39, + R_MIPS_TLS_DTPMOD64 = 40, + R_MIPS_TLS_DTPREL64 = 41, + R_MIPS_TLS_GD = 42, + R_MIPS_TLS_LDM = 43, + R_MIPS_TLS_DTPREL_HI16 = 44, + R_MIPS_TLS_DTPREL_LO16 = 45, + R_MIPS_TLS_GOTTPREL = 46, + R_MIPS_TLS_TPREL32 = 47, + R_MIPS_TLS_TPREL64 = 48, + R_MIPS_TLS_TPREL_HI16 = 49, + R_MIPS_TLS_TPREL_LO16 = 50, + R_MIPS_GLOB_DAT = 51, + R_MIPS_COPY = 126, + R_MIPS_JUMP_SLOT = 127, + R_MIPS_NUM = 218 +}; // Section header. struct Elf32_Shdr { @@ -449,14 +671,14 @@ struct Elf32_Shdr { // Section header for ELF64 - same fields as ELF32, different types. struct Elf64_Shdr { - Elf64_Half sh_name; - Elf64_Half sh_type; + Elf64_Word sh_name; + Elf64_Word sh_type; Elf64_Xword sh_flags; Elf64_Addr sh_addr; Elf64_Off sh_offset; Elf64_Xword sh_size; - Elf64_Half sh_link; - Elf64_Half sh_info; + Elf64_Word sh_link; + Elf64_Word sh_info; Elf64_Xword sh_addralign; Elf64_Xword sh_entsize; }; @@ -467,6 +689,8 @@ enum { SHN_LORESERVE = 0xff00, // Lowest reserved index SHN_LOPROC = 0xff00, // Lowest processor-specific index SHN_HIPROC = 0xff1f, // Highest processor-specific index + SHN_LOOS = 0xff20, // Lowest operating system-specific index + SHN_HIOS = 0xff3f, // Highest operating system-specific index SHN_ABS = 0xfff1, // Symbol has absolute value; does not need relocation SHN_COMMON = 0xfff2, // FORTRAN COMMON or C external global variables SHN_XINDEX = 0xffff, // Mark that the index is >= SHN_LORESERVE @@ -557,8 +781,19 @@ enum { /// set to the start of the section by the boot code. XCORE_SHF_DP_SECTION = 0x1000U, + SHF_MASKOS = 0x0ff00000, + // Bits indicating processor-specific flags. - SHF_MASKPROC = 0xf0000000 + SHF_MASKPROC = 0xf0000000, + + // If an object file section does not have this flag set, then it may not hold + // more than 2GB and can be freely referred to in objects using smaller code + // models. Otherwise, only objects using larger code models can refer to them. + // For example, a medium code model object can refer to data in a section that + // sets this flag besides being able to refer to data in a section that does + // not set it; likewise, a small code model object can refer only to code in a + // section that does not set this flag. + SHF_X86_64_LARGE = 0x10000000 }; // Section Group Flags @@ -619,6 +854,8 @@ enum { STB_LOCAL = 0, // Local symbol, not visible outside obj file containing def STB_GLOBAL = 1, // Global symbol, visible to all object files being combined STB_WEAK = 2, // Weak symbol, like global but lower-precedence + STB_LOOS = 10, // Lowest operating system-specific binding type + STB_HIOS = 12, // Highest operating system-specific binding type STB_LOPROC = 13, // Lowest processor-specific binding type STB_HIPROC = 15 // Highest processor-specific binding type }; @@ -632,6 +869,8 @@ enum { STT_FILE = 4, // Local, absolute symbol that refers to a file STT_COMMON = 5, // An uninitialized common block STT_TLS = 6, // Thread local data object + STT_LOOS = 7, // Lowest operating system-specific symbol type + STT_HIOS = 8, // Highest operating system-specific symbol type STT_LOPROC = 13, // Lowest processor-specific symbol type STT_HIPROC = 15 // Highest processor-specific symbol type }; @@ -746,6 +985,16 @@ enum { PT_NOTE = 4, // Auxiliary information. PT_SHLIB = 5, // Reserved. PT_PHDR = 6, // The program header table itself. + PT_TLS = 7, // The thread-local storage template. + PT_LOOS = 0x60000000, // Lowest operating system-specific pt entry type. + + // x86-64 program header types. + // These all contain stack unwind tables. + PT_GNU_EH_FRAME = 0x6474e550, + PT_SUNW_EH_FRAME = 0x6474e550, + PT_SUNW_UNWIND = 0x6464e550, + + PT_HIOS = 0x6fffffff, // Highest operating system-specific pt entry type. PT_LOPROC = 0x70000000, // Lowest processor-specific program hdr entry type. PT_HIPROC = 0x7fffffff // Highest processor-specific program hdr entry type. }; @@ -755,7 +1004,8 @@ enum { PF_X = 1, // Execute PF_W = 2, // Write PF_R = 4, // Read - PF_MASKPROC = 0xf0000000 // Unspecified + PF_MASKOS = 0x0ff00000,// Bits for operating system-specific semantics. + PF_MASKPROC = 0xf0000000 // Bits for processor-specific semantics. }; // Dynamic table entry for ELF32. @@ -811,12 +1061,29 @@ enum { DT_FINI_ARRAY = 26, // Pointer to array of termination functions. DT_INIT_ARRAYSZ = 27, // Size of DT_INIT_ARRAY. DT_FINI_ARRAYSZ = 28, // Size of DT_FINI_ARRAY. + DT_RUNPATH = 29, // String table offset of lib search path. + DT_FLAGS = 30, // Flags. + DT_ENCODING = 32, // Values from here to DT_LOOS follow the rules + // for the interpretation of the d_un union. + + DT_PREINIT_ARRAY = 32, // Pointer to array of preinit functions. + DT_PREINIT_ARRAYSZ = 33, // Size of the DT_PREINIT_ARRAY array. + DT_LOOS = 0x60000000, // Start of environment specific tags. DT_HIOS = 0x6FFFFFFF, // End of environment specific tags. DT_LOPROC = 0x70000000, // Start of processor specific tags. DT_HIPROC = 0x7FFFFFFF // End of processor specific tags. }; +// DT_FLAGS values. +enum { + DF_ORIGIN = 0x01, // The object may reference $ORIGIN. + DF_SYMBOLIC = 0x02, // Search the shared lib before searching the exe. + DF_TEXTREL = 0x04, // Relocations may modify a non-writable segment. + DF_BIND_NOW = 0x08, // Process all relocations on load. + DF_STATIC_TLS = 0x10 // Reject attempts to load dynamically. +}; + } // end namespace ELF } // end namespace llvm diff --git a/contrib/llvm/include/llvm/Support/FileSystem.h b/contrib/llvm/include/llvm/Support/FileSystem.h index 4f013f89e..a868e5f9f 100644 --- a/contrib/llvm/include/llvm/Support/FileSystem.h +++ b/contrib/llvm/include/llvm/Support/FileSystem.h @@ -201,30 +201,6 @@ error_code rename(const Twine &from, const Twine &to); /// platform specific error_code. error_code resize_file(const Twine &path, uint64_t size); -/// @brief Make file readable. -/// -/// @param path Input path. -/// @param value If true, make readable, else, make unreadable. -/// @results errc::success if readability has been successfully set, otherwise a -/// platform specific error_code. -error_code set_read(const Twine &path, bool value); - -/// @brief Make file writeable. -/// -/// @param path Input path. -/// @param value If true, make writeable, else, make unwriteable. -/// @results errc::success if writeability has been successfully set, otherwise -/// a platform specific error_code. -error_code set_write(const Twine &path, bool value); - -/// @brief Make file executable. -/// -/// @param path Input path. -/// @param value If true, make executable, else, make unexecutable. -/// @results errc::success if executability has been successfully set, otherwise -/// a platform specific error_code. -error_code set_execute(const Twine &path, bool value); - /// @} /// @name Physical Observers /// @{ @@ -245,6 +221,13 @@ bool exists(file_status status); /// platform specific error_code. error_code exists(const Twine &path, bool &result); +/// @brief Simpler version of exists for clients that don't need to +/// differentiate between an error and false. +inline bool exists(const Twine &path) { + bool result; + return !exists(path, result) && result; +} + /// @brief Do file_status's represent the same thing? /// /// @param A Input file_status. @@ -289,15 +272,6 @@ bool is_directory(file_status status); /// platform specific error_code. error_code is_directory(const Twine &path, bool &result); -/// @brief Is path an empty file? -/// -/// @param path Input path. -/// @param result Set to true if \a path is a an empty file, false if it is not. -/// Undefined otherwise. -/// @results errc::success if result has been successfully set, otherwise a -/// platform specific error_code. -error_code is_empty(const Twine &path, bool &result); - /// @brief Does status represent a regular file? /// /// @param status A file_status previously returned from status. @@ -346,40 +320,6 @@ bool is_symlink(file_status status); /// platform specific error_code. error_code is_symlink(const Twine &path, bool &result); -/// @brief Get last write time without changing it. -/// -/// @param path Input path. -/// @param result Set to the last write time (UNIX time) of \a path if it -/// exists. -/// @results errc::success if result has been successfully set, otherwise a -/// platform specific error_code. -error_code last_write_time(const Twine &path, std::time_t &result); - -/// @brief Set last write time. -/// -/// @param path Input path. -/// @param value Time to set (UNIX time) \a path's last write time to. -/// @results errc::success if result has been successfully set, otherwise a -/// platform specific error_code. -error_code set_last_write_time(const Twine &path, std::time_t value); - -/// @brief Read a symlink's value. -/// -/// @param path Input path. -/// @param result Set to the value of the symbolic link \a path. -/// @results errc::success if result has been successfully set, otherwise a -/// platform specific error_code. -error_code read_symlink(const Twine &path, SmallVectorImpl &result); - -/// @brief Get disk space usage information. -/// -/// @param path Input path. -/// @param result Set to the capacity, free, and available space on the device -/// \a path is on. -/// @results errc::success if result has been successfully set, otherwise a -/// platform specific error_code. -error_code disk_space(const Twine &path, space_info &result); - /// @brief Get file status as if by POSIX stat(). /// /// @param path Input path. @@ -402,16 +342,6 @@ bool status_known(file_status s); /// platform specific error_code. error_code status_known(const Twine &path, bool &result); -/// @brief Get file status as if by POSIX lstat(). -/// -/// Does not resolve symlinks. -/// -/// @param path Input path. -/// @param result Set to the file status. -/// @results errc::success if result has been successfully set, otherwise a -/// platform specific error_code. -error_code symlink_status(const Twine &path, file_status &result); - /// @brief Generate a unique path and open it as a file. /// /// Generates a unique path suitable for a temporary file and then opens it as a @@ -427,10 +357,13 @@ error_code symlink_status(const Twine &path, file_status &result); /// @param model Name to base unique path off of. /// @param result_fs Set to the opened file's file descriptor. /// @param result_path Set to the opened file's absolute path. +/// @param makeAbsolute If true and @model is not an absolute path, a temp +/// directory will be prepended. /// @results errc::success if result_{fd,path} have been successfully set, /// otherwise a platform specific error_code. error_code unique_file(const Twine &model, int &result_fd, - SmallVectorImpl &result_path); + SmallVectorImpl &result_path, + bool makeAbsolute = true); /// @brief Canonicalize path. /// @@ -472,60 +405,6 @@ error_code get_magic(const Twine &path, uint32_t len, /// platform specific error_code. error_code identify_magic(const Twine &path, LLVMFileType &result); -/// @brief Is file bitcode? -/// -/// @param path Input path. -/// @param result Set to true if \a path is a bitcode file, false if it is not, -/// undefined otherwise. -/// @results errc::success if result has been successfully set, otherwise a -/// platform specific error_code. -error_code is_bitcode(const Twine &path, bool &result); - -/// @brief Is file a dynamic library? -/// -/// @param path Input path. -/// @param result Set to true if \a path is a dynamic library, false if it is -/// not, undefined otherwise. -/// @results errc::success if result has been successfully set, otherwise a -/// platform specific error_code. -error_code is_dynamic_library(const Twine &path, bool &result); - -/// @brief Is an object file? -/// -/// @param path Input path. -/// @param result Set to true if \a path is an object file, false if it is not, -/// undefined otherwise. -/// @results errc::success if result has been successfully set, otherwise a -/// platform specific error_code. -error_code is_object_file(const Twine &path, bool &result); - -/// @brief Can file be read? -/// -/// @param path Input path. -/// @param result Set to true if \a path is readable, false it it is not, -/// undefined otherwise. -/// @results errc::success if result has been successfully set, otherwise a -/// platform specific error_code. -error_code can_read(const Twine &path, bool &result); - -/// @brief Can file be written? -/// -/// @param path Input path. -/// @param result Set to true if \a path is writeable, false it it is not, -/// undefined otherwise. -/// @results errc::success if result has been successfully set, otherwise a -/// platform specific error_code. -error_code can_write(const Twine &path, bool &result); - -/// @brief Can file be executed? -/// -/// @param path Input path. -/// @param result Set to true if \a path is executable, false it it is not, -/// undefined otherwise. -/// @results errc::success if result has been successfully set, otherwise a -/// platform specific error_code. -error_code can_execute(const Twine &path, bool &result); - /// @brief Get library paths the system linker uses. /// /// @param result Set to the list of system library paths. @@ -569,35 +448,28 @@ error_code GetMainExecutable(const char *argv0, void *MainAddr, /// @{ /// directory_entry - A single entry in a directory. Caches the status either -/// from the result of the iteration syscall, or the first time status or -/// symlink_status is called. +/// from the result of the iteration syscall, or the first time status is +/// called. class directory_entry { std::string Path; mutable file_status Status; - mutable file_status SymlinkStatus; public: - explicit directory_entry(const Twine &path, file_status st = file_status(), - file_status symlink_st = file_status()) + explicit directory_entry(const Twine &path, file_status st = file_status()) : Path(path.str()) - , Status(st) - , SymlinkStatus(symlink_st) {} + , Status(st) {} directory_entry() {} - void assign(const Twine &path, file_status st = file_status(), - file_status symlink_st = file_status()) { + void assign(const Twine &path, file_status st = file_status()) { Path = path.str(); Status = st; - SymlinkStatus = symlink_st; } - void replace_filename(const Twine &filename, file_status st = file_status(), - file_status symlink_st = file_status()); + void replace_filename(const Twine &filename, file_status st = file_status()); const std::string &path() const { return Path; } error_code status(file_status &result) const; - error_code symlink_status(file_status &result) const; bool operator==(const directory_entry& rhs) const { return Path == rhs.Path; } bool operator!=(const directory_entry& rhs) const { return !(*this == rhs); } diff --git a/contrib/llvm/include/llvm/Support/Format.h b/contrib/llvm/include/llvm/Support/Format.h index f64e3db7d..59812d98f 100644 --- a/contrib/llvm/include/llvm/Support/Format.h +++ b/contrib/llvm/include/llvm/Support/Format.h @@ -126,6 +126,50 @@ public: } }; +/// format_object4 - This is a templated helper class used by the format +/// function that captures the object to be formated and the format string. When +/// actually printed, this synthesizes the string into a temporary buffer +/// provided and returns whether or not it is big enough. +template +class format_object4 : public format_object_base { + T1 Val1; + T2 Val2; + T3 Val3; + T4 Val4; +public: + format_object4(const char *fmt, const T1 &val1, const T2 &val2, + const T3 &val3, const T4 &val4) + : format_object_base(fmt), Val1(val1), Val2(val2), Val3(val3), Val4(val4) { + } + + virtual int snprint(char *Buffer, unsigned BufferSize) const { + return snprintf(Buffer, BufferSize, Fmt, Val1, Val2, Val3, Val4); + } +}; + +/// format_object5 - This is a templated helper class used by the format +/// function that captures the object to be formated and the format string. When +/// actually printed, this synthesizes the string into a temporary buffer +/// provided and returns whether or not it is big enough. +template +class format_object5 : public format_object_base { + T1 Val1; + T2 Val2; + T3 Val3; + T4 Val4; + T5 Val5; +public: + format_object5(const char *fmt, const T1 &val1, const T2 &val2, + const T3 &val3, const T4 &val4, const T5 &val5) + : format_object_base(fmt), Val1(val1), Val2(val2), Val3(val3), Val4(val4), + Val5(val5) { + } + + virtual int snprint(char *Buffer, unsigned BufferSize) const { + return snprintf(Buffer, BufferSize, Fmt, Val1, Val2, Val3, Val4, Val5); + } +}; + /// format - This is a helper function that is used to produce formatted output. /// This is typically used like: OS << format("%0.4f", myfloat) << '\n'; template @@ -149,6 +193,24 @@ template return format_object3(Fmt, Val1, Val2, Val3); } +/// format - This is a helper function that is used to produce formatted output. +/// This is typically used like: OS << format("%0.4f", myfloat) << '\n'; +template +inline format_object4 format(const char *Fmt, const T1 &Val1, + const T2 &Val2, const T3 &Val3, + const T4 &Val4) { + return format_object4(Fmt, Val1, Val2, Val3, Val4); +} + +/// format - This is a helper function that is used to produce formatted output. +/// This is typically used like: OS << format("%0.4f", myfloat) << '\n'; +template +inline format_object5 format(const char *Fmt,const T1 &Val1, + const T2 &Val2, const T3 &Val3, + const T4 &Val4, const T5 &Val5) { + return format_object5(Fmt, Val1, Val2, Val3, Val4, Val5); +} + } // end namespace llvm #endif diff --git a/contrib/llvm/include/llvm/Support/GCOV.h b/contrib/llvm/include/llvm/Support/GCOV.h new file mode 100644 index 000000000..49cd87fc7 --- /dev/null +++ b/contrib/llvm/include/llvm/Support/GCOV.h @@ -0,0 +1,224 @@ +//===-- llvm/Support/GCOV.h - LLVM coverage tool ----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header provides the interface to read and write coverage files that +// use 'gcov' format. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_GCOV_H +#define LLVM_GCOV_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/raw_ostream.h" + +namespace llvm { + +class GCOVFunction; +class GCOVBlock; +class GCOVLines; +class FileInfo; + +enum GCOVFormat { + InvalidGCOV, + GCNO_402, + GCNO_404, + GCDA_402, + GCDA_404 +}; + +/// GCOVBuffer - A wrapper around MemoryBuffer to provide GCOV specific +/// read operations. +class GCOVBuffer { +public: + GCOVBuffer(MemoryBuffer *B) : Buffer(B), Cursor(0) {} + + /// readGCOVFormat - Read GCOV signature at the beginning of buffer. + enum GCOVFormat readGCOVFormat() { + StringRef Magic = Buffer->getBuffer().slice(0, 12); + Cursor = 12; + if (Magic == "oncg*404MVLL") + return GCNO_404; + else if (Magic == "oncg*204MVLL") + return GCNO_402; + else if (Magic == "adcg*404MVLL") + return GCDA_404; + else if (Magic == "adcg*204MVLL") + return GCDA_402; + + Cursor = 0; + return InvalidGCOV; + } + + /// readFunctionTag - If cursor points to a function tag then increment the + /// cursor and return true otherwise return false. + bool readFunctionTag() { + StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4); + if (Tag.empty() || + Tag[0] != '\0' || Tag[1] != '\0' || + Tag[2] != '\0' || Tag[3] != '\1') { + return false; + } + Cursor += 4; + return true; + } + + /// readBlockTag - If cursor points to a block tag then increment the + /// cursor and return true otherwise return false. + bool readBlockTag() { + StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4); + if (Tag.empty() || + Tag[0] != '\0' || Tag[1] != '\0' || + Tag[2] != '\x41' || Tag[3] != '\x01') { + return false; + } + Cursor += 4; + return true; + } + + /// readEdgeTag - If cursor points to an edge tag then increment the + /// cursor and return true otherwise return false. + bool readEdgeTag() { + StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4); + if (Tag.empty() || + Tag[0] != '\0' || Tag[1] != '\0' || + Tag[2] != '\x43' || Tag[3] != '\x01') { + return false; + } + Cursor += 4; + return true; + } + + /// readLineTag - If cursor points to a line tag then increment the + /// cursor and return true otherwise return false. + bool readLineTag() { + StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4); + if (Tag.empty() || + Tag[0] != '\0' || Tag[1] != '\0' || + Tag[2] != '\x45' || Tag[3] != '\x01') { + return false; + } + Cursor += 4; + return true; + } + + /// readArcTag - If cursor points to an gcda arc tag then increment the + /// cursor and return true otherwise return false. + bool readArcTag() { + StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4); + if (Tag.empty() || + Tag[0] != '\0' || Tag[1] != '\0' || + Tag[2] != '\xa1' || Tag[3] != '\1') { + return false; + } + Cursor += 4; + return true; + } + + uint32_t readInt() { + uint32_t Result; + StringRef Str = Buffer->getBuffer().slice(Cursor, Cursor+4); + assert (Str.empty() == false && "Unexpected memory buffer end!"); + Cursor += 4; + Result = *(uint32_t *)(Str.data()); + return Result; + } + + uint64_t readInt64() { + uint64_t Lo = readInt(); + uint64_t Hi = readInt(); + uint64_t Result = Lo | (Hi << 32); + return Result; + } + + StringRef readString() { + uint32_t Len = readInt() * 4; + StringRef Str = Buffer->getBuffer().slice(Cursor, Cursor+Len); + Cursor += Len; + return Str; + } + + uint64_t getCursor() const { return Cursor; } +private: + MemoryBuffer *Buffer; + uint64_t Cursor; +}; + +/// GCOVFile - Collects coverage information for one pair of coverage file +/// (.gcno and .gcda). +class GCOVFile { +public: + GCOVFile() {} + ~GCOVFile(); + bool read(GCOVBuffer &Buffer); + void dump(); + void collectLineCounts(FileInfo &FI); +private: + SmallVector Functions; +}; + +/// GCOVFunction - Collects function information. +class GCOVFunction { +public: + GCOVFunction() : Ident(0), LineNumber(0) {} + ~GCOVFunction(); + bool read(GCOVBuffer &Buffer, GCOVFormat Format); + void dump(); + void collectLineCounts(FileInfo &FI); +private: + uint32_t Ident; + uint32_t LineNumber; + StringRef Name; + StringRef Filename; + SmallVector Blocks; +}; + +/// GCOVBlock - Collects block information. +class GCOVBlock { +public: + GCOVBlock(uint32_t N) : Number(N), Counter(0) {} + ~GCOVBlock(); + void addEdge(uint32_t N) { Edges.push_back(N); } + void addLine(StringRef Filename, uint32_t LineNo); + void addCount(uint64_t N) { Counter = N; } + void dump(); + void collectLineCounts(FileInfo &FI); +private: + uint32_t Number; + uint64_t Counter; + SmallVector Edges; + StringMap Lines; +}; + +/// GCOVLines - A wrapper around a vector of int to keep track of line nos. +class GCOVLines { +public: + ~GCOVLines() { Lines.clear(); } + void add(uint32_t N) { Lines.push_back(N); } + void collectLineCounts(FileInfo &FI, StringRef Filename, uint32_t Count); + void dump(); + +private: + SmallVector Lines; +}; + +typedef SmallVector LineCounts; +class FileInfo { +public: + void addLineCount(StringRef Filename, uint32_t Line, uint32_t Count); + void print(); +private: + StringMap LineInfo; +}; + +} + +#endif diff --git a/contrib/llvm/include/llvm/Support/GetElementPtrTypeIterator.h b/contrib/llvm/include/llvm/Support/GetElementPtrTypeIterator.h index e5e7fc740..ef92c95ee 100644 --- a/contrib/llvm/include/llvm/Support/GetElementPtrTypeIterator.h +++ b/contrib/llvm/include/llvm/Support/GetElementPtrTypeIterator.h @@ -21,16 +21,16 @@ namespace llvm { template class generic_gep_type_iterator - : public std::iterator { + : public std::iterator { typedef std::iterator super; + Type *, ptrdiff_t> super; ItTy OpIt; - const Type *CurTy; + Type *CurTy; generic_gep_type_iterator() {} public: - static generic_gep_type_iterator begin(const Type *Ty, ItTy It) { + static generic_gep_type_iterator begin(Type *Ty, ItTy It) { generic_gep_type_iterator I; I.CurTy = Ty; I.OpIt = It; @@ -50,23 +50,23 @@ namespace llvm { return !operator==(x); } - const Type *operator*() const { + Type *operator*() const { return CurTy; } - const Type *getIndexedType() const { - const CompositeType *CT = cast(CurTy); + Type *getIndexedType() const { + CompositeType *CT = cast(CurTy); return CT->getTypeAtIndex(getOperand()); } // This is a non-standard operator->. It allows you to call methods on the // current type directly. - const Type *operator->() const { return operator*(); } + Type *operator->() const { return operator*(); } Value *getOperand() const { return *OpIt; } generic_gep_type_iterator& operator++() { // Preincrement - if (const CompositeType *CT = dyn_cast(CurTy)) { + if (CompositeType *CT = dyn_cast(CurTy)) { CurTy = CT->getTypeAtIndex(getOperand()); } else { CurTy = 0; @@ -97,16 +97,16 @@ namespace llvm { return gep_type_iterator::end(GEP.op_end()); } - template - inline generic_gep_type_iterator - gep_type_begin(const Type *Op0, ItTy I, ItTy E) { - return generic_gep_type_iterator::begin(Op0, I); + template + inline generic_gep_type_iterator + gep_type_begin(Type *Op0, ArrayRef A) { + return generic_gep_type_iterator::begin(Op0, A.begin()); } - template - inline generic_gep_type_iterator - gep_type_end(const Type *Op0, ItTy I, ItTy E) { - return generic_gep_type_iterator::end(E); + template + inline generic_gep_type_iterator + gep_type_end(Type *Op0, ArrayRef A) { + return generic_gep_type_iterator::end(A.end()); } } // end namespace llvm diff --git a/contrib/llvm/include/llvm/Support/IRBuilder.h b/contrib/llvm/include/llvm/Support/IRBuilder.h index 91cd78e7f..782800173 100644 --- a/contrib/llvm/include/llvm/Support/IRBuilder.h +++ b/contrib/llvm/include/llvm/Support/IRBuilder.h @@ -475,8 +475,8 @@ public: Name); } - UnwindInst *CreateUnwind() { - return Insert(new UnwindInst(Context)); + ResumeInst *CreateResume(Value *Exn) { + return Insert(ResumeInst::Create(Exn)); } UnreachableInst *CreateUnreachable() { @@ -744,7 +744,7 @@ public: // Instruction creation methods: Memory Instructions //===--------------------------------------------------------------------===// - AllocaInst *CreateAlloca(const Type *Ty, Value *ArraySize = 0, + AllocaInst *CreateAlloca(Type *Ty, Value *ArraySize = 0, const Twine &Name = "") { return Insert(new AllocaInst(Ty, ArraySize), Name); } @@ -762,71 +762,74 @@ public: StoreInst *CreateStore(Value *Val, Value *Ptr, bool isVolatile = false) { return Insert(new StoreInst(Val, Ptr, isVolatile)); } - template - Value *CreateGEP(Value *Ptr, - RandomAccessIterator IdxBegin, - RandomAccessIterator IdxEnd, + FenceInst *CreateFence(AtomicOrdering Ordering, + SynchronizationScope SynchScope = CrossThread) { + return Insert(new FenceInst(Context, Ordering, SynchScope)); + } + AtomicCmpXchgInst *CreateAtomicCmpXchg(Value *Ptr, Value *Cmp, Value *New, + AtomicOrdering Ordering, + SynchronizationScope SynchScope = CrossThread) { + return Insert(new AtomicCmpXchgInst(Ptr, Cmp, New, Ordering, SynchScope)); + } + AtomicRMWInst *CreateAtomicRMW(AtomicRMWInst::BinOp Op, Value *Ptr, Value *Val, + AtomicOrdering Ordering, + SynchronizationScope SynchScope = CrossThread) { + return Insert(new AtomicRMWInst(Op, Ptr, Val, Ordering, SynchScope)); + } + Value *CreateGEP(Value *Ptr, ArrayRef IdxList, const Twine &Name = "") { if (Constant *PC = dyn_cast(Ptr)) { // Every index must be constant. - RandomAccessIterator i; - for (i = IdxBegin; i < IdxEnd; ++i) - if (!isa(*i)) + size_t i, e; + for (i = 0, e = IdxList.size(); i != e; ++i) + if (!isa(IdxList[i])) break; - if (i == IdxEnd) - return Insert(Folder.CreateGetElementPtr(PC, &IdxBegin[0], - IdxEnd - IdxBegin), - Name); + if (i == e) + return Insert(Folder.CreateGetElementPtr(PC, IdxList), Name); } - return Insert(GetElementPtrInst::Create(Ptr, IdxBegin, IdxEnd), Name); + return Insert(GetElementPtrInst::Create(Ptr, IdxList), Name); } - template - Value *CreateInBoundsGEP(Value *Ptr, RandomAccessIterator IdxBegin, - RandomAccessIterator IdxEnd, + Value *CreateInBoundsGEP(Value *Ptr, ArrayRef IdxList, const Twine &Name = "") { if (Constant *PC = dyn_cast(Ptr)) { // Every index must be constant. - RandomAccessIterator i; - for (i = IdxBegin; i < IdxEnd; ++i) - if (!isa(*i)) + size_t i, e; + for (i = 0, e = IdxList.size(); i != e; ++i) + if (!isa(IdxList[i])) break; - if (i == IdxEnd) - return Insert(Folder.CreateInBoundsGetElementPtr(PC, - &IdxBegin[0], - IdxEnd - IdxBegin), - Name); + if (i == e) + return Insert(Folder.CreateInBoundsGetElementPtr(PC, IdxList), Name); } - return Insert(GetElementPtrInst::CreateInBounds(Ptr, IdxBegin, IdxEnd), - Name); + return Insert(GetElementPtrInst::CreateInBounds(Ptr, IdxList), Name); } Value *CreateGEP(Value *Ptr, Value *Idx, const Twine &Name = "") { if (Constant *PC = dyn_cast(Ptr)) if (Constant *IC = dyn_cast(Idx)) - return Insert(Folder.CreateGetElementPtr(PC, &IC, 1), Name); + return Insert(Folder.CreateGetElementPtr(PC, IC), Name); return Insert(GetElementPtrInst::Create(Ptr, Idx), Name); } Value *CreateInBoundsGEP(Value *Ptr, Value *Idx, const Twine &Name = "") { if (Constant *PC = dyn_cast(Ptr)) if (Constant *IC = dyn_cast(Idx)) - return Insert(Folder.CreateInBoundsGetElementPtr(PC, &IC, 1), Name); + return Insert(Folder.CreateInBoundsGetElementPtr(PC, IC), Name); return Insert(GetElementPtrInst::CreateInBounds(Ptr, Idx), Name); } Value *CreateConstGEP1_32(Value *Ptr, unsigned Idx0, const Twine &Name = "") { Value *Idx = ConstantInt::get(Type::getInt32Ty(Context), Idx0); if (Constant *PC = dyn_cast(Ptr)) - return Insert(Folder.CreateGetElementPtr(PC, &Idx, 1), Name); + return Insert(Folder.CreateGetElementPtr(PC, Idx), Name); - return Insert(GetElementPtrInst::Create(Ptr, &Idx, &Idx+1), Name); + return Insert(GetElementPtrInst::Create(Ptr, Idx), Name); } Value *CreateConstInBoundsGEP1_32(Value *Ptr, unsigned Idx0, const Twine &Name = "") { Value *Idx = ConstantInt::get(Type::getInt32Ty(Context), Idx0); if (Constant *PC = dyn_cast(Ptr)) - return Insert(Folder.CreateInBoundsGetElementPtr(PC, &Idx, 1), Name); + return Insert(Folder.CreateInBoundsGetElementPtr(PC, Idx), Name); - return Insert(GetElementPtrInst::CreateInBounds(Ptr, &Idx, &Idx+1), Name); + return Insert(GetElementPtrInst::CreateInBounds(Ptr, Idx), Name); } Value *CreateConstGEP2_32(Value *Ptr, unsigned Idx0, unsigned Idx1, const Twine &Name = "") { @@ -836,9 +839,9 @@ public: }; if (Constant *PC = dyn_cast(Ptr)) - return Insert(Folder.CreateGetElementPtr(PC, Idxs, 2), Name); + return Insert(Folder.CreateGetElementPtr(PC, Idxs), Name); - return Insert(GetElementPtrInst::Create(Ptr, Idxs, Idxs+2), Name); + return Insert(GetElementPtrInst::Create(Ptr, Idxs), Name); } Value *CreateConstInBoundsGEP2_32(Value *Ptr, unsigned Idx0, unsigned Idx1, const Twine &Name = "") { @@ -848,26 +851,26 @@ public: }; if (Constant *PC = dyn_cast(Ptr)) - return Insert(Folder.CreateInBoundsGetElementPtr(PC, Idxs, 2), Name); + return Insert(Folder.CreateInBoundsGetElementPtr(PC, Idxs), Name); - return Insert(GetElementPtrInst::CreateInBounds(Ptr, Idxs, Idxs+2), Name); + return Insert(GetElementPtrInst::CreateInBounds(Ptr, Idxs), Name); } Value *CreateConstGEP1_64(Value *Ptr, uint64_t Idx0, const Twine &Name = "") { Value *Idx = ConstantInt::get(Type::getInt64Ty(Context), Idx0); if (Constant *PC = dyn_cast(Ptr)) - return Insert(Folder.CreateGetElementPtr(PC, &Idx, 1), Name); + return Insert(Folder.CreateGetElementPtr(PC, Idx), Name); - return Insert(GetElementPtrInst::Create(Ptr, &Idx, &Idx+1), Name); + return Insert(GetElementPtrInst::Create(Ptr, Idx), Name); } Value *CreateConstInBoundsGEP1_64(Value *Ptr, uint64_t Idx0, const Twine &Name = "") { Value *Idx = ConstantInt::get(Type::getInt64Ty(Context), Idx0); if (Constant *PC = dyn_cast(Ptr)) - return Insert(Folder.CreateInBoundsGetElementPtr(PC, &Idx, 1), Name); + return Insert(Folder.CreateInBoundsGetElementPtr(PC, Idx), Name); - return Insert(GetElementPtrInst::CreateInBounds(Ptr, &Idx, &Idx+1), Name); + return Insert(GetElementPtrInst::CreateInBounds(Ptr, Idx), Name); } Value *CreateConstGEP2_64(Value *Ptr, uint64_t Idx0, uint64_t Idx1, const Twine &Name = "") { @@ -877,9 +880,9 @@ public: }; if (Constant *PC = dyn_cast(Ptr)) - return Insert(Folder.CreateGetElementPtr(PC, Idxs, 2), Name); + return Insert(Folder.CreateGetElementPtr(PC, Idxs), Name); - return Insert(GetElementPtrInst::Create(Ptr, Idxs, Idxs+2), Name); + return Insert(GetElementPtrInst::Create(Ptr, Idxs), Name); } Value *CreateConstInBoundsGEP2_64(Value *Ptr, uint64_t Idx0, uint64_t Idx1, const Twine &Name = "") { @@ -889,9 +892,9 @@ public: }; if (Constant *PC = dyn_cast(Ptr)) - return Insert(Folder.CreateInBoundsGetElementPtr(PC, Idxs, 2), Name); + return Insert(Folder.CreateInBoundsGetElementPtr(PC, Idxs), Name); - return Insert(GetElementPtrInst::CreateInBounds(Ptr, Idxs, Idxs+2), Name); + return Insert(GetElementPtrInst::CreateInBounds(Ptr, Idxs), Name); } Value *CreateStructGEP(Value *Ptr, unsigned Idx, const Twine &Name = "") { return CreateConstInBoundsGEP2_32(Ptr, 0, Idx, Name); @@ -903,54 +906,54 @@ public: Value *gv = CreateGlobalString(Str, Name); Value *zero = ConstantInt::get(Type::getInt32Ty(Context), 0); Value *Args[] = { zero, zero }; - return CreateInBoundsGEP(gv, Args, Args+2, Name); + return CreateInBoundsGEP(gv, Args, Name); } //===--------------------------------------------------------------------===// // Instruction creation methods: Cast/Conversion Operators //===--------------------------------------------------------------------===// - Value *CreateTrunc(Value *V, const Type *DestTy, const Twine &Name = "") { + Value *CreateTrunc(Value *V, Type *DestTy, const Twine &Name = "") { return CreateCast(Instruction::Trunc, V, DestTy, Name); } - Value *CreateZExt(Value *V, const Type *DestTy, const Twine &Name = "") { + Value *CreateZExt(Value *V, Type *DestTy, const Twine &Name = "") { return CreateCast(Instruction::ZExt, V, DestTy, Name); } - Value *CreateSExt(Value *V, const Type *DestTy, const Twine &Name = "") { + Value *CreateSExt(Value *V, Type *DestTy, const Twine &Name = "") { return CreateCast(Instruction::SExt, V, DestTy, Name); } - Value *CreateFPToUI(Value *V, const Type *DestTy, const Twine &Name = ""){ + Value *CreateFPToUI(Value *V, Type *DestTy, const Twine &Name = ""){ return CreateCast(Instruction::FPToUI, V, DestTy, Name); } - Value *CreateFPToSI(Value *V, const Type *DestTy, const Twine &Name = ""){ + Value *CreateFPToSI(Value *V, Type *DestTy, const Twine &Name = ""){ return CreateCast(Instruction::FPToSI, V, DestTy, Name); } - Value *CreateUIToFP(Value *V, const Type *DestTy, const Twine &Name = ""){ + Value *CreateUIToFP(Value *V, Type *DestTy, const Twine &Name = ""){ return CreateCast(Instruction::UIToFP, V, DestTy, Name); } - Value *CreateSIToFP(Value *V, const Type *DestTy, const Twine &Name = ""){ + Value *CreateSIToFP(Value *V, Type *DestTy, const Twine &Name = ""){ return CreateCast(Instruction::SIToFP, V, DestTy, Name); } - Value *CreateFPTrunc(Value *V, const Type *DestTy, + Value *CreateFPTrunc(Value *V, Type *DestTy, const Twine &Name = "") { return CreateCast(Instruction::FPTrunc, V, DestTy, Name); } - Value *CreateFPExt(Value *V, const Type *DestTy, const Twine &Name = "") { + Value *CreateFPExt(Value *V, Type *DestTy, const Twine &Name = "") { return CreateCast(Instruction::FPExt, V, DestTy, Name); } - Value *CreatePtrToInt(Value *V, const Type *DestTy, + Value *CreatePtrToInt(Value *V, Type *DestTy, const Twine &Name = "") { return CreateCast(Instruction::PtrToInt, V, DestTy, Name); } - Value *CreateIntToPtr(Value *V, const Type *DestTy, + Value *CreateIntToPtr(Value *V, Type *DestTy, const Twine &Name = "") { return CreateCast(Instruction::IntToPtr, V, DestTy, Name); } - Value *CreateBitCast(Value *V, const Type *DestTy, + Value *CreateBitCast(Value *V, Type *DestTy, const Twine &Name = "") { return CreateCast(Instruction::BitCast, V, DestTy, Name); } - Value *CreateZExtOrBitCast(Value *V, const Type *DestTy, + Value *CreateZExtOrBitCast(Value *V, Type *DestTy, const Twine &Name = "") { if (V->getType() == DestTy) return V; @@ -958,7 +961,7 @@ public: return Insert(Folder.CreateZExtOrBitCast(VC, DestTy), Name); return Insert(CastInst::CreateZExtOrBitCast(V, DestTy), Name); } - Value *CreateSExtOrBitCast(Value *V, const Type *DestTy, + Value *CreateSExtOrBitCast(Value *V, Type *DestTy, const Twine &Name = "") { if (V->getType() == DestTy) return V; @@ -966,7 +969,7 @@ public: return Insert(Folder.CreateSExtOrBitCast(VC, DestTy), Name); return Insert(CastInst::CreateSExtOrBitCast(V, DestTy), Name); } - Value *CreateTruncOrBitCast(Value *V, const Type *DestTy, + Value *CreateTruncOrBitCast(Value *V, Type *DestTy, const Twine &Name = "") { if (V->getType() == DestTy) return V; @@ -974,7 +977,7 @@ public: return Insert(Folder.CreateTruncOrBitCast(VC, DestTy), Name); return Insert(CastInst::CreateTruncOrBitCast(V, DestTy), Name); } - Value *CreateCast(Instruction::CastOps Op, Value *V, const Type *DestTy, + Value *CreateCast(Instruction::CastOps Op, Value *V, Type *DestTy, const Twine &Name = "") { if (V->getType() == DestTy) return V; @@ -982,7 +985,7 @@ public: return Insert(Folder.CreateCast(Op, VC, DestTy), Name); return Insert(CastInst::Create(Op, V, DestTy), Name); } - Value *CreatePointerCast(Value *V, const Type *DestTy, + Value *CreatePointerCast(Value *V, Type *DestTy, const Twine &Name = "") { if (V->getType() == DestTy) return V; @@ -990,7 +993,7 @@ public: return Insert(Folder.CreatePointerCast(VC, DestTy), Name); return Insert(CastInst::CreatePointerCast(V, DestTy), Name); } - Value *CreateIntCast(Value *V, const Type *DestTy, bool isSigned, + Value *CreateIntCast(Value *V, Type *DestTy, bool isSigned, const Twine &Name = "") { if (V->getType() == DestTy) return V; @@ -1001,9 +1004,9 @@ public: private: // Provided to resolve 'CreateIntCast(Ptr, Ptr, "...")', giving a compile time // error, instead of converting the string to bool for the isSigned parameter. - Value *CreateIntCast(Value *, const Type *, const char *); // DO NOT IMPLEMENT + Value *CreateIntCast(Value *, Type *, const char *); // DO NOT IMPLEMENT public: - Value *CreateFPCast(Value *V, const Type *DestTy, const Twine &Name = "") { + Value *CreateFPCast(Value *V, Type *DestTy, const Twine &Name = "") { if (V->getType() == DestTy) return V; if (Constant *VC = dyn_cast(V)) @@ -1108,7 +1111,7 @@ public: // Instruction creation methods: Other Instructions //===--------------------------------------------------------------------===// - PHINode *CreatePHI(const Type *Ty, unsigned NumReservedValues, + PHINode *CreatePHI(Type *Ty, unsigned NumReservedValues, const Twine &Name = "") { return Insert(PHINode::Create(Ty, NumReservedValues), Name); } @@ -1142,7 +1145,7 @@ public: CallInst *CreateCall(Value *Callee, ArrayRef Args, const Twine &Name = "") { - return Insert(CallInst::Create(Callee, Args, Name)); + return Insert(CallInst::Create(Callee, Args), Name); } Value *CreateSelect(Value *C, Value *True, Value *False, @@ -1154,7 +1157,7 @@ public: return Insert(SelectInst::Create(C, True, False), Name); } - VAArgInst *CreateVAArg(Value *List, const Type *Ty, const Twine &Name = "") { + VAArgInst *CreateVAArg(Value *List, Type *Ty, const Twine &Name = "") { return Insert(new VAArgInst(List, Ty), Name); } @@ -1201,6 +1204,11 @@ public: return Insert(InsertValueInst::Create(Agg, Val, Idxs), Name); } + LandingPadInst *CreateLandingPad(Type *Ty, Value *PersFn, unsigned NumClauses, + const Twine &Name = "") { + return Insert(LandingPadInst::Create(Ty, PersFn, NumClauses, Name)); + } + //===--------------------------------------------------------------------===// // Utility creation methods //===--------------------------------------------------------------------===// diff --git a/contrib/llvm/include/llvm/Support/InstVisitor.h b/contrib/llvm/include/llvm/Support/InstVisitor.h index b2e5d58b7..a661c4fac 100644 --- a/contrib/llvm/include/llvm/Support/InstVisitor.h +++ b/contrib/llvm/include/llvm/Support/InstVisitor.h @@ -163,12 +163,16 @@ public: RetTy visitIndirectBrInst(IndirectBrInst &I) { DELEGATE(TerminatorInst);} RetTy visitInvokeInst(InvokeInst &I) { DELEGATE(TerminatorInst);} RetTy visitUnwindInst(UnwindInst &I) { DELEGATE(TerminatorInst);} + RetTy visitResumeInst(ResumeInst &I) { DELEGATE(TerminatorInst);} RetTy visitUnreachableInst(UnreachableInst &I) { DELEGATE(TerminatorInst);} RetTy visitICmpInst(ICmpInst &I) { DELEGATE(CmpInst);} RetTy visitFCmpInst(FCmpInst &I) { DELEGATE(CmpInst);} RetTy visitAllocaInst(AllocaInst &I) { DELEGATE(Instruction); } RetTy visitLoadInst(LoadInst &I) { DELEGATE(Instruction); } RetTy visitStoreInst(StoreInst &I) { DELEGATE(Instruction); } + RetTy visitAtomicCmpXchgInst(AtomicCmpXchgInst &I){ DELEGATE(Instruction); } + RetTy visitAtomicRMWInst(AtomicRMWInst &I) { DELEGATE(Instruction); } + RetTy visitFenceInst(FenceInst &I) { DELEGATE(Instruction); } RetTy visitGetElementPtrInst(GetElementPtrInst &I){ DELEGATE(Instruction); } RetTy visitPHINode(PHINode &I) { DELEGATE(Instruction); } RetTy visitTruncInst(TruncInst &I) { DELEGATE(CastInst); } @@ -191,6 +195,7 @@ public: RetTy visitShuffleVectorInst(ShuffleVectorInst &I) { DELEGATE(Instruction); } RetTy visitExtractValueInst(ExtractValueInst &I) { DELEGATE(Instruction);} RetTy visitInsertValueInst(InsertValueInst &I) { DELEGATE(Instruction); } + RetTy visitLandingPadInst(LandingPadInst &I) { DELEGATE(Instruction); } // Next level propagators: If the user does not overload a specific // instruction type, they can overload one of these to get the whole class diff --git a/contrib/llvm/include/llvm/Support/MachO.h b/contrib/llvm/include/llvm/Support/MachO.h index 6841a0f1f..5b6858613 100644 --- a/contrib/llvm/include/llvm/Support/MachO.h +++ b/contrib/llvm/include/llvm/Support/MachO.h @@ -110,6 +110,10 @@ namespace llvm { LoadCommandDynamicLinkerInfo = 0x00000022u, // LC_DYLD_INFO LoadCommandDynamicLinkerInfoOnly = 0x80000022u, // LC_DYLD_INFO_ONLY LoadCommandDylibLoadUpward = 0x80000023u, // LC_LOAD_UPWARD_DYLIB + LoadCommandVersionMinMacOSX = 0x00000024u, // LC_VERSION_MIN_MACOSX + LoadCommandVersionMinIPhoneOS = 0x00000025u, // LC_VERSION_MIN_IPHONEOS + LoadCommandFunctionStarts = 0x00000026u, // LC_FUNCTION_STARTS + LoadCommandDyldEnvironment = 0x00000027u, // LC_DYLD_ENVIRONMENT // Constant bits for the "flags" field in llvm::MachO::segment_command SegmentCommandFlagBitHighVM = 0x1u, // SG_HIGHVM @@ -569,6 +573,13 @@ namespace llvm { uint32_t cryptid; }; + struct version_min_command { + uint32_t cmd; + uint32_t cmdsize; + uint32_t version; + uint32_t reserved; + }; + struct dyld_info_command { uint32_t cmd; uint32_t cmdsize; diff --git a/contrib/llvm/include/llvm/Support/MemoryBuffer.h b/contrib/llvm/include/llvm/Support/MemoryBuffer.h index 5e55bd981..06816de97 100644 --- a/contrib/llvm/include/llvm/Support/MemoryBuffer.h +++ b/contrib/llvm/include/llvm/Support/MemoryBuffer.h @@ -75,9 +75,9 @@ public: /// return a MemoryBuffer. static error_code getOpenFile(int FD, const char *Filename, OwningPtr &result, - size_t FileSize = -1, - size_t MapSize = -1, - off_t Offset = 0, + uint64_t FileSize = -1, + uint64_t MapSize = -1, + int64_t Offset = 0, bool RequiresNullTerminator = true); /// getMemBuffer - Open the specified memory range as a MemoryBuffer. Note diff --git a/contrib/llvm/include/llvm/Support/NoFolder.h b/contrib/llvm/include/llvm/Support/NoFolder.h index 94359a532..75c1a7926 100644 --- a/contrib/llvm/include/llvm/Support/NoFolder.h +++ b/contrib/llvm/include/llvm/Support/NoFolder.h @@ -177,22 +177,22 @@ public: // Memory Instructions //===--------------------------------------------------------------------===// - Constant *CreateGetElementPtr(Constant *C, Constant* const *IdxList, - unsigned NumIdx) const { - return ConstantExpr::getGetElementPtr(C, IdxList, NumIdx); + Constant *CreateGetElementPtr(Constant *C, + ArrayRef IdxList) const { + return ConstantExpr::getGetElementPtr(C, IdxList); } - Instruction *CreateGetElementPtr(Constant *C, Value* const *IdxList, - unsigned NumIdx) const { - return GetElementPtrInst::Create(C, IdxList, IdxList+NumIdx); + Instruction *CreateGetElementPtr(Constant *C, + ArrayRef IdxList) const { + return GetElementPtrInst::Create(C, IdxList); } - Constant *CreateInBoundsGetElementPtr(Constant *C, Constant* const *IdxList, - unsigned NumIdx) const { - return ConstantExpr::getInBoundsGetElementPtr(C, IdxList, NumIdx); + Constant *CreateInBoundsGetElementPtr(Constant *C, + ArrayRef IdxList) const { + return ConstantExpr::getInBoundsGetElementPtr(C, IdxList); } - Instruction *CreateInBoundsGetElementPtr(Constant *C, Value* const *IdxList, - unsigned NumIdx) const { - return GetElementPtrInst::CreateInBounds(C, IdxList, IdxList+NumIdx); + Instruction *CreateInBoundsGetElementPtr(Constant *C, + ArrayRef IdxList) const { + return GetElementPtrInst::CreateInBounds(C, IdxList); } //===--------------------------------------------------------------------===// @@ -200,37 +200,37 @@ public: //===--------------------------------------------------------------------===// Instruction *CreateCast(Instruction::CastOps Op, Constant *C, - const Type *DestTy) const { + Type *DestTy) const { return CastInst::Create(Op, C, DestTy); } - Instruction *CreatePointerCast(Constant *C, const Type *DestTy) const { + Instruction *CreatePointerCast(Constant *C, Type *DestTy) const { return CastInst::CreatePointerCast(C, DestTy); } - Instruction *CreateIntCast(Constant *C, const Type *DestTy, + Instruction *CreateIntCast(Constant *C, Type *DestTy, bool isSigned) const { return CastInst::CreateIntegerCast(C, DestTy, isSigned); } - Instruction *CreateFPCast(Constant *C, const Type *DestTy) const { + Instruction *CreateFPCast(Constant *C, Type *DestTy) const { return CastInst::CreateFPCast(C, DestTy); } - Instruction *CreateBitCast(Constant *C, const Type *DestTy) const { + Instruction *CreateBitCast(Constant *C, Type *DestTy) const { return CreateCast(Instruction::BitCast, C, DestTy); } - Instruction *CreateIntToPtr(Constant *C, const Type *DestTy) const { + Instruction *CreateIntToPtr(Constant *C, Type *DestTy) const { return CreateCast(Instruction::IntToPtr, C, DestTy); } - Instruction *CreatePtrToInt(Constant *C, const Type *DestTy) const { + Instruction *CreatePtrToInt(Constant *C, Type *DestTy) const { return CreateCast(Instruction::PtrToInt, C, DestTy); } - Instruction *CreateZExtOrBitCast(Constant *C, const Type *DestTy) const { + Instruction *CreateZExtOrBitCast(Constant *C, Type *DestTy) const { return CastInst::CreateZExtOrBitCast(C, DestTy); } - Instruction *CreateSExtOrBitCast(Constant *C, const Type *DestTy) const { + Instruction *CreateSExtOrBitCast(Constant *C, Type *DestTy) const { return CastInst::CreateSExtOrBitCast(C, DestTy); } - Instruction *CreateTruncOrBitCast(Constant *C, const Type *DestTy) const { + Instruction *CreateTruncOrBitCast(Constant *C, Type *DestTy) const { return CastInst::CreateTruncOrBitCast(C, DestTy); } diff --git a/contrib/llvm/include/llvm/Support/PassManagerBuilder.h b/contrib/llvm/include/llvm/Support/PassManagerBuilder.h deleted file mode 100644 index b0cec6e81..000000000 --- a/contrib/llvm/include/llvm/Support/PassManagerBuilder.h +++ /dev/null @@ -1,331 +0,0 @@ -//===-- llvm/Support/PassManagerBuilder.h - Build Standard Pass -*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the PassManagerBuilder class, which is used to set up a -// "standard" optimization sequence suitable for languages like C and C++. -// -// These are implemented as inline functions so that we do not have to worry -// about link issues. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_SUPPORT_PASSMANAGERBUILDER_H -#define LLVM_SUPPORT_PASSMANAGERBUILDER_H - -#include "llvm/PassManager.h" -#include "llvm/DefaultPasses.h" -#include "llvm/Analysis/Passes.h" -#include "llvm/Analysis/Verifier.h" -#include "llvm/Target/TargetLibraryInfo.h" -#include "llvm/Transforms/Scalar.h" -#include "llvm/Transforms/IPO.h" - -namespace llvm { - -/// PassManagerBuilder - This class is used to set up a standard optimization -/// sequence for languages like C and C++, allowing some APIs to customize the -/// pass sequence in various ways. A simple example of using it would be: -/// -/// PassManagerBuilder Builder; -/// Builder.OptLevel = 2; -/// Builder.populateFunctionPassManager(FPM); -/// Builder.populateModulePassManager(MPM); -/// -/// In addition to setting up the basic passes, PassManagerBuilder allows -/// frontends to vend a plugin API, where plugins are allowed to add extensions -/// to the default pass manager. They do this by specifying where in the pass -/// pipeline they want to be added, along with a callback function that adds -/// the pass(es). For example, a plugin that wanted to add a loop optimization -/// could do something like this: -/// -/// static void addMyLoopPass(const PMBuilder &Builder, PassManagerBase &PM) { -/// if (Builder.getOptLevel() > 2 && Builder.getOptSizeLevel() == 0) -/// PM.add(createMyAwesomePass()); -/// } -/// ... -/// Builder.addExtension(PassManagerBuilder::EP_LoopOptimizerEnd, -/// addMyLoopPass); -/// ... -class PassManagerBuilder { -public: - - /// Extensions are passed the builder itself (so they can see how it is - /// configured) as well as the pass manager to add stuff to. - typedef void (*ExtensionFn)(const PassManagerBuilder &Builder, - PassManagerBase &PM); - enum ExtensionPointTy { - /// EP_EarlyAsPossible - This extension point allows adding passes before - /// any other transformations, allowing them to see the code as it is coming - /// out of the frontend. - EP_EarlyAsPossible, - - /// EP_LoopOptimizerEnd - This extension point allows adding loop passes to - /// the end of the loop optimizer. - EP_LoopOptimizerEnd, - - /// EP_ScalarOptimizerLate - This extension point allows adding optimization - /// passes after most of the main optimizations, but before the last - /// cleanup-ish optimizations. - EP_ScalarOptimizerLate - }; - - /// The Optimization Level - Specify the basic optimization level. - /// 0 = -O0, 1 = -O1, 2 = -O2, 3 = -O3 - unsigned OptLevel; - - /// SizeLevel - How much we're optimizing for size. - /// 0 = none, 1 = -Os, 2 = -Oz - unsigned SizeLevel; - - /// LibraryInfo - Specifies information about the runtime library for the - /// optimizer. If this is non-null, it is added to both the function and - /// per-module pass pipeline. - TargetLibraryInfo *LibraryInfo; - - /// Inliner - Specifies the inliner to use. If this is non-null, it is - /// added to the per-module passes. - Pass *Inliner; - - bool DisableSimplifyLibCalls; - bool DisableUnitAtATime; - bool DisableUnrollLoops; - -private: - /// ExtensionList - This is list of all of the extensions that are registered. - std::vector > Extensions; - -public: - PassManagerBuilder() { - OptLevel = 2; - SizeLevel = 0; - LibraryInfo = 0; - Inliner = 0; - DisableSimplifyLibCalls = false; - DisableUnitAtATime = false; - DisableUnrollLoops = false; - } - - ~PassManagerBuilder() { - delete LibraryInfo; - delete Inliner; - } - - void addExtension(ExtensionPointTy Ty, ExtensionFn Fn) { - Extensions.push_back(std::make_pair(Ty, Fn)); - } - -private: - void addExtensionsToPM(ExtensionPointTy ETy, PassManagerBase &PM) const { - for (unsigned i = 0, e = Extensions.size(); i != e; ++i) - if (Extensions[i].first == ETy) - Extensions[i].second(*this, PM); - } - - void addInitialAliasAnalysisPasses(PassManagerBase &PM) const { - // Add TypeBasedAliasAnalysis before BasicAliasAnalysis so that - // BasicAliasAnalysis wins if they disagree. This is intended to help - // support "obvious" type-punning idioms. - PM.add(createTypeBasedAliasAnalysisPass()); - PM.add(createBasicAliasAnalysisPass()); - } -public: - - /// populateFunctionPassManager - This fills in the function pass manager, - /// which is expected to be run on each function immediately as it is - /// generated. The idea is to reduce the size of the IR in memory. - void populateFunctionPassManager(FunctionPassManager &FPM) { - addExtensionsToPM(EP_EarlyAsPossible, FPM); - - // Add LibraryInfo if we have some. - if (LibraryInfo) FPM.add(new TargetLibraryInfo(*LibraryInfo)); - - if (OptLevel == 0) return; - - addInitialAliasAnalysisPasses(FPM); - - FPM.add(createCFGSimplificationPass()); - FPM.add(createScalarReplAggregatesPass()); - FPM.add(createEarlyCSEPass()); - FPM.add(createLowerExpectIntrinsicPass()); - } - - /// populateModulePassManager - This sets up the primary pass manager. - void populateModulePassManager(PassManagerBase &MPM) { - // If all optimizations are disabled, just run the always-inline pass. - if (OptLevel == 0) { - if (Inliner) { - MPM.add(Inliner); - Inliner = 0; - } - return; - } - - // Add LibraryInfo if we have some. - if (LibraryInfo) MPM.add(new TargetLibraryInfo(*LibraryInfo)); - - addInitialAliasAnalysisPasses(MPM); - - if (!DisableUnitAtATime) { - MPM.add(createGlobalOptimizerPass()); // Optimize out global vars - - MPM.add(createIPSCCPPass()); // IP SCCP - MPM.add(createDeadArgEliminationPass()); // Dead argument elimination - - MPM.add(createInstructionCombiningPass());// Clean up after IPCP & DAE - MPM.add(createCFGSimplificationPass()); // Clean up after IPCP & DAE - } - - // Start of CallGraph SCC passes. - if (!DisableUnitAtATime) - MPM.add(createPruneEHPass()); // Remove dead EH info - if (Inliner) { - MPM.add(Inliner); - Inliner = 0; - } - if (!DisableUnitAtATime) - MPM.add(createFunctionAttrsPass()); // Set readonly/readnone attrs - if (OptLevel > 2) - MPM.add(createArgumentPromotionPass()); // Scalarize uninlined fn args - - // Start of function pass. - // Break up aggregate allocas, using SSAUpdater. - MPM.add(createScalarReplAggregatesPass(-1, false)); - MPM.add(createEarlyCSEPass()); // Catch trivial redundancies - if (!DisableSimplifyLibCalls) - MPM.add(createSimplifyLibCallsPass()); // Library Call Optimizations - MPM.add(createJumpThreadingPass()); // Thread jumps. - MPM.add(createCorrelatedValuePropagationPass()); // Propagate conditionals - MPM.add(createCFGSimplificationPass()); // Merge & remove BBs - MPM.add(createInstructionCombiningPass()); // Combine silly seq's - - MPM.add(createTailCallEliminationPass()); // Eliminate tail calls - MPM.add(createCFGSimplificationPass()); // Merge & remove BBs - MPM.add(createReassociatePass()); // Reassociate expressions - MPM.add(createLoopRotatePass()); // Rotate Loop - MPM.add(createLICMPass()); // Hoist loop invariants - MPM.add(createLoopUnswitchPass(SizeLevel || OptLevel < 3)); - MPM.add(createInstructionCombiningPass()); - MPM.add(createIndVarSimplifyPass()); // Canonicalize indvars - MPM.add(createLoopIdiomPass()); // Recognize idioms like memset. - MPM.add(createLoopDeletionPass()); // Delete dead loops - if (!DisableUnrollLoops) - MPM.add(createLoopUnrollPass()); // Unroll small loops - addExtensionsToPM(EP_LoopOptimizerEnd, MPM); - - if (OptLevel > 1) - MPM.add(createGVNPass()); // Remove redundancies - MPM.add(createMemCpyOptPass()); // Remove memcpy / form memset - MPM.add(createSCCPPass()); // Constant prop with SCCP - - // Run instcombine after redundancy elimination to exploit opportunities - // opened up by them. - MPM.add(createInstructionCombiningPass()); - MPM.add(createJumpThreadingPass()); // Thread jumps - MPM.add(createCorrelatedValuePropagationPass()); - MPM.add(createDeadStoreEliminationPass()); // Delete dead stores - - addExtensionsToPM(EP_ScalarOptimizerLate, MPM); - - MPM.add(createAggressiveDCEPass()); // Delete dead instructions - MPM.add(createCFGSimplificationPass()); // Merge & remove BBs - MPM.add(createInstructionCombiningPass()); // Clean up after everything. - - if (!DisableUnitAtATime) { - // FIXME: We shouldn't bother with this anymore. - MPM.add(createStripDeadPrototypesPass()); // Get rid of dead prototypes - - // GlobalOpt already deletes dead functions and globals, at -O3 try a - // late pass of GlobalDCE. It is capable of deleting dead cycles. - if (OptLevel > 2) - MPM.add(createGlobalDCEPass()); // Remove dead fns and globals. - - if (OptLevel > 1) - MPM.add(createConstantMergePass()); // Merge dup global constants - } - } - - void populateLTOPassManager(PassManagerBase &PM, bool Internalize, - bool RunInliner) { - // Provide AliasAnalysis services for optimizations. - addInitialAliasAnalysisPasses(PM); - - // Now that composite has been compiled, scan through the module, looking - // for a main function. If main is defined, mark all other functions - // internal. - if (Internalize) - PM.add(createInternalizePass(true)); - - // Propagate constants at call sites into the functions they call. This - // opens opportunities for globalopt (and inlining) by substituting function - // pointers passed as arguments to direct uses of functions. - PM.add(createIPSCCPPass()); - - // Now that we internalized some globals, see if we can hack on them! - PM.add(createGlobalOptimizerPass()); - - // Linking modules together can lead to duplicated global constants, only - // keep one copy of each constant. - PM.add(createConstantMergePass()); - - // Remove unused arguments from functions. - PM.add(createDeadArgEliminationPass()); - - // Reduce the code after globalopt and ipsccp. Both can open up significant - // simplification opportunities, and both can propagate functions through - // function pointers. When this happens, we often have to resolve varargs - // calls, etc, so let instcombine do this. - PM.add(createInstructionCombiningPass()); - - // Inline small functions - if (RunInliner) - PM.add(createFunctionInliningPass()); - - PM.add(createPruneEHPass()); // Remove dead EH info. - - // Optimize globals again if we ran the inliner. - if (RunInliner) - PM.add(createGlobalOptimizerPass()); - PM.add(createGlobalDCEPass()); // Remove dead functions. - - // If we didn't decide to inline a function, check to see if we can - // transform it to pass arguments by value instead of by reference. - PM.add(createArgumentPromotionPass()); - - // The IPO passes may leave cruft around. Clean up after them. - PM.add(createInstructionCombiningPass()); - PM.add(createJumpThreadingPass()); - // Break up allocas - PM.add(createScalarReplAggregatesPass()); - - // Run a few AA driven optimizations here and now, to cleanup the code. - PM.add(createFunctionAttrsPass()); // Add nocapture. - PM.add(createGlobalsModRefPass()); // IP alias analysis. - - PM.add(createLICMPass()); // Hoist loop invariants. - PM.add(createGVNPass()); // Remove redundancies. - PM.add(createMemCpyOptPass()); // Remove dead memcpys. - // Nuke dead stores. - PM.add(createDeadStoreEliminationPass()); - - // Cleanup and simplify the code after the scalar optimizations. - PM.add(createInstructionCombiningPass()); - - PM.add(createJumpThreadingPass()); - - // Delete basic blocks, which optimization passes may have killed. - PM.add(createCFGSimplificationPass()); - - // Now that we have optimized the program, discard unreachable functions. - PM.add(createGlobalDCEPass()); - } -}; - - -} // end namespace llvm -#endif diff --git a/contrib/llvm/include/llvm/Support/PathV1.h b/contrib/llvm/include/llvm/Support/PathV1.h index 024bb39ce..45165ded6 100644 --- a/contrib/llvm/include/llvm/Support/PathV1.h +++ b/contrib/llvm/include/llvm/Support/PathV1.h @@ -733,6 +733,7 @@ namespace sys { Mach_O_DynamicLinker_FileType, ///< The Mach-O dynamic linker Mach_O_Bundle_FileType, ///< Mach-O Bundle file Mach_O_DynamicallyLinkedSharedLibStub_FileType, ///< Mach-O Shared lib stub + Mach_O_DSYMCompanion_FileType, ///< Mach-O dSYM companion file COFF_FileType ///< COFF object file or lib }; diff --git a/contrib/llvm/include/llvm/Support/PathV2.h b/contrib/llvm/include/llvm/Support/PathV2.h index 251563398..6d38c9571 100644 --- a/contrib/llvm/include/llvm/Support/PathV2.h +++ b/contrib/llvm/include/llvm/Support/PathV2.h @@ -187,7 +187,7 @@ const StringRef root_name(StringRef path); /// @result The root directory of \a path if it has one, otherwise /// "". const StringRef root_directory(StringRef path); - + /// @brief Get root path. /// /// Equivalent to root_name + root_directory. @@ -264,6 +264,17 @@ const StringRef extension(StringRef path); /// @result true if \a value is a path separator character on the host OS bool is_separator(char value); +/// @brief Get the typical temporary directory for the system, e.g., +/// "/var/tmp" or "C:/TEMP" +/// +/// @param erasedOnReboot Whether to favor a path that is erased on reboot +/// rather than one that potentially persists longer. This parameter will be +/// ignored if the user or system has set the typical environment variable +/// (e.g., TEMP on Windows, TMPDIR on *nix) to specify a temporary directory. +/// +/// @param Result Holds the resulting path name. +void system_temp_directory(bool erasedOnReboot, SmallVectorImpl &result); + /// @brief Has root name? /// /// root_name != "" diff --git a/contrib/llvm/include/llvm/Support/Process.h b/contrib/llvm/include/llvm/Support/Process.h index 33799229f..27ef26700 100644 --- a/contrib/llvm/include/llvm/Support/Process.h +++ b/contrib/llvm/include/llvm/Support/Process.h @@ -138,6 +138,9 @@ namespace sys { /// Resets the terminals colors, or returns an escape sequence to do so. static const char *ResetColor(); + + /// Change the program working directory to that given by \arg Path. + static void SetWorkingDirectory(std::string Path); /// @} }; } diff --git a/contrib/llvm/include/llvm/Support/SMLoc.h b/contrib/llvm/include/llvm/Support/SMLoc.h index 967bf1432..02db32794 100644 --- a/contrib/llvm/include/llvm/Support/SMLoc.h +++ b/contrib/llvm/include/llvm/Support/SMLoc.h @@ -18,19 +18,19 @@ namespace llvm { // SMLoc - Represents a location in source code. -class SMLoc { +class SMLoc { const char *Ptr; public: SMLoc() : Ptr(0) {} SMLoc(const SMLoc &RHS) : Ptr(RHS.Ptr) {} - + bool isValid() const { return Ptr != 0; } - + bool operator==(const SMLoc &RHS) const { return RHS.Ptr == Ptr; } bool operator!=(const SMLoc &RHS) const { return RHS.Ptr != Ptr; } - + const char *getPointer() const { return Ptr; } - + static SMLoc getFromPointer(const char *Ptr) { SMLoc L; L.Ptr = Ptr; diff --git a/contrib/llvm/include/llvm/Support/SourceMgr.h b/contrib/llvm/include/llvm/Support/SourceMgr.h index 030db8f4e..deb8cafa0 100644 --- a/contrib/llvm/include/llvm/Support/SourceMgr.h +++ b/contrib/llvm/include/llvm/Support/SourceMgr.h @@ -78,6 +78,9 @@ public: DiagContext = Ctx; } + DiagHandlerTy getDiagHandler() const { return DiagHandler; } + void *getDiagContext() const { return DiagContext; } + const SrcBuffer &getBufferInfo(unsigned i) const { assert(i < Buffers.size() && "Invalid Buffer ID!"); return Buffers[i]; @@ -138,8 +141,12 @@ public: const Twine &Msg, const char *Type, bool ShowLine = true) const; - -private: + /// PrintIncludeStack - Prints the names of included files and the line of the + /// file they were included from. A diagnostic handler can use this before + /// printing its custom formatted message. + /// + /// @param IncludeLoc - The line of the include. + /// @param OS the raw_ostream to print on. void PrintIncludeStack(SMLoc IncludeLoc, raw_ostream &OS) const; }; diff --git a/contrib/llvm/include/llvm/Support/TargetFolder.h b/contrib/llvm/include/llvm/Support/TargetFolder.h index 3233a98da..c65faa662 100644 --- a/contrib/llvm/include/llvm/Support/TargetFolder.h +++ b/contrib/llvm/include/llvm/Support/TargetFolder.h @@ -130,22 +130,34 @@ public: // Memory Instructions //===--------------------------------------------------------------------===// - Constant *CreateGetElementPtr(Constant *C, Constant* const *IdxList, - unsigned NumIdx) const { - return Fold(ConstantExpr::getGetElementPtr(C, IdxList, NumIdx)); + Constant *CreateGetElementPtr(Constant *C, + ArrayRef IdxList) const { + return Fold(ConstantExpr::getGetElementPtr(C, IdxList)); } - Constant *CreateGetElementPtr(Constant *C, Value* const *IdxList, - unsigned NumIdx) const { - return Fold(ConstantExpr::getGetElementPtr(C, IdxList, NumIdx)); + Constant *CreateGetElementPtr(Constant *C, Constant *Idx) const { + // This form of the function only exists to avoid ambiguous overload + // warnings about whether to convert Idx to ArrayRef or + // ArrayRef. + return Fold(ConstantExpr::getGetElementPtr(C, Idx)); + } + Constant *CreateGetElementPtr(Constant *C, + ArrayRef IdxList) const { + return Fold(ConstantExpr::getGetElementPtr(C, IdxList)); } - Constant *CreateInBoundsGetElementPtr(Constant *C, Constant* const *IdxList, - unsigned NumIdx) const { - return Fold(ConstantExpr::getInBoundsGetElementPtr(C, IdxList, NumIdx)); + Constant *CreateInBoundsGetElementPtr(Constant *C, + ArrayRef IdxList) const { + return Fold(ConstantExpr::getInBoundsGetElementPtr(C, IdxList)); + } + Constant *CreateInBoundsGetElementPtr(Constant *C, Constant *Idx) const { + // This form of the function only exists to avoid ambiguous overload + // warnings about whether to convert Idx to ArrayRef or + // ArrayRef. + return Fold(ConstantExpr::getInBoundsGetElementPtr(C, Idx)); } - Constant *CreateInBoundsGetElementPtr(Constant *C, Value* const *IdxList, - unsigned NumIdx) const { - return Fold(ConstantExpr::getInBoundsGetElementPtr(C, IdxList, NumIdx)); + Constant *CreateInBoundsGetElementPtr(Constant *C, + ArrayRef IdxList) const { + return Fold(ConstantExpr::getInBoundsGetElementPtr(C, IdxList)); } //===--------------------------------------------------------------------===// @@ -153,40 +165,40 @@ public: //===--------------------------------------------------------------------===// Constant *CreateCast(Instruction::CastOps Op, Constant *C, - const Type *DestTy) const { + Type *DestTy) const { if (C->getType() == DestTy) return C; // avoid calling Fold return Fold(ConstantExpr::getCast(Op, C, DestTy)); } - Constant *CreateIntCast(Constant *C, const Type *DestTy, + Constant *CreateIntCast(Constant *C, Type *DestTy, bool isSigned) const { if (C->getType() == DestTy) return C; // avoid calling Fold return Fold(ConstantExpr::getIntegerCast(C, DestTy, isSigned)); } - Constant *CreatePointerCast(Constant *C, const Type *DestTy) const { + Constant *CreatePointerCast(Constant *C, Type *DestTy) const { return ConstantExpr::getPointerCast(C, DestTy); } - Constant *CreateBitCast(Constant *C, const Type *DestTy) const { + Constant *CreateBitCast(Constant *C, Type *DestTy) const { return CreateCast(Instruction::BitCast, C, DestTy); } - Constant *CreateIntToPtr(Constant *C, const Type *DestTy) const { + Constant *CreateIntToPtr(Constant *C, Type *DestTy) const { return CreateCast(Instruction::IntToPtr, C, DestTy); } - Constant *CreatePtrToInt(Constant *C, const Type *DestTy) const { + Constant *CreatePtrToInt(Constant *C, Type *DestTy) const { return CreateCast(Instruction::PtrToInt, C, DestTy); } - Constant *CreateZExtOrBitCast(Constant *C, const Type *DestTy) const { + Constant *CreateZExtOrBitCast(Constant *C, Type *DestTy) const { if (C->getType() == DestTy) return C; // avoid calling Fold return Fold(ConstantExpr::getZExtOrBitCast(C, DestTy)); } - Constant *CreateSExtOrBitCast(Constant *C, const Type *DestTy) const { + Constant *CreateSExtOrBitCast(Constant *C, Type *DestTy) const { if (C->getType() == DestTy) return C; // avoid calling Fold return Fold(ConstantExpr::getSExtOrBitCast(C, DestTy)); } - Constant *CreateTruncOrBitCast(Constant *C, const Type *DestTy) const { + Constant *CreateTruncOrBitCast(Constant *C, Type *DestTy) const { if (C->getType() == DestTy) return C; // avoid calling Fold return Fold(ConstantExpr::getTruncOrBitCast(C, DestTy)); diff --git a/contrib/llvm/include/llvm/Target/TargetRegistry.h b/contrib/llvm/include/llvm/Support/TargetRegistry.h similarity index 66% rename from contrib/llvm/include/llvm/Target/TargetRegistry.h rename to contrib/llvm/include/llvm/Support/TargetRegistry.h index 7e0ce19f8..45f249d7e 100644 --- a/contrib/llvm/include/llvm/Target/TargetRegistry.h +++ b/contrib/llvm/include/llvm/Support/TargetRegistry.h @@ -1,4 +1,4 @@ -//===-- Target/TargetRegistry.h - Target Registration -----------*- C++ -*-===// +//===-- Support/TargetRegistry.h - Target Registration ----------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -16,9 +16,10 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_TARGET_TARGETREGISTRY_H -#define LLVM_TARGET_TARGETREGISTRY_H +#ifndef LLVM_SUPPORT_TARGETREGISTRY_H +#define LLVM_SUPPORT_TARGETREGISTRY_H +#include "llvm/Support/CodeGen.h" #include "llvm/ADT/Triple.h" #include #include @@ -27,19 +28,21 @@ namespace llvm { class AsmPrinter; class Module; class MCAssembler; + class MCAsmBackend; class MCAsmInfo; class MCAsmParser; class MCCodeEmitter; + class MCCodeGenInfo; class MCContext; class MCDisassembler; + class MCInstrAnalysis; class MCInstPrinter; class MCInstrInfo; class MCRegisterInfo; class MCStreamer; class MCSubtargetInfo; - class TargetAsmBackend; - class TargetAsmLexer; - class TargetAsmParser; + class MCTargetAsmLexer; + class MCTargetAsmParser; class TargetMachine; class raw_ostream; class formatted_raw_ostream; @@ -49,7 +52,7 @@ namespace llvm { bool useLoc, bool useCFI, MCInstPrinter *InstPrint, MCCodeEmitter *CE, - TargetAsmBackend *TAB, + MCAsmBackend *TAB, bool ShowInst); /// Target - Wrapper for Target specific information. @@ -68,38 +71,46 @@ namespace llvm { typedef MCAsmInfo *(*MCAsmInfoCtorFnTy)(const Target &T, StringRef TT); + typedef MCCodeGenInfo *(*MCCodeGenInfoCtorFnTy)(StringRef TT, + Reloc::Model RM, + CodeModel::Model CM); typedef MCInstrInfo *(*MCInstrInfoCtorFnTy)(void); - typedef MCRegisterInfo *(*MCRegInfoCtorFnTy)(void); + typedef MCInstrAnalysis *(*MCInstrAnalysisCtorFnTy)(const MCInstrInfo*Info); + typedef MCRegisterInfo *(*MCRegInfoCtorFnTy)(StringRef TT); typedef MCSubtargetInfo *(*MCSubtargetInfoCtorFnTy)(StringRef TT, StringRef CPU, StringRef Features); typedef TargetMachine *(*TargetMachineCtorTy)(const Target &T, - const std::string &TT, - const std::string &CPU, - const std::string &Features); + StringRef TT, + StringRef CPU, + StringRef Features, + Reloc::Model RM, + CodeModel::Model CM); typedef AsmPrinter *(*AsmPrinterCtorTy)(TargetMachine &TM, MCStreamer &Streamer); - typedef TargetAsmBackend *(*AsmBackendCtorTy)(const Target &T, - const std::string &TT); - typedef TargetAsmLexer *(*AsmLexerCtorTy)(const Target &T, - const MCAsmInfo &MAI); - typedef TargetAsmParser *(*AsmParserCtorTy)(MCSubtargetInfo &STI, - MCAsmParser &P); - typedef MCDisassembler *(*MCDisassemblerCtorTy)(const Target &T); + typedef MCAsmBackend *(*MCAsmBackendCtorTy)(const Target &T, StringRef TT); + typedef MCTargetAsmLexer *(*MCAsmLexerCtorTy)(const Target &T, + const MCRegisterInfo &MRI, + const MCAsmInfo &MAI); + typedef MCTargetAsmParser *(*MCAsmParserCtorTy)(MCSubtargetInfo &STI, + MCAsmParser &P); + typedef MCDisassembler *(*MCDisassemblerCtorTy)(const Target &T, + const MCSubtargetInfo &STI); typedef MCInstPrinter *(*MCInstPrinterCtorTy)(const Target &T, unsigned SyntaxVariant, - const MCAsmInfo &MAI); - typedef MCCodeEmitter *(*CodeEmitterCtorTy)(const MCInstrInfo &II, - const MCSubtargetInfo &STI, - MCContext &Ctx); - typedef MCStreamer *(*ObjectStreamerCtorTy)(const Target &T, - const std::string &TT, - MCContext &Ctx, - TargetAsmBackend &TAB, - raw_ostream &_OS, - MCCodeEmitter *_Emitter, - bool RelaxAll, - bool NoExecStack); + const MCAsmInfo &MAI, + const MCSubtargetInfo &STI); + typedef MCCodeEmitter *(*MCCodeEmitterCtorTy)(const MCInstrInfo &II, + const MCSubtargetInfo &STI, + MCContext &Ctx); + typedef MCStreamer *(*MCObjectStreamerCtorTy)(const Target &T, + StringRef TT, + MCContext &Ctx, + MCAsmBackend &TAB, + raw_ostream &_OS, + MCCodeEmitter *_Emitter, + bool RelaxAll, + bool NoExecStack); typedef MCStreamer *(*AsmStreamerCtorTy)(MCContext &Ctx, formatted_raw_ostream &OS, bool isVerboseAsm, @@ -107,7 +118,7 @@ namespace llvm { bool useCFI, MCInstPrinter *InstPrint, MCCodeEmitter *CE, - TargetAsmBackend *TAB, + MCAsmBackend *TAB, bool ShowInst); private: @@ -132,10 +143,18 @@ namespace llvm { /// registered. MCAsmInfoCtorFnTy MCAsmInfoCtorFn; + /// MCCodeGenInfoCtorFn - Constructor function for this target's MCCodeGenInfo, + /// if registered. + MCCodeGenInfoCtorFnTy MCCodeGenInfoCtorFn; + /// MCInstrInfoCtorFn - Constructor function for this target's MCInstrInfo, /// if registered. MCInstrInfoCtorFnTy MCInstrInfoCtorFn; + /// MCInstrAnalysisCtorFn - Constructor function for this target's + /// MCInstrAnalysis, if registered. + MCInstrAnalysisCtorFnTy MCInstrAnalysisCtorFn; + /// MCRegInfoCtorFn - Constructor function for this target's MCRegisterInfo, /// if registered. MCRegInfoCtorFnTy MCRegInfoCtorFn; @@ -148,17 +167,17 @@ namespace llvm { /// TargetMachine, if registered. TargetMachineCtorTy TargetMachineCtorFn; - /// AsmBackendCtorFn - Construction function for this target's - /// TargetAsmBackend, if registered. - AsmBackendCtorTy AsmBackendCtorFn; + /// MCAsmBackendCtorFn - Construction function for this target's + /// MCAsmBackend, if registered. + MCAsmBackendCtorTy MCAsmBackendCtorFn; - /// AsmLexerCtorFn - Construction function for this target's TargetAsmLexer, - /// if registered. - AsmLexerCtorTy AsmLexerCtorFn; + /// MCAsmLexerCtorFn - Construction function for this target's + /// MCTargetAsmLexer, if registered. + MCAsmLexerCtorTy MCAsmLexerCtorFn; - /// AsmParserCtorFn - Construction function for this target's - /// TargetAsmParser, if registered. - AsmParserCtorTy AsmParserCtorFn; + /// MCAsmParserCtorFn - Construction function for this target's + /// MCTargetAsmParser, if registered. + MCAsmParserCtorTy MCAsmParserCtorFn; /// AsmPrinterCtorFn - Construction function for this target's AsmPrinter, /// if registered. @@ -172,13 +191,13 @@ namespace llvm { /// MCInstPrinter, if registered. MCInstPrinterCtorTy MCInstPrinterCtorFn; - /// CodeEmitterCtorFn - Construction function for this target's CodeEmitter, - /// if registered. - CodeEmitterCtorTy CodeEmitterCtorFn; + /// MCCodeEmitterCtorFn - Construction function for this target's + /// CodeEmitter, if registered. + MCCodeEmitterCtorTy MCCodeEmitterCtorFn; - /// ObjectStreamerCtorFn - Construction function for this target's - /// ObjectStreamer, if registered. - ObjectStreamerCtorTy ObjectStreamerCtorFn; + /// MCObjectStreamerCtorFn - Construction function for this target's + /// MCObjectStreamer, if registered. + MCObjectStreamerCtorTy MCObjectStreamerCtorFn; /// AsmStreamerCtorFn - Construction function for this target's /// AsmStreamer, if registered (default = llvm::createAsmStreamer). @@ -209,14 +228,14 @@ namespace llvm { /// hasTargetMachine - Check if this target supports code generation. bool hasTargetMachine() const { return TargetMachineCtorFn != 0; } - /// hasAsmBackend - Check if this target supports .o generation. - bool hasAsmBackend() const { return AsmBackendCtorFn != 0; } + /// hasMCAsmBackend - Check if this target supports .o generation. + bool hasMCAsmBackend() const { return MCAsmBackendCtorFn != 0; } - /// hasAsmLexer - Check if this target supports .s lexing. - bool hasAsmLexer() const { return AsmLexerCtorFn != 0; } + /// hasMCAsmLexer - Check if this target supports .s lexing. + bool hasMCAsmLexer() const { return MCAsmLexerCtorFn != 0; } /// hasAsmParser - Check if this target supports .s parsing. - bool hasAsmParser() const { return AsmParserCtorFn != 0; } + bool hasMCAsmParser() const { return MCAsmParserCtorFn != 0; } /// hasAsmPrinter - Check if this target supports .s printing. bool hasAsmPrinter() const { return AsmPrinterCtorFn != 0; } @@ -227,11 +246,11 @@ namespace llvm { /// hasMCInstPrinter - Check if this target has an instruction printer. bool hasMCInstPrinter() const { return MCInstPrinterCtorFn != 0; } - /// hasCodeEmitter - Check if this target supports instruction encoding. - bool hasCodeEmitter() const { return CodeEmitterCtorFn != 0; } + /// hasMCCodeEmitter - Check if this target supports instruction encoding. + bool hasMCCodeEmitter() const { return MCCodeEmitterCtorFn != 0; } - /// hasObjectStreamer - Check if this target supports streaming to files. - bool hasObjectStreamer() const { return ObjectStreamerCtorFn != 0; } + /// hasMCObjectStreamer - Check if this target supports streaming to files. + bool hasMCObjectStreamer() const { return MCObjectStreamerCtorFn != 0; } /// hasAsmStreamer - Check if this target supports streaming to files. bool hasAsmStreamer() const { return AsmStreamerCtorFn != 0; } @@ -253,6 +272,15 @@ namespace llvm { return MCAsmInfoCtorFn(*this, Triple); } + /// createMCCodeGenInfo - Create a MCCodeGenInfo implementation. + /// + MCCodeGenInfo *createMCCodeGenInfo(StringRef Triple, Reloc::Model RM, + CodeModel::Model CM) const { + if (!MCCodeGenInfoCtorFn) + return 0; + return MCCodeGenInfoCtorFn(Triple, RM, CM); + } + /// createMCInstrInfo - Create a MCInstrInfo implementation. /// MCInstrInfo *createMCInstrInfo() const { @@ -261,12 +289,20 @@ namespace llvm { return MCInstrInfoCtorFn(); } + /// createMCInstrAnalysis - Create a MCInstrAnalysis implementation. + /// + MCInstrAnalysis *createMCInstrAnalysis(const MCInstrInfo *Info) const { + if (!MCInstrAnalysisCtorFn) + return 0; + return MCInstrAnalysisCtorFn(Info); + } + /// createMCRegInfo - Create a MCRegisterInfo implementation. /// - MCRegisterInfo *createMCRegInfo() const { + MCRegisterInfo *createMCRegInfo(StringRef Triple) const { if (!MCRegInfoCtorFn) return 0; - return MCRegInfoCtorFn(); + return MCRegInfoCtorFn(Triple); } /// createMCSubtargetInfo - Create a MCSubtargetInfo implementation. @@ -292,41 +328,43 @@ namespace llvm { /// feature set; it should always be provided. Generally this should be /// either the target triple from the module, or the target triple of the /// host if that does not exist. - TargetMachine *createTargetMachine(const std::string &Triple, - const std::string &CPU, - const std::string &Features) const { + TargetMachine *createTargetMachine(StringRef Triple, StringRef CPU, + StringRef Features, + Reloc::Model RM = Reloc::Default, + CodeModel::Model CM = CodeModel::Default) const { if (!TargetMachineCtorFn) return 0; - return TargetMachineCtorFn(*this, Triple, CPU, Features); + return TargetMachineCtorFn(*this, Triple, CPU, Features, RM, CM); } - /// createAsmBackend - Create a target specific assembly parser. + /// createMCAsmBackend - Create a target specific assembly parser. /// /// \arg Triple - The target triple string. /// \arg Backend - The target independent assembler object. - TargetAsmBackend *createAsmBackend(const std::string &Triple) const { - if (!AsmBackendCtorFn) + MCAsmBackend *createMCAsmBackend(StringRef Triple) const { + if (!MCAsmBackendCtorFn) return 0; - return AsmBackendCtorFn(*this, Triple); + return MCAsmBackendCtorFn(*this, Triple); } - /// createAsmLexer - Create a target specific assembly lexer. + /// createMCAsmLexer - Create a target specific assembly lexer. /// - TargetAsmLexer *createAsmLexer(const MCAsmInfo &MAI) const { - if (!AsmLexerCtorFn) + MCTargetAsmLexer *createMCAsmLexer(const MCRegisterInfo &MRI, + const MCAsmInfo &MAI) const { + if (!MCAsmLexerCtorFn) return 0; - return AsmLexerCtorFn(*this, MAI); + return MCAsmLexerCtorFn(*this, MRI, MAI); } - /// createAsmParser - Create a target specific assembly parser. + /// createMCAsmParser - Create a target specific assembly parser. /// /// \arg Parser - The target independent parser implementation to use for /// parsing and lexing. - TargetAsmParser *createAsmParser(MCSubtargetInfo &STI, - MCAsmParser &Parser) const { - if (!AsmParserCtorFn) + MCTargetAsmParser *createMCAsmParser(MCSubtargetInfo &STI, + MCAsmParser &Parser) const { + if (!MCAsmParserCtorFn) return 0; - return AsmParserCtorFn(STI, Parser); + return MCAsmParserCtorFn(STI, Parser); } /// createAsmPrinter - Create a target specific assembly printer pass. This @@ -337,30 +375,31 @@ namespace llvm { return AsmPrinterCtorFn(TM, Streamer); } - MCDisassembler *createMCDisassembler() const { + MCDisassembler *createMCDisassembler(const MCSubtargetInfo &STI) const { if (!MCDisassemblerCtorFn) return 0; - return MCDisassemblerCtorFn(*this); + return MCDisassemblerCtorFn(*this, STI); } MCInstPrinter *createMCInstPrinter(unsigned SyntaxVariant, - const MCAsmInfo &MAI) const { + const MCAsmInfo &MAI, + const MCSubtargetInfo &STI) const { if (!MCInstPrinterCtorFn) return 0; - return MCInstPrinterCtorFn(*this, SyntaxVariant, MAI); + return MCInstPrinterCtorFn(*this, SyntaxVariant, MAI, STI); } - /// createCodeEmitter - Create a target specific code emitter. - MCCodeEmitter *createCodeEmitter(const MCInstrInfo &II, - const MCSubtargetInfo &STI, - MCContext &Ctx) const { - if (!CodeEmitterCtorFn) + /// createMCCodeEmitter - Create a target specific code emitter. + MCCodeEmitter *createMCCodeEmitter(const MCInstrInfo &II, + const MCSubtargetInfo &STI, + MCContext &Ctx) const { + if (!MCCodeEmitterCtorFn) return 0; - return CodeEmitterCtorFn(II, STI, Ctx); + return MCCodeEmitterCtorFn(II, STI, Ctx); } - /// createObjectStreamer - Create a target specific MCStreamer. + /// createMCObjectStreamer - Create a target specific MCStreamer. /// /// \arg TT - The target triple. /// \arg Ctx - The target context. @@ -369,16 +408,16 @@ namespace llvm { /// \arg _Emitter - The target independent assembler object.Takes ownership. /// \arg RelaxAll - Relax all fixups? /// \arg NoExecStack - Mark file as not needing a executable stack. - MCStreamer *createObjectStreamer(const std::string &TT, MCContext &Ctx, - TargetAsmBackend &TAB, - raw_ostream &_OS, - MCCodeEmitter *_Emitter, - bool RelaxAll, - bool NoExecStack) const { - if (!ObjectStreamerCtorFn) + MCStreamer *createMCObjectStreamer(StringRef TT, MCContext &Ctx, + MCAsmBackend &TAB, + raw_ostream &_OS, + MCCodeEmitter *_Emitter, + bool RelaxAll, + bool NoExecStack) const { + if (!MCObjectStreamerCtorFn) return 0; - return ObjectStreamerCtorFn(*this, TT, Ctx, TAB, _OS, _Emitter, RelaxAll, - NoExecStack); + return MCObjectStreamerCtorFn(*this, TT, Ctx, TAB, _OS, _Emitter, + RelaxAll, NoExecStack); } /// createAsmStreamer - Create a target specific MCStreamer. @@ -389,7 +428,7 @@ namespace llvm { bool useCFI, MCInstPrinter *InstPrint, MCCodeEmitter *CE, - TargetAsmBackend *TAB, + MCAsmBackend *TAB, bool ShowInst) const { // AsmStreamerCtorFn is default to llvm::createAsmStreamer return AsmStreamerCtorFn(Ctx, OS, isVerboseAsm, useLoc, useCFI, @@ -438,6 +477,10 @@ namespace llvm { } }; + /// printRegisteredTargetsForVersion - Print the registered targets + /// appropriately for inclusion in a tool's version output. + static void printRegisteredTargetsForVersion(); + /// @name Registry Access /// @{ @@ -500,6 +543,22 @@ namespace llvm { T.MCAsmInfoCtorFn = Fn; } + /// RegisterMCCodeGenInfo - Register a MCCodeGenInfo implementation for the + /// given target. + /// + /// Clients are responsible for ensuring that registration doesn't occur + /// while another thread is attempting to access the registry. Typically + /// this is done by initializing all targets at program startup. + /// + /// @param T - The target being registered. + /// @param Fn - A function to construct a MCCodeGenInfo for the target. + static void RegisterMCCodeGenInfo(Target &T, + Target::MCCodeGenInfoCtorFnTy Fn) { + // Ignore duplicate registration. + if (!T.MCCodeGenInfoCtorFn) + T.MCCodeGenInfoCtorFn = Fn; + } + /// RegisterMCInstrInfo - Register a MCInstrInfo implementation for the /// given target. /// @@ -515,6 +574,15 @@ namespace llvm { T.MCInstrInfoCtorFn = Fn; } + /// RegisterMCInstrAnalysis - Register a MCInstrAnalysis implementation for + /// the given target. + static void RegisterMCInstrAnalysis(Target &T, + Target::MCInstrAnalysisCtorFnTy Fn) { + // Ignore duplicate registration. + if (!T.MCInstrAnalysisCtorFn) + T.MCInstrAnalysisCtorFn = Fn; + } + /// RegisterMCRegInfo - Register a MCRegisterInfo implementation for the /// given target. /// @@ -562,7 +630,7 @@ namespace llvm { T.TargetMachineCtorFn = Fn; } - /// RegisterAsmBackend - Register a TargetAsmBackend implementation for the + /// RegisterMCAsmBackend - Register a MCAsmBackend implementation for the /// given target. /// /// Clients are responsible for ensuring that registration doesn't occur @@ -571,12 +639,12 @@ namespace llvm { /// /// @param T - The target being registered. /// @param Fn - A function to construct an AsmBackend for the target. - static void RegisterAsmBackend(Target &T, Target::AsmBackendCtorTy Fn) { - if (!T.AsmBackendCtorFn) - T.AsmBackendCtorFn = Fn; + static void RegisterMCAsmBackend(Target &T, Target::MCAsmBackendCtorTy Fn) { + if (!T.MCAsmBackendCtorFn) + T.MCAsmBackendCtorFn = Fn; } - /// RegisterAsmLexer - Register a TargetAsmLexer implementation for the + /// RegisterMCAsmLexer - Register a MCTargetAsmLexer implementation for the /// given target. /// /// Clients are responsible for ensuring that registration doesn't occur @@ -584,24 +652,24 @@ namespace llvm { /// this is done by initializing all targets at program startup. /// /// @param T - The target being registered. - /// @param Fn - A function to construct an AsmLexer for the target. - static void RegisterAsmLexer(Target &T, Target::AsmLexerCtorTy Fn) { - if (!T.AsmLexerCtorFn) - T.AsmLexerCtorFn = Fn; + /// @param Fn - A function to construct an MCAsmLexer for the target. + static void RegisterMCAsmLexer(Target &T, Target::MCAsmLexerCtorTy Fn) { + if (!T.MCAsmLexerCtorFn) + T.MCAsmLexerCtorFn = Fn; } - /// RegisterAsmParser - Register a TargetAsmParser implementation for the - /// given target. + /// RegisterMCAsmParser - Register a MCTargetAsmParser implementation for + /// the given target. /// /// Clients are responsible for ensuring that registration doesn't occur /// while another thread is attempting to access the registry. Typically /// this is done by initializing all targets at program startup. /// /// @param T - The target being registered. - /// @param Fn - A function to construct an AsmParser for the target. - static void RegisterAsmParser(Target &T, Target::AsmParserCtorTy Fn) { - if (!T.AsmParserCtorFn) - T.AsmParserCtorFn = Fn; + /// @param Fn - A function to construct an MCTargetAsmParser for the target. + static void RegisterMCAsmParser(Target &T, Target::MCAsmParserCtorTy Fn) { + if (!T.MCAsmParserCtorFn) + T.MCAsmParserCtorFn = Fn; } /// RegisterAsmPrinter - Register an AsmPrinter implementation for the given @@ -649,7 +717,7 @@ namespace llvm { T.MCInstPrinterCtorFn = Fn; } - /// RegisterCodeEmitter - Register a MCCodeEmitter implementation for the + /// RegisterMCCodeEmitter - Register a MCCodeEmitter implementation for the /// given target. /// /// Clients are responsible for ensuring that registration doesn't occur @@ -658,13 +726,14 @@ namespace llvm { /// /// @param T - The target being registered. /// @param Fn - A function to construct an MCCodeEmitter for the target. - static void RegisterCodeEmitter(Target &T, Target::CodeEmitterCtorTy Fn) { - if (!T.CodeEmitterCtorFn) - T.CodeEmitterCtorFn = Fn; + static void RegisterMCCodeEmitter(Target &T, + Target::MCCodeEmitterCtorTy Fn) { + if (!T.MCCodeEmitterCtorFn) + T.MCCodeEmitterCtorFn = Fn; } - /// RegisterObjectStreamer - Register a object code MCStreamer implementation - /// for the given target. + /// RegisterMCObjectStreamer - Register a object code MCStreamer + /// implementation for the given target. /// /// Clients are responsible for ensuring that registration doesn't occur /// while another thread is attempting to access the registry. Typically @@ -672,9 +741,10 @@ namespace llvm { /// /// @param T - The target being registered. /// @param Fn - A function to construct an MCStreamer for the target. - static void RegisterObjectStreamer(Target &T, Target::ObjectStreamerCtorTy Fn) { - if (!T.ObjectStreamerCtorFn) - T.ObjectStreamerCtorFn = Fn; + static void RegisterMCObjectStreamer(Target &T, + Target::MCObjectStreamerCtorTy Fn) { + if (!T.MCObjectStreamerCtorFn) + T.MCObjectStreamerCtorFn = Fn; } /// RegisterAsmStreamer - Register an assembly MCStreamer implementation @@ -756,6 +826,40 @@ namespace llvm { } }; + /// RegisterMCCodeGenInfo - Helper template for registering a target codegen info + /// implementation. This invokes the static "Create" method on the class + /// to actually do the construction. Usage: + /// + /// extern "C" void LLVMInitializeFooTarget() { + /// extern Target TheFooTarget; + /// RegisterMCCodeGenInfo X(TheFooTarget); + /// } + template + struct RegisterMCCodeGenInfo { + RegisterMCCodeGenInfo(Target &T) { + TargetRegistry::RegisterMCCodeGenInfo(T, &Allocator); + } + private: + static MCCodeGenInfo *Allocator(StringRef TT, + Reloc::Model RM, CodeModel::Model CM) { + return new MCCodeGenInfoImpl(); + } + }; + + /// RegisterMCCodeGenInfoFn - Helper template for registering a target codegen + /// info implementation. This invokes the specified function to do the + /// construction. Usage: + /// + /// extern "C" void LLVMInitializeFooTarget() { + /// extern Target TheFooTarget; + /// RegisterMCCodeGenInfoFn X(TheFooTarget, TheFunction); + /// } + struct RegisterMCCodeGenInfoFn { + RegisterMCCodeGenInfoFn(Target &T, Target::MCCodeGenInfoCtorFnTy Fn) { + TargetRegistry::RegisterMCCodeGenInfo(T, Fn); + } + }; + /// RegisterMCInstrInfo - Helper template for registering a target instruction /// info implementation. This invokes the static "Create" method on the class /// to actually do the construction. Usage: @@ -789,6 +893,39 @@ namespace llvm { } }; + /// RegisterMCInstrAnalysis - Helper template for registering a target + /// instruction analyzer implementation. This invokes the static "Create" + /// method on the class to actually do the construction. Usage: + /// + /// extern "C" void LLVMInitializeFooTarget() { + /// extern Target TheFooTarget; + /// RegisterMCInstrAnalysis X(TheFooTarget); + /// } + template + struct RegisterMCInstrAnalysis { + RegisterMCInstrAnalysis(Target &T) { + TargetRegistry::RegisterMCInstrAnalysis(T, &Allocator); + } + private: + static MCInstrAnalysis *Allocator(const MCInstrInfo *Info) { + return new MCInstrAnalysisImpl(Info); + } + }; + + /// RegisterMCInstrAnalysisFn - Helper template for registering a target + /// instruction analyzer implementation. This invokes the specified function + /// to do the construction. Usage: + /// + /// extern "C" void LLVMInitializeFooTarget() { + /// extern Target TheFooTarget; + /// RegisterMCInstrAnalysisFn X(TheFooTarget, TheFunction); + /// } + struct RegisterMCInstrAnalysisFn { + RegisterMCInstrAnalysisFn(Target &T, Target::MCInstrAnalysisCtorFnTy Fn) { + TargetRegistry::RegisterMCInstrAnalysis(T, Fn); + } + }; + /// RegisterMCRegInfo - Helper template for registering a target register info /// implementation. This invokes the static "Create" method on the class to /// actually do the construction. Usage: @@ -803,7 +940,7 @@ namespace llvm { TargetRegistry::RegisterMCRegInfo(T, &Allocator); } private: - static MCRegisterInfo *Allocator() { + static MCRegisterInfo *Allocator(StringRef TT) { return new MCRegisterInfoImpl(); } }; @@ -871,70 +1008,72 @@ namespace llvm { } private: - static TargetMachine *Allocator(const Target &T, const std::string &TT, - const std::string &CPU, - const std::string &FS) { - return new TargetMachineImpl(T, TT, CPU, FS); + static TargetMachine *Allocator(const Target &T, StringRef TT, + StringRef CPU, StringRef FS, + Reloc::Model RM, + CodeModel::Model CM) { + return new TargetMachineImpl(T, TT, CPU, FS, RM, CM); } }; - /// RegisterAsmBackend - Helper template for registering a target specific + /// RegisterMCAsmBackend - Helper template for registering a target specific /// assembler backend. Usage: /// - /// extern "C" void LLVMInitializeFooAsmBackend() { + /// extern "C" void LLVMInitializeFooMCAsmBackend() { /// extern Target TheFooTarget; - /// RegisterAsmBackend X(TheFooTarget); + /// RegisterMCAsmBackend X(TheFooTarget); /// } - template - struct RegisterAsmBackend { - RegisterAsmBackend(Target &T) { - TargetRegistry::RegisterAsmBackend(T, &Allocator); + template + struct RegisterMCAsmBackend { + RegisterMCAsmBackend(Target &T) { + TargetRegistry::RegisterMCAsmBackend(T, &Allocator); } private: - static TargetAsmBackend *Allocator(const Target &T, - const std::string &Triple) { - return new AsmBackendImpl(T, Triple); + static MCAsmBackend *Allocator(const Target &T, StringRef Triple) { + return new MCAsmBackendImpl(T, Triple); } }; - /// RegisterAsmLexer - Helper template for registering a target specific + /// RegisterMCAsmLexer - Helper template for registering a target specific /// assembly lexer, for use in the target machine initialization /// function. Usage: /// - /// extern "C" void LLVMInitializeFooAsmLexer() { + /// extern "C" void LLVMInitializeFooMCAsmLexer() { /// extern Target TheFooTarget; - /// RegisterAsmLexer X(TheFooTarget); + /// RegisterMCAsmLexer X(TheFooTarget); /// } - template - struct RegisterAsmLexer { - RegisterAsmLexer(Target &T) { - TargetRegistry::RegisterAsmLexer(T, &Allocator); + template + struct RegisterMCAsmLexer { + RegisterMCAsmLexer(Target &T) { + TargetRegistry::RegisterMCAsmLexer(T, &Allocator); } private: - static TargetAsmLexer *Allocator(const Target &T, const MCAsmInfo &MAI) { - return new AsmLexerImpl(T, MAI); + static MCTargetAsmLexer *Allocator(const Target &T, + const MCRegisterInfo &MRI, + const MCAsmInfo &MAI) { + return new MCAsmLexerImpl(T, MRI, MAI); } }; - /// RegisterAsmParser - Helper template for registering a target specific + /// RegisterMCAsmParser - Helper template for registering a target specific /// assembly parser, for use in the target machine initialization /// function. Usage: /// - /// extern "C" void LLVMInitializeFooAsmParser() { + /// extern "C" void LLVMInitializeFooMCAsmParser() { /// extern Target TheFooTarget; - /// RegisterAsmParser X(TheFooTarget); + /// RegisterMCAsmParser X(TheFooTarget); /// } - template - struct RegisterAsmParser { - RegisterAsmParser(Target &T) { - TargetRegistry::RegisterAsmParser(T, &Allocator); + template + struct RegisterMCAsmParser { + RegisterMCAsmParser(Target &T) { + TargetRegistry::RegisterMCAsmParser(T, &Allocator); } private: - static TargetAsmParser *Allocator(MCSubtargetInfo &STI, MCAsmParser &P) { - return new AsmParserImpl(STI, P); + static MCTargetAsmParser *Allocator(MCSubtargetInfo &STI, MCAsmParser &P) { + return new MCAsmParserImpl(STI, P); } }; @@ -958,25 +1097,25 @@ namespace llvm { } }; - /// RegisterCodeEmitter - Helper template for registering a target specific + /// RegisterMCCodeEmitter - Helper template for registering a target specific /// machine code emitter, for use in the target initialization /// function. Usage: /// - /// extern "C" void LLVMInitializeFooCodeEmitter() { + /// extern "C" void LLVMInitializeFooMCCodeEmitter() { /// extern Target TheFooTarget; - /// RegisterCodeEmitter X(TheFooTarget); + /// RegisterMCCodeEmitter X(TheFooTarget); /// } - template - struct RegisterCodeEmitter { - RegisterCodeEmitter(Target &T) { - TargetRegistry::RegisterCodeEmitter(T, &Allocator); + template + struct RegisterMCCodeEmitter { + RegisterMCCodeEmitter(Target &T) { + TargetRegistry::RegisterMCCodeEmitter(T, &Allocator); } private: static MCCodeEmitter *Allocator(const MCInstrInfo &II, const MCSubtargetInfo &STI, MCContext &Ctx) { - return new CodeEmitterImpl(); + return new MCCodeEmitterImpl(); } }; diff --git a/contrib/llvm/include/llvm/Target/TargetSelect.h b/contrib/llvm/include/llvm/Support/TargetSelect.h similarity index 75% rename from contrib/llvm/include/llvm/Target/TargetSelect.h rename to contrib/llvm/include/llvm/Support/TargetSelect.h index 272ee0946..83ff68caa 100644 --- a/contrib/llvm/include/llvm/Target/TargetSelect.h +++ b/contrib/llvm/include/llvm/Support/TargetSelect.h @@ -13,8 +13,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_TARGET_TARGETSELECT_H -#define LLVM_TARGET_TARGETSELECT_H +#ifndef LLVM_SUPPORT_TARGETSELECT_H +#define LLVM_SUPPORT_TARGETSELECT_H #include "llvm/Config/llvm-config.h" @@ -26,18 +26,10 @@ extern "C" { #define LLVM_TARGET(TargetName) void LLVMInitialize##TargetName##Target(); #include "llvm/Config/Targets.def" -#define LLVM_TARGET(TargetName) \ - void LLVMInitialize##TargetName##MCAsmInfo(); + // Declare all of the target-MC-initialization functions that are available. +#define LLVM_TARGET(TargetName) void LLVMInitialize##TargetName##TargetMC(); #include "llvm/Config/Targets.def" - -#define LLVM_TARGET(TargetName) \ - void LLVMInitialize##TargetName##MCInstrInfo(); -#include "llvm/Config/Targets.def" - -#define LLVM_TARGET(TargetName) \ - void LLVMInitialize##TargetName##MCSubtargetInfo(); -#include "llvm/Config/Targets.def" - + // Declare all of the available assembly printer initialization functions. #define LLVM_ASM_PRINTER(TargetName) void LLVMInitialize##TargetName##AsmPrinter(); #include "llvm/Config/AsmPrinters.def" @@ -76,35 +68,13 @@ namespace llvm { #include "llvm/Config/Targets.def" } - /// InitializeAllMCAsmInfos - The main program should call this function - /// if it wants access to all available assembly infos for targets that - /// LLVM is configured to support, to make them available via the - /// TargetRegistry. - /// - /// It is legal for a client to make multiple calls to this function. - inline void InitializeAllMCAsmInfos() { -#define LLVM_TARGET(TargetName) LLVMInitialize##TargetName##MCAsmInfo(); -#include "llvm/Config/Targets.def" - } - - /// InitializeAllMCInstrInfos - The main program should call this function - /// if it wants access to all available instruction infos for targets that - /// LLVM is configured to support, to make them available via the - /// TargetRegistry. - /// - /// It is legal for a client to make multiple calls to this function. - inline void InitializeAllMCInstrInfos() { -#define LLVM_TARGET(TargetName) LLVMInitialize##TargetName##MCInstrInfo(); -#include "llvm/Config/Targets.def" - } - - /// InitializeAllMCSubtargetInfos - The main program should call this function - /// if it wants access to all available subtarget infos for targets that LLVM - /// is configured to support, to make them available via the TargetRegistry. + /// InitializeAllTargetMCs - The main program should call this function if it + /// wants access to all available target MC that LLVM is configured to + /// support, to make them available via the TargetRegistry. /// /// It is legal for a client to make multiple calls to this function. - inline void InitializeAllMCSubtargetInfos() { -#define LLVM_TARGET(TargetName) LLVMInitialize##TargetName##MCSubtargetInfo(); + inline void InitializeAllTargetMCs() { +#define LLVM_TARGET(TargetName) LLVMInitialize##TargetName##TargetMC(); #include "llvm/Config/Targets.def" } @@ -148,7 +118,7 @@ namespace llvm { #ifdef LLVM_NATIVE_TARGET LLVM_NATIVE_TARGETINFO(); LLVM_NATIVE_TARGET(); - LLVM_NATIVE_MCASMINFO(); + LLVM_NATIVE_TARGETMC(); return false; #else return true; diff --git a/contrib/llvm/include/llvm/Support/TypeBuilder.h b/contrib/llvm/include/llvm/Support/TypeBuilder.h index 180077897..c75606917 100644 --- a/contrib/llvm/include/llvm/Support/TypeBuilder.h +++ b/contrib/llvm/include/llvm/Support/TypeBuilder.h @@ -18,7 +18,6 @@ #include "llvm/DerivedTypes.h" #include "llvm/LLVMContext.h" #include -#include namespace llvm { @@ -254,9 +253,9 @@ public: template class TypeBuilder { public: static FunctionType *get(LLVMContext &Context) { - std::vector params; - params.reserve(1); - params.push_back(TypeBuilder::get(Context)); + Type *params[] = { + TypeBuilder::get(Context), + }; return FunctionType::get(TypeBuilder::get(Context), params, false); } @@ -265,10 +264,10 @@ template class TypeBuilder { public: static FunctionType *get(LLVMContext &Context) { - std::vector params; - params.reserve(2); - params.push_back(TypeBuilder::get(Context)); - params.push_back(TypeBuilder::get(Context)); + Type *params[] = { + TypeBuilder::get(Context), + TypeBuilder::get(Context), + }; return FunctionType::get(TypeBuilder::get(Context), params, false); } @@ -277,11 +276,11 @@ template class TypeBuilder { public: static FunctionType *get(LLVMContext &Context) { - std::vector params; - params.reserve(3); - params.push_back(TypeBuilder::get(Context)); - params.push_back(TypeBuilder::get(Context)); - params.push_back(TypeBuilder::get(Context)); + Type *params[] = { + TypeBuilder::get(Context), + TypeBuilder::get(Context), + TypeBuilder::get(Context), + }; return FunctionType::get(TypeBuilder::get(Context), params, false); } @@ -292,12 +291,12 @@ template { public: static FunctionType *get(LLVMContext &Context) { - std::vector params; - params.reserve(4); - params.push_back(TypeBuilder::get(Context)); - params.push_back(TypeBuilder::get(Context)); - params.push_back(TypeBuilder::get(Context)); - params.push_back(TypeBuilder::get(Context)); + Type *params[] = { + TypeBuilder::get(Context), + TypeBuilder::get(Context), + TypeBuilder::get(Context), + TypeBuilder::get(Context), + }; return FunctionType::get(TypeBuilder::get(Context), params, false); } @@ -308,13 +307,13 @@ template { public: static FunctionType *get(LLVMContext &Context) { - std::vector params; - params.reserve(5); - params.push_back(TypeBuilder::get(Context)); - params.push_back(TypeBuilder::get(Context)); - params.push_back(TypeBuilder::get(Context)); - params.push_back(TypeBuilder::get(Context)); - params.push_back(TypeBuilder::get(Context)); + Type *params[] = { + TypeBuilder::get(Context), + TypeBuilder::get(Context), + TypeBuilder::get(Context), + TypeBuilder::get(Context), + TypeBuilder::get(Context), + }; return FunctionType::get(TypeBuilder::get(Context), params, false); } @@ -330,9 +329,9 @@ template class TypeBuilder { public: static FunctionType *get(LLVMContext &Context) { - std::vector params; - params.reserve(1); - params.push_back(TypeBuilder::get(Context)); + Type *params[] = { + TypeBuilder::get(Context), + }; return FunctionType::get(TypeBuilder::get(Context), params, true); } }; @@ -340,10 +339,10 @@ template class TypeBuilder { public: static FunctionType *get(LLVMContext &Context) { - std::vector params; - params.reserve(2); - params.push_back(TypeBuilder::get(Context)); - params.push_back(TypeBuilder::get(Context)); + Type *params[] = { + TypeBuilder::get(Context), + TypeBuilder::get(Context), + }; return FunctionType::get(TypeBuilder::get(Context), params, true); } @@ -352,11 +351,11 @@ template class TypeBuilder { public: static FunctionType *get(LLVMContext &Context) { - std::vector params; - params.reserve(3); - params.push_back(TypeBuilder::get(Context)); - params.push_back(TypeBuilder::get(Context)); - params.push_back(TypeBuilder::get(Context)); + Type *params[] = { + TypeBuilder::get(Context), + TypeBuilder::get(Context), + TypeBuilder::get(Context), + }; return FunctionType::get(TypeBuilder::get(Context), params, true); } @@ -367,12 +366,12 @@ template { public: static FunctionType *get(LLVMContext &Context) { - std::vector params; - params.reserve(4); - params.push_back(TypeBuilder::get(Context)); - params.push_back(TypeBuilder::get(Context)); - params.push_back(TypeBuilder::get(Context)); - params.push_back(TypeBuilder::get(Context)); + Type *params[] = { + TypeBuilder::get(Context), + TypeBuilder::get(Context), + TypeBuilder::get(Context), + TypeBuilder::get(Context), + }; return FunctionType::get(TypeBuilder::get(Context), params, true); } @@ -383,13 +382,13 @@ template { public: static FunctionType *get(LLVMContext &Context) { - std::vector params; - params.reserve(5); - params.push_back(TypeBuilder::get(Context)); - params.push_back(TypeBuilder::get(Context)); - params.push_back(TypeBuilder::get(Context)); - params.push_back(TypeBuilder::get(Context)); - params.push_back(TypeBuilder::get(Context)); + Type *params[] = { + TypeBuilder::get(Context), + TypeBuilder::get(Context), + TypeBuilder::get(Context), + TypeBuilder::get(Context), + TypeBuilder::get(Context), + }; return FunctionType::get(TypeBuilder::get(Context), params, true); } diff --git a/contrib/llvm/utils/TableGen/Error.h b/contrib/llvm/include/llvm/TableGen/Error.h similarity index 89% rename from contrib/llvm/utils/TableGen/Error.h rename to contrib/llvm/include/llvm/TableGen/Error.h index b3a014619..c01b32b1c 100644 --- a/contrib/llvm/utils/TableGen/Error.h +++ b/contrib/llvm/include/llvm/TableGen/Error.h @@ -1,4 +1,4 @@ -//===- Error.h - tblgen error handling helper routines ----------*- C++ -*-===// +//===- llvm/TableGen/Error.h - tblgen error handling helpers ----*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef ERROR_H -#define ERROR_H +#ifndef LLVM_TABLEGEN_ERROR_H +#define LLVM_TABLEGEN_ERROR_H #include "llvm/Support/SourceMgr.h" diff --git a/contrib/llvm/include/llvm/TableGen/Main.h b/contrib/llvm/include/llvm/TableGen/Main.h new file mode 100644 index 000000000..deaef4a99 --- /dev/null +++ b/contrib/llvm/include/llvm/TableGen/Main.h @@ -0,0 +1,26 @@ +//===- llvm/TableGen/Main.h - tblgen entry point ----------------*- 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 common entry point for tblgen tools. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TABLEGEN_MAIN_H +#define LLVM_TABLEGEN_MAIN_H + +namespace llvm { + +class TableGenAction; + +/// Run the table generator, performing the specified Action on parsed records. +int TableGenMain(char *argv0, TableGenAction &Action); + +} + +#endif diff --git a/contrib/llvm/utils/TableGen/Record.h b/contrib/llvm/include/llvm/TableGen/Record.h similarity index 80% rename from contrib/llvm/utils/TableGen/Record.h rename to contrib/llvm/include/llvm/TableGen/Record.h index 2f4080bbf..afce76099 100644 --- a/contrib/llvm/utils/TableGen/Record.h +++ b/contrib/llvm/include/llvm/TableGen/Record.h @@ -1,4 +1,4 @@ -//===- Record.h - Classes to represent Table Records ------------*- C++ -*-===// +//===- llvm/TableGen/Record.h - Classes for Table Records -------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -12,9 +12,12 @@ // //===----------------------------------------------------------------------===// -#ifndef RECORD_H -#define RECORD_H +#ifndef LLVM_TABLEGEN_RECORD_H +#define LLVM_TABLEGEN_RECORD_H +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/Support/Allocator.h" #include "llvm/Support/SourceMgr.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/raw_ostream.h" @@ -63,7 +66,10 @@ class RecordKeeper; // Type Classes //===----------------------------------------------------------------------===// -struct RecTy { +class RecTy { + ListRecTy *ListTy; +public: + RecTy() : ListTy(0) {} virtual ~RecTy() {} virtual std::string getAsString() const = 0; @@ -74,6 +80,9 @@ struct RecTy { /// converted to the specified type. virtual bool typeIsConvertibleTo(const RecTy *RHS) const = 0; + /// getListTy - Returns the type representing list. + ListRecTy *getListTy(); + public: // These methods should only be called from subclasses of Init virtual Init *convertValue( UnsetInit *UI) { return 0; } virtual Init *convertValue( BitInit *BI) { return 0; } @@ -124,7 +133,11 @@ inline raw_ostream &operator<<(raw_ostream &OS, const RecTy &Ty) { /// BitRecTy - 'bit' - Represent a single bit /// class BitRecTy : public RecTy { + static BitRecTy Shared; + BitRecTy() {} public: + static BitRecTy *get() { return &Shared; } + virtual Init *convertValue( UnsetInit *UI) { return (Init*)UI; } virtual Init *convertValue( BitInit *BI) { return (Init*)BI; } virtual Init *convertValue( BitsInit *BI); @@ -164,8 +177,9 @@ public: /// class BitsRecTy : public RecTy { unsigned Size; -public: explicit BitsRecTy(unsigned Sz) : Size(Sz) {} +public: + static BitsRecTy *get(unsigned Sz); unsigned getNumBits() const { return Size; } @@ -208,7 +222,11 @@ public: /// IntRecTy - 'int' - Represent an integer value of no particular size /// class IntRecTy : public RecTy { + static IntRecTy Shared; + IntRecTy() {} public: + static IntRecTy *get() { return &Shared; } + virtual Init *convertValue( UnsetInit *UI) { return (Init*)UI; } virtual Init *convertValue( BitInit *BI); virtual Init *convertValue( BitsInit *BI); @@ -246,7 +264,11 @@ public: /// StringRecTy - 'string' - Represent an string value /// class StringRecTy : public RecTy { + static StringRecTy Shared; + StringRecTy() {} public: + static StringRecTy *get() { return &Shared; } + virtual Init *convertValue( UnsetInit *UI) { return (Init*)UI; } virtual Init *convertValue( BitInit *BI) { return 0; } virtual Init *convertValue( BitsInit *BI) { return 0; } @@ -288,9 +310,10 @@ public: /// class ListRecTy : public RecTy { RecTy *Ty; -public: explicit ListRecTy(RecTy *T) : Ty(T) {} - + friend ListRecTy *RecTy::getListTy(); +public: + static ListRecTy *get(RecTy *T) { return T->getListTy(); } RecTy *getElementType() const { return Ty; } virtual Init *convertValue( UnsetInit *UI) { return (Init*)UI; } @@ -331,7 +354,11 @@ public: /// CodeRecTy - 'code' - Represent an code fragment, function or method. /// class CodeRecTy : public RecTy { + static CodeRecTy Shared; + CodeRecTy() {} public: + static CodeRecTy *get() { return &Shared; } + virtual Init *convertValue( UnsetInit *UI) { return (Init*)UI; } virtual Init *convertValue( BitInit *BI) { return 0; } virtual Init *convertValue( BitsInit *BI) { return 0; } @@ -367,7 +394,11 @@ public: /// DagRecTy - 'dag' - Represent a dag fragment /// class DagRecTy : public RecTy { + static DagRecTy Shared; + DagRecTy() {} public: + static DagRecTy *get() { return &Shared; } + virtual Init *convertValue( UnsetInit *UI) { return (Init*)UI; } virtual Init *convertValue( BitInit *BI) { return 0; } virtual Init *convertValue( BitsInit *BI) { return 0; } @@ -407,8 +438,10 @@ public: /// class RecordRecTy : public RecTy { Record *Rec; -public: explicit RecordRecTy(Record *R) : Rec(R) {} + friend class Record; +public: + static RecordRecTy *get(Record *R); Record *getRecord() const { return Rec; } @@ -454,6 +487,12 @@ RecTy *resolveTypes(RecTy *T1, RecTy *T2); //===----------------------------------------------------------------------===// class Init { + Init(const Init &); // Do not define. + Init &operator=(const Init &); // Do not define. + +protected: + Init(void) {} + public: virtual ~Init() {} @@ -466,6 +505,11 @@ public: /// getAsString - Convert this value to a string form. virtual std::string getAsString() const = 0; + /// getAsUnquotedString - Convert this value to a string form, + /// without adding quote markers. This primaruly affects + /// StringInits where we will not surround the string value with + /// quotes. + virtual std::string getAsUnquotedString() const { return getAsString(); } /// dump - Debugging method that may be called through a debugger, just /// invokes print on stderr. @@ -475,14 +519,15 @@ public: /// function that should be overridden to call the appropriate /// RecTy::convertValue method. /// - virtual Init *convertInitializerTo(RecTy *Ty) = 0; + virtual Init *convertInitializerTo(RecTy *Ty) const = 0; /// convertInitializerBitRange - This method is used to implement the bitrange /// selection operator. Given an initializer, it selects the specified bits /// out, returning them as a new init of bits type. If it is not legal to use /// the bit subscript operator on this initializer, return null. /// - virtual Init *convertInitializerBitRange(const std::vector &Bits) { + virtual Init * + convertInitializerBitRange(const std::vector &Bits) const { return 0; } @@ -491,7 +536,8 @@ public: /// elements, returning them as a new init of list type. If it is not legal /// to take a slice of this, return null. /// - virtual Init *convertInitListSlice(const std::vector &Elements) { + virtual Init * + convertInitListSlice(const std::vector &Elements) const { return 0; } @@ -515,8 +561,8 @@ public: /// If a value is set for the variable later, this method will be called on /// users of the value to allow the value to propagate out. /// - virtual Init *resolveReferences(Record &R, const RecordVal *RV) { - return this; + virtual Init *resolveReferences(Record &R, const RecordVal *RV) const { + return const_cast(this); } }; @@ -529,13 +575,20 @@ inline raw_ostream &operator<<(raw_ostream &OS, const Init &I) { /// class TypedInit : public Init { RecTy *Ty; -public: + + TypedInit(const TypedInit &Other); // Do not define. + TypedInit &operator=(const TypedInit &Other); // Do not define. + +protected: explicit TypedInit(RecTy *T) : Ty(T) {} +public: RecTy *getType() const { return Ty; } - virtual Init *convertInitializerBitRange(const std::vector &Bits); - virtual Init *convertInitListSlice(const std::vector &Elements); + virtual Init * + convertInitializerBitRange(const std::vector &Bits) const; + virtual Init * + convertInitListSlice(const std::vector &Elements) const; /// getFieldType - This method is used to implement the FieldInit class. /// Implementors of this method should return the type of the named field if @@ -548,22 +601,28 @@ public: /// simply return the resolved value, otherwise we return null. /// virtual Init *resolveBitReference(Record &R, const RecordVal *RV, - unsigned Bit) = 0; + unsigned Bit) const = 0; /// resolveListElementReference - This method is used to implement /// VarListElementInit::resolveReferences. If the list element is resolvable /// now, we return the resolved value, otherwise we return null. virtual Init *resolveListElementReference(Record &R, const RecordVal *RV, - unsigned Elt) = 0; + unsigned Elt) const = 0; }; /// UnsetInit - ? - Represents an uninitialized value /// class UnsetInit : public Init { + UnsetInit() : Init() {} + UnsetInit(const UnsetInit &); // Do not define. + UnsetInit &operator=(const UnsetInit &Other); // Do not define. + public: - virtual Init *convertInitializerTo(RecTy *Ty) { - return Ty->convertValue(this); + static UnsetInit *get(); + + virtual Init *convertInitializerTo(RecTy *Ty) const { + return Ty->convertValue(const_cast(this)); } virtual bool isComplete() const { return false; } @@ -575,13 +634,18 @@ public: /// class BitInit : public Init { bool Value; -public: + explicit BitInit(bool V) : Value(V) {} + BitInit(const BitInit &Other); // Do not define. + BitInit &operator=(BitInit &Other); // Do not define. + +public: + static BitInit *get(bool V); bool getValue() const { return Value; } - virtual Init *convertInitializerTo(RecTy *Ty) { - return Ty->convertValue(this); + virtual Init *convertInitializerTo(RecTy *Ty) const { + return Ty->convertValue(const_cast(this)); } virtual std::string getAsString() const { return Value ? "1" : "0"; } @@ -590,10 +654,18 @@ public: /// BitsInit - { a, b, c } - Represents an initializer for a BitsRecTy value. /// It contains a vector of bits, whose size is determined by the type. /// -class BitsInit : public Init { +class BitsInit : public Init, public FoldingSetNode { std::vector Bits; + + BitsInit(ArrayRef Range) : Bits(Range.begin(), Range.end()) {} + + BitsInit(const BitsInit &Other); // Do not define. + BitsInit &operator=(const BitsInit &Other); // Do not define. + public: - explicit BitsInit(unsigned Size) : Bits(Size) {} + static BitsInit *get(ArrayRef Range); + + void Profile(FoldingSetNodeID &ID) const; unsigned getNumBits() const { return Bits.size(); } @@ -601,16 +673,12 @@ public: assert(Bit < Bits.size() && "Bit index out of range!"); return Bits[Bit]; } - void setBit(unsigned Bit, Init *V) { - assert(Bit < Bits.size() && "Bit index out of range!"); - assert(Bits[Bit] == 0 && "Bit already set!"); - Bits[Bit] = V; - } - virtual Init *convertInitializerTo(RecTy *Ty) { - return Ty->convertValue(this); + virtual Init *convertInitializerTo(RecTy *Ty) const { + return Ty->convertValue(const_cast(this)); } - virtual Init *convertInitializerBitRange(const std::vector &Bits); + virtual Init * + convertInitializerBitRange(const std::vector &Bits) const; virtual bool isComplete() const { for (unsigned i = 0; i != getNumBits(); ++i) @@ -624,7 +692,7 @@ public: } virtual std::string getAsString() const; - virtual Init *resolveReferences(Record &R, const RecordVal *RV); + virtual Init *resolveReferences(Record &R, const RecordVal *RV) const; }; @@ -632,15 +700,22 @@ public: /// class IntInit : public TypedInit { int64_t Value; + + explicit IntInit(int64_t V) : TypedInit(IntRecTy::get()), Value(V) {} + + IntInit(const IntInit &Other); // Do not define. + IntInit &operator=(const IntInit &Other); // Do note define. + public: - explicit IntInit(int64_t V) : TypedInit(new IntRecTy), Value(V) {} + static IntInit *get(int64_t V); int64_t getValue() const { return Value; } - virtual Init *convertInitializerTo(RecTy *Ty) { - return Ty->convertValue(this); + virtual Init *convertInitializerTo(RecTy *Ty) const { + return Ty->convertValue(const_cast(this)); } - virtual Init *convertInitializerBitRange(const std::vector &Bits); + virtual Init * + convertInitializerBitRange(const std::vector &Bits) const; virtual std::string getAsString() const; @@ -649,7 +724,7 @@ public: /// simply return the resolved value, otherwise we return null. /// virtual Init *resolveBitReference(Record &R, const RecordVal *RV, - unsigned Bit) { + unsigned Bit) const { assert(0 && "Illegal bit reference off int"); return 0; } @@ -658,7 +733,7 @@ public: /// VarListElementInit::resolveReferences. If the list element is resolvable /// now, we return the resolved value, otherwise we return null. virtual Init *resolveListElementReference(Record &R, const RecordVal *RV, - unsigned Elt) { + unsigned Elt) const { assert(0 && "Illegal element reference off int"); return 0; } @@ -669,24 +744,31 @@ public: /// class StringInit : public TypedInit { std::string Value; -public: + explicit StringInit(const std::string &V) - : TypedInit(new StringRecTy), Value(V) {} + : TypedInit(StringRecTy::get()), Value(V) {} + + StringInit(const StringInit &Other); // Do not define. + StringInit &operator=(const StringInit &Other); // Do not define. + +public: + static StringInit *get(const std::string &V); const std::string &getValue() const { return Value; } - virtual Init *convertInitializerTo(RecTy *Ty) { - return Ty->convertValue(this); + virtual Init *convertInitializerTo(RecTy *Ty) const { + return Ty->convertValue(const_cast(this)); } virtual std::string getAsString() const { return "\"" + Value + "\""; } + virtual std::string getAsUnquotedString() const { return Value; } /// resolveBitReference - This method is used to implement /// VarBitInit::resolveReferences. If the bit is able to be resolved, we /// simply return the resolved value, otherwise we return null. /// virtual Init *resolveBitReference(Record &R, const RecordVal *RV, - unsigned Bit) { + unsigned Bit) const { assert(0 && "Illegal bit reference off string"); return 0; } @@ -695,7 +777,7 @@ public: /// VarListElementInit::resolveReferences. If the list element is resolvable /// now, we return the resolved value, otherwise we return null. virtual Init *resolveListElementReference(Record &R, const RecordVal *RV, - unsigned Elt) { + unsigned Elt) const { assert(0 && "Illegal element reference off string"); return 0; } @@ -705,13 +787,19 @@ public: /// class CodeInit : public Init { std::string Value; -public: + explicit CodeInit(const std::string &V) : Value(V) {} + CodeInit(const CodeInit &Other); // Do not define. + CodeInit &operator=(const CodeInit &Other); // Do not define. + +public: + static CodeInit *get(const std::string &V); + const std::string &getValue() const { return Value; } - virtual Init *convertInitializerTo(RecTy *Ty) { - return Ty->convertValue(this); + virtual Init *convertInitializerTo(RecTy *Ty) const { + return Ty->convertValue(const_cast(this)); } virtual std::string getAsString() const { return "[{" + Value + "}]"; } @@ -719,18 +807,22 @@ public: /// ListInit - [AL, AH, CL] - Represent a list of defs /// -class ListInit : public TypedInit { +class ListInit : public TypedInit, public FoldingSetNode { std::vector Values; public: - typedef std::vector::iterator iterator; typedef std::vector::const_iterator const_iterator; - explicit ListInit(std::vector &Vs, RecTy *EltTy) - : TypedInit(new ListRecTy(EltTy)) { - Values.swap(Vs); - } - explicit ListInit(iterator Start, iterator End, RecTy *EltTy) - : TypedInit(new ListRecTy(EltTy)), Values(Start, End) {} +private: + explicit ListInit(ArrayRef Range, RecTy *EltTy) + : TypedInit(ListRecTy::get(EltTy)), Values(Range.begin(), Range.end()) {} + + ListInit(const ListInit &Other); // Do not define. + ListInit &operator=(const ListInit &Other); // Do not define. + +public: + static ListInit *get(ArrayRef Range, RecTy *EltTy); + + void Profile(FoldingSetNodeID &ID) const; unsigned getSize() const { return Values.size(); } Init *getElement(unsigned i) const { @@ -740,10 +832,10 @@ public: Record *getElementAsRecord(unsigned i) const; - Init *convertInitListSlice(const std::vector &Elements); + Init *convertInitListSlice(const std::vector &Elements) const; - virtual Init *convertInitializerTo(RecTy *Ty) { - return Ty->convertValue(this); + virtual Init *convertInitializerTo(RecTy *Ty) const { + return Ty->convertValue(const_cast(this)); } /// resolveReferences - This method is used by classes that refer to other @@ -751,13 +843,13 @@ public: /// If a value is set for the variable later, this method will be called on /// users of the value to allow the value to propagate out. /// - virtual Init *resolveReferences(Record &R, const RecordVal *RV); + virtual Init *resolveReferences(Record &R, const RecordVal *RV) const; virtual std::string getAsString() const; - inline iterator begin() { return Values.begin(); } + ArrayRef getValues() const { return Values; } + inline const_iterator begin() const { return Values.begin(); } - inline iterator end () { return Values.end(); } inline const_iterator end () const { return Values.end(); } inline size_t size () const { return Values.size(); } @@ -768,7 +860,7 @@ public: /// simply return the resolved value, otherwise we return null. /// virtual Init *resolveBitReference(Record &R, const RecordVal *RV, - unsigned Bit) { + unsigned Bit) const { assert(0 && "Illegal bit reference off list"); return 0; } @@ -777,34 +869,38 @@ public: /// VarListElementInit::resolveReferences. If the list element is resolvable /// now, we return the resolved value, otherwise we return null. virtual Init *resolveListElementReference(Record &R, const RecordVal *RV, - unsigned Elt); + unsigned Elt) const; }; /// OpInit - Base class for operators /// class OpInit : public TypedInit { -public: - OpInit(RecTy *Type) : TypedInit(Type) {} + OpInit(const OpInit &Other); // Do not define. + OpInit &operator=(OpInit &Other); // Do not define. +protected: + explicit OpInit(RecTy *Type) : TypedInit(Type) {} + +public: // Clone - Clone this operator, replacing arguments with the new list - virtual OpInit *clone(std::vector &Operands) = 0; + virtual OpInit *clone(std::vector &Operands) const = 0; virtual int getNumOperands() const = 0; - virtual Init *getOperand(int i) = 0; + virtual Init *getOperand(int i) const = 0; // Fold - If possible, fold this to a simpler init. Return this if not // possible to fold. - virtual Init *Fold(Record *CurRec, MultiClass *CurMultiClass) = 0; + virtual Init *Fold(Record *CurRec, MultiClass *CurMultiClass) const = 0; - virtual Init *convertInitializerTo(RecTy *Ty) { - return Ty->convertValue(this); + virtual Init *convertInitializerTo(RecTy *Ty) const { + return Ty->convertValue(const_cast(this)); } virtual Init *resolveBitReference(Record &R, const RecordVal *RV, - unsigned Bit); + unsigned Bit) const; virtual Init *resolveListElementReference(Record &R, const RecordVal *RV, - unsigned Elt); + unsigned Elt) const; }; @@ -816,20 +912,25 @@ public: private: UnaryOp Opc; Init *LHS; + + UnOpInit(UnaryOp opc, Init *lhs, RecTy *Type) + : OpInit(Type), Opc(opc), LHS(lhs) {} + + UnOpInit(const UnOpInit &Other); // Do not define. + UnOpInit &operator=(const UnOpInit &Other); // Do not define. + public: - UnOpInit(UnaryOp opc, Init *lhs, RecTy *Type) : - OpInit(Type), Opc(opc), LHS(lhs) { - } + static UnOpInit *get(UnaryOp opc, Init *lhs, RecTy *Type); // Clone - Clone this operator, replacing arguments with the new list - virtual OpInit *clone(std::vector &Operands) { + virtual OpInit *clone(std::vector &Operands) const { assert(Operands.size() == 1 && "Wrong number of operands for unary operation"); - return new UnOpInit(getOpcode(), *Operands.begin(), getType()); + return UnOpInit::get(getOpcode(), *Operands.begin(), getType()); } int getNumOperands() const { return 1; } - Init *getOperand(int i) { + Init *getOperand(int i) const { assert(i == 0 && "Invalid operand id for unary operator"); return getOperand(); } @@ -839,9 +940,9 @@ public: // Fold - If possible, fold this to a simpler init. Return this if not // possible to fold. - Init *Fold(Record *CurRec, MultiClass *CurMultiClass); + Init *Fold(Record *CurRec, MultiClass *CurMultiClass) const; - virtual Init *resolveReferences(Record &R, const RecordVal *RV); + virtual Init *resolveReferences(Record &R, const RecordVal *RV) const; virtual std::string getAsString() const; }; @@ -854,20 +955,26 @@ public: private: BinaryOp Opc; Init *LHS, *RHS; -public: + BinOpInit(BinaryOp opc, Init *lhs, Init *rhs, RecTy *Type) : - OpInit(Type), Opc(opc), LHS(lhs), RHS(rhs) { - } + OpInit(Type), Opc(opc), LHS(lhs), RHS(rhs) {} + + BinOpInit(const BinOpInit &Other); // Do not define. + BinOpInit &operator=(const BinOpInit &Other); // Do not define. + +public: + static BinOpInit *get(BinaryOp opc, Init *lhs, Init *rhs, + RecTy *Type); // Clone - Clone this operator, replacing arguments with the new list - virtual OpInit *clone(std::vector &Operands) { + virtual OpInit *clone(std::vector &Operands) const { assert(Operands.size() == 2 && "Wrong number of operands for binary operation"); - return new BinOpInit(getOpcode(), Operands[0], Operands[1], getType()); + return BinOpInit::get(getOpcode(), Operands[0], Operands[1], getType()); } int getNumOperands() const { return 2; } - Init *getOperand(int i) { + Init *getOperand(int i) const { assert((i == 0 || i == 1) && "Invalid operand id for binary operator"); if (i == 0) { return getLHS(); @@ -882,9 +989,9 @@ public: // Fold - If possible, fold this to a simpler init. Return this if not // possible to fold. - Init *Fold(Record *CurRec, MultiClass *CurMultiClass); + Init *Fold(Record *CurRec, MultiClass *CurMultiClass) const; - virtual Init *resolveReferences(Record &R, const RecordVal *RV); + virtual Init *resolveReferences(Record &R, const RecordVal *RV) const; virtual std::string getAsString() const; }; @@ -897,21 +1004,29 @@ public: private: TernaryOp Opc; Init *LHS, *MHS, *RHS; + + TernOpInit(TernaryOp opc, Init *lhs, Init *mhs, Init *rhs, + RecTy *Type) : + OpInit(Type), Opc(opc), LHS(lhs), MHS(mhs), RHS(rhs) {} + + TernOpInit(const TernOpInit &Other); // Do not define. + TernOpInit &operator=(const TernOpInit &Other); // Do not define. + public: - TernOpInit(TernaryOp opc, Init *lhs, Init *mhs, Init *rhs, RecTy *Type) : - OpInit(Type), Opc(opc), LHS(lhs), MHS(mhs), RHS(rhs) { - } + static TernOpInit *get(TernaryOp opc, Init *lhs, + Init *mhs, Init *rhs, + RecTy *Type); // Clone - Clone this operator, replacing arguments with the new list - virtual OpInit *clone(std::vector &Operands) { + virtual OpInit *clone(std::vector &Operands) const { assert(Operands.size() == 3 && "Wrong number of operands for ternary operation"); - return new TernOpInit(getOpcode(), Operands[0], Operands[1], Operands[2], - getType()); + return TernOpInit::get(getOpcode(), Operands[0], Operands[1], Operands[2], + getType()); } int getNumOperands() const { return 3; } - Init *getOperand(int i) { + Init *getOperand(int i) const { assert((i == 0 || i == 1 || i == 2) && "Invalid operand id for ternary operator"); if (i == 0) { @@ -930,11 +1045,11 @@ public: // Fold - If possible, fold this to a simpler init. Return this if not // possible to fold. - Init *Fold(Record *CurRec, MultiClass *CurMultiClass); + Init *Fold(Record *CurRec, MultiClass *CurMultiClass) const; virtual bool isComplete() const { return false; } - virtual Init *resolveReferences(Record &R, const RecordVal *RV); + virtual Init *resolveReferences(Record &R, const RecordVal *RV) const; virtual std::string getAsString() const; }; @@ -944,20 +1059,27 @@ public: /// class VarInit : public TypedInit { std::string VarName; -public: + explicit VarInit(const std::string &VN, RecTy *T) - : TypedInit(T), VarName(VN) {} + : TypedInit(T), VarName(VN) {} + + VarInit(const VarInit &Other); // Do not define. + VarInit &operator=(const VarInit &Other); // Do not define. + +public: + static VarInit *get(const std::string &VN, RecTy *T); + static VarInit *get(Init *VN, RecTy *T); - virtual Init *convertInitializerTo(RecTy *Ty) { - return Ty->convertValue(this); + virtual Init *convertInitializerTo(RecTy *Ty) const { + return Ty->convertValue(const_cast(this)); } const std::string &getName() const { return VarName; } virtual Init *resolveBitReference(Record &R, const RecordVal *RV, - unsigned Bit); + unsigned Bit) const; virtual Init *resolveListElementReference(Record &R, const RecordVal *RV, - unsigned Elt); + unsigned Elt) const; virtual RecTy *getFieldType(const std::string &FieldName) const; virtual Init *getFieldInit(Record &R, const RecordVal *RV, @@ -968,7 +1090,7 @@ public: /// If a value is set for the variable later, this method will be called on /// users of the value to allow the value to propagate out. /// - virtual Init *resolveReferences(Record &R, const RecordVal *RV); + virtual Init *resolveReferences(Record &R, const RecordVal *RV) const; virtual std::string getAsString() const { return VarName; } }; @@ -979,22 +1101,28 @@ public: class VarBitInit : public Init { TypedInit *TI; unsigned Bit; -public: + VarBitInit(TypedInit *T, unsigned B) : TI(T), Bit(B) { assert(T->getType() && dynamic_cast(T->getType()) && ((BitsRecTy*)T->getType())->getNumBits() > B && "Illegal VarBitInit expression!"); } - virtual Init *convertInitializerTo(RecTy *Ty) { - return Ty->convertValue(this); + VarBitInit(const VarBitInit &Other); // Do not define. + VarBitInit &operator=(const VarBitInit &Other); // Do not define. + +public: + static VarBitInit *get(TypedInit *T, unsigned B); + + virtual Init *convertInitializerTo(RecTy *Ty) const { + return Ty->convertValue(const_cast(this)); } TypedInit *getVariable() const { return TI; } unsigned getBitNum() const { return Bit; } virtual std::string getAsString() const; - virtual Init *resolveReferences(Record &R, const RecordVal *RV); + virtual Init *resolveReferences(Record &R, const RecordVal *RV) const; }; /// VarListElementInit - List[4] - Represent access to one element of a var or @@ -1002,43 +1130,59 @@ public: class VarListElementInit : public TypedInit { TypedInit *TI; unsigned Element; -public: + VarListElementInit(TypedInit *T, unsigned E) - : TypedInit(dynamic_cast(T->getType())->getElementType()), - TI(T), Element(E) { + : TypedInit(dynamic_cast(T->getType())->getElementType()), + TI(T), Element(E) { assert(T->getType() && dynamic_cast(T->getType()) && "Illegal VarBitInit expression!"); } - virtual Init *convertInitializerTo(RecTy *Ty) { - return Ty->convertValue(this); + VarListElementInit(const VarListElementInit &Other); // Do not define. + VarListElementInit &operator=(const VarListElementInit &Other); // Do + // not + // define. + +public: + static VarListElementInit *get(TypedInit *T, unsigned E); + + virtual Init *convertInitializerTo(RecTy *Ty) const { + return Ty->convertValue(const_cast(this)); } TypedInit *getVariable() const { return TI; } unsigned getElementNum() const { return Element; } virtual Init *resolveBitReference(Record &R, const RecordVal *RV, - unsigned Bit); + unsigned Bit) const; /// resolveListElementReference - This method is used to implement /// VarListElementInit::resolveReferences. If the list element is resolvable /// now, we return the resolved value, otherwise we return null. - virtual Init *resolveListElementReference(Record &R, const RecordVal *RV, - unsigned Elt); + virtual Init *resolveListElementReference(Record &R, + const RecordVal *RV, + unsigned Elt) const; virtual std::string getAsString() const; - virtual Init *resolveReferences(Record &R, const RecordVal *RV); + virtual Init *resolveReferences(Record &R, const RecordVal *RV) const; }; /// DefInit - AL - Represent a reference to a 'def' in the description /// class DefInit : public TypedInit { Record *Def; + + DefInit(Record *D, RecordRecTy *T) : TypedInit(T), Def(D) {} + friend class Record; + + DefInit(const DefInit &Other); // Do not define. + DefInit &operator=(const DefInit &Other); // Do not define. + public: - explicit DefInit(Record *D) : TypedInit(new RecordRecTy(D)), Def(D) {} + static DefInit *get(Record*); - virtual Init *convertInitializerTo(RecTy *Ty) { - return Ty->convertValue(this); + virtual Init *convertInitializerTo(RecTy *Ty) const { + return Ty->convertValue(const_cast(this)); } Record *getDef() const { return Def; } @@ -1056,7 +1200,7 @@ public: /// simply return the resolved value, otherwise we return null. /// virtual Init *resolveBitReference(Record &R, const RecordVal *RV, - unsigned Bit) { + unsigned Bit) const { assert(0 && "Illegal bit reference off def"); return 0; } @@ -1065,7 +1209,7 @@ public: /// VarListElementInit::resolveReferences. If the list element is resolvable /// now, we return the resolved value, otherwise we return null. virtual Init *resolveListElementReference(Record &R, const RecordVal *RV, - unsigned Elt) { + unsigned Elt) const { assert(0 && "Illegal element reference off def"); return 0; } @@ -1077,22 +1221,30 @@ public: class FieldInit : public TypedInit { Init *Rec; // Record we are referring to std::string FieldName; // Field we are accessing -public: + FieldInit(Init *R, const std::string &FN) - : TypedInit(R->getFieldType(FN)), Rec(R), FieldName(FN) { + : TypedInit(R->getFieldType(FN)), Rec(R), FieldName(FN) { assert(getType() && "FieldInit with non-record type!"); } - virtual Init *convertInitializerTo(RecTy *Ty) { - return Ty->convertValue(this); + FieldInit(const FieldInit &Other); // Do not define. + FieldInit &operator=(const FieldInit &Other); // Do not define. + +public: + static FieldInit *get(Init *R, const std::string &FN); + static FieldInit *get(Init *R, const Init *FN); + + virtual Init *convertInitializerTo(RecTy *Ty) const { + return Ty->convertValue(const_cast(this)); } virtual Init *resolveBitReference(Record &R, const RecordVal *RV, - unsigned Bit); - virtual Init *resolveListElementReference(Record &R, const RecordVal *RV, - unsigned Elt); + unsigned Bit) const; + virtual Init *resolveListElementReference(Record &R, + const RecordVal *RV, + unsigned Elt) const; - virtual Init *resolveReferences(Record &R, const RecordVal *RV); + virtual Init *resolveReferences(Record &R, const RecordVal *RV) const; virtual std::string getAsString() const { return Rec->getAsString() + "." + FieldName; @@ -1103,29 +1255,34 @@ public: /// to have at least one value then a (possibly empty) list of arguments. Each /// argument can have a name associated with it. /// -class DagInit : public TypedInit { +class DagInit : public TypedInit, public FoldingSetNode { Init *Val; std::string ValName; std::vector Args; std::vector ArgNames; + + DagInit(Init *V, const std::string &VN, + ArrayRef ArgRange, + ArrayRef NameRange) + : TypedInit(DagRecTy::get()), Val(V), ValName(VN), + Args(ArgRange.begin(), ArgRange.end()), + ArgNames(NameRange.begin(), NameRange.end()) {} + + DagInit(const DagInit &Other); // Do not define. + DagInit &operator=(const DagInit &Other); // Do not define. + public: - DagInit(Init *V, std::string VN, - const std::vector > &args) - : TypedInit(new DagRecTy), Val(V), ValName(VN) { - Args.reserve(args.size()); - ArgNames.reserve(args.size()); - for (unsigned i = 0, e = args.size(); i != e; ++i) { - Args.push_back(args[i].first); - ArgNames.push_back(args[i].second); - } - } - DagInit(Init *V, std::string VN, const std::vector &args, - const std::vector &argNames) - : TypedInit(new DagRecTy), Val(V), ValName(VN), Args(args), - ArgNames(argNames) { } + static DagInit *get(Init *V, const std::string &VN, + ArrayRef ArgRange, + ArrayRef NameRange); + static DagInit *get(Init *V, const std::string &VN, + const std::vector< + std::pair > &args); + + void Profile(FoldingSetNodeID &ID) const; - virtual Init *convertInitializerTo(RecTy *Ty) { - return Ty->convertValue(this); + virtual Init *convertInitializerTo(RecTy *Ty) const { + return Ty->convertValue(const_cast(this)); } Init *getOperator() const { return Val; } @@ -1142,44 +1299,33 @@ public: return ArgNames[Num]; } - void setArg(unsigned Num, Init *I) { - assert(Num < Args.size() && "Arg number out of range!"); - Args[Num] = I; - } - - virtual Init *resolveReferences(Record &R, const RecordVal *RV); + virtual Init *resolveReferences(Record &R, const RecordVal *RV) const; virtual std::string getAsString() const; - typedef std::vector::iterator arg_iterator; typedef std::vector::const_iterator const_arg_iterator; - typedef std::vector::iterator name_iterator; typedef std::vector::const_iterator const_name_iterator; - inline arg_iterator arg_begin() { return Args.begin(); } inline const_arg_iterator arg_begin() const { return Args.begin(); } - inline arg_iterator arg_end () { return Args.end(); } inline const_arg_iterator arg_end () const { return Args.end(); } inline size_t arg_size () const { return Args.size(); } inline bool arg_empty() const { return Args.empty(); } - inline name_iterator name_begin() { return ArgNames.begin(); } inline const_name_iterator name_begin() const { return ArgNames.begin(); } - inline name_iterator name_end () { return ArgNames.end(); } inline const_name_iterator name_end () const { return ArgNames.end(); } inline size_t name_size () const { return ArgNames.size(); } inline bool name_empty() const { return ArgNames.empty(); } virtual Init *resolveBitReference(Record &R, const RecordVal *RV, - unsigned Bit) { + unsigned Bit) const { assert(0 && "Illegal bit reference off dag"); return 0; } virtual Init *resolveListElementReference(Record &R, const RecordVal *RV, - unsigned Elt) { + unsigned Elt) const { assert(0 && "Illegal element reference off dag"); return 0; } @@ -1190,14 +1336,15 @@ public: //===----------------------------------------------------------------------===// class RecordVal { - std::string Name; + Init *Name; RecTy *Ty; unsigned Prefix; Init *Value; public: + RecordVal(Init *N, RecTy *T, unsigned P); RecordVal(const std::string &N, RecTy *T, unsigned P); - const std::string &getName() const { return Name; } + const std::string &getName() const; unsigned getPrefix() const { return Prefix; } RecTy *getType() const { return Ty; } @@ -1226,7 +1373,7 @@ class Record { // Unique record ID. unsigned ID; - std::string Name; + Init *Name; SMLoc Loc; std::vector TemplateArgs; std::vector Values; @@ -1235,11 +1382,15 @@ class Record { // Tracks Record instances. Not owned by Record. RecordKeeper &TrackedRecords; + DefInit *TheInit; + + void checkName(); + public: // Constructs a record. explicit Record(const std::string &N, SMLoc loc, RecordKeeper &records) : - ID(LastID++), Name(N), Loc(loc), TrackedRecords(records) {} + ID(LastID++), Name(StringInit::get(N)), Loc(loc), TrackedRecords(records), TheInit(0) {} ~Record() {} @@ -1248,11 +1399,15 @@ public: unsigned getID() const { return ID; } - const std::string &getName() const { return Name; } + const std::string &getName() const; + void setName(Init *Name); // Also updates RecordKeeper. void setName(const std::string &Name); // Also updates RecordKeeper. SMLoc getLoc() const { return Loc; } + /// get the corresponding DefInit. + DefInit *getDefInit(); + const std::vector &getTemplateArgs() const { return TemplateArgs; } diff --git a/contrib/llvm/include/llvm/TableGen/TableGenAction.h b/contrib/llvm/include/llvm/TableGen/TableGenAction.h new file mode 100644 index 000000000..9f1c23c5b --- /dev/null +++ b/contrib/llvm/include/llvm/TableGen/TableGenAction.h @@ -0,0 +1,34 @@ +//===- llvm/TableGen/TableGenAction.h - defines TableGenAction --*- 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 TableGenAction base class to be derived from by +// tblgen tools. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TABLEGEN_TABLEGENACTION_H +#define LLVM_TABLEGEN_TABLEGENACTION_H + +namespace llvm { + +class raw_ostream; +class RecordKeeper; + +class TableGenAction { +public: + virtual ~TableGenAction() {} + + /// Perform the action using Records, and write output to OS. + /// @returns true on error, false otherwise + virtual bool operator()(raw_ostream &OS, RecordKeeper &Records) = 0; +}; + +} + +#endif diff --git a/contrib/llvm/utils/TableGen/TableGenBackend.h b/contrib/llvm/include/llvm/TableGen/TableGenBackend.h similarity index 88% rename from contrib/llvm/utils/TableGen/TableGenBackend.h rename to contrib/llvm/include/llvm/TableGen/TableGenBackend.h index 9c2b948b0..853f92e40 100644 --- a/contrib/llvm/utils/TableGen/TableGenBackend.h +++ b/contrib/llvm/include/llvm/TableGen/TableGenBackend.h @@ -1,4 +1,4 @@ -//===- TableGenBackend.h - Base class for TableGen Backends -----*- C++ -*-===// +//===- llvm/TableGen/TableGenBackend.h - Backend base class -----*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef TABLEGENBACKEND_H -#define TABLEGENBACKEND_H +#ifndef LLVM_TABLEGEN_TABLEGENBACKEND_H +#define LLVM_TABLEGEN_TABLEGENBACKEND_H #include "llvm/Support/raw_ostream.h" #include diff --git a/contrib/llvm/include/llvm/Target/Target.td b/contrib/llvm/include/llvm/Target/Target.td index 018ccbd72..aa9a4f5af 100644 --- a/contrib/llvm/include/llvm/Target/Target.td +++ b/contrib/llvm/include/llvm/Target/Target.td @@ -297,6 +297,10 @@ class Instruction { // from the opcode. int Size = 0; + // DecoderNamespace - The "namespace" in which this instruction exists, on + // targets like ARM which multiple ISA namespaces exist. + string DecoderNamespace = ""; + // Code size, for instruction selection. // FIXME: What does this actually mean? int CodeSize = 0; @@ -324,6 +328,7 @@ class Instruction { bit isPredicable = 0; // Is this instruction predicable? bit hasDelaySlot = 0; // Does this instruction have an delay slot? bit usesCustomInserter = 0; // Pseudo instr needing special help. + bit hasPostISelHook = 0; // To be *adjusted* after isel by target hook. bit hasCtrlDep = 0; // Does this instruction r/w ctrl-flow chains? bit isNotDuplicable = 0; // Is it unsafe to duplicate this instruction? bit isAsCheapAsAMove = 0; // As cheap (or cheaper) than a move instruction. @@ -581,7 +586,7 @@ class InstrInfo { // Standard Pseudo Instructions. // This list must match TargetOpcodes.h and CodeGenTarget.cpp. // Only these instructions are allowed in the TargetOpcode namespace. -let isCodeGenOnly = 1, Namespace = "TargetOpcode" in { +let isCodeGenOnly = 1, isPseudo = 1, Namespace = "TargetOpcode" in { def PHI : Instruction { let OutOperandList = (outs); let InOperandList = (ins variable_ops); diff --git a/contrib/llvm/include/llvm/Target/TargetAsmInfo.h b/contrib/llvm/include/llvm/Target/TargetAsmInfo.h deleted file mode 100644 index 5a526dceb..000000000 --- a/contrib/llvm/include/llvm/Target/TargetAsmInfo.h +++ /dev/null @@ -1,103 +0,0 @@ -//===-- llvm/Target/TargetAsmInfo.h -----------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Interface to provide the information necessary for producing assembly files. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TARGET_TARGETASMINFO_H -#define LLVM_TARGET_TARGETASMINFO_H - -#include "llvm/CodeGen/MachineLocation.h" -#include "llvm/Target/TargetLoweringObjectFile.h" -#include "llvm/Target/TargetFrameLowering.h" -#include "llvm/Target/TargetRegisterInfo.h" - -namespace llvm { - template class ArrayRef; - class MCSection; - class MCContext; - class MachineFunction; - class TargetMachine; - class TargetLoweringObjectFile; - -class TargetAsmInfo { - std::vector InitialFrameState; - const TargetRegisterInfo *TRI; - const TargetFrameLowering *TFI; - const TargetLoweringObjectFile *TLOF; - -public: - explicit TargetAsmInfo(const TargetMachine &TM); - - const MCSection *getDwarfLineSection() const { - return TLOF->getDwarfLineSection(); - } - - const MCSection *getEHFrameSection() const { - return TLOF->getEHFrameSection(); - } - - const MCSection *getCompactUnwindSection() const { - return TLOF->getCompactUnwindSection(); - } - - const MCSection *getDwarfFrameSection() const { - return TLOF->getDwarfFrameSection(); - } - - const MCSection *getWin64EHFuncTableSection(StringRef Suffix) const { - return TLOF->getWin64EHFuncTableSection(Suffix); - } - - const MCSection *getWin64EHTableSection(StringRef Suffix) const { - return TLOF->getWin64EHTableSection(Suffix); - } - - unsigned getFDEEncoding(bool CFI) const { - return TLOF->getFDEEncoding(CFI); - } - - bool isFunctionEHFrameSymbolPrivate() const { - return TLOF->isFunctionEHFrameSymbolPrivate(); - } - - int getCompactUnwindEncoding(ArrayRef Instrs, - int DataAlignmentFactor, - bool IsEH) const { - return TFI->getCompactUnwindEncoding(Instrs, DataAlignmentFactor, IsEH); - } - - const unsigned *getCalleeSavedRegs(MachineFunction *MF = 0) const { - return TRI->getCalleeSavedRegs(MF); - } - - unsigned getDwarfRARegNum(bool isEH) const { - return TRI->getDwarfRegNum(TRI->getRARegister(), isEH); - } - - const std::vector &getInitialFrameState() const { - return InitialFrameState; - } - - int getDwarfRegNum(unsigned RegNum, bool isEH) const { - return TRI->getDwarfRegNum(RegNum, isEH); - } - - int getLLVMRegNum(unsigned DwarfRegNum, bool isEH) const { - return TRI->getLLVMRegNum(DwarfRegNum, isEH); - } - - int getSEHRegNum(unsigned RegNum) const { - return TRI->getSEHRegNum(RegNum); - } -}; - -} -#endif diff --git a/contrib/llvm/include/llvm/Target/TargetData.h b/contrib/llvm/include/llvm/Target/TargetData.h index c28081000..26fd1870a 100644 --- a/contrib/llvm/include/llvm/Target/TargetData.h +++ b/contrib/llvm/include/llvm/Target/TargetData.h @@ -33,6 +33,8 @@ class StructType; class StructLayout; class GlobalVariable; class LLVMContext; +template +class ArrayRef; /// Enum used to categorize the alignment types stored by TargetAlignElem enum AlignTypeEnum { @@ -42,6 +44,7 @@ enum AlignTypeEnum { AGGREGATE_ALIGN = 'a', ///< Aggregate alignment STACK_ALIGN = 's' ///< Stack objects alignment }; + /// Target alignment element. /// /// Stores the alignment data associated with a given alignment type (pointer, @@ -62,12 +65,19 @@ struct TargetAlignElem { bool operator==(const TargetAlignElem &rhs) const; }; +/// TargetData - This class holds a parsed version of the target data layout +/// string in a module and provides methods for querying it. The target data +/// layout string is specified *by the target* - a frontend generating LLVM IR +/// is required to generate the right target data for the target being codegen'd +/// to. If some measure of portability is desired, an empty string may be +/// specified in the module. class TargetData : public ImmutablePass { private: bool LittleEndian; ///< Defaults to false unsigned PointerMemSize; ///< Pointer size in bytes unsigned PointerABIAlign; ///< Pointer ABI alignment unsigned PointerPrefAlign; ///< Pointer preferred alignment + unsigned StackNaturalAlign; ///< Stack natural alignment SmallVector LegalIntWidths; ///< Legal Integers. @@ -90,9 +100,9 @@ private: void setAlignment(AlignTypeEnum align_type, unsigned abi_align, unsigned pref_align, uint32_t bit_width); unsigned getAlignmentInfo(AlignTypeEnum align_type, uint32_t bit_width, - bool ABIAlign, const Type *Ty) const; + bool ABIAlign, Type *Ty) const; //! Internal helper method that returns requested alignment for type. - unsigned getAlignment(const Type *Ty, bool abi_or_pref) const; + unsigned getAlignment(Type *Ty, bool abi_or_pref) const; /// Valid alignment predicate. /// @@ -161,6 +171,11 @@ public: return !isLegalInteger(Width); } + /// Returns true if the given alignment exceeds the natural stack alignment. + bool exceedsNaturalStackAlignment(unsigned Align) const { + return (StackNaturalAlign != 0) && (Align > StackNaturalAlign); + } + /// fitsInLegalInteger - This function returns true if the specified type fits /// in a native integer type supported by the CPU. For example, if the CPU /// only supports i32 as a native integer type, then i27 fits in a legal @@ -200,19 +215,19 @@ public: /// getTypeSizeInBits - Return the number of bits necessary to hold the /// specified type. For example, returns 36 for i36 and 80 for x86_fp80. - uint64_t getTypeSizeInBits(const Type* Ty) const; + uint64_t getTypeSizeInBits(Type* Ty) const; /// getTypeStoreSize - Return the maximum number of bytes that may be /// overwritten by storing the specified type. For example, returns 5 /// for i36 and 10 for x86_fp80. - uint64_t getTypeStoreSize(const Type *Ty) const { + uint64_t getTypeStoreSize(Type *Ty) const { return (getTypeSizeInBits(Ty)+7)/8; } /// getTypeStoreSizeInBits - Return the maximum number of bits that may be /// overwritten by storing the specified type; always a multiple of 8. For /// example, returns 40 for i36 and 80 for x86_fp80. - uint64_t getTypeStoreSizeInBits(const Type *Ty) const { + uint64_t getTypeStoreSizeInBits(Type *Ty) const { return 8*getTypeStoreSize(Ty); } @@ -220,7 +235,7 @@ public: /// of the specified type, including alignment padding. This is the amount /// that alloca reserves for this type. For example, returns 12 or 16 for /// x86_fp80, depending on alignment. - uint64_t getTypeAllocSize(const Type* Ty) const { + uint64_t getTypeAllocSize(Type* Ty) const { // Round up to the next alignment boundary. return RoundUpAlignment(getTypeStoreSize(Ty), getABITypeAlignment(Ty)); } @@ -229,13 +244,13 @@ public: /// objects of the specified type, including alignment padding; always a /// multiple of 8. This is the amount that alloca reserves for this type. /// For example, returns 96 or 128 for x86_fp80, depending on alignment. - uint64_t getTypeAllocSizeInBits(const Type* Ty) const { + uint64_t getTypeAllocSizeInBits(Type* Ty) const { return 8*getTypeAllocSize(Ty); } /// getABITypeAlignment - Return the minimum ABI-required alignment for the /// specified type. - unsigned getABITypeAlignment(const Type *Ty) const; + unsigned getABITypeAlignment(Type *Ty) const; /// getABIIntegerTypeAlignment - Return the minimum ABI-required alignment for /// an integer type of the specified bitwidth. @@ -244,17 +259,17 @@ public: /// getCallFrameTypeAlignment - Return the minimum ABI-required alignment /// for the specified type when it is part of a call frame. - unsigned getCallFrameTypeAlignment(const Type *Ty) const; + unsigned getCallFrameTypeAlignment(Type *Ty) const; /// getPrefTypeAlignment - Return the preferred stack/global alignment for /// the specified type. This is always at least as good as the ABI alignment. - unsigned getPrefTypeAlignment(const Type *Ty) const; + unsigned getPrefTypeAlignment(Type *Ty) const; /// getPreferredTypeAlignmentShift - Return the preferred alignment for the /// specified type, returned as log2 of the value (a shift amount). /// - unsigned getPreferredTypeAlignmentShift(const Type *Ty) const; + unsigned getPreferredTypeAlignmentShift(Type *Ty) const; /// getIntPtrType - Return an unsigned integer type that is the same size or /// greater to the host pointer size. @@ -264,13 +279,12 @@ public: /// getIndexedOffset - return the offset from the beginning of the type for /// the specified indices. This is used to implement getelementptr. /// - uint64_t getIndexedOffset(const Type *Ty, - Value* const* Indices, unsigned NumIndices) const; + uint64_t getIndexedOffset(Type *Ty, ArrayRef Indices) const; /// getStructLayout - Return a StructLayout object, indicating the alignment /// of the struct, its size, and the offsets of its fields. Note that this /// information is lazily cached. - const StructLayout *getStructLayout(const StructType *Ty) const; + const StructLayout *getStructLayout(StructType *Ty) const; /// getPreferredAlignment - Return the preferred alignment of the specified /// global. This includes an explicitly requested alignment (if the global @@ -333,7 +347,7 @@ public: private: friend class TargetData; // Only TargetData can create this class - StructLayout(const StructType *ST, const TargetData &TD); + StructLayout(StructType *ST, const TargetData &TD); }; } // End llvm namespace diff --git a/contrib/llvm/include/llvm/Target/TargetFrameLowering.h b/contrib/llvm/include/llvm/Target/TargetFrameLowering.h index e3d77cf76..4c759b2cc 100644 --- a/contrib/llvm/include/llvm/Target/TargetFrameLowering.h +++ b/contrib/llvm/include/llvm/Target/TargetFrameLowering.h @@ -114,6 +114,10 @@ public: virtual void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const = 0; + /// Adjust the prologue to have the function use segmented stacks. This works + /// by adding a check even before the "normal" function prologue. + virtual void adjustForSegmentedStacks(MachineFunction &MF) const { } + /// spillCalleeSavedRegisters - Issues instruction(s) to spill all callee /// saved registers and returns true if it isn't possible / profitable to do /// so by issuing a series of store instructions via @@ -161,11 +165,6 @@ public: return hasReservedCallFrame(MF) || hasFP(MF); } - /// getInitialFrameState - Returns a list of machine moves that are assumed - /// on entry to all functions. Note that LabelID is ignored (assumed to be - /// the beginning of the function.) - virtual void getInitialFrameState(std::vector &Moves) const; - /// getFrameIndexOffset - Returns the displacement from the frame register to /// the stack frame of the specified index. virtual int getFrameIndexOffset(const MachineFunction &MF, int FI) const; @@ -191,14 +190,6 @@ public: /// virtual void processFunctionBeforeFrameFinalized(MachineFunction &MF) const { } - - /// getCompactUnwindEncoding - Get the compact unwind encoding for the - /// function. Return 0 if the compact unwind isn't available. - virtual uint32_t getCompactUnwindEncoding(ArrayRef Instrs, - int DataAlignmentFactor, - bool IsEH) const { - return 0; - } }; } // End llvm namespace diff --git a/contrib/llvm/include/llvm/Target/TargetInstrInfo.h b/contrib/llvm/include/llvm/Target/TargetInstrInfo.h index f6635667b..07f614d61 100644 --- a/contrib/llvm/include/llvm/Target/TargetInstrInfo.h +++ b/contrib/llvm/include/llvm/Target/TargetInstrInfo.h @@ -49,7 +49,7 @@ public: : CallFrameSetupOpcode(CFSetupOpcode), CallFrameDestroyOpcode(CFDestroyOpcode) { } - + virtual ~TargetInstrInfo(); /// getRegClass - Givem a machine instruction descriptor, returns the register @@ -386,6 +386,16 @@ public: assert(0 && "Target didn't implement TargetInstrInfo::loadRegFromStackSlot!"); } + /// expandPostRAPseudo - This function is called for all pseudo instructions + /// that remain after register allocation. Many pseudo instructions are + /// created to help register allocation. This is the place to convert them + /// into real instructions. The target can edit MI in place, or it can insert + /// new instructions and erase MI. The function should return true if + /// anything was changed. + virtual bool expandPostRAPseudo(MachineBasicBlock::iterator MI) const { + return false; + } + /// emitFrameIndexDebugValue - Emit a target-dependent form of /// DBG_VALUE encoding the address of a frame index. Addresses would /// normally be lowered the same way as other addresses on the target, @@ -671,6 +681,43 @@ public: bool hasLowDefLatency(const InstrItineraryData *ItinData, const MachineInstr *DefMI, unsigned DefIdx) const; + /// verifyInstruction - Perform target specific instruction verification. + virtual + bool verifyInstruction(const MachineInstr *MI, StringRef &ErrInfo) const { + return true; + } + + /// getExecutionDomain - Return the current execution domain and bit mask of + /// possible domains for instruction. + /// + /// Some micro-architectures have multiple execution domains, and multiple + /// opcodes that perform the same operation in different domains. For + /// example, the x86 architecture provides the por, orps, and orpd + /// instructions that all do the same thing. There is a latency penalty if a + /// register is written in one domain and read in another. + /// + /// This function returns a pair (domain, mask) containing the execution + /// domain of MI, and a bit mask of possible domains. The setExecutionDomain + /// function can be used to change the opcode to one of the domains in the + /// bit mask. Instructions whose execution domain can't be changed should + /// return a 0 mask. + /// + /// The execution domain numbers don't have any special meaning except domain + /// 0 is used for instructions that are not associated with any interesting + /// execution domain. + /// + virtual std::pair + getExecutionDomain(const MachineInstr *MI) const { + return std::make_pair(0, 0); + } + + /// setExecutionDomain - Change the opcode of MI to execute in Domain. + /// + /// The bit (1 << Domain) must be set in the mask returned from + /// getExecutionDomain(MI). + /// + virtual void setExecutionDomain(MachineInstr *MI, unsigned Domain) const {} + private: int CallFrameSetupOpcode, CallFrameDestroyOpcode; }; @@ -693,6 +740,12 @@ public: unsigned &SrcOpIdx2) const; virtual bool canFoldMemoryOperand(const MachineInstr *MI, const SmallVectorImpl &Ops) const; + virtual bool hasLoadFromStackSlot(const MachineInstr *MI, + const MachineMemOperand *&MMO, + int &FrameIndex) const; + virtual bool hasStoreToStackSlot(const MachineInstr *MI, + const MachineMemOperand *&MMO, + int &FrameIndex) const; virtual bool PredicateInstruction(MachineInstr *MI, const SmallVectorImpl &Pred) const; virtual void reMaterialize(MachineBasicBlock &MBB, diff --git a/contrib/llvm/include/llvm/Target/TargetIntrinsicInfo.h b/contrib/llvm/include/llvm/Target/TargetIntrinsicInfo.h index ad8ac925e..c44b9230c 100644 --- a/contrib/llvm/include/llvm/Target/TargetIntrinsicInfo.h +++ b/contrib/llvm/include/llvm/Target/TargetIntrinsicInfo.h @@ -39,7 +39,7 @@ public: /// intrinsic, Tys should point to an array of numTys pointers to Type, /// and must provide exactly one type for each overloaded type in the /// intrinsic. - virtual std::string getName(unsigned IID, const Type **Tys = 0, + virtual std::string getName(unsigned IID, Type **Tys = 0, unsigned numTys = 0) const = 0; /// Look up target intrinsic by name. Return intrinsic ID or 0 for unknown @@ -55,7 +55,7 @@ public: /// Create or insert an LLVM Function declaration for an intrinsic, /// and return it. The Tys and numTys are for intrinsics with overloaded /// types. See above for more information. - virtual Function *getDeclaration(Module *M, unsigned ID, const Type **Tys = 0, + virtual Function *getDeclaration(Module *M, unsigned ID, Type **Tys = 0, unsigned numTys = 0) const = 0; }; diff --git a/contrib/llvm/include/llvm/Target/TargetLowering.h b/contrib/llvm/include/llvm/Target/TargetLowering.h index 533c3ac87..013e70a05 100644 --- a/contrib/llvm/include/llvm/Target/TargetLowering.h +++ b/contrib/llvm/include/llvm/Target/TargetLowering.h @@ -113,6 +113,22 @@ public: ZeroOrNegativeOneBooleanContent // All bits equal to bit 0. }; + static ISD::NodeType getExtendForContent(BooleanContent Content) { + switch (Content) { + default: + assert(false && "Unknown BooleanContent!"); + case UndefinedBooleanContent: + // Extend by adding rubbish bits. + return ISD::ANY_EXTEND; + case ZeroOrOneBooleanContent: + // Extend by adding zero bits. + return ISD::ZERO_EXTEND; + case ZeroOrNegativeOneBooleanContent: + // Extend by copying the sign bit. + return ISD::SIGN_EXTEND; + } + } + /// NOTE: The constructor takes ownership of TLOF. explicit TargetLowering(const TargetMachine &TM, const TargetLoweringObjectFile *TLOF); @@ -148,8 +164,7 @@ public: /// the condition operand of SELECT and BRCOND nodes. In the case of /// BRCOND the argument passed is MVT::Other since there are no other /// operands to get a type hint from. - virtual - MVT::SimpleValueType getSetCCResultType(EVT VT) const; + virtual EVT getSetCCResultType(EVT VT) const; /// getCmpLibcallReturnType - Return the ValueType for comparison /// libcalls. Comparions libcalls include floating point comparion calls, @@ -162,7 +177,13 @@ public: /// "Boolean values" are special true/false values produced by nodes like /// SETCC and consumed (as the condition) by nodes like SELECT and BRCOND. /// Not to be confused with general values promoted from i1. - BooleanContent getBooleanContents() const { return BooleanContents;} + /// Some cpus distinguish between vectors of boolean and scalars; the isVec + /// parameter selects between the two kinds. For example on X86 a scalar + /// boolean should be zero extended from i1, while the elements of a vector + /// of booleans should be sign extended from i1. + BooleanContent getBooleanContents(bool isVec) const { + return isVec ? BooleanVectorContents : BooleanContents; + } /// getSchedulingPreference - Return target scheduling preference. Sched::Preference getSchedulingPreference() const { @@ -172,7 +193,7 @@ public: /// getSchedulingPreference - Some scheduler, e.g. hybrid, can switch to /// different scheduling heuristics for different nodes. This function returns /// the preference (or none) for the given node. - virtual Sched::Preference getSchedulingPreference(SDNode *N) const { + virtual Sched::Preference getSchedulingPreference(SDNode *) const { return Sched::None; } @@ -265,9 +286,9 @@ public: assert(!VT.isVector()); while (true) { switch (getTypeAction(Context, VT)) { - case Legal: + case TypeLegal: return VT; - case Expand: + case TypeExpandInteger: VT = getTypeToTransformTo(Context, VT); break; default: @@ -307,15 +328,15 @@ public: bool writeMem; // writes memory? }; - virtual bool getTgtMemIntrinsic(IntrinsicInfo &Info, - const CallInst &I, unsigned Intrinsic) const { + virtual bool getTgtMemIntrinsic(IntrinsicInfo &, const CallInst &, + unsigned /*Intrinsic*/) const { return false; } /// isFPImmLegal - Returns true if the target can instruction select the /// specified FP immediate natively. If false, the legalizer will materialize /// the FP immediate as a load from a constant pool. - virtual bool isFPImmLegal(const APFloat &Imm, EVT VT) const { + virtual bool isFPImmLegal(const APFloat &/*Imm*/, EVT /*VT*/) const { return false; } @@ -323,8 +344,8 @@ public: /// support *some* VECTOR_SHUFFLE operations, those with specific masks. /// By default, if a target supports the VECTOR_SHUFFLE node, all mask values /// are assumed to be legal. - virtual bool isShuffleMaskLegal(const SmallVectorImpl &Mask, - EVT VT) const { + virtual bool isShuffleMaskLegal(const SmallVectorImpl &/*Mask*/, + EVT /*VT*/) const { return true; } @@ -337,8 +358,8 @@ public: /// used by Targets can use this to indicate if there is a suitable /// VECTOR_SHUFFLE that can be used to replace a VAND with a constant /// pool entry. - virtual bool isVectorClearMaskLegal(const SmallVectorImpl &Mask, - EVT VT) const { + virtual bool isVectorClearMaskLegal(const SmallVectorImpl &/*Mask*/, + EVT /*VT*/) const { return false; } @@ -383,9 +404,7 @@ public: /// isLoadExtLegal - Return true if the specified load with extension is legal /// on this target. bool isLoadExtLegal(unsigned ExtType, EVT VT) const { - return VT.isSimple() && - (getLoadExtAction(ExtType, VT) == Legal || - getLoadExtAction(ExtType, VT) == Custom); + return VT.isSimple() && getLoadExtAction(ExtType, VT) == Legal; } /// getTruncStoreAction - Return how this store with truncation should be @@ -404,8 +423,7 @@ public: /// legal on this target. bool isTruncStoreLegal(EVT ValVT, EVT MemVT) const { return isTypeLegal(ValVT) && MemVT.isSimple() && - (getTruncStoreAction(ValVT, MemVT) == Legal || - getTruncStoreAction(ValVT, MemVT) == Custom); + getTruncStoreAction(ValVT, MemVT) == Legal; } /// getIndexedLoadAction - Return how the indexed load should be treated: @@ -501,7 +519,7 @@ public: /// This is fixed by the LLVM operations except for the pointer size. If /// AllowUnknown is true, this will return MVT::Other for types with no EVT /// counterpart (e.g. structs), otherwise it will assert. - EVT getValueType(const Type *Ty, bool AllowUnknown = false) const { + EVT getValueType(Type *Ty, bool AllowUnknown = false) const { EVT VT = EVT::getEVT(Ty, AllowUnknown); return VT == MVT::iPTR ? PointerTy : VT; } @@ -509,7 +527,7 @@ public: /// getByValTypeAlignment - Return the desired alignment for ByVal aggregate /// function arguments in the caller parameter area. This is the actual /// alignment, not its logarithm. - virtual unsigned getByValTypeAlignment(const Type *Ty) const; + virtual unsigned getByValTypeAlignment(Type *Ty) const; /// getRegisterType - Return the type of registers that this ValueType will /// eventually require. @@ -569,7 +587,7 @@ public: /// ShouldShrinkFPConstant - If true, then instruction selection should /// seek to shrink the FP constant of the specified type to a smaller type /// in order to save space and / or reduce runtime. - virtual bool ShouldShrinkFPConstant(EVT VT) const { return true; } + virtual bool ShouldShrinkFPConstant(EVT) const { return true; } /// hasTargetDAGCombine - If true, the target has custom DAG combine /// transformations that it can perform for the specified node. @@ -611,7 +629,7 @@ public: /// use helps to ensure that such replacements don't generate code that causes /// an alignment error (trap) on the target machine. /// @brief Determine if the target supports unaligned memory accesses. - virtual bool allowsUnalignedMemoryAccesses(EVT VT) const { + virtual bool allowsUnalignedMemoryAccesses(EVT) const { return false; } @@ -634,10 +652,11 @@ public: /// constant so it does not need to be loaded. /// It returns EVT::Other if the type should be determined using generic /// target-independent logic. - virtual EVT getOptimalMemOpType(uint64_t Size, - unsigned DstAlign, unsigned SrcAlign, - bool NonScalarIntSafe, bool MemcpyStrSrc, - MachineFunction &MF) const { + virtual EVT getOptimalMemOpType(uint64_t /*Size*/, + unsigned /*DstAlign*/, unsigned /*SrcAlign*/, + bool /*NonScalarIntSafe*/, + bool /*MemcpyStrSrc*/, + MachineFunction &/*MF*/) const { return MVT::Other; } @@ -717,23 +736,30 @@ public: return ShouldFoldAtomicFences; } + /// getInsertFencesFor - return whether the DAG builder should automatically + /// insert fences and reduce ordering for atomics. + /// + bool getInsertFencesForAtomic() const { + return InsertFencesForAtomic; + } + /// getPreIndexedAddressParts - returns true by value, base pointer and /// offset pointer and addressing mode by reference if the node's address /// can be legally represented as pre-indexed load / store address. - virtual bool getPreIndexedAddressParts(SDNode *N, SDValue &Base, - SDValue &Offset, - ISD::MemIndexedMode &AM, - SelectionDAG &DAG) const { + virtual bool getPreIndexedAddressParts(SDNode * /*N*/, SDValue &/*Base*/, + SDValue &/*Offset*/, + ISD::MemIndexedMode &/*AM*/, + SelectionDAG &/*DAG*/) const { return false; } /// getPostIndexedAddressParts - returns true by value, base pointer and /// offset pointer and addressing mode by reference if this node can be /// combined with a load / store to form a post-indexed load / store. - virtual bool getPostIndexedAddressParts(SDNode *N, SDNode *Op, - SDValue &Base, SDValue &Offset, - ISD::MemIndexedMode &AM, - SelectionDAG &DAG) const { + virtual bool getPostIndexedAddressParts(SDNode * /*N*/, SDNode * /*Op*/, + SDValue &/*Base*/, SDValue &/*Offset*/, + ISD::MemIndexedMode &/*AM*/, + SelectionDAG &/*DAG*/) const { return false; } @@ -743,9 +769,9 @@ public: virtual unsigned getJumpTableEncoding() const; virtual const MCExpr * - LowerCustomJumpTableEntry(const MachineJumpTableInfo *MJTI, - const MachineBasicBlock *MBB, unsigned uid, - MCContext &Ctx) const { + LowerCustomJumpTableEntry(const MachineJumpTableInfo * /*MJTI*/, + const MachineBasicBlock * /*MBB*/, unsigned /*uid*/, + MCContext &/*Ctx*/) const { assert(0 && "Need to implement this hook if target has custom JTIs"); return 0; } @@ -771,7 +797,8 @@ public: /// protector cookies at a fixed offset in some non-standard address /// space, and populates the address space and offset as /// appropriate. - virtual bool getStackCookieLocation(unsigned &AddressSpace, unsigned &Offset) const { + virtual bool getStackCookieLocation(unsigned &/*AddressSpace*/, + unsigned &/*Offset*/) const { return false; } @@ -906,7 +933,7 @@ public: /// the specified value type and it is 'desirable' to use the type for the /// given node type. e.g. On x86 i16 is legal, but undesirable since i16 /// instruction encodings are longer and some i16 instructions are slow. - virtual bool isTypeDesirableForOp(unsigned Opc, EVT VT) const { + virtual bool isTypeDesirableForOp(unsigned /*Opc*/, EVT VT) const { // By default, assume all legal types are desirable. return isTypeLegal(VT); } @@ -914,14 +941,15 @@ public: /// isDesirableToPromoteOp - Return true if it is profitable for dag combiner /// to transform a floating point op of specified opcode to a equivalent op of /// an integer type. e.g. f32 load -> i32 load can be profitable on ARM. - virtual bool isDesirableToTransformToIntegerOp(unsigned Opc, EVT VT) const { + virtual bool isDesirableToTransformToIntegerOp(unsigned /*Opc*/, + EVT /*VT*/) const { return false; } /// IsDesirableToPromoteOp - This method query the target whether it is /// beneficial for dag combiner to promote the specified node. If true, it /// should return the desired promotion type by reference. - virtual bool IsDesirableToPromoteOp(SDValue Op, EVT &PVT) const { + virtual bool IsDesirableToPromoteOp(SDValue /*Op*/, EVT &/*PVT*/) const { return false; } @@ -934,6 +962,12 @@ protected: /// setBooleanContents - Specify how the target extends the result of a /// boolean value from i1 to a wider type. See getBooleanContents. void setBooleanContents(BooleanContent Ty) { BooleanContents = Ty; } + /// setBooleanVectorContents - Specify how the target extends the result + /// of a vector boolean value from a vector of i1 to a wider type. See + /// getBooleanContents. + void setBooleanVectorContents(BooleanContent Ty) { + BooleanVectorContents = Ty; + } /// setSchedulingPreference - Specify the target scheduling preference. void setSchedulingPreference(Sched::Preference Pref) { @@ -1137,6 +1171,13 @@ protected: ShouldFoldAtomicFences = fold; } + /// setInsertFencesForAtomic - Set if the the DAG builder should + /// automatically insert fences and reduce the order of atomic memory + /// operations to Monotonic. + void setInsertFencesForAtomic(bool fence) { + InsertFencesForAtomic = fence; + } + public: //===--------------------------------------------------------------------===// // Lowering methods - These methods must be implemented by targets so that @@ -1150,11 +1191,11 @@ public: /// chain value. /// virtual SDValue - LowerFormalArguments(SDValue Chain, - CallingConv::ID CallConv, bool isVarArg, - const SmallVectorImpl &Ins, - DebugLoc dl, SelectionDAG &DAG, - SmallVectorImpl &InVals) const { + LowerFormalArguments(SDValue /*Chain*/, CallingConv::ID /*CallConv*/, + bool /*isVarArg*/, + const SmallVectorImpl &/*Ins*/, + DebugLoc /*dl*/, SelectionDAG &/*DAG*/, + SmallVectorImpl &/*InVals*/) const { assert(0 && "Not Implemented"); return SDValue(); // this is here to silence compiler errors } @@ -1166,7 +1207,7 @@ public: /// lowering. struct ArgListEntry { SDValue Node; - const Type* Ty; + Type* Ty; bool isSExt : 1; bool isZExt : 1; bool isInReg : 1; @@ -1180,7 +1221,7 @@ public: }; typedef std::vector ArgListTy; std::pair - LowerCallTo(SDValue Chain, const Type *RetTy, bool RetSExt, bool RetZExt, + LowerCallTo(SDValue Chain, Type *RetTy, bool RetSExt, bool RetZExt, bool isVarArg, bool isInreg, unsigned NumFixedArgs, CallingConv::ID CallConv, bool isTailCall, bool isReturnValueUsed, SDValue Callee, ArgListTy &Args, @@ -1193,13 +1234,14 @@ public: /// InVals array with legal-type return values from the call, and return /// the resulting token chain value. virtual SDValue - LowerCall(SDValue Chain, SDValue Callee, - CallingConv::ID CallConv, bool isVarArg, bool &isTailCall, - const SmallVectorImpl &Outs, - const SmallVectorImpl &OutVals, - const SmallVectorImpl &Ins, - DebugLoc dl, SelectionDAG &DAG, - SmallVectorImpl &InVals) const { + LowerCall(SDValue /*Chain*/, SDValue /*Callee*/, + CallingConv::ID /*CallConv*/, bool /*isVarArg*/, + bool &/*isTailCall*/, + const SmallVectorImpl &/*Outs*/, + const SmallVectorImpl &/*OutVals*/, + const SmallVectorImpl &/*Ins*/, + DebugLoc /*dl*/, SelectionDAG &/*DAG*/, + SmallVectorImpl &/*InVals*/) const { assert(0 && "Not Implemented"); return SDValue(); // this is here to silence compiler errors } @@ -1211,10 +1253,10 @@ public: /// return values described by the Outs array can fit into the return /// registers. If false is returned, an sret-demotion is performed. /// - virtual bool CanLowerReturn(CallingConv::ID CallConv, - MachineFunction &MF, bool isVarArg, - const SmallVectorImpl &Outs, - LLVMContext &Context) const + virtual bool CanLowerReturn(CallingConv::ID /*CallConv*/, + MachineFunction &/*MF*/, bool /*isVarArg*/, + const SmallVectorImpl &/*Outs*/, + LLVMContext &/*Context*/) const { // Return true by default to get preexisting behavior. return true; @@ -1226,10 +1268,11 @@ public: /// value. /// virtual SDValue - LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, - const SmallVectorImpl &Outs, - const SmallVectorImpl &OutVals, - DebugLoc dl, SelectionDAG &DAG) const { + LowerReturn(SDValue /*Chain*/, CallingConv::ID /*CallConv*/, + bool /*isVarArg*/, + const SmallVectorImpl &/*Outs*/, + const SmallVectorImpl &/*OutVals*/, + DebugLoc /*dl*/, SelectionDAG &/*DAG*/) const { assert(0 && "Not Implemented"); return SDValue(); // this is here to silence compiler errors } @@ -1237,7 +1280,7 @@ public: /// isUsedByReturnOnly - Return true if result of the specified node is used /// by a return node only. This is used to determine whether it is possible /// to codegen a libcall as tail call at legalization time. - virtual bool isUsedByReturnOnly(SDNode *N) const { + virtual bool isUsedByReturnOnly(SDNode *) const { return false; } @@ -1245,7 +1288,7 @@ public: /// call instruction as a tail call. This is used by optimization passes to /// determine if it's profitable to duplicate return instructions to enable /// tailcall optimization. - virtual bool mayBeEmittedAsTailCall(CallInst *CI) const { + virtual bool mayBeEmittedAsTailCall(CallInst *) const { return false; } @@ -1256,7 +1299,7 @@ public: /// necessary for non-C calling conventions. The frontend should handle this /// and include all of the necessary information. virtual EVT getTypeForExtArgOrReturn(LLVMContext &Context, EVT VT, - ISD::NodeType ExtendKind) const { + ISD::NodeType /*ExtendKind*/) const { EVT MinVT = getRegisterType(Context, MVT::i32); return VT.bitsLT(MinVT) ? MinVT : VT; } @@ -1293,8 +1336,9 @@ public: /// /// If the target has no operations that require custom lowering, it need not /// implement this. The default implementation aborts. - virtual void ReplaceNodeResults(SDNode *N, SmallVectorImpl &Results, - SelectionDAG &DAG) const { + virtual void ReplaceNodeResults(SDNode * /*N*/, + SmallVectorImpl &/*Results*/, + SelectionDAG &/*DAG*/) const { assert(0 && "ReplaceNodeResults not implemented for this target!"); } @@ -1304,7 +1348,7 @@ public: /// createFastISel - This method returns a target specific FastISel object, /// or null if the target does not support "fast" ISel. - virtual FastISel *createFastISel(FunctionLoweringInfo &funcInfo) const { + virtual FastISel *createFastISel(FunctionLoweringInfo &) const { return 0; } @@ -1316,7 +1360,7 @@ public: /// call to be explicit llvm code if it wants to. This is useful for /// turning simple inline asms into LLVM intrinsics, which gives the /// compiler more information about the behavior of the code. - virtual bool ExpandInlineAsm(CallInst *CI) const { + virtual bool ExpandInlineAsm(CallInst *) const { return false; } @@ -1460,6 +1504,13 @@ public: virtual MachineBasicBlock * EmitInstrWithCustomInserter(MachineInstr *MI, MachineBasicBlock *MBB) const; + /// AdjustInstrPostInstrSelection - This method should be implemented by + /// targets that mark instructions with the 'hasPostISelHook' flag. These + /// instructions must be adjusted after instruction selection by target hooks. + /// e.g. To fill in optional defs for ARM 's' setting instructions. + virtual void + AdjustInstrPostInstrSelection(MachineInstr *MI, SDNode *Node) const; + //===--------------------------------------------------------------------===// // Addressing mode description hooks (used by LSR etc). // @@ -1485,16 +1536,32 @@ public: /// The type may be VoidTy, in which case only return true if the addressing /// mode is legal for a load/store of any legal type. /// TODO: Handle pre/postinc as well. - virtual bool isLegalAddressingMode(const AddrMode &AM, const Type *Ty) const; + virtual bool isLegalAddressingMode(const AddrMode &AM, Type *Ty) const; + + /// isLegalICmpImmediate - Return true if the specified immediate is legal + /// icmp immediate, that is the target has icmp instructions which can compare + /// a register against the immediate without having to materialize the + /// immediate into a register. + virtual bool isLegalICmpImmediate(int64_t) const { + return true; + } + + /// isLegalAddImmediate - Return true if the specified immediate is legal + /// add immediate, that is the target has add instructions which can add + /// a register with the immediate without having to materialize the + /// immediate into a register. + virtual bool isLegalAddImmediate(int64_t) const { + return true; + } /// 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. - virtual bool isTruncateFree(const Type *Ty1, const Type *Ty2) const { + virtual bool isTruncateFree(Type * /*Ty1*/, Type * /*Ty2*/) const { return false; } - virtual bool isTruncateFree(EVT VT1, EVT VT2) const { + virtual bool isTruncateFree(EVT /*VT1*/, EVT /*VT2*/) const { return false; } @@ -1506,37 +1573,21 @@ public: /// does not necessarily apply to truncate instructions. e.g. on x86-64, /// all instructions that define 32-bit values implicit zero-extend the /// result out to 64 bits. - virtual bool isZExtFree(const Type *Ty1, const Type *Ty2) const { + virtual bool isZExtFree(Type * /*Ty1*/, Type * /*Ty2*/) const { return false; } - virtual bool isZExtFree(EVT VT1, EVT VT2) const { + virtual bool isZExtFree(EVT /*VT1*/, EVT /*VT2*/) const { return false; } /// isNarrowingProfitable - Return true if it's profitable to narrow /// operations of type VT1 to VT2. e.g. on x86, it's profitable to narrow /// from i32 to i8 but not from i32 to i16. - virtual bool isNarrowingProfitable(EVT VT1, EVT VT2) const { + virtual bool isNarrowingProfitable(EVT /*VT1*/, EVT /*VT2*/) const { return false; } - /// isLegalICmpImmediate - Return true if the specified immediate is legal - /// icmp immediate, that is the target has icmp instructions which can compare - /// a register against the immediate without having to materialize the - /// immediate into a register. - virtual bool isLegalICmpImmediate(int64_t Imm) const { - return true; - } - - /// isLegalAddImmediate - Return true if the specified immediate is legal - /// add immediate, that is the target has add instructions which can add - /// a register with the immediate without having to materialize the - /// immediate into a register. - virtual bool isLegalAddImmediate(int64_t Imm) const { - return true; - } - //===--------------------------------------------------------------------===// // Div utility functions // @@ -1639,6 +1690,10 @@ private: /// BooleanContents - Information about the contents of the high-bits in /// boolean values held in a type wider than i1. See getBooleanContents. BooleanContent BooleanContents; + /// BooleanVectorContents - Information about the contents of the high-bits + /// in boolean vector values when the element type is wider than i1. See + /// getBooleanContents. + BooleanContent BooleanVectorContents; /// SchedPreferenceInfo - The target scheduling preference: shortest possible /// total cycles or lowest register usage. @@ -1676,6 +1731,11 @@ private: /// combiner. bool ShouldFoldAtomicFences; + /// InsertFencesForAtomic - Whether the DAG builder should automatically + /// insert fences and reduce ordering for atomics. (This will be set for + /// for most architectures with weak memory ordering.) + bool InsertFencesForAtomic; + /// StackPointerRegisterToSaveRestore - If set to a physical register, this /// specifies the register that llvm.savestack/llvm.restorestack should save /// and restore. @@ -1963,7 +2023,7 @@ private: /// GetReturnInfo - Given an LLVM IR type and return type attributes, /// compute the return value EVTs and flags, and optionally also /// the offsets, if the return value is being lowered to memory. -void GetReturnInfo(const Type* ReturnType, Attributes attr, +void GetReturnInfo(Type* ReturnType, Attributes attr, SmallVectorImpl &Outs, const TargetLowering &TLI, SmallVectorImpl *Offsets = 0); diff --git a/contrib/llvm/include/llvm/Target/TargetLoweringObjectFile.h b/contrib/llvm/include/llvm/Target/TargetLoweringObjectFile.h index 2e1d6b97e..7d06cec0a 100644 --- a/contrib/llvm/include/llvm/Target/TargetLoweringObjectFile.h +++ b/contrib/llvm/include/llvm/Target/TargetLoweringObjectFile.h @@ -16,6 +16,7 @@ #define LLVM_TARGET_TARGETLOWERINGOBJECTFILE_H #include "llvm/ADT/StringRef.h" +#include "llvm/MC/MCObjectFileInfo.h" #include "llvm/MC/SectionKind.h" namespace llvm { @@ -31,137 +32,27 @@ namespace llvm { class GlobalValue; class TargetMachine; -class TargetLoweringObjectFile { +class TargetLoweringObjectFile : public MCObjectFileInfo { MCContext *Ctx; TargetLoweringObjectFile(const TargetLoweringObjectFile&); // DO NOT IMPLEMENT void operator=(const TargetLoweringObjectFile&); // DO NOT IMPLEMENT -protected: - - TargetLoweringObjectFile(); - - /// TextSection - Section directive for standard text. - /// - const MCSection *TextSection; - - /// DataSection - Section directive for standard data. - /// - const MCSection *DataSection; - /// BSSSection - Section that is default initialized to zero. - const MCSection *BSSSection; - - /// ReadOnlySection - Section that is readonly and can contain arbitrary - /// initialized data. Targets are not required to have a readonly section. - /// If they don't, various bits of code will fall back to using the data - /// section for constants. - const MCSection *ReadOnlySection; - - /// StaticCtorSection - This section contains the static constructor pointer - /// list. - const MCSection *StaticCtorSection; - - /// StaticDtorSection - This section contains the static destructor pointer - /// list. - const MCSection *StaticDtorSection; - - /// LSDASection - If exception handling is supported by the target, this is - /// the section the Language Specific Data Area information is emitted to. - const MCSection *LSDASection; - - /// CompactUnwindSection - If exception handling is supported by the target - /// and the target can support a compact representation of the CIE and FDE, - /// this is the section to emit them into. - const MCSection *CompactUnwindSection; - - // Dwarf sections for debug info. If a target supports debug info, these must - // be set. - const MCSection *DwarfAbbrevSection; - const MCSection *DwarfInfoSection; - const MCSection *DwarfLineSection; - const MCSection *DwarfFrameSection; - const MCSection *DwarfPubNamesSection; - const MCSection *DwarfPubTypesSection; - const MCSection *DwarfDebugInlineSection; - const MCSection *DwarfStrSection; - const MCSection *DwarfLocSection; - const MCSection *DwarfARangesSection; - const MCSection *DwarfRangesSection; - const MCSection *DwarfMacroInfoSection; - - // Extra TLS Variable Data section. If the target needs to put additional - // information for a TLS variable, it'll go here. - const MCSection *TLSExtraDataSection; - - /// CommDirectiveSupportsAlignment - True if .comm supports alignment. This - /// is a hack for as long as we support 10.4 Tiger, whose assembler doesn't - /// support alignment on comm. - bool CommDirectiveSupportsAlignment; - - /// SupportsWeakEmptyEHFrame - True if target object file supports a - /// weak_definition of constant 0 for an omitted EH frame. - bool SupportsWeakOmittedEHFrame; - - /// IsFunctionEHFrameSymbolPrivate - This flag is set to true if the - /// "EH_frame" symbol for EH information should be an assembler temporary (aka - /// private linkage, aka an L or .L label) or false if it should be a normal - /// non-.globl label. This defaults to true. - bool IsFunctionEHFrameSymbolPrivate; - public: MCContext &getContext() const { return *Ctx; } + + TargetLoweringObjectFile() : MCObjectFileInfo(), Ctx(0) {} virtual ~TargetLoweringObjectFile(); /// Initialize - this method must be called before any actual lowering is /// done. This specifies the current context for codegen, and gives the /// lowering implementations a chance to set up their default sections. - virtual void Initialize(MCContext &ctx, const TargetMachine &TM) { - Ctx = &ctx; - } + virtual void Initialize(MCContext &ctx, const TargetMachine &TM); - bool isFunctionEHFrameSymbolPrivate() const { - return IsFunctionEHFrameSymbolPrivate; - } - bool getSupportsWeakOmittedEHFrame() const { - return SupportsWeakOmittedEHFrame; - } - bool getCommDirectiveSupportsAlignment() const { - return CommDirectiveSupportsAlignment; - } - - const MCSection *getTextSection() const { return TextSection; } - const MCSection *getDataSection() const { return DataSection; } - const MCSection *getBSSSection() const { return BSSSection; } - const MCSection *getStaticCtorSection() const { return StaticCtorSection; } - const MCSection *getStaticDtorSection() const { return StaticDtorSection; } - const MCSection *getLSDASection() const { return LSDASection; } - const MCSection *getCompactUnwindSection() const{return CompactUnwindSection;} - virtual const MCSection *getEHFrameSection() const = 0; virtual void emitPersonalityValue(MCStreamer &Streamer, const TargetMachine &TM, const MCSymbol *Sym) const; - const MCSection *getDwarfAbbrevSection() const { return DwarfAbbrevSection; } - const MCSection *getDwarfInfoSection() const { return DwarfInfoSection; } - const MCSection *getDwarfLineSection() const { return DwarfLineSection; } - const MCSection *getDwarfFrameSection() const { return DwarfFrameSection; } - const MCSection *getDwarfPubNamesSection() const{return DwarfPubNamesSection;} - const MCSection *getDwarfPubTypesSection() const{return DwarfPubTypesSection;} - const MCSection *getDwarfDebugInlineSection() const { - return DwarfDebugInlineSection; - } - const MCSection *getDwarfStrSection() const { return DwarfStrSection; } - const MCSection *getDwarfLocSection() const { return DwarfLocSection; } - const MCSection *getDwarfARangesSection() const { return DwarfARangesSection;} - const MCSection *getDwarfRangesSection() const { return DwarfRangesSection; } - const MCSection *getDwarfMacroInfoSection() const { - return DwarfMacroInfoSection; - } - const MCSection *getTLSExtraDataSection() const { - return TLSExtraDataSection; - } - virtual const MCSection *getWin64EHFuncTableSection(StringRef suffix)const=0; - virtual const MCSection *getWin64EHTableSection(StringRef suffix) const = 0; /// shouldEmitUsedDirectiveFor - This hook allows targets to selectively /// decide not to emit the UsedDirective for some symbols in llvm.used. @@ -231,11 +122,6 @@ public: getExprForDwarfReference(const MCSymbol *Sym, unsigned Encoding, MCStreamer &Streamer) const; - virtual unsigned getPersonalityEncoding() const; - virtual unsigned getLSDAEncoding() const; - virtual unsigned getFDEEncoding(bool CFI) const; - virtual unsigned getTTypeEncoding() const; - protected: virtual const MCSection * SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, diff --git a/contrib/llvm/include/llvm/Target/TargetMachine.h b/contrib/llvm/include/llvm/Target/TargetMachine.h index ac41a58cc..8a8d14229 100644 --- a/contrib/llvm/include/llvm/Target/TargetMachine.h +++ b/contrib/llvm/include/llvm/Target/TargetMachine.h @@ -14,6 +14,7 @@ #ifndef LLVM_TARGET_TARGETMACHINE_H #define LLVM_TARGET_TARGETMACHINE_H +#include "llvm/MC/MCCodeGenInfo.h" #include "llvm/ADT/StringRef.h" #include #include @@ -23,6 +24,7 @@ namespace llvm { class InstrItineraryData; class JITCodeEmitter; class MCAsmInfo; +class MCCodeGenInfo; class MCContext; class Pass; class PassManager; @@ -41,27 +43,6 @@ class TargetSubtargetInfo; class formatted_raw_ostream; class raw_ostream; -// Relocation model types. -namespace Reloc { - enum Model { - Default, - Static, - PIC_, // Cannot be named PIC due to collision with -DPIC - DynamicNoPIC - }; -} - -// Code model types. -namespace CodeModel { - enum Model { - Default, - Small, - Kernel, - Medium, - Large - }; -} - // Code generation optimization level. namespace CodeGenOpt { enum Level { @@ -108,6 +89,9 @@ protected: // Can only create subclasses. std::string TargetCPU; std::string TargetFS; + /// CodeGenInfo - Low level target information such as relocation model. + const MCCodeGenInfo *CodeGenInfo; + /// AsmInfo - Contains target specific asm information. /// const MCAsmInfo *AsmInfo; @@ -214,19 +198,11 @@ public: /// getRelocationModel - Returns the code generation relocation model. The /// choices are static, PIC, and dynamic-no-pic, and target default. - static Reloc::Model getRelocationModel(); - - /// setRelocationModel - Sets the code generation relocation model. - /// - static void setRelocationModel(Reloc::Model Model); + Reloc::Model getRelocationModel() const; /// getCodeModel - Returns the code model. The choices are small, kernel, /// medium, large, and target default. - static CodeModel::Model getCodeModel(); - - /// setCodeModel - Sets the code model. - /// - static void setCodeModel(CodeModel::Model Model); + CodeModel::Model getCodeModel() const; /// getAsmVerbosityDefault - Returns the default value of asm verbosity. /// @@ -309,7 +285,8 @@ public: class LLVMTargetMachine : public TargetMachine { protected: // Can only create subclasses. LLVMTargetMachine(const Target &T, StringRef TargetTriple, - StringRef CPU, StringRef FS); + StringRef CPU, StringRef FS, + Reloc::Model RM, CodeModel::Model CM); private: /// addCommonCodeGenPasses - Add standard LLVM codegen passes used for @@ -318,9 +295,6 @@ private: bool addCommonCodeGenPasses(PassManagerBase &, CodeGenOpt::Level, bool DisableVerify, MCContext *&OutCtx); - virtual void setCodeModelForJIT(); - virtual void setCodeModelForStatic(); - public: /// addPassesToEmitFile - Add passes to the specified pass manager to get the /// specified file emitted. Typically this will involve several steps of code diff --git a/contrib/llvm/include/llvm/Target/TargetOptions.h b/contrib/llvm/include/llvm/Target/TargetOptions.h index 55d50d977..e07e8c1ce 100644 --- a/contrib/llvm/include/llvm/Target/TargetOptions.h +++ b/contrib/llvm/include/llvm/Target/TargetOptions.h @@ -158,6 +158,8 @@ namespace llvm { /// instead of an ISD::TRAP node. extern StringRef getTrapFunctionName(); + extern bool EnableSegmentedStacks; + } // End llvm namespace #endif diff --git a/contrib/llvm/include/llvm/Target/TargetRegisterInfo.h b/contrib/llvm/include/llvm/Target/TargetRegisterInfo.h index 8d827f117..682aa5073 100644 --- a/contrib/llvm/include/llvm/Target/TargetRegisterInfo.h +++ b/contrib/llvm/include/llvm/Target/TargetRegisterInfo.h @@ -20,7 +20,6 @@ #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/ValueTypes.h" #include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/DenseSet.h" #include #include @@ -36,76 +35,75 @@ class TargetRegisterClass { public: typedef const unsigned* iterator; typedef const unsigned* const_iterator; - typedef const EVT* vt_iterator; typedef const TargetRegisterClass* const * sc_iterator; private: - unsigned ID; - const char *Name; + const MCRegisterClass *MC; const vt_iterator VTs; - const sc_iterator SubClasses; + const unsigned *SubClassMask; const sc_iterator SuperClasses; - const sc_iterator SubRegClasses; const sc_iterator SuperRegClasses; - const unsigned RegSize, Alignment; // Size & Alignment of register in bytes - const int CopyCost; - const bool Allocatable; - const iterator RegsBegin, RegsEnd; - DenseSet RegSet; public: - TargetRegisterClass(unsigned id, - const char *name, - const EVT *vts, - const TargetRegisterClass * const *subcs, + TargetRegisterClass(const MCRegisterClass *MC, const EVT *vts, + const unsigned *subcm, const TargetRegisterClass * const *supcs, - const TargetRegisterClass * const *subregcs, - const TargetRegisterClass * const *superregcs, - unsigned RS, unsigned Al, int CC, bool Allocable, - iterator RB, iterator RE) - : ID(id), Name(name), VTs(vts), SubClasses(subcs), SuperClasses(supcs), - SubRegClasses(subregcs), SuperRegClasses(superregcs), - RegSize(RS), Alignment(Al), CopyCost(CC), Allocatable(Allocable), - RegsBegin(RB), RegsEnd(RE) { - for (iterator I = RegsBegin, E = RegsEnd; I != E; ++I) - RegSet.insert(*I); - } + const TargetRegisterClass * const *superregcs) + : MC(MC), VTs(vts), SubClassMask(subcm), SuperClasses(supcs), + SuperRegClasses(superregcs) {} + virtual ~TargetRegisterClass() {} // Allow subclasses /// getID() - Return the register class ID number. /// - unsigned getID() const { return ID; } + unsigned getID() const { return MC->getID(); } /// getName() - Return the register class name for debugging. /// - const char *getName() const { return Name; } + const char *getName() const { return MC->getName(); } /// begin/end - Return all of the registers in this class. /// - iterator begin() const { return RegsBegin; } - iterator end() const { return RegsEnd; } + iterator begin() const { return MC->begin(); } + iterator end() const { return MC->end(); } /// getNumRegs - Return the number of registers in this class. /// - unsigned getNumRegs() const { return (unsigned)(RegsEnd-RegsBegin); } + unsigned getNumRegs() const { return MC->getNumRegs(); } /// getRegister - Return the specified register in the class. /// unsigned getRegister(unsigned i) const { - assert(i < getNumRegs() && "Register number out of range!"); - return RegsBegin[i]; + return MC->getRegister(i); } /// contains - Return true if the specified register is included in this /// register class. This does not include virtual registers. bool contains(unsigned Reg) const { - return RegSet.count(Reg); + return MC->contains(Reg); } /// contains - Return true if both registers are in this class. bool contains(unsigned Reg1, unsigned Reg2) const { - return contains(Reg1) && contains(Reg2); + return MC->contains(Reg1, Reg2); } + /// getSize - Return the size of the register in bytes, which is also the size + /// of a stack slot allocated to hold a spilled copy of this register. + unsigned getSize() const { return MC->getSize(); } + + /// getAlignment - Return the minimum required alignment for a register of + /// this class. + unsigned getAlignment() const { return MC->getAlignment(); } + + /// getCopyCost - Return the cost of copying a value between two registers in + /// this class. A negative number means the register class is very expensive + /// to copy e.g. status flag register classes. + int getCopyCost() const { return MC->getCopyCost(); } + + /// isAllocatable - Return true if this register class may be used to create + /// virtual registers. + bool isAllocatable() const { return MC->isAllocatable(); } + /// hasType - return true if this TargetRegisterClass has the ValueType vt. /// bool hasType(EVT vt) const { @@ -127,25 +125,6 @@ public: return I; } - /// subregclasses_begin / subregclasses_end - Loop over all of - /// the subreg register classes of this register class. - sc_iterator subregclasses_begin() const { - return SubRegClasses; - } - - sc_iterator subregclasses_end() const { - sc_iterator I = SubRegClasses; - while (*I != NULL) ++I; - return I; - } - - /// getSubRegisterRegClass - Return the register class of subregisters with - /// index SubIdx, or NULL if no such class exists. - const TargetRegisterClass* getSubRegisterRegClass(unsigned SubIdx) const { - assert(SubIdx>0 && "Invalid subregister index"); - return SubRegClasses[SubIdx-1]; - } - /// superregclasses_begin / superregclasses_end - Loop over all of /// the superreg register classes of this register class. sc_iterator superregclasses_begin() const { @@ -159,57 +138,42 @@ public: } /// hasSubClass - return true if the specified TargetRegisterClass - /// is a proper subset of this TargetRegisterClass. - bool hasSubClass(const TargetRegisterClass *cs) const { - for (int i = 0; SubClasses[i] != NULL; ++i) - if (SubClasses[i] == cs) - return true; - return false; + /// is a proper sub-class of this TargetRegisterClass. + bool hasSubClass(const TargetRegisterClass *RC) const { + return RC != this && hasSubClassEq(RC); } - /// hasSubClassEq - Returns true if RC is a subclass of or equal to this + /// hasSubClassEq - Returns true if RC is a sub-class of or equal to this /// class. bool hasSubClassEq(const TargetRegisterClass *RC) const { - return RC == this || hasSubClass(RC); - } - - /// subclasses_begin / subclasses_end - Loop over all of the classes - /// that are proper subsets of this register class. - sc_iterator subclasses_begin() const { - return SubClasses; - } - - sc_iterator subclasses_end() const { - sc_iterator I = SubClasses; - while (*I != NULL) ++I; - return I; + unsigned ID = RC->getID(); + return (SubClassMask[ID / 32] >> (ID % 32)) & 1; } /// hasSuperClass - return true if the specified TargetRegisterClass is a - /// proper superset of this TargetRegisterClass. - bool hasSuperClass(const TargetRegisterClass *cs) const { - for (int i = 0; SuperClasses[i] != NULL; ++i) - if (SuperClasses[i] == cs) - return true; - return false; + /// proper super-class of this TargetRegisterClass. + bool hasSuperClass(const TargetRegisterClass *RC) const { + return RC->hasSubClass(this); } - /// hasSuperClassEq - Returns true if RC is a superclass of or equal to this + /// hasSuperClassEq - Returns true if RC is a super-class of or equal to this /// class. bool hasSuperClassEq(const TargetRegisterClass *RC) const { - return RC == this || hasSuperClass(RC); + return RC->hasSubClassEq(this); } - /// superclasses_begin / superclasses_end - Loop over all of the classes - /// that are proper supersets of this register class. - sc_iterator superclasses_begin() const { - return SuperClasses; + /// getSubClassMask - Returns a bit vector of subclasses, including this one. + /// The vector is indexed by class IDs, see hasSubClassEq() above for how to + /// use it. + const unsigned *getSubClassMask() const { + return SubClassMask; } - sc_iterator superclasses_end() const { - sc_iterator I = SuperClasses; - while (*I != NULL) ++I; - return I; + /// getSuperClasses - Returns a NULL terminated list of super-classes. The + /// classes are ordered by ID which is also a topological ordering from large + /// to small classes. The list does NOT include the current class. + sc_iterator getSuperClasses() const { + return SuperClasses; } /// isASubClass - return true if this TargetRegisterClass is a subset @@ -234,25 +198,8 @@ public: /// virtual ArrayRef getRawAllocationOrder(const MachineFunction &MF) const { - return ArrayRef(begin(), getNumRegs()); + return makeArrayRef(begin(), getNumRegs()); } - - /// getSize - Return the size of the register in bytes, which is also the size - /// of a stack slot allocated to hold a spilled copy of this register. - unsigned getSize() const { return RegSize; } - - /// getAlignment - Return the minimum required alignment for a register of - /// this class. - unsigned getAlignment() const { return Alignment; } - - /// getCopyCost - Return the cost of copying a value between two registers in - /// this class. A negative number means the register class is very expensive - /// to copy e.g. status flag register classes. - int getCopyCost() const { return CopyCost; } - - /// isAllocatable - Return true if this register class may be used to create - /// virtual registers. - bool isAllocatable() const { return Allocatable; } }; /// TargetRegisterInfoDesc - Extra information, not in MCRegisterDesc, about @@ -461,6 +408,20 @@ public: return 0; } + /// getSubClassWithSubReg - Returns the largest legal sub-class of RC that + /// supports the sub-register index Idx. + /// If no such sub-class exists, return NULL. + /// If all registers in RC already have an Idx sub-register, return RC. + /// + /// TableGen generates a version of this function that is good enough in most + /// cases. Targets can override if they have constraints that TableGen + /// doesn't understand. For example, the x86 sub_8bit sub-register index is + /// supported by the full GR32 register class in 64-bit mode, but only by the + /// GR32_ABCD regiister class in 32-bit mode. + /// + virtual const TargetRegisterClass * + getSubClassWithSubReg(const TargetRegisterClass *RC, unsigned Idx) const =0; + /// composeSubRegIndices - Return the subregister index you get from composing /// two subregister indices. /// @@ -498,6 +459,12 @@ public: return RegClassBegin[i]; } + /// getCommonSubClass - find the largest common subclass of A and B. Return + /// NULL if there is no common subclass. + const TargetRegisterClass * + getCommonSubClass(const TargetRegisterClass *A, + const TargetRegisterClass *B) const; + /// getPointerRegClass - Returns a TargetRegisterClass used for pointer /// values. If a target supports multiple different pointer register classes, /// kind specifies which one is indicated. @@ -699,28 +666,10 @@ public: //===--------------------------------------------------------------------===// /// Debug information queries. - /// getDwarfRegNum - Map a target register to an equivalent dwarf register - /// number. Returns -1 if there is no equivalent value. The second - /// parameter allows targets to use different numberings for EH info and - /// debugging info. - virtual int getDwarfRegNum(unsigned RegNum, bool isEH) const = 0; - - virtual int getLLVMRegNum(unsigned RegNum, bool isEH) const = 0; - /// getFrameRegister - This method should return the register used as a base /// for values allocated in the current stack frame. virtual unsigned getFrameRegister(const MachineFunction &MF) const = 0; - /// getRARegister - This method should return the register where the return - /// address can be found. - virtual unsigned getRARegister() const = 0; - - /// getSEHRegNum - Map a target register to an equivalent SEH register - /// number. Returns -1 if there is no equivalent value. - virtual int getSEHRegNum(unsigned i) const { - return i; - } - /// getCompactUnwindRegNum - This function maps the register to the number for /// compact unwind encoding. Return -1 if the register isn't valid. virtual int getCompactUnwindRegNum(unsigned, bool) const { @@ -736,11 +685,6 @@ struct VirtReg2IndexFunctor : public std::unary_function { } }; -/// getCommonSubClass - find the largest common subclass of A and B. Return NULL -/// if there is no common subclass. -const TargetRegisterClass *getCommonSubClass(const TargetRegisterClass *A, - const TargetRegisterClass *B); - /// PrintReg - Helper class for printing registers on a raw_ostream. /// Prints virtual and physical registers with or without a TRI instance. /// diff --git a/contrib/llvm/include/llvm/Target/TargetSelectionDAG.td b/contrib/llvm/include/llvm/Target/TargetSelectionDAG.td index 9d1ef2c13..612635ea7 100644 --- a/contrib/llvm/include/llvm/Target/TargetSelectionDAG.td +++ b/contrib/llvm/include/llvm/Target/TargetSelectionDAG.td @@ -149,6 +149,10 @@ def SDTSelect : SDTypeProfile<1, 3, [ // select SDTCisInt<1>, SDTCisSameAs<0, 2>, SDTCisSameAs<2, 3> ]>; +def SDTVSelect : SDTypeProfile<1, 3, [ // vselect + SDTCisInt<1>, SDTCisSameAs<0, 2>, SDTCisSameAs<2, 3> +]>; + def SDTSelectCC : SDTypeProfile<1, 5, [ // select_cc SDTCisSameAs<1, 2>, SDTCisSameAs<3, 4>, SDTCisSameAs<0, 3>, SDTCisVT<5, OtherVT> @@ -205,12 +209,21 @@ def SDTMemBarrier : SDTypeProfile<0, 5, [ // memory barier SDTCisSameAs<0,1>, SDTCisSameAs<0,2>, SDTCisSameAs<0,3>, SDTCisSameAs<0,4>, SDTCisInt<0> ]>; +def SDTAtomicFence : SDTypeProfile<0, 2, [ + SDTCisSameAs<0,1>, SDTCisPtrTy<0> +]>; def SDTAtomic3 : SDTypeProfile<1, 3, [ SDTCisSameAs<0,2>, SDTCisSameAs<0,3>, SDTCisInt<0>, SDTCisPtrTy<1> ]>; def SDTAtomic2 : SDTypeProfile<1, 2, [ SDTCisSameAs<0,2>, SDTCisInt<0>, SDTCisPtrTy<1> ]>; +def SDTAtomicStore : SDTypeProfile<0, 2, [ + SDTCisPtrTy<0>, SDTCisInt<1> +]>; +def SDTAtomicLoad : SDTypeProfile<1, 1, [ + SDTCisInt<0>, SDTCisPtrTy<1> +]>; def SDTConvertOp : SDTypeProfile<1, 5, [ //cvtss, su, us, uu, ff, fs, fu, sf, su SDTCisVT<2, OtherVT>, SDTCisVT<3, OtherVT>, SDTCisPtrTy<4>, SDTCisPtrTy<5> @@ -381,8 +394,8 @@ def f32_to_f16 : SDNode<"ISD::FP32_TO_FP16", SDTFPToIntOp>; def setcc : SDNode<"ISD::SETCC" , SDTSetCC>; def select : SDNode<"ISD::SELECT" , SDTSelect>; +def vselect : SDNode<"ISD::VSELECT" , SDTVSelect>; def selectcc : SDNode<"ISD::SELECT_CC" , SDTSelectCC>; -def vsetcc : SDNode<"ISD::VSETCC" , SDTSetCC>; def brcond : SDNode<"ISD::BRCOND" , SDTBrcond, [SDNPHasChain]>; def brind : SDNode<"ISD::BRIND" , SDTBrind, [SDNPHasChain]>; @@ -397,6 +410,9 @@ def prefetch : SDNode<"ISD::PREFETCH" , SDTPrefetch, def membarrier : SDNode<"ISD::MEMBARRIER" , SDTMemBarrier, [SDNPHasChain, SDNPSideEffect]>; +def atomic_fence : SDNode<"ISD::ATOMIC_FENCE" , SDTAtomicFence, + [SDNPHasChain, SDNPSideEffect]>; + def atomic_cmp_swap : SDNode<"ISD::ATOMIC_CMP_SWAP" , SDTAtomic3, [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; def atomic_load_add : SDNode<"ISD::ATOMIC_LOAD_ADD" , SDTAtomic2, @@ -421,6 +437,10 @@ def atomic_load_umin : SDNode<"ISD::ATOMIC_LOAD_UMIN", SDTAtomic2, [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; def atomic_load_umax : SDNode<"ISD::ATOMIC_LOAD_UMAX", SDTAtomic2, [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; +def atomic_load : SDNode<"ISD::ATOMIC_LOAD", SDTAtomicLoad, + [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; +def atomic_store : SDNode<"ISD::ATOMIC_STORE", SDTAtomicStore, + [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; // Do not use ld, st directly. Use load, extload, sextload, zextload, store, // and truncst (see below). @@ -838,6 +858,28 @@ defm atomic_load_min : binary_atomic_op; defm atomic_load_max : binary_atomic_op; defm atomic_load_umin : binary_atomic_op; defm atomic_load_umax : binary_atomic_op; +defm atomic_store : binary_atomic_op; + +def atomic_load_8 : + PatFrag<(ops node:$ptr), + (atomic_load node:$ptr), [{ + return cast(N)->getMemoryVT() == MVT::i8; +}]>; +def atomic_load_16 : + PatFrag<(ops node:$ptr), + (atomic_load node:$ptr), [{ + return cast(N)->getMemoryVT() == MVT::i16; +}]>; +def atomic_load_32 : + PatFrag<(ops node:$ptr), + (atomic_load node:$ptr), [{ + return cast(N)->getMemoryVT() == MVT::i32; +}]>; +def atomic_load_64 : + PatFrag<(ops node:$ptr), + (atomic_load node:$ptr), [{ + return cast(N)->getMemoryVT() == MVT::i64; +}]>; //===----------------------------------------------------------------------===// // Selection DAG CONVERT_RNDSAT patterns diff --git a/contrib/llvm/include/llvm/Transforms/IPO.h b/contrib/llvm/include/llvm/Transforms/IPO.h index f025e1806..f9d7f9e6b 100644 --- a/contrib/llvm/include/llvm/Transforms/IPO.h +++ b/contrib/llvm/include/llvm/Transforms/IPO.h @@ -49,13 +49,6 @@ ModulePass *createStripDebugDeclarePass(); // These pass removes unused symbols' debug info. ModulePass *createStripDeadDebugInfoPass(); -//===----------------------------------------------------------------------===// -/// createLowerSetJmpPass - This function lowers the setjmp/longjmp intrinsics -/// to invoke/unwind instructions. This should really be part of the C/C++ -/// front-end, but it's so much easier to write transformations in LLVM proper. -/// -ModulePass *createLowerSetJmpPass(); - //===----------------------------------------------------------------------===// /// createConstantMergePass - This function returns a new pass that merges /// duplicate global constants together into a single constant that is shared. @@ -81,7 +74,7 @@ ModulePass *createGlobalDCEPass(); //===----------------------------------------------------------------------===// -/// createGVExtractionPass - If deleteFn is true, this pass deletes as +/// createGVExtractionPass - If deleteFn is true, this pass deletes /// the specified global values. Otherwise, it deletes as much of the module as /// possible, except for the global values specified. /// diff --git a/contrib/llvm/include/llvm/Transforms/IPO/PassManagerBuilder.h b/contrib/llvm/include/llvm/Transforms/IPO/PassManagerBuilder.h new file mode 100644 index 000000000..cc74e7fef --- /dev/null +++ b/contrib/llvm/include/llvm/Transforms/IPO/PassManagerBuilder.h @@ -0,0 +1,133 @@ +// llvm/Transforms/IPO/PassManagerBuilder.h - Build Standard Pass -*- C++ -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the PassManagerBuilder class, which is used to set up a +// "standard" optimization sequence suitable for languages like C and C++. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_PASSMANAGERBUILDER_H +#define LLVM_SUPPORT_PASSMANAGERBUILDER_H + +#include + +namespace llvm { + class TargetLibraryInfo; + class PassManagerBase; + class Pass; + class FunctionPassManager; + +/// PassManagerBuilder - This class is used to set up a standard optimization +/// sequence for languages like C and C++, allowing some APIs to customize the +/// pass sequence in various ways. A simple example of using it would be: +/// +/// PassManagerBuilder Builder; +/// Builder.OptLevel = 2; +/// Builder.populateFunctionPassManager(FPM); +/// Builder.populateModulePassManager(MPM); +/// +/// In addition to setting up the basic passes, PassManagerBuilder allows +/// frontends to vend a plugin API, where plugins are allowed to add extensions +/// to the default pass manager. They do this by specifying where in the pass +/// pipeline they want to be added, along with a callback function that adds +/// the pass(es). For example, a plugin that wanted to add a loop optimization +/// could do something like this: +/// +/// static void addMyLoopPass(const PMBuilder &Builder, PassManagerBase &PM) { +/// if (Builder.getOptLevel() > 2 && Builder.getOptSizeLevel() == 0) +/// PM.add(createMyAwesomePass()); +/// } +/// ... +/// Builder.addExtension(PassManagerBuilder::EP_LoopOptimizerEnd, +/// addMyLoopPass); +/// ... +class PassManagerBuilder { +public: + + /// Extensions are passed the builder itself (so they can see how it is + /// configured) as well as the pass manager to add stuff to. + typedef void (*ExtensionFn)(const PassManagerBuilder &Builder, + PassManagerBase &PM); + enum ExtensionPointTy { + /// EP_EarlyAsPossible - This extension point allows adding passes before + /// any other transformations, allowing them to see the code as it is coming + /// out of the frontend. + EP_EarlyAsPossible, + + /// EP_LoopOptimizerEnd - This extension point allows adding loop passes to + /// the end of the loop optimizer. + EP_LoopOptimizerEnd, + + /// EP_ScalarOptimizerLate - This extension point allows adding optimization + /// passes after most of the main optimizations, but before the last + /// cleanup-ish optimizations. + EP_ScalarOptimizerLate + }; + + /// The Optimization Level - Specify the basic optimization level. + /// 0 = -O0, 1 = -O1, 2 = -O2, 3 = -O3 + unsigned OptLevel; + + /// SizeLevel - How much we're optimizing for size. + /// 0 = none, 1 = -Os, 2 = -Oz + unsigned SizeLevel; + + /// LibraryInfo - Specifies information about the runtime library for the + /// optimizer. If this is non-null, it is added to both the function and + /// per-module pass pipeline. + TargetLibraryInfo *LibraryInfo; + + /// Inliner - Specifies the inliner to use. If this is non-null, it is + /// added to the per-module passes. + Pass *Inliner; + + bool DisableSimplifyLibCalls; + bool DisableUnitAtATime; + bool DisableUnrollLoops; + +private: + /// ExtensionList - This is list of all of the extensions that are registered. + std::vector > Extensions; + +public: + PassManagerBuilder(); + ~PassManagerBuilder(); + /// Adds an extension that will be used by all PassManagerBuilder instances. + /// This is intended to be used by plugins, to register a set of + /// optimisations to run automatically. + static void addGlobalExtension(ExtensionPointTy Ty, ExtensionFn Fn); + void addExtension(ExtensionPointTy Ty, ExtensionFn Fn); + +private: + void addExtensionsToPM(ExtensionPointTy ETy, PassManagerBase &PM) const; + void addInitialAliasAnalysisPasses(PassManagerBase &PM) const; +public: + + /// populateFunctionPassManager - This fills in the function pass manager, + /// which is expected to be run on each function immediately as it is + /// generated. The idea is to reduce the size of the IR in memory. + void populateFunctionPassManager(FunctionPassManager &FPM); + + /// populateModulePassManager - This sets up the primary pass manager. + void populateModulePassManager(PassManagerBase &MPM); + void populateLTOPassManager(PassManagerBase &PM, bool Internalize, + bool RunInliner); +}; +/// Registers a function for adding a standard set of passes. This should be +/// used by optimizer plugins to allow all front ends to transparently use +/// them. Create a static instance of this class in your plugin, providing a +/// private function that the PassManagerBuilder can use to add your passes. +struct RegisterStandardPasses { + RegisterStandardPasses(PassManagerBuilder::ExtensionPointTy Ty, + PassManagerBuilder::ExtensionFn Fn) { + PassManagerBuilder::addGlobalExtension(Ty, Fn); + } +}; +} // end namespace llvm +#endif diff --git a/contrib/llvm/include/llvm/Transforms/Scalar.h b/contrib/llvm/include/llvm/Transforms/Scalar.h index 2187d4eb7..b1536f906 100644 --- a/contrib/llvm/include/llvm/Transforms/Scalar.h +++ b/contrib/llvm/include/llvm/Transforms/Scalar.h @@ -174,13 +174,6 @@ extern char &DemoteRegisterToMemoryID; // FunctionPass *createReassociatePass(); -//===----------------------------------------------------------------------===// -// -// TailDuplication - Eliminate unconditional branches through controlled code -// duplication, creating simpler CFG structures. -// -FunctionPass *createTailDuplicationPass(); - //===----------------------------------------------------------------------===// // // JumpThreading - Thread control through mult-pred/multi-succ blocks where some diff --git a/contrib/llvm/include/llvm/Transforms/Utils/AddrModeMatcher.h b/contrib/llvm/include/llvm/Transforms/Utils/AddrModeMatcher.h index 0678eccb5..90485eb4c 100644 --- a/contrib/llvm/include/llvm/Transforms/Utils/AddrModeMatcher.h +++ b/contrib/llvm/include/llvm/Transforms/Utils/AddrModeMatcher.h @@ -58,7 +58,7 @@ class AddressingModeMatcher { /// AccessTy/MemoryInst - This is the type for the access (e.g. double) and /// the memory instruction that we're computing this address for. - const Type *AccessTy; + Type *AccessTy; Instruction *MemoryInst; /// AddrMode - This is the addressing mode that we're building up. This is @@ -71,7 +71,7 @@ class AddressingModeMatcher { bool IgnoreProfitability; AddressingModeMatcher(SmallVectorImpl &AMI, - const TargetLowering &T, const Type *AT, + const TargetLowering &T, Type *AT, Instruction *MI, ExtAddrMode &AM) : AddrModeInsts(AMI), TLI(T), AccessTy(AT), MemoryInst(MI), AddrMode(AM) { IgnoreProfitability = false; @@ -81,7 +81,7 @@ public: /// Match - Find the maximal addressing mode that a load/store of V can fold, /// give an access type of AccessTy. This returns a list of involved /// instructions in AddrModeInsts. - static ExtAddrMode Match(Value *V, const Type *AccessTy, + static ExtAddrMode Match(Value *V, Type *AccessTy, Instruction *MemoryInst, SmallVectorImpl &AddrModeInsts, const TargetLowering &TLI) { diff --git a/contrib/llvm/include/llvm/Transforms/Utils/BasicBlockUtils.h b/contrib/llvm/include/llvm/Transforms/Utils/BasicBlockUtils.h index 90eabef12..6fcd160e6 100644 --- a/contrib/llvm/include/llvm/Transforms/Utils/BasicBlockUtils.h +++ b/contrib/llvm/include/llvm/Transforms/Utils/BasicBlockUtils.h @@ -31,8 +31,8 @@ class ReturnInst; /// DeleteDeadBlock - Delete the specified block, which must have no /// predecessors. void DeleteDeadBlock(BasicBlock *BB); - - + + /// FoldSingleEntryPHINodes - We know that BB has one predecessor. If there are /// any single-entry PHI nodes in it, fold them away. This handles the case /// when all entries to the PHI nodes in a block are guaranteed equal, such as @@ -75,7 +75,7 @@ void ReplaceInstWithInst(Instruction *From, Instruction *To); /// The output is added to Result, as pairs of edge info. void FindFunctionBackedges(const Function &F, SmallVectorImpl > &Result); - + /// GetSuccessorNumber - Search for the specified successor of basic block BB /// and return its position in the terminator instruction's list of @@ -97,10 +97,10 @@ bool isCriticalEdge(const TerminatorInst *TI, unsigned SuccNum, /// was split, null otherwise. /// /// If MergeIdenticalEdges is true (not the default), *all* edges from TI to the -/// specified successor will be merged into the same critical edge block. -/// This is most commonly interesting with switch instructions, which may +/// specified successor will be merged into the same critical edge block. +/// This is most commonly interesting with switch instructions, which may /// have many edges to any one destination. This ensures that all edges to that -/// dest go to one block instead of each going to a different block, but isn't +/// dest go to one block instead of each going to a different block, but isn't /// the standard definition of a "critical edge". /// /// It is invalid to call this function on a critical edge that starts at an @@ -109,7 +109,8 @@ bool isCriticalEdge(const TerminatorInst *TI, unsigned SuccNum, /// to. /// BasicBlock *SplitCriticalEdge(TerminatorInst *TI, unsigned SuccNum, - Pass *P = 0, bool MergeIdenticalEdges = false); + Pass *P = 0, bool MergeIdenticalEdges = false, + bool DontDeleteUselessPHIs = false); inline BasicBlock *SplitCriticalEdge(BasicBlock *BB, succ_iterator SI, Pass *P = 0) { @@ -136,19 +137,21 @@ inline bool SplitCriticalEdge(BasicBlock *Succ, pred_iterator PI, Pass *P = 0) { /// described above. inline BasicBlock *SplitCriticalEdge(BasicBlock *Src, BasicBlock *Dst, Pass *P = 0, - bool MergeIdenticalEdges = false) { + bool MergeIdenticalEdges = false, + bool DontDeleteUselessPHIs = false) { TerminatorInst *TI = Src->getTerminator(); unsigned i = 0; while (1) { assert(i != TI->getNumSuccessors() && "Edge doesn't exist!"); if (TI->getSuccessor(i) == Dst) - return SplitCriticalEdge(TI, i, P, MergeIdenticalEdges); + return SplitCriticalEdge(TI, i, P, MergeIdenticalEdges, + DontDeleteUselessPHIs); ++i; } } -/// SplitEdge - Split the edge connecting specified block. Pass P must -/// not be NULL. +/// SplitEdge - Split the edge connecting specified block. Pass P must +/// not be NULL. BasicBlock *SplitEdge(BasicBlock *From, BasicBlock *To, Pass *P); /// SplitBlock - Split the specified block at the specified instruction - every @@ -157,7 +160,7 @@ BasicBlock *SplitEdge(BasicBlock *From, BasicBlock *To, Pass *P); /// the loop info is updated. /// BasicBlock *SplitBlock(BasicBlock *Old, Instruction *SplitPt, Pass *P); - + /// SplitBlockPredecessors - This method transforms BB by introducing a new /// basic block into the function, and moving some of the predecessors of BB to /// be predecessors of the new block. The new predecessors are indicated by the @@ -174,6 +177,23 @@ BasicBlock *SplitBlockPredecessors(BasicBlock *BB, BasicBlock *const *Preds, unsigned NumPreds, const char *Suffix, Pass *P = 0); +/// SplitLandingPadPredecessors - This method transforms the landing pad, +/// OrigBB, by introducing two new basic blocks into the function. One of those +/// new basic blocks gets the predecessors listed in Preds. The other basic +/// block gets the remaining predecessors of OrigBB. The landingpad instruction +/// OrigBB is clone into both of the new basic blocks. The new blocks are given +/// the suffixes 'Suffix1' and 'Suffix2', and are returned in the NewBBs vector. +/// +/// This currently updates the LLVM IR, AliasAnalysis, DominatorTree, +/// DominanceFrontier, LoopInfo, and LCCSA but no other analyses. In particular, +/// it does not preserve LoopSimplify (because it's complicated to handle the +/// case where one of the edges being split is an exit of a loop with other +/// exits). +/// +void SplitLandingPadPredecessors(BasicBlock *OrigBB,ArrayRef Preds, + const char *Suffix, const char *Suffix2, + Pass *P, SmallVectorImpl &NewBBs); + /// FoldReturnIntoUncondBranch - This method duplicates the specified return /// instruction into a predecessor which ends in an unconditional branch. If /// the return instruction returns a value defined by a PHI, propagate the @@ -182,7 +202,7 @@ BasicBlock *SplitBlockPredecessors(BasicBlock *BB, BasicBlock *const *Preds, ReturnInst *FoldReturnIntoUncondBranch(ReturnInst *RI, BasicBlock *BB, BasicBlock *Pred); -/// GetFirstDebugLocInBasicBlock - Return first valid DebugLoc entry in a +/// GetFirstDebugLocInBasicBlock - Return first valid DebugLoc entry in a /// given basic block. DebugLoc GetFirstDebugLocInBasicBlock(const BasicBlock *BB); diff --git a/contrib/llvm/include/llvm/Transforms/Utils/FunctionUtils.h b/contrib/llvm/include/llvm/Transforms/Utils/FunctionUtils.h index 785b08f82..8d71e43aa 100644 --- a/contrib/llvm/include/llvm/Transforms/Utils/FunctionUtils.h +++ b/contrib/llvm/include/llvm/Transforms/Utils/FunctionUtils.h @@ -14,6 +14,7 @@ #ifndef LLVM_TRANSFORMS_UTILS_FUNCTION_H #define LLVM_TRANSFORMS_UTILS_FUNCTION_H +#include "llvm/ADT/ArrayRef.h" #include namespace llvm { @@ -22,20 +23,23 @@ namespace llvm { class Function; class Loop; - /// ExtractCodeRegion - rip out a sequence of basic blocks into a new function + /// ExtractCodeRegion - Rip out a sequence of basic blocks into a new + /// function. /// Function* ExtractCodeRegion(DominatorTree& DT, - const std::vector &code, + ArrayRef code, bool AggregateArgs = false); - /// ExtractLoop - rip out a natural loop into a new function + /// ExtractLoop - Rip out a natural loop into a new function. /// Function* ExtractLoop(DominatorTree& DT, Loop *L, bool AggregateArgs = false); - /// ExtractBasicBlock - rip out a basic block into a new function + /// ExtractBasicBlock - Rip out a basic block (and the associated landing pad) + /// into a new function. /// - Function* ExtractBasicBlock(BasicBlock *BB, bool AggregateArgs = false); + Function* ExtractBasicBlock(ArrayRef BBs, + bool AggregateArgs = false); } #endif diff --git a/contrib/llvm/include/llvm/Transforms/Utils/SSAUpdater.h b/contrib/llvm/include/llvm/Transforms/Utils/SSAUpdater.h index 063d41398..064e5501a 100644 --- a/contrib/llvm/include/llvm/Transforms/Utils/SSAUpdater.h +++ b/contrib/llvm/include/llvm/Transforms/Utils/SSAUpdater.h @@ -39,7 +39,7 @@ private: void *AV; /// ProtoType holds the type of the values being rewritten. - const Type *ProtoType; + Type *ProtoType; // PHI nodes are given a name based on ProtoName. std::string ProtoName; @@ -56,7 +56,7 @@ public: /// Initialize - Reset this object to get ready for a new set of SSA /// updates with type 'Ty'. PHI nodes get a name based on 'Name'. - void Initialize(const Type *Ty, StringRef Name); + void Initialize(Type *Ty, StringRef Name); /// AddAvailableValue - Indicate that a rewritten value is available at the /// end of the specified block with the specified value. diff --git a/contrib/llvm/include/llvm/Transforms/Utils/SimplifyIndVar.h b/contrib/llvm/include/llvm/Transforms/Utils/SimplifyIndVar.h new file mode 100644 index 000000000..524cf5ad9 --- /dev/null +++ b/contrib/llvm/include/llvm/Transforms/Utils/SimplifyIndVar.h @@ -0,0 +1,58 @@ +//===-- llvm/Transforms/Utils/SimplifyIndVar.h - Indvar Utils ---*- 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 in interface for induction variable simplification. It does +// not define any actual pass or policy, but provides a single function to +// simplify a loop's induction variables based on ScalarEvolution. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_UTILS_SIMPLIFYINDVAR_H +#define LLVM_TRANSFORMS_UTILS_SIMPLIFYINDVAR_H + +#include "llvm/Support/CommandLine.h" + +namespace llvm { + +extern cl::opt DisableIVRewrite; + +class Loop; +class LoopInfo; +class DominatorTree; +class ScalarEvolution; +class LPPassManager; +class IVUsers; + +/// Interface for visiting interesting IV users that are recognized but not +/// simplified by this utility. +class IVVisitor { +public: + virtual ~IVVisitor() {} + virtual void visitCast(CastInst *Cast) = 0; +}; + +/// simplifyUsersOfIV - Simplify instructions that use this induction variable +/// by using ScalarEvolution to analyze the IV's recurrence. +bool simplifyUsersOfIV(PHINode *CurrIV, ScalarEvolution *SE, LPPassManager *LPM, + SmallVectorImpl &Dead, IVVisitor *V = NULL); + +/// SimplifyLoopIVs - Simplify users of induction variables within this +/// loop. This does not actually change or add IVs. +bool simplifyLoopIVs(Loop *L, ScalarEvolution *SE, LPPassManager *LPM, + SmallVectorImpl &Dead); + +/// simplifyIVUsers - Simplify instructions recorded by the IVUsers pass. +/// This is a legacy implementation to reproduce the behavior of the +/// IndVarSimplify pass prior to DisableIVRewrite. +bool simplifyIVUsers(IVUsers *IU, ScalarEvolution *SE, LPPassManager *LPM, + SmallVectorImpl &Dead); + +} // namespace llvm + +#endif diff --git a/contrib/llvm/include/llvm/Transforms/Utils/UnrollLoop.h b/contrib/llvm/include/llvm/Transforms/Utils/UnrollLoop.h index 3d5ee1a62..7212a8c76 100644 --- a/contrib/llvm/include/llvm/Transforms/Utils/UnrollLoop.h +++ b/contrib/llvm/include/llvm/Transforms/Utils/UnrollLoop.h @@ -22,7 +22,8 @@ class Loop; class LoopInfo; class LPPassManager; -bool UnrollLoop(Loop *L, unsigned Count, LoopInfo* LI, LPPassManager* LPM); +bool UnrollLoop(Loop *L, unsigned Count, unsigned TripCount, + unsigned TripMultiple, LoopInfo* LI, LPPassManager* LPM); } diff --git a/contrib/llvm/include/llvm/Transforms/Utils/ValueMapper.h b/contrib/llvm/include/llvm/Transforms/Utils/ValueMapper.h index 2194373c4..03846567d 100644 --- a/contrib/llvm/include/llvm/Transforms/Utils/ValueMapper.h +++ b/contrib/llvm/include/llvm/Transforms/Utils/ValueMapper.h @@ -66,12 +66,12 @@ namespace llvm { inline MDNode *MapValue(const MDNode *V, ValueToValueMapTy &VM, RemapFlags Flags = RF_None, ValueMapTypeRemapper *TypeMapper = 0) { - return (MDNode*)MapValue((const Value*)V, VM, Flags, TypeMapper); + return cast(MapValue((const Value*)V, VM, Flags, TypeMapper)); } inline Constant *MapValue(const Constant *V, ValueToValueMapTy &VM, RemapFlags Flags = RF_None, ValueMapTypeRemapper *TypeMapper = 0) { - return (Constant*)MapValue((const Value*)V, VM, Flags, TypeMapper); + return cast(MapValue((const Value*)V, VM, Flags, TypeMapper)); } diff --git a/contrib/llvm/include/llvm/Type.h b/contrib/llvm/include/llvm/Type.h index e4ff3e1c8..43b7dc578 100644 --- a/contrib/llvm/include/llvm/Type.h +++ b/contrib/llvm/include/llvm/Type.h @@ -193,7 +193,7 @@ public: /// are valid for types of the same size only where no re-interpretation of /// the bits is done. /// @brief Determine if this type could be losslessly bitcast to Ty - bool canLosslesslyBitCastTo(const Type *Ty) const; + bool canLosslesslyBitCastTo(Type *Ty) const; /// isEmptyTy - Return true if this type is empty, that is, it has no /// elements or all its elements are empty. @@ -262,7 +262,7 @@ public: /// getScalarSizeInBits - If this is a vector type, return the /// getPrimitiveSizeInBits value for the element type. Otherwise return the /// getPrimitiveSizeInBits value for this type. - unsigned getScalarSizeInBits() const; + unsigned getScalarSizeInBits(); /// getFPMantissaWidth - Return the width of the mantissa of this type. This /// is only valid on floating point types. If the FP type does not @@ -271,7 +271,7 @@ public: /// getScalarType - If this is a vector type, return the element type, /// otherwise return 'this'. - const Type *getScalarType() const; + Type *getScalarType(); //===--------------------------------------------------------------------===// // Type Iteration support. @@ -342,7 +342,7 @@ public: /// getPointerTo - Return a pointer to the current type. This is equivalent /// to PointerType::get(Foo, AddrSpace). - PointerType *getPointerTo(unsigned AddrSpace = 0) const; + PointerType *getPointerTo(unsigned AddrSpace = 0); private: /// isSizedDerivedType - Derived types like structures and arrays are sized @@ -352,7 +352,7 @@ private: }; // Printing of types. -static inline raw_ostream &operator<<(raw_ostream &OS, const Type &T) { +static inline raw_ostream &operator<<(raw_ostream &OS, Type &T) { T.print(OS); return OS; } @@ -387,7 +387,7 @@ template <> struct GraphTraits { typedef const Type NodeType; typedef Type::subtype_iterator ChildIteratorType; - static inline NodeType *getEntryNode(const Type *T) { return T; } + static inline NodeType *getEntryNode(NodeType *T) { return T; } static inline ChildIteratorType child_begin(NodeType *N) { return N->subtype_begin(); } diff --git a/contrib/llvm/include/llvm/User.h b/contrib/llvm/include/llvm/User.h index 3f9c28e7b..62bc9f034 100644 --- a/contrib/llvm/include/llvm/User.h +++ b/contrib/llvm/include/llvm/User.h @@ -47,7 +47,7 @@ protected: unsigned NumOperands; void *operator new(size_t s, unsigned Us); - User(const Type *ty, unsigned vty, Use *OpList, unsigned NumOps) + User(Type *ty, unsigned vty, Use *OpList, unsigned NumOps) : Value(ty, vty), OperandList(OpList), NumOperands(NumOps) {} Use *allocHungoffUses(unsigned) const; void dropHungoffUses() { diff --git a/contrib/llvm/include/llvm/Value.h b/contrib/llvm/include/llvm/Value.h index 08fa1c903..a71e2fdef 100644 --- a/contrib/llvm/include/llvm/Value.h +++ b/contrib/llvm/include/llvm/Value.h @@ -91,7 +91,7 @@ protected: /// printing behavior. virtual void printCustom(raw_ostream &O) const; - Value(const Type *Ty, unsigned scid); + Value(Type *Ty, unsigned scid); public: virtual ~Value(); @@ -183,7 +183,7 @@ public: bool isUsedInBasicBlock(const BasicBlock *BB) const; /// getNumUses - This method computes the number of uses of this Value. This - /// is a linear time operation. Use hasOneUse, hasNUses, or hasMoreThanNUses + /// is a linear time operation. Use hasOneUse, hasNUses, or hasNUsesOrMore /// to check for specific values. unsigned getNumUses() const; diff --git a/contrib/llvm/lib/Analysis/AliasAnalysis.cpp b/contrib/llvm/lib/Analysis/AliasAnalysis.cpp index c189a0042..bd132c05c 100644 --- a/contrib/llvm/lib/Analysis/AliasAnalysis.cpp +++ b/contrib/llvm/lib/Analysis/AliasAnalysis.cpp @@ -237,6 +237,19 @@ AliasAnalysis::Location AliasAnalysis::getLocation(const VAArgInst *VI) { VI->getMetadata(LLVMContext::MD_tbaa)); } +AliasAnalysis::Location +AliasAnalysis::getLocation(const AtomicCmpXchgInst *CXI) { + return Location(CXI->getPointerOperand(), + getTypeStoreSize(CXI->getCompareOperand()->getType()), + CXI->getMetadata(LLVMContext::MD_tbaa)); +} + +AliasAnalysis::Location +AliasAnalysis::getLocation(const AtomicRMWInst *RMWI) { + return Location(RMWI->getPointerOperand(), + getTypeStoreSize(RMWI->getValOperand()->getType()), + RMWI->getMetadata(LLVMContext::MD_tbaa)); +} AliasAnalysis::Location AliasAnalysis::getLocationForSource(const MemTransferInst *MTI) { @@ -268,8 +281,8 @@ AliasAnalysis::getLocationForDest(const MemIntrinsic *MTI) { AliasAnalysis::ModRefResult AliasAnalysis::getModRefInfo(const LoadInst *L, const Location &Loc) { - // Be conservative in the face of volatile. - if (L->isVolatile()) + // Be conservative in the face of volatile/atomic. + if (!L->isUnordered()) return ModRef; // If the load address doesn't alias the given address, it doesn't read @@ -283,8 +296,8 @@ AliasAnalysis::getModRefInfo(const LoadInst *L, const Location &Loc) { AliasAnalysis::ModRefResult AliasAnalysis::getModRefInfo(const StoreInst *S, const Location &Loc) { - // Be conservative in the face of volatile. - if (S->isVolatile()) + // Be conservative in the face of volatile/atomic. + if (!S->isUnordered()) return ModRef; // If the store address cannot alias the pointer in question, then the @@ -317,6 +330,33 @@ AliasAnalysis::getModRefInfo(const VAArgInst *V, const Location &Loc) { return ModRef; } +AliasAnalysis::ModRefResult +AliasAnalysis::getModRefInfo(const AtomicCmpXchgInst *CX, const Location &Loc) { + // Acquire/Release cmpxchg has properties that matter for arbitrary addresses. + if (CX->getOrdering() > Monotonic) + return ModRef; + + // If the cmpxchg address does not alias the location, it does not access it. + if (!alias(getLocation(CX), Loc)) + return NoModRef; + + return ModRef; +} + +AliasAnalysis::ModRefResult +AliasAnalysis::getModRefInfo(const AtomicRMWInst *RMW, const Location &Loc) { + // Acquire/Release atomicrmw has properties that matter for arbitrary addresses. + if (RMW->getOrdering() > Monotonic) + return ModRef; + + // If the atomicrmw address does not alias the location, it does not access it. + if (!alias(getLocation(RMW), Loc)) + return NoModRef; + + return ModRef; +} + + // AliasAnalysis destructor: DO NOT move this to the header file for // AliasAnalysis or else clients of the AliasAnalysis class may not depend on // the AliasAnalysis.o file in the current .a file, causing alias analysis @@ -341,7 +381,7 @@ void AliasAnalysis::getAnalysisUsage(AnalysisUsage &AU) const { /// getTypeStoreSize - Return the TargetData store size for the given type, /// if known, or a conservative value otherwise. /// -uint64_t AliasAnalysis::getTypeStoreSize(const Type *Ty) { +uint64_t AliasAnalysis::getTypeStoreSize(Type *Ty) { return TD ? TD->getTypeStoreSize(Ty) : UnknownSize; } diff --git a/contrib/llvm/lib/Analysis/AliasAnalysisEvaluator.cpp b/contrib/llvm/lib/Analysis/AliasAnalysisEvaluator.cpp index 1afc1b71d..37271b94a 100644 --- a/contrib/llvm/lib/Analysis/AliasAnalysisEvaluator.cpp +++ b/contrib/llvm/lib/Analysis/AliasAnalysisEvaluator.cpp @@ -171,12 +171,12 @@ bool AAEval::runOnFunction(Function &F) { for (SetVector::iterator I1 = Pointers.begin(), E = Pointers.end(); I1 != E; ++I1) { uint64_t I1Size = AliasAnalysis::UnknownSize; - const Type *I1ElTy = cast((*I1)->getType())->getElementType(); + Type *I1ElTy = cast((*I1)->getType())->getElementType(); if (I1ElTy->isSized()) I1Size = AA.getTypeStoreSize(I1ElTy); for (SetVector::iterator I2 = Pointers.begin(); I2 != I1; ++I2) { uint64_t I2Size = AliasAnalysis::UnknownSize; - const Type *I2ElTy =cast((*I2)->getType())->getElementType(); + Type *I2ElTy =cast((*I2)->getType())->getElementType(); if (I2ElTy->isSized()) I2Size = AA.getTypeStoreSize(I2ElTy); switch (AA.alias(*I1, I1Size, *I2, I2Size)) { @@ -207,7 +207,7 @@ bool AAEval::runOnFunction(Function &F) { for (SetVector::iterator V = Pointers.begin(), Ve = Pointers.end(); V != Ve; ++V) { uint64_t Size = AliasAnalysis::UnknownSize; - const Type *ElTy = cast((*V)->getType())->getElementType(); + Type *ElTy = cast((*V)->getType())->getElementType(); if (ElTy->isSized()) Size = AA.getTypeStoreSize(ElTy); switch (AA.getModRefInfo(*C, *V, Size)) { diff --git a/contrib/llvm/lib/Analysis/AliasSetTracker.cpp b/contrib/llvm/lib/Analysis/AliasSetTracker.cpp index 2ed694941..3fcd3b55d 100644 --- a/contrib/llvm/lib/Analysis/AliasSetTracker.cpp +++ b/contrib/llvm/lib/Analysis/AliasSetTracker.cpp @@ -56,12 +56,12 @@ void AliasSet::mergeSetIn(AliasSet &AS, AliasSetTracker &AST) { AliasTy = MayAlias; } - if (CallSites.empty()) { // Merge call sites... - if (!AS.CallSites.empty()) - std::swap(CallSites, AS.CallSites); - } else if (!AS.CallSites.empty()) { - CallSites.insert(CallSites.end(), AS.CallSites.begin(), AS.CallSites.end()); - AS.CallSites.clear(); + if (UnknownInsts.empty()) { // Merge call sites... + if (!AS.UnknownInsts.empty()) + std::swap(UnknownInsts, AS.UnknownInsts); + } else if (!AS.UnknownInsts.empty()) { + UnknownInsts.insert(UnknownInsts.end(), AS.UnknownInsts.begin(), AS.UnknownInsts.end()); + AS.UnknownInsts.clear(); } AS.Forward = this; // Forward across AS now... @@ -123,13 +123,10 @@ void AliasSet::addPointer(AliasSetTracker &AST, PointerRec &Entry, addRef(); // Entry points to alias set. } -void AliasSet::addCallSite(CallSite CS, AliasAnalysis &AA) { - CallSites.push_back(CS.getInstruction()); +void AliasSet::addUnknownInst(Instruction *I, AliasAnalysis &AA) { + UnknownInsts.push_back(I); - AliasAnalysis::ModRefBehavior Behavior = AA.getModRefBehavior(CS); - if (Behavior == AliasAnalysis::DoesNotAccessMemory) - return; - if (AliasAnalysis::onlyReadsMemory(Behavior)) { + if (!I->mayWriteToMemory()) { AliasTy = MayAlias; AccessTy |= Refs; return; @@ -147,7 +144,7 @@ bool AliasSet::aliasesPointer(const Value *Ptr, uint64_t Size, const MDNode *TBAAInfo, AliasAnalysis &AA) const { if (AliasTy == MustAlias) { - assert(CallSites.empty() && "Illegal must alias set!"); + assert(UnknownInsts.empty() && "Illegal must alias set!"); // If this is a set of MustAliases, only check to see if the pointer aliases // SOME value in the set. @@ -167,10 +164,10 @@ bool AliasSet::aliasesPointer(const Value *Ptr, uint64_t Size, I.getTBAAInfo()))) return true; - // Check the call sites list and invoke list... - if (!CallSites.empty()) { - for (unsigned i = 0, e = CallSites.size(); i != e; ++i) - if (AA.getModRefInfo(CallSites[i], + // Check the unknown instructions... + if (!UnknownInsts.empty()) { + for (unsigned i = 0, e = UnknownInsts.size(); i != e; ++i) + if (AA.getModRefInfo(UnknownInsts[i], AliasAnalysis::Location(Ptr, Size, TBAAInfo)) != AliasAnalysis::NoModRef) return true; @@ -179,18 +176,20 @@ bool AliasSet::aliasesPointer(const Value *Ptr, uint64_t Size, return false; } -bool AliasSet::aliasesCallSite(CallSite CS, AliasAnalysis &AA) const { - if (AA.doesNotAccessMemory(CS)) +bool AliasSet::aliasesUnknownInst(Instruction *Inst, AliasAnalysis &AA) const { + if (!Inst->mayReadOrWriteMemory()) return false; - for (unsigned i = 0, e = CallSites.size(); i != e; ++i) { - if (AA.getModRefInfo(getCallSite(i), CS) != AliasAnalysis::NoModRef || - AA.getModRefInfo(CS, getCallSite(i)) != AliasAnalysis::NoModRef) + for (unsigned i = 0, e = UnknownInsts.size(); i != e; ++i) { + CallSite C1 = getUnknownInst(i), C2 = Inst; + if (!C1 || !C2 || + AA.getModRefInfo(C1, C2) != AliasAnalysis::NoModRef || + AA.getModRefInfo(C2, C1) != AliasAnalysis::NoModRef) return true; } for (iterator I = begin(), E = end(); I != E; ++I) - if (AA.getModRefInfo(CS, I.getPointer(), I.getSize()) != + if (AA.getModRefInfo(Inst, I.getPointer(), I.getSize()) != AliasAnalysis::NoModRef) return true; @@ -244,10 +243,10 @@ bool AliasSetTracker::containsPointer(Value *Ptr, uint64_t Size, -AliasSet *AliasSetTracker::findAliasSetForCallSite(CallSite CS) { +AliasSet *AliasSetTracker::findAliasSetForUnknownInst(Instruction *Inst) { AliasSet *FoundSet = 0; for (iterator I = begin(), E = end(); I != E; ++I) { - if (I->Forward || !I->aliasesCallSite(CS, AA)) + if (I->Forward || !I->aliasesUnknownInst(Inst, AA)) continue; if (FoundSet == 0) // If this is the first alias set ptr can go into. @@ -296,22 +295,28 @@ bool AliasSetTracker::add(Value *Ptr, uint64_t Size, const MDNode *TBAAInfo) { bool AliasSetTracker::add(LoadInst *LI) { + if (LI->getOrdering() > Monotonic) return addUnknown(LI); + AliasSet::AccessType ATy = AliasSet::Refs; + if (!LI->isUnordered()) ATy = AliasSet::ModRef; bool NewPtr; AliasSet &AS = addPointer(LI->getOperand(0), AA.getTypeStoreSize(LI->getType()), LI->getMetadata(LLVMContext::MD_tbaa), - AliasSet::Refs, NewPtr); + ATy, NewPtr); if (LI->isVolatile()) AS.setVolatile(); return NewPtr; } bool AliasSetTracker::add(StoreInst *SI) { + if (SI->getOrdering() > Monotonic) return addUnknown(SI); + AliasSet::AccessType ATy = AliasSet::Mods; + if (!SI->isUnordered()) ATy = AliasSet::ModRef; bool NewPtr; Value *Val = SI->getOperand(0); AliasSet &AS = addPointer(SI->getOperand(1), AA.getTypeStoreSize(Val->getType()), SI->getMetadata(LLVMContext::MD_tbaa), - AliasSet::Mods, NewPtr); + ATy, NewPtr); if (SI->isVolatile()) AS.setVolatile(); return NewPtr; } @@ -325,20 +330,20 @@ bool AliasSetTracker::add(VAArgInst *VAAI) { } -bool AliasSetTracker::add(CallSite CS) { - if (isa(CS.getInstruction())) +bool AliasSetTracker::addUnknown(Instruction *Inst) { + if (isa(Inst)) return true; // Ignore DbgInfo Intrinsics. - if (AA.doesNotAccessMemory(CS)) + if (!Inst->mayReadOrWriteMemory()) return true; // doesn't alias anything - AliasSet *AS = findAliasSetForCallSite(CS); + AliasSet *AS = findAliasSetForUnknownInst(Inst); if (AS) { - AS->addCallSite(CS, AA); + AS->addUnknownInst(Inst, AA); return false; } AliasSets.push_back(new AliasSet()); AS = &AliasSets.back(); - AS->addCallSite(CS, AA); + AS->addUnknownInst(Inst, AA); return true; } @@ -348,13 +353,9 @@ bool AliasSetTracker::add(Instruction *I) { return add(LI); if (StoreInst *SI = dyn_cast(I)) return add(SI); - if (CallInst *CI = dyn_cast(I)) - return add(CI); - if (InvokeInst *II = dyn_cast(I)) - return add(II); if (VAArgInst *VAAI = dyn_cast(I)) return add(VAAI); - return true; + return addUnknown(I); } void AliasSetTracker::add(BasicBlock &BB) { @@ -375,8 +376,8 @@ void AliasSetTracker::add(const AliasSetTracker &AST) { AliasSet &AS = const_cast(*I); // If there are any call sites in the alias set, add them to this AST. - for (unsigned i = 0, e = AS.CallSites.size(); i != e; ++i) - add(AS.CallSites[i]); + for (unsigned i = 0, e = AS.UnknownInsts.size(); i != e; ++i) + add(AS.UnknownInsts[i]); // Loop over all of the pointers in this alias set. bool X; @@ -393,7 +394,7 @@ void AliasSetTracker::add(const AliasSetTracker &AST) { /// tracker. void AliasSetTracker::remove(AliasSet &AS) { // Drop all call sites. - AS.CallSites.clear(); + AS.UnknownInsts.clear(); // Clear the alias set. unsigned NumRefs = 0; @@ -453,11 +454,11 @@ bool AliasSetTracker::remove(VAArgInst *VAAI) { return true; } -bool AliasSetTracker::remove(CallSite CS) { - if (AA.doesNotAccessMemory(CS)) +bool AliasSetTracker::removeUnknown(Instruction *I) { + if (!I->mayReadOrWriteMemory()) return false; // doesn't alias anything - AliasSet *AS = findAliasSetForCallSite(CS); + AliasSet *AS = findAliasSetForUnknownInst(I); if (!AS) return false; remove(*AS); return true; @@ -469,11 +470,9 @@ bool AliasSetTracker::remove(Instruction *I) { return remove(LI); if (StoreInst *SI = dyn_cast(I)) return remove(SI); - if (CallInst *CI = dyn_cast(I)) - return remove(CI); if (VAArgInst *VAAI = dyn_cast(I)) return remove(VAAI); - return true; + return removeUnknown(I); } @@ -488,13 +487,13 @@ void AliasSetTracker::deleteValue(Value *PtrVal) { // If this is a call instruction, remove the callsite from the appropriate // AliasSet (if present). - if (CallSite CS = PtrVal) { - if (!AA.doesNotAccessMemory(CS)) { + if (Instruction *Inst = dyn_cast(PtrVal)) { + if (Inst->mayReadOrWriteMemory()) { // Scan all the alias sets to see if this call site is contained. for (iterator I = begin(), E = end(); I != E; ++I) { if (I->Forward) continue; - I->removeCallSite(CS); + I->removeUnknownInst(Inst); } } } @@ -571,11 +570,11 @@ void AliasSet::print(raw_ostream &OS) const { OS << ", " << I.getSize() << ")"; } } - if (!CallSites.empty()) { - OS << "\n " << CallSites.size() << " Call Sites: "; - for (unsigned i = 0, e = CallSites.size(); i != e; ++i) { + if (!UnknownInsts.empty()) { + OS << "\n " << UnknownInsts.size() << " Unknown instructions: "; + for (unsigned i = 0, e = UnknownInsts.size(); i != e; ++i) { if (i) OS << ", "; - WriteAsOperand(OS, CallSites[i]); + WriteAsOperand(OS, UnknownInsts[i]); } } OS << "\n"; diff --git a/contrib/llvm/lib/Analysis/Analysis.cpp b/contrib/llvm/lib/Analysis/Analysis.cpp index 71e0a8326..0ba6af93b 100644 --- a/contrib/llvm/lib/Analysis/Analysis.cpp +++ b/contrib/llvm/lib/Analysis/Analysis.cpp @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// #include "llvm-c/Analysis.h" +#include "llvm-c/Initialization.h" #include "llvm/InitializePasses.h" #include "llvm/Analysis/Verifier.h" #include @@ -23,7 +24,7 @@ void llvm::initializeAnalysis(PassRegistry &Registry) { initializeAliasSetPrinterPass(Registry); initializeNoAAPass(Registry); initializeBasicAliasAnalysisPass(Registry); - initializeBlockFrequencyPass(Registry); + initializeBlockFrequencyInfoPass(Registry); initializeBranchProbabilityInfoPass(Registry); initializeCFGViewerPass(Registry); initializeCFGPrinterPass(Registry); diff --git a/contrib/llvm/lib/Analysis/BasicAliasAnalysis.cpp b/contrib/llvm/lib/Analysis/BasicAliasAnalysis.cpp index 8330ea7c7..af400ba7e 100644 --- a/contrib/llvm/lib/Analysis/BasicAliasAnalysis.cpp +++ b/contrib/llvm/lib/Analysis/BasicAliasAnalysis.cpp @@ -30,6 +30,7 @@ #include "llvm/Analysis/InstructionSimplify.h" #include "llvm/Analysis/ValueTracking.h" #include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetLibraryInfo.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/ErrorHandling.h" @@ -100,7 +101,7 @@ static bool isEscapeSource(const Value *V) { /// getObjectSize - Return the size of the object specified by V, or /// UnknownSize if unknown. static uint64_t getObjectSize(const Value *V, const TargetData &TD) { - const Type *AccessTy; + Type *AccessTy; if (const GlobalVariable *GV = dyn_cast(V)) { if (!GV->hasDefinitiveInitializer()) return AliasAnalysis::UnknownSize; @@ -317,7 +318,7 @@ DecomposeGEPExpression(const Value *V, int64_t &BaseOffs, E = GEPOp->op_end(); I != E; ++I) { Value *Index = *I; // Compute the (potentially symbolic) offset in bytes for this index. - if (const StructType *STy = dyn_cast(*GTI++)) { + if (StructType *STy = dyn_cast(*GTI++)) { // For a struct, add the member offset. unsigned FieldNo = cast(Index)->getZExtValue(); if (FieldNo == 0) continue; @@ -374,7 +375,8 @@ DecomposeGEPExpression(const Value *V, int64_t &BaseOffs, } if (Scale) { - VariableGEPIndex Entry = {Index, Extension, Scale}; + VariableGEPIndex Entry = {Index, Extension, + static_cast(Scale)}; VarIndices.push_back(Entry); } } @@ -467,6 +469,7 @@ namespace { virtual void getAnalysisUsage(AnalysisUsage &AU) const { AU.addRequired(); + AU.addRequired(); } virtual AliasResult alias(const Location &LocA, @@ -549,10 +552,15 @@ namespace { // Register this pass... char BasicAliasAnalysis::ID = 0; -INITIALIZE_AG_PASS(BasicAliasAnalysis, AliasAnalysis, "basicaa", +INITIALIZE_AG_PASS_BEGIN(BasicAliasAnalysis, AliasAnalysis, "basicaa", + "Basic Alias Analysis (stateless AA impl)", + false, true, false) +INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfo) +INITIALIZE_AG_PASS_END(BasicAliasAnalysis, AliasAnalysis, "basicaa", "Basic Alias Analysis (stateless AA impl)", false, true, false) + ImmutablePass *llvm::createBasicAliasAnalysisPass() { return new BasicAliasAnalysis(); } @@ -706,7 +714,7 @@ BasicAliasAnalysis::getModRefInfo(ImmutableCallSite CS, // is impossible to alias the pointer we're checking. If not, we have to // assume that the call could touch the pointer, even though it doesn't // escape. - if (!isNoAlias(Location(cast(CI)), Loc)) { + if (!isNoAlias(Location(*CI), Location(Object))) { PassedAsArg = true; break; } @@ -716,6 +724,7 @@ BasicAliasAnalysis::getModRefInfo(ImmutableCallSite CS, return NoModRef; } + const TargetLibraryInfo &TLI = getAnalysis(); ModRefResult Min = ModRef; // Finally, handle specific knowledge of intrinsics. @@ -754,26 +763,6 @@ BasicAliasAnalysis::getModRefInfo(ImmutableCallSite CS, // We know that memset doesn't load anything. Min = Mod; break; - case Intrinsic::atomic_cmp_swap: - case Intrinsic::atomic_swap: - case Intrinsic::atomic_load_add: - case Intrinsic::atomic_load_sub: - case Intrinsic::atomic_load_and: - case Intrinsic::atomic_load_nand: - case Intrinsic::atomic_load_or: - case Intrinsic::atomic_load_xor: - case Intrinsic::atomic_load_max: - case Intrinsic::atomic_load_min: - case Intrinsic::atomic_load_umax: - case Intrinsic::atomic_load_umin: - if (TD) { - Value *Op1 = II->getArgOperand(0); - uint64_t Op1Size = TD->getTypeStoreSize(Op1->getType()); - MDNode *Tag = II->getMetadata(LLVMContext::MD_tbaa); - if (isNoAlias(Location(Op1, Op1Size, Tag), Loc)) - return NoModRef; - } - break; case Intrinsic::lifetime_start: case Intrinsic::lifetime_end: case Intrinsic::invariant_start: { @@ -818,6 +807,39 @@ BasicAliasAnalysis::getModRefInfo(ImmutableCallSite CS, } } + // We can bound the aliasing properties of memset_pattern16 just as we can + // for memcpy/memset. This is particularly important because the + // LoopIdiomRecognizer likes to turn loops into calls to memset_pattern16 + // whenever possible. + else if (TLI.has(LibFunc::memset_pattern16) && + CS.getCalledFunction() && + CS.getCalledFunction()->getName() == "memset_pattern16") { + const Function *MS = CS.getCalledFunction(); + FunctionType *MemsetType = MS->getFunctionType(); + if (!MemsetType->isVarArg() && MemsetType->getNumParams() == 3 && + isa(MemsetType->getParamType(0)) && + isa(MemsetType->getParamType(1)) && + isa(MemsetType->getParamType(2))) { + uint64_t Len = UnknownSize; + if (const ConstantInt *LenCI = dyn_cast(CS.getArgument(2))) + Len = LenCI->getZExtValue(); + const Value *Dest = CS.getArgument(0); + const Value *Src = CS.getArgument(1); + // If it can't overlap the source dest, then it doesn't modref the loc. + if (isNoAlias(Location(Dest, Len), Loc)) { + // Always reads 16 bytes of the source. + if (isNoAlias(Location(Src, 16), Loc)) + return NoModRef; + // If it can't overlap the dest, then worst case it reads the loc. + Min = Ref; + // Always reads 16 bytes of the source. + } else if (isNoAlias(Location(Src, 16), Loc)) { + // If it can't overlap the source, then worst case it mutates the loc. + Min = Mod; + } + } + } + // The AliasAnalysis base class has some smarts, lets use them. return ModRefResult(AliasAnalysis::getModRefInfo(CS, Loc) & Min); } @@ -913,43 +935,43 @@ BasicAliasAnalysis::aliasGEP(const GEPOperator *GEP1, uint64_t V1Size, if (GEP1BaseOffset == 0 && GEP1VariableIndices.empty()) return MustAlias; - // If there is a difference between the pointers, but the difference is - // less than the size of the associated memory object, then we know - // that the objects are partially overlapping. + // If there is a constant difference between the pointers, but the difference + // is less than the size of the associated memory object, then we know + // that the objects are partially overlapping. If the difference is + // greater, we know they do not overlap. if (GEP1BaseOffset != 0 && GEP1VariableIndices.empty()) { - if (GEP1BaseOffset >= 0 ? - (V2Size != UnknownSize && (uint64_t)GEP1BaseOffset < V2Size) : - (V1Size != UnknownSize && -(uint64_t)GEP1BaseOffset < V1Size && - GEP1BaseOffset != INT64_MIN)) - return PartialAlias; + if (GEP1BaseOffset >= 0) { + if (V2Size != UnknownSize) { + if ((uint64_t)GEP1BaseOffset < V2Size) + return PartialAlias; + return NoAlias; + } + } else { + if (V1Size != UnknownSize) { + if (-(uint64_t)GEP1BaseOffset < V1Size) + return PartialAlias; + return NoAlias; + } + } } - // If we have a known constant offset, see if this offset is larger than the - // access size being queried. If so, and if no variable indices can remove - // pieces of this constant, then we know we have a no-alias. For example, - // &A[100] != &A. - - // In order to handle cases like &A[100][i] where i is an out of range - // subscript, we have to ignore all constant offset pieces that are a multiple - // of a scaled index. Do this by removing constant offsets that are a - // multiple of any of our variable indices. This allows us to transform - // things like &A[i][1] because i has a stride of (e.g.) 8 bytes but the 1 - // provides an offset of 4 bytes (assuming a <= 4 byte access). - for (unsigned i = 0, e = GEP1VariableIndices.size(); - i != e && GEP1BaseOffset;++i) - if (int64_t RemovedOffset = GEP1BaseOffset/GEP1VariableIndices[i].Scale) - GEP1BaseOffset -= RemovedOffset*GEP1VariableIndices[i].Scale; - - // If our known offset is bigger than the access size, we know we don't have - // an alias. - if (GEP1BaseOffset) { - if (GEP1BaseOffset >= 0 ? - (V2Size != UnknownSize && (uint64_t)GEP1BaseOffset >= V2Size) : - (V1Size != UnknownSize && -(uint64_t)GEP1BaseOffset >= V1Size && - GEP1BaseOffset != INT64_MIN)) + // Try to distinguish something like &A[i][1] against &A[42][0]. + // Grab the least significant bit set in any of the scales. + if (!GEP1VariableIndices.empty()) { + uint64_t Modulo = 0; + for (unsigned i = 0, e = GEP1VariableIndices.size(); i != e; ++i) + Modulo |= (uint64_t)GEP1VariableIndices[i].Scale; + Modulo = Modulo ^ (Modulo & (Modulo - 1)); + + // We can compute the difference between the two addresses + // mod Modulo. Check whether that difference guarantees that the + // two locations do not alias. + uint64_t ModOffset = (uint64_t)GEP1BaseOffset & (Modulo - 1); + if (V1Size != UnknownSize && V2Size != UnknownSize && + ModOffset >= V2Size && V1Size <= Modulo - ModOffset) return NoAlias; } - + // Statically, we can see that the base objects are the same, but the // pointers have dynamic offsets which we can't resolve. And none of our // little tricks above worked. diff --git a/contrib/llvm/lib/Analysis/BlockFrequency.cpp b/contrib/llvm/lib/Analysis/BlockFrequency.cpp deleted file mode 100644 index 4b86d1db1..000000000 --- a/contrib/llvm/lib/Analysis/BlockFrequency.cpp +++ /dev/null @@ -1,59 +0,0 @@ -//=======-------- BlockFrequency.cpp - Block Frequency Analysis -------=======// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Loops should be simplified before this analysis. -// -//===----------------------------------------------------------------------===// - -#include "llvm/InitializePasses.h" -#include "llvm/Analysis/BlockFrequencyImpl.h" -#include "llvm/Analysis/BlockFrequency.h" -#include "llvm/Analysis/LoopInfo.h" -#include "llvm/Analysis/Passes.h" -#include "llvm/Analysis/BranchProbabilityInfo.h" - -using namespace llvm; - -INITIALIZE_PASS_BEGIN(BlockFrequency, "block-freq", "Block Frequency Analysis", - true, true) -INITIALIZE_PASS_DEPENDENCY(BranchProbabilityInfo) -INITIALIZE_PASS_END(BlockFrequency, "block-freq", "Block Frequency Analysis", - true, true) - -char BlockFrequency::ID = 0; - - -BlockFrequency::BlockFrequency() : FunctionPass(ID) { - initializeBlockFrequencyPass(*PassRegistry::getPassRegistry()); - BFI = new BlockFrequencyImpl(); -} - -BlockFrequency::~BlockFrequency() { - delete BFI; -} - -void BlockFrequency::getAnalysisUsage(AnalysisUsage &AU) const { - AU.addRequired(); - AU.setPreservesAll(); -} - -bool BlockFrequency::runOnFunction(Function &F) { - BranchProbabilityInfo &BPI = getAnalysis(); - BFI->doFunction(&F, &BPI); - return false; -} - -/// getblockFreq - Return block frequency. Never return 0, value must be -/// positive. 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. -/// -uint32_t BlockFrequency::getBlockFreq(BasicBlock *BB) { - return BFI->getBlockFreq(BB); -} diff --git a/contrib/llvm/lib/Analysis/BlockFrequencyInfo.cpp b/contrib/llvm/lib/Analysis/BlockFrequencyInfo.cpp new file mode 100644 index 000000000..d16665fa5 --- /dev/null +++ b/contrib/llvm/lib/Analysis/BlockFrequencyInfo.cpp @@ -0,0 +1,63 @@ +//=======-------- BlockFrequencyInfo.cpp - Block Frequency Analysis -------=======// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Loops should be simplified before this analysis. +// +//===----------------------------------------------------------------------===// + +#include "llvm/InitializePasses.h" +#include "llvm/Analysis/BlockFrequencyImpl.h" +#include "llvm/Analysis/BlockFrequencyInfo.h" +#include "llvm/Analysis/LoopInfo.h" +#include "llvm/Analysis/Passes.h" +#include "llvm/Analysis/BranchProbabilityInfo.h" + +using namespace llvm; + +INITIALIZE_PASS_BEGIN(BlockFrequencyInfo, "block-freq", "Block Frequency Analysis", + true, true) +INITIALIZE_PASS_DEPENDENCY(BranchProbabilityInfo) +INITIALIZE_PASS_END(BlockFrequencyInfo, "block-freq", "Block Frequency Analysis", + true, true) + +char BlockFrequencyInfo::ID = 0; + + +BlockFrequencyInfo::BlockFrequencyInfo() : FunctionPass(ID) { + initializeBlockFrequencyInfoPass(*PassRegistry::getPassRegistry()); + BFI = new BlockFrequencyImpl(); +} + +BlockFrequencyInfo::~BlockFrequencyInfo() { + delete BFI; +} + +void BlockFrequencyInfo::getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequired(); + AU.setPreservesAll(); +} + +bool BlockFrequencyInfo::runOnFunction(Function &F) { + BranchProbabilityInfo &BPI = getAnalysis(); + BFI->doFunction(&F, &BPI); + return false; +} + +void BlockFrequencyInfo::print(raw_ostream &O, const Module *) const { + if (BFI) BFI->print(O); +} + +/// 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. +/// +BlockFrequency BlockFrequencyInfo::getBlockFreq(BasicBlock *BB) const { + return BFI->getBlockFreq(BB); +} diff --git a/contrib/llvm/lib/Analysis/BranchProbabilityInfo.cpp b/contrib/llvm/lib/Analysis/BranchProbabilityInfo.cpp index e39cd221b..bde3b7670 100644 --- a/contrib/llvm/lib/Analysis/BranchProbabilityInfo.cpp +++ b/contrib/llvm/lib/Analysis/BranchProbabilityInfo.cpp @@ -11,7 +11,10 @@ // //===----------------------------------------------------------------------===// +#include "llvm/Constants.h" #include "llvm/Instructions.h" +#include "llvm/LLVMContext.h" +#include "llvm/Metadata.h" #include "llvm/Analysis/BranchProbabilityInfo.h" #include "llvm/Analysis/LoopInfo.h" #include "llvm/Support/Debug.h" @@ -33,7 +36,7 @@ namespace { // private methods are hidden in the .cpp file. class BranchProbabilityAnalysis { - typedef std::pair Edge; + typedef std::pair Edge; DenseMap *Weights; @@ -52,7 +55,7 @@ class BranchProbabilityAnalysis { // V // BB1<-+ // | | - // | | (Weight = 128) + // | | (Weight = 124) // V | // BB2--+ // | @@ -60,12 +63,21 @@ class BranchProbabilityAnalysis { // V // BB3 // - // Probability of the edge BB2->BB1 = 128 / (128 + 4) = 0.9696.. - // Probability of the edge BB2->BB3 = 4 / (128 + 4) = 0.0303.. + // Probability of the edge BB2->BB1 = 124 / (124 + 4) = 0.96875 + // Probability of the edge BB2->BB3 = 4 / (124 + 4) = 0.03125 - static const uint32_t LBH_TAKEN_WEIGHT = 128; + static const uint32_t LBH_TAKEN_WEIGHT = 124; static const uint32_t LBH_NONTAKEN_WEIGHT = 4; + static const uint32_t RH_TAKEN_WEIGHT = 24; + static const uint32_t RH_NONTAKEN_WEIGHT = 8; + + static const uint32_t PH_TAKEN_WEIGHT = 20; + static const uint32_t PH_NONTAKEN_WEIGHT = 12; + + static const uint32_t ZH_TAKEN_WEIGHT = 20; + static const uint32_t ZH_NONTAKEN_WEIGHT = 12; + // Standard weight value. Used when none of the heuristics set weight for // the edge. static const uint32_t NORMAL_WEIGHT = 16; @@ -100,29 +112,6 @@ class BranchProbabilityAnalysis { return false; } - // Multiply Edge Weight by two. - void incEdgeWeight(BasicBlock *Src, BasicBlock *Dst) { - uint32_t Weight = BP->getEdgeWeight(Src, Dst); - uint32_t MaxWeight = getMaxWeightFor(Src); - - if (Weight * 2 > MaxWeight) - BP->setEdgeWeight(Src, Dst, MaxWeight); - else - BP->setEdgeWeight(Src, Dst, Weight * 2); - } - - // Divide Edge Weight by two. - void decEdgeWeight(BasicBlock *Src, BasicBlock *Dst) { - uint32_t Weight = BP->getEdgeWeight(Src, Dst); - - assert(Weight > 0); - if (Weight / 2 < MIN_WEIGHT) - BP->setEdgeWeight(Src, Dst, MIN_WEIGHT); - else - BP->setEdgeWeight(Src, Dst, Weight / 2); - } - - uint32_t getMaxWeightFor(BasicBlock *BB) const { return UINT32_MAX / BB->getTerminator()->getNumSuccessors(); } @@ -133,49 +122,119 @@ public: : Weights(W), BP(BP), LI(LI) { } + // Metadata Weights + bool calcMetadataWeights(BasicBlock *BB); + // Return Heuristics - void calcReturnHeuristics(BasicBlock *BB); + bool calcReturnHeuristics(BasicBlock *BB); // Pointer Heuristics - void calcPointerHeuristics(BasicBlock *BB); + bool calcPointerHeuristics(BasicBlock *BB); // Loop Branch Heuristics - void calcLoopBranchHeuristics(BasicBlock *BB); + bool calcLoopBranchHeuristics(BasicBlock *BB); + + // Zero Heurestics + bool calcZeroHeuristics(BasicBlock *BB); bool runOnFunction(Function &F); }; } // end anonymous namespace +// Propagate existing explicit probabilities from either profile data or +// 'expect' intrinsic processing. +bool BranchProbabilityAnalysis::calcMetadataWeights(BasicBlock *BB) { + TerminatorInst *TI = BB->getTerminator(); + if (TI->getNumSuccessors() == 1) + return false; + if (!isa(TI) && !isa(TI)) + return false; + + MDNode *WeightsNode = TI->getMetadata(LLVMContext::MD_prof); + if (!WeightsNode) + return false; + + // Ensure there are weights for all of the successors. Note that the first + // operand to the metadata node is a name, not a weight. + if (WeightsNode->getNumOperands() != TI->getNumSuccessors() + 1) + return false; + + // Build up the final weights that will be used in a temporary buffer, but + // don't add them until all weihts are present. Each weight value is clamped + // to [1, getMaxWeightFor(BB)]. + uint32_t WeightLimit = getMaxWeightFor(BB); + SmallVector Weights; + Weights.reserve(TI->getNumSuccessors()); + for (unsigned i = 1, e = WeightsNode->getNumOperands(); i != e; ++i) { + ConstantInt *Weight = dyn_cast(WeightsNode->getOperand(i)); + if (!Weight) + return false; + Weights.push_back( + std::max(1, Weight->getLimitedValue(WeightLimit))); + } + assert(Weights.size() == TI->getNumSuccessors() && "Checked above"); + for (unsigned i = 0, e = TI->getNumSuccessors(); i != e; ++i) + BP->setEdgeWeight(BB, TI->getSuccessor(i), Weights[i]); + + return true; +} + // Calculate Edge Weights using "Return Heuristics". Predict a successor which // leads directly to Return Instruction will not be taken. -void BranchProbabilityAnalysis::calcReturnHeuristics(BasicBlock *BB){ +bool BranchProbabilityAnalysis::calcReturnHeuristics(BasicBlock *BB){ if (BB->getTerminator()->getNumSuccessors() == 1) - return; + return false; + + SmallPtrSet ReturningEdges; + SmallPtrSet StayEdges; for (succ_iterator I = succ_begin(BB), E = succ_end(BB); I != E; ++I) { BasicBlock *Succ = *I; - if (isReturningBlock(Succ)) { - decEdgeWeight(BB, Succ); + if (isReturningBlock(Succ)) + ReturningEdges.insert(Succ); + else + StayEdges.insert(Succ); + } + + if (uint32_t numStayEdges = StayEdges.size()) { + uint32_t stayWeight = RH_TAKEN_WEIGHT / numStayEdges; + if (stayWeight < NORMAL_WEIGHT) + stayWeight = NORMAL_WEIGHT; + + for (SmallPtrSet::iterator I = StayEdges.begin(), + E = StayEdges.end(); I != E; ++I) + BP->setEdgeWeight(BB, *I, stayWeight); + } + + if (uint32_t numRetEdges = ReturningEdges.size()) { + uint32_t retWeight = RH_NONTAKEN_WEIGHT / numRetEdges; + if (retWeight < MIN_WEIGHT) + retWeight = MIN_WEIGHT; + for (SmallPtrSet::iterator I = ReturningEdges.begin(), + E = ReturningEdges.end(); I != E; ++I) { + BP->setEdgeWeight(BB, *I, retWeight); } } + + return ReturningEdges.size() > 0; } // Calculate Edge Weights using "Pointer Heuristics". Predict a comparsion // between two pointer or pointer and NULL will fail. -void BranchProbabilityAnalysis::calcPointerHeuristics(BasicBlock *BB) { +bool BranchProbabilityAnalysis::calcPointerHeuristics(BasicBlock *BB) { BranchInst * BI = dyn_cast(BB->getTerminator()); if (!BI || !BI->isConditional()) - return; + return false; Value *Cond = BI->getCondition(); ICmpInst *CI = dyn_cast(Cond); if (!CI || !CI->isEquality()) - return; + return false; Value *LHS = CI->getOperand(0); if (!LHS->getType()->isPointerTy()) - return; + return false; assert(CI->getOperand(1)->getType()->isPointerTy()); @@ -190,29 +249,35 @@ void BranchProbabilityAnalysis::calcPointerHeuristics(BasicBlock *BB) { if (!isProb) std::swap(Taken, NonTaken); - incEdgeWeight(BB, Taken); - decEdgeWeight(BB, NonTaken); + BP->setEdgeWeight(BB, Taken, PH_TAKEN_WEIGHT); + BP->setEdgeWeight(BB, NonTaken, PH_NONTAKEN_WEIGHT); + return true; } // Calculate Edge Weights using "Loop Branch Heuristics". Predict backedges // as taken, exiting edges as not-taken. -void BranchProbabilityAnalysis::calcLoopBranchHeuristics(BasicBlock *BB) { +bool BranchProbabilityAnalysis::calcLoopBranchHeuristics(BasicBlock *BB) { uint32_t numSuccs = BB->getTerminator()->getNumSuccessors(); Loop *L = LI->getLoopFor(BB); if (!L) - return; + return false; + + SmallPtrSet BackEdges; + SmallPtrSet ExitingEdges; + SmallPtrSet InEdges; // Edges from header to the loop. - SmallVector BackEdges; - SmallVector ExitingEdges; + bool isHeader = BB == L->getHeader(); for (succ_iterator I = succ_begin(BB), E = succ_end(BB); I != E; ++I) { BasicBlock *Succ = *I; Loop *SuccL = LI->getLoopFor(Succ); if (SuccL != L) - ExitingEdges.push_back(Succ); + ExitingEdges.insert(Succ); else if (Succ == L->getHeader()) - BackEdges.push_back(Succ); + BackEdges.insert(Succ); + else if (isHeader) + InEdges.insert(Succ); } if (uint32_t numBackEdges = BackEdges.size()) { @@ -220,39 +285,121 @@ void BranchProbabilityAnalysis::calcLoopBranchHeuristics(BasicBlock *BB) { if (backWeight < NORMAL_WEIGHT) backWeight = NORMAL_WEIGHT; - for (SmallVector::iterator EI = BackEdges.begin(), + for (SmallPtrSet::iterator EI = BackEdges.begin(), EE = BackEdges.end(); EI != EE; ++EI) { BasicBlock *Back = *EI; BP->setEdgeWeight(BB, Back, backWeight); } } + if (uint32_t numInEdges = InEdges.size()) { + uint32_t inWeight = LBH_TAKEN_WEIGHT / numInEdges; + if (inWeight < NORMAL_WEIGHT) + inWeight = NORMAL_WEIGHT; + + for (SmallPtrSet::iterator EI = InEdges.begin(), + EE = InEdges.end(); EI != EE; ++EI) { + BasicBlock *Back = *EI; + BP->setEdgeWeight(BB, Back, inWeight); + } + } + uint32_t numExitingEdges = ExitingEdges.size(); if (uint32_t numNonExitingEdges = numSuccs - numExitingEdges) { uint32_t exitWeight = LBH_NONTAKEN_WEIGHT / numNonExitingEdges; if (exitWeight < MIN_WEIGHT) exitWeight = MIN_WEIGHT; - for (SmallVector::iterator EI = ExitingEdges.begin(), + for (SmallPtrSet::iterator EI = ExitingEdges.begin(), EE = ExitingEdges.end(); EI != EE; ++EI) { BasicBlock *Exiting = *EI; BP->setEdgeWeight(BB, Exiting, exitWeight); } } + + return true; } +bool BranchProbabilityAnalysis::calcZeroHeuristics(BasicBlock *BB) { + BranchInst * BI = dyn_cast(BB->getTerminator()); + if (!BI || !BI->isConditional()) + return false; + + Value *Cond = BI->getCondition(); + ICmpInst *CI = dyn_cast(Cond); + if (!CI) + return false; + + Value *RHS = CI->getOperand(1); + ConstantInt *CV = dyn_cast(RHS); + if (!CV) + return false; + + bool isProb; + if (CV->isZero()) { + switch (CI->getPredicate()) { + case CmpInst::ICMP_EQ: + // X == 0 -> Unlikely + isProb = false; + break; + case CmpInst::ICMP_NE: + // X != 0 -> Likely + isProb = true; + break; + case CmpInst::ICMP_SLT: + // X < 0 -> Unlikely + isProb = false; + break; + case CmpInst::ICMP_SGT: + // X > 0 -> Likely + isProb = true; + break; + default: + return false; + } + } else if (CV->isOne() && CI->getPredicate() == CmpInst::ICMP_SLT) { + // InstCombine canonicalizes X <= 0 into X < 1. + // X <= 0 -> Unlikely + isProb = false; + } else if (CV->isAllOnesValue() && CI->getPredicate() == CmpInst::ICMP_SGT) { + // InstCombine canonicalizes X >= 0 into X > -1. + // X >= 0 -> Likely + isProb = true; + } else { + return false; + } + + BasicBlock *Taken = BI->getSuccessor(0); + BasicBlock *NonTaken = BI->getSuccessor(1); + + if (!isProb) + std::swap(Taken, NonTaken); + + BP->setEdgeWeight(BB, Taken, ZH_TAKEN_WEIGHT); + BP->setEdgeWeight(BB, NonTaken, ZH_NONTAKEN_WEIGHT); + + return true; +} + + bool BranchProbabilityAnalysis::runOnFunction(Function &F) { for (Function::iterator I = F.begin(), E = F.end(); I != E; ) { BasicBlock *BB = I++; - // Only LBH uses setEdgeWeight method. - calcLoopBranchHeuristics(BB); + if (calcMetadataWeights(BB)) + continue; + + if (calcLoopBranchHeuristics(BB)) + continue; - // PH and RH use only incEdgeWeight and decEwdgeWeight methods to - // not efface LBH results. - calcPointerHeuristics(BB); - calcReturnHeuristics(BB); + if (calcReturnHeuristics(BB)) + continue; + + if (calcPointerHeuristics(BB)) + continue; + + calcZeroHeuristics(BB); } return false; @@ -269,11 +416,11 @@ bool BranchProbabilityInfo::runOnFunction(Function &F) { return BPA.runOnFunction(F); } -uint32_t BranchProbabilityInfo::getSumForBlock(BasicBlock *BB) const { +uint32_t BranchProbabilityInfo::getSumForBlock(const BasicBlock *BB) const { uint32_t Sum = 0; - for (succ_iterator I = succ_begin(BB), E = succ_end(BB); I != E; ++I) { - BasicBlock *Succ = *I; + for (succ_const_iterator I = succ_begin(BB), E = succ_end(BB); I != E; ++I) { + const BasicBlock *Succ = *I; uint32_t Weight = getEdgeWeight(BB, Succ); uint32_t PrevSum = Sum; @@ -284,7 +431,8 @@ uint32_t BranchProbabilityInfo::getSumForBlock(BasicBlock *BB) const { return Sum; } -bool BranchProbabilityInfo::isEdgeHot(BasicBlock *Src, BasicBlock *Dst) const { +bool BranchProbabilityInfo:: +isEdgeHot(const BasicBlock *Src, const BasicBlock *Dst) const { // Hot probability is at least 4/5 = 80% uint32_t Weight = getEdgeWeight(Src, Dst); uint32_t Sum = getSumForBlock(Src); @@ -321,8 +469,8 @@ BasicBlock *BranchProbabilityInfo::getHotSucc(BasicBlock *BB) const { } // Return edge's weight. If can't find it, return DEFAULT_WEIGHT value. -uint32_t -BranchProbabilityInfo::getEdgeWeight(BasicBlock *Src, BasicBlock *Dst) const { +uint32_t BranchProbabilityInfo:: +getEdgeWeight(const BasicBlock *Src, const BasicBlock *Dst) const { Edge E(Src, Dst); DenseMap::const_iterator I = Weights.find(E); @@ -332,8 +480,8 @@ BranchProbabilityInfo::getEdgeWeight(BasicBlock *Src, BasicBlock *Dst) const { return DEFAULT_WEIGHT; } -void BranchProbabilityInfo::setEdgeWeight(BasicBlock *Src, BasicBlock *Dst, - uint32_t Weight) { +void BranchProbabilityInfo:: +setEdgeWeight(const BasicBlock *Src, const BasicBlock *Dst, uint32_t Weight) { Weights[std::make_pair(Src, Dst)] = Weight; DEBUG(dbgs() << "set edge " << Src->getNameStr() << " -> " << Dst->getNameStr() << " weight to " << Weight @@ -342,7 +490,7 @@ void BranchProbabilityInfo::setEdgeWeight(BasicBlock *Src, BasicBlock *Dst, BranchProbability BranchProbabilityInfo:: -getEdgeProbability(BasicBlock *Src, BasicBlock *Dst) const { +getEdgeProbability(const BasicBlock *Src, const BasicBlock *Dst) const { uint32_t N = getEdgeWeight(Src, Dst); uint32_t D = getSumForBlock(Src); diff --git a/contrib/llvm/lib/Analysis/ConstantFolding.cpp b/contrib/llvm/lib/Analysis/ConstantFolding.cpp index 7fca17eb6..df79849c3 100644 --- a/contrib/llvm/lib/Analysis/ConstantFolding.cpp +++ b/contrib/llvm/lib/Analysis/ConstantFolding.cpp @@ -43,11 +43,16 @@ using namespace llvm; /// FoldBitCast - Constant fold bitcast, symbolically evaluating it with /// TargetData. This always returns a non-null constant, but it may be a /// ConstantExpr if unfoldable. -static Constant *FoldBitCast(Constant *C, const Type *DestTy, +static Constant *FoldBitCast(Constant *C, Type *DestTy, const TargetData &TD) { - - // This only handles casts to vectors currently. - const VectorType *DestVTy = dyn_cast(DestTy); + // Catch the obvious splat cases. + if (C->isNullValue() && !DestTy->isX86_MMXTy()) + return Constant::getNullValue(DestTy); + if (C->isAllOnesValue() && !DestTy->isX86_MMXTy()) + return Constant::getAllOnesValue(DestTy); + + // The code below only handles casts to vectors currently. + VectorType *DestVTy = dyn_cast(DestTy); if (DestVTy == 0) return ConstantExpr::getBitCast(C, DestTy); @@ -69,8 +74,8 @@ static Constant *FoldBitCast(Constant *C, const Type *DestTy, if (NumDstElt == NumSrcElt) return ConstantExpr::getBitCast(C, DestTy); - const Type *SrcEltTy = CV->getType()->getElementType(); - const Type *DstEltTy = DestVTy->getElementType(); + Type *SrcEltTy = CV->getType()->getElementType(); + Type *DstEltTy = DestVTy->getElementType(); // Otherwise, we're changing the number of elements in a vector, which // requires endianness information to do the right thing. For example, @@ -85,7 +90,7 @@ static Constant *FoldBitCast(Constant *C, const Type *DestTy, if (DstEltTy->isFloatingPointTy()) { // Fold to an vector of integers with same size as our FP type. unsigned FPWidth = DstEltTy->getPrimitiveSizeInBits(); - const Type *DestIVTy = + Type *DestIVTy = VectorType::get(IntegerType::get(C->getContext(), FPWidth), NumDstElt); // Recursively handle this integer conversion, if possible. C = FoldBitCast(C, DestIVTy, TD); @@ -99,7 +104,7 @@ static Constant *FoldBitCast(Constant *C, const Type *DestTy, // it to integer first. if (SrcEltTy->isFloatingPointTy()) { unsigned FPWidth = SrcEltTy->getPrimitiveSizeInBits(); - const Type *SrcIVTy = + Type *SrcIVTy = VectorType::get(IntegerType::get(C->getContext(), FPWidth), NumSrcElt); // Ask VMCore to do the conversion now that #elts line up. C = ConstantExpr::getBitCast(C, SrcIVTy); @@ -212,11 +217,11 @@ static bool IsConstantOffsetFromGlobal(Constant *C, GlobalValue *&GV, if (!CI) return false; // Index isn't a simple constant? if (CI->isZero()) continue; // Not adding anything. - if (const StructType *ST = dyn_cast(*GTI)) { + if (StructType *ST = dyn_cast(*GTI)) { // N = N + Offset Offset += TD.getStructLayout(ST)->getElementOffset(CI->getZExtValue()); } else { - const SequentialType *SQT = cast(*GTI); + SequentialType *SQT = cast(*GTI); Offset += TD.getTypeAllocSize(SQT->getElementType())*CI->getSExtValue(); } } @@ -354,8 +359,8 @@ static bool ReadDataFromGlobal(Constant *C, uint64_t ByteOffset, static Constant *FoldReinterpretLoadFromConstPtr(Constant *C, const TargetData &TD) { - const Type *LoadTy = cast(C->getType())->getElementType(); - const IntegerType *IntType = dyn_cast(LoadTy); + Type *LoadTy = cast(C->getType())->getElementType(); + IntegerType *IntType = dyn_cast(LoadTy); // If this isn't an integer load we can't fold it directly. if (!IntType) { @@ -363,7 +368,7 @@ static Constant *FoldReinterpretLoadFromConstPtr(Constant *C, // and then bitcast the result. This can be useful for union cases. Note // that address spaces don't matter here since we're not going to result in // an actual new load. - const Type *MapTy; + Type *MapTy; if (LoadTy->isFloatTy()) MapTy = Type::getInt32PtrTy(C->getContext()); else if (LoadTy->isDoubleTy()) @@ -443,7 +448,7 @@ Constant *llvm::ConstantFoldLoadFromConstPtr(Constant *C, std::string Str; if (TD && GetConstantStringInfo(CE, Str) && !Str.empty()) { unsigned StrLen = Str.length(); - const Type *Ty = cast(CE->getType())->getElementType(); + Type *Ty = cast(CE->getType())->getElementType(); unsigned NumBits = Ty->getPrimitiveSizeInBits(); // Replace load with immediate integer if the result is an integer or fp // value. @@ -478,7 +483,7 @@ Constant *llvm::ConstantFoldLoadFromConstPtr(Constant *C, if (GlobalVariable *GV = dyn_cast(GetUnderlyingObject(CE, TD))) { if (GV->isConstant() && GV->hasDefinitiveInitializer()) { - const Type *ResTy = cast(C->getType())->getElementType(); + Type *ResTy = cast(C->getType())->getElementType(); if (GV->getInitializer()->isNullValue()) return Constant::getNullValue(ResTy); if (isa(GV->getInitializer())) @@ -536,19 +541,18 @@ static Constant *SymbolicallyEvaluateBinop(unsigned Opc, Constant *Op0, /// CastGEPIndices - If array indices are not pointer-sized integers, /// explicitly cast them so that they aren't implicitly casted by the /// getelementptr. -static Constant *CastGEPIndices(Constant *const *Ops, unsigned NumOps, - const Type *ResultTy, +static Constant *CastGEPIndices(ArrayRef Ops, + Type *ResultTy, const TargetData *TD) { if (!TD) return 0; - const Type *IntPtrTy = TD->getIntPtrType(ResultTy->getContext()); + Type *IntPtrTy = TD->getIntPtrType(ResultTy->getContext()); bool Any = false; SmallVector NewIdxs; - for (unsigned i = 1; i != NumOps; ++i) { + for (unsigned i = 1, e = Ops.size(); i != e; ++i) { if ((i == 1 || !isa(GetElementPtrInst::getIndexedType(Ops[0]->getType(), - reinterpret_cast(Ops+1), - i-1))) && + Ops.slice(1, i-1)))) && Ops[i]->getType() != IntPtrTy) { Any = true; NewIdxs.push_back(ConstantExpr::getCast(CastInst::getCastOpcode(Ops[i], @@ -562,7 +566,7 @@ static Constant *CastGEPIndices(Constant *const *Ops, unsigned NumOps, if (!Any) return 0; Constant *C = - ConstantExpr::getGetElementPtr(Ops[0], &NewIdxs[0], NewIdxs.size()); + ConstantExpr::getGetElementPtr(Ops[0], NewIdxs); if (ConstantExpr *CE = dyn_cast(C)) if (Constant *Folded = ConstantFoldConstantExpression(CE, TD)) C = Folded; @@ -571,23 +575,23 @@ static Constant *CastGEPIndices(Constant *const *Ops, unsigned NumOps, /// SymbolicallyEvaluateGEP - If we can symbolically evaluate the specified GEP /// constant expression, do so. -static Constant *SymbolicallyEvaluateGEP(Constant *const *Ops, unsigned NumOps, - const Type *ResultTy, +static Constant *SymbolicallyEvaluateGEP(ArrayRef Ops, + Type *ResultTy, const TargetData *TD) { Constant *Ptr = Ops[0]; if (!TD || !cast(Ptr->getType())->getElementType()->isSized()) return 0; - const Type *IntPtrTy = TD->getIntPtrType(Ptr->getContext()); + Type *IntPtrTy = TD->getIntPtrType(Ptr->getContext()); // If this is a constant expr gep that is effectively computing an // "offsetof", fold it into 'cast int Size to T*' instead of 'gep 0, 0, 12' - for (unsigned i = 1; i != NumOps; ++i) + for (unsigned i = 1, e = Ops.size(); i != e; ++i) if (!isa(Ops[i])) { // If this is "gep i8* Ptr, (sub 0, V)", fold this as: // "inttoptr (sub (ptrtoint Ptr), V)" - if (NumOps == 2 && + if (Ops.size() == 2 && cast(ResultTy)->getElementType()->isIntegerTy(8)) { ConstantExpr *CE = dyn_cast(Ops[1]); assert((CE == 0 || CE->getType() == IntPtrTy) && @@ -606,9 +610,10 @@ static Constant *SymbolicallyEvaluateGEP(Constant *const *Ops, unsigned NumOps, } unsigned BitWidth = TD->getTypeSizeInBits(IntPtrTy); - APInt Offset = APInt(BitWidth, - TD->getIndexedOffset(Ptr->getType(), - (Value**)Ops+1, NumOps-1)); + APInt Offset = + APInt(BitWidth, TD->getIndexedOffset(Ptr->getType(), + makeArrayRef((Value **)Ops.data() + 1, + Ops.size() - 1))); Ptr = cast(Ptr->stripPointerCasts()); // If this is a GEP of a GEP, fold it all into a single GEP. @@ -627,9 +632,7 @@ static Constant *SymbolicallyEvaluateGEP(Constant *const *Ops, unsigned NumOps, Ptr = cast(GEP->getOperand(0)); Offset += APInt(BitWidth, - TD->getIndexedOffset(Ptr->getType(), - (Value**)NestedOps.data(), - NestedOps.size())); + TD->getIndexedOffset(Ptr->getType(), NestedOps)); Ptr = cast(Ptr->stripPointerCasts()); } @@ -649,10 +652,10 @@ static Constant *SymbolicallyEvaluateGEP(Constant *const *Ops, unsigned NumOps, // we eliminate over-indexing of the notional static type array bounds. // This makes it easy to determine if the getelementptr is "inbounds". // Also, this helps GlobalOpt do SROA on GlobalVariables. - const Type *Ty = Ptr->getType(); + Type *Ty = Ptr->getType(); SmallVector NewIdxs; do { - if (const SequentialType *ATy = dyn_cast(Ty)) { + if (SequentialType *ATy = dyn_cast(Ty)) { if (ATy->isPointerTy()) { // The only pointer indexing we'll do is on the first index of the GEP. if (!NewIdxs.empty()) @@ -665,7 +668,7 @@ static Constant *SymbolicallyEvaluateGEP(Constant *const *Ops, unsigned NumOps, // Determine which element of the array the offset points into. APInt ElemSize(BitWidth, TD->getTypeAllocSize(ATy->getElementType())); - const IntegerType *IntPtrTy = TD->getIntPtrType(Ty->getContext()); + IntegerType *IntPtrTy = TD->getIntPtrType(Ty->getContext()); if (ElemSize == 0) // The element size is 0. This may be [0 x Ty]*, so just use a zero // index for this level and proceed to the next level to see if it can @@ -679,7 +682,7 @@ static Constant *SymbolicallyEvaluateGEP(Constant *const *Ops, unsigned NumOps, NewIdxs.push_back(ConstantInt::get(IntPtrTy, NewIdx)); } Ty = ATy->getElementType(); - } else if (const StructType *STy = dyn_cast(Ty)) { + } else if (StructType *STy = dyn_cast(Ty)) { // Determine which field of the struct the offset points into. The // getZExtValue is at least as safe as the StructLayout API because we // know the offset is within the struct at this point. @@ -703,7 +706,7 @@ static Constant *SymbolicallyEvaluateGEP(Constant *const *Ops, unsigned NumOps, // Create a GEP. Constant *C = - ConstantExpr::getGetElementPtr(Ptr, &NewIdxs[0], NewIdxs.size()); + ConstantExpr::getGetElementPtr(Ptr, NewIdxs); assert(cast(C->getType())->getElementType() == Ty && "Computed GetElementPtr has unexpected type!"); @@ -778,8 +781,7 @@ Constant *llvm::ConstantFoldInstruction(Instruction *I, const TargetData *TD) { cast(EVI->getAggregateOperand()), EVI->getIndices()); - return ConstantFoldInstOperands(I->getOpcode(), I->getType(), - Ops.data(), Ops.size(), TD); + return ConstantFoldInstOperands(I->getOpcode(), I->getType(), Ops, TD); } /// ConstantFoldConstantExpression - Attempt to fold the constant expression @@ -800,8 +802,7 @@ Constant *llvm::ConstantFoldConstantExpression(const ConstantExpr *CE, if (CE->isCompare()) return ConstantFoldCompareInstOperands(CE->getPredicate(), Ops[0], Ops[1], TD); - return ConstantFoldInstOperands(CE->getOpcode(), CE->getType(), - Ops.data(), Ops.size(), TD); + return ConstantFoldInstOperands(CE->getOpcode(), CE->getType(), Ops, TD); } /// ConstantFoldInstOperands - Attempt to constant fold an instruction with the @@ -814,8 +815,8 @@ Constant *llvm::ConstantFoldConstantExpression(const ConstantExpr *CE, /// information, due to only being passed an opcode and operands. Constant /// folding using this function strips this information. /// -Constant *llvm::ConstantFoldInstOperands(unsigned Opcode, const Type *DestTy, - Constant* const* Ops, unsigned NumOps, +Constant *llvm::ConstantFoldInstOperands(unsigned Opcode, Type *DestTy, + ArrayRef Ops, const TargetData *TD) { // Handle easy binops first. if (Instruction::isBinaryOp(Opcode)) { @@ -831,9 +832,9 @@ Constant *llvm::ConstantFoldInstOperands(unsigned Opcode, const Type *DestTy, case Instruction::ICmp: case Instruction::FCmp: assert(0 && "Invalid for compares"); case Instruction::Call: - if (Function *F = dyn_cast(Ops[NumOps - 1])) + if (Function *F = dyn_cast(Ops.back())) if (canConstantFoldCallTo(F)) - return ConstantFoldCall(F, Ops, NumOps - 1); + return ConstantFoldCall(F, Ops.slice(0, Ops.size() - 1)); return 0; case Instruction::PtrToInt: // If the input is a inttoptr, eliminate the pair. This requires knowing @@ -887,12 +888,12 @@ Constant *llvm::ConstantFoldInstOperands(unsigned Opcode, const Type *DestTy, case Instruction::ShuffleVector: return ConstantExpr::getShuffleVector(Ops[0], Ops[1], Ops[2]); case Instruction::GetElementPtr: - if (Constant *C = CastGEPIndices(Ops, NumOps, DestTy, TD)) + if (Constant *C = CastGEPIndices(Ops, DestTy, TD)) return C; - if (Constant *C = SymbolicallyEvaluateGEP(Ops, NumOps, DestTy, TD)) + if (Constant *C = SymbolicallyEvaluateGEP(Ops, DestTy, TD)) return C; - return ConstantExpr::getGetElementPtr(Ops[0], Ops+1, NumOps-1); + return ConstantExpr::getGetElementPtr(Ops[0], Ops.slice(1)); } } @@ -912,7 +913,7 @@ Constant *llvm::ConstantFoldCompareInstOperands(unsigned Predicate, // around to know if bit truncation is happening. if (ConstantExpr *CE0 = dyn_cast(Ops0)) { if (TD && Ops1->isNullValue()) { - const Type *IntPtrTy = TD->getIntPtrType(CE0->getContext()); + Type *IntPtrTy = TD->getIntPtrType(CE0->getContext()); if (CE0->getOpcode() == Instruction::IntToPtr) { // Convert the integer value to the right size to ensure we get the // proper extension or truncation. @@ -934,7 +935,7 @@ Constant *llvm::ConstantFoldCompareInstOperands(unsigned Predicate, if (ConstantExpr *CE1 = dyn_cast(Ops1)) { if (TD && CE0->getOpcode() == CE1->getOpcode()) { - const Type *IntPtrTy = TD->getIntPtrType(CE0->getContext()); + Type *IntPtrTy = TD->getIntPtrType(CE0->getContext()); if (CE0->getOpcode() == Instruction::IntToPtr) { // Convert the integer value to the right size to ensure we get the @@ -967,7 +968,7 @@ Constant *llvm::ConstantFoldCompareInstOperands(unsigned Predicate, unsigned OpC = Predicate == ICmpInst::ICMP_EQ ? Instruction::And : Instruction::Or; Constant *Ops[] = { LHS, RHS }; - return ConstantFoldInstOperands(OpC, LHS->getType(), Ops, 2, TD); + return ConstantFoldInstOperands(OpC, LHS->getType(), Ops, TD); } } @@ -987,7 +988,7 @@ Constant *llvm::ConstantFoldLoadThroughGEPConstantExpr(Constant *C, // addressing... gep_type_iterator I = gep_type_begin(CE), E = gep_type_end(CE); for (++I; I != E; ++I) - if (const StructType *STy = dyn_cast(*I)) { + if (StructType *STy = dyn_cast(*I)) { ConstantInt *CU = cast(I.getOperand()); assert(CU->getZExtValue() < STy->getNumElements() && "Struct index out of range!"); @@ -1002,7 +1003,7 @@ Constant *llvm::ConstantFoldLoadThroughGEPConstantExpr(Constant *C, return 0; } } else if (ConstantInt *CI = dyn_cast(I.getOperand())) { - if (const ArrayType *ATy = dyn_cast(*I)) { + if (ArrayType *ATy = dyn_cast(*I)) { if (CI->getZExtValue() >= ATy->getNumElements()) return 0; if (ConstantArray *CA = dyn_cast(C)) @@ -1013,7 +1014,7 @@ Constant *llvm::ConstantFoldLoadThroughGEPConstantExpr(Constant *C, C = UndefValue::get(ATy->getElementType()); else return 0; - } else if (const VectorType *VTy = dyn_cast(*I)) { + } else if (VectorType *VTy = dyn_cast(*I)) { if (CI->getZExtValue() >= VTy->getNumElements()) return 0; if (ConstantVector *CP = dyn_cast(C)) @@ -1101,7 +1102,7 @@ llvm::canConstantFoldCallTo(const Function *F) { } static Constant *ConstantFoldFP(double (*NativeFP)(double), double V, - const Type *Ty) { + Type *Ty) { sys::llvm_fenv_clearexcept(); V = NativeFP(V); if (sys::llvm_fenv_testexcept()) { @@ -1118,7 +1119,7 @@ static Constant *ConstantFoldFP(double (*NativeFP)(double), double V, } static Constant *ConstantFoldBinaryFP(double (*NativeFP)(double, double), - double V, double W, const Type *Ty) { + double V, double W, Type *Ty) { sys::llvm_fenv_clearexcept(); V = NativeFP(V, W); if (sys::llvm_fenv_testexcept()) { @@ -1143,7 +1144,7 @@ static Constant *ConstantFoldBinaryFP(double (*NativeFP)(double, double), /// performed, otherwise returns the Constant value resulting from the /// conversion. static Constant *ConstantFoldConvertToInt(ConstantFP *Op, bool roundTowardZero, - const Type *Ty) { + Type *Ty) { assert(Op && "Called with NULL operand"); APFloat Val(Op->getValueAPF()); @@ -1167,13 +1168,12 @@ static Constant *ConstantFoldConvertToInt(ConstantFP *Op, bool roundTowardZero, /// ConstantFoldCall - Attempt to constant fold a call to the specified function /// with the specified arguments, returning null if unsuccessful. Constant * -llvm::ConstantFoldCall(Function *F, - Constant *const *Operands, unsigned NumOperands) { +llvm::ConstantFoldCall(Function *F, ArrayRef Operands) { if (!F->hasName()) return 0; StringRef Name = F->getName(); - const Type *Ty = F->getReturnType(); - if (NumOperands == 1) { + Type *Ty = F->getReturnType(); + if (Operands.size() == 1) { if (ConstantFP *Op = dyn_cast(Operands[0])) { if (F->getIntrinsicID() == Intrinsic::convert_to_fp16) { APFloat Val(Op->getValueAPF()); @@ -1327,7 +1327,7 @@ llvm::ConstantFoldCall(Function *F, return 0; } - if (NumOperands == 2) { + if (Operands.size() == 2) { if (ConstantFP *Op1 = dyn_cast(Operands[0])) { if (!Ty->isFloatTy() && !Ty->isDoubleTy()) return 0; diff --git a/contrib/llvm/lib/Analysis/DIBuilder.cpp b/contrib/llvm/lib/Analysis/DIBuilder.cpp index ac5eeeb47..bfa429d54 100644 --- a/contrib/llvm/lib/Analysis/DIBuilder.cpp +++ b/contrib/llvm/lib/Analysis/DIBuilder.cpp @@ -29,14 +29,74 @@ static Constant *GetTagConstant(LLVMContext &VMContext, unsigned Tag) { } DIBuilder::DIBuilder(Module &m) - : M(m), VMContext(M.getContext()), TheCU(0), DeclareFn(0), ValueFn(0) {} + : M(m), VMContext(M.getContext()), TheCU(0), TempEnumTypes(0), + TempRetainTypes(0), TempSubprograms(0), TempGVs(0), DeclareFn(0), + ValueFn(0) +{} + +/// finalize - Construct any deferred debug info descriptors. +void DIBuilder::finalize() { + DIArray Enums = getOrCreateArray(AllEnumTypes); + DIType(TempEnumTypes).replaceAllUsesWith(Enums); + + DIArray RetainTypes = getOrCreateArray(AllRetainTypes); + DIType(TempRetainTypes).replaceAllUsesWith(RetainTypes); + + DIArray SPs = getOrCreateArray(AllSubprograms); + DIType(TempSubprograms).replaceAllUsesWith(SPs); + for (unsigned i = 0, e = SPs.getNumElements(); i != e; ++i) { + DISubprogram SP(SPs.getElement(i)); + if (NamedMDNode *NMD = getFnSpecificMDNode(M, SP)) { + SmallVector Variables; + for (unsigned ii = 0, ee = NMD->getNumOperands(); ii != ee; ++ii) + Variables.push_back(NMD->getOperand(ii)); + if (MDNode *Temp = SP.getVariablesNodes()) { + DIArray AV = getOrCreateArray(Variables); + DIType(Temp).replaceAllUsesWith(AV); + } + NMD->eraseFromParent(); + } + } + + DIArray GVs = getOrCreateArray(AllGVs); + DIType(TempGVs).replaceAllUsesWith(GVs); +} + +/// getNonCompileUnitScope - If N is compile unit return NULL otherwise return +/// N. +static MDNode *getNonCompileUnitScope(MDNode *N) { + if (DIDescriptor(N).isCompileUnit()) + return NULL; + return N; +} /// createCompileUnit - A CompileUnit provides an anchor for all debugging /// information generated during this instance of compilation. -void DIBuilder::createCompileUnit(unsigned Lang, StringRef Filename, - StringRef Directory, StringRef Producer, - bool isOptimized, StringRef Flags, +void DIBuilder::createCompileUnit(unsigned Lang, StringRef Filename, + StringRef Directory, StringRef Producer, + bool isOptimized, StringRef Flags, unsigned RunTimeVer) { + assert (Lang <= dwarf::DW_LANG_D && Lang >= dwarf::DW_LANG_C89 + && "Invalid Language tag"); + assert (!Filename.empty() + && "Unable to create compile unit without filename"); + Value *TElts[] = { GetTagConstant(VMContext, DW_TAG_base_type) }; + TempEnumTypes = MDNode::getTemporary(VMContext, TElts); + Value *THElts[] = { TempEnumTypes }; + MDNode *EnumHolder = MDNode::get(VMContext, THElts); + + TempRetainTypes = MDNode::getTemporary(VMContext, TElts); + Value *TRElts[] = { TempRetainTypes }; + MDNode *RetainHolder = MDNode::get(VMContext, TRElts); + + TempSubprograms = MDNode::getTemporary(VMContext, TElts); + Value *TSElts[] = { TempSubprograms }; + MDNode *SPHolder = MDNode::get(VMContext, TSElts); + + TempGVs = MDNode::getTemporary(VMContext, TElts); + Value *TVElts[] = { TempGVs }; + MDNode *GVHolder = MDNode::get(VMContext, TVElts); + Value *Elts[] = { GetTagConstant(VMContext, dwarf::DW_TAG_compile_unit), llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)), @@ -48,7 +108,11 @@ void DIBuilder::createCompileUnit(unsigned Lang, StringRef Filename, ConstantInt::get(Type::getInt1Ty(VMContext), true), // isMain ConstantInt::get(Type::getInt1Ty(VMContext), isOptimized), MDString::get(VMContext, Flags), - ConstantInt::get(Type::getInt32Ty(VMContext), RunTimeVer) + ConstantInt::get(Type::getInt32Ty(VMContext), RunTimeVer), + EnumHolder, + RetainHolder, + SPHolder, + GVHolder }; TheCU = DICompileUnit(MDNode::get(VMContext, Elts)); @@ -61,17 +125,19 @@ void DIBuilder::createCompileUnit(unsigned Lang, StringRef Filename, /// for a file. DIFile DIBuilder::createFile(StringRef Filename, StringRef Directory) { assert(TheCU && "Unable to create DW_TAG_file_type without CompileUnit"); + assert(!Filename.empty() && "Unable to create file without name"); Value *Elts[] = { GetTagConstant(VMContext, dwarf::DW_TAG_file_type), MDString::get(VMContext, Filename), MDString::get(VMContext, Directory), - TheCU + NULL // TheCU }; return DIFile(MDNode::get(VMContext, Elts)); } /// createEnumerator - Create a single enumerator value. DIEnumerator DIBuilder::createEnumerator(StringRef Name, uint64_t Val) { + assert(!Name.empty() && "Unable to create enumerator without name"); Value *Elts[] = { GetTagConstant(VMContext, dwarf::DW_TAG_enumerator), MDString::get(VMContext, Name), @@ -80,16 +146,37 @@ DIEnumerator DIBuilder::createEnumerator(StringRef Name, uint64_t Val) { return DIEnumerator(MDNode::get(VMContext, Elts)); } -/// createBasicType - Create debugging information entry for a basic +/// createNullPtrType - Create C++0x nullptr type. +DIType DIBuilder::createNullPtrType(StringRef Name) { + assert(!Name.empty() && "Unable to create type without name"); + // nullptr is encoded in DIBasicType format. Line number, filename, + // ,size, alignment, offset and flags are always empty here. + Value *Elts[] = { + GetTagConstant(VMContext, dwarf::DW_TAG_unspecified_type), + NULL, //TheCU, + MDString::get(VMContext, Name), + NULL, // Filename + ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Line + ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Size + ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Align + ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Offset + ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Flags; + ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Encoding + }; + return DIType(MDNode::get(VMContext, Elts)); +} + +/// createBasicType - Create debugging information entry for a basic /// type, e.g 'char'. -DIType DIBuilder::createBasicType(StringRef Name, uint64_t SizeInBits, +DIType DIBuilder::createBasicType(StringRef Name, uint64_t SizeInBits, uint64_t AlignInBits, unsigned Encoding) { + assert(!Name.empty() && "Unable to create type without name"); // Basic types are encoded in DIBasicType format. Line number, filename, // offset and flags are always empty here. Value *Elts[] = { GetTagConstant(VMContext, dwarf::DW_TAG_base_type), - TheCU, + NULL, //TheCU, MDString::get(VMContext, Name), NULL, // Filename ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Line @@ -108,7 +195,7 @@ DIType DIBuilder::createQualifiedType(unsigned Tag, DIType FromTy) { // Qualified types are encoded in DIDerivedType format. Value *Elts[] = { GetTagConstant(VMContext, Tag), - TheCU, + NULL, //TheCU, MDString::get(VMContext, StringRef()), // Empty name. NULL, // Filename ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Line @@ -127,7 +214,7 @@ DIType DIBuilder::createPointerType(DIType PointeeTy, uint64_t SizeInBits, // Pointer types are encoded in DIDerivedType format. Value *Elts[] = { GetTagConstant(VMContext, dwarf::DW_TAG_pointer_type), - TheCU, + NULL, //TheCU, MDString::get(VMContext, Name), NULL, // Filename ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Line @@ -142,10 +229,11 @@ DIType DIBuilder::createPointerType(DIType PointeeTy, uint64_t SizeInBits, /// createReferenceType - Create debugging information entry for a reference. DIType DIBuilder::createReferenceType(DIType RTy) { + assert(RTy.Verify() && "Unable to create reference type"); // References are encoded in DIDerivedType format. Value *Elts[] = { GetTagConstant(VMContext, dwarf::DW_TAG_reference_type), - TheCU, + NULL, // TheCU, NULL, // Name NULL, // Filename ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Line @@ -165,7 +253,7 @@ DIType DIBuilder::createTypedef(DIType Ty, StringRef Name, DIFile File, assert(Ty.Verify() && "Invalid typedef type!"); Value *Elts[] = { GetTagConstant(VMContext, dwarf::DW_TAG_typedef), - Context, + getNonCompileUnitScope(Context), MDString::get(VMContext, Name), File, ConstantInt::get(Type::getInt32Ty(VMContext), LineNo), @@ -199,9 +287,10 @@ DIType DIBuilder::createFriend(DIType Ty, DIType FriendTy) { } /// createInheritance - Create debugging information entry to establish -/// inheritnace relationship between two types. -DIType DIBuilder::createInheritance(DIType Ty, DIType BaseTy, +/// inheritance relationship between two types. +DIType DIBuilder::createInheritance(DIType Ty, DIType BaseTy, uint64_t BaseOffset, unsigned Flags) { + assert(Ty.Verify() && "Unable to create inheritance"); // TAG_inheritance is encoded in DIDerivedType format. Value *Elts[] = { GetTagConstant(VMContext, dwarf::DW_TAG_inheritance), @@ -219,15 +308,15 @@ DIType DIBuilder::createInheritance(DIType Ty, DIType BaseTy, } /// createMemberType - Create debugging information entry for a member. -DIType DIBuilder::createMemberType(DIDescriptor Scope, StringRef Name, - DIFile File, unsigned LineNumber, +DIType DIBuilder::createMemberType(DIDescriptor Scope, StringRef Name, + DIFile File, unsigned LineNumber, uint64_t SizeInBits, uint64_t AlignInBits, - uint64_t OffsetInBits, unsigned Flags, + uint64_t OffsetInBits, unsigned Flags, DIType Ty) { // TAG_member is encoded in DIDerivedType format. Value *Elts[] = { GetTagConstant(VMContext, dwarf::DW_TAG_member), - Scope, + getNonCompileUnitScope(Scope), MDString::get(VMContext, Name), File, ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), @@ -242,17 +331,17 @@ DIType DIBuilder::createMemberType(DIDescriptor Scope, StringRef Name, /// createObjCIVar - Create debugging information entry for Objective-C /// instance variable. -DIType DIBuilder::createObjCIVar(StringRef Name, - DIFile File, unsigned LineNumber, +DIType DIBuilder::createObjCIVar(StringRef Name, + DIFile File, unsigned LineNumber, uint64_t SizeInBits, uint64_t AlignInBits, - uint64_t OffsetInBits, unsigned Flags, + uint64_t OffsetInBits, unsigned Flags, DIType Ty, StringRef PropertyName, StringRef GetterName, StringRef SetterName, unsigned PropertyAttributes) { // TAG_member is encoded in DIDerivedType format. Value *Elts[] = { GetTagConstant(VMContext, dwarf::DW_TAG_member), - File, // Or TheCU ? Ty ? + getNonCompileUnitScope(File), MDString::get(VMContext, Name), File, ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), @@ -270,8 +359,8 @@ DIType DIBuilder::createObjCIVar(StringRef Name, } /// createClassType - Create debugging information entry for a class. -DIType DIBuilder::createClassType(DIDescriptor Context, StringRef Name, - DIFile File, unsigned LineNumber, +DIType DIBuilder::createClassType(DIDescriptor Context, StringRef Name, + DIFile File, unsigned LineNumber, uint64_t SizeInBits, uint64_t AlignInBits, uint64_t OffsetInBits, unsigned Flags, DIType DerivedFrom, DIArray Elements, @@ -279,7 +368,7 @@ DIType DIBuilder::createClassType(DIDescriptor Context, StringRef Name, // TAG_class_type is encoded in DICompositeType format. Value *Elts[] = { GetTagConstant(VMContext, dwarf::DW_TAG_class_type), - Context, + getNonCompileUnitScope(Context), MDString::get(VMContext, Name), File, ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), @@ -298,13 +387,13 @@ DIType DIBuilder::createClassType(DIDescriptor Context, StringRef Name, /// createTemplateTypeParameter - Create debugging information for template /// type parameter. -DITemplateTypeParameter +DITemplateTypeParameter DIBuilder::createTemplateTypeParameter(DIDescriptor Context, StringRef Name, DIType Ty, MDNode *File, unsigned LineNo, unsigned ColumnNo) { Value *Elts[] = { GetTagConstant(VMContext, dwarf::DW_TAG_template_type_parameter), - Context, + getNonCompileUnitScope(Context), MDString::get(VMContext, Name), Ty, File, @@ -316,14 +405,14 @@ DIBuilder::createTemplateTypeParameter(DIDescriptor Context, StringRef Name, /// createTemplateValueParameter - Create debugging information for template /// value parameter. -DITemplateValueParameter +DITemplateValueParameter DIBuilder::createTemplateValueParameter(DIDescriptor Context, StringRef Name, DIType Ty, uint64_t Val, MDNode *File, unsigned LineNo, unsigned ColumnNo) { Value *Elts[] = { GetTagConstant(VMContext, dwarf::DW_TAG_template_value_parameter), - Context, + getNonCompileUnitScope(Context), MDString::get(VMContext, Name), Ty, ConstantInt::get(Type::getInt64Ty(VMContext), Val), @@ -335,15 +424,15 @@ DIBuilder::createTemplateValueParameter(DIDescriptor Context, StringRef Name, } /// createStructType - Create debugging information entry for a struct. -DIType DIBuilder::createStructType(DIDescriptor Context, StringRef Name, - DIFile File, unsigned LineNumber, +DIType DIBuilder::createStructType(DIDescriptor Context, StringRef Name, + DIFile File, unsigned LineNumber, uint64_t SizeInBits, uint64_t AlignInBits, - unsigned Flags, DIArray Elements, + unsigned Flags, DIArray Elements, unsigned RunTimeLang) { // TAG_structure_type is encoded in DICompositeType format. Value *Elts[] = { GetTagConstant(VMContext, dwarf::DW_TAG_structure_type), - Context, + getNonCompileUnitScope(Context), MDString::get(VMContext, Name), File, ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), @@ -360,7 +449,7 @@ DIType DIBuilder::createStructType(DIDescriptor Context, StringRef Name, } /// createUnionType - Create debugging information entry for an union. -DIType DIBuilder::createUnionType(DIDescriptor Scope, StringRef Name, +DIType DIBuilder::createUnionType(DIDescriptor Scope, StringRef Name, DIFile File, unsigned LineNumber, uint64_t SizeInBits, uint64_t AlignInBits, unsigned Flags, @@ -368,7 +457,7 @@ DIType DIBuilder::createUnionType(DIDescriptor Scope, StringRef Name, // TAG_union_type is encoded in DICompositeType format. Value *Elts[] = { GetTagConstant(VMContext, dwarf::DW_TAG_union_type), - Scope, + getNonCompileUnitScope(Scope), MDString::get(VMContext, Name), File, ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), @@ -389,9 +478,9 @@ DIType DIBuilder::createSubroutineType(DIFile File, DIArray ParameterTypes) { // TAG_subroutine_type is encoded in DICompositeType format. Value *Elts[] = { GetTagConstant(VMContext, dwarf::DW_TAG_subroutine_type), - File, + llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)), MDString::get(VMContext, ""), - File, + llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)), ConstantInt::get(Type::getInt32Ty(VMContext), 0), ConstantInt::get(Type::getInt64Ty(VMContext), 0), ConstantInt::get(Type::getInt64Ty(VMContext), 0), @@ -405,16 +494,17 @@ DIType DIBuilder::createSubroutineType(DIFile File, DIArray ParameterTypes) { return DIType(MDNode::get(VMContext, Elts)); } -/// createEnumerationType - Create debugging information entry for an +/// createEnumerationType - Create debugging information entry for an /// enumeration. -DIType DIBuilder::createEnumerationType(DIDescriptor Scope, StringRef Name, - DIFile File, unsigned LineNumber, - uint64_t SizeInBits, - uint64_t AlignInBits, DIArray Elements) { +DIType DIBuilder::createEnumerationType(DIDescriptor Scope, StringRef Name, + DIFile File, unsigned LineNumber, + uint64_t SizeInBits, + uint64_t AlignInBits, + DIArray Elements) { // TAG_enumeration_type is encoded in DICompositeType format. Value *Elts[] = { GetTagConstant(VMContext, dwarf::DW_TAG_enumeration_type), - Scope, + getNonCompileUnitScope(Scope), MDString::get(VMContext, Name), File, ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), @@ -428,20 +518,19 @@ DIType DIBuilder::createEnumerationType(DIDescriptor Scope, StringRef Name, llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)), }; MDNode *Node = MDNode::get(VMContext, Elts); - NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.dbg.enum"); - NMD->addOperand(Node); + AllEnumTypes.push_back(Node); return DIType(Node); } /// createArrayType - Create debugging information entry for an array. -DIType DIBuilder::createArrayType(uint64_t Size, uint64_t AlignInBits, +DIType DIBuilder::createArrayType(uint64_t Size, uint64_t AlignInBits, DIType Ty, DIArray Subscripts) { // TAG_array_type is encoded in DICompositeType format. Value *Elts[] = { GetTagConstant(VMContext, dwarf::DW_TAG_array_type), - TheCU, + NULL, //TheCU, MDString::get(VMContext, ""), - TheCU, + NULL, //TheCU, ConstantInt::get(Type::getInt32Ty(VMContext), 0), ConstantInt::get(Type::getInt64Ty(VMContext), Size), ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits), @@ -456,14 +545,14 @@ DIType DIBuilder::createArrayType(uint64_t Size, uint64_t AlignInBits, } /// createVectorType - Create debugging information entry for a vector. -DIType DIBuilder::createVectorType(uint64_t Size, uint64_t AlignInBits, +DIType DIBuilder::createVectorType(uint64_t Size, uint64_t AlignInBits, DIType Ty, DIArray Subscripts) { // TAG_vector_type is encoded in DICompositeType format. Value *Elts[] = { GetTagConstant(VMContext, dwarf::DW_TAG_vector_type), - TheCU, + NULL, //TheCU, MDString::get(VMContext, ""), - TheCU, + NULL, //TheCU, ConstantInt::get(Type::getInt32Ty(VMContext), 0), ConstantInt::get(Type::getInt64Ty(VMContext), Size), ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits), @@ -501,18 +590,17 @@ DIType DIBuilder::createArtificialType(DIType Ty) { return DIType(MDNode::get(VMContext, Elts)); } -/// retainType - Retain DIType in a module even if it is not referenced +/// retainType - Retain DIType in a module even if it is not referenced /// through debug info anchors. void DIBuilder::retainType(DIType T) { - NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.dbg.ty"); - NMD->addOperand(T); + AllRetainTypes.push_back(T); } /// createUnspecifiedParameter - Create unspeicified type descriptor /// for the subroutine type. DIDescriptor DIBuilder::createUnspecifiedParameter() { - Value *Elts[] = { - GetTagConstant(VMContext, dwarf::DW_TAG_unspecified_parameters) + Value *Elts[] = { + GetTagConstant(VMContext, dwarf::DW_TAG_unspecified_parameters) }; return DIDescriptor(MDNode::get(VMContext, Elts)); } @@ -532,7 +620,7 @@ DIType DIBuilder::createTemporaryType(DIFile F) { // use here as long as DIType accepts it. Value *Elts[] = { GetTagConstant(VMContext, DW_TAG_base_type), - F.getCompileUnit(), + TheCU, NULL, F }; @@ -563,12 +651,12 @@ DISubrange DIBuilder::getOrCreateSubrange(int64_t Lo, int64_t Hi) { /// createGlobalVariable - Create a new descriptor for the specified global. DIGlobalVariable DIBuilder:: -createGlobalVariable(StringRef Name, DIFile F, unsigned LineNumber, +createGlobalVariable(StringRef Name, DIFile F, unsigned LineNumber, DIType Ty, bool isLocalToUnit, llvm::Value *Val) { Value *Elts[] = { GetTagConstant(VMContext, dwarf::DW_TAG_variable), llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)), - TheCU, + NULL, // TheCU, MDString::get(VMContext, Name), MDString::get(VMContext, Name), MDString::get(VMContext, Name), @@ -580,22 +668,20 @@ createGlobalVariable(StringRef Name, DIFile F, unsigned LineNumber, Val }; MDNode *Node = MDNode::get(VMContext, Elts); - // Create a named metadata so that we do not lose this mdnode. - NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.dbg.gv"); - NMD->addOperand(Node); + AllGVs.push_back(Node); return DIGlobalVariable(Node); } /// createStaticVariable - Create a new descriptor for the specified static /// variable. DIGlobalVariable DIBuilder:: -createStaticVariable(DIDescriptor Context, StringRef Name, - StringRef LinkageName, DIFile F, unsigned LineNumber, +createStaticVariable(DIDescriptor Context, StringRef Name, + StringRef LinkageName, DIFile F, unsigned LineNumber, DIType Ty, bool isLocalToUnit, llvm::Value *Val) { Value *Elts[] = { GetTagConstant(VMContext, dwarf::DW_TAG_variable), llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)), - Context, + getNonCompileUnitScope(Context), MDString::get(VMContext, Name), MDString::get(VMContext, Name), MDString::get(VMContext, LinkageName), @@ -607,26 +693,25 @@ createStaticVariable(DIDescriptor Context, StringRef Name, Val }; MDNode *Node = MDNode::get(VMContext, Elts); - // Create a named metadata so that we do not lose this mdnode. - NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.dbg.gv"); - NMD->addOperand(Node); + AllGVs.push_back(Node); return DIGlobalVariable(Node); } /// createVariable - Create a new descriptor for the specified variable. DIVariable DIBuilder::createLocalVariable(unsigned Tag, DIDescriptor Scope, StringRef Name, DIFile File, - unsigned LineNo, DIType Ty, + unsigned LineNo, DIType Ty, bool AlwaysPreserve, unsigned Flags, unsigned ArgNo) { Value *Elts[] = { GetTagConstant(VMContext, Tag), - Scope, + getNonCompileUnitScope(Scope), MDString::get(VMContext, Name), File, ConstantInt::get(Type::getInt32Ty(VMContext), (LineNo | (ArgNo << 24))), Ty, - ConstantInt::get(Type::getInt32Ty(VMContext), Flags) + ConstantInt::get(Type::getInt32Ty(VMContext), Flags), + Constant::getNullValue(Type::getInt32Ty(VMContext)), }; MDNode *Node = MDNode::get(VMContext, Elts); if (AlwaysPreserve) { @@ -634,13 +719,7 @@ DIVariable DIBuilder::createLocalVariable(unsigned Tag, DIDescriptor Scope, // to preserve variable info in such situation then stash it in a // named mdnode. DISubprogram Fn(getDISubprogram(Scope)); - StringRef FName = "fn"; - if (Fn.getFunction()) - FName = Fn.getFunction()->getName(); - char One = '\1'; - if (FName.startswith(StringRef(&One, 1))) - FName = FName.substr(1); - NamedMDNode *FnLocals = getOrInsertFnSpecificMDNode(M, FName); + NamedMDNode *FnLocals = getOrInsertFnSpecificMDNode(M, Fn); FnLocals->addOperand(Node); } return DIVariable(Node); @@ -655,12 +734,14 @@ DIVariable DIBuilder::createComplexVariable(unsigned Tag, DIDescriptor Scope, unsigned ArgNo) { SmallVector Elts; Elts.push_back(GetTagConstant(VMContext, Tag)); - Elts.push_back(Scope); + Elts.push_back(getNonCompileUnitScope(Scope)), Elts.push_back(MDString::get(VMContext, Name)); Elts.push_back(F); - Elts.push_back(ConstantInt::get(Type::getInt32Ty(VMContext), (LineNo | (ArgNo << 24)))); + Elts.push_back(ConstantInt::get(Type::getInt32Ty(VMContext), + (LineNo | (ArgNo << 24)))); Elts.push_back(Ty); Elts.push_back(llvm::Constant::getNullValue(Type::getInt32Ty(VMContext))); + Elts.push_back(llvm::Constant::getNullValue(Type::getInt32Ty(VMContext))); Elts.append(Addr.begin(), Addr.end()); return DIVariable(MDNode::get(VMContext, Elts)); @@ -677,10 +758,15 @@ DISubprogram DIBuilder::createFunction(DIDescriptor Context, Function *Fn, MDNode *TParams, MDNode *Decl) { + Value *TElts[] = { GetTagConstant(VMContext, DW_TAG_base_type) }; + MDNode *Temp = MDNode::getTemporary(VMContext, TElts); + Value *TVElts[] = { Temp }; + MDNode *THolder = MDNode::get(VMContext, TVElts); + Value *Elts[] = { GetTagConstant(VMContext, dwarf::DW_TAG_subprogram), llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)), - Context, + getNonCompileUnitScope(Context), MDString::get(VMContext, Name), MDString::get(VMContext, Name), MDString::get(VMContext, LinkageName), @@ -696,13 +782,13 @@ DISubprogram DIBuilder::createFunction(DIDescriptor Context, ConstantInt::get(Type::getInt1Ty(VMContext), isOptimized), Fn, TParams, - Decl + Decl, + THolder }; MDNode *Node = MDNode::get(VMContext, Elts); // Create a named metadata so that we do not lose this mdnode. - NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.dbg.sp"); - NMD->addOperand(Node); + AllSubprograms.push_back(Node); return DISubprogram(Node); } @@ -720,10 +806,15 @@ DISubprogram DIBuilder::createMethod(DIDescriptor Context, bool isOptimized, Function *Fn, MDNode *TParam) { + Value *TElts[] = { GetTagConstant(VMContext, DW_TAG_base_type) }; + MDNode *Temp = MDNode::getTemporary(VMContext, TElts); + Value *TVElts[] = { Temp }; + MDNode *THolder = MDNode::get(VMContext, TVElts); + Value *Elts[] = { GetTagConstant(VMContext, dwarf::DW_TAG_subprogram), llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)), - Context, + getNonCompileUnitScope(Context), MDString::get(VMContext, Name), MDString::get(VMContext, Name), MDString::get(VMContext, LinkageName), @@ -739,12 +830,10 @@ DISubprogram DIBuilder::createMethod(DIDescriptor Context, ConstantInt::get(Type::getInt1Ty(VMContext), isOptimized), Fn, TParam, + llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)), + THolder }; MDNode *Node = MDNode::get(VMContext, Elts); - - // Create a named metadata so that we do not lose this mdnode. - NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.dbg.sp"); - NMD->addOperand(Node); return DISubprogram(Node); } @@ -754,7 +843,7 @@ DINameSpace DIBuilder::createNameSpace(DIDescriptor Scope, StringRef Name, DIFile File, unsigned LineNo) { Value *Elts[] = { GetTagConstant(VMContext, dwarf::DW_TAG_namespace), - Scope, + getNonCompileUnitScope(Scope), MDString::get(VMContext, Name), File, ConstantInt::get(Type::getInt32Ty(VMContext), LineNo) @@ -762,13 +851,25 @@ DINameSpace DIBuilder::createNameSpace(DIDescriptor Scope, StringRef Name, return DINameSpace(MDNode::get(VMContext, Elts)); } +/// createLexicalBlockFile - This creates a new MDNode that encapsulates +/// an existing scope with a new filename. +DILexicalBlockFile DIBuilder::createLexicalBlockFile(DIDescriptor Scope, + DIFile File) { + Value *Elts[] = { + GetTagConstant(VMContext, dwarf::DW_TAG_lexical_block), + Scope, + File + }; + return DILexicalBlockFile(MDNode::get(VMContext, Elts)); +} + DILexicalBlock DIBuilder::createLexicalBlock(DIDescriptor Scope, DIFile File, unsigned Line, unsigned Col) { // Defeat MDNode uniqing for lexical blocks by using unique id. static unsigned int unique_id = 0; Value *Elts[] = { GetTagConstant(VMContext, dwarf::DW_TAG_lexical_block), - Scope, + getNonCompileUnitScope(Scope), ConstantInt::get(Type::getInt32Ty(VMContext), Line), ConstantInt::get(Type::getInt32Ty(VMContext), Col), File, @@ -836,4 +937,3 @@ Instruction *DIBuilder::insertDbgValueIntrinsic(Value *V, uint64_t Offset, VarInfo }; return CallInst::Create(ValueFn, Args, "", InsertAtEnd); } - diff --git a/contrib/llvm/lib/Analysis/DbgInfoPrinter.cpp b/contrib/llvm/lib/Analysis/DbgInfoPrinter.cpp index b23c3514d..cd832abeb 100644 --- a/contrib/llvm/lib/Analysis/DbgInfoPrinter.cpp +++ b/contrib/llvm/lib/Analysis/DbgInfoPrinter.cpp @@ -171,7 +171,7 @@ static bool getLocationInfo(const Value *V, std::string &DisplayName, void PrintDbgInfo::printVariableDeclaration(const Value *V) { std::string DisplayName, File, Directory, Type; - unsigned LineNo; + unsigned LineNo = 0; if (!getLocationInfo(V, DisplayName, Type, LineNo, File, Directory)) return; diff --git a/contrib/llvm/lib/Analysis/DebugInfo.cpp b/contrib/llvm/lib/Analysis/DebugInfo.cpp index b42e946f2..44457d3c3 100644 --- a/contrib/llvm/lib/Analysis/DebugInfo.cpp +++ b/contrib/llvm/lib/Analysis/DebugInfo.cpp @@ -39,6 +39,9 @@ DIDescriptor::DIDescriptor(const DIFile F) : DbgNode(F.DbgNode) { DIDescriptor::DIDescriptor(const DISubprogram F) : DbgNode(F.DbgNode) { } +DIDescriptor::DIDescriptor(const DILexicalBlockFile F) : DbgNode(F.DbgNode) { +} + DIDescriptor::DIDescriptor(const DILexicalBlock F) : DbgNode(F.DbgNode) { } @@ -111,9 +114,17 @@ Function *DIDescriptor::getFunctionField(unsigned Elt) const { unsigned DIVariable::getNumAddrElements() const { if (getVersion() <= llvm::LLVMDebugVersion8) return DbgNode->getNumOperands()-6; - return DbgNode->getNumOperands()-7; + if (getVersion() == llvm::LLVMDebugVersion9) + return DbgNode->getNumOperands()-7; + return DbgNode->getNumOperands()-8; } +/// getInlinedAt - If this variable is inlined then return inline location. +MDNode *DIVariable::getInlinedAt() const { + if (getVersion() <= llvm::LLVMDebugVersion9) + return NULL; + return dyn_cast_or_null(DbgNode->getOperand(7)); +} //===----------------------------------------------------------------------===// // Predicates @@ -122,7 +133,14 @@ unsigned DIVariable::getNumAddrElements() const { /// isBasicType - Return true if the specified tag is legal for /// DIBasicType. bool DIDescriptor::isBasicType() const { - return DbgNode && getTag() == dwarf::DW_TAG_base_type; + if (!DbgNode) return false; + switch (getTag()) { + case dwarf::DW_TAG_base_type: + case dwarf::DW_TAG_unspecified_type: + return true; + default: + return false; + } } /// isDerivedType - Return true if the specified tag is legal for DIDerivedType. @@ -248,9 +266,17 @@ bool DIDescriptor::isNameSpace() const { return DbgNode && getTag() == dwarf::DW_TAG_namespace; } +/// isLexicalBlockFile - Return true if the specified descriptor is a +/// lexical block with an extra file. +bool DIDescriptor::isLexicalBlockFile() const { + return DbgNode && getTag() == dwarf::DW_TAG_lexical_block && + (DbgNode->getNumOperands() == 3); +} + /// isLexicalBlock - Return true if the specified tag is DW_TAG_lexical_block. bool DIDescriptor::isLexicalBlock() const { - return DbgNode && getTag() == dwarf::DW_TAG_lexical_block; + return DbgNode && getTag() == dwarf::DW_TAG_lexical_block && + (DbgNode->getNumOperands() > 3); } /// isSubrange - Return true if the specified tag is DW_TAG_subrange_type. @@ -320,6 +346,22 @@ void DIType::replaceAllUsesWith(MDNode *D) { } } +/// isUnsignedDIType - Return true if type encoding is unsigned. +bool DIType::isUnsignedDIType() { + DIDerivedType DTy(DbgNode); + if (DTy.Verify()) + return DTy.getTypeDerivedFrom().isUnsignedDIType(); + + DIBasicType BTy(DbgNode); + if (BTy.Verify()) { + unsigned Encoding = BTy.getEncoding(); + if (Encoding == dwarf::DW_ATE_unsigned || + Encoding == dwarf::DW_ATE_unsigned_char) + return true; + } + return false; +} + /// Verify - Verify that a compile unit is well formed. bool DICompileUnit::Verify() const { if (!DbgNode) @@ -335,7 +377,7 @@ bool DICompileUnit::Verify() const { bool DIType::Verify() const { if (!DbgNode) return false; - if (!getContext().Verify()) + if (getContext() && !getContext().Verify()) return false; unsigned Tag = getTag(); if (!isBasicType() && Tag != dwarf::DW_TAG_const_type && @@ -343,6 +385,7 @@ bool DIType::Verify() const { Tag != dwarf::DW_TAG_reference_type && Tag != dwarf::DW_TAG_restrict_type && Tag != dwarf::DW_TAG_vector_type && Tag != dwarf::DW_TAG_array_type && Tag != dwarf::DW_TAG_enumeration_type + && Tag != dwarf::DW_TAG_subroutine_type && getFilename().empty()) return false; return true; @@ -362,12 +405,9 @@ bool DIDerivedType::Verify() const { bool DICompositeType::Verify() const { if (!DbgNode) return false; - if (!getContext().Verify()) + if (getContext() && !getContext().Verify()) return false; - DICompileUnit CU = getCompileUnit(); - if (!CU.Verify()) - return false; return true; } @@ -376,11 +416,7 @@ bool DISubprogram::Verify() const { if (!DbgNode) return false; - if (!getContext().Verify()) - return false; - - DICompileUnit CU = getCompileUnit(); - if (!CU.Verify()) + if (getContext() && !getContext().Verify()) return false; DICompositeType Ty = getType(); @@ -397,11 +433,7 @@ bool DIGlobalVariable::Verify() const { if (getDisplayName().empty()) return false; - if (!getContext().Verify()) - return false; - - DICompileUnit CU = getCompileUnit(); - if (!CU.Verify()) + if (getContext() && !getContext().Verify()) return false; DIType Ty = getType(); @@ -419,10 +451,7 @@ bool DIVariable::Verify() const { if (!DbgNode) return false; - if (!getContext().Verify()) - return false; - - if (!getCompileUnit().Verify()) + if (getContext() && !getContext().Verify()) return false; DIType Ty = getType(); @@ -446,8 +475,6 @@ bool DINameSpace::Verify() const { return false; if (getName().empty()) return false; - if (!getCompileUnit().Verify()) - return false; return true; } @@ -504,9 +531,28 @@ unsigned DISubprogram::isOptimized() const { return 0; } +MDNode *DISubprogram::getVariablesNodes() const { + if (!DbgNode || DbgNode->getNumOperands() <= 19) + return NULL; + if (MDNode *Temp = dyn_cast_or_null(DbgNode->getOperand(19))) + return dyn_cast_or_null(Temp->getOperand(0)); + return NULL; +} + +DIArray DISubprogram::getVariables() const { + if (!DbgNode || DbgNode->getNumOperands() <= 19) + return DIArray(); + if (MDNode *T = dyn_cast_or_null(DbgNode->getOperand(19))) + if (MDNode *A = dyn_cast_or_null(T->getOperand(0))) + return DIArray(A); + return DIArray(); +} + StringRef DIScope::getFilename() const { if (!DbgNode) return StringRef(); + if (isLexicalBlockFile()) + return DILexicalBlockFile(DbgNode).getFilename(); if (isLexicalBlock()) return DILexicalBlock(DbgNode).getFilename(); if (isSubprogram()) @@ -526,6 +572,8 @@ StringRef DIScope::getFilename() const { StringRef DIScope::getDirectory() const { if (!DbgNode) return StringRef(); + if (isLexicalBlockFile()) + return DILexicalBlockFile(DbgNode).getDirectory(); if (isLexicalBlock()) return DILexicalBlock(DbgNode).getDirectory(); if (isSubprogram()) @@ -542,6 +590,47 @@ StringRef DIScope::getDirectory() const { return StringRef(); } +DIArray DICompileUnit::getEnumTypes() const { + if (!DbgNode || DbgNode->getNumOperands() < 14) + return DIArray(); + + if (MDNode *N = dyn_cast_or_null(DbgNode->getOperand(10))) + if (MDNode *A = dyn_cast_or_null(N->getOperand(0))) + return DIArray(A); + return DIArray(); +} + +DIArray DICompileUnit::getRetainedTypes() const { + if (!DbgNode || DbgNode->getNumOperands() < 14) + return DIArray(); + + if (MDNode *N = dyn_cast_or_null(DbgNode->getOperand(11))) + if (MDNode *A = dyn_cast_or_null(N->getOperand(0))) + return DIArray(A); + return DIArray(); +} + +DIArray DICompileUnit::getSubprograms() const { + if (!DbgNode || DbgNode->getNumOperands() < 14) + return DIArray(); + + if (MDNode *N = dyn_cast_or_null(DbgNode->getOperand(12))) + if (MDNode *A = dyn_cast_or_null(N->getOperand(0))) + return DIArray(A); + return DIArray(); +} + + +DIArray DICompileUnit::getGlobalVariables() const { + if (!DbgNode || DbgNode->getNumOperands() < 14) + return DIArray(); + + if (MDNode *N = dyn_cast_or_null(DbgNode->getOperand(13))) + if (MDNode *A = dyn_cast_or_null(N->getOperand(0))) + return DIArray(A); + return DIArray(); +} + //===----------------------------------------------------------------------===// // DIDescriptor: dump routines for all descriptors. //===----------------------------------------------------------------------===// @@ -573,7 +662,6 @@ void DIType::print(raw_ostream &OS) const { OS << " [" << dwarf::TagString(Tag) << "] "; // TODO : Print context - getCompileUnit().print(OS); OS << " [" << "line " << getLineNumber() << ", " << getSizeInBits() << " bits, " @@ -629,7 +717,6 @@ void DISubprogram::print(raw_ostream &OS) const { OS << " [" << dwarf::TagString(Tag) << "] "; // TODO : Print context - getCompileUnit().print(OS); OS << " [" << getLineNumber() << "] "; if (isLocalToUnit()) @@ -652,7 +739,6 @@ void DIGlobalVariable::print(raw_ostream &OS) const { OS << " [" << dwarf::TagString(Tag) << "] "; // TODO : Print context - getCompileUnit().print(OS); OS << " [" << getLineNumber() << "] "; if (isLocalToUnit()) @@ -666,13 +752,48 @@ void DIGlobalVariable::print(raw_ostream &OS) const { OS << "]\n"; } +static void printDebugLoc(DebugLoc DL, raw_ostream &CommentOS, + const LLVMContext &Ctx) { + if (!DL.isUnknown()) { // Print source line info. + DIScope Scope(DL.getScope(Ctx)); + // Omit the directory, because it's likely to be long and uninteresting. + if (Scope.Verify()) + CommentOS << Scope.getFilename(); + else + CommentOS << ""; + CommentOS << ':' << DL.getLine(); + if (DL.getCol() != 0) + CommentOS << ':' << DL.getCol(); + DebugLoc InlinedAtDL = DebugLoc::getFromDILocation(DL.getInlinedAt(Ctx)); + if (!InlinedAtDL.isUnknown()) { + CommentOS << " @[ "; + printDebugLoc(InlinedAtDL, CommentOS, Ctx); + CommentOS << " ]"; + } + } +} + +void DIVariable::printExtendedName(raw_ostream &OS) const { + const LLVMContext &Ctx = DbgNode->getContext(); + StringRef Res = getName(); + if (!Res.empty()) + OS << Res << "," << getLineNumber(); + if (MDNode *InlinedAt = getInlinedAt()) { + DebugLoc InlinedAtDL = DebugLoc::getFromDILocation(InlinedAt); + if (!InlinedAtDL.isUnknown()) { + OS << " @["; + printDebugLoc(InlinedAtDL, OS, Ctx); + OS << "]"; + } + } +} + /// print - Print variable. void DIVariable::print(raw_ostream &OS) const { StringRef Res = getName(); if (!Res.empty()) OS << " [" << Res << "] "; - getCompileUnit().print(OS); OS << " [" << getLineNumber() << "] "; getType().print(OS); OS << "\n"; @@ -744,22 +865,61 @@ static void fixupObjcLikeName(StringRef Str, SmallVectorImpl &Out) { /// getFnSpecificMDNode - Return a NameMDNode, if available, that is /// suitable to hold function specific information. -NamedMDNode *llvm::getFnSpecificMDNode(const Module &M, StringRef FuncName) { +NamedMDNode *llvm::getFnSpecificMDNode(const Module &M, DISubprogram Fn) { SmallString<32> Name = StringRef("llvm.dbg.lv."); - fixupObjcLikeName(FuncName, Name); - + StringRef FName = "fn"; + if (Fn.getFunction()) + FName = Fn.getFunction()->getName(); + else + FName = Fn.getName(); + char One = '\1'; + if (FName.startswith(StringRef(&One, 1))) + FName = FName.substr(1); + fixupObjcLikeName(FName, Name); return M.getNamedMetadata(Name.str()); } /// getOrInsertFnSpecificMDNode - Return a NameMDNode that is suitable /// to hold function specific information. -NamedMDNode *llvm::getOrInsertFnSpecificMDNode(Module &M, StringRef FuncName) { +NamedMDNode *llvm::getOrInsertFnSpecificMDNode(Module &M, DISubprogram Fn) { SmallString<32> Name = StringRef("llvm.dbg.lv."); - fixupObjcLikeName(FuncName, Name); - + StringRef FName = "fn"; + if (Fn.getFunction()) + FName = Fn.getFunction()->getName(); + else + FName = Fn.getName(); + char One = '\1'; + if (FName.startswith(StringRef(&One, 1))) + FName = FName.substr(1); + fixupObjcLikeName(FName, Name); + return M.getOrInsertNamedMetadata(Name.str()); } +/// createInlinedVariable - Create a new inlined variable based on current +/// variable. +/// @param DV Current Variable. +/// @param InlinedScope Location at current variable is inlined. +DIVariable llvm::createInlinedVariable(MDNode *DV, MDNode *InlinedScope, + LLVMContext &VMContext) { + SmallVector Elts; + // Insert inlined scope as 7th element. + for (unsigned i = 0, e = DV->getNumOperands(); i != e; ++i) + i == 7 ? Elts.push_back(InlinedScope) : + Elts.push_back(DV->getOperand(i)); + return DIVariable(MDNode::get(VMContext, Elts)); +} + +/// cleanseInlinedVariable - Remove inlined scope from the variable. +DIVariable llvm::cleanseInlinedVariable(MDNode *DV, LLVMContext &VMContext) { + SmallVector Elts; + // Insert inlined scope as 7th element. + for (unsigned i = 0, e = DV->getNumOperands(); i != e; ++i) + i == 7 ? + Elts.push_back(llvm::Constant::getNullValue(Type::getInt32Ty(VMContext))): + Elts.push_back(DV->getOperand(i)); + return DIVariable(MDNode::get(VMContext, Elts)); +} //===----------------------------------------------------------------------===// // DebugInfoFinder implementations. @@ -767,6 +927,10 @@ NamedMDNode *llvm::getOrInsertFnSpecificMDNode(Module &M, StringRef FuncName) { /// processModule - Process entire module and collect debug info. void DebugInfoFinder::processModule(Module &M) { + if (NamedMDNode *CU_Nodes = M.getNamedMetadata("llvm.dbg.cu")) + for (unsigned i = 0, e = CU_Nodes->getNumOperands(); i != e; ++i) + addCompileUnit(DICompileUnit(CU_Nodes->getOperand(i))); + for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) for (Function::iterator FI = (*I).begin(), FE = (*I).end(); FI != FE; ++FI) for (BasicBlock::iterator BI = (*FI).begin(), BE = (*FI).end(); BI != BE; @@ -785,6 +949,10 @@ void DebugInfoFinder::processModule(Module &M) { addCompileUnit(DICompileUnit(Scope)); else if (Scope.isSubprogram()) processSubprogram(DISubprogram(Scope)); + else if (Scope.isLexicalBlockFile()) { + DILexicalBlockFile DBF = DILexicalBlockFile(Scope); + processLexicalBlock(DILexicalBlock(DBF.getScope())); + } else if (Scope.isLexicalBlock()) processLexicalBlock(DILexicalBlock(Scope)); @@ -796,7 +964,8 @@ void DebugInfoFinder::processModule(Module &M) { for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) { DIGlobalVariable DIG(cast(NMD->getOperand(i))); if (addGlobalVariable(DIG)) { - addCompileUnit(DIG.getCompileUnit()); + if (DIG.getVersion() <= LLVMDebugVersion10) + addCompileUnit(DIG.getCompileUnit()); processType(DIG.getType()); } } @@ -817,6 +986,10 @@ void DebugInfoFinder::processLocation(DILocation Loc) { processSubprogram(DISubprogram(S)); else if (S.isLexicalBlock()) processLexicalBlock(DILexicalBlock(S)); + else if (S.isLexicalBlockFile()) { + DILexicalBlockFile DBF = DILexicalBlockFile(S); + processLexicalBlock(DILexicalBlock(DBF.getScope())); + } processLocation(Loc.getOrigLocation()); } @@ -824,8 +997,8 @@ void DebugInfoFinder::processLocation(DILocation Loc) { void DebugInfoFinder::processType(DIType DT) { if (!addType(DT)) return; - - addCompileUnit(DT.getCompileUnit()); + if (DT.getVersion() <= LLVMDebugVersion10) + addCompileUnit(DT.getCompileUnit()); if (DT.isCompositeType()) { DICompositeType DCT(DT); processType(DCT.getTypeDerivedFrom()); @@ -848,6 +1021,10 @@ void DebugInfoFinder::processLexicalBlock(DILexicalBlock LB) { DIScope Context = LB.getContext(); if (Context.isLexicalBlock()) return processLexicalBlock(DILexicalBlock(Context)); + else if (Context.isLexicalBlockFile()) { + DILexicalBlockFile DBF = DILexicalBlockFile(Context); + return processLexicalBlock(DILexicalBlock(DBF.getScope())); + } else return processSubprogram(DISubprogram(Context)); } @@ -856,7 +1033,8 @@ void DebugInfoFinder::processLexicalBlock(DILexicalBlock LB) { void DebugInfoFinder::processSubprogram(DISubprogram SP) { if (!addSubprogram(SP)) return; - addCompileUnit(SP.getCompileUnit()); + if (SP.getVersion() <= LLVMDebugVersion10) + addCompileUnit(SP.getCompileUnit()); processType(SP.getType()); } @@ -871,8 +1049,8 @@ void DebugInfoFinder::processDeclare(DbgDeclareInst *DDI) { if (!NodesSeen.insert(DV)) return; - - addCompileUnit(DIVariable(N).getCompileUnit()); + if (DIVariable(N).getVersion() <= LLVMDebugVersion10) + addCompileUnit(DIVariable(N).getCompileUnit()); processType(DIVariable(N).getType()); } @@ -930,6 +1108,9 @@ DISubprogram llvm::getDISubprogram(const MDNode *Scope) { if (D.isSubprogram()) return DISubprogram(Scope); + if (D.isLexicalBlockFile()) + return getDISubprogram(DILexicalBlockFile(Scope).getContext()); + if (D.isLexicalBlock()) return getDISubprogram(DILexicalBlock(Scope).getContext()); @@ -946,3 +1127,17 @@ DICompositeType llvm::getDICompositeType(DIType T) { return DICompositeType(); } + +/// isSubprogramContext - Return true if Context is either a subprogram +/// or another context nested inside a subprogram. +bool llvm::isSubprogramContext(const MDNode *Context) { + if (!Context) + return false; + DIDescriptor D(Context); + if (D.isSubprogram()) + return true; + if (D.isType()) + return isSubprogramContext(DIType(Context).getContext()); + return false; +} + diff --git a/contrib/llvm/lib/Analysis/IPA/CallGraphSCCPass.cpp b/contrib/llvm/lib/Analysis/IPA/CallGraphSCCPass.cpp index 659ffab0c..963da7523 100644 --- a/contrib/llvm/lib/Analysis/IPA/CallGraphSCCPass.cpp +++ b/contrib/llvm/lib/Analysis/IPA/CallGraphSCCPass.cpp @@ -44,8 +44,8 @@ namespace { class CGPassManager : public ModulePass, public PMDataManager { public: static char ID; - explicit CGPassManager(int Depth) - : ModulePass(ID), PMDataManager(Depth) { } + explicit CGPassManager() + : ModulePass(ID), PMDataManager() { } /// 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. @@ -350,6 +350,7 @@ bool CGPassManager::RefreshCallGraph(CallGraphSCC &CurSCC, dbgs() << "CGSCCPASSMGR: SCC Refresh didn't change call graph.\n"; } ); + (void)MadeChange; return DevirtualizedCall; } @@ -542,7 +543,7 @@ void CallGraphSCCPass::assignPassManager(PMStack &PMS, PMDataManager *PMD = PMS.top(); // [1] Create new Call Graph Pass Manager - CGP = new CGPassManager(PMD->getDepth() + 1); + CGP = new CGPassManager(); // [2] Set up new manager's top level manager PMTopLevelManager *TPM = PMD->getTopLevelManager(); diff --git a/contrib/llvm/lib/Analysis/IPA/FindUsedTypes.cpp b/contrib/llvm/lib/Analysis/IPA/FindUsedTypes.cpp index 653578666..e9df3ca01 100644 --- a/contrib/llvm/lib/Analysis/IPA/FindUsedTypes.cpp +++ b/contrib/llvm/lib/Analysis/IPA/FindUsedTypes.cpp @@ -29,7 +29,7 @@ INITIALIZE_PASS(FindUsedTypes, "print-used-types", // IncorporateType - Incorporate one type and all of its subtypes into the // collection of used types. // -void FindUsedTypes::IncorporateType(const Type *Ty) { +void FindUsedTypes::IncorporateType(Type *Ty) { // If ty doesn't already exist in the used types map, add it now, otherwise // return. if (!UsedTypes.insert(Ty)) return; // Already contain Ty. @@ -94,7 +94,7 @@ bool FindUsedTypes::runOnModule(Module &m) { // void FindUsedTypes::print(raw_ostream &OS, const Module *M) const { OS << "Types in use by this module:\n"; - for (SetVector::const_iterator I = UsedTypes.begin(), + for (SetVector::const_iterator I = UsedTypes.begin(), E = UsedTypes.end(); I != E; ++I) { OS << " " << **I << '\n'; } diff --git a/contrib/llvm/lib/Analysis/IVUsers.cpp b/contrib/llvm/lib/Analysis/IVUsers.cpp index e5f0a77ab..d0ca8920a 100644 --- a/contrib/llvm/lib/Analysis/IVUsers.cpp +++ b/contrib/llvm/lib/Analysis/IVUsers.cpp @@ -146,7 +146,8 @@ bool IVUsers::AddUsersIfInteresting(Instruction *I) { ISE, User, I, NewUse.PostIncLoops, *SE, *DT); - DEBUG(dbgs() << " NORMALIZED TO: " << *ISE << '\n'); + DEBUG(if (SE->getSCEV(I) != ISE) + dbgs() << " NORMALIZED TO: " << *ISE << '\n'); } } return true; diff --git a/contrib/llvm/lib/Analysis/InlineCost.cpp b/contrib/llvm/lib/Analysis/InlineCost.cpp index efde5984c..e12e322c2 100644 --- a/contrib/llvm/lib/Analysis/InlineCost.cpp +++ b/contrib/llvm/lib/Analysis/InlineCost.cpp @@ -15,6 +15,7 @@ #include "llvm/Support/CallSite.h" #include "llvm/CallingConv.h" #include "llvm/IntrinsicInst.h" +#include "llvm/Target/TargetData.h" #include "llvm/ADT/SmallPtrSet.h" using namespace llvm; @@ -24,13 +25,13 @@ using namespace llvm; /// TODO: Perhaps calls like memcpy, strcpy, etc? bool llvm::callIsSmall(const Function *F) { if (!F) return false; - + if (F->hasLocalLinkage()) return false; - + if (!F->hasName()) return false; - + StringRef Name = F->getName(); - + // These will all likely lower to a single selection DAG node. if (Name == "copysign" || Name == "copysignf" || Name == "copysignl" || Name == "fabs" || Name == "fabsf" || Name == "fabsl" || @@ -38,7 +39,7 @@ bool llvm::callIsSmall(const Function *F) { Name == "cos" || Name == "cosf" || Name == "cosl" || Name == "sqrt" || Name == "sqrtf" || Name == "sqrtl" ) return true; - + // These are all likely to be optimized into something smaller. if (Name == "pow" || Name == "powf" || Name == "powl" || Name == "exp2" || Name == "exp2l" || Name == "exp2f" || @@ -46,13 +47,14 @@ bool llvm::callIsSmall(const Function *F) { Name == "round" || Name == "ffs" || Name == "ffsl" || Name == "abs" || Name == "labs" || Name == "llabs") return true; - + return false; } /// analyzeBasicBlock - Fill in the current structure with information gleaned /// from the specified block. -void CodeMetrics::analyzeBasicBlock(const BasicBlock *BB) { +void CodeMetrics::analyzeBasicBlock(const BasicBlock *BB, + const TargetData *TD) { ++NumBlocks; unsigned NumInstsBeforeThisBB = NumInsts; for (BasicBlock::const_iterator II = BB->begin(), E = BB->end(); @@ -67,8 +69,8 @@ void CodeMetrics::analyzeBasicBlock(const BasicBlock *BB) { ImmutableCallSite CS(cast(II)); if (const Function *F = CS.getCalledFunction()) { - // If a function is both internal and has a single use, then it is - // extremely likely to get inlined in the future (it was probably + // If a function is both internal and has a single use, then it is + // extremely likely to get inlined in the future (it was probably // exposed by an interleaved devirtualization pass). if (F->hasInternalLinkage() && F->hasOneUse()) ++NumInlineCandidates; @@ -91,20 +93,25 @@ void CodeMetrics::analyzeBasicBlock(const BasicBlock *BB) { ++NumCalls; } } - + if (const AllocaInst *AI = dyn_cast(II)) { if (!AI->isStaticAlloca()) this->usesDynamicAlloca = true; } if (isa(II) || II->getType()->isVectorTy()) - ++NumVectorInsts; - + ++NumVectorInsts; + if (const CastInst *CI = dyn_cast(II)) { // Noop casts, including ptr <-> int, don't count. - if (CI->isLosslessCast() || isa(CI) || + if (CI->isLosslessCast() || isa(CI) || isa(CI)) continue; + // trunc to a native type is free (assuming the target has compare and + // shift-right of the same width). + if (isa(CI) && TD && + TD->isLegalInteger(TD->getTypeSizeInBits(CI->getType()))) + continue; // Result of a cmp instruction is often extended (to be used by other // cmp instructions, logical or return instructions). These are usually // nop on most sane targets. @@ -119,10 +126,10 @@ void CodeMetrics::analyzeBasicBlock(const BasicBlock *BB) { ++NumInsts; } - + if (isa(BB->getTerminator())) ++NumRets; - + // We never want to inline functions that contain an indirectbr. This is // incorrect because all the blockaddress's (in static global initializers // for example) would be referring to the original function, and this indirect @@ -217,7 +224,7 @@ unsigned CodeMetrics::CountCodeReductionForAlloca(Value *V) { /// analyzeFunction - Fill in the current structure with information gleaned /// from the specified function. -void CodeMetrics::analyzeFunction(Function *F) { +void CodeMetrics::analyzeFunction(Function *F, const TargetData *TD) { // If this function contains a call to setjmp or _setjmp, never inline // it. This is a hack because we depend on the user marking their local // variables as volatile if they are live across a setjmp call, and they @@ -227,13 +234,14 @@ void CodeMetrics::analyzeFunction(Function *F) { // Look at the size of the callee. for (Function::const_iterator BB = F->begin(), E = F->end(); BB != E; ++BB) - analyzeBasicBlock(&*BB); + analyzeBasicBlock(&*BB, TD); } /// analyzeFunction - Fill in the current structure with information gleaned /// from the specified function. -void InlineCostAnalyzer::FunctionInfo::analyzeFunction(Function *F) { - Metrics.analyzeFunction(F); +void InlineCostAnalyzer::FunctionInfo::analyzeFunction(Function *F, + const TargetData *TD) { + Metrics.analyzeFunction(F, TD); // A function with exactly one return has it removed during the inlining // process (see InlineFunction), so don't count it. @@ -252,7 +260,7 @@ void InlineCostAnalyzer::FunctionInfo::analyzeFunction(Function *F) { /// NeverInline - returns true if the function should never be inlined into /// any caller bool InlineCostAnalyzer::FunctionInfo::NeverInline() { - return (Metrics.callsSetJmp || Metrics.isRecursive || + return (Metrics.callsSetJmp || Metrics.isRecursive || Metrics.containsIndirectBr); } // getSpecializationBonus - The heuristic used to determine the per-call @@ -263,19 +271,19 @@ int InlineCostAnalyzer::getSpecializationBonus(Function *Callee, { if (Callee->mayBeOverridden()) return 0; - + int Bonus = 0; // If this function uses the coldcc calling convention, prefer not to // specialize it. if (Callee->getCallingConv() == CallingConv::Cold) Bonus -= InlineConstants::ColdccPenalty; - + // Get information about the callee. FunctionInfo *CalleeFI = &CachedFunctionInfo[Callee]; - + // If we haven't calculated this information yet, do so now. if (CalleeFI->Metrics.NumBlocks == 0) - CalleeFI->analyzeFunction(Callee); + CalleeFI->analyzeFunction(Callee, TD); unsigned ArgNo = 0; unsigned i = 0; @@ -286,7 +294,7 @@ int InlineCostAnalyzer::getSpecializationBonus(Function *Callee, Bonus += CountBonusForConstant(I); } - // Calls usually take a long time, so they make the specialization gain + // Calls usually take a long time, so they make the specialization gain // smaller. Bonus -= CalleeFI->Metrics.NumCalls * InlineConstants::CallPenalty; @@ -300,13 +308,13 @@ int InlineCostAnalyzer::getSpecializationBonus(Function *Callee, // inlining because we decide we don't want to give a bonus for // devirtualizing. int InlineCostAnalyzer::ConstantFunctionBonus(CallSite CS, Constant *C) { - + // This could just be NULL. if (!C) return 0; - + Function *F = dyn_cast(C); if (!F) return 0; - + int Bonus = InlineConstants::IndirectCallBonus + getInlineSize(CS, F); return (Bonus > 0) ? 0 : Bonus; } @@ -355,18 +363,18 @@ int InlineCostAnalyzer::CountBonusForConstant(Value *V, Constant *C) { Bonus += CountBonusForConstant(&Inst); } } - + return Bonus; } int InlineCostAnalyzer::getInlineSize(CallSite CS, Function *Callee) { // Get information about the callee. FunctionInfo *CalleeFI = &CachedFunctionInfo[Callee]; - + // If we haven't calculated this information yet, do so now. if (CalleeFI->Metrics.NumBlocks == 0) - CalleeFI->analyzeFunction(Callee); - + CalleeFI->analyzeFunction(Callee, TD); + // InlineCost - This value measures how good of an inline candidate this call // site is to inline. A lower inline cost make is more likely for the call to // be inlined. This value may go negative. @@ -392,9 +400,9 @@ int InlineCostAnalyzer::getInlineSize(CallSite CS, Function *Callee) { // weights calculated for the callee to determine how much will be folded // away with this information. else if (isa(I)) - InlineCost -= CalleeFI->ArgumentWeights[ArgNo].ConstantWeight; + InlineCost -= CalleeFI->ArgumentWeights[ArgNo].ConstantWeight; } - + // Each argument passed in has a cost at both the caller and the callee // sides. Measurements show that each argument costs about the same as an // instruction. @@ -408,28 +416,28 @@ int InlineCostAnalyzer::getInlineSize(CallSite CS, Function *Callee) { // Look at the size of the callee. Each instruction counts as 5. InlineCost += CalleeFI->Metrics.NumInsts*InlineConstants::InstrCost; - + return InlineCost; } int InlineCostAnalyzer::getInlineBonuses(CallSite CS, Function *Callee) { // Get information about the callee. FunctionInfo *CalleeFI = &CachedFunctionInfo[Callee]; - + // If we haven't calculated this information yet, do so now. if (CalleeFI->Metrics.NumBlocks == 0) - CalleeFI->analyzeFunction(Callee); - + CalleeFI->analyzeFunction(Callee, TD); + bool isDirectCall = CS.getCalledFunction() == Callee; Instruction *TheCall = CS.getInstruction(); int Bonus = 0; - + // If there is only one call of the function, and it has internal linkage, // make it almost guaranteed to be inlined. // if (Callee->hasLocalLinkage() && Callee->hasOneUse() && isDirectCall) Bonus += InlineConstants::LastCallToStaticBonus; - + // If the instruction after the call, or if the normal destination of the // invoke is an unreachable instruction, the function is noreturn. As such, // there is little point in inlining this. @@ -438,12 +446,12 @@ int InlineCostAnalyzer::getInlineBonuses(CallSite CS, Function *Callee) { Bonus += InlineConstants::NoreturnPenalty; } else if (isa(++BasicBlock::iterator(TheCall))) Bonus += InlineConstants::NoreturnPenalty; - + // If this function uses the coldcc calling convention, prefer not to inline // it. if (Callee->getCallingConv() == CallingConv::Cold) Bonus += InlineConstants::ColdccPenalty; - + // Add to the inline quality for properties that make the call valuable to // inline. This includes factors that indicate that the result of inlining // the function will be optimizable. Currently this just looks at arguments @@ -455,7 +463,7 @@ int InlineCostAnalyzer::getInlineBonuses(CallSite CS, Function *Callee) { // Compute any constant bonus due to inlining we want to give here. if (isa(I)) Bonus += CountBonusForConstant(FI, cast(I)); - + return Bonus; } @@ -483,10 +491,10 @@ InlineCost InlineCostAnalyzer::getInlineCost(CallSite CS, // Get information about the callee. FunctionInfo *CalleeFI = &CachedFunctionInfo[Callee]; - + // If we haven't calculated this information yet, do so now. if (CalleeFI->Metrics.NumBlocks == 0) - CalleeFI->analyzeFunction(Callee); + CalleeFI->analyzeFunction(Callee, TD); // If we should never inline this, return a huge cost. if (CalleeFI->NeverInline()) @@ -498,15 +506,15 @@ InlineCost InlineCostAnalyzer::getInlineCost(CallSite CS, // requires handling setjmp somewhere else, however. if (!Callee->isDeclaration() && Callee->hasFnAttr(Attribute::AlwaysInline)) return InlineCost::getAlways(); - + if (CalleeFI->Metrics.usesDynamicAlloca) { // Get information about the caller. FunctionInfo &CallerFI = CachedFunctionInfo[Caller]; // If we haven't calculated this information yet, do so now. if (CallerFI.Metrics.NumBlocks == 0) { - CallerFI.analyzeFunction(Caller); - + CallerFI.analyzeFunction(Caller, TD); + // Recompute the CalleeFI pointer, getting Caller could have invalidated // it. CalleeFI = &CachedFunctionInfo[Callee]; @@ -538,16 +546,16 @@ InlineCost InlineCostAnalyzer::getSpecializationCost(Function *Callee, // something else. if (Callee->mayBeOverridden()) return llvm::InlineCost::getNever(); - + // Get information about the callee. FunctionInfo *CalleeFI = &CachedFunctionInfo[Callee]; - + // If we haven't calculated this information yet, do so now. if (CalleeFI->Metrics.NumBlocks == 0) - CalleeFI->analyzeFunction(Callee); + CalleeFI->analyzeFunction(Callee, TD); int Cost = 0; - + // Look at the original size of the callee. Each instruction counts as 5. Cost += CalleeFI->Metrics.NumInsts * InlineConstants::InstrCost; @@ -564,13 +572,13 @@ InlineCost InlineCostAnalyzer::getSpecializationCost(Function *Callee, // higher threshold to determine if the function call should be inlined. float InlineCostAnalyzer::getInlineFudgeFactor(CallSite CS) { Function *Callee = CS.getCalledFunction(); - + // Get information about the callee. FunctionInfo &CalleeFI = CachedFunctionInfo[Callee]; - + // If we haven't calculated this information yet, do so now. if (CalleeFI.Metrics.NumBlocks == 0) - CalleeFI.analyzeFunction(Callee); + CalleeFI.analyzeFunction(Callee, TD); float Factor = 1.0f; // Single BB functions are often written to be inlined. @@ -604,7 +612,7 @@ InlineCostAnalyzer::growCachedCostInfo(Function *Caller, Function *Callee) { --CallerMetrics.NumCalls; if (Callee == 0) return; - + CodeMetrics &CalleeMetrics = CachedFunctionInfo[Callee].Metrics; // If we don't have metrics for the callee, don't recalculate them just to @@ -614,7 +622,7 @@ InlineCostAnalyzer::growCachedCostInfo(Function *Caller, Function *Callee) { resetCachedCostInfo(Caller); return; } - + // Since CalleeMetrics were already calculated, we know that the CallerMetrics // reference isn't invalidated: both were in the DenseMap. CallerMetrics.usesDynamicAlloca |= CalleeMetrics.usesDynamicAlloca; @@ -636,7 +644,7 @@ InlineCostAnalyzer::growCachedCostInfo(Function *Caller, Function *Callee) { CallerMetrics.NumInsts -= Callee->arg_size(); else CallerMetrics.NumInsts = 0; - + // We are not updating the argument weights. We have already determined that // Caller is a fairly large function, so we accept the loss of precision. } diff --git a/contrib/llvm/lib/Analysis/InstructionSimplify.cpp b/contrib/llvm/lib/Analysis/InstructionSimplify.cpp index 8709f6bf9..131cc97d2 100644 --- a/contrib/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/contrib/llvm/lib/Analysis/InstructionSimplify.cpp @@ -48,6 +48,26 @@ static Value *SimplifyOrInst(Value *, Value *, const TargetData *, static Value *SimplifyXorInst(Value *, Value *, const TargetData *, const DominatorTree *, unsigned); +/// getFalse - For a boolean type, or a vector of boolean type, return false, or +/// a vector with every element false, as appropriate for the type. +static Constant *getFalse(Type *Ty) { + assert((Ty->isIntegerTy(1) || + (Ty->isVectorTy() && + cast(Ty)->getElementType()->isIntegerTy(1))) && + "Expected i1 type or a vector of i1!"); + return Constant::getNullValue(Ty); +} + +/// getTrue - For a boolean type, or a vector of boolean type, return true, or +/// a vector with every element true, as appropriate for the type. +static Constant *getTrue(Type *Ty) { + assert((Ty->isIntegerTy(1) || + (Ty->isVectorTy() && + cast(Ty)->getElementType()->isIntegerTy(1))) && + "Expected i1 type or a vector of i1!"); + return Constant::getAllOnesValue(Ty); +} + /// ValueDominatesPHI - Does the given value dominate the specified phi node? static bool ValueDominatesPHI(Value *V, PHINode *P, const DominatorTree *DT) { Instruction *I = dyn_cast(V); @@ -526,7 +546,7 @@ static Value *SimplifyAddInst(Value *Op0, Value *Op1, bool isNSW, bool isNUW, if (Constant *CRHS = dyn_cast(Op1)) { Constant *Ops[] = { CLHS, CRHS }; return ConstantFoldInstOperands(Instruction::Add, CLHS->getType(), - Ops, 2, TD); + Ops, TD); } // Canonicalize the constant to the RHS. @@ -595,7 +615,7 @@ static Value *SimplifySubInst(Value *Op0, Value *Op1, bool isNSW, bool isNUW, if (Constant *CRHS = dyn_cast(Op1)) { Constant *Ops[] = { CLHS, CRHS }; return ConstantFoldInstOperands(Instruction::Sub, CLHS->getType(), - Ops, 2, TD); + Ops, TD); } // X - undef -> undef @@ -715,7 +735,7 @@ static Value *SimplifyMulInst(Value *Op0, Value *Op1, const TargetData *TD, if (Constant *CRHS = dyn_cast(Op1)) { Constant *Ops[] = { CLHS, CRHS }; return ConstantFoldInstOperands(Instruction::Mul, CLHS->getType(), - Ops, 2, TD); + Ops, TD); } // Canonicalize the constant to the RHS. @@ -788,7 +808,7 @@ static Value *SimplifyDiv(Instruction::BinaryOps Opcode, Value *Op0, Value *Op1, if (Constant *C0 = dyn_cast(Op0)) { if (Constant *C1 = dyn_cast(Op1)) { Constant *Ops[] = { C0, C1 }; - return ConstantFoldInstOperands(Opcode, C0->getType(), Ops, 2, TD); + return ConstantFoldInstOperands(Opcode, C0->getType(), Ops, TD); } } @@ -909,7 +929,7 @@ static Value *SimplifyRem(Instruction::BinaryOps Opcode, Value *Op0, Value *Op1, if (Constant *C0 = dyn_cast(Op0)) { if (Constant *C1 = dyn_cast(Op1)) { Constant *Ops[] = { C0, C1 }; - return ConstantFoldInstOperands(Opcode, C0->getType(), Ops, 2, TD); + return ConstantFoldInstOperands(Opcode, C0->getType(), Ops, TD); } } @@ -1012,7 +1032,7 @@ static Value *SimplifyShift(unsigned Opcode, Value *Op0, Value *Op1, if (Constant *C0 = dyn_cast(Op0)) { if (Constant *C1 = dyn_cast(Op1)) { Constant *Ops[] = { C0, C1 }; - return ConstantFoldInstOperands(Opcode, C0->getType(), Ops, 2, TD); + return ConstantFoldInstOperands(Opcode, C0->getType(), Ops, TD); } } @@ -1138,7 +1158,7 @@ static Value *SimplifyAndInst(Value *Op0, Value *Op1, const TargetData *TD, if (Constant *CRHS = dyn_cast(Op1)) { Constant *Ops[] = { CLHS, CRHS }; return ConstantFoldInstOperands(Instruction::And, CLHS->getType(), - Ops, 2, TD); + Ops, TD); } // Canonicalize the constant to the RHS. @@ -1227,7 +1247,7 @@ static Value *SimplifyOrInst(Value *Op0, Value *Op1, const TargetData *TD, if (Constant *CRHS = dyn_cast(Op1)) { Constant *Ops[] = { CLHS, CRHS }; return ConstantFoldInstOperands(Instruction::Or, CLHS->getType(), - Ops, 2, TD); + Ops, TD); } // Canonicalize the constant to the RHS. @@ -1321,7 +1341,7 @@ static Value *SimplifyXorInst(Value *Op0, Value *Op1, const TargetData *TD, if (Constant *CRHS = dyn_cast(Op1)) { Constant *Ops[] = { CLHS, CRHS }; return ConstantFoldInstOperands(Instruction::Xor, CLHS->getType(), - Ops, 2, TD); + Ops, TD); } // Canonicalize the constant to the RHS. @@ -1372,7 +1392,7 @@ Value *llvm::SimplifyXorInst(Value *Op0, Value *Op1, const TargetData *TD, return ::SimplifyXorInst(Op0, Op1, TD, DT, RecursionLimit); } -static const Type *GetCompareTy(Value *Op) { +static Type *GetCompareTy(Value *Op) { return CmpInst::makeCmpResultType(Op->getType()); } @@ -1413,8 +1433,8 @@ static Value *SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS, Pred = CmpInst::getSwappedPredicate(Pred); } - const Type *ITy = GetCompareTy(LHS); // The return type. - const Type *OpTy = LHS->getType(); // The operand type. + Type *ITy = GetCompareTy(LHS); // The return type. + Type *OpTy = LHS->getType(); // The operand type. // icmp X, X -> true/false // X icmp undef -> true/false. For example, icmp ugt %X, undef -> false @@ -1478,48 +1498,46 @@ static Value *SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS, default: assert(false && "Unknown ICmp predicate!"); case ICmpInst::ICMP_ULT: - // getNullValue also works for vectors, unlike getFalse. - return Constant::getNullValue(ITy); + return getFalse(ITy); case ICmpInst::ICMP_UGE: - // getAllOnesValue also works for vectors, unlike getTrue. - return ConstantInt::getAllOnesValue(ITy); + return getTrue(ITy); case ICmpInst::ICMP_EQ: case ICmpInst::ICMP_ULE: if (isKnownNonZero(LHS, TD)) - return Constant::getNullValue(ITy); + return getFalse(ITy); break; case ICmpInst::ICMP_NE: case ICmpInst::ICMP_UGT: if (isKnownNonZero(LHS, TD)) - return ConstantInt::getAllOnesValue(ITy); + return getTrue(ITy); break; case ICmpInst::ICMP_SLT: ComputeSignBit(LHS, LHSKnownNonNegative, LHSKnownNegative, TD); if (LHSKnownNegative) - return ConstantInt::getAllOnesValue(ITy); + return getTrue(ITy); if (LHSKnownNonNegative) - return Constant::getNullValue(ITy); + return getFalse(ITy); break; case ICmpInst::ICMP_SLE: ComputeSignBit(LHS, LHSKnownNonNegative, LHSKnownNegative, TD); if (LHSKnownNegative) - return ConstantInt::getAllOnesValue(ITy); + return getTrue(ITy); if (LHSKnownNonNegative && isKnownNonZero(LHS, TD)) - return Constant::getNullValue(ITy); + return getFalse(ITy); break; case ICmpInst::ICMP_SGE: ComputeSignBit(LHS, LHSKnownNonNegative, LHSKnownNegative, TD); if (LHSKnownNegative) - return Constant::getNullValue(ITy); + return getFalse(ITy); if (LHSKnownNonNegative) - return ConstantInt::getAllOnesValue(ITy); + return getTrue(ITy); break; case ICmpInst::ICMP_SGT: ComputeSignBit(LHS, LHSKnownNonNegative, LHSKnownNegative, TD); if (LHSKnownNegative) - return Constant::getNullValue(ITy); + return getFalse(ITy); if (LHSKnownNonNegative && isKnownNonZero(LHS, TD)) - return ConstantInt::getAllOnesValue(ITy); + return getTrue(ITy); break; } } @@ -1593,8 +1611,8 @@ static Value *SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS, if (isa(LHS) && (isa(RHS) || isa(RHS))) { Instruction *LI = cast(LHS); Value *SrcOp = LI->getOperand(0); - const Type *SrcTy = SrcOp->getType(); - const Type *DstTy = LI->getType(); + Type *SrcTy = SrcOp->getType(); + Type *DstTy = LI->getType(); // Turn icmp (ptrtoint x), (ptrtoint/constant) into a compare of the input // if the integer type is the same size as the pointer type. @@ -1811,8 +1829,7 @@ static Value *SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS, case ICmpInst::ICMP_EQ: case ICmpInst::ICMP_UGT: case ICmpInst::ICMP_UGE: - // getNullValue also works for vectors, unlike getFalse. - return Constant::getNullValue(ITy); + return getFalse(ITy); case ICmpInst::ICMP_SLT: case ICmpInst::ICMP_SLE: ComputeSignBit(LHS, KnownNonNegative, KnownNegative, TD); @@ -1822,8 +1839,7 @@ static Value *SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS, case ICmpInst::ICMP_NE: case ICmpInst::ICMP_ULT: case ICmpInst::ICMP_ULE: - // getAllOnesValue also works for vectors, unlike getTrue. - return Constant::getAllOnesValue(ITy); + return getTrue(ITy); } } if (RBO && match(RBO, m_URem(m_Value(), m_Specific(LHS)))) { @@ -1840,8 +1856,7 @@ static Value *SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS, case ICmpInst::ICMP_NE: case ICmpInst::ICMP_UGT: case ICmpInst::ICMP_UGE: - // getAllOnesValue also works for vectors, unlike getTrue. - return Constant::getAllOnesValue(ITy); + return getTrue(ITy); case ICmpInst::ICMP_SLT: case ICmpInst::ICMP_SLE: ComputeSignBit(RHS, KnownNonNegative, KnownNegative, TD); @@ -1851,8 +1866,7 @@ static Value *SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS, case ICmpInst::ICMP_EQ: case ICmpInst::ICMP_ULT: case ICmpInst::ICMP_ULE: - // getNullValue also works for vectors, unlike getFalse. - return Constant::getNullValue(ITy); + return getFalse(ITy); } } @@ -1874,7 +1888,7 @@ static Value *SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS, return V; break; case Instruction::Shl: { - bool NUW = LBO->hasNoUnsignedWrap() && LBO->hasNoUnsignedWrap(); + bool NUW = LBO->hasNoUnsignedWrap() && RBO->hasNoUnsignedWrap(); bool NSW = LBO->hasNoSignedWrap() && RBO->hasNoSignedWrap(); if (!NUW && !NSW) break; @@ -1955,10 +1969,10 @@ static Value *SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS, } case CmpInst::ICMP_SGE: // Always true. - return Constant::getAllOnesValue(ITy); + return getTrue(ITy); case CmpInst::ICMP_SLT: // Always false. - return Constant::getNullValue(ITy); + return getFalse(ITy); } } @@ -2025,10 +2039,10 @@ static Value *SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS, } case CmpInst::ICMP_UGE: // Always true. - return Constant::getAllOnesValue(ITy); + return getTrue(ITy); case CmpInst::ICMP_ULT: // Always false. - return Constant::getNullValue(ITy); + return getFalse(ITy); } } @@ -2040,40 +2054,40 @@ static Value *SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS, // max(x, ?) pred min(x, ?). if (Pred == CmpInst::ICMP_SGE) // Always true. - return Constant::getAllOnesValue(ITy); + return getTrue(ITy); if (Pred == CmpInst::ICMP_SLT) // Always false. - return Constant::getNullValue(ITy); + return getFalse(ITy); } else if (match(LHS, m_SMin(m_Value(A), m_Value(B))) && match(RHS, m_SMax(m_Value(C), m_Value(D))) && (A == C || A == D || B == C || B == D)) { // min(x, ?) pred max(x, ?). if (Pred == CmpInst::ICMP_SLE) // Always true. - return Constant::getAllOnesValue(ITy); + return getTrue(ITy); if (Pred == CmpInst::ICMP_SGT) // Always false. - return Constant::getNullValue(ITy); + return getFalse(ITy); } else if (match(LHS, m_UMax(m_Value(A), m_Value(B))) && match(RHS, m_UMin(m_Value(C), m_Value(D))) && (A == C || A == D || B == C || B == D)) { // max(x, ?) pred min(x, ?). if (Pred == CmpInst::ICMP_UGE) // Always true. - return Constant::getAllOnesValue(ITy); + return getTrue(ITy); if (Pred == CmpInst::ICMP_ULT) // Always false. - return Constant::getNullValue(ITy); + return getFalse(ITy); } else if (match(LHS, m_UMin(m_Value(A), m_Value(B))) && match(RHS, m_UMax(m_Value(C), m_Value(D))) && (A == C || A == D || B == C || B == D)) { // min(x, ?) pred max(x, ?). if (Pred == CmpInst::ICMP_ULE) // Always true. - return Constant::getAllOnesValue(ITy); + return getTrue(ITy); if (Pred == CmpInst::ICMP_UGT) // Always false. - return Constant::getNullValue(ITy); + return getFalse(ITy); } // If the comparison is with the result of a select instruction, check whether @@ -2219,43 +2233,71 @@ Value *llvm::SimplifySelectInst(Value *CondVal, Value *TrueVal, Value *FalseVal, /// SimplifyGEPInst - Given operands for an GetElementPtrInst, see if we can /// fold the result. If not, this returns null. -Value *llvm::SimplifyGEPInst(Value *const *Ops, unsigned NumOps, +Value *llvm::SimplifyGEPInst(ArrayRef Ops, const TargetData *TD, const DominatorTree *) { // The type of the GEP pointer operand. - const PointerType *PtrTy = cast(Ops[0]->getType()); + PointerType *PtrTy = cast(Ops[0]->getType()); // getelementptr P -> P. - if (NumOps == 1) + if (Ops.size() == 1) return Ops[0]; if (isa(Ops[0])) { // Compute the (pointer) type returned by the GEP instruction. - const Type *LastType = GetElementPtrInst::getIndexedType(PtrTy, &Ops[1], - NumOps-1); - const Type *GEPTy = PointerType::get(LastType, PtrTy->getAddressSpace()); + Type *LastType = GetElementPtrInst::getIndexedType(PtrTy, Ops.slice(1)); + Type *GEPTy = PointerType::get(LastType, PtrTy->getAddressSpace()); return UndefValue::get(GEPTy); } - if (NumOps == 2) { + if (Ops.size() == 2) { // getelementptr P, 0 -> P. if (ConstantInt *C = dyn_cast(Ops[1])) if (C->isZero()) return Ops[0]; // getelementptr P, N -> P if P points to a type of zero size. if (TD) { - const Type *Ty = PtrTy->getElementType(); + Type *Ty = PtrTy->getElementType(); if (Ty->isSized() && TD->getTypeAllocSize(Ty) == 0) return Ops[0]; } } // Check to see if this is constant foldable. - for (unsigned i = 0; i != NumOps; ++i) + for (unsigned i = 0, e = Ops.size(); i != e; ++i) if (!isa(Ops[i])) return 0; - return ConstantExpr::getGetElementPtr(cast(Ops[0]), - (Constant *const*)Ops+1, NumOps-1); + return ConstantExpr::getGetElementPtr(cast(Ops[0]), Ops.slice(1)); +} + +/// SimplifyInsertValueInst - Given operands for an InsertValueInst, see if we +/// can fold the result. If not, this returns null. +Value *llvm::SimplifyInsertValueInst(Value *Agg, Value *Val, + ArrayRef Idxs, + const TargetData *, + const DominatorTree *) { + if (Constant *CAgg = dyn_cast(Agg)) + if (Constant *CVal = dyn_cast(Val)) + return ConstantFoldInsertValueInstruction(CAgg, CVal, Idxs); + + // insertvalue x, undef, n -> x + if (match(Val, m_Undef())) + return Agg; + + // insertvalue x, (extractvalue y, n), n + if (ExtractValueInst *EV = dyn_cast(Val)) + if (EV->getAggregateOperand()->getType() == Agg->getType() && + EV->getIndices() == Idxs) { + // insertvalue undef, (extractvalue y, n), n -> y + if (match(Agg, m_Undef())) + return EV->getAggregateOperand(); + + // insertvalue y, (extractvalue y, n), n -> y + if (Agg == EV->getAggregateOperand()) + return Agg; + } + + return 0; } /// SimplifyPHINode - See if we can fold the given phi. If not, returns null. @@ -2328,7 +2370,7 @@ static Value *SimplifyBinOp(unsigned Opcode, Value *LHS, Value *RHS, if (Constant *CLHS = dyn_cast(LHS)) if (Constant *CRHS = dyn_cast(RHS)) { Constant *COps[] = {CLHS, CRHS}; - return ConstantFoldInstOperands(Opcode, LHS->getType(), COps, 2, TD); + return ConstantFoldInstOperands(Opcode, LHS->getType(), COps, TD); } // If the operation is associative, try some generic simplifications. @@ -2456,7 +2498,14 @@ Value *llvm::SimplifyInstruction(Instruction *I, const TargetData *TD, break; case Instruction::GetElementPtr: { SmallVector Ops(I->op_begin(), I->op_end()); - Result = SimplifyGEPInst(&Ops[0], Ops.size(), TD, DT); + Result = SimplifyGEPInst(Ops, TD, DT); + break; + } + case Instruction::InsertValue: { + InsertValueInst *IV = cast(I); + Result = SimplifyInsertValueInst(IV->getAggregateOperand(), + IV->getInsertedValueOperand(), + IV->getIndices(), TD, DT); break; } case Instruction::PHI: diff --git a/contrib/llvm/lib/Analysis/LazyValueInfo.cpp b/contrib/llvm/lib/Analysis/LazyValueInfo.cpp index 6e2759782..f80595c7d 100644 --- a/contrib/llvm/lib/Analysis/LazyValueInfo.cpp +++ b/contrib/llvm/lib/Analysis/LazyValueInfo.cpp @@ -630,7 +630,7 @@ bool LazyValueInfoCache::solveBlockValueNonLocal(LVILatticeVal &BBLV, if (BB == &BB->getParent()->getEntryBlock()) { assert(isa(Val) && "Unknown live-in to the entry block"); if (NotNull) { - const PointerType *PTy = cast(Val->getType()); + PointerType *PTy = cast(Val->getType()); Result = LVILatticeVal::getNot(ConstantPointerNull::get(PTy)); } else { Result.markOverdefined(); @@ -658,7 +658,7 @@ bool LazyValueInfoCache::solveBlockValueNonLocal(LVILatticeVal &BBLV, // If we previously determined that this is a pointer that can't be null // then return that rather than giving up entirely. if (NotNull) { - const PointerType *PTy = cast(Val->getType()); + PointerType *PTy = cast(Val->getType()); Result = LVILatticeVal::getNot(ConstantPointerNull::get(PTy)); } @@ -728,7 +728,7 @@ bool LazyValueInfoCache::solveBlockValueConstantRange(LVILatticeVal &BBLV, ConstantRange LHSRange = LHSVal.getConstantRange(); ConstantRange RHSRange(1); - const IntegerType *ResultTy = cast(BBI->getType()); + IntegerType *ResultTy = cast(BBI->getType()); if (isa(BBI)) { if (ConstantInt *RHS = dyn_cast(BBI->getOperand(1))) { RHSRange = ConstantRange(RHS->getValue()); diff --git a/contrib/llvm/lib/Analysis/Lint.cpp b/contrib/llvm/lib/Analysis/Lint.cpp index 89755da85..38d677d50 100644 --- a/contrib/llvm/lib/Analysis/Lint.cpp +++ b/contrib/llvm/lib/Analysis/Lint.cpp @@ -71,7 +71,7 @@ namespace { void visitCallSite(CallSite CS); void visitMemoryReference(Instruction &I, Value *Ptr, uint64_t Size, unsigned Align, - const Type *Ty, unsigned Flags); + Type *Ty, unsigned Flags); void visitCallInst(CallInst &I); void visitInvokeInst(InvokeInst &I); @@ -201,7 +201,7 @@ void Lint::visitCallSite(CallSite CS) { "Undefined behavior: Caller and callee calling convention differ", &I); - const FunctionType *FT = F->getFunctionType(); + FunctionType *FT = F->getFunctionType(); unsigned NumActualArgs = unsigned(CS.arg_end()-CS.arg_begin()); Assert1(FT->isVarArg() ? @@ -240,7 +240,7 @@ void Lint::visitCallSite(CallSite CS) { // Check that an sret argument points to valid memory. if (Formal->hasStructRetAttr() && Actual->getType()->isPointerTy()) { - const Type *Ty = + Type *Ty = cast(Formal->getType())->getElementType(); visitMemoryReference(I, Actual, AA->getTypeStoreSize(Ty), TD ? TD->getABITypeAlignment(Ty) : 0, @@ -364,7 +364,7 @@ void Lint::visitReturnInst(ReturnInst &I) { // TODO: Check readnone/readonly function attributes. void Lint::visitMemoryReference(Instruction &I, Value *Ptr, uint64_t Size, unsigned Align, - const Type *Ty, unsigned Flags) { + Type *Ty, unsigned Flags) { // If no memory is being referenced, it doesn't matter if the pointer // is valid. if (Size == 0) diff --git a/contrib/llvm/lib/Analysis/Loads.cpp b/contrib/llvm/lib/Analysis/Loads.cpp index c5c676b52..0e6bcbfae 100644 --- a/contrib/llvm/lib/Analysis/Loads.cpp +++ b/contrib/llvm/lib/Analysis/Loads.cpp @@ -63,7 +63,7 @@ static Value *getUnderlyingObjectWithOffset(Value *V, const TargetData *TD, return V; SmallVector Indices(GEP->op_begin() + 1, GEP->op_end()); ByteOffset += TD->getIndexedOffset(GEP->getPointerOperandType(), - &Indices[0], Indices.size()); + Indices); V = GEP->getPointerOperand(); } else if (Operator::getOpcode(V) == Instruction::BitCast) { V = cast(V)->getOperand(0); @@ -90,7 +90,7 @@ bool llvm::isSafeToLoadUnconditionally(Value *V, Instruction *ScanFrom, if (TD) Base = getUnderlyingObjectWithOffset(V, TD, ByteOffset); - const Type *BaseType = 0; + Type *BaseType = 0; unsigned BaseAlign = 0; if (const AllocaInst *AI = dyn_cast(Base)) { // An alloca is safe to load from as load as it is suitably aligned. @@ -114,7 +114,7 @@ bool llvm::isSafeToLoadUnconditionally(Value *V, Instruction *ScanFrom, return true; // Loading directly from an alloca or global is OK. // Check if the load is within the bounds of the underlying object. - const PointerType *AddrTy = cast(V->getType()); + PointerType *AddrTy = cast(V->getType()); uint64_t LoadSize = TD->getTypeStoreSize(AddrTy->getElementType()); if (ByteOffset + LoadSize <= TD->getTypeAllocSize(BaseType) && (Align == 0 || (ByteOffset % Align) == 0)) @@ -169,7 +169,7 @@ Value *llvm::FindAvailableLoadedValue(Value *Ptr, BasicBlock *ScanBB, // If we're using alias analysis to disambiguate get the size of *Ptr. uint64_t AccessSize = 0; if (AA) { - const Type *AccessTy = cast(Ptr->getType())->getElementType(); + Type *AccessTy = cast(Ptr->getType())->getElementType(); AccessSize = AA->getTypeStoreSize(AccessTy); } @@ -188,12 +188,16 @@ Value *llvm::FindAvailableLoadedValue(Value *Ptr, BasicBlock *ScanBB, --ScanFrom; // If this is a load of Ptr, the loaded value is available. + // (This is true even if the load is volatile or atomic, although + // those cases are unlikely.) if (LoadInst *LI = dyn_cast(Inst)) if (AreEquivalentAddressValues(LI->getOperand(0), Ptr)) return LI; if (StoreInst *SI = dyn_cast(Inst)) { // If this is a store through Ptr, the value is available! + // (This is true even if the store is volatile or atomic, although + // those cases are unlikely.) if (AreEquivalentAddressValues(SI->getOperand(1), Ptr)) return SI->getOperand(0); diff --git a/contrib/llvm/lib/Analysis/LoopDependenceAnalysis.cpp b/contrib/llvm/lib/Analysis/LoopDependenceAnalysis.cpp index c1afe8fbd..3997ac478 100644 --- a/contrib/llvm/lib/Analysis/LoopDependenceAnalysis.cpp +++ b/contrib/llvm/lib/Analysis/LoopDependenceAnalysis.cpp @@ -76,7 +76,13 @@ static void GetMemRefInstrs(const Loop *L, } static bool IsLoadOrStoreInst(Value *I) { - return isa(I) || isa(I); + // Returns true if the load or store can be analyzed. Atomic and volatile + // operations have properties which this analysis does not understand. + if (LoadInst *LI = dyn_cast(I)) + return LI->isUnordered(); + else if (StoreInst *SI = dyn_cast(I)) + return SI->isUnordered(); + return false; } static Value *GetPointerOperand(Value *I) { diff --git a/contrib/llvm/lib/Analysis/LoopInfo.cpp b/contrib/llvm/lib/Analysis/LoopInfo.cpp index 05831402f..85aaccaef 100644 --- a/contrib/llvm/lib/Analysis/LoopInfo.cpp +++ b/contrib/llvm/lib/Analysis/LoopInfo.cpp @@ -18,6 +18,7 @@ #include "llvm/Constants.h" #include "llvm/Instructions.h" #include "llvm/Analysis/Dominators.h" +#include "llvm/Analysis/LoopIterator.h" #include "llvm/Assembly/Writer.h" #include "llvm/Support/CFG.h" #include "llvm/Support/CommandLine.h" @@ -55,12 +56,12 @@ bool Loop::isLoopInvariant(Value *V) const { } /// hasLoopInvariantOperands - Return true if all the operands of the -/// specified instruction are loop invariant. +/// specified instruction are loop invariant. bool Loop::hasLoopInvariantOperands(Instruction *I) const { for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) if (!isLoopInvariant(I->getOperand(i))) return false; - + return true; } @@ -98,6 +99,9 @@ bool Loop::makeLoopInvariant(Instruction *I, bool &Changed, return false; if (I->mayReadFromMemory()) return false; + // The landingpad instruction is immobile. + if (isa(I)) + return false; // Determine the insertion point, unless one was given. if (!InsertPt) { BasicBlock *Preheader = getLoopPreheader(); @@ -110,7 +114,7 @@ bool Loop::makeLoopInvariant(Instruction *I, bool &Changed, for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) if (!makeLoopInvariant(I->getOperand(i), Changed, InsertPt)) return false; - + // Hoist. I->moveBefore(InsertPt); Changed = true; @@ -382,6 +386,205 @@ void Loop::dump() const { print(dbgs()); } +//===----------------------------------------------------------------------===// +// UnloopUpdater implementation +// + +namespace { +/// Find the new parent loop for all blocks within the "unloop" whose last +/// backedges has just been removed. +class UnloopUpdater { + Loop *Unloop; + LoopInfo *LI; + + LoopBlocksDFS DFS; + + // Map unloop's immediate subloops to their nearest reachable parents. Nested + // loops within these subloops will not change parents. However, an immediate + // subloop's new parent will be the nearest loop reachable from either its own + // exits *or* any of its nested loop's exits. + DenseMap SubloopParents; + + // Flag the presence of an irreducible backedge whose destination is a block + // directly contained by the original unloop. + bool FoundIB; + +public: + UnloopUpdater(Loop *UL, LoopInfo *LInfo) : + Unloop(UL), LI(LInfo), DFS(UL), FoundIB(false) {} + + void updateBlockParents(); + + void removeBlocksFromAncestors(); + + void updateSubloopParents(); + +protected: + Loop *getNearestLoop(BasicBlock *BB, Loop *BBLoop); +}; +} // end anonymous namespace + +/// updateBlockParents - Update the parent loop for all blocks that are directly +/// contained within the original "unloop". +void UnloopUpdater::updateBlockParents() { + if (Unloop->getNumBlocks()) { + // Perform a post order CFG traversal of all blocks within this loop, + // propagating the nearest loop from sucessors to predecessors. + LoopBlocksTraversal Traversal(DFS, LI); + for (LoopBlocksTraversal::POTIterator POI = Traversal.begin(), + POE = Traversal.end(); POI != POE; ++POI) { + + Loop *L = LI->getLoopFor(*POI); + Loop *NL = getNearestLoop(*POI, L); + + if (NL != L) { + // For reducible loops, NL is now an ancestor of Unloop. + assert((NL != Unloop && (!NL || NL->contains(Unloop))) && + "uninitialized successor"); + LI->changeLoopFor(*POI, NL); + } + else { + // Or the current block is part of a subloop, in which case its parent + // is unchanged. + assert((FoundIB || Unloop->contains(L)) && "uninitialized successor"); + } + } + } + // Each irreducible loop within the unloop induces a round of iteration using + // the DFS result cached by Traversal. + bool Changed = FoundIB; + for (unsigned NIters = 0; Changed; ++NIters) { + assert(NIters < Unloop->getNumBlocks() && "runaway iterative algorithm"); + + // Iterate over the postorder list of blocks, propagating the nearest loop + // from successors to predecessors as before. + Changed = false; + for (LoopBlocksDFS::POIterator POI = DFS.beginPostorder(), + POE = DFS.endPostorder(); POI != POE; ++POI) { + + Loop *L = LI->getLoopFor(*POI); + Loop *NL = getNearestLoop(*POI, L); + if (NL != L) { + assert(NL != Unloop && (!NL || NL->contains(Unloop)) && + "uninitialized successor"); + LI->changeLoopFor(*POI, NL); + Changed = true; + } + } + } +} + +/// removeBlocksFromAncestors - Remove unloop's blocks from all ancestors below +/// their new parents. +void UnloopUpdater::removeBlocksFromAncestors() { + // Remove unloop's blocks from all ancestors below their new parents. + for (Loop::block_iterator BI = Unloop->block_begin(), + BE = Unloop->block_end(); BI != BE; ++BI) { + Loop *NewParent = LI->getLoopFor(*BI); + // If this block is an immediate subloop, remove all blocks (including + // nested subloops) from ancestors below the new parent loop. + // Otherwise, if this block is in a nested subloop, skip it. + if (SubloopParents.count(NewParent)) + NewParent = SubloopParents[NewParent]; + else if (Unloop->contains(NewParent)) + continue; + + // Remove blocks from former Ancestors except Unloop itself which will be + // deleted. + for (Loop *OldParent = Unloop->getParentLoop(); OldParent != NewParent; + OldParent = OldParent->getParentLoop()) { + assert(OldParent && "new loop is not an ancestor of the original"); + OldParent->removeBlockFromLoop(*BI); + } + } +} + +/// updateSubloopParents - Update the parent loop for all subloops directly +/// nested within unloop. +void UnloopUpdater::updateSubloopParents() { + while (!Unloop->empty()) { + Loop *Subloop = *llvm::prior(Unloop->end()); + Unloop->removeChildLoop(llvm::prior(Unloop->end())); + + assert(SubloopParents.count(Subloop) && "DFS failed to visit subloop"); + if (SubloopParents[Subloop]) + SubloopParents[Subloop]->addChildLoop(Subloop); + else + LI->addTopLevelLoop(Subloop); + } +} + +/// getNearestLoop - Return the nearest parent loop among this block's +/// successors. If a successor is a subloop header, consider its parent to be +/// the nearest parent of the subloop's exits. +/// +/// For subloop blocks, simply update SubloopParents and return NULL. +Loop *UnloopUpdater::getNearestLoop(BasicBlock *BB, Loop *BBLoop) { + + // Initially for blocks directly contained by Unloop, NearLoop == Unloop and + // is considered uninitialized. + Loop *NearLoop = BBLoop; + + Loop *Subloop = 0; + if (NearLoop != Unloop && Unloop->contains(NearLoop)) { + Subloop = NearLoop; + // Find the subloop ancestor that is directly contained within Unloop. + while (Subloop->getParentLoop() != Unloop) { + Subloop = Subloop->getParentLoop(); + assert(Subloop && "subloop is not an ancestor of the original loop"); + } + // Get the current nearest parent of the Subloop exits, initially Unloop. + if (!SubloopParents.count(Subloop)) + SubloopParents[Subloop] = Unloop; + NearLoop = SubloopParents[Subloop]; + } + + succ_iterator I = succ_begin(BB), E = succ_end(BB); + if (I == E) { + assert(!Subloop && "subloop blocks must have a successor"); + NearLoop = 0; // unloop blocks may now exit the function. + } + for (; I != E; ++I) { + if (*I == BB) + continue; // self loops are uninteresting + + Loop *L = LI->getLoopFor(*I); + if (L == Unloop) { + // This successor has not been processed. This path must lead to an + // irreducible backedge. + assert((FoundIB || !DFS.hasPostorder(*I)) && "should have seen IB"); + FoundIB = true; + } + if (L != Unloop && Unloop->contains(L)) { + // Successor is in a subloop. + if (Subloop) + continue; // Branching within subloops. Ignore it. + + // BB branches from the original into a subloop header. + assert(L->getParentLoop() == Unloop && "cannot skip into nested loops"); + + // Get the current nearest parent of the Subloop's exits. + L = SubloopParents[L]; + // L could be Unloop if the only exit was an irreducible backedge. + } + if (L == Unloop) { + continue; + } + // Handle critical edges from Unloop into a sibling loop. + if (L && !L->contains(Unloop)) { + L = L->getParentLoop(); + } + // Remember the nearest parent loop among successors or subloop exits. + if (NearLoop == Unloop || !NearLoop || NearLoop->contains(L)) + NearLoop = L; + } + if (Subloop) { + SubloopParents[Subloop] = NearLoop; + return BBLoop; + } + return NearLoop; +} + //===----------------------------------------------------------------------===// // LoopInfo implementation // @@ -391,6 +594,68 @@ bool LoopInfo::runOnFunction(Function &) { return false; } +/// updateUnloop - The last backedge has been removed from a loop--now the +/// "unloop". Find a new parent for the blocks contained within unloop and +/// update the loop tree. We don't necessarily have valid dominators at this +/// point, but LoopInfo is still valid except for the removal of this loop. +/// +/// Note that Unloop may now be an empty loop. Calling Loop::getHeader without +/// checking first is illegal. +void LoopInfo::updateUnloop(Loop *Unloop) { + + // First handle the special case of no parent loop to simplify the algorithm. + if (!Unloop->getParentLoop()) { + // Since BBLoop had no parent, Unloop blocks are no longer in a loop. + for (Loop::block_iterator I = Unloop->block_begin(), + E = Unloop->block_end(); I != E; ++I) { + + // Don't reparent blocks in subloops. + if (getLoopFor(*I) != Unloop) + continue; + + // Blocks no longer have a parent but are still referenced by Unloop until + // the Unloop object is deleted. + LI.changeLoopFor(*I, 0); + } + + // Remove the loop from the top-level LoopInfo object. + for (LoopInfo::iterator I = LI.begin();; ++I) { + assert(I != LI.end() && "Couldn't find loop"); + if (*I == Unloop) { + LI.removeLoop(I); + break; + } + } + + // Move all of the subloops to the top-level. + while (!Unloop->empty()) + LI.addTopLevelLoop(Unloop->removeChildLoop(llvm::prior(Unloop->end()))); + + return; + } + + // Update the parent loop for all blocks within the loop. Blocks within + // subloops will not change parents. + UnloopUpdater Updater(Unloop, this); + Updater.updateBlockParents(); + + // Remove blocks from former ancestor loops. + Updater.removeBlocksFromAncestors(); + + // Add direct subloops as children in their new parent loop. + Updater.updateSubloopParents(); + + // Remove unloop from its parent loop. + Loop *ParentLoop = Unloop->getParentLoop(); + for (Loop::iterator I = ParentLoop->begin();; ++I) { + assert(I != ParentLoop->end() && "Couldn't find loop"); + if (*I == Unloop) { + ParentLoop->removeChildLoop(I); + break; + } + } +} + void LoopInfo::verifyAnalysis() const { // LoopInfo is a FunctionPass, but verifying every loop in the function // each time verifyAnalysis is called is very expensive. The @@ -400,12 +665,21 @@ void LoopInfo::verifyAnalysis() const { if (!VerifyLoopInfo) return; + DenseSet Loops; for (iterator I = begin(), E = end(); I != E; ++I) { assert(!(*I)->getParentLoop() && "Top-level loop has a parent!"); - (*I)->verifyLoopNest(); + (*I)->verifyLoopNest(&Loops); } - // TODO: check BBMap consistency. + // Verify that blocks are mapped to valid loops. + // + // FIXME: With an up-to-date DFS (see LoopIterator.h) and DominatorTree, we + // could also verify that the blocks are still in the correct loops. + for (DenseMap::const_iterator I = LI.BBMap.begin(), + E = LI.BBMap.end(); I != E; ++I) { + assert(Loops.count(I->second) && "orphaned loop"); + assert(I->second->contains(I->first) && "orphaned block"); + } } void LoopInfo::getAnalysisUsage(AnalysisUsage &AU) const { @@ -417,3 +691,15 @@ void LoopInfo::print(raw_ostream &OS, const Module*) const { LI.print(OS); } +//===----------------------------------------------------------------------===// +// LoopBlocksDFS implementation +// + +/// Traverse the loop blocks and store the DFS result. +/// Useful for clients that just want the final DFS result and don't need to +/// visit blocks during the initial traversal. +void LoopBlocksDFS::perform(LoopInfo *LI) { + LoopBlocksTraversal Traversal(*this, LI); + for (LoopBlocksTraversal::POTIterator POI = Traversal.begin(), + POE = Traversal.end(); POI != POE; ++POI) ; +} diff --git a/contrib/llvm/lib/Analysis/LoopPass.cpp b/contrib/llvm/lib/Analysis/LoopPass.cpp index 10e3f297f..5ba1f4045 100644 --- a/contrib/llvm/lib/Analysis/LoopPass.cpp +++ b/contrib/llvm/lib/Analysis/LoopPass.cpp @@ -59,9 +59,9 @@ char PrintLoopPass::ID = 0; static DebugInfoProbeInfo *TheDebugProbe; static void createDebugInfoProbe() { if (TheDebugProbe) return; - - // Constructed the first time this is called. This guarantees that the - // object will be constructed, if -enable-debug-info-probe is set, + + // Constructed the first time this is called. This guarantees that the + // object will be constructed, if -enable-debug-info-probe is set, // before static globals, thus it will be destroyed before them. static ManagedStatic DIP; TheDebugProbe = &*DIP; @@ -73,73 +73,29 @@ static void createDebugInfoProbe() { char LPPassManager::ID = 0; -LPPassManager::LPPassManager(int Depth) - : FunctionPass(ID), PMDataManager(Depth) { +LPPassManager::LPPassManager() + : FunctionPass(ID), PMDataManager() { skipThisLoop = false; redoThisLoop = false; LI = NULL; CurrentLoop = NULL; } -/// Delete loop from the loop queue and loop hierarchy (LoopInfo). +/// Delete loop from the loop queue and loop hierarchy (LoopInfo). void LPPassManager::deleteLoopFromQueue(Loop *L) { - if (Loop *ParentLoop = L->getParentLoop()) { // Not a top-level loop. - // Reparent all of the blocks in this loop. Since BBLoop had a parent, - // they are now all in it. - for (Loop::block_iterator I = L->block_begin(), E = L->block_end(); - I != E; ++I) - if (LI->getLoopFor(*I) == L) // Don't change blocks in subloops. - LI->changeLoopFor(*I, ParentLoop); - - // Remove the loop from its parent loop. - for (Loop::iterator I = ParentLoop->begin(), E = ParentLoop->end();; - ++I) { - assert(I != E && "Couldn't find loop"); - if (*I == L) { - ParentLoop->removeChildLoop(I); - break; - } - } - - // Move all subloops into the parent loop. - while (!L->empty()) - ParentLoop->addChildLoop(L->removeChildLoop(L->end()-1)); - } else { - // Reparent all of the blocks in this loop. Since BBLoop had no parent, - // they no longer in a loop at all. - - for (unsigned i = 0; i != L->getBlocks().size(); ++i) { - // Don't change blocks in subloops. - if (LI->getLoopFor(L->getBlocks()[i]) == L) { - LI->removeBlock(L->getBlocks()[i]); - --i; - } - } - - // Remove the loop from the top-level LoopInfo object. - for (LoopInfo::iterator I = LI->begin(), E = LI->end();; ++I) { - assert(I != E && "Couldn't find loop"); - if (*I == L) { - LI->removeLoop(I); - break; - } - } - - // Move all of the subloops to the top-level. - while (!L->empty()) - LI->addTopLevelLoop(L->removeChildLoop(L->end()-1)); - } - - delete L; + LI->updateUnloop(L); // If L is current loop then skip rest of the passes and let // runOnFunction remove L from LQ. Otherwise, remove L from LQ now // and continue applying other passes on CurrentLoop. - if (CurrentLoop == L) { + if (CurrentLoop == L) skipThisLoop = true; + + delete L; + + if (skipThisLoop) return; - } for (std::deque::iterator I = LQ.begin(), E = LQ.end(); I != E; ++I) { @@ -166,10 +122,10 @@ void LPPassManager::insertLoop(Loop *L, Loop *ParentLoop) { void LPPassManager::insertLoopIntoQueue(Loop *L) { // Insert L into loop queue - if (L == CurrentLoop) + if (L == CurrentLoop) redoLoop(L); else if (!L->getParentLoop()) - // This is top level loop. + // This is top level loop. LQ.push_front(L); else { // Insert L after the parent loop. @@ -195,9 +151,9 @@ void LPPassManager::redoLoop(Loop *L) { /// cloneBasicBlockSimpleAnalysis - Invoke cloneBasicBlockAnalysis hook for /// all loop passes. -void LPPassManager::cloneBasicBlockSimpleAnalysis(BasicBlock *From, +void LPPassManager::cloneBasicBlockSimpleAnalysis(BasicBlock *From, BasicBlock *To, Loop *L) { - for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) { + for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) { LoopPass *LP = getContainedPass(Index); LP->cloneBasicBlockAnalysis(From, To, L); } @@ -206,13 +162,13 @@ void LPPassManager::cloneBasicBlockSimpleAnalysis(BasicBlock *From, /// deleteSimpleAnalysisValue - Invoke deleteAnalysisValue hook for all passes. void LPPassManager::deleteSimpleAnalysisValue(Value *V, Loop *L) { if (BasicBlock *BB = dyn_cast(V)) { - for (BasicBlock::iterator BI = BB->begin(), BE = BB->end(); BI != BE; + for (BasicBlock::iterator BI = BB->begin(), BE = BB->end(); BI != BE; ++BI) { Instruction &I = *BI; deleteSimpleAnalysisValue(&I, L); } } - for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) { + for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) { LoopPass *LP = getContainedPass(Index); LP->deleteAnalysisValue(V, L); } @@ -228,7 +184,7 @@ static void addLoopIntoQueue(Loop *L, std::deque &LQ) { /// Pass Manager itself does not invalidate any analysis info. void LPPassManager::getAnalysisUsage(AnalysisUsage &Info) const { - // LPPassManager needs LoopInfo. In the long term LoopInfo class will + // LPPassManager needs LoopInfo. In the long term LoopInfo class will // become part of LPPassManager. Info.addRequired(); Info.setPreservesAll(); @@ -255,7 +211,7 @@ bool LPPassManager::runOnFunction(Function &F) { for (std::deque::const_iterator I = LQ.begin(), E = LQ.end(); I != E; ++I) { Loop *L = *I; - for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) { + for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) { LoopPass *P = getContainedPass(Index); Changed |= P->doInitialization(L, *this); } @@ -263,13 +219,13 @@ bool LPPassManager::runOnFunction(Function &F) { // Walk Loops while (!LQ.empty()) { - + CurrentLoop = LQ.back(); skipThisLoop = false; redoThisLoop = false; // Run all passes on the current Loop. - for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) { + for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) { LoopPass *P = getContainedPass(Index); dumpPassInfo(P, EXECUTION_MSG, ON_LOOP_MSG, CurrentLoop->getHeader()->getName()); @@ -319,23 +275,23 @@ bool LPPassManager::runOnFunction(Function &F) { // Do not run other passes on this loop. break; } - + // If the loop was deleted, release all the loop passes. This frees up // some memory, and avoids trouble with the pass manager trying to call // verifyAnalysis on them. if (skipThisLoop) - for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) { + for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) { Pass *P = getContainedPass(Index); freePass(P, "", ON_LOOP_MSG); } // Pop the loop from queue after running all passes. LQ.pop_back(); - + if (redoThisLoop) LQ.push_back(CurrentLoop); } - + // Finalization for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) { LoopPass *P = getContainedPass(Index); @@ -372,7 +328,7 @@ Pass *LoopPass::createPrinterPass(raw_ostream &O, // LPPassManger as expected. void LoopPass::preparePassManager(PMStack &PMS) { - // Find LPPassManager + // Find LPPassManager while (!PMS.empty() && PMS.top()->getPassManagerType() > PMT_LoopPassManager) PMS.pop(); @@ -381,14 +337,14 @@ void LoopPass::preparePassManager(PMStack &PMS) { // by other passes that are managed by LPM then do not insert // this pass in current LPM. Use new LPPassManager. if (PMS.top()->getPassManagerType() == PMT_LoopPassManager && - !PMS.top()->preserveHigherLevelAnalysis(this)) + !PMS.top()->preserveHigherLevelAnalysis(this)) PMS.pop(); } /// Assign pass manager to manage this pass. void LoopPass::assignPassManager(PMStack &PMS, PassManagerType PreferredType) { - // Find LPPassManager + // Find LPPassManager while (!PMS.empty() && PMS.top()->getPassManagerType() > PMT_LoopPassManager) PMS.pop(); @@ -397,12 +353,12 @@ void LoopPass::assignPassManager(PMStack &PMS, if (PMS.top()->getPassManagerType() == PMT_LoopPassManager) LPPM = (LPPassManager*)PMS.top(); else { - // Create new Loop Pass Manager if it does not exist. + // Create new Loop Pass Manager if it does not exist. assert (!PMS.empty() && "Unable to create Loop Pass Manager"); PMDataManager *PMD = PMS.top(); - // [1] Create new Call Graph Pass Manager - LPPM = new LPPassManager(PMD->getDepth() + 1); + // [1] Create new Loop Pass Manager + LPPM = new LPPassManager(); LPPM->populateInheritedAnalysis(PMS); // [2] Set up new manager's top level manager diff --git a/contrib/llvm/lib/Analysis/MemDepPrinter.cpp b/contrib/llvm/lib/Analysis/MemDepPrinter.cpp index 2283db0bc..fde07ea4f 100644 --- a/contrib/llvm/lib/Analysis/MemDepPrinter.cpp +++ b/contrib/llvm/lib/Analysis/MemDepPrinter.cpp @@ -25,8 +25,17 @@ namespace { struct MemDepPrinter : public FunctionPass { const Function *F; - typedef PointerIntPair InstAndClobberFlag; - typedef std::pair Dep; + enum DepType { + Clobber = 0, + Def, + NonFuncLocal, + Unknown + }; + + static const char* DepTypeStr[]; + + typedef PointerIntPair InstTypePair; + typedef std::pair Dep; typedef SmallSetVector DepSet; typedef DenseMap DepSetMap; DepSetMap Deps; @@ -50,6 +59,21 @@ namespace { Deps.clear(); F = 0; } + + private: + static InstTypePair getInstTypePair(MemDepResult dep) { + if (dep.isClobber()) + return InstTypePair(dep.getInst(), Clobber); + if (dep.isDef()) + return InstTypePair(dep.getInst(), Def); + if (dep.isNonFuncLocal()) + return InstTypePair(dep.getInst(), NonFuncLocal); + assert(dep.isUnknown() && "unexptected dependence type"); + return InstTypePair(dep.getInst(), Unknown); + } + static InstTypePair getInstTypePair(const Instruction* inst, DepType type) { + return InstTypePair(inst, type); + } }; } @@ -64,6 +88,9 @@ FunctionPass *llvm::createMemDepPrinter() { return new MemDepPrinter(); } +const char* MemDepPrinter::DepTypeStr[] + = {"Clobber", "Def", "NonFuncLocal", "Unknown"}; + bool MemDepPrinter::runOnFunction(Function &F) { this->F = &F; AliasAnalysis &AA = getAnalysis(); @@ -79,10 +106,7 @@ bool MemDepPrinter::runOnFunction(Function &F) { MemDepResult Res = MDA.getDependency(Inst); if (!Res.isNonLocal()) { - assert((Res.isUnknown() || Res.isClobber() || Res.isDef()) && - "Local dep should be unknown, def or clobber!"); - Deps[Inst].insert(std::make_pair(InstAndClobberFlag(Res.getInst(), - Res.isClobber()), + Deps[Inst].insert(std::make_pair(getInstTypePair(Res), static_cast(0))); } else if (CallSite CS = cast(Inst)) { const MemoryDependenceAnalysis::NonLocalDepInfo &NLDI = @@ -92,22 +116,26 @@ bool MemDepPrinter::runOnFunction(Function &F) { for (MemoryDependenceAnalysis::NonLocalDepInfo::const_iterator I = NLDI.begin(), E = NLDI.end(); I != E; ++I) { const MemDepResult &Res = I->getResult(); - assert((Res.isUnknown() || Res.isClobber() || Res.isDef()) && - "Resolved non-local call dep should be unknown, def or " - "clobber!"); - InstDeps.insert(std::make_pair(InstAndClobberFlag(Res.getInst(), - Res.isClobber()), - I->getBB())); + InstDeps.insert(std::make_pair(getInstTypePair(Res), I->getBB())); } } else { SmallVector NLDI; if (LoadInst *LI = dyn_cast(Inst)) { - // FIXME: Volatile is not handled properly here. + if (!LI->isUnordered()) { + // FIXME: Handle atomic/volatile loads. + Deps[Inst].insert(std::make_pair(getInstTypePair(0, Unknown), + static_cast(0))); + continue; + } AliasAnalysis::Location Loc = AA.getLocation(LI); - MDA.getNonLocalPointerDependency(Loc, !LI->isVolatile(), - LI->getParent(), NLDI); + MDA.getNonLocalPointerDependency(Loc, true, LI->getParent(), NLDI); } else if (StoreInst *SI = dyn_cast(Inst)) { - // FIXME: Volatile is not handled properly here. + if (!LI->isUnordered()) { + // FIXME: Handle atomic/volatile stores. + Deps[Inst].insert(std::make_pair(getInstTypePair(0, Unknown), + static_cast(0))); + continue; + } AliasAnalysis::Location Loc = AA.getLocation(SI); MDA.getNonLocalPointerDependency(Loc, false, SI->getParent(), NLDI); } else if (VAArgInst *VI = dyn_cast(Inst)) { @@ -121,11 +149,7 @@ bool MemDepPrinter::runOnFunction(Function &F) { for (SmallVectorImpl::const_iterator I = NLDI.begin(), E = NLDI.end(); I != E; ++I) { const MemDepResult &Res = I->getResult(); - assert(Res.isClobber() != Res.isDef() && - "Resolved non-local pointer dep should be def or clobber!"); - InstDeps.insert(std::make_pair(InstAndClobberFlag(Res.getInst(), - Res.isClobber()), - I->getBB())); + InstDeps.insert(std::make_pair(getInstTypePair(Res), I->getBB())); } } } @@ -146,26 +170,18 @@ void MemDepPrinter::print(raw_ostream &OS, const Module *M) const { for (DepSet::const_iterator I = InstDeps.begin(), E = InstDeps.end(); I != E; ++I) { const Instruction *DepInst = I->first.getPointer(); - bool isClobber = I->first.getInt(); + DepType type = I->first.getInt(); const BasicBlock *DepBB = I->second; OS << " "; - if (!DepInst) - OS << "Unknown"; - else if (isClobber) - OS << "Clobber"; - else - OS << " Def"; + OS << DepTypeStr[type]; if (DepBB) { OS << " in block "; WriteAsOperand(OS, DepBB, /*PrintType=*/false, M); } if (DepInst) { OS << " from: "; - if (DepInst == Inst) - OS << ""; - else - DepInst->print(OS); + DepInst->print(OS); } OS << "\n"; } diff --git a/contrib/llvm/lib/Analysis/MemoryBuiltins.cpp b/contrib/llvm/lib/Analysis/MemoryBuiltins.cpp index 53d430491..8d451c46f 100644 --- a/contrib/llvm/lib/Analysis/MemoryBuiltins.cpp +++ b/contrib/llvm/lib/Analysis/MemoryBuiltins.cpp @@ -47,7 +47,7 @@ static bool isMallocCall(const CallInst *CI) { // Check malloc prototype. // FIXME: workaround for PR5130, this will be obsolete when a nobuiltin // attribute will exist. - const FunctionType *FTy = Callee->getFunctionType(); + FunctionType *FTy = Callee->getFunctionType(); if (FTy->getNumParams() != 1) return false; return FTy->getParamType(0)->isIntegerTy(32) || @@ -94,12 +94,12 @@ static Value *computeArraySize(const CallInst *CI, const TargetData *TD, return NULL; // The size of the malloc's result type must be known to determine array size. - const Type *T = getMallocAllocatedType(CI); + Type *T = getMallocAllocatedType(CI); if (!T || !T->isSized() || !TD) return NULL; unsigned ElementSize = TD->getTypeAllocSize(T); - if (const StructType *ST = dyn_cast(T)) + if (StructType *ST = dyn_cast(T)) ElementSize = TD->getStructLayout(ST)->getSizeInBytes(); // If malloc call's arg can be determined to be a multiple of ElementSize, @@ -133,10 +133,10 @@ const CallInst *llvm::isArrayMalloc(const Value *I, const TargetData *TD) { /// 0: PointerType is the calls' return type. /// 1: PointerType is the bitcast's result type. /// >1: Unique PointerType cannot be determined, return NULL. -const PointerType *llvm::getMallocType(const CallInst *CI) { +PointerType *llvm::getMallocType(const CallInst *CI) { assert(isMalloc(CI) && "getMallocType and not malloc call"); - const PointerType *MallocType = NULL; + PointerType *MallocType = NULL; unsigned NumOfBitCastUses = 0; // Determine if CallInst has a bitcast use. @@ -164,8 +164,8 @@ const PointerType *llvm::getMallocType(const CallInst *CI) { /// 0: PointerType is the malloc calls' return type. /// 1: PointerType is the bitcast's result type. /// >1: Unique PointerType cannot be determined, return NULL. -const Type *llvm::getMallocAllocatedType(const CallInst *CI) { - const PointerType *PT = getMallocType(CI); +Type *llvm::getMallocAllocatedType(const CallInst *CI) { + PointerType *PT = getMallocType(CI); return PT ? PT->getElementType() : NULL; } @@ -201,7 +201,7 @@ const CallInst *llvm::isFreeCall(const Value *I) { // Check free prototype. // FIXME: workaround for PR5130, this will be obsolete when a nobuiltin // attribute will exist. - const FunctionType *FTy = Callee->getFunctionType(); + FunctionType *FTy = Callee->getFunctionType(); if (!FTy->getReturnType()->isVoidTy()) return 0; if (FTy->getNumParams() != 1) diff --git a/contrib/llvm/lib/Analysis/MemoryDependenceAnalysis.cpp b/contrib/llvm/lib/Analysis/MemoryDependenceAnalysis.cpp index bba4482f4..92967c08d 100644 --- a/contrib/llvm/lib/Analysis/MemoryDependenceAnalysis.cpp +++ b/contrib/llvm/lib/Analysis/MemoryDependenceAnalysis.cpp @@ -120,21 +120,27 @@ AliasAnalysis::ModRefResult GetLocation(const Instruction *Inst, AliasAnalysis::Location &Loc, AliasAnalysis *AA) { if (const LoadInst *LI = dyn_cast(Inst)) { - if (LI->isVolatile()) { - Loc = AliasAnalysis::Location(); + if (LI->isUnordered()) { + Loc = AA->getLocation(LI); + return AliasAnalysis::Ref; + } else if (LI->getOrdering() == Monotonic) { + Loc = AA->getLocation(LI); return AliasAnalysis::ModRef; } - Loc = AA->getLocation(LI); - return AliasAnalysis::Ref; + Loc = AliasAnalysis::Location(); + return AliasAnalysis::ModRef; } if (const StoreInst *SI = dyn_cast(Inst)) { - if (SI->isVolatile()) { - Loc = AliasAnalysis::Location(); + if (SI->isUnordered()) { + Loc = AA->getLocation(SI); + return AliasAnalysis::Mod; + } else if (SI->getOrdering() == Monotonic) { + Loc = AA->getLocation(SI); return AliasAnalysis::ModRef; } - Loc = AA->getLocation(SI); - return AliasAnalysis::Mod; + Loc = AliasAnalysis::Location(); + return AliasAnalysis::ModRef; } if (const VAArgInst *V = dyn_cast(Inst)) { @@ -232,7 +238,7 @@ getCallSiteDependencyFrom(CallSite CS, bool isReadOnlyCall, // unknown, otherwise it is non-local. if (BB != &BB->getParent()->getEntryBlock()) return MemDepResult::getNonLocal(); - return MemDepResult::getUnknown(); + return MemDepResult::getNonFuncLocal(); } /// isLoadLoadClobberIfExtendedToFullWidth - Return true if LI is a load that @@ -270,8 +276,8 @@ unsigned MemoryDependenceAnalysis:: getLoadLoadClobberFullWidthSize(const Value *MemLocBase, int64_t MemLocOffs, unsigned MemLocSize, const LoadInst *LI, const TargetData &TD) { - // We can only extend non-volatile integer loads. - if (!isa(LI->getType()) || LI->isVolatile()) return 0; + // We can only extend simple integer loads. + if (!isa(LI->getType()) || !LI->isSimple()) return 0; // Get the base of this load. int64_t LIOffs = 0; @@ -369,6 +375,11 @@ getPointerDependencyFrom(const AliasAnalysis::Location &MemLoc, bool isLoad, // Values depend on loads if the pointers are must aliased. This means that // a load depends on another must aliased load from the same value. if (LoadInst *LI = dyn_cast(Inst)) { + // Atomic loads have complications involved. + // FIXME: This is overly conservative. + if (!LI->isUnordered()) + return MemDepResult::getClobber(LI); + AliasAnalysis::Location LoadLoc = AA->getLocation(LI); // If we found a pointer, check if it could be the same as our pointer. @@ -382,7 +393,7 @@ getPointerDependencyFrom(const AliasAnalysis::Location &MemLoc, bool isLoad, // location is 1 byte at P+1). If so, return it as a load/load // clobber result, allowing the client to decide to widen the load if // it wants to. - if (const IntegerType *ITy = dyn_cast(LI->getType())) + if (IntegerType *ITy = dyn_cast(LI->getType())) if (LI->getAlignment()*8 > ITy->getPrimitiveSizeInBits() && isLoadLoadClobberIfExtendedToFullWidth(MemLoc, MemLocBase, MemLocOffset, LI, TD)) @@ -424,6 +435,11 @@ getPointerDependencyFrom(const AliasAnalysis::Location &MemLoc, bool isLoad, } if (StoreInst *SI = dyn_cast(Inst)) { + // Atomic stores have complications involved. + // FIXME: This is overly conservative. + if (!SI->isUnordered()) + return MemDepResult::getClobber(SI); + // If alias analysis can tell that this store is guaranteed to not modify // the query pointer, ignore it. Use getModRefInfo to handle cases where // the query pointer points to constant memory etc. @@ -483,7 +499,7 @@ getPointerDependencyFrom(const AliasAnalysis::Location &MemLoc, bool isLoad, // unknown, otherwise it is non-local. if (BB != &BB->getParent()->getEntryBlock()) return MemDepResult::getNonLocal(); - return MemDepResult::getUnknown(); + return MemDepResult::getNonFuncLocal(); } /// getDependency - Return the instruction on which a memory operation @@ -516,7 +532,7 @@ MemDepResult MemoryDependenceAnalysis::getDependency(Instruction *QueryInst) { if (QueryParent != &QueryParent->getParent()->getEntryBlock()) LocalCache = MemDepResult::getNonLocal(); else - LocalCache = MemDepResult::getUnknown(); + LocalCache = MemDepResult::getNonFuncLocal(); } else { AliasAnalysis::Location MemLoc; AliasAnalysis::ModRefResult MR = GetLocation(QueryInst, MemLoc, AA); @@ -672,7 +688,7 @@ MemoryDependenceAnalysis::getNonLocalCallDependency(CallSite QueryCS) { // a clobber, otherwise it is unknown. Dep = MemDepResult::getNonLocal(); } else { - Dep = MemDepResult::getUnknown(); + Dep = MemDepResult::getNonFuncLocal(); } // If we had a dirty entry for the block, update it. Otherwise, just add @@ -790,7 +806,7 @@ GetNonLocalInfoForBlock(const AliasAnalysis::Location &Loc, // If the block has a dependency (i.e. it isn't completely transparent to // the value), remember the reverse association because we just added it // to Cache! - if (Dep.isNonLocal() || Dep.isUnknown()) + if (!Dep.isDef() && !Dep.isClobber()) return Dep; // Keep the ReverseNonLocalPtrDeps map up to date so we can efficiently diff --git a/contrib/llvm/lib/Analysis/PHITransAddr.cpp b/contrib/llvm/lib/Analysis/PHITransAddr.cpp index 70dcd0df2..7e22ddc61 100644 --- a/contrib/llvm/lib/Analysis/PHITransAddr.cpp +++ b/contrib/llvm/lib/Analysis/PHITransAddr.cpp @@ -228,7 +228,7 @@ Value *PHITransAddr::PHITranslateSubExpr(Value *V, BasicBlock *CurBB, return GEP; // Simplify the GEP to handle 'gep x, 0' -> x etc. - if (Value *V = SimplifyGEPInst(&GEPOps[0], GEPOps.size(), TD, DT)) { + if (Value *V = SimplifyGEPInst(GEPOps, TD, DT)) { for (unsigned i = 0, e = GEPOps.size(); i != e; ++i) RemoveInstInputs(GEPOps[i], InstInputs); @@ -407,9 +407,9 @@ InsertPHITranslatedSubExpr(Value *InVal, BasicBlock *CurBB, } GetElementPtrInst *Result = - GetElementPtrInst::Create(GEPOps[0], GEPOps.begin()+1, GEPOps.end(), - InVal->getName()+".phi.trans.insert", - PredBB->getTerminator()); + GetElementPtrInst::Create(GEPOps[0], makeArrayRef(GEPOps).slice(1), + InVal->getName()+".phi.trans.insert", + PredBB->getTerminator()); Result->setIsInBounds(GEP->isInBounds()); NewInsts.push_back(Result); return Result; diff --git a/contrib/llvm/lib/Analysis/PathNumbering.cpp b/contrib/llvm/lib/Analysis/PathNumbering.cpp index 7c584daef..0e3b6e69c 100644 --- a/contrib/llvm/lib/Analysis/PathNumbering.cpp +++ b/contrib/llvm/lib/Analysis/PathNumbering.cpp @@ -387,7 +387,7 @@ void BallLarusDag::buildNode(BLBlockNodeMap& inDag, BLNodeStack& dfsStack) { TerminatorInst* terminator = currentNode->getBlock()->getTerminator(); if(isa(terminator) || isa(terminator) - || isa(terminator)) + || isa(terminator) || isa(terminator)) addEdge(currentNode, getExit(),0); currentNode->setColor(BallLarusNode::GRAY); diff --git a/contrib/llvm/lib/Analysis/RegionPass.cpp b/contrib/llvm/lib/Analysis/RegionPass.cpp index 80eda79d8..3a3529baf 100644 --- a/contrib/llvm/lib/Analysis/RegionPass.cpp +++ b/contrib/llvm/lib/Analysis/RegionPass.cpp @@ -27,8 +27,8 @@ using namespace llvm; char RGPassManager::ID = 0; -RGPassManager::RGPassManager(int Depth) - : FunctionPass(ID), PMDataManager(Depth) { +RGPassManager::RGPassManager() + : FunctionPass(ID), PMDataManager() { skipThisRegion = false; redoThisRegion = false; RI = NULL; @@ -250,7 +250,7 @@ void RegionPass::assignPassManager(PMStack &PMS, PMDataManager *PMD = PMS.top(); // [1] Create new Region Pass Manager - RGPM = new RGPassManager(PMD->getDepth() + 1); + RGPM = new RGPassManager(); RGPM->populateInheritedAnalysis(PMS); // [2] Set up new manager's top level manager diff --git a/contrib/llvm/lib/Analysis/ScalarEvolution.cpp b/contrib/llvm/lib/Analysis/ScalarEvolution.cpp index 025718e09..e0ac56c65 100644 --- a/contrib/llvm/lib/Analysis/ScalarEvolution.cpp +++ b/contrib/llvm/lib/Analysis/ScalarEvolution.cpp @@ -197,7 +197,7 @@ void SCEV::print(raw_ostream &OS) const { } case scUnknown: { const SCEVUnknown *U = cast(this); - const Type *AllocTy; + Type *AllocTy; if (U->isSizeOf(AllocTy)) { OS << "sizeof(" << *AllocTy << ")"; return; @@ -207,7 +207,7 @@ void SCEV::print(raw_ostream &OS) const { return; } - const Type *CTy; + Type *CTy; Constant *FieldNo; if (U->isOffsetOf(CTy, FieldNo)) { OS << "offsetof(" << *CTy << ", "; @@ -228,7 +228,7 @@ void SCEV::print(raw_ostream &OS) const { llvm_unreachable("Unknown SCEV kind!"); } -const Type *SCEV::getType() const { +Type *SCEV::getType() const { switch (getSCEVType()) { case scConstant: return cast(this)->getType(); @@ -297,17 +297,17 @@ const SCEV *ScalarEvolution::getConstant(const APInt& Val) { } const SCEV * -ScalarEvolution::getConstant(const Type *Ty, uint64_t V, bool isSigned) { - const IntegerType *ITy = cast(getEffectiveSCEVType(Ty)); +ScalarEvolution::getConstant(Type *Ty, uint64_t V, bool isSigned) { + IntegerType *ITy = cast(getEffectiveSCEVType(Ty)); return getConstant(ConstantInt::get(ITy, V, isSigned)); } SCEVCastExpr::SCEVCastExpr(const FoldingSetNodeIDRef ID, - unsigned SCEVTy, const SCEV *op, const Type *ty) + unsigned SCEVTy, const SCEV *op, Type *ty) : SCEV(ID, SCEVTy), Op(op), Ty(ty) {} SCEVTruncateExpr::SCEVTruncateExpr(const FoldingSetNodeIDRef ID, - const SCEV *op, const Type *ty) + const SCEV *op, Type *ty) : SCEVCastExpr(ID, scTruncate, op, ty) { assert((Op->getType()->isIntegerTy() || Op->getType()->isPointerTy()) && (Ty->isIntegerTy() || Ty->isPointerTy()) && @@ -315,7 +315,7 @@ SCEVTruncateExpr::SCEVTruncateExpr(const FoldingSetNodeIDRef ID, } SCEVZeroExtendExpr::SCEVZeroExtendExpr(const FoldingSetNodeIDRef ID, - const SCEV *op, const Type *ty) + const SCEV *op, Type *ty) : SCEVCastExpr(ID, scZeroExtend, op, ty) { assert((Op->getType()->isIntegerTy() || Op->getType()->isPointerTy()) && (Ty->isIntegerTy() || Ty->isPointerTy()) && @@ -323,7 +323,7 @@ SCEVZeroExtendExpr::SCEVZeroExtendExpr(const FoldingSetNodeIDRef ID, } SCEVSignExtendExpr::SCEVSignExtendExpr(const FoldingSetNodeIDRef ID, - const SCEV *op, const Type *ty) + const SCEV *op, Type *ty) : SCEVCastExpr(ID, scSignExtend, op, ty) { assert((Op->getType()->isIntegerTy() || Op->getType()->isPointerTy()) && (Ty->isIntegerTy() || Ty->isPointerTy()) && @@ -354,7 +354,7 @@ void SCEVUnknown::allUsesReplacedWith(Value *New) { setValPtr(New); } -bool SCEVUnknown::isSizeOf(const Type *&AllocTy) const { +bool SCEVUnknown::isSizeOf(Type *&AllocTy) const { if (ConstantExpr *VCE = dyn_cast(getValue())) if (VCE->getOpcode() == Instruction::PtrToInt) if (ConstantExpr *CE = dyn_cast(VCE->getOperand(0))) @@ -371,15 +371,15 @@ bool SCEVUnknown::isSizeOf(const Type *&AllocTy) const { return false; } -bool SCEVUnknown::isAlignOf(const Type *&AllocTy) const { +bool SCEVUnknown::isAlignOf(Type *&AllocTy) const { if (ConstantExpr *VCE = dyn_cast(getValue())) if (VCE->getOpcode() == Instruction::PtrToInt) if (ConstantExpr *CE = dyn_cast(VCE->getOperand(0))) if (CE->getOpcode() == Instruction::GetElementPtr && CE->getOperand(0)->isNullValue()) { - const Type *Ty = + Type *Ty = cast(CE->getOperand(0)->getType())->getElementType(); - if (const StructType *STy = dyn_cast(Ty)) + if (StructType *STy = dyn_cast(Ty)) if (!STy->isPacked() && CE->getNumOperands() == 3 && CE->getOperand(1)->isNullValue()) { @@ -396,7 +396,7 @@ bool SCEVUnknown::isAlignOf(const Type *&AllocTy) const { return false; } -bool SCEVUnknown::isOffsetOf(const Type *&CTy, Constant *&FieldNo) const { +bool SCEVUnknown::isOffsetOf(Type *&CTy, Constant *&FieldNo) const { if (ConstantExpr *VCE = dyn_cast(getValue())) if (VCE->getOpcode() == Instruction::PtrToInt) if (ConstantExpr *CE = dyn_cast(VCE->getOperand(0))) @@ -404,7 +404,7 @@ bool SCEVUnknown::isOffsetOf(const Type *&CTy, Constant *&FieldNo) const { CE->getNumOperands() == 3 && CE->getOperand(0)->isNullValue() && CE->getOperand(1)->isNullValue()) { - const Type *Ty = + Type *Ty = cast(CE->getOperand(0)->getType())->getElementType(); // Ignore vector types here so that ScalarEvolutionExpander doesn't // emit getelementptrs that index into vectors. @@ -652,7 +652,7 @@ static void GroupByComplexity(SmallVectorImpl &Ops, /// Assume, K > 0. static const SCEV *BinomialCoefficient(const SCEV *It, unsigned K, ScalarEvolution &SE, - const Type* ResultTy) { + Type *ResultTy) { // Handle the simplest case efficiently. if (K == 1) return SE.getTruncateOrZeroExtend(It, ResultTy); @@ -742,7 +742,7 @@ static const SCEV *BinomialCoefficient(const SCEV *It, unsigned K, MultiplyFactor = MultiplyFactor.trunc(W); // Calculate the product, at width T+W - const IntegerType *CalculationTy = IntegerType::get(SE.getContext(), + IntegerType *CalculationTy = IntegerType::get(SE.getContext(), CalculationBits); const SCEV *Dividend = SE.getTruncateOrZeroExtend(It, CalculationTy); for (unsigned i = 1; i != K; ++i) { @@ -790,7 +790,7 @@ const SCEV *SCEVAddRecExpr::evaluateAtIteration(const SCEV *It, //===----------------------------------------------------------------------===// const SCEV *ScalarEvolution::getTruncateExpr(const SCEV *Op, - const Type *Ty) { + Type *Ty) { assert(getTypeSizeInBits(Op->getType()) > getTypeSizeInBits(Ty) && "This is not a truncating conversion!"); assert(isSCEVable(Ty) && @@ -877,7 +877,7 @@ const SCEV *ScalarEvolution::getTruncateExpr(const SCEV *Op, } const SCEV *ScalarEvolution::getZeroExtendExpr(const SCEV *Op, - const Type *Ty) { + Type *Ty) { assert(getTypeSizeInBits(Op->getType()) < getTypeSizeInBits(Ty) && "This is not an extending conversion!"); assert(isSCEVable(Ty) && @@ -954,7 +954,7 @@ const SCEV *ScalarEvolution::getZeroExtendExpr(const SCEV *Op, const SCEV *RecastedMaxBECount = getTruncateOrZeroExtend(CastedMaxBECount, MaxBECount->getType()); if (MaxBECount == RecastedMaxBECount) { - const Type *WideTy = IntegerType::get(getContext(), BitWidth * 2); + Type *WideTy = IntegerType::get(getContext(), BitWidth * 2); // Check whether Start+Step*MaxBECount has no unsigned overflow. const SCEV *ZMul = getMulExpr(CastedMaxBECount, Step); const SCEV *Add = getAddExpr(Start, ZMul); @@ -1062,7 +1062,7 @@ static const SCEV *getOverflowLimitForStep(const SCEV *Step, // result, the expression "Step + sext(PreIncAR)" is congruent with // "sext(PostIncAR)" static const SCEV *getPreStartForSignExtend(const SCEVAddRecExpr *AR, - const Type *Ty, + Type *Ty, ScalarEvolution *SE) { const Loop *L = AR->getLoop(); const SCEV *Start = AR->getStart(); @@ -1070,14 +1070,26 @@ static const SCEV *getPreStartForSignExtend(const SCEVAddRecExpr *AR, // Check for a simple looking step prior to loop entry. const SCEVAddExpr *SA = dyn_cast(Start); - if (!SA || SA->getNumOperands() != 2 || SA->getOperand(0) != Step) + if (!SA) + return 0; + + // Create an AddExpr for "PreStart" after subtracting Step. Full SCEV + // subtraction is expensive. For this purpose, perform a quick and dirty + // difference, by checking for Step in the operand list. + SmallVector DiffOps; + for (SCEVAddExpr::op_iterator I = SA->op_begin(), E = SA->op_end(); + I != E; ++I) { + if (*I != Step) + DiffOps.push_back(*I); + } + if (DiffOps.size() == SA->getNumOperands()) return 0; // This is a postinc AR. Check for overflow on the preinc recurrence using the // same three conditions that getSignExtendedExpr checks. // 1. NSW flags on the step increment. - const SCEV *PreStart = SA->getOperand(1); + const SCEV *PreStart = SE->getAddExpr(DiffOps, SA->getNoWrapFlags()); const SCEVAddRecExpr *PreAR = dyn_cast( SE->getAddRecExpr(PreStart, Step, L, SCEV::FlagAnyWrap)); @@ -1086,7 +1098,7 @@ static const SCEV *getPreStartForSignExtend(const SCEVAddRecExpr *AR, // 2. Direct overflow check on the step operation's expression. unsigned BitWidth = SE->getTypeSizeInBits(AR->getType()); - const Type *WideTy = IntegerType::get(SE->getContext(), BitWidth * 2); + Type *WideTy = IntegerType::get(SE->getContext(), BitWidth * 2); const SCEV *OperandExtendedStart = SE->getAddExpr(SE->getSignExtendExpr(PreStart, WideTy), SE->getSignExtendExpr(Step, WideTy)); @@ -1112,7 +1124,7 @@ static const SCEV *getPreStartForSignExtend(const SCEVAddRecExpr *AR, // Get the normalized sign-extended expression for this AddRec's Start. static const SCEV *getSignExtendAddRecStart(const SCEVAddRecExpr *AR, - const Type *Ty, + Type *Ty, ScalarEvolution *SE) { const SCEV *PreStart = getPreStartForSignExtend(AR, Ty, SE); if (!PreStart) @@ -1123,7 +1135,7 @@ static const SCEV *getSignExtendAddRecStart(const SCEVAddRecExpr *AR, } const SCEV *ScalarEvolution::getSignExtendExpr(const SCEV *Op, - const Type *Ty) { + Type *Ty) { assert(getTypeSizeInBits(Op->getType()) < getTypeSizeInBits(Ty) && "This is not an extending conversion!"); assert(isSCEVable(Ty) && @@ -1208,7 +1220,7 @@ const SCEV *ScalarEvolution::getSignExtendExpr(const SCEV *Op, const SCEV *RecastedMaxBECount = getTruncateOrZeroExtend(CastedMaxBECount, MaxBECount->getType()); if (MaxBECount == RecastedMaxBECount) { - const Type *WideTy = IntegerType::get(getContext(), BitWidth * 2); + Type *WideTy = IntegerType::get(getContext(), BitWidth * 2); // Check whether Start+Step*MaxBECount has no signed overflow. const SCEV *SMul = getMulExpr(CastedMaxBECount, Step); const SCEV *Add = getAddExpr(Start, SMul); @@ -1275,7 +1287,7 @@ const SCEV *ScalarEvolution::getSignExtendExpr(const SCEV *Op, /// unspecified bits out to the given type. /// const SCEV *ScalarEvolution::getAnyExtendExpr(const SCEV *Op, - const Type *Ty) { + Type *Ty) { assert(getTypeSizeInBits(Op->getType()) < getTypeSizeInBits(Ty) && "This is not an extending conversion!"); assert(isSCEVable(Ty) && @@ -1438,7 +1450,7 @@ const SCEV *ScalarEvolution::getAddExpr(SmallVectorImpl &Ops, assert(!Ops.empty() && "Cannot get empty add!"); if (Ops.size() == 1) return Ops[0]; #ifndef NDEBUG - const Type *ETy = getEffectiveSCEVType(Ops[0]->getType()); + Type *ETy = getEffectiveSCEVType(Ops[0]->getType()); for (unsigned i = 1, e = Ops.size(); i != e; ++i) assert(getEffectiveSCEVType(Ops[i]->getType()) == ETy && "SCEVAddExpr operand types don't match!"); @@ -1488,7 +1500,7 @@ const SCEV *ScalarEvolution::getAddExpr(SmallVectorImpl &Ops, // Okay, check to see if the same value occurs in the operand list more than // once. If so, merge them together into an multiply expression. Since we // sorted the list, these values are required to be adjacent. - const Type *Ty = Ops[0]->getType(); + Type *Ty = Ops[0]->getType(); bool FoundMatch = false; for (unsigned i = 0, e = Ops.size(); i != e-1; ++i) if (Ops[i] == Ops[i+1]) { // X + Y + Y --> X + Y*2 @@ -1515,8 +1527,8 @@ const SCEV *ScalarEvolution::getAddExpr(SmallVectorImpl &Ops, // if the contents of the resulting outer trunc fold to something simple. for (; Idx < Ops.size() && isa(Ops[Idx]); ++Idx) { const SCEVTruncateExpr *Trunc = cast(Ops[Idx]); - const Type *DstType = Trunc->getType(); - const Type *SrcType = Trunc->getOperand()->getType(); + Type *DstType = Trunc->getType(); + Type *SrcType = Trunc->getOperand()->getType(); SmallVector LargeOps; bool Ok = true; // Check all the operands to see if they can be represented in the @@ -1735,7 +1747,7 @@ const SCEV *ScalarEvolution::getAddExpr(SmallVectorImpl &Ops, // If all of the other operands were loop invariant, we are done. if (Ops.size() == 1) return NewRec; - // Otherwise, add the folded AddRec by the non-liv parts. + // Otherwise, add the folded AddRec by the non-invariant parts. for (unsigned i = 0;; ++i) if (Ops[i] == AddRec) { Ops[i] = NewRec; @@ -1800,6 +1812,38 @@ const SCEV *ScalarEvolution::getAddExpr(SmallVectorImpl &Ops, return S; } +static uint64_t umul_ov(uint64_t i, uint64_t j, bool &Overflow) { + uint64_t k = i*j; + if (j > 1 && k / j != i) Overflow = true; + return k; +} + +/// Compute the result of "n choose k", the binomial coefficient. If an +/// intermediate computation overflows, Overflow will be set and the return will +/// be garbage. Overflow is not cleared on absense of overflow. +static uint64_t Choose(uint64_t n, uint64_t k, bool &Overflow) { + // We use the multiplicative formula: + // n(n-1)(n-2)...(n-(k-1)) / k(k-1)(k-2)...1 . + // At each iteration, we take the n-th term of the numeral and divide by the + // (k-n)th term of the denominator. This division will always produce an + // integral result, and helps reduce the chance of overflow in the + // intermediate computations. However, we can still overflow even when the + // final result would fit. + + if (n == 0 || n == k) return 1; + if (k > n) return 0; + + if (k > n/2) + k = n-k; + + uint64_t r = 1; + for (uint64_t i = 1; i <= k; ++i) { + r = umul_ov(r, n-(i-1), Overflow); + r /= i; + } + return r; +} + /// getMulExpr - Get a canonical multiply expression, or something simpler if /// possible. const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl &Ops, @@ -1809,7 +1853,7 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl &Ops, assert(!Ops.empty() && "Cannot get empty mul!"); if (Ops.size() == 1) return Ops[0]; #ifndef NDEBUG - const Type *ETy = getEffectiveSCEVType(Ops[0]->getType()); + Type *ETy = getEffectiveSCEVType(Ops[0]->getType()); for (unsigned i = 1, e = Ops.size(); i != e; ++i) assert(getEffectiveSCEVType(Ops[i]->getType()) == ETy && "SCEVMulExpr operand types don't match!"); @@ -1960,7 +2004,7 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl &Ops, // If all of the other operands were loop invariant, we are done. if (Ops.size() == 1) return NewRec; - // Otherwise, multiply the folded AddRec by the non-liv parts. + // Otherwise, multiply the folded AddRec by the non-invariant parts. for (unsigned i = 0;; ++i) if (Ops[i] == AddRec) { Ops[i] = NewRec; @@ -1974,31 +2018,65 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl &Ops, // multiplied together. If so, we can fold them. for (unsigned OtherIdx = Idx+1; OtherIdx < Ops.size() && isa(Ops[OtherIdx]); - ++OtherIdx) + ++OtherIdx) { if (AddRecLoop == cast(Ops[OtherIdx])->getLoop()) { - // F * G, where F = {A,+,B} and G = {C,+,D} --> - // {A*C,+,F*D + G*B + B*D} + // {A1,+,A2,+,...,+,An} * {B1,+,B2,+,...,+,Bn} + // = {x=1 in [ sum y=x..2x [ sum z=max(y-x, y-n)..min(x,n) [ + // choose(x, 2x)*choose(2x-y, x-z)*A_{y-z}*B_z + // ]]],+,...up to x=2n}. + // Note that the arguments to choose() are always integers with values + // known at compile time, never SCEV objects. + // + // The implementation avoids pointless extra computations when the two + // addrec's are of different length (mathematically, it's equivalent to + // an infinite stream of zeros on the right). + bool OpsModified = false; for (; OtherIdx != Ops.size() && isa(Ops[OtherIdx]); ++OtherIdx) if (const SCEVAddRecExpr *OtherAddRec = dyn_cast(Ops[OtherIdx])) if (OtherAddRec->getLoop() == AddRecLoop) { - const SCEVAddRecExpr *F = AddRec, *G = OtherAddRec; - const SCEV *NewStart = getMulExpr(F->getStart(), G->getStart()); - const SCEV *B = F->getStepRecurrence(*this); - const SCEV *D = G->getStepRecurrence(*this); - const SCEV *NewStep = getAddExpr(getMulExpr(F, D), - getMulExpr(G, B), - getMulExpr(B, D)); - const SCEV *NewAddRec = getAddRecExpr(NewStart, NewStep, - F->getLoop(), - SCEV::FlagAnyWrap); - if (Ops.size() == 2) return NewAddRec; - Ops[Idx] = AddRec = cast(NewAddRec); - Ops.erase(Ops.begin() + OtherIdx); --OtherIdx; + bool Overflow = false; + Type *Ty = AddRec->getType(); + bool LargerThan64Bits = getTypeSizeInBits(Ty) > 64; + SmallVector AddRecOps; + for (int x = 0, xe = AddRec->getNumOperands() + + OtherAddRec->getNumOperands() - 1; + x != xe && !Overflow; ++x) { + const SCEV *Term = getConstant(Ty, 0); + for (int y = x, ye = 2*x+1; y != ye && !Overflow; ++y) { + uint64_t Coeff1 = Choose(x, 2*x - y, Overflow); + for (int z = std::max(y-x, y-(int)AddRec->getNumOperands()+1), + ze = std::min(x+1, (int)OtherAddRec->getNumOperands()); + z < ze && !Overflow; ++z) { + uint64_t Coeff2 = Choose(2*x - y, x-z, Overflow); + uint64_t Coeff; + if (LargerThan64Bits) + Coeff = umul_ov(Coeff1, Coeff2, Overflow); + else + Coeff = Coeff1*Coeff2; + const SCEV *CoeffTerm = getConstant(Ty, Coeff); + const SCEV *Term1 = AddRec->getOperand(y-z); + const SCEV *Term2 = OtherAddRec->getOperand(z); + Term = getAddExpr(Term, getMulExpr(CoeffTerm, Term1,Term2)); + } + } + AddRecOps.push_back(Term); + } + if (!Overflow) { + const SCEV *NewAddRec = getAddRecExpr(AddRecOps, + AddRec->getLoop(), + SCEV::FlagAnyWrap); + if (Ops.size() == 2) return NewAddRec; + Ops[Idx] = AddRec = cast(NewAddRec); + Ops.erase(Ops.begin() + OtherIdx); --OtherIdx; + OpsModified = true; + } } - return getMulExpr(Ops); + if (OpsModified) + return getMulExpr(Ops); } + } // Otherwise couldn't fold anything into this recurrence. Move onto the // next one. @@ -2042,21 +2120,22 @@ const SCEV *ScalarEvolution::getUDivExpr(const SCEV *LHS, // Determine if the division can be folded into the operands of // its operands. // TODO: Generalize this to non-constants by using known-bits information. - const Type *Ty = LHS->getType(); + Type *Ty = LHS->getType(); unsigned LZ = RHSC->getValue()->getValue().countLeadingZeros(); unsigned MaxShiftAmt = getTypeSizeInBits(Ty) - LZ - 1; // For non-power-of-two values, effectively round the value up to the // nearest power of two. if (!RHSC->getValue()->getValue().isPowerOf2()) ++MaxShiftAmt; - const IntegerType *ExtTy = + IntegerType *ExtTy = IntegerType::get(getContext(), getTypeSizeInBits(Ty) + MaxShiftAmt); - // {X,+,N}/C --> {X/C,+,N/C} if safe and N/C can be folded. if (const SCEVAddRecExpr *AR = dyn_cast(LHS)) if (const SCEVConstant *Step = - dyn_cast(AR->getStepRecurrence(*this))) - if (!Step->getValue()->getValue() - .urem(RHSC->getValue()->getValue()) && + dyn_cast(AR->getStepRecurrence(*this))) { + // {X,+,N}/C --> {X/C,+,N/C} if safe and N/C can be folded. + const APInt &StepInt = Step->getValue()->getValue(); + const APInt &DivInt = RHSC->getValue()->getValue(); + if (!StepInt.urem(DivInt) && getZeroExtendExpr(AR, ExtTy) == getAddRecExpr(getZeroExtendExpr(AR->getStart(), ExtTy), getZeroExtendExpr(Step, ExtTy), @@ -2067,6 +2146,22 @@ const SCEV *ScalarEvolution::getUDivExpr(const SCEV *LHS, return getAddRecExpr(Operands, AR->getLoop(), SCEV::FlagNW); } + /// Get a canonical UDivExpr for a recurrence. + /// {X,+,N}/C => {Y,+,N}/C where Y=X-(X%N). Safe when C%N=0. + // We can currently only fold X%N if X is constant. + const SCEVConstant *StartC = dyn_cast(AR->getStart()); + if (StartC && !DivInt.urem(StepInt) && + getZeroExtendExpr(AR, ExtTy) == + getAddRecExpr(getZeroExtendExpr(AR->getStart(), ExtTy), + getZeroExtendExpr(Step, ExtTy), + AR->getLoop(), SCEV::FlagAnyWrap)) { + const APInt &StartInt = StartC->getValue()->getValue(); + const APInt &StartRem = StartInt.urem(StepInt); + if (StartRem != 0) + LHS = getAddRecExpr(getConstant(StartInt - StartRem), Step, + AR->getLoop(), SCEV::FlagNW); + } + } // (A*B)/C --> A*(B/C) if safe and B/C can be folded. if (const SCEVMulExpr *M = dyn_cast(LHS)) { SmallVector Operands; @@ -2151,7 +2246,7 @@ ScalarEvolution::getAddRecExpr(SmallVectorImpl &Operands, const Loop *L, SCEV::NoWrapFlags Flags) { if (Operands.size() == 1) return Operands[0]; #ifndef NDEBUG - const Type *ETy = getEffectiveSCEVType(Operands[0]->getType()); + Type *ETy = getEffectiveSCEVType(Operands[0]->getType()); for (unsigned i = 1, e = Operands.size(); i != e; ++i) assert(getEffectiveSCEVType(Operands[i]->getType()) == ETy && "SCEVAddRecExpr operand types don't match!"); @@ -2269,7 +2364,7 @@ ScalarEvolution::getSMaxExpr(SmallVectorImpl &Ops) { assert(!Ops.empty() && "Cannot get empty smax!"); if (Ops.size() == 1) return Ops[0]; #ifndef NDEBUG - const Type *ETy = getEffectiveSCEVType(Ops[0]->getType()); + Type *ETy = getEffectiveSCEVType(Ops[0]->getType()); for (unsigned i = 1, e = Ops.size(); i != e; ++i) assert(getEffectiveSCEVType(Ops[i]->getType()) == ETy && "SCEVSMaxExpr operand types don't match!"); @@ -2373,7 +2468,7 @@ ScalarEvolution::getUMaxExpr(SmallVectorImpl &Ops) { assert(!Ops.empty() && "Cannot get empty umax!"); if (Ops.size() == 1) return Ops[0]; #ifndef NDEBUG - const Type *ETy = getEffectiveSCEVType(Ops[0]->getType()); + Type *ETy = getEffectiveSCEVType(Ops[0]->getType()); for (unsigned i = 1, e = Ops.size(); i != e; ++i) assert(getEffectiveSCEVType(Ops[i]->getType()) == ETy && "SCEVUMaxExpr operand types don't match!"); @@ -2476,7 +2571,7 @@ const SCEV *ScalarEvolution::getUMinExpr(const SCEV *LHS, return getNotSCEV(getUMaxExpr(getNotSCEV(LHS), getNotSCEV(RHS))); } -const SCEV *ScalarEvolution::getSizeOfExpr(const Type *AllocTy) { +const SCEV *ScalarEvolution::getSizeOfExpr(Type *AllocTy) { // If we have TargetData, we can bypass creating a target-independent // constant expression and then folding it back into a ConstantInt. // This is just a compile-time optimization. @@ -2488,20 +2583,20 @@ const SCEV *ScalarEvolution::getSizeOfExpr(const Type *AllocTy) { if (ConstantExpr *CE = dyn_cast(C)) if (Constant *Folded = ConstantFoldConstantExpression(CE, TD)) C = Folded; - const Type *Ty = getEffectiveSCEVType(PointerType::getUnqual(AllocTy)); + Type *Ty = getEffectiveSCEVType(PointerType::getUnqual(AllocTy)); return getTruncateOrZeroExtend(getSCEV(C), Ty); } -const SCEV *ScalarEvolution::getAlignOfExpr(const Type *AllocTy) { +const SCEV *ScalarEvolution::getAlignOfExpr(Type *AllocTy) { Constant *C = ConstantExpr::getAlignOf(AllocTy); if (ConstantExpr *CE = dyn_cast(C)) if (Constant *Folded = ConstantFoldConstantExpression(CE, TD)) C = Folded; - const Type *Ty = getEffectiveSCEVType(PointerType::getUnqual(AllocTy)); + Type *Ty = getEffectiveSCEVType(PointerType::getUnqual(AllocTy)); return getTruncateOrZeroExtend(getSCEV(C), Ty); } -const SCEV *ScalarEvolution::getOffsetOfExpr(const StructType *STy, +const SCEV *ScalarEvolution::getOffsetOfExpr(StructType *STy, unsigned FieldNo) { // If we have TargetData, we can bypass creating a target-independent // constant expression and then folding it back into a ConstantInt. @@ -2514,17 +2609,17 @@ const SCEV *ScalarEvolution::getOffsetOfExpr(const StructType *STy, if (ConstantExpr *CE = dyn_cast(C)) if (Constant *Folded = ConstantFoldConstantExpression(CE, TD)) C = Folded; - const Type *Ty = getEffectiveSCEVType(PointerType::getUnqual(STy)); + Type *Ty = getEffectiveSCEVType(PointerType::getUnqual(STy)); return getTruncateOrZeroExtend(getSCEV(C), Ty); } -const SCEV *ScalarEvolution::getOffsetOfExpr(const Type *CTy, +const SCEV *ScalarEvolution::getOffsetOfExpr(Type *CTy, Constant *FieldNo) { Constant *C = ConstantExpr::getOffsetOf(CTy, FieldNo); if (ConstantExpr *CE = dyn_cast(C)) if (Constant *Folded = ConstantFoldConstantExpression(CE, TD)) C = Folded; - const Type *Ty = getEffectiveSCEVType(PointerType::getUnqual(CTy)); + Type *Ty = getEffectiveSCEVType(PointerType::getUnqual(CTy)); return getTruncateOrZeroExtend(getSCEV(C), Ty); } @@ -2558,14 +2653,14 @@ const SCEV *ScalarEvolution::getUnknown(Value *V) { /// the SCEV framework. This primarily includes integer types, and it /// can optionally include pointer types if the ScalarEvolution class /// has access to target-specific information. -bool ScalarEvolution::isSCEVable(const Type *Ty) const { +bool ScalarEvolution::isSCEVable(Type *Ty) const { // Integers and pointers are always SCEVable. return Ty->isIntegerTy() || Ty->isPointerTy(); } /// getTypeSizeInBits - Return the size in bits of the specified type, /// for which isSCEVable must return true. -uint64_t ScalarEvolution::getTypeSizeInBits(const Type *Ty) const { +uint64_t ScalarEvolution::getTypeSizeInBits(Type *Ty) const { assert(isSCEVable(Ty) && "Type is not SCEVable!"); // If we have a TargetData, use it! @@ -2586,7 +2681,7 @@ uint64_t ScalarEvolution::getTypeSizeInBits(const Type *Ty) const { /// the given type and which represents how SCEV will treat the given /// type, for which isSCEVable must return true. For pointer types, /// this is the pointer-sized integer type. -const Type *ScalarEvolution::getEffectiveSCEVType(const Type *Ty) const { +Type *ScalarEvolution::getEffectiveSCEVType(Type *Ty) const { assert(isSCEVable(Ty) && "Type is not SCEVable!"); if (Ty->isIntegerTy()) @@ -2628,7 +2723,7 @@ const SCEV *ScalarEvolution::getNegativeSCEV(const SCEV *V) { return getConstant( cast(ConstantExpr::getNeg(VC->getValue()))); - const Type *Ty = V->getType(); + Type *Ty = V->getType(); Ty = getEffectiveSCEVType(Ty); return getMulExpr(V, getConstant(cast(Constant::getAllOnesValue(Ty)))); @@ -2640,7 +2735,7 @@ const SCEV *ScalarEvolution::getNotSCEV(const SCEV *V) { return getConstant( cast(ConstantExpr::getNot(VC->getValue()))); - const Type *Ty = V->getType(); + Type *Ty = V->getType(); Ty = getEffectiveSCEVType(Ty); const SCEV *AllOnes = getConstant(cast(Constant::getAllOnesValue(Ty))); @@ -2664,8 +2759,8 @@ const SCEV *ScalarEvolution::getMinusSCEV(const SCEV *LHS, const SCEV *RHS, /// input value to the specified type. If the type must be extended, it is zero /// extended. const SCEV * -ScalarEvolution::getTruncateOrZeroExtend(const SCEV *V, const Type *Ty) { - const Type *SrcTy = V->getType(); +ScalarEvolution::getTruncateOrZeroExtend(const SCEV *V, Type *Ty) { + Type *SrcTy = V->getType(); assert((SrcTy->isIntegerTy() || SrcTy->isPointerTy()) && (Ty->isIntegerTy() || Ty->isPointerTy()) && "Cannot truncate or zero extend with non-integer arguments!"); @@ -2681,8 +2776,8 @@ ScalarEvolution::getTruncateOrZeroExtend(const SCEV *V, const Type *Ty) { /// extended. const SCEV * ScalarEvolution::getTruncateOrSignExtend(const SCEV *V, - const Type *Ty) { - const Type *SrcTy = V->getType(); + Type *Ty) { + Type *SrcTy = V->getType(); assert((SrcTy->isIntegerTy() || SrcTy->isPointerTy()) && (Ty->isIntegerTy() || Ty->isPointerTy()) && "Cannot truncate or zero extend with non-integer arguments!"); @@ -2697,8 +2792,8 @@ ScalarEvolution::getTruncateOrSignExtend(const SCEV *V, /// input value to the specified type. If the type must be extended, it is zero /// extended. The conversion must not be narrowing. const SCEV * -ScalarEvolution::getNoopOrZeroExtend(const SCEV *V, const Type *Ty) { - const Type *SrcTy = V->getType(); +ScalarEvolution::getNoopOrZeroExtend(const SCEV *V, Type *Ty) { + Type *SrcTy = V->getType(); assert((SrcTy->isIntegerTy() || SrcTy->isPointerTy()) && (Ty->isIntegerTy() || Ty->isPointerTy()) && "Cannot noop or zero extend with non-integer arguments!"); @@ -2713,8 +2808,8 @@ ScalarEvolution::getNoopOrZeroExtend(const SCEV *V, const Type *Ty) { /// input value to the specified type. If the type must be extended, it is sign /// extended. The conversion must not be narrowing. const SCEV * -ScalarEvolution::getNoopOrSignExtend(const SCEV *V, const Type *Ty) { - const Type *SrcTy = V->getType(); +ScalarEvolution::getNoopOrSignExtend(const SCEV *V, Type *Ty) { + Type *SrcTy = V->getType(); assert((SrcTy->isIntegerTy() || SrcTy->isPointerTy()) && (Ty->isIntegerTy() || Ty->isPointerTy()) && "Cannot noop or sign extend with non-integer arguments!"); @@ -2730,8 +2825,8 @@ ScalarEvolution::getNoopOrSignExtend(const SCEV *V, const Type *Ty) { /// it is extended with unspecified bits. The conversion must not be /// narrowing. const SCEV * -ScalarEvolution::getNoopOrAnyExtend(const SCEV *V, const Type *Ty) { - const Type *SrcTy = V->getType(); +ScalarEvolution::getNoopOrAnyExtend(const SCEV *V, Type *Ty) { + Type *SrcTy = V->getType(); assert((SrcTy->isIntegerTy() || SrcTy->isPointerTy()) && (Ty->isIntegerTy() || Ty->isPointerTy()) && "Cannot noop or any extend with non-integer arguments!"); @@ -2745,8 +2840,8 @@ ScalarEvolution::getNoopOrAnyExtend(const SCEV *V, const Type *Ty) { /// getTruncateOrNoop - Return a SCEV corresponding to a conversion of the /// input value to the specified type. The conversion must not be widening. const SCEV * -ScalarEvolution::getTruncateOrNoop(const SCEV *V, const Type *Ty) { - const Type *SrcTy = V->getType(); +ScalarEvolution::getTruncateOrNoop(const SCEV *V, Type *Ty) { + Type *SrcTy = V->getType(); assert((SrcTy->isIntegerTy() || SrcTy->isPointerTy()) && (Ty->isIntegerTy() || Ty->isPointerTy()) && "Cannot truncate or noop with non-integer arguments!"); @@ -3032,7 +3127,7 @@ const SCEV *ScalarEvolution::createNodeForGEP(GEPOperator *GEP) { // context. bool isInBounds = GEP->isInBounds(); - const Type *IntPtrTy = getEffectiveSCEVType(GEP->getType()); + Type *IntPtrTy = getEffectiveSCEVType(GEP->getType()); Value *Base = GEP->getOperand(0); // Don't attempt to analyze GEPs over unsized objects. if (!cast(Base->getType())->getElementType()->isSized()) @@ -3044,7 +3139,7 @@ const SCEV *ScalarEvolution::createNodeForGEP(GEPOperator *GEP) { I != E; ++I) { Value *Index = *I; // Compute the (potentially symbolic) offset in bytes for this index. - if (const StructType *STy = dyn_cast(*GTI++)) { + if (StructType *STy = dyn_cast(*GTI++)) { // For a struct, add the member offset. unsigned FieldNo = cast(Index)->getZExtValue(); const SCEV *FieldOffset = getOffsetOfExpr(STy, FieldNo); @@ -3244,7 +3339,7 @@ ScalarEvolution::getUnsignedRange(const SCEV *S) { // TODO: non-affine addrec if (AddRec->isAffine()) { - const Type *Ty = AddRec->getType(); + Type *Ty = AddRec->getType(); const SCEV *MaxBECount = getMaxBackedgeTakenCount(AddRec->getLoop()); if (!isa(MaxBECount) && getTypeSizeInBits(MaxBECount->getType()) <= BitWidth) { @@ -3396,7 +3491,7 @@ ScalarEvolution::getSignedRange(const SCEV *S) { // TODO: non-affine addrec if (AddRec->isAffine()) { - const Type *Ty = AddRec->getType(); + Type *Ty = AddRec->getType(); const SCEV *MaxBECount = getMaxBackedgeTakenCount(AddRec->getLoop()); if (!isa(MaxBECount) && getTypeSizeInBits(MaxBECount->getType()) <= BitWidth) { @@ -3503,7 +3598,13 @@ const SCEV *ScalarEvolution::createSCEV(Value *V) { AddOps.push_back(Op1); } AddOps.push_back(getSCEV(U->getOperand(0))); - return getAddExpr(AddOps); + SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap; + OverflowingBinaryOperator *OBO = cast(V); + if (OBO->hasNoSignedWrap()) + setFlags(Flags, SCEV::FlagNSW); + if (OBO->hasNoUnsignedWrap()) + setFlags(Flags, SCEV::FlagNUW); + return getAddExpr(AddOps, Flags); } case Instruction::Mul: { // See the Add code above. @@ -3601,9 +3702,9 @@ const SCEV *ScalarEvolution::createSCEV(Value *V) { LCI->getValue() == CI->getValue()) if (const SCEVZeroExtendExpr *Z = dyn_cast(getSCEV(U->getOperand(0)))) { - const Type *UTy = U->getType(); + Type *UTy = U->getType(); const SCEV *Z0 = Z->getOperand(); - const Type *Z0Ty = Z0->getType(); + Type *Z0Ty = Z0->getType(); unsigned Z0TySize = getTypeSizeInBits(Z0Ty); // If C is a low-bits mask, the zero extend is serving to @@ -3813,6 +3914,70 @@ const SCEV *ScalarEvolution::createSCEV(Value *V) { // Iteration Count Computation Code // +/// getSmallConstantTripCount - Returns the maximum trip count of this loop as a +/// normal unsigned value, if possible. Returns 0 if the trip count is unknown +/// or not constant. Will also return 0 if the maximum trip count is very large +/// (>= 2^32) +unsigned ScalarEvolution::getSmallConstantTripCount(Loop *L, + BasicBlock *ExitBlock) { + const SCEVConstant *ExitCount = + dyn_cast(getExitCount(L, ExitBlock)); + if (!ExitCount) + return 0; + + ConstantInt *ExitConst = ExitCount->getValue(); + + // Guard against huge trip counts. + if (ExitConst->getValue().getActiveBits() > 32) + return 0; + + // In case of integer overflow, this returns 0, which is correct. + return ((unsigned)ExitConst->getZExtValue()) + 1; +} + +/// getSmallConstantTripMultiple - Returns the largest constant divisor of the +/// trip count of this loop as a normal unsigned value, if possible. This +/// means that the actual trip count is always a multiple of the returned +/// value (don't forget the trip count could very well be zero as well!). +/// +/// Returns 1 if the trip count is unknown or not guaranteed to be the +/// multiple of a constant (which is also the case if the trip count is simply +/// constant, use getSmallConstantTripCount for that case), Will also return 1 +/// if the trip count is very large (>= 2^32). +unsigned ScalarEvolution::getSmallConstantTripMultiple(Loop *L, + BasicBlock *ExitBlock) { + const SCEV *ExitCount = getExitCount(L, ExitBlock); + if (ExitCount == getCouldNotCompute()) + return 1; + + // Get the trip count from the BE count by adding 1. + const SCEV *TCMul = getAddExpr(ExitCount, + getConstant(ExitCount->getType(), 1)); + // FIXME: SCEV distributes multiplication as V1*C1 + V2*C1. We could attempt + // to factor simple cases. + if (const SCEVMulExpr *Mul = dyn_cast(TCMul)) + TCMul = Mul->getOperand(0); + + const SCEVConstant *MulC = dyn_cast(TCMul); + if (!MulC) + return 1; + + ConstantInt *Result = MulC->getValue(); + + // Guard against huge trip counts. + if (!Result || Result->getValue().getActiveBits() > 32) + return 1; + + return (unsigned)Result->getZExtValue(); +} + +// getExitCount - Get the expression for the number of loop iterations for which +// this loop is guaranteed not to exit via ExitintBlock. Otherwise return +// SCEVCouldNotCompute. +const SCEV *ScalarEvolution::getExitCount(Loop *L, BasicBlock *ExitingBlock) { + return getBackedgeTakenInfo(L).getExact(ExitingBlock, this); +} + /// getBackedgeTakenCount - If the specified loop has a predictable /// backedge-taken count, return it, otherwise return a SCEVCouldNotCompute /// object. The backedge-taken count is the number of times the loop header @@ -3825,14 +3990,14 @@ const SCEV *ScalarEvolution::createSCEV(Value *V) { /// hasLoopInvariantBackedgeTakenCount). /// const SCEV *ScalarEvolution::getBackedgeTakenCount(const Loop *L) { - return getBackedgeTakenInfo(L).Exact; + return getBackedgeTakenInfo(L).getExact(this); } /// getMaxBackedgeTakenCount - Similar to getBackedgeTakenCount, except /// return the least SCEV value that is known never to be less than the /// actual backedge taken count. const SCEV *ScalarEvolution::getMaxBackedgeTakenCount(const Loop *L) { - return getBackedgeTakenInfo(L).Max; + return getBackedgeTakenInfo(L).getMax(this); } /// PushLoopPHIs - Push PHI nodes in the header of the given loop @@ -3849,33 +4014,31 @@ PushLoopPHIs(const Loop *L, SmallVectorImpl &Worklist) { const ScalarEvolution::BackedgeTakenInfo & ScalarEvolution::getBackedgeTakenInfo(const Loop *L) { - // Initially insert a CouldNotCompute for this loop. If the insertion + // Initially insert an invalid entry for this loop. If the insertion // succeeds, proceed to actually compute a backedge-taken count and // update the value. The temporary CouldNotCompute value tells SCEV // code elsewhere that it shouldn't attempt to request a new // backedge-taken count, which could result in infinite recursion. std::pair::iterator, bool> Pair = - BackedgeTakenCounts.insert(std::make_pair(L, getCouldNotCompute())); + BackedgeTakenCounts.insert(std::make_pair(L, BackedgeTakenInfo())); if (!Pair.second) return Pair.first->second; - BackedgeTakenInfo Result = getCouldNotCompute(); - BackedgeTakenInfo Computed = ComputeBackedgeTakenCount(L); - if (Computed.Exact != getCouldNotCompute()) { - assert(isLoopInvariant(Computed.Exact, L) && - isLoopInvariant(Computed.Max, L) && + // ComputeBackedgeTakenCount may allocate memory for its result. Inserting it + // into the BackedgeTakenCounts map transfers ownership. Otherwise, the result + // must be cleared in this scope. + BackedgeTakenInfo Result = ComputeBackedgeTakenCount(L); + + if (Result.getExact(this) != getCouldNotCompute()) { + assert(isLoopInvariant(Result.getExact(this), L) && + isLoopInvariant(Result.getMax(this), L) && "Computed backedge-taken count isn't loop invariant for loop!"); ++NumTripCountsComputed; - - // Update the value in the map. - Result = Computed; - } else { - if (Computed.Max != getCouldNotCompute()) - // Update the value in the map. - Result = Computed; - if (isa(L->getHeader()->begin())) - // Only count loops that have phi nodes as not being computable. - ++NumTripCountsNotComputed; + } + else if (Result.getMax(this) == getCouldNotCompute() && + isa(L->getHeader()->begin())) { + // Only count loops that have phi nodes as not being computable. + ++NumTripCountsNotComputed; } // Now that we know more about the trip count for this loop, forget any @@ -3883,7 +4046,7 @@ ScalarEvolution::getBackedgeTakenInfo(const Loop *L) { // conservative estimates made without the benefit of trip count // information. This is similar to the code in forgetLoop, except that // it handles SCEVUnknown PHI nodes specially. - if (Computed.hasAnyInfo()) { + if (Result.hasAnyInfo()) { SmallVector Worklist; PushLoopPHIs(L, Worklist); @@ -3928,7 +4091,12 @@ ScalarEvolution::getBackedgeTakenInfo(const Loop *L) { /// compute a trip count, or if the loop is deleted. void ScalarEvolution::forgetLoop(const Loop *L) { // Drop any stored trip count value. - BackedgeTakenCounts.erase(L); + DenseMap::iterator BTCPos = + BackedgeTakenCounts.find(L); + if (BTCPos != BackedgeTakenCounts.end()) { + BTCPos->second.clear(); + BackedgeTakenCounts.erase(BTCPos); + } // Drop information about expressions based on loop-header PHIs. SmallVector Worklist; @@ -3984,6 +4152,85 @@ void ScalarEvolution::forgetValue(Value *V) { } } +/// getExact - Get the exact loop backedge taken count considering all loop +/// exits. If all exits are computable, this is the minimum computed count. +const SCEV * +ScalarEvolution::BackedgeTakenInfo::getExact(ScalarEvolution *SE) const { + // If any exits were not computable, the loop is not computable. + if (!ExitNotTaken.isCompleteList()) return SE->getCouldNotCompute(); + + // We need at least one computable exit. + if (!ExitNotTaken.ExitingBlock) return SE->getCouldNotCompute(); + assert(ExitNotTaken.ExactNotTaken && "uninitialized not-taken info"); + + const SCEV *BECount = 0; + for (const ExitNotTakenInfo *ENT = &ExitNotTaken; + ENT != 0; ENT = ENT->getNextExit()) { + + assert(ENT->ExactNotTaken != SE->getCouldNotCompute() && "bad exit SCEV"); + + if (!BECount) + BECount = ENT->ExactNotTaken; + else + BECount = SE->getUMinFromMismatchedTypes(BECount, ENT->ExactNotTaken); + } + assert(BECount && "Invalid not taken count for loop exit"); + return BECount; +} + +/// getExact - Get the exact not taken count for this loop exit. +const SCEV * +ScalarEvolution::BackedgeTakenInfo::getExact(BasicBlock *ExitingBlock, + ScalarEvolution *SE) const { + for (const ExitNotTakenInfo *ENT = &ExitNotTaken; + ENT != 0; ENT = ENT->getNextExit()) { + + if (ENT->ExitingBlock == ExitingBlock) + return ENT->ExactNotTaken; + } + return SE->getCouldNotCompute(); +} + +/// getMax - Get the max backedge taken count for the loop. +const SCEV * +ScalarEvolution::BackedgeTakenInfo::getMax(ScalarEvolution *SE) const { + return Max ? Max : SE->getCouldNotCompute(); +} + +/// Allocate memory for BackedgeTakenInfo and copy the not-taken count of each +/// computable exit into a persistent ExitNotTakenInfo array. +ScalarEvolution::BackedgeTakenInfo::BackedgeTakenInfo( + SmallVectorImpl< std::pair > &ExitCounts, + bool Complete, const SCEV *MaxCount) : Max(MaxCount) { + + if (!Complete) + ExitNotTaken.setIncomplete(); + + unsigned NumExits = ExitCounts.size(); + if (NumExits == 0) return; + + ExitNotTaken.ExitingBlock = ExitCounts[0].first; + ExitNotTaken.ExactNotTaken = ExitCounts[0].second; + if (NumExits == 1) return; + + // Handle the rare case of multiple computable exits. + ExitNotTakenInfo *ENT = new ExitNotTakenInfo[NumExits-1]; + + ExitNotTakenInfo *PrevENT = &ExitNotTaken; + for (unsigned i = 1; i < NumExits; ++i, PrevENT = ENT, ++ENT) { + PrevENT->setNextExit(ENT); + ENT->ExitingBlock = ExitCounts[i].first; + ENT->ExactNotTaken = ExitCounts[i].second; + } +} + +/// clear - Invalidate this result and free the ExitNotTakenInfo array. +void ScalarEvolution::BackedgeTakenInfo::clear() { + ExitNotTaken.ExitingBlock = 0; + ExitNotTaken.ExactNotTaken = 0; + delete[] ExitNotTaken.getNextExit(); +} + /// ComputeBackedgeTakenCount - Compute the number of times the backedge /// of the specified loop will execute. ScalarEvolution::BackedgeTakenInfo @@ -3992,38 +4239,31 @@ ScalarEvolution::ComputeBackedgeTakenCount(const Loop *L) { L->getExitingBlocks(ExitingBlocks); // Examine all exits and pick the most conservative values. - const SCEV *BECount = getCouldNotCompute(); const SCEV *MaxBECount = getCouldNotCompute(); - bool CouldNotComputeBECount = false; + bool CouldComputeBECount = true; + SmallVector, 4> ExitCounts; for (unsigned i = 0, e = ExitingBlocks.size(); i != e; ++i) { - BackedgeTakenInfo NewBTI = - ComputeBackedgeTakenCountFromExit(L, ExitingBlocks[i]); - - if (NewBTI.Exact == getCouldNotCompute()) { + ExitLimit EL = ComputeExitLimit(L, ExitingBlocks[i]); + if (EL.Exact == getCouldNotCompute()) // We couldn't compute an exact value for this exit, so // we won't be able to compute an exact value for the loop. - CouldNotComputeBECount = true; - BECount = getCouldNotCompute(); - } else if (!CouldNotComputeBECount) { - if (BECount == getCouldNotCompute()) - BECount = NewBTI.Exact; - else - BECount = getUMinFromMismatchedTypes(BECount, NewBTI.Exact); - } + CouldComputeBECount = false; + else + ExitCounts.push_back(std::make_pair(ExitingBlocks[i], EL.Exact)); + if (MaxBECount == getCouldNotCompute()) - MaxBECount = NewBTI.Max; - else if (NewBTI.Max != getCouldNotCompute()) - MaxBECount = getUMinFromMismatchedTypes(MaxBECount, NewBTI.Max); + MaxBECount = EL.Max; + else if (EL.Max != getCouldNotCompute()) + MaxBECount = getUMinFromMismatchedTypes(MaxBECount, EL.Max); } - return BackedgeTakenInfo(BECount, MaxBECount); + return BackedgeTakenInfo(ExitCounts, CouldComputeBECount, MaxBECount); } -/// ComputeBackedgeTakenCountFromExit - Compute the number of times the backedge -/// of the specified loop will execute if it exits via the specified block. -ScalarEvolution::BackedgeTakenInfo -ScalarEvolution::ComputeBackedgeTakenCountFromExit(const Loop *L, - BasicBlock *ExitingBlock) { +/// ComputeExitLimit - Compute the number of times the backedge of the specified +/// loop will execute if it exits via the specified block. +ScalarEvolution::ExitLimit +ScalarEvolution::ComputeExitLimit(const Loop *L, BasicBlock *ExitingBlock) { // Okay, we've chosen an exiting block. See what condition causes us to // exit at this block. @@ -4081,95 +4321,91 @@ ScalarEvolution::ComputeBackedgeTakenCountFromExit(const Loop *L, } // Proceed to the next level to examine the exit condition expression. - return ComputeBackedgeTakenCountFromExitCond(L, ExitBr->getCondition(), - ExitBr->getSuccessor(0), - ExitBr->getSuccessor(1)); + return ComputeExitLimitFromCond(L, ExitBr->getCondition(), + ExitBr->getSuccessor(0), + ExitBr->getSuccessor(1)); } -/// ComputeBackedgeTakenCountFromExitCond - Compute the number of times the +/// ComputeExitLimitFromCond - Compute the number of times the /// backedge of the specified loop will execute if its exit condition /// were a conditional branch of ExitCond, TBB, and FBB. -ScalarEvolution::BackedgeTakenInfo -ScalarEvolution::ComputeBackedgeTakenCountFromExitCond(const Loop *L, - Value *ExitCond, - BasicBlock *TBB, - BasicBlock *FBB) { +ScalarEvolution::ExitLimit +ScalarEvolution::ComputeExitLimitFromCond(const Loop *L, + Value *ExitCond, + BasicBlock *TBB, + BasicBlock *FBB) { // Check if the controlling expression for this loop is an And or Or. if (BinaryOperator *BO = dyn_cast(ExitCond)) { if (BO->getOpcode() == Instruction::And) { // Recurse on the operands of the and. - BackedgeTakenInfo BTI0 = - ComputeBackedgeTakenCountFromExitCond(L, BO->getOperand(0), TBB, FBB); - BackedgeTakenInfo BTI1 = - ComputeBackedgeTakenCountFromExitCond(L, BO->getOperand(1), TBB, FBB); + ExitLimit EL0 = ComputeExitLimitFromCond(L, BO->getOperand(0), TBB, FBB); + ExitLimit EL1 = ComputeExitLimitFromCond(L, BO->getOperand(1), TBB, FBB); const SCEV *BECount = getCouldNotCompute(); const SCEV *MaxBECount = getCouldNotCompute(); if (L->contains(TBB)) { // Both conditions must be true for the loop to continue executing. // Choose the less conservative count. - if (BTI0.Exact == getCouldNotCompute() || - BTI1.Exact == getCouldNotCompute()) + if (EL0.Exact == getCouldNotCompute() || + EL1.Exact == getCouldNotCompute()) BECount = getCouldNotCompute(); else - BECount = getUMinFromMismatchedTypes(BTI0.Exact, BTI1.Exact); - if (BTI0.Max == getCouldNotCompute()) - MaxBECount = BTI1.Max; - else if (BTI1.Max == getCouldNotCompute()) - MaxBECount = BTI0.Max; + BECount = getUMinFromMismatchedTypes(EL0.Exact, EL1.Exact); + if (EL0.Max == getCouldNotCompute()) + MaxBECount = EL1.Max; + else if (EL1.Max == getCouldNotCompute()) + MaxBECount = EL0.Max; else - MaxBECount = getUMinFromMismatchedTypes(BTI0.Max, BTI1.Max); + MaxBECount = getUMinFromMismatchedTypes(EL0.Max, EL1.Max); } else { // Both conditions must be true at the same time for the loop to exit. // For now, be conservative. assert(L->contains(FBB) && "Loop block has no successor in loop!"); - if (BTI0.Max == BTI1.Max) - MaxBECount = BTI0.Max; - if (BTI0.Exact == BTI1.Exact) - BECount = BTI0.Exact; + if (EL0.Max == EL1.Max) + MaxBECount = EL0.Max; + if (EL0.Exact == EL1.Exact) + BECount = EL0.Exact; } - return BackedgeTakenInfo(BECount, MaxBECount); + return ExitLimit(BECount, MaxBECount); } if (BO->getOpcode() == Instruction::Or) { // Recurse on the operands of the or. - BackedgeTakenInfo BTI0 = - ComputeBackedgeTakenCountFromExitCond(L, BO->getOperand(0), TBB, FBB); - BackedgeTakenInfo BTI1 = - ComputeBackedgeTakenCountFromExitCond(L, BO->getOperand(1), TBB, FBB); + ExitLimit EL0 = ComputeExitLimitFromCond(L, BO->getOperand(0), TBB, FBB); + ExitLimit EL1 = ComputeExitLimitFromCond(L, BO->getOperand(1), TBB, FBB); const SCEV *BECount = getCouldNotCompute(); const SCEV *MaxBECount = getCouldNotCompute(); if (L->contains(FBB)) { // Both conditions must be false for the loop to continue executing. // Choose the less conservative count. - if (BTI0.Exact == getCouldNotCompute() || - BTI1.Exact == getCouldNotCompute()) + if (EL0.Exact == getCouldNotCompute() || + EL1.Exact == getCouldNotCompute()) BECount = getCouldNotCompute(); else - BECount = getUMinFromMismatchedTypes(BTI0.Exact, BTI1.Exact); - if (BTI0.Max == getCouldNotCompute()) - MaxBECount = BTI1.Max; - else if (BTI1.Max == getCouldNotCompute()) - MaxBECount = BTI0.Max; + BECount = getUMinFromMismatchedTypes(EL0.Exact, EL1.Exact); + if (EL0.Max == getCouldNotCompute()) + MaxBECount = EL1.Max; + else if (EL1.Max == getCouldNotCompute()) + MaxBECount = EL0.Max; else - MaxBECount = getUMinFromMismatchedTypes(BTI0.Max, BTI1.Max); + MaxBECount = getUMinFromMismatchedTypes(EL0.Max, EL1.Max); } else { // Both conditions must be false at the same time for the loop to exit. // For now, be conservative. assert(L->contains(TBB) && "Loop block has no successor in loop!"); - if (BTI0.Max == BTI1.Max) - MaxBECount = BTI0.Max; - if (BTI0.Exact == BTI1.Exact) - BECount = BTI0.Exact; + if (EL0.Max == EL1.Max) + MaxBECount = EL0.Max; + if (EL0.Exact == EL1.Exact) + BECount = EL0.Exact; } - return BackedgeTakenInfo(BECount, MaxBECount); + return ExitLimit(BECount, MaxBECount); } } // With an icmp, it may be feasible to compute an exact backedge-taken count. // Proceed to the next level to examine the icmp. if (ICmpInst *ExitCondICmp = dyn_cast(ExitCond)) - return ComputeBackedgeTakenCountFromExitCondICmp(L, ExitCondICmp, TBB, FBB); + return ComputeExitLimitFromICmp(L, ExitCondICmp, TBB, FBB); // Check for a constant condition. These are normally stripped out by // SimplifyCFG, but ScalarEvolution may be used by a pass which wishes to @@ -4185,17 +4421,17 @@ ScalarEvolution::ComputeBackedgeTakenCountFromExitCond(const Loop *L, } // If it's not an integer or pointer comparison then compute it the hard way. - return ComputeBackedgeTakenCountExhaustively(L, ExitCond, !L->contains(TBB)); + return ComputeExitCountExhaustively(L, ExitCond, !L->contains(TBB)); } -/// ComputeBackedgeTakenCountFromExitCondICmp - Compute the number of times the +/// ComputeExitLimitFromICmp - Compute the number of times the /// backedge of the specified loop will execute if its exit condition /// were a conditional branch of the ICmpInst ExitCond, TBB, and FBB. -ScalarEvolution::BackedgeTakenInfo -ScalarEvolution::ComputeBackedgeTakenCountFromExitCondICmp(const Loop *L, - ICmpInst *ExitCond, - BasicBlock *TBB, - BasicBlock *FBB) { +ScalarEvolution::ExitLimit +ScalarEvolution::ComputeExitLimitFromICmp(const Loop *L, + ICmpInst *ExitCond, + BasicBlock *TBB, + BasicBlock *FBB) { // If the condition was exit on true, convert the condition to exit on false ICmpInst::Predicate Cond; @@ -4207,8 +4443,8 @@ ScalarEvolution::ComputeBackedgeTakenCountFromExitCondICmp(const Loop *L, // Handle common loops like: for (X = "string"; *X; ++X) if (LoadInst *LI = dyn_cast(ExitCond->getOperand(0))) if (Constant *RHS = dyn_cast(ExitCond->getOperand(1))) { - BackedgeTakenInfo ItCnt = - ComputeLoadConstantCompareBackedgeTakenCount(LI, RHS, L, Cond); + ExitLimit ItCnt = + ComputeLoadConstantCompareExitLimit(LI, RHS, L, Cond); if (ItCnt.hasAnyInfo()) return ItCnt; } @@ -4247,36 +4483,36 @@ ScalarEvolution::ComputeBackedgeTakenCountFromExitCondICmp(const Loop *L, switch (Cond) { case ICmpInst::ICMP_NE: { // while (X != Y) // Convert to: while (X-Y != 0) - BackedgeTakenInfo BTI = HowFarToZero(getMinusSCEV(LHS, RHS), L); - if (BTI.hasAnyInfo()) return BTI; + ExitLimit EL = HowFarToZero(getMinusSCEV(LHS, RHS), L); + if (EL.hasAnyInfo()) return EL; break; } case ICmpInst::ICMP_EQ: { // while (X == Y) // Convert to: while (X-Y == 0) - BackedgeTakenInfo BTI = HowFarToNonZero(getMinusSCEV(LHS, RHS), L); - if (BTI.hasAnyInfo()) return BTI; + ExitLimit EL = HowFarToNonZero(getMinusSCEV(LHS, RHS), L); + if (EL.hasAnyInfo()) return EL; break; } case ICmpInst::ICMP_SLT: { - BackedgeTakenInfo BTI = HowManyLessThans(LHS, RHS, L, true); - if (BTI.hasAnyInfo()) return BTI; + ExitLimit EL = HowManyLessThans(LHS, RHS, L, true); + if (EL.hasAnyInfo()) return EL; break; } case ICmpInst::ICMP_SGT: { - BackedgeTakenInfo BTI = HowManyLessThans(getNotSCEV(LHS), + ExitLimit EL = HowManyLessThans(getNotSCEV(LHS), getNotSCEV(RHS), L, true); - if (BTI.hasAnyInfo()) return BTI; + if (EL.hasAnyInfo()) return EL; break; } case ICmpInst::ICMP_ULT: { - BackedgeTakenInfo BTI = HowManyLessThans(LHS, RHS, L, false); - if (BTI.hasAnyInfo()) return BTI; + ExitLimit EL = HowManyLessThans(LHS, RHS, L, false); + if (EL.hasAnyInfo()) return EL; break; } case ICmpInst::ICMP_UGT: { - BackedgeTakenInfo BTI = HowManyLessThans(getNotSCEV(LHS), + ExitLimit EL = HowManyLessThans(getNotSCEV(LHS), getNotSCEV(RHS), L, false); - if (BTI.hasAnyInfo()) return BTI; + if (EL.hasAnyInfo()) return EL; break; } default: @@ -4290,8 +4526,7 @@ ScalarEvolution::ComputeBackedgeTakenCountFromExitCondICmp(const Loop *L, #endif break; } - return - ComputeBackedgeTakenCountExhaustively(L, ExitCond, !L->contains(TBB)); + return ComputeExitCountExhaustively(L, ExitCond, !L->contains(TBB)); } static ConstantInt * @@ -4321,10 +4556,10 @@ GetAddressedElementFromGlobal(GlobalVariable *GV, if (Idx >= CA->getNumOperands()) return 0; // Bogus program Init = cast(CA->getOperand(Idx)); } else if (isa(Init)) { - if (const StructType *STy = dyn_cast(Init->getType())) { + if (StructType *STy = dyn_cast(Init->getType())) { assert(Idx < STy->getNumElements() && "Bad struct index!"); Init = Constant::getNullValue(STy->getElementType(Idx)); - } else if (const ArrayType *ATy = dyn_cast(Init->getType())) { + } else if (ArrayType *ATy = dyn_cast(Init->getType())) { if (Idx >= ATy->getNumElements()) return 0; // Bogus program Init = Constant::getNullValue(ATy->getElementType()); } else { @@ -4338,15 +4573,16 @@ GetAddressedElementFromGlobal(GlobalVariable *GV, return Init; } -/// ComputeLoadConstantCompareBackedgeTakenCount - Given an exit condition of +/// ComputeLoadConstantCompareExitLimit - Given an exit condition of /// 'icmp op load X, cst', try to see if we can compute the backedge /// execution count. -ScalarEvolution::BackedgeTakenInfo -ScalarEvolution::ComputeLoadConstantCompareBackedgeTakenCount( - LoadInst *LI, - Constant *RHS, - const Loop *L, - ICmpInst::Predicate predicate) { +ScalarEvolution::ExitLimit +ScalarEvolution::ComputeLoadConstantCompareExitLimit( + LoadInst *LI, + Constant *RHS, + const Loop *L, + ICmpInst::Predicate predicate) { + if (LI->isVolatile()) return getCouldNotCompute(); // Check to see if the loaded pointer is a getelementptr of a global. @@ -4431,69 +4667,117 @@ static bool CanConstantFold(const Instruction *I) { return false; } -/// getConstantEvolvingPHI - Given an LLVM value and a loop, return a PHI node -/// in the loop that V is derived from. We allow arbitrary operations along the -/// way, but the operands of an operation must either be constants or a value -/// derived from a constant PHI. If this expression does not fit with these -/// constraints, return null. -static PHINode *getConstantEvolvingPHI(Value *V, const Loop *L) { - // If this is not an instruction, or if this is an instruction outside of the - // loop, it can't be derived from a loop PHI. - Instruction *I = dyn_cast(V); - if (I == 0 || !L->contains(I)) return 0; +/// Determine whether this instruction can constant evolve within this loop +/// assuming its operands can all constant evolve. +static bool canConstantEvolve(Instruction *I, const Loop *L) { + // An instruction outside of the loop can't be derived from a loop PHI. + if (!L->contains(I)) return false; - if (PHINode *PN = dyn_cast(I)) { + if (isa(I)) { if (L->getHeader() == I->getParent()) - return PN; + return true; else // We don't currently keep track of the control flow needed to evaluate // PHIs, so we cannot handle PHIs inside of loops. - return 0; + return false; } // If we won't be able to constant fold this expression even if the operands - // are constants, return early. - if (!CanConstantFold(I)) return 0; + // are constants, bail early. + return CanConstantFold(I); +} + +/// getConstantEvolvingPHIOperands - Implement getConstantEvolvingPHI by +/// recursing through each instruction operand until reaching a loop header phi. +static PHINode * +getConstantEvolvingPHIOperands(Instruction *UseInst, const Loop *L, + DenseMap &PHIMap) { // Otherwise, we can evaluate this instruction if all of its operands are // constant or derived from a PHI node themselves. PHINode *PHI = 0; - for (unsigned Op = 0, e = I->getNumOperands(); Op != e; ++Op) - if (!isa(I->getOperand(Op))) { - PHINode *P = getConstantEvolvingPHI(I->getOperand(Op), L); - if (P == 0) return 0; // Not evolving from PHI - if (PHI == 0) - PHI = P; - else if (PHI != P) - return 0; // Evolving from multiple different PHIs. + for (Instruction::op_iterator OpI = UseInst->op_begin(), + OpE = UseInst->op_end(); OpI != OpE; ++OpI) { + + if (isa(*OpI)) continue; + + Instruction *OpInst = dyn_cast(*OpI); + if (!OpInst || !canConstantEvolve(OpInst, L)) return 0; + + PHINode *P = dyn_cast(OpInst); + if (!P) + // If this operand is already visited, reuse the prior result. + // We may have P != PHI if this is the deepest point at which the + // inconsistent paths meet. + P = PHIMap.lookup(OpInst); + if (!P) { + // Recurse and memoize the results, whether a phi is found or not. + // This recursive call invalidates pointers into PHIMap. + P = getConstantEvolvingPHIOperands(OpInst, L, PHIMap); + PHIMap[OpInst] = P; } - + if (P == 0) return 0; // Not evolving from PHI + if (PHI && PHI != P) return 0; // Evolving from multiple different PHIs. + PHI = P; + } // This is a expression evolving from a constant PHI! return PHI; } +/// getConstantEvolvingPHI - Given an LLVM value and a loop, return a PHI node +/// in the loop that V is derived from. We allow arbitrary operations along the +/// way, but the operands of an operation must either be constants or a value +/// derived from a constant PHI. If this expression does not fit with these +/// constraints, return null. +static PHINode *getConstantEvolvingPHI(Value *V, const Loop *L) { + Instruction *I = dyn_cast(V); + if (I == 0 || !canConstantEvolve(I, L)) return 0; + + if (PHINode *PN = dyn_cast(I)) { + return PN; + } + + // Record non-constant instructions contained by the loop. + DenseMap PHIMap; + return getConstantEvolvingPHIOperands(I, L, PHIMap); +} + /// EvaluateExpression - Given an expression that passes the /// getConstantEvolvingPHI predicate, evaluate its value assuming the PHI node /// in the loop has the value PHIVal. If we can't fold this expression for some /// reason, return null. -static Constant *EvaluateExpression(Value *V, Constant *PHIVal, +static Constant *EvaluateExpression(Value *V, const Loop *L, + DenseMap &Vals, const TargetData *TD) { - if (isa(V)) return PHIVal; + // Convenient constant check, but redundant for recursive calls. if (Constant *C = dyn_cast(V)) return C; + Instruction *I = cast(V); + if (Constant *C = Vals.lookup(I)) return C; + + assert(!isa(I) && "loop header phis should be mapped to constant"); + assert(canConstantEvolve(I, L) && "cannot evaluate expression in this loop"); + (void)L; std::vector Operands(I->getNumOperands()); for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) { - Operands[i] = EvaluateExpression(I->getOperand(i), PHIVal, TD); - if (Operands[i] == 0) return 0; + Instruction *Operand = dyn_cast(I->getOperand(i)); + if (!Operand) { + Operands[i] = dyn_cast(I->getOperand(i)); + if (!Operands[i]) return 0; + continue; + } + Constant *C = EvaluateExpression(Operand, L, Vals, TD); + Vals[Operand] = C; + if (!C) return 0; + Operands[i] = C; } if (const CmpInst *CI = dyn_cast(I)) return ConstantFoldCompareInstOperands(CI->getPredicate(), Operands[0], Operands[1], TD); - return ConstantFoldInstOperands(I->getOpcode(), I->getType(), - &Operands[0], Operands.size(), TD); + return ConstantFoldInstOperands(I->getOpcode(), I->getType(), Operands, TD); } /// getConstantEvolutionLoopExitValue - If we know that the specified Phi is @@ -4514,6 +4798,9 @@ ScalarEvolution::getConstantEvolutionLoopExitValue(PHINode *PN, Constant *&RetVal = ConstantEvolutionLoopExitValue[PN]; + // FIXME: Nick's fix for PR11034 will seed constants for multiple header phis. + DenseMap CurrentIterVals; + // Since the loop is canonicalized, the PHI node must have two entries. One // entry must be a constant (coming in from outside of the loop), and the // second must be derived from the same PHI. @@ -4522,6 +4809,7 @@ ScalarEvolution::getConstantEvolutionLoopExitValue(PHINode *PN, dyn_cast(PN->getIncomingValue(!SecondIsBackedge)); if (StartCST == 0) return RetVal = 0; // Must be a constant. + CurrentIterVals[PN] = StartCST; Value *BEValue = PN->getIncomingValue(SecondIsBackedge); if (getConstantEvolvingPHI(BEValue, L) != PN && @@ -4534,29 +4822,31 @@ ScalarEvolution::getConstantEvolutionLoopExitValue(PHINode *PN, unsigned NumIterations = BEs.getZExtValue(); // must be in range unsigned IterationNum = 0; - for (Constant *PHIVal = StartCST; ; ++IterationNum) { + for (; ; ++IterationNum) { if (IterationNum == NumIterations) - return RetVal = PHIVal; // Got exit value! + return RetVal = CurrentIterVals[PN]; // Got exit value! // Compute the value of the PHI node for the next iteration. - Constant *NextPHI = EvaluateExpression(BEValue, PHIVal, TD); - if (NextPHI == PHIVal) + // EvaluateExpression adds non-phi values to the CurrentIterVals map. + Constant *NextPHI = EvaluateExpression(BEValue, L, CurrentIterVals, TD); + if (NextPHI == CurrentIterVals[PN]) return RetVal = NextPHI; // Stopped evolving! if (NextPHI == 0) return 0; // Couldn't evaluate! - PHIVal = NextPHI; + DenseMap NextIterVals; + NextIterVals[PN] = NextPHI; + CurrentIterVals.swap(NextIterVals); } } -/// ComputeBackedgeTakenCountExhaustively - If the loop is known to execute a +/// ComputeExitCountExhaustively - If the loop is known to execute a /// constant number of times (the condition evolves only from constants), /// try to evaluate a few iterations of the loop until we get the exit /// condition gets a value of ExitWhen (true or false). If we cannot /// evaluate the trip count of the loop, return getCouldNotCompute(). -const SCEV * -ScalarEvolution::ComputeBackedgeTakenCountExhaustively(const Loop *L, - Value *Cond, - bool ExitWhen) { +const SCEV * ScalarEvolution::ComputeExitCountExhaustively(const Loop *L, + Value *Cond, + bool ExitWhen) { PHINode *PN = getConstantEvolvingPHI(Cond, L); if (PN == 0) return getCouldNotCompute(); @@ -4583,8 +4873,10 @@ ScalarEvolution::ComputeBackedgeTakenCountExhaustively(const Loop *L, unsigned MaxIterations = MaxBruteForceIterations; // Limit analysis. for (Constant *PHIVal = StartCST; IterationNum != MaxIterations; ++IterationNum) { + DenseMap PHIValMap; + PHIValMap[PN] = PHIVal; ConstantInt *CondVal = - dyn_cast_or_null(EvaluateExpression(Cond, PHIVal, TD)); + dyn_cast_or_null(EvaluateExpression(Cond, L, PHIValMap, TD)); // Couldn't symbolically evaluate. if (!CondVal) return getCouldNotCompute(); @@ -4595,7 +4887,7 @@ ScalarEvolution::ComputeBackedgeTakenCountExhaustively(const Loop *L, } // Compute the value of the PHI node for the next iteration. - Constant *NextPHI = EvaluateExpression(BEValue, PHIVal, TD); + Constant *NextPHI = EvaluateExpression(BEValue, L, PHIValMap, TD); if (NextPHI == 0 || NextPHI == PHIVal) return getCouldNotCompute();// Couldn't evaluate or not making progress... PHIVal = NextPHI; @@ -4703,7 +4995,7 @@ const SCEV *ScalarEvolution::computeSCEVAtScope(const SCEV *V, const Loop *L) { Operands[0], Operands[1], TD); else C = ConstantFoldInstOperands(I->getOpcode(), I->getType(), - &Operands[0], Operands.size(), TD); + Operands, TD); if (!C) return V; return getSCEV(C); } @@ -4925,7 +5217,7 @@ SolveQuadraticEquation(const SCEVAddRecExpr *AddRec, ScalarEvolution &SE) { // Compute the two solutions for the quadratic formula. // The divisions must be performed as signed divisions. APInt NegB(-B); - APInt TwoA( A << 1 ); + APInt TwoA(A << 1); if (TwoA.isMinValue()) { const SCEV *CNC = SE.getCouldNotCompute(); return std::make_pair(CNC, CNC); @@ -4940,7 +5232,7 @@ SolveQuadraticEquation(const SCEVAddRecExpr *AddRec, ScalarEvolution &SE) { return std::make_pair(SE.getConstant(Solution1), SE.getConstant(Solution2)); - } // end APIntOps namespace + } // end APIntOps namespace } /// HowFarToZero - Return the number of times a backedge comparing the specified @@ -4950,7 +5242,7 @@ SolveQuadraticEquation(const SCEVAddRecExpr *AddRec, ScalarEvolution &SE) { /// now expressed as a single expression, V = x-y. So the exit test is /// effectively V != 0. We know and take advantage of the fact that this /// expression only being used in a comparison by zero context. -ScalarEvolution::BackedgeTakenInfo +ScalarEvolution::ExitLimit ScalarEvolution::HowFarToZero(const SCEV *V, const Loop *L) { // If the value is a constant if (const SCEVConstant *C = dyn_cast(V)) { @@ -5034,8 +5326,19 @@ ScalarEvolution::HowFarToZero(const SCEV *V, const Loop *L) { // Handle unitary steps, which cannot wraparound. // 1*N = -Start; -1*N = Start (mod 2^BW), so: // N = Distance (as unsigned) - if (StepC->getValue()->equalsInt(1) || StepC->getValue()->isAllOnesValue()) - return Distance; + if (StepC->getValue()->equalsInt(1) || StepC->getValue()->isAllOnesValue()) { + ConstantRange CR = getUnsignedRange(Start); + const SCEV *MaxBECount; + if (!CountDown && CR.getUnsignedMin().isMinValue()) + // When counting up, the worst starting value is 1, not 0. + MaxBECount = CR.getUnsignedMax().isMinValue() + ? getConstant(APInt::getMinValue(CR.getBitWidth())) + : getConstant(APInt::getMaxValue(CR.getBitWidth())); + else + MaxBECount = getConstant(CountDown ? CR.getUnsignedMax() + : -CR.getUnsignedMin()); + return ExitLimit(Distance, MaxBECount); + } // If the recurrence is known not to wraparound, unsigned divide computes the // back edge count. We know that the value will either become zero (and thus @@ -5062,7 +5365,7 @@ ScalarEvolution::HowFarToZero(const SCEV *V, const Loop *L) { /// HowFarToNonZero - Return the number of times a backedge checking the /// specified value for nonzero will execute. If not computable, return /// CouldNotCompute -ScalarEvolution::BackedgeTakenInfo +ScalarEvolution::ExitLimit ScalarEvolution::HowFarToNonZero(const SCEV *V, const Loop *L) { // Loops that look like: while (X == 0) are very strange indeed. We don't // handle them yet except for the trivial case. This could be expanded in the @@ -5741,7 +6044,7 @@ const SCEV *ScalarEvolution::getBECount(const SCEV *Start, assert(!isKnownNegative(Step) && "This code doesn't handle negative strides yet!"); - const Type *Ty = Start->getType(); + Type *Ty = Start->getType(); // When Start == End, we have an exact BECount == 0. Short-circuit this case // here because SCEV may not be able to determine that the unsigned division @@ -5760,7 +6063,7 @@ const SCEV *ScalarEvolution::getBECount(const SCEV *Start, if (!NoWrap) { // Check Add for unsigned overflow. // TODO: More sophisticated things could be done here. - const Type *WideTy = IntegerType::get(getContext(), + Type *WideTy = IntegerType::get(getContext(), getTypeSizeInBits(Ty) + 1); const SCEV *EDiff = getZeroExtendExpr(Diff, WideTy); const SCEV *ERoundUp = getZeroExtendExpr(RoundUp, WideTy); @@ -5775,7 +6078,7 @@ const SCEV *ScalarEvolution::getBECount(const SCEV *Start, /// HowManyLessThans - Return the number of times a backedge containing the /// specified less-than comparison will execute. If not computable, return /// CouldNotCompute. -ScalarEvolution::BackedgeTakenInfo +ScalarEvolution::ExitLimit ScalarEvolution::HowManyLessThans(const SCEV *LHS, const SCEV *RHS, const Loop *L, bool isSigned) { // Only handle: "ADDREC < LoopInvariant". @@ -5882,7 +6185,7 @@ ScalarEvolution::HowManyLessThans(const SCEV *LHS, const SCEV *RHS, if (isa(MaxBECount)) MaxBECount = BECount; - return BackedgeTakenInfo(BECount, MaxBECount); + return ExitLimit(BECount, MaxBECount); } return getCouldNotCompute(); @@ -6090,6 +6393,15 @@ void ScalarEvolution::releaseMemory() { FirstUnknown = 0; ValueExprMap.clear(); + + // Free any extra memory created for ExitNotTakenInfo in the unlikely event + // that a loop had multiple computable exits. + for (DenseMap::iterator I = + BackedgeTakenCounts.begin(), E = BackedgeTakenCounts.end(); + I != E; ++I) { + I->second.clear(); + } + BackedgeTakenCounts.clear(); ConstantEvolutionLoopExitValue.clear(); ValuesAtScopes.clear(); diff --git a/contrib/llvm/lib/Analysis/ScalarEvolutionExpander.cpp b/contrib/llvm/lib/Analysis/ScalarEvolutionExpander.cpp index befe6d259..47f0f3211 100644 --- a/contrib/llvm/lib/Analysis/ScalarEvolutionExpander.cpp +++ b/contrib/llvm/lib/Analysis/ScalarEvolutionExpander.cpp @@ -17,6 +17,7 @@ #include "llvm/Analysis/LoopInfo.h" #include "llvm/IntrinsicInst.h" #include "llvm/LLVMContext.h" +#include "llvm/Support/Debug.h" #include "llvm/Target/TargetData.h" #include "llvm/ADT/STLExtras.h" @@ -26,7 +27,7 @@ using namespace llvm; /// reusing an existing cast if a suitable one exists, moving an existing /// cast if a suitable one exists but isn't in the right place, or /// creating a new one. -Value *SCEVExpander::ReuseOrCreateCast(Value *V, const Type *Ty, +Value *SCEVExpander::ReuseOrCreateCast(Value *V, Type *Ty, Instruction::CastOps Op, BasicBlock::iterator IP) { // Check to see if there is already a cast! @@ -62,7 +63,7 @@ Value *SCEVExpander::ReuseOrCreateCast(Value *V, const Type *Ty, /// InsertNoopCastOfTo - Insert a cast of V to the specified type, /// which must be possible with a noop cast, doing what we can to share /// the casts. -Value *SCEVExpander::InsertNoopCastOfTo(Value *V, const Type *Ty) { +Value *SCEVExpander::InsertNoopCastOfTo(Value *V, Type *Ty) { Instruction::CastOps Op = CastInst::getCastOpcode(V, false, Ty, false); assert((Op == Instruction::BitCast || Op == Instruction::PtrToInt || @@ -103,7 +104,8 @@ Value *SCEVExpander::InsertNoopCastOfTo(Value *V, const Type *Ty) { while ((isa(IP) && isa(cast(IP)->getOperand(0)) && cast(IP)->getOperand(0) != A) || - isa(IP)) + isa(IP) || + isa(IP)) ++IP; return ReuseOrCreateCast(A, Ty, Op, IP); } @@ -113,7 +115,9 @@ Value *SCEVExpander::InsertNoopCastOfTo(Value *V, const Type *Ty) { BasicBlock::iterator IP = I; ++IP; if (InvokeInst *II = dyn_cast(I)) IP = II->getNormalDest()->begin(); - while (isa(IP) || isa(IP)) ++IP; + while (isa(IP) || isa(IP) || + isa(IP)) + ++IP; return ReuseOrCreateCast(I, Ty, Op, IP); } @@ -160,7 +164,7 @@ Value *SCEVExpander::InsertBinop(Instruction::BinaryOps Opcode, } // If we haven't found this binop, insert it. - Instruction *BO = cast(Builder.CreateBinOp(Opcode, LHS, RHS, "tmp")); + Instruction *BO = cast(Builder.CreateBinOp(Opcode, LHS, RHS)); BO->setDebugLoc(SaveInsertPt->getDebugLoc()); rememberInstruction(BO); @@ -277,7 +281,7 @@ static bool FactorOutConstant(const SCEV *&S, /// the list. /// static void SimplifyAddOperands(SmallVectorImpl &Ops, - const Type *Ty, + Type *Ty, ScalarEvolution &SE) { unsigned NumAddRecs = 0; for (unsigned i = Ops.size(); i > 0 && isa(Ops[i-1]); --i) @@ -306,7 +310,7 @@ static void SimplifyAddOperands(SmallVectorImpl &Ops, /// into GEP indices. /// static void SplitAddRecs(SmallVectorImpl &Ops, - const Type *Ty, + Type *Ty, ScalarEvolution &SE) { // Find the addrecs. SmallVector AddRecs; @@ -365,10 +369,10 @@ static void SplitAddRecs(SmallVectorImpl &Ops, /// Value *SCEVExpander::expandAddToGEP(const SCEV *const *op_begin, const SCEV *const *op_end, - const PointerType *PTy, - const Type *Ty, + PointerType *PTy, + Type *Ty, Value *V) { - const Type *ElTy = PTy->getElementType(); + Type *ElTy = PTy->getElementType(); SmallVector GepIndices; SmallVector Ops(op_begin, op_end); bool AnyNonZeroIndices = false; @@ -423,7 +427,7 @@ Value *SCEVExpander::expandAddToGEP(const SCEV *const *op_begin, GepIndices.push_back(Scaled); // Collect struct field index operands. - while (const StructType *STy = dyn_cast(ElTy)) { + while (StructType *STy = dyn_cast(ElTy)) { bool FoundFieldNo = false; // An empty struct has no fields. if (STy->getNumElements() == 0) break; @@ -451,7 +455,7 @@ Value *SCEVExpander::expandAddToGEP(const SCEV *const *op_begin, // appropriate struct type. for (unsigned i = 0, e = Ops.size(); i != e; ++i) if (const SCEVUnknown *U = dyn_cast(Ops[i])) { - const Type *CTy; + Type *CTy; Constant *FieldNo; if (U->isOffsetOf(CTy, FieldNo) && CTy == STy) { GepIndices.push_back(FieldNo); @@ -474,7 +478,7 @@ Value *SCEVExpander::expandAddToGEP(const SCEV *const *op_begin, } } - if (const ArrayType *ATy = dyn_cast(ElTy)) + if (ArrayType *ATy = dyn_cast(ElTy)) ElTy = ATy->getElementType(); else break; @@ -494,7 +498,7 @@ Value *SCEVExpander::expandAddToGEP(const SCEV *const *op_begin, // Fold a GEP with constant operands. if (Constant *CLHS = dyn_cast(V)) if (Constant *CRHS = dyn_cast(Idx)) - return ConstantExpr::getGetElementPtr(CLHS, &CRHS, 1); + return ConstantExpr::getGetElementPtr(CLHS, CRHS); // Do a quick scan to see if we have this GEP nearby. If so, reuse it. unsigned ScanLimit = 6; @@ -572,8 +576,7 @@ Value *SCEVExpander::expandAddToGEP(const SCEV *const *op_begin, if (V->getType() != PTy) Casted = InsertNoopCastOfTo(Casted, PTy); Value *GEP = Builder.CreateGEP(Casted, - GepIndices.begin(), - GepIndices.end(), + GepIndices, "scevgep"); Ops.push_back(SE.getUnknown(GEP)); rememberInstruction(GEP); @@ -691,7 +694,7 @@ public: } Value *SCEVExpander::visitAddExpr(const SCEVAddExpr *S) { - const Type *Ty = SE.getEffectiveSCEVType(S->getType()); + Type *Ty = SE.getEffectiveSCEVType(S->getType()); // Collect all the add operands in a loop, along with their associated loops. // Iterate in reverse so that constants are emitted last, all else equal, and @@ -717,7 +720,7 @@ Value *SCEVExpander::visitAddExpr(const SCEVAddExpr *S) { // This is the first operand. Just expand it. Sum = expand(Op); ++I; - } else if (const PointerType *PTy = dyn_cast(Sum->getType())) { + } else if (PointerType *PTy = dyn_cast(Sum->getType())) { // The running sum expression is a pointer. Try to form a getelementptr // at this level with that as the base. SmallVector NewOps; @@ -731,7 +734,7 @@ Value *SCEVExpander::visitAddExpr(const SCEVAddExpr *S) { NewOps.push_back(X); } Sum = expandAddToGEP(NewOps.begin(), NewOps.end(), PTy, Ty, Sum); - } else if (const PointerType *PTy = dyn_cast(Op->getType())) { + } else if (PointerType *PTy = dyn_cast(Op->getType())) { // The running sum is an integer, and there's a pointer at this level. // Try to form a getelementptr. If the running sum is instructions, // use a SCEVUnknown to avoid re-analyzing them. @@ -762,7 +765,7 @@ Value *SCEVExpander::visitAddExpr(const SCEVAddExpr *S) { } Value *SCEVExpander::visitMulExpr(const SCEVMulExpr *S) { - const Type *Ty = SE.getEffectiveSCEVType(S->getType()); + Type *Ty = SE.getEffectiveSCEVType(S->getType()); // Collect all the mul operands in a loop, along with their associated loops. // Iterate in reverse so that constants are emitted last, all else equal. @@ -804,7 +807,7 @@ Value *SCEVExpander::visitMulExpr(const SCEVMulExpr *S) { } Value *SCEVExpander::visitUDivExpr(const SCEVUDivExpr *S) { - const Type *Ty = SE.getEffectiveSCEVType(S->getType()); + Type *Ty = SE.getEffectiveSCEVType(S->getType()); Value *LHS = expandCodeFor(S->getLHS(), Ty); if (const SCEVConstant *SC = dyn_cast(S->getRHS())) { @@ -841,81 +844,141 @@ static void ExposePointerBase(const SCEV *&Base, const SCEV *&Rest, } } +/// Determine if this is a well-behaved chain of instructions leading back to +/// the PHI. If so, it may be reused by expanded expressions. +bool SCEVExpander::isNormalAddRecExprPHI(PHINode *PN, Instruction *IncV, + const Loop *L) { + if (IncV->getNumOperands() == 0 || isa(IncV) || + (isa(IncV) && !isa(IncV))) + return false; + // If any of the operands don't dominate the insert position, bail. + // Addrec operands are always loop-invariant, so this can only happen + // if there are instructions which haven't been hoisted. + if (L == IVIncInsertLoop) { + for (User::op_iterator OI = IncV->op_begin()+1, + OE = IncV->op_end(); OI != OE; ++OI) + if (Instruction *OInst = dyn_cast(OI)) + if (!SE.DT->dominates(OInst, IVIncInsertPos)) + return false; + } + // Advance to the next instruction. + IncV = dyn_cast(IncV->getOperand(0)); + if (!IncV) + return false; + + if (IncV->mayHaveSideEffects()) + return false; + + if (IncV != PN) + return true; + + return isNormalAddRecExprPHI(PN, IncV, L); +} + +/// Determine if this cyclic phi is in a form that would have been generated by +/// LSR. We don't care if the phi was actually expanded in this pass, as long +/// as it is in a low-cost form, for example, no implied multiplication. This +/// should match any patterns generated by getAddRecExprPHILiterally and +/// expandAddtoGEP. +bool SCEVExpander::isExpandedAddRecExprPHI(PHINode *PN, Instruction *IncV, + const Loop *L) { + switch (IncV->getOpcode()) { + // Check for a simple Add/Sub or GEP of a loop invariant step. + case Instruction::Add: + case Instruction::Sub: + return IncV->getOperand(0) == PN + && L->isLoopInvariant(IncV->getOperand(1)); + case Instruction::BitCast: + IncV = dyn_cast(IncV->getOperand(0)); + if (!IncV) + return false; + // fall-thru to GEP handling + case Instruction::GetElementPtr: { + // This must be a pointer addition of constants (pretty) or some number of + // address-size elements (ugly). + for (Instruction::op_iterator I = IncV->op_begin()+1, E = IncV->op_end(); + I != E; ++I) { + if (isa(*I)) + continue; + // ugly geps have 2 operands. + // i1* is used by the expander to represent an address-size element. + if (IncV->getNumOperands() != 2) + return false; + unsigned AS = cast(IncV->getType())->getAddressSpace(); + if (IncV->getType() != Type::getInt1PtrTy(SE.getContext(), AS) + && IncV->getType() != Type::getInt8PtrTy(SE.getContext(), AS)) + return false; + // Ensure the operands dominate the insertion point. I don't know of a + // case when this would not be true, so this is somewhat untested. + if (L == IVIncInsertLoop) { + for (User::op_iterator OI = IncV->op_begin()+1, + OE = IncV->op_end(); OI != OE; ++OI) + if (Instruction *OInst = dyn_cast(OI)) + if (!SE.DT->dominates(OInst, IVIncInsertPos)) + return false; + } + break; + } + IncV = dyn_cast(IncV->getOperand(0)); + if (IncV && IncV->getOpcode() == Instruction::BitCast) + IncV = dyn_cast(IncV->getOperand(0)); + return IncV == PN; + } + default: + return false; + } +} + /// getAddRecExprPHILiterally - Helper for expandAddRecExprLiterally. Expand /// the base addrec, which is the addrec without any non-loop-dominating /// values, and return the PHI. PHINode * SCEVExpander::getAddRecExprPHILiterally(const SCEVAddRecExpr *Normalized, const Loop *L, - const Type *ExpandTy, - const Type *IntTy) { + Type *ExpandTy, + Type *IntTy) { assert((!IVIncInsertLoop||IVIncInsertPos) && "Uninitialized insert position"); // Reuse a previously-inserted PHI, if present. - for (BasicBlock::iterator I = L->getHeader()->begin(); - PHINode *PN = dyn_cast(I); ++I) - if (SE.isSCEVable(PN->getType()) && - (SE.getEffectiveSCEVType(PN->getType()) == - SE.getEffectiveSCEVType(Normalized->getType())) && - SE.getSCEV(PN) == Normalized) - if (BasicBlock *LatchBlock = L->getLoopLatch()) { - Instruction *IncV = - cast(PN->getIncomingValueForBlock(LatchBlock)); - - // Determine if this is a well-behaved chain of instructions leading - // back to the PHI. It probably will be, if we're scanning an inner - // loop already visited by LSR for example, but it wouldn't have - // to be. + BasicBlock *LatchBlock = L->getLoopLatch(); + if (LatchBlock) { + for (BasicBlock::iterator I = L->getHeader()->begin(); + PHINode *PN = dyn_cast(I); ++I) { + if (!SE.isSCEVable(PN->getType()) || + (SE.getEffectiveSCEVType(PN->getType()) != + SE.getEffectiveSCEVType(Normalized->getType())) || + SE.getSCEV(PN) != Normalized) + continue; + + Instruction *IncV = + cast(PN->getIncomingValueForBlock(LatchBlock)); + + if (LSRMode) { + if (!isExpandedAddRecExprPHI(PN, IncV, L)) + continue; + } + else { + if (!isNormalAddRecExprPHI(PN, IncV, L)) + continue; + } + // Ok, the add recurrence looks usable. + // Remember this PHI, even in post-inc mode. + InsertedValues.insert(PN); + // Remember the increment. + rememberInstruction(IncV); + if (L == IVIncInsertLoop) do { - if (IncV->getNumOperands() == 0 || isa(IncV) || - (isa(IncV) && !isa(IncV))) { - IncV = 0; + if (SE.DT->dominates(IncV, IVIncInsertPos)) break; - } - // If any of the operands don't dominate the insert position, bail. - // Addrec operands are always loop-invariant, so this can only happen - // if there are instructions which haven't been hoisted. - if (L == IVIncInsertLoop) { - for (User::op_iterator OI = IncV->op_begin()+1, - OE = IncV->op_end(); OI != OE; ++OI) - if (Instruction *OInst = dyn_cast(OI)) - if (!SE.DT->dominates(OInst, IVIncInsertPos)) { - IncV = 0; - break; - } - } - if (!IncV) - break; - // Advance to the next instruction. - IncV = dyn_cast(IncV->getOperand(0)); - if (!IncV) - break; - if (IncV->mayHaveSideEffects()) { - IncV = 0; - break; - } + // Make sure the increment is where we want it. But don't move it + // down past a potential existing post-inc user. + IncV->moveBefore(IVIncInsertPos); + IVIncInsertPos = IncV; + IncV = cast(IncV->getOperand(0)); } while (IncV != PN); - - if (IncV) { - // Ok, the add recurrence looks usable. - // Remember this PHI, even in post-inc mode. - InsertedValues.insert(PN); - // Remember the increment. - IncV = cast(PN->getIncomingValueForBlock(LatchBlock)); - rememberInstruction(IncV); - if (L == IVIncInsertLoop) - do { - if (SE.DT->dominates(IncV, IVIncInsertPos)) - break; - // Make sure the increment is where we want it. But don't move it - // down past a potential existing post-inc user. - IncV->moveBefore(IVIncInsertPos); - IVIncInsertPos = IncV; - IncV = cast(IncV->getOperand(0)); - } while (IncV != PN); - return PN; - } - } + return PN; + } + } // Save the original insertion point so we can restore it when we're done. BasicBlock *SaveInsertBB = Builder.GetInsertBlock(); @@ -969,7 +1032,7 @@ SCEVExpander::getAddRecExprPHILiterally(const SCEVAddRecExpr *Normalized, Value *IncV; // If the PHI is a pointer, use a GEP, otherwise use an add or sub. if (isPointer) { - const PointerType *GEPPtrTy = cast(ExpandTy); + PointerType *GEPPtrTy = cast(ExpandTy); // If the step isn't constant, don't use an implicitly scaled GEP, because // that would require a multiply inside the loop. if (!isa(StepV)) @@ -978,7 +1041,7 @@ SCEVExpander::getAddRecExprPHILiterally(const SCEVAddRecExpr *Normalized, const SCEV *const StepArray[1] = { SE.getSCEV(StepV) }; IncV = expandAddToGEP(StepArray, StepArray+1, GEPPtrTy, IntTy, PN); if (IncV->getType() != PN->getType()) { - IncV = Builder.CreateBitCast(IncV, PN->getType(), "tmp"); + IncV = Builder.CreateBitCast(IncV, PN->getType()); rememberInstruction(IncV); } } else { @@ -1001,8 +1064,8 @@ SCEVExpander::getAddRecExprPHILiterally(const SCEVAddRecExpr *Normalized, } Value *SCEVExpander::expandAddRecExprLiterally(const SCEVAddRecExpr *S) { - const Type *STy = S->getType(); - const Type *IntTy = SE.getEffectiveSCEVType(STy); + Type *STy = S->getType(); + Type *IntTy = SE.getEffectiveSCEVType(STy); const Loop *L = S->getLoop(); // Determine a normalized form of this expression, which is the expression @@ -1045,7 +1108,7 @@ Value *SCEVExpander::expandAddRecExprLiterally(const SCEVAddRecExpr *S) { // Expand the core addrec. If we need post-loop scaling, force it to // expand to an integer type to avoid the need for additional casting. - const Type *ExpandTy = PostLoopScale ? IntTy : STy; + Type *ExpandTy = PostLoopScale ? IntTy : STy; PHINode *PN = getAddRecExprPHILiterally(Normalized, L, ExpandTy, IntTy); // Accommodate post-inc mode, if necessary. @@ -1057,6 +1120,14 @@ Value *SCEVExpander::expandAddRecExprLiterally(const SCEVAddRecExpr *S) { BasicBlock *LatchBlock = L->getLoopLatch(); assert(LatchBlock && "PostInc mode requires a unique loop latch!"); Result = PN->getIncomingValueForBlock(LatchBlock); + + // For an expansion to use the postinc form, the client must call + // expandCodeFor with an InsertPoint that is either outside the PostIncLoop + // or dominated by IVIncInsertPos. + assert((!isa(Result) || + SE.DT->dominates(cast(Result), + Builder.GetInsertPoint())) && + "postinc expansion does not dominate use"); } // Re-apply any non-loop-dominating scale. @@ -1069,7 +1140,7 @@ Value *SCEVExpander::expandAddRecExprLiterally(const SCEVAddRecExpr *S) { // Re-apply any non-loop-dominating offset. if (PostLoopOffset) { - if (const PointerType *PTy = dyn_cast(ExpandTy)) { + if (PointerType *PTy = dyn_cast(ExpandTy)) { const SCEV *const OffsetArray[1] = { PostLoopOffset }; Result = expandAddToGEP(OffsetArray, OffsetArray+1, PTy, IntTy, Result); } else { @@ -1086,7 +1157,7 @@ Value *SCEVExpander::expandAddRecExprLiterally(const SCEVAddRecExpr *S) { Value *SCEVExpander::visitAddRecExpr(const SCEVAddRecExpr *S) { if (!CanonicalMode) return expandAddRecExprLiterally(S); - const Type *Ty = SE.getEffectiveSCEVType(S->getType()); + Type *Ty = SE.getEffectiveSCEVType(S->getType()); const Loop *L = S->getLoop(); // First check for an existing canonical IV in a suitable type. @@ -1110,7 +1181,8 @@ Value *SCEVExpander::visitAddRecExpr(const SCEVAddRecExpr *S) { BasicBlock::iterator SaveInsertPt = Builder.GetInsertPoint(); BasicBlock::iterator NewInsertPt = llvm::next(BasicBlock::iterator(cast(V))); - while (isa(NewInsertPt) || isa(NewInsertPt)) + while (isa(NewInsertPt) || isa(NewInsertPt) || + isa(NewInsertPt)) ++NewInsertPt; V = expandCodeFor(SE.getTruncateExpr(SE.getUnknown(V), Ty), 0, NewInsertPt); @@ -1132,7 +1204,7 @@ Value *SCEVExpander::visitAddRecExpr(const SCEVAddRecExpr *S) { // Dig into the expression to find the pointer base for a GEP. ExposePointerBase(Base, RestArray[0], SE); // If we found a pointer, expand the AddRec with a GEP. - if (const PointerType *PTy = dyn_cast(Base->getType())) { + if (PointerType *PTy = dyn_cast(Base->getType())) { // Make sure the Base isn't something exotic, such as a multiplied // or divided pointer value. In those cases, the result type isn't // actually a pointer type. @@ -1216,35 +1288,35 @@ Value *SCEVExpander::visitAddRecExpr(const SCEVAddRecExpr *S) { } Value *SCEVExpander::visitTruncateExpr(const SCEVTruncateExpr *S) { - const Type *Ty = SE.getEffectiveSCEVType(S->getType()); + Type *Ty = SE.getEffectiveSCEVType(S->getType()); Value *V = expandCodeFor(S->getOperand(), SE.getEffectiveSCEVType(S->getOperand()->getType())); - Value *I = Builder.CreateTrunc(V, Ty, "tmp"); + Value *I = Builder.CreateTrunc(V, Ty); rememberInstruction(I); return I; } Value *SCEVExpander::visitZeroExtendExpr(const SCEVZeroExtendExpr *S) { - const Type *Ty = SE.getEffectiveSCEVType(S->getType()); + Type *Ty = SE.getEffectiveSCEVType(S->getType()); Value *V = expandCodeFor(S->getOperand(), SE.getEffectiveSCEVType(S->getOperand()->getType())); - Value *I = Builder.CreateZExt(V, Ty, "tmp"); + Value *I = Builder.CreateZExt(V, Ty); rememberInstruction(I); return I; } Value *SCEVExpander::visitSignExtendExpr(const SCEVSignExtendExpr *S) { - const Type *Ty = SE.getEffectiveSCEVType(S->getType()); + Type *Ty = SE.getEffectiveSCEVType(S->getType()); Value *V = expandCodeFor(S->getOperand(), SE.getEffectiveSCEVType(S->getOperand()->getType())); - Value *I = Builder.CreateSExt(V, Ty, "tmp"); + Value *I = Builder.CreateSExt(V, Ty); rememberInstruction(I); return I; } Value *SCEVExpander::visitSMaxExpr(const SCEVSMaxExpr *S) { Value *LHS = expand(S->getOperand(S->getNumOperands()-1)); - const Type *Ty = LHS->getType(); + Type *Ty = LHS->getType(); for (int i = S->getNumOperands()-2; i >= 0; --i) { // In the case of mixed integer and pointer types, do the // rest of the comparisons as integer. @@ -1253,7 +1325,7 @@ Value *SCEVExpander::visitSMaxExpr(const SCEVSMaxExpr *S) { LHS = InsertNoopCastOfTo(LHS, Ty); } Value *RHS = expandCodeFor(S->getOperand(i), Ty); - Value *ICmp = Builder.CreateICmpSGT(LHS, RHS, "tmp"); + Value *ICmp = Builder.CreateICmpSGT(LHS, RHS); rememberInstruction(ICmp); Value *Sel = Builder.CreateSelect(ICmp, LHS, RHS, "smax"); rememberInstruction(Sel); @@ -1268,7 +1340,7 @@ Value *SCEVExpander::visitSMaxExpr(const SCEVSMaxExpr *S) { Value *SCEVExpander::visitUMaxExpr(const SCEVUMaxExpr *S) { Value *LHS = expand(S->getOperand(S->getNumOperands()-1)); - const Type *Ty = LHS->getType(); + Type *Ty = LHS->getType(); for (int i = S->getNumOperands()-2; i >= 0; --i) { // In the case of mixed integer and pointer types, do the // rest of the comparisons as integer. @@ -1277,7 +1349,7 @@ Value *SCEVExpander::visitUMaxExpr(const SCEVUMaxExpr *S) { LHS = InsertNoopCastOfTo(LHS, Ty); } Value *RHS = expandCodeFor(S->getOperand(i), Ty); - Value *ICmp = Builder.CreateICmpUGT(LHS, RHS, "tmp"); + Value *ICmp = Builder.CreateICmpUGT(LHS, RHS); rememberInstruction(ICmp); Value *Sel = Builder.CreateSelect(ICmp, LHS, RHS, "umax"); rememberInstruction(Sel); @@ -1290,7 +1362,7 @@ Value *SCEVExpander::visitUMaxExpr(const SCEVUMaxExpr *S) { return LHS; } -Value *SCEVExpander::expandCodeFor(const SCEV *SH, const Type *Ty, +Value *SCEVExpander::expandCodeFor(const SCEV *SH, Type *Ty, Instruction *I) { BasicBlock::iterator IP = I; while (isInsertedInstruction(IP) || isa(IP)) @@ -1299,7 +1371,7 @@ Value *SCEVExpander::expandCodeFor(const SCEV *SH, const Type *Ty, return expandCodeFor(SH, Ty); } -Value *SCEVExpander::expandCodeFor(const SCEV *SH, const Type *Ty) { +Value *SCEVExpander::expandCodeFor(const SCEV *SH, Type *Ty) { // Expand the code for this SCEV. Value *V = expand(SH); if (Ty) { @@ -1325,7 +1397,7 @@ Value *SCEVExpander::expand(const SCEV *S) { // after the PHIs (and after any other instructions that we've inserted // there) so that it is guaranteed to dominate any user inside the loop. if (L && SE.hasComputableLoopEvolution(S, L) && !PostIncLoops.count(L)) - InsertPt = L->getHeader()->getFirstNonPHI(); + InsertPt = L->getHeader()->getFirstInsertionPt(); while (isInsertedInstruction(InsertPt) || isa(InsertPt)) InsertPt = llvm::next(BasicBlock::iterator(InsertPt)); break; @@ -1346,8 +1418,12 @@ Value *SCEVExpander::expand(const SCEV *S) { Value *V = visit(S); // Remember the expanded value for this SCEV at this location. - if (PostIncLoops.empty()) - InsertedExpressions[std::make_pair(S, InsertPt)] = V; + // + // This is independent of PostIncLoops. The mapped value simply materializes + // the expression at this insertion point. If the mapped value happened to be + // a postinc expansion, it could be reused by a non postinc user, but only if + // its insertion point was already at the head of the loop. + InsertedExpressions[std::make_pair(S, InsertPt)] = V; restoreInsertPoint(SaveInsertBB, SaveInsertPt); return V; @@ -1384,7 +1460,7 @@ void SCEVExpander::restoreInsertPoint(BasicBlock *BB, BasicBlock::iterator I) { /// starts at zero and steps by one on each iteration. PHINode * SCEVExpander::getOrInsertCanonicalInductionVariable(const Loop *L, - const Type *Ty) { + Type *Ty) { assert(Ty->isIntegerTy() && "Can only insert integer induction variables!"); // Build a SCEV for {0,+,1}. @@ -1401,3 +1477,102 @@ SCEVExpander::getOrInsertCanonicalInductionVariable(const Loop *L, return V; } + +/// hoistStep - Attempt to hoist an IV increment above a potential use. +/// +/// To successfully hoist, two criteria must be met: +/// - IncV operands dominate InsertPos and +/// - InsertPos dominates IncV +/// +/// Meeting the second condition means that we don't need to check all of IncV's +/// existing uses (it's moving up in the domtree). +/// +/// This does not yet recursively hoist the operands, although that would +/// not be difficult. +/// +/// This does not require a SCEVExpander instance and could be replaced by a +/// general code-insertion helper. +bool SCEVExpander::hoistStep(Instruction *IncV, Instruction *InsertPos, + const DominatorTree *DT) { + if (DT->dominates(IncV, InsertPos)) + return true; + + if (!DT->dominates(InsertPos->getParent(), IncV->getParent())) + return false; + + if (IncV->mayHaveSideEffects()) + return false; + + // Attempt to hoist IncV + for (User::op_iterator OI = IncV->op_begin(), OE = IncV->op_end(); + OI != OE; ++OI) { + Instruction *OInst = dyn_cast(OI); + if (OInst && !DT->dominates(OInst, InsertPos)) + return false; + } + IncV->moveBefore(InsertPos); + return true; +} + +/// replaceCongruentIVs - Check for congruent phis in this loop header and +/// replace them with their most canonical representative. Return the number of +/// phis eliminated. +/// +/// This does not depend on any SCEVExpander state but should be used in +/// the same context that SCEVExpander is used. +unsigned SCEVExpander::replaceCongruentIVs(Loop *L, const DominatorTree *DT, + SmallVectorImpl &DeadInsts) { + unsigned NumElim = 0; + DenseMap ExprToIVMap; + for (BasicBlock::iterator I = L->getHeader()->begin(); isa(I); ++I) { + PHINode *Phi = cast(I); + if (!SE.isSCEVable(Phi->getType())) + continue; + + PHINode *&OrigPhiRef = ExprToIVMap[SE.getSCEV(Phi)]; + if (!OrigPhiRef) { + OrigPhiRef = Phi; + continue; + } + + // If one phi derives from the other via GEPs, types may differ. + // We could consider adding a bitcast here to handle it. + if (OrigPhiRef->getType() != Phi->getType()) + continue; + + if (BasicBlock *LatchBlock = L->getLoopLatch()) { + Instruction *OrigInc = + cast(OrigPhiRef->getIncomingValueForBlock(LatchBlock)); + Instruction *IsomorphicInc = + cast(Phi->getIncomingValueForBlock(LatchBlock)); + + // If this phi is more canonical, swap it with the original. + if (!isExpandedAddRecExprPHI(OrigPhiRef, OrigInc, L) + && isExpandedAddRecExprPHI(Phi, IsomorphicInc, L)) { + std::swap(OrigPhiRef, Phi); + std::swap(OrigInc, IsomorphicInc); + } + // Replacing the congruent phi is sufficient because acyclic redundancy + // elimination, CSE/GVN, should handle the rest. However, once SCEV proves + // that a phi is congruent, it's often the head of an IV user cycle that + // is isomorphic with the original phi. So it's worth eagerly cleaning up + // the common case of a single IV increment. + if (OrigInc != IsomorphicInc && + OrigInc->getType() == IsomorphicInc->getType() && + SE.getSCEV(OrigInc) == SE.getSCEV(IsomorphicInc) && + hoistStep(OrigInc, IsomorphicInc, DT)) { + DEBUG_WITH_TYPE(DebugType, dbgs() + << "INDVARS: Eliminated congruent iv.inc: " + << *IsomorphicInc << '\n'); + IsomorphicInc->replaceAllUsesWith(OrigInc); + DeadInsts.push_back(IsomorphicInc); + } + } + DEBUG_WITH_TYPE(DebugType, dbgs() + << "INDVARS: Eliminated congruent iv: " << *Phi << '\n'); + ++NumElim; + Phi->replaceAllUsesWith(OrigPhiRef); + DeadInsts.push_back(Phi); + } + return NumElim; +} diff --git a/contrib/llvm/lib/Analysis/ScalarEvolutionNormalization.cpp b/contrib/llvm/lib/Analysis/ScalarEvolutionNormalization.cpp index 60e630aaa..c66ecd6e8 100644 --- a/contrib/llvm/lib/Analysis/ScalarEvolutionNormalization.cpp +++ b/contrib/llvm/lib/Analysis/ScalarEvolutionNormalization.cpp @@ -60,20 +60,40 @@ static bool IVUseShouldUsePostIncValue(Instruction *User, Value *Operand, return true; } -const SCEV *llvm::TransformForPostIncUse(TransformKind Kind, - const SCEV *S, - Instruction *User, - Value *OperandValToReplace, - PostIncLoopSet &Loops, - ScalarEvolution &SE, - DominatorTree &DT) { - if (isa(S) || isa(S)) - return S; +namespace { + +/// Hold the state used during post-inc expression transformation, including a +/// map of transformed expressions. +class PostIncTransform { + TransformKind Kind; + PostIncLoopSet &Loops; + ScalarEvolution &SE; + DominatorTree &DT; + + DenseMap Transformed; + +public: + PostIncTransform(TransformKind kind, PostIncLoopSet &loops, + ScalarEvolution &se, DominatorTree &dt): + Kind(kind), Loops(loops), SE(se), DT(dt) {} + + const SCEV *TransformSubExpr(const SCEV *S, Instruction *User, + Value *OperandValToReplace); + +protected: + const SCEV *TransformImpl(const SCEV *S, Instruction *User, + Value *OperandValToReplace); +}; + +} // namespace + +/// Implement post-inc transformation for all valid expression types. +const SCEV *PostIncTransform:: +TransformImpl(const SCEV *S, Instruction *User, Value *OperandValToReplace) { if (const SCEVCastExpr *X = dyn_cast(S)) { const SCEV *O = X->getOperand(); - const SCEV *N = TransformForPostIncUse(Kind, O, User, OperandValToReplace, - Loops, SE, DT); + const SCEV *N = TransformSubExpr(O, User, OperandValToReplace); if (O != N) switch (S->getSCEVType()) { case scZeroExtend: return SE.getZeroExtendExpr(N, S->getType()); @@ -93,9 +113,7 @@ const SCEV *llvm::TransformForPostIncUse(TransformKind Kind, // Transform each operand. for (SCEVNAryExpr::op_iterator I = AR->op_begin(), E = AR->op_end(); I != E; ++I) { - const SCEV *O = *I; - const SCEV *N = TransformForPostIncUse(Kind, O, LUser, 0, Loops, SE, DT); - Operands.push_back(N); + Operands.push_back(TransformSubExpr(*I, LUser, 0)); } // Conservatively use AnyWrap until/unless we need FlagNW. const SCEV *Result = SE.getAddRecExpr(Operands, L, SCEV::FlagAnyWrap); @@ -104,8 +122,8 @@ const SCEV *llvm::TransformForPostIncUse(TransformKind Kind, case NormalizeAutodetect: if (IVUseShouldUsePostIncValue(User, OperandValToReplace, L, &DT)) { const SCEV *TransformedStep = - TransformForPostIncUse(Kind, AR->getStepRecurrence(SE), - User, OperandValToReplace, Loops, SE, DT); + TransformSubExpr(AR->getStepRecurrence(SE), + User, OperandValToReplace); Result = SE.getMinusSCEV(Result, TransformedStep); Loops.insert(L); } @@ -114,24 +132,20 @@ const SCEV *llvm::TransformForPostIncUse(TransformKind Kind, // sometimes fails to canonicalize two equal SCEVs to exactly the same // form. It's possibly a pessimization when this happens, but it isn't a // correctness problem, so disable this assert for now. - assert(S == TransformForPostIncUse(Denormalize, Result, - User, OperandValToReplace, - Loops, SE, DT) && + assert(S == TransformSubExpr(Result, User, OperandValToReplace) && "SCEV normalization is not invertible!"); #endif break; case Normalize: if (Loops.count(L)) { const SCEV *TransformedStep = - TransformForPostIncUse(Kind, AR->getStepRecurrence(SE), - User, OperandValToReplace, Loops, SE, DT); + TransformSubExpr(AR->getStepRecurrence(SE), + User, OperandValToReplace); Result = SE.getMinusSCEV(Result, TransformedStep); } #if 0 // See the comment on the assert above. - assert(S == TransformForPostIncUse(Denormalize, Result, - User, OperandValToReplace, - Loops, SE, DT) && + assert(S == TransformSubExpr(Result, User, OperandValToReplace) && "SCEV normalization is not invertible!"); #endif break; @@ -150,8 +164,7 @@ const SCEV *llvm::TransformForPostIncUse(TransformKind Kind, for (SCEVNAryExpr::op_iterator I = X->op_begin(), E = X->op_end(); I != E; ++I) { const SCEV *O = *I; - const SCEV *N = TransformForPostIncUse(Kind, O, User, OperandValToReplace, - Loops, SE, DT); + const SCEV *N = TransformSubExpr(O, User, OperandValToReplace); Changed |= N != O; Operands.push_back(N); } @@ -170,10 +183,8 @@ const SCEV *llvm::TransformForPostIncUse(TransformKind Kind, if (const SCEVUDivExpr *X = dyn_cast(S)) { const SCEV *LO = X->getLHS(); const SCEV *RO = X->getRHS(); - const SCEV *LN = TransformForPostIncUse(Kind, LO, User, OperandValToReplace, - Loops, SE, DT); - const SCEV *RN = TransformForPostIncUse(Kind, RO, User, OperandValToReplace, - Loops, SE, DT); + const SCEV *LN = TransformSubExpr(LO, User, OperandValToReplace); + const SCEV *RN = TransformSubExpr(RO, User, OperandValToReplace); if (LO != LN || RO != RN) return SE.getUDivExpr(LN, RN); return S; @@ -182,3 +193,33 @@ const SCEV *llvm::TransformForPostIncUse(TransformKind Kind, llvm_unreachable("Unexpected SCEV kind!"); return 0; } + +/// Manage recursive transformation across an expression DAG. Revisiting +/// expressions would lead to exponential recursion. +const SCEV *PostIncTransform:: +TransformSubExpr(const SCEV *S, Instruction *User, Value *OperandValToReplace) { + + if (isa(S) || isa(S)) + return S; + + const SCEV *Result = Transformed.lookup(S); + if (Result) + return Result; + + Result = TransformImpl(S, User, OperandValToReplace); + Transformed[S] = Result; + return Result; +} + +/// Top level driver for transforming an expression DAG into its requested +/// post-inc form (either "Normalized" or "Denormalized". +const SCEV *llvm::TransformForPostIncUse(TransformKind Kind, + const SCEV *S, + Instruction *User, + Value *OperandValToReplace, + PostIncLoopSet &Loops, + ScalarEvolution &SE, + DominatorTree &DT) { + PostIncTransform Transform(Kind, Loops, SE, DT); + return Transform.TransformSubExpr(S, User, OperandValToReplace); +} diff --git a/contrib/llvm/lib/Analysis/ValueTracking.cpp b/contrib/llvm/lib/Analysis/ValueTracking.cpp index 455c91077..4d94f619f 100644 --- a/contrib/llvm/lib/Analysis/ValueTracking.cpp +++ b/contrib/llvm/lib/Analysis/ValueTracking.cpp @@ -34,7 +34,7 @@ const unsigned MaxDepth = 6; /// getBitWidth - Returns the bitwidth of the given scalar or pointer type (if /// unknown returns 0). For vector types, returns the element type's bitwidth. -static unsigned getBitWidth(const Type *Ty, const TargetData *TD) { +static unsigned getBitWidth(Type *Ty, const TargetData *TD) { if (unsigned BitWidth = Ty->getScalarSizeInBits()) return BitWidth; assert(isa(Ty) && "Expected a pointer type!"); @@ -103,7 +103,7 @@ void llvm::ComputeMaskedBits(Value *V, const APInt &Mask, if (GlobalValue *GV = dyn_cast(V)) { unsigned Align = GV->getAlignment(); if (Align == 0 && TD && GV->getType()->getElementType()->isSized()) { - const Type *ObjectType = GV->getType()->getElementType(); + Type *ObjectType = GV->getType()->getElementType(); // If the object is defined in the current Module, we'll be giving // it the preferred alignment. Otherwise, we have to assume that it // may only have the minimum ABI alignment. @@ -268,7 +268,7 @@ void llvm::ComputeMaskedBits(Value *V, const APInt &Mask, // FALL THROUGH and handle them the same as zext/trunc. case Instruction::ZExt: case Instruction::Trunc: { - const Type *SrcTy = I->getOperand(0)->getType(); + Type *SrcTy = I->getOperand(0)->getType(); unsigned SrcBitWidth; // Note that we handle pointer operands here because of inttoptr/ptrtoint @@ -291,7 +291,7 @@ void llvm::ComputeMaskedBits(Value *V, const APInt &Mask, return; } case Instruction::BitCast: { - const Type *SrcTy = I->getOperand(0)->getType(); + Type *SrcTy = I->getOperand(0)->getType(); if ((SrcTy->isIntegerTy() || SrcTy->isPointerTy()) && // TODO: For now, not handling conversions like: // (bitcast i64 %x to <2 x i32>) @@ -559,7 +559,7 @@ void llvm::ComputeMaskedBits(Value *V, const APInt &Mask, gep_type_iterator GTI = gep_type_begin(I); for (unsigned i = 1, e = I->getNumOperands(); i != e; ++i, ++GTI) { Value *Index = I->getOperand(i); - if (const StructType *STy = dyn_cast(*GTI)) { + if (StructType *STy = dyn_cast(*GTI)) { // Handle struct member offset arithmetic. if (!TD) return; const StructLayout *SL = TD->getStructLayout(STy); @@ -569,7 +569,7 @@ void llvm::ComputeMaskedBits(Value *V, const APInt &Mask, CountTrailingZeros_64(Offset)); } else { // Handle array index arithmetic. - const Type *IndexedTy = GTI.getIndexedType(); + Type *IndexedTy = GTI.getIndexedType(); if (!IndexedTy->isSized()) return; unsigned GEPOpiBits = Index->getType()->getScalarSizeInBits(); uint64_t TypeSize = TD ? TD->getTypeAllocSize(IndexedTy) : 1; @@ -898,7 +898,7 @@ unsigned llvm::ComputeNumSignBits(Value *V, const TargetData *TD, assert((TD || V->getType()->isIntOrIntVectorTy()) && "ComputeNumSignBits requires a TargetData object to operate " "on non-integer values!"); - const Type *Ty = V->getType(); + Type *Ty = V->getType(); unsigned TyBits = TD ? TD->getTypeSizeInBits(V->getType()->getScalarType()) : Ty->getScalarSizeInBits(); unsigned Tmp, Tmp2; @@ -1078,7 +1078,7 @@ bool llvm::ComputeMultiple(Value *V, unsigned Base, Value *&Multiple, assert(Depth <= MaxDepth && "Limit Search Depth"); assert(V->getType()->isIntegerTy() && "Not integer or pointer type!"); - const Type *T = V->getType(); + Type *T = V->getType(); ConstantInt *CI = dyn_cast(V); @@ -1315,11 +1315,11 @@ Value *llvm::isBytewiseValue(Value *V) { // indices from Idxs that should be left out when inserting into the resulting // struct. To is the result struct built so far, new insertvalue instructions // build on that. -static Value *BuildSubAggregate(Value *From, Value* To, const Type *IndexedType, +static Value *BuildSubAggregate(Value *From, Value* To, Type *IndexedType, SmallVector &Idxs, unsigned IdxSkip, Instruction *InsertBefore) { - const llvm::StructType *STy = llvm::dyn_cast(IndexedType); + llvm::StructType *STy = llvm::dyn_cast(IndexedType); if (STy) { // Save the original To argument so we can modify it Value *OrigTo = To; @@ -1358,8 +1358,7 @@ static Value *BuildSubAggregate(Value *From, Value* To, const Type *IndexedType, return NULL; // Insert the value in the new (sub) aggregrate - return llvm::InsertValueInst::Create(To, V, - ArrayRef(Idxs).slice(IdxSkip), + return llvm::InsertValueInst::Create(To, V, makeArrayRef(Idxs).slice(IdxSkip), "tmp", InsertBefore); } @@ -1378,7 +1377,7 @@ static Value *BuildSubAggregate(Value *From, Value* To, const Type *IndexedType, static Value *BuildSubAggregate(Value *From, ArrayRef idx_range, Instruction *InsertBefore) { assert(InsertBefore && "Must have someplace to insert!"); - const Type *IndexedType = ExtractValueInst::getIndexedType(From->getType(), + Type *IndexedType = ExtractValueInst::getIndexedType(From->getType(), idx_range); Value *To = UndefValue::get(IndexedType); SmallVector Idxs(idx_range.begin(), idx_range.end()); @@ -1404,7 +1403,7 @@ Value *llvm::FindInsertedValue(Value *V, ArrayRef idx_range, && "Not looking at a struct or array?"); assert(ExtractValueInst::getIndexedType(V->getType(), idx_range) && "Invalid indices for type?"); - const CompositeType *PTy = cast(V->getType()); + CompositeType *PTy = cast(V->getType()); if (isa(V)) return UndefValue::get(ExtractValueInst::getIndexedType(PTy, @@ -1435,9 +1434,7 @@ Value *llvm::FindInsertedValue(Value *V, ArrayRef idx_range, // %C = insertvalue {i32, i32 } %A, i32 11, 1 // which allows the unused 0,0 element from the nested struct to be // removed. - return BuildSubAggregate(V, - ArrayRef(idx_range.begin(), - req_idx), + return BuildSubAggregate(V, makeArrayRef(idx_range.begin(), req_idx), InsertBefore); else // We can't handle this without inserting insertvalues @@ -1455,7 +1452,7 @@ Value *llvm::FindInsertedValue(Value *V, ArrayRef idx_range, // requested (though possibly only partially). Now we recursively look at // the inserted value, passing any remaining indices. return FindInsertedValue(I->getInsertedValueOperand(), - ArrayRef(req_idx, idx_range.end()), + makeArrayRef(req_idx, idx_range.end()), InsertBefore); } else if (ExtractValueInst *I = dyn_cast(V)) { // If we're extracting a value from an aggregrate that was extracted from @@ -1506,7 +1503,7 @@ Value *llvm::GetPointerBaseWithConstantOffset(Value *Ptr, int64_t &Offset, if (OpC->isZero()) continue; // Handle a struct and array indices which add their offset to the pointer. - if (const StructType *STy = dyn_cast(*GTI)) { + if (StructType *STy = dyn_cast(*GTI)) { Offset += TD.getStructLayout(STy)->getElementOffset(OpC->getZExtValue()); } else { uint64_t Size = TD.getTypeAllocSize(GTI.getIndexedType()); @@ -1557,8 +1554,8 @@ bool llvm::GetConstantStringInfo(const Value *V, std::string &Str, return false; // Make sure the index-ee is a pointer to array of i8. - const PointerType *PT = cast(GEP->getOperand(0)->getType()); - const ArrayType *AT = dyn_cast(PT->getElementType()); + PointerType *PT = cast(GEP->getOperand(0)->getType()); + ArrayType *AT = dyn_cast(PT->getElementType()); if (AT == 0 || !AT->getElementType()->isIntegerTy(8)) return false; diff --git a/contrib/llvm/lib/AsmParser/LLLexer.cpp b/contrib/llvm/lib/AsmParser/LLLexer.cpp index 3c63106e8..d0dd98627 100644 --- a/contrib/llvm/lib/AsmParser/LLLexer.cpp +++ b/contrib/llvm/lib/AsmParser/LLLexer.cpp @@ -506,6 +506,15 @@ lltok::Kind LLLexer::LexIdentifier() { KEYWORD(deplibs); KEYWORD(datalayout); KEYWORD(volatile); + KEYWORD(atomic); + KEYWORD(unordered); + KEYWORD(monotonic); + KEYWORD(acquire); + KEYWORD(release); + KEYWORD(acq_rel); + KEYWORD(seq_cst); + KEYWORD(singlethread); + KEYWORD(nuw); KEYWORD(nsw); KEYWORD(exact); @@ -549,6 +558,7 @@ lltok::Kind LLLexer::LexIdentifier() { KEYWORD(readnone); KEYWORD(readonly); KEYWORD(uwtable); + KEYWORD(returns_twice); KEYWORD(inlinehint); KEYWORD(noinline); @@ -559,7 +569,6 @@ lltok::Kind LLLexer::LexIdentifier() { KEYWORD(noredzone); KEYWORD(noimplicitfloat); KEYWORD(naked); - KEYWORD(hotpatch); KEYWORD(nonlazybind); KEYWORD(type); @@ -570,8 +579,16 @@ lltok::Kind LLLexer::LexIdentifier() { KEYWORD(oeq); KEYWORD(one); KEYWORD(olt); KEYWORD(ogt); KEYWORD(ole); KEYWORD(oge); KEYWORD(ord); KEYWORD(uno); KEYWORD(ueq); KEYWORD(une); + KEYWORD(xchg); KEYWORD(nand); KEYWORD(max); KEYWORD(min); KEYWORD(umax); + KEYWORD(umin); + KEYWORD(x); KEYWORD(blockaddress); + + KEYWORD(personality); + KEYWORD(cleanup); + KEYWORD(catch); + KEYWORD(filter); #undef KEYWORD // Keywords for types. @@ -624,12 +641,16 @@ lltok::Kind LLLexer::LexIdentifier() { INSTKEYWORD(switch, Switch); INSTKEYWORD(indirectbr, IndirectBr); INSTKEYWORD(invoke, Invoke); + INSTKEYWORD(resume, Resume); INSTKEYWORD(unwind, Unwind); INSTKEYWORD(unreachable, Unreachable); INSTKEYWORD(alloca, Alloca); INSTKEYWORD(load, Load); INSTKEYWORD(store, Store); + INSTKEYWORD(cmpxchg, AtomicCmpXchg); + INSTKEYWORD(atomicrmw, AtomicRMW); + INSTKEYWORD(fence, Fence); INSTKEYWORD(getelementptr, GetElementPtr); INSTKEYWORD(extractelement, ExtractElement); @@ -637,6 +658,7 @@ lltok::Kind LLLexer::LexIdentifier() { INSTKEYWORD(shufflevector, ShuffleVector); INSTKEYWORD(extractvalue, ExtractValue); INSTKEYWORD(insertvalue, InsertValue); + INSTKEYWORD(landingpad, LandingPad); #undef INSTKEYWORD // Check for [us]0x[0-9A-Fa-f]+ which are Hexadecimal constant generated by @@ -704,17 +726,17 @@ lltok::Kind LLLexer::Lex0x() { case 'K': // F80HexFPConstant - x87 long double in hexadecimal format (10 bytes) FP80HexToIntPair(TokStart+3, CurPtr, Pair); - APFloatVal = APFloat(APInt(80, 2, Pair)); + APFloatVal = APFloat(APInt(80, Pair)); return lltok::APFloat; case 'L': // F128HexFPConstant - IEEE 128-bit in hexadecimal format (16 bytes) HexToIntPair(TokStart+3, CurPtr, Pair); - APFloatVal = APFloat(APInt(128, 2, Pair), true); + APFloatVal = APFloat(APInt(128, Pair), true); return lltok::APFloat; case 'M': // PPC128HexFPConstant - PowerPC 128-bit in hexadecimal format (16 bytes) HexToIntPair(TokStart+3, CurPtr, Pair); - APFloatVal = APFloat(APInt(128, 2, Pair)); + APFloatVal = APFloat(APInt(128, Pair)); return lltok::APFloat; } } diff --git a/contrib/llvm/lib/AsmParser/LLParser.cpp b/contrib/llvm/lib/AsmParser/LLParser.cpp index cfc31f3db..cafaab01a 100644 --- a/contrib/llvm/lib/AsmParser/LLParser.cpp +++ b/contrib/llvm/lib/AsmParser/LLParser.cpp @@ -26,7 +26,7 @@ #include "llvm/Support/raw_ostream.h" using namespace llvm; -static std::string getTypeString(const Type *T) { +static std::string getTypeString(Type *T) { std::string Result; raw_string_ostream Tmp(Result); Tmp << *T; @@ -120,6 +120,9 @@ bool LLParser::ValidateEndOfModule() { for (Module::iterator FI = M->begin(), FE = M->end(); FI != FE; ) UpgradeCallsToIntrinsic(FI++); // must be post-increment, as we remove + // Upgrade to new EH scheme. N.B. This will go away in 3.1. + UpgradeExceptionHandling(M); + // Check debug info intrinsics. CheckDebugInfoIntrinsics(M); return false; @@ -744,9 +747,9 @@ bool LLParser::ParseGlobal(const std::string &Name, LocTy NameLoc, /// GetGlobalVal - Get a value with the specified name or ID, creating a /// forward reference record if needed. This can return null if the value /// exists but does not have the right type. -GlobalValue *LLParser::GetGlobalVal(const std::string &Name, const Type *Ty, +GlobalValue *LLParser::GetGlobalVal(const std::string &Name, Type *Ty, LocTy Loc) { - const PointerType *PTy = dyn_cast(Ty); + PointerType *PTy = dyn_cast(Ty); if (PTy == 0) { Error(Loc, "global variable reference must have pointer type"); return 0; @@ -775,7 +778,7 @@ GlobalValue *LLParser::GetGlobalVal(const std::string &Name, const Type *Ty, // Otherwise, create a new forward reference for this value and remember it. GlobalValue *FwdVal; - if (const FunctionType *FT = dyn_cast(PTy->getElementType())) + if (FunctionType *FT = dyn_cast(PTy->getElementType())) FwdVal = Function::Create(FT, GlobalValue::ExternalWeakLinkage, Name, M); else FwdVal = new GlobalVariable(*M, PTy->getElementType(), false, @@ -785,8 +788,8 @@ GlobalValue *LLParser::GetGlobalVal(const std::string &Name, const Type *Ty, return FwdVal; } -GlobalValue *LLParser::GetGlobalVal(unsigned ID, const Type *Ty, LocTy Loc) { - const PointerType *PTy = dyn_cast(Ty); +GlobalValue *LLParser::GetGlobalVal(unsigned ID, Type *Ty, LocTy Loc) { + PointerType *PTy = dyn_cast(Ty); if (PTy == 0) { Error(Loc, "global variable reference must have pointer type"); return 0; @@ -813,7 +816,7 @@ GlobalValue *LLParser::GetGlobalVal(unsigned ID, const Type *Ty, LocTy Loc) { // Otherwise, create a new forward reference for this value and remember it. GlobalValue *FwdVal; - if (const FunctionType *FT = dyn_cast(PTy->getElementType())) + if (FunctionType *FT = dyn_cast(PTy->getElementType())) FwdVal = Function::Create(FT, GlobalValue::ExternalWeakLinkage, "", M); else FwdVal = new GlobalVariable(*M, PTy->getElementType(), false, @@ -908,6 +911,7 @@ bool LLParser::ParseOptionalAttrs(unsigned &Attrs, unsigned AttrKind) { case lltok::kw_noreturn: Attrs |= Attribute::NoReturn; break; case lltok::kw_nounwind: Attrs |= Attribute::NoUnwind; break; case lltok::kw_uwtable: Attrs |= Attribute::UWTable; break; + case lltok::kw_returns_twice: Attrs |= Attribute::ReturnsTwice; break; case lltok::kw_noinline: Attrs |= Attribute::NoInline; break; case lltok::kw_readnone: Attrs |= Attribute::ReadNone; break; case lltok::kw_readonly: Attrs |= Attribute::ReadOnly; break; @@ -919,7 +923,6 @@ bool LLParser::ParseOptionalAttrs(unsigned &Attrs, unsigned AttrKind) { case lltok::kw_noredzone: Attrs |= Attribute::NoRedZone; break; case lltok::kw_noimplicitfloat: Attrs |= Attribute::NoImplicitFloat; break; case lltok::kw_naked: Attrs |= Attribute::Naked; break; - case lltok::kw_hotpatch: Attrs |= Attribute::Hotpatch; break; case lltok::kw_nonlazybind: Attrs |= Attribute::NonLazyBind; break; case lltok::kw_alignstack: { @@ -1145,6 +1148,32 @@ bool LLParser::ParseOptionalCommaAlign(unsigned &Alignment, return false; } +/// ParseScopeAndOrdering +/// if isAtomic: ::= 'singlethread'? AtomicOrdering +/// else: ::= +/// +/// This sets Scope and Ordering to the parsed values. +bool LLParser::ParseScopeAndOrdering(bool isAtomic, SynchronizationScope &Scope, + AtomicOrdering &Ordering) { + if (!isAtomic) + return false; + + Scope = CrossThread; + if (EatIfPresent(lltok::kw_singlethread)) + Scope = SingleThread; + switch (Lex.getKind()) { + default: return TokError("Expected ordering on atomic instruction"); + case lltok::kw_unordered: Ordering = Unordered; break; + case lltok::kw_monotonic: Ordering = Monotonic; break; + case lltok::kw_acquire: Ordering = Acquire; break; + case lltok::kw_release: Ordering = Release; break; + case lltok::kw_acq_rel: Ordering = AcquireRelease; break; + case lltok::kw_seq_cst: Ordering = SequentiallyConsistent; break; + } + Lex.Lex(); + return false; +} + /// ParseOptionalStackAlignment /// ::= /* empty */ /// ::= 'alignstack' '(' 4 ')' @@ -1237,7 +1266,7 @@ bool LLParser::ParseType(Type *&Result, bool AllowVoid) { // If the type hasn't been defined yet, create a forward definition and // remember where that forward def'n was seen (in case it never is defined). if (Entry.first == 0) { - Entry.first = StructType::createNamed(Context, Lex.getStrVal()); + Entry.first = StructType::create(Context, Lex.getStrVal()); Entry.second = Lex.getLoc(); } Result = Entry.first; @@ -1254,7 +1283,7 @@ bool LLParser::ParseType(Type *&Result, bool AllowVoid) { // If the type hasn't been defined yet, create a forward definition and // remember where that forward def'n was seen (in case it never is defined). if (Entry.first == 0) { - Entry.first = StructType::createNamed(Context, ""); + Entry.first = StructType::create(Context); Entry.second = Lex.getLoc(); } Result = Entry.first; @@ -1476,7 +1505,7 @@ bool LLParser::ParseStructDefinition(SMLoc TypeLoc, StringRef Name, // If this type number has never been uttered, create it. if (Entry.first == 0) - Entry.first = StructType::createNamed(Context, Name); + Entry.first = StructType::create(Context, Name); ResultTy = Entry.first; return false; } @@ -1502,7 +1531,7 @@ bool LLParser::ParseStructDefinition(SMLoc TypeLoc, StringRef Name, // If this type number has never been uttered, create it. if (Entry.first == 0) - Entry.first = StructType::createNamed(Context, Name); + Entry.first = StructType::create(Context, Name); StructType *STy = cast(Entry.first); @@ -1668,7 +1697,7 @@ bool LLParser::PerFunctionState::FinishFunction() { /// forward reference record if needed. This can return null if the value /// exists but does not have the right type. Value *LLParser::PerFunctionState::GetVal(const std::string &Name, - const Type *Ty, LocTy Loc) { + Type *Ty, LocTy Loc) { // Look this name up in the normal function symbol table. Value *Val = F.getValueSymbolTable().lookup(Name); @@ -1709,7 +1738,7 @@ Value *LLParser::PerFunctionState::GetVal(const std::string &Name, return FwdVal; } -Value *LLParser::PerFunctionState::GetVal(unsigned ID, const Type *Ty, +Value *LLParser::PerFunctionState::GetVal(unsigned ID, Type *Ty, LocTy Loc) { // Look this name up in the normal function symbol table. Value *Val = ID < NumberedVals.size() ? NumberedVals[ID] : 0; @@ -2273,16 +2302,11 @@ bool LLParser::ParseValID(ValID &ID, PerFunctionState *PFS) { if (Elts.size() == 0 || !Elts[0]->getType()->isPointerTy()) return Error(ID.Loc, "getelementptr requires pointer operand"); - if (!GetElementPtrInst::getIndexedType(Elts[0]->getType(), - (Value**)(Elts.data() + 1), - Elts.size() - 1)) + ArrayRef Indices(Elts.begin() + 1, Elts.end()); + if (!GetElementPtrInst::getIndexedType(Elts[0]->getType(), Indices)) return Error(ID.Loc, "invalid indices for getelementptr"); - ID.ConstantVal = InBounds ? - ConstantExpr::getInBoundsGetElementPtr(Elts[0], - Elts.data() + 1, - Elts.size() - 1) : - ConstantExpr::getGetElementPtr(Elts[0], - Elts.data() + 1, Elts.size() - 1); + ID.ConstantVal = ConstantExpr::getGetElementPtr(Elts[0], Indices, + InBounds); } else if (Opc == Instruction::Select) { if (Elts.size() != 3) return Error(ID.Loc, "expected three operands to select"); @@ -2323,7 +2347,7 @@ bool LLParser::ParseValID(ValID &ID, PerFunctionState *PFS) { } /// ParseGlobalValue - Parse a global value with the specified type. -bool LLParser::ParseGlobalValue(const Type *Ty, Constant *&C) { +bool LLParser::ParseGlobalValue(Type *Ty, Constant *&C) { C = 0; ValID ID; Value *V = NULL; @@ -2410,7 +2434,7 @@ bool LLParser::ParseMetadataValue(ValID &ID, PerFunctionState *PFS) { // Function Parsing. //===----------------------------------------------------------------------===// -bool LLParser::ConvertValIDToValue(const Type *Ty, ValID &ID, Value *&V, +bool LLParser::ConvertValIDToValue(Type *Ty, ValID &ID, Value *&V, PerFunctionState *PFS) { if (Ty->isFunctionTy()) return Error(ID.Loc, "functions are not values, refer to them as pointers"); @@ -2426,8 +2450,8 @@ bool LLParser::ConvertValIDToValue(const Type *Ty, ValID &ID, Value *&V, V = PFS->GetVal(ID.StrVal, Ty, ID.Loc); return (V == 0); case ValID::t_InlineAsm: { - const PointerType *PTy = dyn_cast(Ty); - const FunctionType *FTy = + PointerType *PTy = dyn_cast(Ty); + FunctionType *FTy = PTy ? dyn_cast(PTy->getElementType()) : 0; if (!FTy || !InlineAsm::Verify(FTy, ID.StrVal2)) return Error(ID.Loc, "invalid type for inline asm constraint string"); @@ -2506,7 +2530,7 @@ bool LLParser::ConvertValIDToValue(const Type *Ty, ValID &ID, Value *&V, return false; case ValID::t_ConstantStruct: case ValID::t_PackedConstantStruct: - if (const StructType *ST = dyn_cast(Ty)) { + if (StructType *ST = dyn_cast(Ty)) { if (ST->getNumElements() != ID.UIntVal) return Error(ID.Loc, "initializer with struct type has wrong # elements"); @@ -2519,15 +2543,15 @@ bool LLParser::ConvertValIDToValue(const Type *Ty, ValID &ID, Value *&V, return Error(ID.Loc, "element " + Twine(i) + " of struct initializer doesn't match struct element type"); - V = ConstantStruct::get(ST, ArrayRef(ID.ConstantStructElts, - ID.UIntVal)); + V = ConstantStruct::get(ST, makeArrayRef(ID.ConstantStructElts, + ID.UIntVal)); } else return Error(ID.Loc, "constant expression type mismatch"); return false; } } -bool LLParser::ParseValue(const Type *Ty, Value *&V, PerFunctionState *PFS) { +bool LLParser::ParseValue(Type *Ty, Value *&V, PerFunctionState *PFS) { V = 0; ValID ID; return ParseValID(ID, PFS) || @@ -2671,9 +2695,9 @@ bool LLParser::ParseFunctionHeader(Function *&Fn, bool isDefine) { if (PAL.paramHasAttr(1, Attribute::StructRet) && !RetType->isVoidTy()) return Error(RetTypeLoc, "functions with 'sret' argument must return void"); - const FunctionType *FT = + FunctionType *FT = FunctionType::get(RetType, ParamTypeList, isVarArg); - const PointerType *PFT = PointerType::getUnqual(FT); + PointerType *PFT = PointerType::getUnqual(FT); Fn = 0; if (!FunctionName.empty()) { @@ -2864,6 +2888,7 @@ int LLParser::ParseInstruction(Instruction *&Inst, BasicBlock *BB, case lltok::kw_switch: return ParseSwitch(Inst, PFS); case lltok::kw_indirectbr: return ParseIndirectBr(Inst, PFS); case lltok::kw_invoke: return ParseInvoke(Inst, PFS); + case lltok::kw_resume: return ParseResume(Inst, PFS); // Binary Operators. case lltok::kw_add: case lltok::kw_sub: @@ -2923,13 +2948,18 @@ int LLParser::ParseInstruction(Instruction *&Inst, BasicBlock *BB, case lltok::kw_insertelement: return ParseInsertElement(Inst, PFS); case lltok::kw_shufflevector: return ParseShuffleVector(Inst, PFS); case lltok::kw_phi: return ParsePHI(Inst, PFS); + case lltok::kw_landingpad: return ParseLandingPad(Inst, PFS); case lltok::kw_call: return ParseCall(Inst, PFS, false); case lltok::kw_tail: return ParseCall(Inst, PFS, true); // Memory. case lltok::kw_alloca: return ParseAlloc(Inst, PFS); case lltok::kw_load: return ParseLoad(Inst, PFS, false); case lltok::kw_store: return ParseStore(Inst, PFS, false); + case lltok::kw_cmpxchg: return ParseCmpXchg(Inst, PFS); + case lltok::kw_atomicrmw: return ParseAtomicRMW(Inst, PFS); + case lltok::kw_fence: return ParseFence(Inst, PFS); case lltok::kw_volatile: + // For compatibility; canonical location is after load if (EatIfPresent(lltok::kw_load)) return ParseLoad(Inst, PFS, true); else if (EatIfPresent(lltok::kw_store)) @@ -3162,8 +3192,8 @@ bool LLParser::ParseInvoke(Instruction *&Inst, PerFunctionState &PFS) { // If RetType is a non-function pointer type, then this is the short syntax // for the call, which means that RetType is just the return type. Infer the // rest of the function argument types from the arguments that are present. - const PointerType *PFTy = 0; - const FunctionType *Ty = 0; + PointerType *PFTy = 0; + FunctionType *Ty = 0; if (!(PFTy = dyn_cast(RetType)) || !(Ty = dyn_cast(PFTy->getElementType()))) { // Pull out the types of all of the arguments... @@ -3194,7 +3224,7 @@ bool LLParser::ParseInvoke(Instruction *&Inst, PerFunctionState &PFS) { FunctionType::param_iterator I = Ty->param_begin(); FunctionType::param_iterator E = Ty->param_end(); for (unsigned i = 0, e = ArgList.size(); i != e; ++i) { - const Type *ExpectedTy = 0; + Type *ExpectedTy = 0; if (I != E) { ExpectedTy = *I++; } else if (!Ty->isVarArg()) { @@ -3225,7 +3255,17 @@ bool LLParser::ParseInvoke(Instruction *&Inst, PerFunctionState &PFS) { return false; } +/// ParseResume +/// ::= 'resume' TypeAndValue +bool LLParser::ParseResume(Instruction *&Inst, PerFunctionState &PFS) { + Value *Exn; LocTy ExnLoc; + if (ParseTypeAndValue(Exn, ExnLoc, PFS)) + return true; + ResumeInst *RI = ResumeInst::Create(Exn); + Inst = RI; + return false; +} //===----------------------------------------------------------------------===// // Binary Operators. @@ -3473,6 +3513,56 @@ int LLParser::ParsePHI(Instruction *&Inst, PerFunctionState &PFS) { return AteExtraComma ? InstExtraComma : InstNormal; } +/// ParseLandingPad +/// ::= 'landingpad' Type 'personality' TypeAndValue 'cleanup'? Clause+ +/// Clause +/// ::= 'catch' TypeAndValue +/// ::= 'filter' +/// ::= 'filter' TypeAndValue ( ',' TypeAndValue )* +bool LLParser::ParseLandingPad(Instruction *&Inst, PerFunctionState &PFS) { + Type *Ty = 0; LocTy TyLoc; + Value *PersFn; LocTy PersFnLoc; + + if (ParseType(Ty, TyLoc) || + ParseToken(lltok::kw_personality, "expected 'personality'") || + ParseTypeAndValue(PersFn, PersFnLoc, PFS)) + return true; + + LandingPadInst *LP = LandingPadInst::Create(Ty, PersFn, 0); + LP->setCleanup(EatIfPresent(lltok::kw_cleanup)); + + while (Lex.getKind() == lltok::kw_catch || Lex.getKind() == lltok::kw_filter){ + LandingPadInst::ClauseType CT; + if (EatIfPresent(lltok::kw_catch)) + CT = LandingPadInst::Catch; + else if (EatIfPresent(lltok::kw_filter)) + CT = LandingPadInst::Filter; + else + return TokError("expected 'catch' or 'filter' clause type"); + + Value *V; LocTy VLoc; + if (ParseTypeAndValue(V, VLoc, PFS)) { + delete LP; + return true; + } + + // A 'catch' type expects a non-array constant. A filter clause expects an + // array constant. + if (CT == LandingPadInst::Catch) { + if (isa(V->getType())) + Error(VLoc, "'catch' clause has an invalid type"); + } else { + if (!isa(V->getType())) + Error(VLoc, "'filter' clause has an invalid type"); + } + + LP->addClause(V); + } + + Inst = LP; + return false; +} + /// ParseCall /// ::= 'tail'? 'call' OptionalCallingConv OptionalAttrs Type Value /// ParameterList OptionalAttrs @@ -3498,8 +3588,8 @@ bool LLParser::ParseCall(Instruction *&Inst, PerFunctionState &PFS, // If RetType is a non-function pointer type, then this is the short syntax // for the call, which means that RetType is just the return type. Infer the // rest of the function argument types from the arguments that are present. - const PointerType *PFTy = 0; - const FunctionType *Ty = 0; + PointerType *PFTy = 0; + FunctionType *Ty = 0; if (!(PFTy = dyn_cast(RetType)) || !(Ty = dyn_cast(PFTy->getElementType()))) { // Pull out the types of all of the arguments... @@ -3530,7 +3620,7 @@ bool LLParser::ParseCall(Instruction *&Inst, PerFunctionState &PFS, FunctionType::param_iterator I = Ty->param_begin(); FunctionType::param_iterator E = Ty->param_end(); for (unsigned i = 0, e = ArgList.size(); i != e; ++i) { - const Type *ExpectedTy = 0; + Type *ExpectedTy = 0; if (I != E) { ExpectedTy = *I++; } else if (!Ty->isVarArg()) { @@ -3596,34 +3686,85 @@ int LLParser::ParseAlloc(Instruction *&Inst, PerFunctionState &PFS) { } /// ParseLoad -/// ::= 'volatile'? 'load' TypeAndValue (',' OptionalInfo)? +/// ::= 'load' 'volatile'? TypeAndValue (',' 'align' i32)? +/// ::= 'load' 'atomic' 'volatile'? TypeAndValue +/// 'singlethread'? AtomicOrdering (',' 'align' i32)? +/// Compatibility: +/// ::= 'volatile' 'load' TypeAndValue (',' 'align' i32)? int LLParser::ParseLoad(Instruction *&Inst, PerFunctionState &PFS, bool isVolatile) { Value *Val; LocTy Loc; unsigned Alignment = 0; bool AteExtraComma = false; + bool isAtomic = false; + AtomicOrdering Ordering = NotAtomic; + SynchronizationScope Scope = CrossThread; + + if (Lex.getKind() == lltok::kw_atomic) { + if (isVolatile) + return TokError("mixing atomic with old volatile placement"); + isAtomic = true; + Lex.Lex(); + } + + if (Lex.getKind() == lltok::kw_volatile) { + if (isVolatile) + return TokError("duplicate volatile before and after store"); + isVolatile = true; + Lex.Lex(); + } + if (ParseTypeAndValue(Val, Loc, PFS) || + ParseScopeAndOrdering(isAtomic, Scope, Ordering) || ParseOptionalCommaAlign(Alignment, AteExtraComma)) return true; if (!Val->getType()->isPointerTy() || !cast(Val->getType())->getElementType()->isFirstClassType()) return Error(Loc, "load operand must be a pointer to a first class type"); + if (isAtomic && !Alignment) + return Error(Loc, "atomic load must have explicit non-zero alignment"); + if (Ordering == Release || Ordering == AcquireRelease) + return Error(Loc, "atomic load cannot use Release ordering"); - Inst = new LoadInst(Val, "", isVolatile, Alignment); + Inst = new LoadInst(Val, "", isVolatile, Alignment, Ordering, Scope); return AteExtraComma ? InstExtraComma : InstNormal; } /// ParseStore -/// ::= 'volatile'? 'store' TypeAndValue ',' TypeAndValue (',' 'align' i32)? + +/// ::= 'store' 'volatile'? TypeAndValue ',' TypeAndValue (',' 'align' i32)? +/// ::= 'store' 'atomic' 'volatile'? TypeAndValue ',' TypeAndValue +/// 'singlethread'? AtomicOrdering (',' 'align' i32)? +/// Compatibility: +/// ::= 'volatile' 'store' TypeAndValue ',' TypeAndValue (',' 'align' i32)? int LLParser::ParseStore(Instruction *&Inst, PerFunctionState &PFS, bool isVolatile) { Value *Val, *Ptr; LocTy Loc, PtrLoc; unsigned Alignment = 0; bool AteExtraComma = false; + bool isAtomic = false; + AtomicOrdering Ordering = NotAtomic; + SynchronizationScope Scope = CrossThread; + + if (Lex.getKind() == lltok::kw_atomic) { + if (isVolatile) + return TokError("mixing atomic with old volatile placement"); + isAtomic = true; + Lex.Lex(); + } + + if (Lex.getKind() == lltok::kw_volatile) { + if (isVolatile) + return TokError("duplicate volatile before and after store"); + isVolatile = true; + Lex.Lex(); + } + if (ParseTypeAndValue(Val, Loc, PFS) || ParseToken(lltok::comma, "expected ',' after store operand") || ParseTypeAndValue(Ptr, PtrLoc, PFS) || + ParseScopeAndOrdering(isAtomic, Scope, Ordering) || ParseOptionalCommaAlign(Alignment, AteExtraComma)) return true; @@ -3633,11 +3774,131 @@ int LLParser::ParseStore(Instruction *&Inst, PerFunctionState &PFS, return Error(Loc, "store operand must be a first class value"); if (cast(Ptr->getType())->getElementType() != Val->getType()) return Error(Loc, "stored value and pointer type do not match"); + if (isAtomic && !Alignment) + return Error(Loc, "atomic store must have explicit non-zero alignment"); + if (Ordering == Acquire || Ordering == AcquireRelease) + return Error(Loc, "atomic store cannot use Acquire ordering"); + + Inst = new StoreInst(Val, Ptr, isVolatile, Alignment, Ordering, Scope); + return AteExtraComma ? InstExtraComma : InstNormal; +} - Inst = new StoreInst(Val, Ptr, isVolatile, Alignment); +/// ParseCmpXchg +/// ::= 'cmpxchg' 'volatile'? TypeAndValue ',' TypeAndValue ',' TypeAndValue +/// 'singlethread'? AtomicOrdering +int LLParser::ParseCmpXchg(Instruction *&Inst, PerFunctionState &PFS) { + Value *Ptr, *Cmp, *New; LocTy PtrLoc, CmpLoc, NewLoc; + bool AteExtraComma = false; + AtomicOrdering Ordering = NotAtomic; + SynchronizationScope Scope = CrossThread; + bool isVolatile = false; + + if (EatIfPresent(lltok::kw_volatile)) + isVolatile = true; + + if (ParseTypeAndValue(Ptr, PtrLoc, PFS) || + ParseToken(lltok::comma, "expected ',' after cmpxchg address") || + ParseTypeAndValue(Cmp, CmpLoc, PFS) || + ParseToken(lltok::comma, "expected ',' after cmpxchg cmp operand") || + ParseTypeAndValue(New, NewLoc, PFS) || + ParseScopeAndOrdering(true /*Always atomic*/, Scope, Ordering)) + return true; + + if (Ordering == Unordered) + return TokError("cmpxchg cannot be unordered"); + if (!Ptr->getType()->isPointerTy()) + return Error(PtrLoc, "cmpxchg operand must be a pointer"); + if (cast(Ptr->getType())->getElementType() != Cmp->getType()) + return Error(CmpLoc, "compare value and pointer type do not match"); + if (cast(Ptr->getType())->getElementType() != New->getType()) + return Error(NewLoc, "new value and pointer type do not match"); + if (!New->getType()->isIntegerTy()) + return Error(NewLoc, "cmpxchg operand must be an integer"); + unsigned Size = New->getType()->getPrimitiveSizeInBits(); + if (Size < 8 || (Size & (Size - 1))) + return Error(NewLoc, "cmpxchg operand must be power-of-two byte-sized" + " integer"); + + AtomicCmpXchgInst *CXI = + new AtomicCmpXchgInst(Ptr, Cmp, New, Ordering, Scope); + CXI->setVolatile(isVolatile); + Inst = CXI; return AteExtraComma ? InstExtraComma : InstNormal; } +/// ParseAtomicRMW +/// ::= 'atomicrmw' 'volatile'? BinOp TypeAndValue ',' TypeAndValue +/// 'singlethread'? AtomicOrdering +int LLParser::ParseAtomicRMW(Instruction *&Inst, PerFunctionState &PFS) { + Value *Ptr, *Val; LocTy PtrLoc, ValLoc; + bool AteExtraComma = false; + AtomicOrdering Ordering = NotAtomic; + SynchronizationScope Scope = CrossThread; + bool isVolatile = false; + AtomicRMWInst::BinOp Operation; + + if (EatIfPresent(lltok::kw_volatile)) + isVolatile = true; + + switch (Lex.getKind()) { + default: return TokError("expected binary operation in atomicrmw"); + case lltok::kw_xchg: Operation = AtomicRMWInst::Xchg; break; + case lltok::kw_add: Operation = AtomicRMWInst::Add; break; + case lltok::kw_sub: Operation = AtomicRMWInst::Sub; break; + case lltok::kw_and: Operation = AtomicRMWInst::And; break; + case lltok::kw_nand: Operation = AtomicRMWInst::Nand; break; + case lltok::kw_or: Operation = AtomicRMWInst::Or; break; + case lltok::kw_xor: Operation = AtomicRMWInst::Xor; break; + case lltok::kw_max: Operation = AtomicRMWInst::Max; break; + case lltok::kw_min: Operation = AtomicRMWInst::Min; break; + case lltok::kw_umax: Operation = AtomicRMWInst::UMax; break; + case lltok::kw_umin: Operation = AtomicRMWInst::UMin; break; + } + Lex.Lex(); // Eat the operation. + + if (ParseTypeAndValue(Ptr, PtrLoc, PFS) || + ParseToken(lltok::comma, "expected ',' after atomicrmw address") || + ParseTypeAndValue(Val, ValLoc, PFS) || + ParseScopeAndOrdering(true /*Always atomic*/, Scope, Ordering)) + return true; + + if (Ordering == Unordered) + return TokError("atomicrmw cannot be unordered"); + if (!Ptr->getType()->isPointerTy()) + return Error(PtrLoc, "atomicrmw operand must be a pointer"); + if (cast(Ptr->getType())->getElementType() != Val->getType()) + return Error(ValLoc, "atomicrmw value and pointer type do not match"); + if (!Val->getType()->isIntegerTy()) + return Error(ValLoc, "atomicrmw operand must be an integer"); + unsigned Size = Val->getType()->getPrimitiveSizeInBits(); + if (Size < 8 || (Size & (Size - 1))) + return Error(ValLoc, "atomicrmw operand must be power-of-two byte-sized" + " integer"); + + AtomicRMWInst *RMWI = + new AtomicRMWInst(Operation, Ptr, Val, Ordering, Scope); + RMWI->setVolatile(isVolatile); + Inst = RMWI; + return AteExtraComma ? InstExtraComma : InstNormal; +} + +/// ParseFence +/// ::= 'fence' 'singlethread'? AtomicOrdering +int LLParser::ParseFence(Instruction *&Inst, PerFunctionState &PFS) { + AtomicOrdering Ordering = NotAtomic; + SynchronizationScope Scope = CrossThread; + if (ParseScopeAndOrdering(true /*Always atomic*/, Scope, Ordering)) + return true; + + if (Ordering == Unordered) + return TokError("fence cannot be unordered"); + if (Ordering == Monotonic) + return TokError("fence cannot be monotonic"); + + Inst = new FenceInst(Context, Ordering, Scope); + return InstNormal; +} + /// ParseGetElementPtr /// ::= 'getelementptr' 'inbounds'? TypeAndValue (',' TypeAndValue)* int LLParser::ParseGetElementPtr(Instruction *&Inst, PerFunctionState &PFS) { @@ -3663,10 +3924,9 @@ int LLParser::ParseGetElementPtr(Instruction *&Inst, PerFunctionState &PFS) { Indices.push_back(Val); } - if (!GetElementPtrInst::getIndexedType(Ptr->getType(), - Indices.begin(), Indices.end())) + if (!GetElementPtrInst::getIndexedType(Ptr->getType(), Indices)) return Error(Loc, "invalid getelementptr indices"); - Inst = GetElementPtrInst::Create(Ptr, Indices.begin(), Indices.end()); + Inst = GetElementPtrInst::Create(Ptr, Indices); if (InBounds) cast(Inst)->setIsInBounds(true); return AteExtraComma ? InstExtraComma : InstNormal; diff --git a/contrib/llvm/lib/AsmParser/LLParser.h b/contrib/llvm/lib/AsmParser/LLParser.h index 963065785..cbc3c23e8 100644 --- a/contrib/llvm/lib/AsmParser/LLParser.h +++ b/contrib/llvm/lib/AsmParser/LLParser.h @@ -15,6 +15,7 @@ #define LLVM_ASMPARSER_LLPARSER_H #include "LLLexer.h" +#include "llvm/Instructions.h" #include "llvm/Module.h" #include "llvm/Type.h" #include "llvm/ADT/DenseMap.h" @@ -142,8 +143,8 @@ namespace llvm { /// GetGlobalVal - Get a value with the specified name or ID, creating a /// forward reference record if needed. This can return null if the value /// exists but does not have the right type. - GlobalValue *GetGlobalVal(const std::string &N, const Type *Ty, LocTy Loc); - GlobalValue *GetGlobalVal(unsigned ID, const Type *Ty, LocTy Loc); + GlobalValue *GetGlobalVal(const std::string &N, Type *Ty, LocTy Loc); + GlobalValue *GetGlobalVal(unsigned ID, Type *Ty, LocTy Loc); // Helper Routines. bool ParseToken(lltok::Kind T, const char *ErrMsg); @@ -178,6 +179,8 @@ namespace llvm { bool ParseOptionalVisibility(unsigned &Visibility); bool ParseOptionalCallingConv(CallingConv::ID &CC); bool ParseOptionalAlignment(unsigned &Alignment); + bool ParseScopeAndOrdering(bool isAtomic, SynchronizationScope &Scope, + AtomicOrdering &Ordering); bool ParseOptionalStackAlignment(unsigned &Alignment); bool ParseOptionalCommaAlign(unsigned &Alignment, bool &AteExtraComma); bool ParseIndexList(SmallVectorImpl &Indices,bool &AteExtraComma); @@ -249,8 +252,8 @@ namespace llvm { /// GetVal - Get a value with the specified name or ID, creating a /// forward reference record if needed. This can return null if the value /// exists but does not have the right type. - Value *GetVal(const std::string &Name, const Type *Ty, LocTy Loc); - Value *GetVal(unsigned ID, const Type *Ty, LocTy Loc); + Value *GetVal(const std::string &Name, Type *Ty, LocTy Loc); + Value *GetVal(unsigned ID, Type *Ty, LocTy Loc); /// SetInstName - After an instruction is parsed and inserted into its /// basic block, this installs its name. @@ -269,14 +272,14 @@ namespace llvm { BasicBlock *DefineBB(const std::string &Name, LocTy Loc); }; - bool ConvertValIDToValue(const Type *Ty, ValID &ID, Value *&V, + bool ConvertValIDToValue(Type *Ty, ValID &ID, Value *&V, PerFunctionState *PFS); - bool ParseValue(const Type *Ty, Value *&V, PerFunctionState *PFS); - bool ParseValue(const Type *Ty, Value *&V, PerFunctionState &PFS) { + bool ParseValue(Type *Ty, Value *&V, PerFunctionState *PFS); + bool ParseValue(Type *Ty, Value *&V, PerFunctionState &PFS) { return ParseValue(Ty, V, &PFS); } - bool ParseValue(const Type *Ty, Value *&V, LocTy &Loc, + bool ParseValue(Type *Ty, Value *&V, LocTy &Loc, PerFunctionState &PFS) { Loc = Lex.getLoc(); return ParseValue(Ty, V, &PFS); @@ -310,7 +313,7 @@ namespace llvm { // Constant Parsing. bool ParseValID(ValID &ID, PerFunctionState *PFS = NULL); - bool ParseGlobalValue(const Type *Ty, Constant *&V); + bool ParseGlobalValue(Type *Ty, Constant *&V); bool ParseGlobalTypeAndValue(Constant *&V); bool ParseGlobalValueVector(SmallVectorImpl &Elts); bool ParseMetadataListValue(ValID &ID, PerFunctionState *PFS); @@ -344,6 +347,7 @@ namespace llvm { bool ParseSwitch(Instruction *&Inst, PerFunctionState &PFS); bool ParseIndirectBr(Instruction *&Inst, PerFunctionState &PFS); bool ParseInvoke(Instruction *&Inst, PerFunctionState &PFS); + bool ParseResume(Instruction *&Inst, PerFunctionState &PFS); bool ParseArithmetic(Instruction *&I, PerFunctionState &PFS, unsigned Opc, unsigned OperandType); @@ -356,10 +360,14 @@ namespace llvm { bool ParseInsertElement(Instruction *&I, PerFunctionState &PFS); bool ParseShuffleVector(Instruction *&I, PerFunctionState &PFS); int ParsePHI(Instruction *&I, PerFunctionState &PFS); + bool ParseLandingPad(Instruction *&I, PerFunctionState &PFS); bool ParseCall(Instruction *&I, PerFunctionState &PFS, bool isTail); int ParseAlloc(Instruction *&I, PerFunctionState &PFS); int ParseLoad(Instruction *&I, PerFunctionState &PFS, bool isVolatile); int ParseStore(Instruction *&I, PerFunctionState &PFS, bool isVolatile); + int ParseCmpXchg(Instruction *&I, PerFunctionState &PFS); + int ParseAtomicRMW(Instruction *&I, PerFunctionState &PFS); + int ParseFence(Instruction *&I, PerFunctionState &PFS); int ParseGetElementPtr(Instruction *&I, PerFunctionState &PFS); int ParseExtractValue(Instruction *&I, PerFunctionState &PFS); int ParseInsertValue(Instruction *&I, PerFunctionState &PFS); diff --git a/contrib/llvm/lib/AsmParser/LLToken.h b/contrib/llvm/lib/AsmParser/LLToken.h index a5f89fcce..8f167725e 100644 --- a/contrib/llvm/lib/AsmParser/LLToken.h +++ b/contrib/llvm/lib/AsmParser/LLToken.h @@ -53,6 +53,9 @@ namespace lltok { kw_deplibs, kw_datalayout, kw_volatile, + kw_atomic, + kw_unordered, kw_monotonic, kw_acquire, kw_release, kw_acq_rel, kw_seq_cst, + kw_singlethread, kw_nuw, kw_nsw, kw_exact, @@ -87,6 +90,7 @@ namespace lltok { kw_readnone, kw_readonly, kw_uwtable, + kw_returns_twice, kw_inlinehint, kw_noinline, @@ -97,7 +101,6 @@ namespace lltok { kw_noredzone, kw_noimplicitfloat, kw_naked, - kw_hotpatch, kw_nonlazybind, kw_type, @@ -107,6 +110,9 @@ namespace lltok { kw_uge, kw_oeq, kw_one, kw_olt, kw_ogt, kw_ole, kw_oge, kw_ord, kw_uno, kw_ueq, kw_une, + // atomicrmw operations that aren't also instruction keywords. + kw_xchg, kw_nand, kw_max, kw_min, kw_umax, kw_umin, + // Instruction Opcodes (Opcode in UIntVal). kw_add, kw_fadd, kw_sub, kw_fsub, kw_mul, kw_fmul, kw_udiv, kw_sdiv, kw_fdiv, @@ -118,10 +124,13 @@ namespace lltok { kw_fptoui, kw_fptosi, kw_inttoptr, kw_ptrtoint, kw_bitcast, kw_select, kw_va_arg, - kw_ret, kw_br, kw_switch, kw_indirectbr, kw_invoke, kw_unwind, + kw_landingpad, kw_personality, kw_cleanup, kw_catch, kw_filter, + + kw_ret, kw_br, kw_switch, kw_indirectbr, kw_invoke, kw_unwind, kw_resume, kw_unreachable, - kw_alloca, kw_load, kw_store, kw_getelementptr, + kw_alloca, kw_load, kw_store, kw_fence, kw_cmpxchg, kw_atomicrmw, + kw_getelementptr, kw_extractelement, kw_insertelement, kw_shufflevector, kw_extractvalue, kw_insertvalue, kw_blockaddress, diff --git a/contrib/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/contrib/llvm/lib/Bitcode/Reader/BitcodeReader.cpp index 24c29941c..46565f36a 100644 --- a/contrib/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/contrib/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -107,7 +107,7 @@ static int GetDecodedCastOpcode(unsigned Val) { case bitc::CAST_BITCAST : return Instruction::BitCast; } } -static int GetDecodedBinaryOpcode(unsigned Val, const Type *Ty) { +static int GetDecodedBinaryOpcode(unsigned Val, Type *Ty) { switch (Val) { default: return -1; case bitc::BINOP_ADD: @@ -131,6 +131,44 @@ static int GetDecodedBinaryOpcode(unsigned Val, const Type *Ty) { } } +static AtomicRMWInst::BinOp GetDecodedRMWOperation(unsigned Val) { + switch (Val) { + default: return AtomicRMWInst::BAD_BINOP; + case bitc::RMW_XCHG: return AtomicRMWInst::Xchg; + case bitc::RMW_ADD: return AtomicRMWInst::Add; + case bitc::RMW_SUB: return AtomicRMWInst::Sub; + case bitc::RMW_AND: return AtomicRMWInst::And; + case bitc::RMW_NAND: return AtomicRMWInst::Nand; + case bitc::RMW_OR: return AtomicRMWInst::Or; + case bitc::RMW_XOR: return AtomicRMWInst::Xor; + case bitc::RMW_MAX: return AtomicRMWInst::Max; + case bitc::RMW_MIN: return AtomicRMWInst::Min; + case bitc::RMW_UMAX: return AtomicRMWInst::UMax; + case bitc::RMW_UMIN: return AtomicRMWInst::UMin; + } +} + +static AtomicOrdering GetDecodedOrdering(unsigned Val) { + switch (Val) { + case bitc::ORDERING_NOTATOMIC: return NotAtomic; + case bitc::ORDERING_UNORDERED: return Unordered; + case bitc::ORDERING_MONOTONIC: return Monotonic; + case bitc::ORDERING_ACQUIRE: return Acquire; + case bitc::ORDERING_RELEASE: return Release; + case bitc::ORDERING_ACQREL: return AcquireRelease; + default: // Map unknown orderings to sequentially-consistent. + case bitc::ORDERING_SEQCST: return SequentiallyConsistent; + } +} + +static SynchronizationScope GetDecodedSynchScope(unsigned Val) { + switch (Val) { + case bitc::SYNCHSCOPE_SINGLETHREAD: return SingleThread; + default: // Map unknown scopes to cross-thread. + case bitc::SYNCHSCOPE_CROSSTHREAD: return CrossThread; + } +} + namespace llvm { namespace { /// @brief A class for maintaining the slot number definition @@ -142,7 +180,7 @@ namespace { void *operator new(size_t s) { return User::operator new(s, 1); } - explicit ConstantPlaceHolder(const Type *Ty, LLVMContext& Context) + explicit ConstantPlaceHolder(Type *Ty, LLVMContext& Context) : ConstantExpr(Ty, Instruction::UserOp1, &Op<0>(), 1) { Op<0>() = UndefValue::get(Type::getInt32Ty(Context)); } @@ -198,7 +236,7 @@ void BitcodeReaderValueList::AssignValue(Value *V, unsigned Idx) { Constant *BitcodeReaderValueList::getConstantFwdRef(unsigned Idx, - const Type *Ty) { + Type *Ty) { if (Idx >= size()) resize(Idx + 1); @@ -213,7 +251,7 @@ Constant *BitcodeReaderValueList::getConstantFwdRef(unsigned Idx, return C; } -Value *BitcodeReaderValueList::getValueFwdRef(unsigned Idx, const Type *Ty) { +Value *BitcodeReaderValueList::getValueFwdRef(unsigned Idx, Type *Ty) { if (Idx >= size()) resize(Idx + 1); @@ -362,7 +400,7 @@ Type *BitcodeReader::getTypeByID(unsigned ID) { // If we have a forward reference, the only possible case is when it is to a // named struct. Just create a placeholder for now. - return TypeList[ID] = StructType::createNamed(Context, ""); + return TypeList[ID] = StructType::create(Context); } /// FIXME: Remove in LLVM 3.1, only used by ParseOldTypeTable. @@ -630,7 +668,7 @@ bool BitcodeReader::ParseTypeTableBody() { Res->setName(TypeName); TypeList[NumRecords] = 0; } else // Otherwise, create a new struct. - Res = StructType::createNamed(Context, TypeName); + Res = StructType::create(Context, TypeName); TypeName.clear(); SmallVector EltTys; @@ -659,7 +697,7 @@ bool BitcodeReader::ParseTypeTableBody() { Res->setName(TypeName); TypeList[NumRecords] = 0; } else // Otherwise, create a new struct with no body. - Res = StructType::createNamed(Context, TypeName); + Res = StructType::create(Context, TypeName); TypeName.clear(); ResultTy = Res; break; @@ -793,7 +831,7 @@ RestartScan: break; case bitc::TYPE_CODE_OPAQUE: // OPAQUE if (NextTypeID < TypeList.size() && TypeList[NextTypeID] == 0) - ResultTy = StructType::createNamed(Context, ""); + ResultTy = StructType::create(Context); break; case bitc::TYPE_CODE_STRUCT_OLD: {// STRUCT_OLD if (NextTypeID >= TypeList.size()) break; @@ -804,7 +842,7 @@ RestartScan: // Set a type. if (TypeList[NextTypeID] == 0) - TypeList[NextTypeID] = StructType::createNamed(Context, ""); + TypeList[NextTypeID] = StructType::create(Context); std::vector EltTys; for (unsigned i = 1, e = Record.size(); i != e; ++i) { @@ -923,7 +961,7 @@ bool BitcodeReader::ParseOldTypeSymbolTable() { // Only apply the type name to a struct type with no name. if (StructType *STy = dyn_cast(TypeList[TypeID])) - if (!STy->isAnonymous() && !STy->hasName()) + if (!STy->isLiteral() && !STy->hasName()) STy->setName(TypeName); TypeName.clear(); break; @@ -1063,7 +1101,7 @@ bool BitcodeReader::ParseMetadata() { unsigned Size = Record.size(); SmallVector Elts; for (unsigned i = 0; i != Size; i += 2) { - const Type *Ty = getTypeByID(Record[i]); + Type *Ty = getTypeByID(Record[i]); if (!Ty) return Error("Invalid METADATA_NODE record"); if (Ty->isMetadataTy()) Elts.push_back(MDValueList.getValueFwdRef(Record[i+1])); @@ -1163,7 +1201,7 @@ bool BitcodeReader::ParseConstants() { SmallVector Record; // Read all the records for this value table. - const Type *CurTy = Type::getInt32Ty(Context); + Type *CurTy = Type::getInt32Ty(Context); unsigned NextCstNo = ValueList.size(); while (1) { unsigned Code = Stream.ReadCode(); @@ -1218,7 +1256,7 @@ bool BitcodeReader::ParseConstants() { Words[i] = DecodeSignRotatedValue(Record[i]); V = ConstantInt::get(Context, APInt(cast(CurTy)->getBitWidth(), - NumWords, &Words[0])); + Words)); break; } case bitc::CST_CODE_FLOAT: { // FLOAT: [fpval] @@ -1233,11 +1271,11 @@ bool BitcodeReader::ParseConstants() { uint64_t Rearrange[2]; Rearrange[0] = (Record[1] & 0xffffLL) | (Record[0] << 16); Rearrange[1] = Record[0] >> 48; - V = ConstantFP::get(Context, APFloat(APInt(80, 2, Rearrange))); + V = ConstantFP::get(Context, APFloat(APInt(80, Rearrange))); } else if (CurTy->isFP128Ty()) - V = ConstantFP::get(Context, APFloat(APInt(128, 2, &Record[0]), true)); + V = ConstantFP::get(Context, APFloat(APInt(128, Record), true)); else if (CurTy->isPPC_FP128Ty()) - V = ConstantFP::get(Context, APFloat(APInt(128, 2, &Record[0]))); + V = ConstantFP::get(Context, APFloat(APInt(128, Record))); else V = UndefValue::get(CurTy); break; @@ -1250,18 +1288,18 @@ bool BitcodeReader::ParseConstants() { unsigned Size = Record.size(); std::vector Elts; - if (const StructType *STy = dyn_cast(CurTy)) { + if (StructType *STy = dyn_cast(CurTy)) { for (unsigned i = 0; i != Size; ++i) Elts.push_back(ValueList.getConstantFwdRef(Record[i], STy->getElementType(i))); V = ConstantStruct::get(STy, Elts); - } else if (const ArrayType *ATy = dyn_cast(CurTy)) { - const Type *EltTy = ATy->getElementType(); + } else if (ArrayType *ATy = dyn_cast(CurTy)) { + Type *EltTy = ATy->getElementType(); for (unsigned i = 0; i != Size; ++i) Elts.push_back(ValueList.getConstantFwdRef(Record[i], EltTy)); V = ConstantArray::get(ATy, Elts); - } else if (const VectorType *VTy = dyn_cast(CurTy)) { - const Type *EltTy = VTy->getElementType(); + } else if (VectorType *VTy = dyn_cast(CurTy)) { + Type *EltTy = VTy->getElementType(); for (unsigned i = 0; i != Size; ++i) Elts.push_back(ValueList.getConstantFwdRef(Record[i], EltTy)); V = ConstantVector::get(Elts); @@ -1274,8 +1312,8 @@ bool BitcodeReader::ParseConstants() { if (Record.empty()) return Error("Invalid CST_AGGREGATE record"); - const ArrayType *ATy = cast(CurTy); - const Type *EltTy = ATy->getElementType(); + ArrayType *ATy = cast(CurTy); + Type *EltTy = ATy->getElementType(); unsigned Size = Record.size(); std::vector Elts; @@ -1288,8 +1326,8 @@ bool BitcodeReader::ParseConstants() { if (Record.empty()) return Error("Invalid CST_AGGREGATE record"); - const ArrayType *ATy = cast(CurTy); - const Type *EltTy = ATy->getElementType(); + ArrayType *ATy = cast(CurTy); + Type *EltTy = ATy->getElementType(); unsigned Size = Record.size(); std::vector Elts; @@ -1335,7 +1373,7 @@ bool BitcodeReader::ParseConstants() { if (Opc < 0) { V = UndefValue::get(CurTy); // Unknown cast. } else { - const Type *OpTy = getTypeByID(Record[1]); + Type *OpTy = getTypeByID(Record[1]); if (!OpTy) return Error("Invalid CE_CAST record"); Constant *Op = ValueList.getConstantFwdRef(Record[2], OpTy); V = ConstantExpr::getCast(Opc, Op, CurTy); @@ -1347,16 +1385,14 @@ bool BitcodeReader::ParseConstants() { if (Record.size() & 1) return Error("Invalid CE_GEP record"); SmallVector Elts; for (unsigned i = 0, e = Record.size(); i != e; i += 2) { - const Type *ElTy = getTypeByID(Record[i]); + Type *ElTy = getTypeByID(Record[i]); if (!ElTy) return Error("Invalid CE_GEP record"); Elts.push_back(ValueList.getConstantFwdRef(Record[i+1], ElTy)); } - if (BitCode == bitc::CST_CODE_CE_INBOUNDS_GEP) - V = ConstantExpr::getInBoundsGetElementPtr(Elts[0], &Elts[1], - Elts.size()-1); - else - V = ConstantExpr::getGetElementPtr(Elts[0], &Elts[1], - Elts.size()-1); + ArrayRef Indices(Elts.begin() + 1, Elts.end()); + V = ConstantExpr::getGetElementPtr(Elts[0], Indices, + BitCode == + bitc::CST_CODE_CE_INBOUNDS_GEP); break; } case bitc::CST_CODE_CE_SELECT: // CE_SELECT: [opval#, opval#, opval#] @@ -1368,7 +1404,7 @@ bool BitcodeReader::ParseConstants() { break; case bitc::CST_CODE_CE_EXTRACTELT: { // CE_EXTRACTELT: [opty, opval, opval] if (Record.size() < 3) return Error("Invalid CE_EXTRACTELT record"); - const VectorType *OpTy = + VectorType *OpTy = dyn_cast_or_null(getTypeByID(Record[0])); if (OpTy == 0) return Error("Invalid CE_EXTRACTELT record"); Constant *Op0 = ValueList.getConstantFwdRef(Record[1], OpTy); @@ -1377,7 +1413,7 @@ bool BitcodeReader::ParseConstants() { break; } case bitc::CST_CODE_CE_INSERTELT: { // CE_INSERTELT: [opval, opval, opval] - const VectorType *OpTy = dyn_cast(CurTy); + VectorType *OpTy = dyn_cast(CurTy); if (Record.size() < 3 || OpTy == 0) return Error("Invalid CE_INSERTELT record"); Constant *Op0 = ValueList.getConstantFwdRef(Record[0], OpTy); @@ -1388,26 +1424,26 @@ bool BitcodeReader::ParseConstants() { break; } case bitc::CST_CODE_CE_SHUFFLEVEC: { // CE_SHUFFLEVEC: [opval, opval, opval] - const VectorType *OpTy = dyn_cast(CurTy); + VectorType *OpTy = dyn_cast(CurTy); if (Record.size() < 3 || OpTy == 0) return Error("Invalid CE_SHUFFLEVEC record"); Constant *Op0 = ValueList.getConstantFwdRef(Record[0], OpTy); Constant *Op1 = ValueList.getConstantFwdRef(Record[1], OpTy); - const Type *ShufTy = VectorType::get(Type::getInt32Ty(Context), + Type *ShufTy = VectorType::get(Type::getInt32Ty(Context), OpTy->getNumElements()); Constant *Op2 = ValueList.getConstantFwdRef(Record[2], ShufTy); V = ConstantExpr::getShuffleVector(Op0, Op1, Op2); break; } case bitc::CST_CODE_CE_SHUFVEC_EX: { // [opty, opval, opval, opval] - const VectorType *RTy = dyn_cast(CurTy); - const VectorType *OpTy = + VectorType *RTy = dyn_cast(CurTy); + VectorType *OpTy = dyn_cast_or_null(getTypeByID(Record[0])); if (Record.size() < 4 || RTy == 0 || OpTy == 0) return Error("Invalid CE_SHUFVEC_EX record"); Constant *Op0 = ValueList.getConstantFwdRef(Record[1], OpTy); Constant *Op1 = ValueList.getConstantFwdRef(Record[2], OpTy); - const Type *ShufTy = VectorType::get(Type::getInt32Ty(Context), + Type *ShufTy = VectorType::get(Type::getInt32Ty(Context), RTy->getNumElements()); Constant *Op2 = ValueList.getConstantFwdRef(Record[3], ShufTy); V = ConstantExpr::getShuffleVector(Op0, Op1, Op2); @@ -1415,7 +1451,7 @@ bool BitcodeReader::ParseConstants() { } case bitc::CST_CODE_CE_CMP: { // CE_CMP: [opty, opval, opval, pred] if (Record.size() < 4) return Error("Invalid CE_CMP record"); - const Type *OpTy = getTypeByID(Record[0]); + Type *OpTy = getTypeByID(Record[0]); if (OpTy == 0) return Error("Invalid CE_CMP record"); Constant *Op0 = ValueList.getConstantFwdRef(Record[1], OpTy); Constant *Op1 = ValueList.getConstantFwdRef(Record[2], OpTy); @@ -1442,14 +1478,14 @@ bool BitcodeReader::ParseConstants() { AsmStr += (char)Record[2+i]; for (unsigned i = 0; i != ConstStrSize; ++i) ConstrStr += (char)Record[3+AsmStrSize+i]; - const PointerType *PTy = cast(CurTy); + PointerType *PTy = cast(CurTy); V = InlineAsm::get(cast(PTy->getElementType()), AsmStr, ConstrStr, HasSideEffects, IsAlignStack); break; } case bitc::CST_CODE_BLOCKADDRESS:{ if (Record.size() < 3) return Error("Invalid CE_BLOCKADDRESS record"); - const Type *FnTy = getTypeByID(Record[0]); + Type *FnTy = getTypeByID(Record[0]); if (FnTy == 0) return Error("Invalid CE_BLOCKADDRESS record"); Function *Fn = dyn_cast_or_null(ValueList.getConstantFwdRef(Record[1],FnTy)); @@ -1662,7 +1698,7 @@ bool BitcodeReader::ParseModule() { case bitc::MODULE_CODE_GLOBALVAR: { if (Record.size() < 6) return Error("Invalid MODULE_CODE_GLOBALVAR record"); - const Type *Ty = getTypeByID(Record[0]); + Type *Ty = getTypeByID(Record[0]); if (!Ty) return Error("Invalid MODULE_CODE_GLOBALVAR record"); if (!Ty->isPointerTy()) return Error("Global not a pointer type!"); @@ -1711,11 +1747,11 @@ bool BitcodeReader::ParseModule() { case bitc::MODULE_CODE_FUNCTION: { if (Record.size() < 8) return Error("Invalid MODULE_CODE_FUNCTION record"); - const Type *Ty = getTypeByID(Record[0]); + Type *Ty = getTypeByID(Record[0]); if (!Ty) return Error("Invalid MODULE_CODE_FUNCTION record"); if (!Ty->isPointerTy()) return Error("Function not a pointer type!"); - const FunctionType *FTy = + FunctionType *FTy = dyn_cast(cast(Ty)->getElementType()); if (!FTy) return Error("Function not a pointer to function type!"); @@ -1757,7 +1793,7 @@ bool BitcodeReader::ParseModule() { case bitc::MODULE_CODE_ALIAS: { if (Record.size() < 3) return Error("Invalid MODULE_ALIAS record"); - const Type *Ty = getTypeByID(Record[0]); + Type *Ty = getTypeByID(Record[0]); if (!Ty) return Error("Invalid MODULE_ALIAS record"); if (!Ty->isPointerTy()) return Error("Function not a pointer type!"); @@ -1823,9 +1859,9 @@ bool BitcodeReader::ParseBitcodeInto(Module *M) { if (Code != bitc::ENTER_SUBBLOCK) { - // The ranlib in xcode 4 will align archive members by appending newlines to the - // end of them. If this file size is a multiple of 4 but not 8, we have to read and - // ignore these final 4 bytes :-( + // The ranlib in xcode 4 will align archive members by appending newlines + // to the end of them. If this file size is a multiple of 4 but not 8, we + // have to read and ignore these final 4 bytes :-( if (Stream.GetAbbrevIDWidth() == 2 && Code == 2 && Stream.Read(6) == 2 && Stream.Read(24) == 0xa0a0a && Stream.AtEndOfStream()) @@ -2160,7 +2196,7 @@ bool BitcodeReader::ParseFunctionBody(Function *F) { OpNum+2 != Record.size()) return Error("Invalid CAST record"); - const Type *ResTy = getTypeByID(Record[OpNum]); + Type *ResTy = getTypeByID(Record[OpNum]); int Opc = GetDecodedCastOpcode(Record[OpNum+1]); if (Opc == -1 || ResTy == 0) return Error("Invalid CAST record"); @@ -2183,7 +2219,7 @@ bool BitcodeReader::ParseFunctionBody(Function *F) { GEPIdx.push_back(Op); } - I = GetElementPtrInst::Create(BasePtr, GEPIdx.begin(), GEPIdx.end()); + I = GetElementPtrInst::Create(BasePtr, GEPIdx); InstructionList.push_back(I); if (BitCode == bitc::FUNC_CODE_INST_INBOUNDS_GEP) cast(I)->setIsInBounds(true); @@ -2261,8 +2297,8 @@ bool BitcodeReader::ParseFunctionBody(Function *F) { return Error("Invalid SELECT record"); // select condition can be either i1 or [N x i1] - if (const VectorType* vector_type = - dyn_cast(Cond->getType())) { + if (VectorType* vector_type = + dyn_cast(Cond->getType())) { // expect if (vector_type->getElementType() != Type::getInt1Ty(Context)) return Error("Invalid SELECT condition type"); @@ -2381,7 +2417,7 @@ bool BitcodeReader::ParseFunctionBody(Function *F) { case bitc::FUNC_CODE_INST_SWITCH: { // SWITCH: [opty, op0, op1, ...] if (Record.size() < 3 || (Record.size() & 1) == 0) return Error("Invalid SWITCH record"); - const Type *OpTy = getTypeByID(Record[0]); + Type *OpTy = getTypeByID(Record[0]); Value *Cond = getFnValueByID(Record[1], OpTy); BasicBlock *Default = getBasicBlock(Record[2]); if (OpTy == 0 || Cond == 0 || Default == 0) @@ -2405,7 +2441,7 @@ bool BitcodeReader::ParseFunctionBody(Function *F) { case bitc::FUNC_CODE_INST_INDIRECTBR: { // INDIRECTBR: [opty, op0, op1, ...] if (Record.size() < 2) return Error("Invalid INDIRECTBR record"); - const Type *OpTy = getTypeByID(Record[0]); + Type *OpTy = getTypeByID(Record[0]); Value *Address = getFnValueByID(Record[1], OpTy); if (OpTy == 0 || Address == 0) return Error("Invalid INDIRECTBR record"); @@ -2437,8 +2473,8 @@ bool BitcodeReader::ParseFunctionBody(Function *F) { if (getValueTypePair(Record, OpNum, NextValueNo, Callee)) return Error("Invalid INVOKE record"); - const PointerType *CalleeTy = dyn_cast(Callee->getType()); - const FunctionType *FTy = !CalleeTy ? 0 : + PointerType *CalleeTy = dyn_cast(Callee->getType()); + FunctionType *FTy = !CalleeTy ? 0 : dyn_cast(CalleeTy->getElementType()); // Check that the right number of fixed parameters are here. @@ -2472,6 +2508,15 @@ bool BitcodeReader::ParseFunctionBody(Function *F) { cast(I)->setAttributes(PAL); break; } + case bitc::FUNC_CODE_INST_RESUME: { // RESUME: [opval] + unsigned Idx = 0; + Value *Val = 0; + if (getValueTypePair(Record, Idx, NextValueNo, Val)) + return Error("Invalid RESUME record"); + I = ResumeInst::Create(Val); + InstructionList.push_back(I); + break; + } case bitc::FUNC_CODE_INST_UNWIND: // UNWIND I = new UnwindInst(Context); InstructionList.push_back(I); @@ -2483,7 +2528,7 @@ bool BitcodeReader::ParseFunctionBody(Function *F) { case bitc::FUNC_CODE_INST_PHI: { // PHI: [ty, val0,bb0, ...] if (Record.size() < 1 || ((Record.size()-1)&1)) return Error("Invalid PHI record"); - const Type *Ty = getTypeByID(Record[0]); + Type *Ty = getTypeByID(Record[0]); if (!Ty) return Error("Invalid PHI record"); PHINode *PN = PHINode::Create(Ty, (Record.size()-1)/2); @@ -2499,12 +2544,51 @@ bool BitcodeReader::ParseFunctionBody(Function *F) { break; } + case bitc::FUNC_CODE_INST_LANDINGPAD: { + // LANDINGPAD: [ty, val, val, num, (id0,val0 ...)?] + unsigned Idx = 0; + if (Record.size() < 4) + return Error("Invalid LANDINGPAD record"); + Type *Ty = getTypeByID(Record[Idx++]); + if (!Ty) return Error("Invalid LANDINGPAD record"); + Value *PersFn = 0; + if (getValueTypePair(Record, Idx, NextValueNo, PersFn)) + return Error("Invalid LANDINGPAD record"); + + bool IsCleanup = !!Record[Idx++]; + unsigned NumClauses = Record[Idx++]; + LandingPadInst *LP = LandingPadInst::Create(Ty, PersFn, NumClauses); + LP->setCleanup(IsCleanup); + for (unsigned J = 0; J != NumClauses; ++J) { + LandingPadInst::ClauseType CT = + LandingPadInst::ClauseType(Record[Idx++]); (void)CT; + Value *Val; + + if (getValueTypePair(Record, Idx, NextValueNo, Val)) { + delete LP; + return Error("Invalid LANDINGPAD record"); + } + + assert((CT != LandingPadInst::Catch || + !isa(Val->getType())) && + "Catch clause has a invalid type!"); + assert((CT != LandingPadInst::Filter || + isa(Val->getType())) && + "Filter clause has invalid type!"); + LP->addClause(Val); + } + + I = LP; + InstructionList.push_back(I); + break; + } + case bitc::FUNC_CODE_INST_ALLOCA: { // ALLOCA: [instty, opty, op, align] if (Record.size() != 4) return Error("Invalid ALLOCA record"); - const PointerType *Ty = + PointerType *Ty = dyn_cast_or_null(getTypeByID(Record[0])); - const Type *OpTy = getTypeByID(Record[1]); + Type *OpTy = getTypeByID(Record[1]); Value *Size = getFnValueByID(Record[2], OpTy); unsigned Align = Record[3]; if (!Ty || !Size) return Error("Invalid ALLOCA record"); @@ -2523,6 +2607,28 @@ bool BitcodeReader::ParseFunctionBody(Function *F) { InstructionList.push_back(I); break; } + case bitc::FUNC_CODE_INST_LOADATOMIC: { + // LOADATOMIC: [opty, op, align, vol, ordering, synchscope] + unsigned OpNum = 0; + Value *Op; + if (getValueTypePair(Record, OpNum, NextValueNo, Op) || + OpNum+4 != Record.size()) + return Error("Invalid LOADATOMIC record"); + + + AtomicOrdering Ordering = GetDecodedOrdering(Record[OpNum+2]); + if (Ordering == NotAtomic || Ordering == Release || + Ordering == AcquireRelease) + return Error("Invalid LOADATOMIC record"); + if (Ordering != NotAtomic && Record[OpNum] == 0) + return Error("Invalid LOADATOMIC record"); + SynchronizationScope SynchScope = GetDecodedSynchScope(Record[OpNum+3]); + + I = new LoadInst(Op, "", Record[OpNum+1], (1 << Record[OpNum]) >> 1, + Ordering, SynchScope); + InstructionList.push_back(I); + break; + } case bitc::FUNC_CODE_INST_STORE: { // STORE2:[ptrty, ptr, val, align, vol] unsigned OpNum = 0; Value *Val, *Ptr; @@ -2536,6 +2642,83 @@ bool BitcodeReader::ParseFunctionBody(Function *F) { InstructionList.push_back(I); break; } + case bitc::FUNC_CODE_INST_STOREATOMIC: { + // STOREATOMIC: [ptrty, ptr, val, align, vol, ordering, synchscope] + unsigned OpNum = 0; + Value *Val, *Ptr; + if (getValueTypePair(Record, OpNum, NextValueNo, Ptr) || + getValue(Record, OpNum, + cast(Ptr->getType())->getElementType(), Val) || + OpNum+4 != Record.size()) + return Error("Invalid STOREATOMIC record"); + + AtomicOrdering Ordering = GetDecodedOrdering(Record[OpNum+2]); + if (Ordering == NotAtomic || Ordering == Acquire || + Ordering == AcquireRelease) + return Error("Invalid STOREATOMIC record"); + SynchronizationScope SynchScope = GetDecodedSynchScope(Record[OpNum+3]); + if (Ordering != NotAtomic && Record[OpNum] == 0) + return Error("Invalid STOREATOMIC record"); + + I = new StoreInst(Val, Ptr, Record[OpNum+1], (1 << Record[OpNum]) >> 1, + Ordering, SynchScope); + InstructionList.push_back(I); + break; + } + case bitc::FUNC_CODE_INST_CMPXCHG: { + // CMPXCHG:[ptrty, ptr, cmp, new, vol, ordering, synchscope] + unsigned OpNum = 0; + Value *Ptr, *Cmp, *New; + if (getValueTypePair(Record, OpNum, NextValueNo, Ptr) || + getValue(Record, OpNum, + cast(Ptr->getType())->getElementType(), Cmp) || + getValue(Record, OpNum, + cast(Ptr->getType())->getElementType(), New) || + OpNum+3 != Record.size()) + return Error("Invalid CMPXCHG record"); + AtomicOrdering Ordering = GetDecodedOrdering(Record[OpNum+1]); + if (Ordering == NotAtomic || Ordering == Unordered) + return Error("Invalid CMPXCHG record"); + SynchronizationScope SynchScope = GetDecodedSynchScope(Record[OpNum+2]); + I = new AtomicCmpXchgInst(Ptr, Cmp, New, Ordering, SynchScope); + cast(I)->setVolatile(Record[OpNum]); + InstructionList.push_back(I); + break; + } + case bitc::FUNC_CODE_INST_ATOMICRMW: { + // ATOMICRMW:[ptrty, ptr, val, op, vol, ordering, synchscope] + unsigned OpNum = 0; + Value *Ptr, *Val; + if (getValueTypePair(Record, OpNum, NextValueNo, Ptr) || + getValue(Record, OpNum, + cast(Ptr->getType())->getElementType(), Val) || + OpNum+4 != Record.size()) + return Error("Invalid ATOMICRMW record"); + AtomicRMWInst::BinOp Operation = GetDecodedRMWOperation(Record[OpNum]); + if (Operation < AtomicRMWInst::FIRST_BINOP || + Operation > AtomicRMWInst::LAST_BINOP) + return Error("Invalid ATOMICRMW record"); + AtomicOrdering Ordering = GetDecodedOrdering(Record[OpNum+2]); + if (Ordering == NotAtomic || Ordering == Unordered) + return Error("Invalid ATOMICRMW record"); + SynchronizationScope SynchScope = GetDecodedSynchScope(Record[OpNum+3]); + I = new AtomicRMWInst(Operation, Ptr, Val, Ordering, SynchScope); + cast(I)->setVolatile(Record[OpNum+1]); + InstructionList.push_back(I); + break; + } + case bitc::FUNC_CODE_INST_FENCE: { // FENCE:[ordering, synchscope] + if (2 != Record.size()) + return Error("Invalid FENCE record"); + AtomicOrdering Ordering = GetDecodedOrdering(Record[0]); + if (Ordering == NotAtomic || Ordering == Unordered || + Ordering == Monotonic) + return Error("Invalid FENCE record"); + SynchronizationScope SynchScope = GetDecodedSynchScope(Record[1]); + I = new FenceInst(Context, Ordering, SynchScope); + InstructionList.push_back(I); + break; + } case bitc::FUNC_CODE_INST_CALL: { // CALL: [paramattrs, cc, fnty, fnid, arg0, arg1...] if (Record.size() < 3) @@ -2549,8 +2732,8 @@ bool BitcodeReader::ParseFunctionBody(Function *F) { if (getValueTypePair(Record, OpNum, NextValueNo, Callee)) return Error("Invalid CALL record"); - const PointerType *OpTy = dyn_cast(Callee->getType()); - const FunctionType *FTy = 0; + PointerType *OpTy = dyn_cast(Callee->getType()); + FunctionType *FTy = 0; if (OpTy) FTy = dyn_cast(OpTy->getElementType()); if (!FTy || Record.size() < FTy->getNumParams()+OpNum) return Error("Invalid CALL record"); @@ -2589,9 +2772,9 @@ bool BitcodeReader::ParseFunctionBody(Function *F) { case bitc::FUNC_CODE_INST_VAARG: { // VAARG: [valistty, valist, instty] if (Record.size() < 3) return Error("Invalid VAARG record"); - const Type *OpTy = getTypeByID(Record[0]); + Type *OpTy = getTypeByID(Record[0]); Value *Op = getFnValueByID(Record[1], OpTy); - const Type *ResTy = getTypeByID(Record[2]); + Type *ResTy = getTypeByID(Record[2]); if (!OpTy || !Op || !ResTy) return Error("Invalid VAARG record"); I = new VAArgInst(Op, ResTy); @@ -2756,6 +2939,9 @@ bool BitcodeReader::MaterializeModule(Module *M, std::string *ErrInfo) { } std::vector >().swap(UpgradedIntrinsics); + // Upgrade to new EH scheme. N.B. This will go away in 3.1. + UpgradeExceptionHandling(M); + // Check debug info intrinsics. CheckDebugInfoIntrinsics(TheModule); diff --git a/contrib/llvm/lib/Bitcode/Reader/BitcodeReader.h b/contrib/llvm/lib/Bitcode/Reader/BitcodeReader.h index 1b3bf1a18..6e6118cac 100644 --- a/contrib/llvm/lib/Bitcode/Reader/BitcodeReader.h +++ b/contrib/llvm/lib/Bitcode/Reader/BitcodeReader.h @@ -76,8 +76,8 @@ public: ValuePtrs.resize(N); } - Constant *getConstantFwdRef(unsigned Idx, const Type *Ty); - Value *getValueFwdRef(unsigned Idx, const Type *Ty); + Constant *getConstantFwdRef(unsigned Idx, Type *Ty); + Value *getValueFwdRef(unsigned Idx, Type *Ty); void AssignValue(Value *V, unsigned Idx); @@ -212,7 +212,7 @@ public: private: Type *getTypeByID(unsigned ID); Type *getTypeByIDOrNull(unsigned ID); - Value *getFnValueByID(unsigned ID, const Type *Ty) { + Value *getFnValueByID(unsigned ID, Type *Ty) { if (Ty && Ty->isMetadataTy()) return MDValueList.getValueFwdRef(ID); return ValueList.getValueFwdRef(ID, Ty); @@ -248,7 +248,7 @@ private: return ResVal == 0; } bool getValue(SmallVector &Record, unsigned &Slot, - const Type *Ty, Value *&ResVal) { + Type *Ty, Value *&ResVal) { if (Slot == Record.size()) return true; unsigned ValNo = (unsigned)Record[Slot++]; ResVal = getFnValueByID(ValNo, Ty); diff --git a/contrib/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/contrib/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp index 85d67ce62..5b3d96953 100644 --- a/contrib/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/contrib/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -58,7 +58,6 @@ enum { FUNCTION_INST_UNREACHABLE_ABBREV }; - static unsigned GetEncodedCastOpcode(unsigned Opcode) { switch (Opcode) { default: llvm_unreachable("Unknown cast instruction!"); @@ -101,6 +100,44 @@ static unsigned GetEncodedBinaryOpcode(unsigned Opcode) { } } +static unsigned GetEncodedRMWOperation(AtomicRMWInst::BinOp Op) { + switch (Op) { + default: llvm_unreachable("Unknown RMW operation!"); + case AtomicRMWInst::Xchg: return bitc::RMW_XCHG; + case AtomicRMWInst::Add: return bitc::RMW_ADD; + case AtomicRMWInst::Sub: return bitc::RMW_SUB; + case AtomicRMWInst::And: return bitc::RMW_AND; + case AtomicRMWInst::Nand: return bitc::RMW_NAND; + case AtomicRMWInst::Or: return bitc::RMW_OR; + case AtomicRMWInst::Xor: return bitc::RMW_XOR; + case AtomicRMWInst::Max: return bitc::RMW_MAX; + case AtomicRMWInst::Min: return bitc::RMW_MIN; + case AtomicRMWInst::UMax: return bitc::RMW_UMAX; + case AtomicRMWInst::UMin: return bitc::RMW_UMIN; + } +} + +static unsigned GetEncodedOrdering(AtomicOrdering Ordering) { + switch (Ordering) { + default: llvm_unreachable("Unknown atomic ordering"); + case NotAtomic: return bitc::ORDERING_NOTATOMIC; + case Unordered: return bitc::ORDERING_UNORDERED; + case Monotonic: return bitc::ORDERING_MONOTONIC; + case Acquire: return bitc::ORDERING_ACQUIRE; + case Release: return bitc::ORDERING_RELEASE; + case AcquireRelease: return bitc::ORDERING_ACQREL; + case SequentiallyConsistent: return bitc::ORDERING_SEQCST; + } +} + +static unsigned GetEncodedSynchScope(SynchronizationScope SynchScope) { + switch (SynchScope) { + default: llvm_unreachable("Unknown synchronization scope"); + case SingleThread: return bitc::SYNCHSCOPE_SINGLETHREAD; + case CrossThread: return bitc::SYNCHSCOPE_CROSSTHREAD; + } +} + static void WriteStringRecord(unsigned Code, StringRef Str, unsigned AbbrevToUse, BitstreamWriter &Stream) { SmallVector Vals; @@ -199,7 +236,6 @@ static void WriteTypeTable(const ValueEnumerator &VE, BitstreamWriter &Stream) { Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, Log2_32_Ceil(VE.getTypes().size()+1))); unsigned StructNamedAbbrev = Stream.EmitAbbrev(Abbv); - // Abbrev for TYPE_CODE_ARRAY. Abbv = new BitCodeAbbrev(); @@ -216,7 +252,7 @@ static void WriteTypeTable(const ValueEnumerator &VE, BitstreamWriter &Stream) { // Loop over all of the types, emitting each in turn. for (unsigned i = 0, e = TypeList.size(); i != e; ++i) { - const Type *T = TypeList[i]; + Type *T = TypeList[i]; int AbbrevToUse = 0; unsigned Code = 0; @@ -237,7 +273,7 @@ static void WriteTypeTable(const ValueEnumerator &VE, BitstreamWriter &Stream) { TypeVals.push_back(cast(T)->getBitWidth()); break; case Type::PointerTyID: { - const PointerType *PTy = cast(T); + PointerType *PTy = cast(T); // POINTER: [pointee type, address space] Code = bitc::TYPE_CODE_POINTER; TypeVals.push_back(VE.getTypeID(PTy->getElementType())); @@ -247,7 +283,7 @@ static void WriteTypeTable(const ValueEnumerator &VE, BitstreamWriter &Stream) { break; } case Type::FunctionTyID: { - const FunctionType *FT = cast(T); + FunctionType *FT = cast(T); // FUNCTION: [isvararg, attrid, retty, paramty x N] Code = bitc::TYPE_CODE_FUNCTION; TypeVals.push_back(FT->isVarArg()); @@ -259,7 +295,7 @@ static void WriteTypeTable(const ValueEnumerator &VE, BitstreamWriter &Stream) { break; } case Type::StructTyID: { - const StructType *ST = cast(T); + StructType *ST = cast(T); // STRUCT: [ispacked, eltty x N] TypeVals.push_back(ST->isPacked()); // Output all of the element types. @@ -267,7 +303,7 @@ static void WriteTypeTable(const ValueEnumerator &VE, BitstreamWriter &Stream) { E = ST->element_end(); I != E; ++I) TypeVals.push_back(VE.getTypeID(*I)); - if (ST->isAnonymous()) { + if (ST->isLiteral()) { Code = bitc::TYPE_CODE_STRUCT_ANON; AbbrevToUse = StructAnonAbbrev; } else { @@ -286,7 +322,7 @@ static void WriteTypeTable(const ValueEnumerator &VE, BitstreamWriter &Stream) { break; } case Type::ArrayTyID: { - const ArrayType *AT = cast(T); + ArrayType *AT = cast(T); // ARRAY: [numelts, eltty] Code = bitc::TYPE_CODE_ARRAY; TypeVals.push_back(AT->getNumElements()); @@ -295,7 +331,7 @@ static void WriteTypeTable(const ValueEnumerator &VE, BitstreamWriter &Stream) { break; } case Type::VectorTyID: { - const VectorType *VT = cast(T); + VectorType *VT = cast(T); // VECTOR [numelts, eltty] Code = bitc::TYPE_CODE_VECTOR; TypeVals.push_back(VT->getNumElements()); @@ -372,14 +408,15 @@ static void WriteModuleInfo(const Module *M, const ValueEnumerator &VE, GV != E; ++GV) { MaxAlignment = std::max(MaxAlignment, GV->getAlignment()); MaxGlobalType = std::max(MaxGlobalType, VE.getTypeID(GV->getType())); - - if (!GV->hasSection()) continue; - // Give section names unique ID's. - unsigned &Entry = SectionMap[GV->getSection()]; - if (Entry != 0) continue; - WriteStringRecord(bitc::MODULE_CODE_SECTIONNAME, GV->getSection(), - 0/*TODO*/, Stream); - Entry = SectionMap.size(); + if (GV->hasSection()) { + // Give section names unique ID's. + unsigned &Entry = SectionMap[GV->getSection()]; + if (!Entry) { + WriteStringRecord(bitc::MODULE_CODE_SECTIONNAME, GV->getSection(), + 0/*TODO*/, Stream); + Entry = SectionMap.size(); + } + } } for (Module::const_iterator F = M->begin(), E = M->end(); F != E; ++F) { MaxAlignment = std::max(MaxAlignment, F->getAlignment()); @@ -716,7 +753,7 @@ static void WriteConstants(unsigned FirstVal, unsigned LastVal, SmallVector Record; const ValueEnumerator::ValueList &Vals = VE.getValues(); - const Type *LastTy = 0; + Type *LastTy = 0; for (unsigned i = FirstVal; i != LastVal; ++i) { const Value *V = Vals[i].first; // If we need to switch types, do so now. @@ -781,7 +818,7 @@ static void WriteConstants(unsigned FirstVal, unsigned LastVal, } } else if (const ConstantFP *CFP = dyn_cast(C)) { Code = bitc::CST_CODE_FLOAT; - const Type *Ty = CFP->getType(); + Type *Ty = CFP->getType(); if (Ty->isFloatTy() || Ty->isDoubleTy()) { Record.push_back(CFP->getValueAPF().bitcastToAPInt().getZExtValue()); } else if (Ty->isX86_FP80Ty()) { @@ -1083,8 +1120,8 @@ static void WriteInstruction(const Instruction &I, unsigned InstID, case Instruction::Invoke: { const InvokeInst *II = cast(&I); const Value *Callee(II->getCalledValue()); - const PointerType *PTy = cast(Callee->getType()); - const FunctionType *FTy = cast(PTy->getElementType()); + PointerType *PTy = cast(Callee->getType()); + FunctionType *FTy = cast(PTy->getElementType()); Code = bitc::FUNC_CODE_INST_INVOKE; Vals.push_back(VE.getAttributeID(II->getAttributes())); @@ -1105,6 +1142,10 @@ static void WriteInstruction(const Instruction &I, unsigned InstID, } break; } + case Instruction::Resume: + Code = bitc::FUNC_CODE_INST_RESUME; + PushValueAndType(I.getOperand(0), InstID, Vals, VE); + break; case Instruction::Unwind: Code = bitc::FUNC_CODE_INST_UNWIND; break; @@ -1124,6 +1165,23 @@ static void WriteInstruction(const Instruction &I, unsigned InstID, break; } + case Instruction::LandingPad: { + const LandingPadInst &LP = cast(I); + Code = bitc::FUNC_CODE_INST_LANDINGPAD; + Vals.push_back(VE.getTypeID(LP.getType())); + PushValueAndType(LP.getPersonalityFn(), InstID, Vals, VE); + Vals.push_back(LP.isCleanup()); + Vals.push_back(LP.getNumClauses()); + for (unsigned I = 0, E = LP.getNumClauses(); I != E; ++I) { + if (LP.isCatch(I)) + Vals.push_back(LandingPadInst::Catch); + else + Vals.push_back(LandingPadInst::Filter); + PushValueAndType(LP.getClause(I), InstID, Vals, VE); + } + break; + } + case Instruction::Alloca: Code = bitc::FUNC_CODE_INST_ALLOCA; Vals.push_back(VE.getTypeID(I.getType())); @@ -1133,24 +1191,66 @@ static void WriteInstruction(const Instruction &I, unsigned InstID, break; case Instruction::Load: - Code = bitc::FUNC_CODE_INST_LOAD; - if (!PushValueAndType(I.getOperand(0), InstID, Vals, VE)) // ptr - AbbrevToUse = FUNCTION_INST_LOAD_ABBREV; - + if (cast(I).isAtomic()) { + Code = bitc::FUNC_CODE_INST_LOADATOMIC; + PushValueAndType(I.getOperand(0), InstID, Vals, VE); + } else { + Code = bitc::FUNC_CODE_INST_LOAD; + if (!PushValueAndType(I.getOperand(0), InstID, Vals, VE)) // ptr + AbbrevToUse = FUNCTION_INST_LOAD_ABBREV; + } Vals.push_back(Log2_32(cast(I).getAlignment())+1); Vals.push_back(cast(I).isVolatile()); + if (cast(I).isAtomic()) { + Vals.push_back(GetEncodedOrdering(cast(I).getOrdering())); + Vals.push_back(GetEncodedSynchScope(cast(I).getSynchScope())); + } break; case Instruction::Store: - Code = bitc::FUNC_CODE_INST_STORE; + if (cast(I).isAtomic()) + Code = bitc::FUNC_CODE_INST_STOREATOMIC; + else + Code = bitc::FUNC_CODE_INST_STORE; PushValueAndType(I.getOperand(1), InstID, Vals, VE); // ptrty + ptr Vals.push_back(VE.getValueID(I.getOperand(0))); // val. Vals.push_back(Log2_32(cast(I).getAlignment())+1); Vals.push_back(cast(I).isVolatile()); + if (cast(I).isAtomic()) { + Vals.push_back(GetEncodedOrdering(cast(I).getOrdering())); + Vals.push_back(GetEncodedSynchScope(cast(I).getSynchScope())); + } + break; + case Instruction::AtomicCmpXchg: + Code = bitc::FUNC_CODE_INST_CMPXCHG; + PushValueAndType(I.getOperand(0), InstID, Vals, VE); // ptrty + ptr + Vals.push_back(VE.getValueID(I.getOperand(1))); // cmp. + Vals.push_back(VE.getValueID(I.getOperand(2))); // newval. + Vals.push_back(cast(I).isVolatile()); + Vals.push_back(GetEncodedOrdering( + cast(I).getOrdering())); + Vals.push_back(GetEncodedSynchScope( + cast(I).getSynchScope())); + break; + case Instruction::AtomicRMW: + Code = bitc::FUNC_CODE_INST_ATOMICRMW; + PushValueAndType(I.getOperand(0), InstID, Vals, VE); // ptrty + ptr + Vals.push_back(VE.getValueID(I.getOperand(1))); // val. + Vals.push_back(GetEncodedRMWOperation( + cast(I).getOperation())); + Vals.push_back(cast(I).isVolatile()); + Vals.push_back(GetEncodedOrdering(cast(I).getOrdering())); + Vals.push_back(GetEncodedSynchScope( + cast(I).getSynchScope())); + break; + case Instruction::Fence: + Code = bitc::FUNC_CODE_INST_FENCE; + Vals.push_back(GetEncodedOrdering(cast(I).getOrdering())); + Vals.push_back(GetEncodedSynchScope(cast(I).getSynchScope())); break; case Instruction::Call: { const CallInst &CI = cast(I); - const PointerType *PTy = cast(CI.getCalledValue()->getType()); - const FunctionType *FTy = cast(PTy->getElementType()); + PointerType *PTy = cast(CI.getCalledValue()->getType()); + FunctionType *FTy = cast(PTy->getElementType()); Code = bitc::FUNC_CODE_INST_CALL; diff --git a/contrib/llvm/lib/Bitcode/Writer/ValueEnumerator.cpp b/contrib/llvm/lib/Bitcode/Writer/ValueEnumerator.cpp index b68bf92d5..9ae9905b9 100644 --- a/contrib/llvm/lib/Bitcode/Writer/ValueEnumerator.cpp +++ b/contrib/llvm/lib/Bitcode/Writer/ValueEnumerator.cpp @@ -315,7 +315,7 @@ void ValueEnumerator::EnumerateValue(const Value *V) { } -void ValueEnumerator::EnumerateType(const Type *Ty) { +void ValueEnumerator::EnumerateType(Type *Ty) { unsigned *TypeID = &TypeMap[Ty]; // We've already seen this type. @@ -325,8 +325,8 @@ void ValueEnumerator::EnumerateType(const Type *Ty) { // If it is a non-anonymous struct, mark the type as being visited so that we // don't recursively visit it. This is safe because we allow forward // references of these in the bitcode reader. - if (const StructType *STy = dyn_cast(Ty)) - if (!STy->isAnonymous()) + if (StructType *STy = dyn_cast(Ty)) + if (!STy->isLiteral()) *TypeID = ~0U; // Enumerate all of the subtypes before we enumerate this type. This ensures diff --git a/contrib/llvm/lib/Bitcode/Writer/ValueEnumerator.h b/contrib/llvm/lib/Bitcode/Writer/ValueEnumerator.h index 6617b60de..b6fc920e4 100644 --- a/contrib/llvm/lib/Bitcode/Writer/ValueEnumerator.h +++ b/contrib/llvm/lib/Bitcode/Writer/ValueEnumerator.h @@ -35,12 +35,12 @@ class MDSymbolTable; class ValueEnumerator { public: - typedef std::vector TypeList; + typedef std::vector TypeList; // For each value, we remember its Value* and occurrence frequency. typedef std::vector > ValueList; private: - typedef DenseMap TypeMapType; + typedef DenseMap TypeMapType; TypeMapType TypeMap; TypeList Types; @@ -85,7 +85,7 @@ public: unsigned getValueID(const Value *V) const; - unsigned getTypeID(const Type *T) const { + unsigned getTypeID(Type *T) const { TypeMapType::const_iterator I = TypeMap.find(T); assert(I != TypeMap.end() && "Type not in ValueEnumerator!"); return I->second-1; @@ -140,7 +140,7 @@ private: void EnumerateFunctionLocalMetadata(const MDNode *N); void EnumerateNamedMDNode(const NamedMDNode *NMD); void EnumerateValue(const Value *V); - void EnumerateType(const Type *T); + void EnumerateType(Type *T); void EnumerateOperandType(const Value *V); void EnumerateAttributes(const AttrListPtr &PAL); diff --git a/contrib/llvm/lib/CodeGen/Analysis.cpp b/contrib/llvm/lib/CodeGen/Analysis.cpp index 125e64196..fafc01044 100644 --- a/contrib/llvm/lib/CodeGen/Analysis.cpp +++ b/contrib/llvm/lib/CodeGen/Analysis.cpp @@ -31,7 +31,7 @@ using namespace llvm; /// of insertvalue or extractvalue indices that identify a member, return /// the linearized index of the start of the member. /// -unsigned llvm::ComputeLinearIndex(const Type *Ty, +unsigned llvm::ComputeLinearIndex(Type *Ty, const unsigned *Indices, const unsigned *IndicesEnd, unsigned CurIndex) { @@ -40,7 +40,7 @@ unsigned llvm::ComputeLinearIndex(const Type *Ty, return CurIndex; // Given a struct type, recursively traverse the elements. - if (const StructType *STy = dyn_cast(Ty)) { + if (StructType *STy = dyn_cast(Ty)) { for (StructType::element_iterator EB = STy->element_begin(), EI = EB, EE = STy->element_end(); @@ -52,8 +52,8 @@ unsigned llvm::ComputeLinearIndex(const Type *Ty, return CurIndex; } // Given an array type, recursively traverse the elements. - else if (const ArrayType *ATy = dyn_cast(Ty)) { - const Type *EltTy = ATy->getElementType(); + else if (ArrayType *ATy = dyn_cast(Ty)) { + Type *EltTy = ATy->getElementType(); for (unsigned i = 0, e = ATy->getNumElements(); i != e; ++i) { if (Indices && *Indices == i) return ComputeLinearIndex(EltTy, Indices+1, IndicesEnd, CurIndex); @@ -72,12 +72,12 @@ unsigned llvm::ComputeLinearIndex(const Type *Ty, /// If Offsets is non-null, it points to a vector to be filled in /// with the in-memory offsets of each of the individual values. /// -void llvm::ComputeValueVTs(const TargetLowering &TLI, const Type *Ty, +void llvm::ComputeValueVTs(const TargetLowering &TLI, Type *Ty, SmallVectorImpl &ValueVTs, SmallVectorImpl *Offsets, uint64_t StartingOffset) { // Given a struct type, recursively traverse the elements. - if (const StructType *STy = dyn_cast(Ty)) { + if (StructType *STy = dyn_cast(Ty)) { const StructLayout *SL = TLI.getTargetData()->getStructLayout(STy); for (StructType::element_iterator EB = STy->element_begin(), EI = EB, @@ -88,8 +88,8 @@ void llvm::ComputeValueVTs(const TargetLowering &TLI, const Type *Ty, return; } // Given an array type, recursively traverse the elements. - if (const ArrayType *ATy = dyn_cast(Ty)) { - const Type *EltTy = ATy->getElementType(); + if (ArrayType *ATy = dyn_cast(Ty)) { + Type *EltTy = ATy->getElementType(); uint64_t EltSize = TLI.getTargetData()->getTypeAllocSize(EltTy); for (unsigned i = 0, e = ATy->getNumElements(); i != e; ++i) ComputeValueVTs(TLI, EltTy, ValueVTs, Offsets, diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/ARMException.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/ARMException.cpp index 5861fa481..3f2387325 100644 --- a/contrib/llvm/lib/CodeGen/AsmPrinter/ARMException.cpp +++ b/contrib/llvm/lib/CodeGen/AsmPrinter/ARMException.cpp @@ -17,7 +17,6 @@ #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" -#include "llvm/CodeGen/MachineLocation.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" @@ -27,7 +26,6 @@ #include "llvm/Target/Mangler.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetFrameLowering.h" -#include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" #include "llvm/Target/TargetRegisterInfo.h" diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index 7f314eed3..1999f3608 100644 --- a/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -33,7 +33,6 @@ #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" #include "llvm/Target/Mangler.h" -#include "llvm/Target/TargetAsmInfo.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetInstrInfo.h" #include "llvm/Target/TargetLowering.h" @@ -45,6 +44,7 @@ #include "llvm/ADT/Statistic.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Format.h" +#include "llvm/Support/MathExtras.h" #include "llvm/Support/Timer.h" using namespace llvm; @@ -290,10 +290,10 @@ void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { // Handle common and BSS local symbols (.lcomm). if (GVKind.isCommon() || GVKind.isBSSLocal()) { if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it. + unsigned Align = 1 << AlignLog; // Handle common symbols. if (GVKind.isCommon()) { - unsigned Align = 1 << AlignLog; if (!getObjFileLowering().getCommDirectiveSupportsAlignment()) Align = 0; @@ -307,17 +307,17 @@ void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { const MCSection *TheSection = getObjFileLowering().SectionForGlobal(GV, GVKind, Mang, TM); // .zerofill __DATA, __bss, _foo, 400, 5 - OutStreamer.EmitZerofill(TheSection, GVSym, Size, 1 << AlignLog); + OutStreamer.EmitZerofill(TheSection, GVSym, Size, Align); return; } - if (MAI->hasLCOMMDirective()) { + if (MAI->getLCOMMDirectiveType() != LCOMM::None && + (MAI->getLCOMMDirectiveType() != LCOMM::NoAlignment || Align == 1)) { // .lcomm _foo, 42 - OutStreamer.EmitLocalCommonSymbol(GVSym, Size); + OutStreamer.EmitLocalCommonSymbol(GVSym, Size, Align); return; } - unsigned Align = 1 << AlignLog; if (!getObjFileLowering().getCommDirectiveSupportsAlignment()) Align = 0; @@ -474,8 +474,10 @@ void AsmPrinter::EmitFunctionHeader() { void AsmPrinter::EmitFunctionEntryLabel() { // The function label could have already been emitted if two symbols end up // conflicting due to asm renaming. Detect this and emit an error. - if (CurrentFnSym->isUndefined()) + if (CurrentFnSym->isUndefined()) { + OutStreamer.ForceCodeRegion(); return OutStreamer.EmitLabel(CurrentFnSym); + } report_fatal_error("'" + Twine(CurrentFnSym->getName()) + "' label emitted multiple times to assembly file"); @@ -620,6 +622,9 @@ void AsmPrinter::emitPrologLabel(const MachineInstr &MI) { if (needsCFIMoves() == CFI_M_None) return; + if (MMI->getCompactUnwindEncoding() != 0) + OutStreamer.EmitCompactUnwindEncoding(MMI->getCompactUnwindEncoding()); + MachineModuleInfo &MMI = MF->getMMI(); std::vector &Moves = MMI.getFrameMoves(); bool FoundOne = false; @@ -878,7 +883,7 @@ bool AsmPrinter::doFinalization(Module &M) { I != E; ++I) { MCSymbol *Name = Mang->getSymbol(I); - const GlobalValue *GV = cast(I->getAliasedGlobal()); + const GlobalValue *GV = I->getAliasedGlobal(); MCSymbol *Target = Mang->getSymbol(GV); if (I->hasExternalLinkage() || !MAI->getWeakRefDirective()) @@ -1009,7 +1014,7 @@ void AsmPrinter::EmitConstantPool() { unsigned NewOffset = (Offset + AlignMask) & ~AlignMask; OutStreamer.EmitFill(NewOffset - Offset, 0/*fillval*/, 0/*addrspace*/); - const Type *Ty = CPE.getType(); + Type *Ty = CPE.getType(); Offset = NewOffset + TM.getTargetData()->getTypeAllocSize(Ty); OutStreamer.EmitLabel(GetCPISymbol(CPI)); @@ -1055,6 +1060,15 @@ void AsmPrinter::EmitJumpTableInfo() { EmitAlignment(Log2_32(MJTI->getEntryAlignment(*TM.getTargetData()))); + // If we know the form of the jump table, go ahead and tag it as such. + if (!JTInDiffSection) { + if (MJTI->getEntryKind() == MachineJumpTableInfo::EK_LabelDifference32) { + OutStreamer.EmitJumpTable32Region(); + } else { + OutStreamer.EmitDataRegion(); + } + } + for (unsigned JTI = 0, e = JT.size(); JTI != e; ++JTI) { const std::vector &JTBBs = JT[JTI].MBBs; @@ -1226,22 +1240,53 @@ void AsmPrinter::EmitLLVMUsedList(const Constant *List) { } } -/// EmitXXStructorList - Emit the ctor or dtor list. This just prints out the -/// function pointers, ignoring the init priority. +typedef std::pair Structor; + +static bool priority_order(const Structor& lhs, const Structor& rhs) { + return lhs.first < rhs.first; +} + +/// EmitXXStructorList - Emit the ctor or dtor list taking into account the init +/// priority. void AsmPrinter::EmitXXStructorList(const Constant *List) { // Should be an array of '{ int, void ()* }' structs. The first value is the - // init priority, which we ignore. + // init priority. if (!isa(List)) return; - const ConstantArray *InitList = cast(List); - for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) - if (ConstantStruct *CS = dyn_cast(InitList->getOperand(i))){ - if (CS->getNumOperands() != 2) return; // Not array of 2-element structs. - - if (CS->getOperand(1)->isNullValue()) - return; // Found a null terminator, exit printing. - // Emit the function pointer. - EmitGlobalConstant(CS->getOperand(1)); - } + + // Sanity check the structors list. + const ConstantArray *InitList = dyn_cast(List); + if (!InitList) return; // Not an array! + StructType *ETy = dyn_cast(InitList->getType()->getElementType()); + if (!ETy || ETy->getNumElements() != 2) return; // Not an array of pairs! + if (!isa(ETy->getTypeAtIndex(0U)) || + !isa(ETy->getTypeAtIndex(1U))) return; // Not (int, ptr). + + // Gather the structors in a form that's convenient for sorting by priority. + SmallVector Structors; + for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) { + ConstantStruct *CS = dyn_cast(InitList->getOperand(i)); + if (!CS) continue; // Malformed. + if (CS->getOperand(1)->isNullValue()) + break; // Found a null terminator, skip the rest. + ConstantInt *Priority = dyn_cast(CS->getOperand(0)); + if (!Priority) continue; // Malformed. + Structors.push_back(std::make_pair(Priority->getLimitedValue(65535), + CS->getOperand(1))); + } + + // Emit the function pointers in reverse priority order. + switch (MAI->getStructorOutputOrder()) { + case Structors::None: + break; + case Structors::PriorityOrder: + std::sort(Structors.begin(), Structors.end(), priority_order); + break; + case Structors::ReversePriorityOrder: + std::sort(Structors.rbegin(), Structors.rend(), priority_order); + break; + } + for (unsigned i = 0, e = Structors.size(); i != e; ++i) + EmitGlobalConstant(Structors[i].second); } //===--------------------------------------------------------------------===// @@ -1406,8 +1451,7 @@ static const MCExpr *LowerConstant(const Constant *CV, AsmPrinter &AP) { // Generate a symbolic expression for the byte address const Constant *PtrVal = CE->getOperand(0); SmallVector IdxVec(CE->op_begin()+1, CE->op_end()); - int64_t Offset = TD.getIndexedOffset(PtrVal->getType(), &IdxVec[0], - IdxVec.size()); + int64_t Offset = TD.getIndexedOffset(PtrVal->getType(), IdxVec); const MCExpr *Base = LowerConstant(CE->getOperand(0), AP); if (Offset == 0) @@ -1447,7 +1491,7 @@ static const MCExpr *LowerConstant(const Constant *CV, AsmPrinter &AP) { // Support only foldable casts to/from pointers that can be eliminated by // changing the pointer to the appropriately sized integer type. Constant *Op = CE->getOperand(0); - const Type *Ty = CE->getType(); + Type *Ty = CE->getType(); const MCExpr *OpExpr = LowerConstant(Op, AP); @@ -1496,12 +1540,67 @@ static const MCExpr *LowerConstant(const Constant *CV, AsmPrinter &AP) { static void EmitGlobalConstantImpl(const Constant *C, unsigned AddrSpace, AsmPrinter &AP); +/// isRepeatedByteSequence - Determine whether the given value is +/// composed of a repeated sequence of identical bytes and return the +/// byte value. If it is not a repeated sequence, return -1. +static int isRepeatedByteSequence(const Value *V, TargetMachine &TM) { + + if (const ConstantInt *CI = dyn_cast(V)) { + if (CI->getBitWidth() > 64) return -1; + + uint64_t Size = TM.getTargetData()->getTypeAllocSize(V->getType()); + uint64_t Value = CI->getZExtValue(); + + // Make sure the constant is at least 8 bits long and has a power + // of 2 bit width. This guarantees the constant bit width is + // always a multiple of 8 bits, avoiding issues with padding out + // to Size and other such corner cases. + if (CI->getBitWidth() < 8 || !isPowerOf2_64(CI->getBitWidth())) return -1; + + uint8_t Byte = static_cast(Value); + + for (unsigned i = 1; i < Size; ++i) { + Value >>= 8; + if (static_cast(Value) != Byte) return -1; + } + return Byte; + } + if (const ConstantArray *CA = dyn_cast(V)) { + // Make sure all array elements are sequences of the same repeated + // byte. + if (CA->getNumOperands() == 0) return -1; + + int Byte = isRepeatedByteSequence(CA->getOperand(0), TM); + if (Byte == -1) return -1; + + for (unsigned i = 1, e = CA->getNumOperands(); i != e; ++i) { + int ThisByte = isRepeatedByteSequence(CA->getOperand(i), TM); + if (ThisByte == -1) return -1; + if (Byte != ThisByte) return -1; + } + return Byte; + } + + return -1; +} + static void EmitGlobalConstantArray(const ConstantArray *CA, unsigned AddrSpace, AsmPrinter &AP) { if (AddrSpace != 0 || !CA->isString()) { - // Not a string. Print the values in successive locations - for (unsigned i = 0, e = CA->getNumOperands(); i != e; ++i) - EmitGlobalConstantImpl(CA->getOperand(i), AddrSpace, AP); + // Not a string. Print the values in successive locations. + + // See if we can aggregate some values. Make sure it can be + // represented as a series of bytes of the constant value. + int Value = isRepeatedByteSequence(CA, AP.TM); + + if (Value != -1) { + uint64_t Bytes = AP.TM.getTargetData()->getTypeAllocSize(CA->getType()); + AP.OutStreamer.EmitFill(Bytes, Value, AddrSpace); + } + else { + for (unsigned i = 0, e = CA->getNumOperands(); i != e; ++i) + EmitGlobalConstantImpl(CA->getOperand(i), AddrSpace, AP); + } return; } diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp index dd5b0e261..4d6c28118 100644 --- a/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp +++ b/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp @@ -13,7 +13,7 @@ #define DEBUG_TYPE "asm-printer" #include "llvm/CodeGen/AsmPrinter.h" -#include "llvm/CodeGen/MachineLocation.h" +#include "llvm/MC/MachineLocation.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCSection.h" #include "llvm/MC/MCStreamer.h" diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp index 5ac455e1a..8eda88915 100644 --- a/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp +++ b/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp @@ -23,15 +23,15 @@ #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/MC/MCSymbol.h" -#include "llvm/Target/TargetAsmParser.h" +#include "llvm/MC/MCTargetAsmParser.h" #include "llvm/Target/TargetMachine.h" -#include "llvm/Target/TargetRegistry.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/SourceMgr.h" +#include "llvm/Support/TargetRegistry.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; @@ -49,7 +49,7 @@ namespace { static void SrcMgrDiagHandler(const SMDiagnostic &Diag, void *diagInfo) { SrcMgrDiagInfo *DiagInfo = static_cast(diagInfo); assert(DiagInfo && "Diagnostic context not passed down?"); - + // If the inline asm had metadata associated with it, pull out a location // cookie corresponding to which line the error occurred on. unsigned LocCookie = 0; @@ -57,13 +57,13 @@ static void SrcMgrDiagHandler(const SMDiagnostic &Diag, void *diagInfo) { unsigned ErrorLine = Diag.getLineNo()-1; if (ErrorLine >= LocInfo->getNumOperands()) ErrorLine = 0; - + if (LocInfo->getNumOperands() != 0) if (const ConstantInt *CI = dyn_cast(LocInfo->getOperand(ErrorLine))) LocCookie = CI->getZExtValue(); } - + DiagInfo->DiagHandler(Diag, DiagInfo->DiagContext, LocCookie); } @@ -109,7 +109,7 @@ void AsmPrinter::EmitInlineAsm(StringRef Str, const MDNode *LocMDNode) const { // Tell SrcMgr about this buffer, it takes ownership of the buffer. SrcMgr.AddNewSourceBuffer(Buffer, SMLoc()); - OwningPtr Parser(createMCAsmParser(TM.getTarget(), SrcMgr, + OwningPtr Parser(createMCAsmParser(SrcMgr, OutContext, OutStreamer, *MAI)); @@ -121,7 +121,8 @@ void AsmPrinter::EmitInlineAsm(StringRef Str, const MDNode *LocMDNode) const { STI(TM.getTarget().createMCSubtargetInfo(TM.getTargetTriple(), TM.getTargetCPU(), TM.getTargetFeatureString())); - OwningPtr TAP(TM.getTarget().createAsmParser(*STI, *Parser)); + OwningPtr + TAP(TM.getTarget().createMCAsmParser(*STI, *Parser)); if (!TAP) report_fatal_error("Inline asm not supported by this streamer because" " we don't have an asm parser for this target\n"); diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DIE.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/DIE.cpp index 21396ca37..9c1ce761b 100644 --- a/contrib/llvm/lib/CodeGen/AsmPrinter/DIE.cpp +++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DIE.cpp @@ -69,7 +69,7 @@ void DIEAbbrev::Emit(AsmPrinter *AP) const { // Emit attribute type. // FIXME: Doing work even in non-asm-verbose runs. AP->EmitULEB128(AttrData.getAttribute(), - dwarf::AttributeString(AttrData.getAttribute())); + dwarf::AttributeString(AttrData.getAttribute())); // Emit form type. // FIXME: Doing work even in non-asm-verbose runs. diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp index 91b7d08c6..8ed4f4c43 100644 --- a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp +++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp @@ -17,7 +17,7 @@ #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" -#include "llvm/CodeGen/MachineLocation.h" +#include "llvm/MC/MachineLocation.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" @@ -77,7 +77,8 @@ void DwarfCFIException::EndModule() { // This is a temporary hack to keep sections in the same order they // were before. This lets us produce bit identical outputs while // transitioning to CFI. - Asm->OutStreamer.SwitchSection(TLOF.getEHFrameSection()); + Asm->OutStreamer.SwitchSection( + const_cast(TLOF).getEHFrameSection()); } } diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp index 1fe035efd..88b752473 100644 --- a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp +++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp @@ -16,7 +16,10 @@ #include "DwarfCompileUnit.h" #include "DwarfDebug.h" #include "llvm/Constants.h" +#include "llvm/GlobalVariable.h" +#include "llvm/Instructions.h" #include "llvm/Analysis/DIBuilder.h" +#include "llvm/Target/Mangler.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetFrameLowering.h" #include "llvm/Target/TargetMachine.h" @@ -132,8 +135,8 @@ void CompileUnit::addSourceLine(DIE *Die, DIGlobalVariable G) { unsigned Line = G.getLineNumber(); if (Line == 0) return; - unsigned FileID = DD->GetOrCreateSourceID(G.getContext().getFilename(), - G.getContext().getDirectory()); + unsigned FileID = DD->GetOrCreateSourceID(G.getFilename(), + G.getDirectory()); assert(FileID && "Invalid file id"); addUInt(Die, dwarf::DW_AT_decl_file, 0, FileID); addUInt(Die, dwarf::DW_AT_decl_line, 0, Line); @@ -439,27 +442,36 @@ void CompileUnit::addBlockByrefAddress(DbgVariable *&DV, DIE *Die, addBlock(Die, Attribute, 0, Block); } +/// isTypeSigned - Return true if the type is signed. +static bool isTypeSigned(DIType Ty, int *SizeInBits) { + if (Ty.isDerivedType()) + return isTypeSigned(DIDerivedType(Ty).getTypeDerivedFrom(), SizeInBits); + if (Ty.isBasicType()) + if (DIBasicType(Ty).getEncoding() == dwarf::DW_ATE_signed + || DIBasicType(Ty).getEncoding() == dwarf::DW_ATE_signed_char) { + *SizeInBits = Ty.getSizeInBits(); + return true; + } + return false; +} + /// addConstantValue - Add constant value entry in variable DIE. bool CompileUnit::addConstantValue(DIE *Die, const MachineOperand &MO, DIType Ty) { assert (MO.isImm() && "Invalid machine operand!"); DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); - unsigned form = dwarf::DW_FORM_udata; - switch (Ty.getSizeInBits()) { - case 8: form = dwarf::DW_FORM_data1; break; - case 16: form = dwarf::DW_FORM_data2; break; - case 32: form = dwarf::DW_FORM_data4; break; - case 64: form = dwarf::DW_FORM_data8; break; + int SizeInBits = -1; + bool SignedConstant = isTypeSigned(Ty, &SizeInBits); + unsigned Form = SignedConstant ? dwarf::DW_FORM_sdata : dwarf::DW_FORM_udata; + switch (SizeInBits) { + case 8: Form = dwarf::DW_FORM_data1; break; + case 16: Form = dwarf::DW_FORM_data2; break; + case 32: Form = dwarf::DW_FORM_data4; break; + case 64: Form = dwarf::DW_FORM_data8; break; default: break; } - - DIBasicType BTy(Ty); - if (BTy.Verify() && - (BTy.getEncoding() == dwarf::DW_ATE_signed - || BTy.getEncoding() == dwarf::DW_ATE_signed_char)) - addSInt(Block, 0, form, MO.getImm()); - else - addUInt(Block, 0, form, MO.getImm()); + SignedConstant ? addSInt(Block, 0, Form, MO.getImm()) + : addUInt(Block, 0, Form, MO.getImm()); addBlock(Die, dwarf::DW_AT_const_value, 0, Block); return true; @@ -555,7 +567,7 @@ void CompileUnit::addToContextOwner(DIE *Die, DIDescriptor Context) { DIE *ContextDIE = getOrCreateNameSpace(DINameSpace(Context)); ContextDIE->addChild(Die); } else if (Context.isSubprogram()) { - DIE *ContextDIE = DD->createSubprogramDIE(DISubprogram(Context)); + DIE *ContextDIE = getOrCreateSubprogramDIE(DISubprogram(Context)); ContextDIE->addChild(Die); } else if (DIE *ContextDIE = getDIE(Context)) ContextDIE->addChild(Die); @@ -565,7 +577,10 @@ void CompileUnit::addToContextOwner(DIE *Die, DIDescriptor Context) { /// getOrCreateTypeDIE - Find existing DIE or create new DIE for the /// given DIType. -DIE *CompileUnit::getOrCreateTypeDIE(DIType Ty) { +DIE *CompileUnit::getOrCreateTypeDIE(const MDNode *TyNode) { + DIType Ty(TyNode); + if (!Ty.Verify()) + return NULL; DIE *TyDIE = getDIE(Ty); if (TyDIE) return TyDIE; @@ -617,7 +632,8 @@ void CompileUnit::addType(DIE *Entity, DIType Ty) { void CompileUnit::addGlobalType(DIType Ty) { DIDescriptor Context = Ty.getContext(); if (Ty.isCompositeType() && !Ty.getName().empty() && !Ty.isForwardDecl() - && (Context.isCompileUnit() || Context.isFile() || Context.isNameSpace())) + && (!Context || Context.isCompileUnit() || Context.isFile() + || Context.isNameSpace())) if (DIEEntry *Entry = getDIEEntry(Ty)) GlobalTypes[Ty.getName()] = Entry->getEntry(); } @@ -642,13 +658,20 @@ void CompileUnit::addPubTypes(DISubprogram SP) { void CompileUnit::constructTypeDIE(DIE &Buffer, DIBasicType BTy) { // Get core information. StringRef Name = BTy.getName(); - Buffer.setTag(dwarf::DW_TAG_base_type); - addUInt(&Buffer, dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, - BTy.getEncoding()); - // Add name if not anonymous or intermediate type. if (!Name.empty()) addString(&Buffer, dwarf::DW_AT_name, dwarf::DW_FORM_string, Name); + + if (BTy.getTag() == dwarf::DW_TAG_unspecified_type) { + Buffer.setTag(dwarf::DW_TAG_unspecified_type); + // Unspecified types has only name, nothing else. + return; + } + + Buffer.setTag(dwarf::DW_TAG_base_type); + addUInt(&Buffer, dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, + BTy.getEncoding()); + uint64_t Size = BTy.getSizeInBits() >> 3; addUInt(&Buffer, dwarf::DW_AT_byte_size, 0, Size); } @@ -752,7 +775,7 @@ void CompileUnit::constructTypeDIE(DIE &Buffer, DICompositeType CTy) { DIE *ElemDie = NULL; if (Element.isSubprogram()) { DISubprogram SP(Element); - ElemDie = DD->createSubprogramDIE(DISubprogram(Element)); + ElemDie = getOrCreateSubprogramDIE(DISubprogram(Element)); if (SP.isProtected()) addUInt(ElemDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_flag, dwarf::DW_ACCESS_protected); @@ -880,6 +903,218 @@ DIE *CompileUnit::getOrCreateNameSpace(DINameSpace NS) { return NDie; } +/// 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 LinkageName) { + char One = '\1'; + if (LinkageName.startswith(StringRef(&One, 1))) + return LinkageName.substr(1); + return LinkageName; +} + +/// getOrCreateSubprogramDIE - Create new DIE using SP. +DIE *CompileUnit::getOrCreateSubprogramDIE(DISubprogram SP) { + DIE *SPDie = getDIE(SP); + if (SPDie) + return SPDie; + + SPDie = new DIE(dwarf::DW_TAG_subprogram); + + // DW_TAG_inlined_subroutine may refer to this DIE. + insertDIE(SP, SPDie); + + // Add to context owner. + addToContextOwner(SPDie, SP.getContext()); + + // Add function template parameters. + addTemplateParams(*SPDie, SP.getTemplateParams()); + + StringRef LinkageName = SP.getLinkageName(); + if (!LinkageName.empty()) + addString(SPDie, dwarf::DW_AT_MIPS_linkage_name, + dwarf::DW_FORM_string, + getRealLinkageName(LinkageName)); + + // If this DIE is going to refer declaration info using AT_specification + // then there is no need to add other attributes. + if (SP.getFunctionDeclaration().isSubprogram()) + return SPDie; + + // Constructors and operators for anonymous aggregates do not have names. + if (!SP.getName().empty()) + addString(SPDie, dwarf::DW_AT_name, dwarf::DW_FORM_string, + SP.getName()); + + addSourceLine(SPDie, SP); + + if (SP.isPrototyped()) + addUInt(SPDie, dwarf::DW_AT_prototyped, dwarf::DW_FORM_flag, 1); + + // Add Return Type. + DICompositeType SPTy = SP.getType(); + DIArray Args = SPTy.getTypeArray(); + unsigned SPTag = SPTy.getTag(); + + if (Args.getNumElements() == 0 || SPTag != dwarf::DW_TAG_subroutine_type) + addType(SPDie, SPTy); + else + addType(SPDie, DIType(Args.getElement(0))); + + unsigned VK = SP.getVirtuality(); + if (VK) { + addUInt(SPDie, dwarf::DW_AT_virtuality, dwarf::DW_FORM_flag, VK); + DIEBlock *Block = getDIEBlock(); + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_constu); + addUInt(Block, 0, dwarf::DW_FORM_udata, SP.getVirtualIndex()); + addBlock(SPDie, dwarf::DW_AT_vtable_elem_location, 0, Block); + ContainingTypeMap.insert(std::make_pair(SPDie, + SP.getContainingType())); + } + + if (!SP.isDefinition()) { + addUInt(SPDie, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag, 1); + + // Add arguments. Do not add arguments for subprogram definition. They will + // be handled while processing variables. + DICompositeType SPTy = SP.getType(); + DIArray Args = SPTy.getTypeArray(); + unsigned SPTag = SPTy.getTag(); + + if (SPTag == dwarf::DW_TAG_subroutine_type) + for (unsigned i = 1, N = Args.getNumElements(); i < N; ++i) { + DIE *Arg = new DIE(dwarf::DW_TAG_formal_parameter); + DIType ATy = DIType(DIType(Args.getElement(i))); + addType(Arg, ATy); + if (ATy.isArtificial()) + addUInt(Arg, dwarf::DW_AT_artificial, dwarf::DW_FORM_flag, 1); + SPDie->addChild(Arg); + } + } + + if (SP.isArtificial()) + addUInt(SPDie, dwarf::DW_AT_artificial, dwarf::DW_FORM_flag, 1); + + if (!SP.isLocalToUnit()) + addUInt(SPDie, dwarf::DW_AT_external, dwarf::DW_FORM_flag, 1); + + if (SP.isOptimized()) + addUInt(SPDie, dwarf::DW_AT_APPLE_optimized, dwarf::DW_FORM_flag, 1); + + if (unsigned isa = Asm->getISAEncoding()) { + addUInt(SPDie, dwarf::DW_AT_APPLE_isa, dwarf::DW_FORM_flag, isa); + } + + return SPDie; +} + +// Return const expression if value is a GEP to access merged global +// constant. e.g. +// i8* getelementptr ({ i8, i8, i8, i8 }* @_MergedGlobals, i32 0, i32 0) +static const ConstantExpr *getMergedGlobalExpr(const Value *V) { + const ConstantExpr *CE = dyn_cast_or_null(V); + if (!CE || CE->getNumOperands() != 3 || + CE->getOpcode() != Instruction::GetElementPtr) + return NULL; + + // First operand points to a global struct. + Value *Ptr = CE->getOperand(0); + if (!isa(Ptr) || + !isa(cast(Ptr->getType())->getElementType())) + return NULL; + + // Second operand is zero. + const ConstantInt *CI = dyn_cast_or_null(CE->getOperand(1)); + if (!CI || !CI->isZero()) + return NULL; + + // Third operand is offset. + if (!isa(CE->getOperand(2))) + return NULL; + + return CE; +} + +/// createGlobalVariableDIE - create global variable DIE. +void CompileUnit::createGlobalVariableDIE(const MDNode *N) { + // Check for pre-existence. + if (getDIE(N)) + return; + + DIGlobalVariable GV(N); + if (!GV.Verify()) + return; + + DIE *VariableDIE = new DIE(GV.getTag()); + // Add to map. + insertDIE(N, VariableDIE); + + // Add name. + addString(VariableDIE, dwarf::DW_AT_name, dwarf::DW_FORM_string, + GV.getDisplayName()); + StringRef LinkageName = GV.getLinkageName(); + bool isGlobalVariable = GV.getGlobal() != NULL; + if (!LinkageName.empty() && isGlobalVariable) + addString(VariableDIE, dwarf::DW_AT_MIPS_linkage_name, + dwarf::DW_FORM_string, + getRealLinkageName(LinkageName)); + // Add type. + DIType GTy = GV.getType(); + addType(VariableDIE, GTy); + + // Add scoping info. + if (!GV.isLocalToUnit()) { + addUInt(VariableDIE, dwarf::DW_AT_external, dwarf::DW_FORM_flag, 1); + // Expose as global. + addGlobal(GV.getName(), VariableDIE); + } + // Add line number info. + addSourceLine(VariableDIE, GV); + // Add to context owner. + DIDescriptor GVContext = GV.getContext(); + addToContextOwner(VariableDIE, GVContext); + // Add location. + if (isGlobalVariable) { + DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_addr); + addLabel(Block, 0, dwarf::DW_FORM_udata, + Asm->Mang->getSymbol(GV.getGlobal())); + // Do not create specification DIE if context is either compile unit + // or a subprogram. + if (GVContext && GV.isDefinition() && !GVContext.isCompileUnit() && + !GVContext.isFile() && !isSubprogramContext(GVContext)) { + // Create specification DIE. + DIE *VariableSpecDIE = new DIE(dwarf::DW_TAG_variable); + addDIEEntry(VariableSpecDIE, dwarf::DW_AT_specification, + dwarf::DW_FORM_ref4, VariableDIE); + addBlock(VariableSpecDIE, dwarf::DW_AT_location, 0, Block); + addUInt(VariableDIE, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag, + 1); + addDie(VariableSpecDIE); + } else { + addBlock(VariableDIE, dwarf::DW_AT_location, 0, Block); + } + } else if (const ConstantInt *CI = + dyn_cast_or_null(GV.getConstant())) + addConstantValue(VariableDIE, CI, GTy.isUnsignedDIType()); + else if (const ConstantExpr *CE = getMergedGlobalExpr(N->getOperand(11))) { + // GV is a merged global. + DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); + Value *Ptr = CE->getOperand(0); + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_addr); + addLabel(Block, 0, dwarf::DW_FORM_udata, + Asm->Mang->getSymbol(cast(Ptr))); + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_constu); + SmallVector Idx(CE->op_begin()+1, CE->op_end()); + addUInt(Block, 0, dwarf::DW_FORM_udata, + Asm->getTargetData().getIndexedOffset(Ptr->getType(), Idx)); + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_plus); + addBlock(VariableDIE, dwarf::DW_AT_location, 0, Block); + } + + return; +} + /// constructSubrangeDIE - Construct subrange DIE from DISubrange. void CompileUnit::constructSubrangeDIE(DIE &Buffer, DISubrange SR, DIE *IndexTy){ DIE *DW_Subrange = new DIE(dwarf::DW_TAG_subrange_type); @@ -944,6 +1179,128 @@ DIE *CompileUnit::constructEnumTypeDIE(DIEnumerator ETy) { return Enumerator; } +/// constructContainingTypeDIEs - Construct DIEs for types that contain +/// vtables. +void CompileUnit::constructContainingTypeDIEs() { + for (DenseMap::iterator CI = ContainingTypeMap.begin(), + CE = ContainingTypeMap.end(); CI != CE; ++CI) { + DIE *SPDie = CI->first; + const MDNode *N = CI->second; + if (!N) continue; + DIE *NDie = getDIE(N); + if (!NDie) continue; + addDIEEntry(SPDie, dwarf::DW_AT_containing_type, dwarf::DW_FORM_ref4, NDie); + } +} + +/// constructVariableDIE - Construct a DIE for the given DbgVariable. +DIE *CompileUnit::constructVariableDIE(DbgVariable *DV, bool isScopeAbstract) { + StringRef Name = DV->getName(); + if (Name.empty()) + return NULL; + + // Translate tag to proper Dwarf tag. + unsigned Tag = DV->getTag(); + + // Define variable debug information entry. + DIE *VariableDie = new DIE(Tag); + DbgVariable *AbsVar = DV->getAbstractVariable(); + DIE *AbsDIE = AbsVar ? AbsVar->getDIE() : NULL; + if (AbsDIE) + addDIEEntry(VariableDie, dwarf::DW_AT_abstract_origin, + dwarf::DW_FORM_ref4, AbsDIE); + else { + addString(VariableDie, dwarf::DW_AT_name, + dwarf::DW_FORM_string, Name); + addSourceLine(VariableDie, DV->getVariable()); + addType(VariableDie, DV->getType()); + } + + if (DV->isArtificial()) + addUInt(VariableDie, dwarf::DW_AT_artificial, + dwarf::DW_FORM_flag, 1); + + if (isScopeAbstract) { + DV->setDIE(VariableDie); + return VariableDie; + } + + // Add variable address. + + unsigned Offset = DV->getDotDebugLocOffset(); + if (Offset != ~0U) { + addLabel(VariableDie, dwarf::DW_AT_location, + dwarf::DW_FORM_data4, + Asm->GetTempSymbol("debug_loc", Offset)); + DV->setDIE(VariableDie); + return VariableDie; + } + + // Check if variable is described by a DBG_VALUE instruction. + if (const MachineInstr *DVInsn = DV->getMInsn()) { + bool updated = false; + if (DVInsn->getNumOperands() == 3) { + if (DVInsn->getOperand(0).isReg()) { + const MachineOperand RegOp = DVInsn->getOperand(0); + const TargetRegisterInfo *TRI = Asm->TM.getRegisterInfo(); + if (DVInsn->getOperand(1).isImm() && + TRI->getFrameRegister(*Asm->MF) == RegOp.getReg()) { + unsigned FrameReg = 0; + const TargetFrameLowering *TFI = Asm->TM.getFrameLowering(); + int Offset = + TFI->getFrameIndexReference(*Asm->MF, + DVInsn->getOperand(1).getImm(), + FrameReg); + MachineLocation Location(FrameReg, Offset); + addVariableAddress(DV, VariableDie, Location); + + } else if (RegOp.getReg()) + addVariableAddress(DV, VariableDie, + MachineLocation(RegOp.getReg())); + updated = true; + } + else if (DVInsn->getOperand(0).isImm()) + updated = + addConstantValue(VariableDie, DVInsn->getOperand(0), + DV->getType()); + else if (DVInsn->getOperand(0).isFPImm()) + updated = + addConstantFPValue(VariableDie, DVInsn->getOperand(0)); + else if (DVInsn->getOperand(0).isCImm()) + updated = + addConstantValue(VariableDie, + DVInsn->getOperand(0).getCImm(), + DV->getType().isUnsignedDIType()); + } else { + addVariableAddress(DV, VariableDie, + Asm->getDebugValueLocation(DVInsn)); + updated = true; + } + if (!updated) { + // If variableDie is not updated then DBG_VALUE instruction does not + // have valid variable info. + delete VariableDie; + return NULL; + } + DV->setDIE(VariableDie); + return VariableDie; + } else { + // .. else use frame index. + int FI = DV->getFrameIndex(); + if (FI != ~0) { + unsigned FrameReg = 0; + const TargetFrameLowering *TFI = Asm->TM.getFrameLowering(); + int Offset = + TFI->getFrameIndexReference(*Asm->MF, FI, FrameReg); + MachineLocation Location(FrameReg, Offset); + addVariableAddress(DV, VariableDie, Location); + } + } + + DV->setDIE(VariableDie); + return VariableDie; +} + /// createMemberDIE - Create new member DIE. DIE *CompileUnit::createMemberDIE(DIDerivedType DT) { DIE *MemberDie = new DIE(DT.getTag()); @@ -1013,7 +1370,7 @@ DIE *CompileUnit::createMemberDIE(DIDerivedType DT) { addUInt(MemberDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_flag, dwarf::DW_ACCESS_private); // Otherwise C++ member and base classes are considered public. - else if (DT.getCompileUnit().getLanguage() == dwarf::DW_LANG_C_plus_plus) + else addUInt(MemberDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_flag, dwarf::DW_ACCESS_public); if (DT.isVirtual()) diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h index 213c7fc63..785926579 100644 --- a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h +++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h @@ -67,6 +67,11 @@ class CompileUnit { /// DIEBlocks - A list of all the DIEBlocks in use. std::vector DIEBlocks; + /// ContainingTypeMap - This map is used to keep track of subprogram DIEs that + /// need DW_AT_containing_type attribute. This attribute points to a DIE that + /// corresponds to the MDNode mapped with the subprogram DIE. + DenseMap ContainingTypeMap; + public: CompileUnit(unsigned I, DIE *D, AsmPrinter *A, DwarfDebug *DW); ~CompileUnit(); @@ -226,9 +231,12 @@ public: /// getOrCreateNameSpace - Create a DIE for DINameSpace. DIE *getOrCreateNameSpace(DINameSpace NS); + /// getOrCreateSubprogramDIE - Create new DIE using SP. + DIE *getOrCreateSubprogramDIE(DISubprogram SP); + /// getOrCreateTypeDIE - Find existing DIE or create new DIE for the /// given DIType. - DIE *getOrCreateTypeDIE(DIType Ty); + DIE *getOrCreateTypeDIE(const MDNode *N); /// getOrCreateTemplateTypeParameterDIE - Find existing DIE or create new DIE /// for the given DITemplateTypeParameter. @@ -242,6 +250,9 @@ public: /// information entry. DIEEntry *createDIEEntry(DIE *Entry); + /// createGlobalVariableDIE - create global variable DIE. + void createGlobalVariableDIE(const MDNode *N); + void addPubTypes(DISubprogram SP); /// constructTypeDIE - Construct basic type die from DIBasicType. @@ -266,6 +277,13 @@ public: /// constructEnumTypeDIE - Construct enum type DIE from DIEnumerator. DIE *constructEnumTypeDIE(DIEnumerator ETy); + /// constructContainingTypeDIEs - Construct DIEs for types that contain + /// vtables. + void constructContainingTypeDIEs(); + + /// constructVariableDIE - Construct a DIE for the given DbgVariable. + DIE *constructVariableDIE(DbgVariable *DV, bool isScopeAbstract); + /// createMemberDIE - Create new member DIE. DIE *createMemberDIE(DIDerivedType DT); diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index 125e1e86b..1b7e370fc 100644 --- a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -24,7 +24,6 @@ #include "llvm/MC/MCSection.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" -#include "llvm/Target/Mangler.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetFrameLowering.h" #include "llvm/Target/TargetLoweringObjectFile.h" @@ -45,9 +44,6 @@ #include "llvm/Support/Path.h" using namespace llvm; -static cl::opt PrintDbgScope("print-dbgscope", cl::Hidden, - cl::desc("Print DbgScope information for each machine instruction")); - static cl::opt DisableDebugInfoPrinting("disable-debug-info-print", cl::Hidden, cl::desc("Disable debug info printing")); @@ -69,7 +65,7 @@ static const unsigned InitAbbreviationsSetSize = 9; // log2(512) namespace llvm { -DIType DbgVariable::getType() const { +DIType DbgVariable::getType() const { DIType Ty = Var.getType(); // FIXME: isBlockByrefVariable should be reformulated in terms of complex // addresses instead. @@ -120,141 +116,12 @@ DIType DbgVariable::getType() const { return Ty; } -//===----------------------------------------------------------------------===// -/// DbgRange - This is used to track range of instructions with identical -/// debug info scope. -/// -typedef std::pair DbgRange; - -//===----------------------------------------------------------------------===// -/// DbgScope - This class is used to track scope information. -/// -class DbgScope { - DbgScope *Parent; // Parent to this scope. - DIDescriptor Desc; // Debug info descriptor for scope. - // Location at which this scope is inlined. - AssertingVH InlinedAtLocation; - bool AbstractScope; // Abstract Scope - const MachineInstr *LastInsn; // Last instruction of this scope. - const MachineInstr *FirstInsn; // First instruction of this scope. - unsigned DFSIn, DFSOut; - // Scopes defined in scope. Contents not owned. - SmallVector Scopes; - // Variables declared in scope. Contents owned. - SmallVector Variables; - SmallVector Ranges; - // Private state for dump() - mutable unsigned IndentLevel; -public: - DbgScope(DbgScope *P, DIDescriptor D, const MDNode *I = 0) - : Parent(P), Desc(D), InlinedAtLocation(I), AbstractScope(false), - LastInsn(0), FirstInsn(0), - DFSIn(0), DFSOut(0), IndentLevel(0) {} - virtual ~DbgScope(); - - // Accessors. - DbgScope *getParent() const { return Parent; } - void setParent(DbgScope *P) { Parent = P; } - DIDescriptor getDesc() const { return Desc; } - const MDNode *getInlinedAt() const { return InlinedAtLocation; } - const MDNode *getScopeNode() const { return Desc; } - const SmallVector &getScopes() { return Scopes; } - const SmallVector &getDbgVariables() { return Variables; } - const SmallVector &getRanges() { return Ranges; } - - /// openInsnRange - This scope covers instruction range starting from MI. - void openInsnRange(const MachineInstr *MI) { - if (!FirstInsn) - FirstInsn = MI; - - if (Parent) - Parent->openInsnRange(MI); - } - - /// extendInsnRange - Extend the current instruction range covered by - /// this scope. - void extendInsnRange(const MachineInstr *MI) { - assert (FirstInsn && "MI Range is not open!"); - LastInsn = MI; - if (Parent) - Parent->extendInsnRange(MI); - } - - /// closeInsnRange - Create a range based on FirstInsn and LastInsn collected - /// until now. This is used when a new scope is encountered while walking - /// machine instructions. - void closeInsnRange(DbgScope *NewScope = NULL) { - assert (LastInsn && "Last insn missing!"); - Ranges.push_back(DbgRange(FirstInsn, LastInsn)); - FirstInsn = NULL; - LastInsn = NULL; - // If Parent dominates NewScope then do not close Parent's instruction - // range. - if (Parent && (!NewScope || !Parent->dominates(NewScope))) - Parent->closeInsnRange(NewScope); - } - - void setAbstractScope() { AbstractScope = true; } - bool isAbstractScope() const { return AbstractScope; } - - // Depth First Search support to walk and mainpluate DbgScope hierarchy. - unsigned getDFSOut() const { return DFSOut; } - void setDFSOut(unsigned O) { DFSOut = O; } - unsigned getDFSIn() const { return DFSIn; } - void setDFSIn(unsigned I) { DFSIn = I; } - bool dominates(const DbgScope *S) { - if (S == this) - return true; - if (DFSIn < S->getDFSIn() && DFSOut > S->getDFSOut()) - return true; - return false; - } - - /// addScope - Add a scope to the scope. - /// - void addScope(DbgScope *S) { Scopes.push_back(S); } - - /// addVariable - Add a variable to the scope. - /// - void addVariable(DbgVariable *V) { Variables.push_back(V); } - -#ifndef NDEBUG - void dump() const; -#endif -}; - } // end llvm namespace -#ifndef NDEBUG -void DbgScope::dump() const { - raw_ostream &err = dbgs(); - err.indent(IndentLevel); - err << "DFSIn: " << DFSIn << " DFSOut: " << DFSOut << "\n"; - const MDNode *N = Desc; - N->dump(); - if (AbstractScope) - err << "Abstract Scope\n"; - - IndentLevel += 2; - if (!Scopes.empty()) - err << "Children ...\n"; - for (unsigned i = 0, e = Scopes.size(); i != e; ++i) - if (Scopes[i] != this) - Scopes[i]->dump(); - - IndentLevel -= 2; -} -#endif - -DbgScope::~DbgScope() { - for (unsigned j = 0, M = Variables.size(); j < M; ++j) - delete Variables[j]; -} - DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M) : Asm(A), MMI(Asm->MMI), FirstCU(0), AbbreviationsSet(InitAbbreviationsSetSize), - CurrentFnDbgScope(0), PrevLabel(NULL) { + PrevLabel(NULL) { NextStringPoolNumber = 0; DwarfInfoSectionSym = DwarfAbbrevSectionSym = 0; @@ -311,147 +178,12 @@ static StringRef getRealLinkageName(StringRef LinkageName) { return LinkageName; } -/// createSubprogramDIE - Create new DIE using SP. -DIE *DwarfDebug::createSubprogramDIE(DISubprogram SP) { - CompileUnit *SPCU = getCompileUnit(SP); - DIE *SPDie = SPCU->getDIE(SP); - if (SPDie) - return SPDie; - - SPDie = new DIE(dwarf::DW_TAG_subprogram); - - // DW_TAG_inlined_subroutine may refer to this DIE. - SPCU->insertDIE(SP, SPDie); - - // Add to context owner. - SPCU->addToContextOwner(SPDie, SP.getContext()); - - // Add function template parameters. - SPCU->addTemplateParams(*SPDie, SP.getTemplateParams()); - - StringRef LinkageName = SP.getLinkageName(); - if (!LinkageName.empty()) - SPCU->addString(SPDie, dwarf::DW_AT_MIPS_linkage_name, dwarf::DW_FORM_string, - getRealLinkageName(LinkageName)); - - // If this DIE is going to refer declaration info using AT_specification - // then there is no need to add other attributes. - if (SP.getFunctionDeclaration().isSubprogram()) - return SPDie; - - // Constructors and operators for anonymous aggregates do not have names. - if (!SP.getName().empty()) - SPCU->addString(SPDie, dwarf::DW_AT_name, dwarf::DW_FORM_string, - SP.getName()); - - SPCU->addSourceLine(SPDie, SP); - - if (SP.isPrototyped()) - SPCU->addUInt(SPDie, dwarf::DW_AT_prototyped, dwarf::DW_FORM_flag, 1); - - // Add Return Type. - DICompositeType SPTy = SP.getType(); - DIArray Args = SPTy.getTypeArray(); - unsigned SPTag = SPTy.getTag(); - - if (Args.getNumElements() == 0 || SPTag != dwarf::DW_TAG_subroutine_type) - SPCU->addType(SPDie, SPTy); - else - SPCU->addType(SPDie, DIType(Args.getElement(0))); - - unsigned VK = SP.getVirtuality(); - if (VK) { - SPCU->addUInt(SPDie, dwarf::DW_AT_virtuality, dwarf::DW_FORM_flag, VK); - DIEBlock *Block = SPCU->getDIEBlock(); - SPCU->addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_constu); - SPCU->addUInt(Block, 0, dwarf::DW_FORM_udata, SP.getVirtualIndex()); - SPCU->addBlock(SPDie, dwarf::DW_AT_vtable_elem_location, 0, Block); - ContainingTypeMap.insert(std::make_pair(SPDie, - SP.getContainingType())); - } - - if (!SP.isDefinition()) { - SPCU->addUInt(SPDie, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag, 1); - - // Add arguments. Do not add arguments for subprogram definition. They will - // be handled while processing variables. - DICompositeType SPTy = SP.getType(); - DIArray Args = SPTy.getTypeArray(); - unsigned SPTag = SPTy.getTag(); - - if (SPTag == dwarf::DW_TAG_subroutine_type) - for (unsigned i = 1, N = Args.getNumElements(); i < N; ++i) { - DIE *Arg = new DIE(dwarf::DW_TAG_formal_parameter); - DIType ATy = DIType(DIType(Args.getElement(i))); - SPCU->addType(Arg, ATy); - if (ATy.isArtificial()) - SPCU->addUInt(Arg, dwarf::DW_AT_artificial, dwarf::DW_FORM_flag, 1); - SPDie->addChild(Arg); - } - } - - if (SP.isArtificial()) - SPCU->addUInt(SPDie, dwarf::DW_AT_artificial, dwarf::DW_FORM_flag, 1); - - if (!SP.isLocalToUnit()) - SPCU->addUInt(SPDie, dwarf::DW_AT_external, dwarf::DW_FORM_flag, 1); - - if (SP.isOptimized()) - SPCU->addUInt(SPDie, dwarf::DW_AT_APPLE_optimized, dwarf::DW_FORM_flag, 1); - - if (unsigned isa = Asm->getISAEncoding()) { - SPCU->addUInt(SPDie, dwarf::DW_AT_APPLE_isa, dwarf::DW_FORM_flag, isa); - } - - return SPDie; -} - -DbgScope *DwarfDebug::getOrCreateAbstractScope(const MDNode *N) { - assert(N && "Invalid Scope encoding!"); - - DbgScope *AScope = AbstractScopes.lookup(N); - if (AScope) - return AScope; - - DbgScope *Parent = NULL; - - DIDescriptor Scope(N); - if (Scope.isLexicalBlock()) { - DILexicalBlock DB(N); - DIDescriptor ParentDesc = DB.getContext(); - Parent = getOrCreateAbstractScope(ParentDesc); - } - - AScope = new DbgScope(Parent, DIDescriptor(N), NULL); - - if (Parent) - Parent->addScope(AScope); - AScope->setAbstractScope(); - AbstractScopes[N] = AScope; - if (DIDescriptor(N).isSubprogram()) - AbstractScopesList.push_back(AScope); - return AScope; -} - -/// isSubprogramContext - Return true if Context is either a subprogram -/// or another context nested inside a subprogram. -static bool isSubprogramContext(const MDNode *Context) { - if (!Context) - return false; - DIDescriptor D(Context); - if (D.isSubprogram()) - return true; - if (D.isType()) - return isSubprogramContext(DIType(Context).getContext()); - return false; -} - /// updateSubprogramScopeDIE - Find DIE for the given subprogram and /// attach appropriate DW_AT_low_pc and DW_AT_high_pc attributes. /// If there are global variables in this scope then create and insert /// DIEs for these variables. -DIE *DwarfDebug::updateSubprogramScopeDIE(const MDNode *SPNode) { - CompileUnit *SPCU = getCompileUnit(SPNode); +DIE *DwarfDebug::updateSubprogramScopeDIE(CompileUnit *SPCU, + const MDNode *SPNode) { DIE *SPDie = SPCU->getDIE(SPNode); assert(SPDie && "Unable to find subprogram DIE!"); @@ -461,7 +193,7 @@ DIE *DwarfDebug::updateSubprogramScopeDIE(const MDNode *SPNode) { if (SPDecl.isSubprogram()) // Refer function declaration directly. SPCU->addDIEEntry(SPDie, dwarf::DW_AT_specification, dwarf::DW_FORM_ref4, - createSubprogramDIE(SPDecl)); + SPCU->getOrCreateSubprogramDIE(SPDecl)); else { // There is not any need to generate specification DIE for a function // defined at compile unit level. If a function is defined inside another @@ -514,25 +246,26 @@ DIE *DwarfDebug::updateSubprogramScopeDIE(const MDNode *SPNode) { /// constructLexicalScope - Construct new DW_TAG_lexical_block /// for this scope and attach DW_AT_low_pc/DW_AT_high_pc labels. -DIE *DwarfDebug::constructLexicalScopeDIE(DbgScope *Scope) { +DIE *DwarfDebug::constructLexicalScopeDIE(CompileUnit *TheCU, + LexicalScope *Scope) { DIE *ScopeDIE = new DIE(dwarf::DW_TAG_lexical_block); if (Scope->isAbstractScope()) return ScopeDIE; - const SmallVector &Ranges = Scope->getRanges(); + const SmallVector &Ranges = Scope->getRanges(); if (Ranges.empty()) return 0; - CompileUnit *TheCU = getCompileUnit(Scope->getScopeNode()); - SmallVector::const_iterator RI = Ranges.begin(); + SmallVector::const_iterator RI = Ranges.begin(); if (Ranges.size() > 1) { // .debug_range section has not been laid out yet. Emit offset in // .debug_range as a uint, size 4, for now. emitDIE will handle // DW_AT_ranges appropriately. TheCU->addUInt(ScopeDIE, dwarf::DW_AT_ranges, dwarf::DW_FORM_data4, - DebugRangeSymbols.size() * Asm->getTargetData().getPointerSize()); - for (SmallVector::const_iterator RI = Ranges.begin(), + DebugRangeSymbols.size() + * Asm->getTargetData().getPointerSize()); + for (SmallVector::const_iterator RI = Ranges.begin(), RE = Ranges.end(); RI != RE; ++RI) { DebugRangeSymbols.push_back(getLabelBeforeInsn(RI->first)); DebugRangeSymbols.push_back(getLabelAfterInsn(RI->second)); @@ -559,22 +292,29 @@ DIE *DwarfDebug::constructLexicalScopeDIE(DbgScope *Scope) { /// constructInlinedScopeDIE - This scope represents inlined body of /// a function. Construct DIE to represent this concrete inlined copy /// of the function. -DIE *DwarfDebug::constructInlinedScopeDIE(DbgScope *Scope) { +DIE *DwarfDebug::constructInlinedScopeDIE(CompileUnit *TheCU, + LexicalScope *Scope) { - const SmallVector &Ranges = Scope->getRanges(); + const SmallVector &Ranges = Scope->getRanges(); assert (Ranges.empty() == false - && "DbgScope does not have instruction markers!"); + && "LexicalScope does not have instruction markers!"); - // FIXME : .debug_inlined section specification does not clearly state how - // to emit inlined scope that is split into multiple instruction ranges. - // For now, use first instruction range and emit low_pc/high_pc pair and - // corresponding .debug_inlined section entry for this pair. - SmallVector::const_iterator RI = Ranges.begin(); + if (!Scope->getScopeNode()) + return NULL; + DIScope DS(Scope->getScopeNode()); + DISubprogram InlinedSP = getDISubprogram(DS); + DIE *OriginDIE = TheCU->getDIE(InlinedSP); + if (!OriginDIE) { + DEBUG(dbgs() << "Unable to find original DIE for inlined subprogram."); + return NULL; + } + + SmallVector::const_iterator RI = Ranges.begin(); const MCSymbol *StartLabel = getLabelBeforeInsn(RI->first); const MCSymbol *EndLabel = getLabelAfterInsn(RI->second); if (StartLabel == 0 || EndLabel == 0) { - assert (0 && "Unexpected Start and End labels for a inlined scope!"); + assert (0 && "Unexpected Start and End labels for a inlined scope!"); return 0; } assert(StartLabel->isDefined() && @@ -582,26 +322,38 @@ DIE *DwarfDebug::constructInlinedScopeDIE(DbgScope *Scope) { assert(EndLabel->isDefined() && "Invalid end label for an inlined scope!"); - if (!Scope->getScopeNode()) - return NULL; - DIScope DS(Scope->getScopeNode()); - DISubprogram InlinedSP = getDISubprogram(DS); - CompileUnit *TheCU = getCompileUnit(InlinedSP); - DIE *OriginDIE = TheCU->getDIE(InlinedSP); - if (!OriginDIE) { - DEBUG(dbgs() << "Unable to find original DIE for inlined subprogram."); - return NULL; - } DIE *ScopeDIE = new DIE(dwarf::DW_TAG_inlined_subroutine); TheCU->addDIEEntry(ScopeDIE, dwarf::DW_AT_abstract_origin, dwarf::DW_FORM_ref4, OriginDIE); - TheCU->addLabel(ScopeDIE, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, StartLabel); - TheCU->addLabel(ScopeDIE, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr, EndLabel); + if (Ranges.size() > 1) { + // .debug_range section has not been laid out yet. Emit offset in + // .debug_range as a uint, size 4, for now. emitDIE will handle + // DW_AT_ranges appropriately. + TheCU->addUInt(ScopeDIE, dwarf::DW_AT_ranges, dwarf::DW_FORM_data4, + DebugRangeSymbols.size() + * Asm->getTargetData().getPointerSize()); + for (SmallVector::const_iterator RI = Ranges.begin(), + RE = Ranges.end(); RI != RE; ++RI) { + DebugRangeSymbols.push_back(getLabelBeforeInsn(RI->first)); + DebugRangeSymbols.push_back(getLabelAfterInsn(RI->second)); + } + DebugRangeSymbols.push_back(NULL); + DebugRangeSymbols.push_back(NULL); + } else { + TheCU->addLabel(ScopeDIE, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, + StartLabel); + TheCU->addLabel(ScopeDIE, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr, + EndLabel); + } InlinedSubprogramDIEs.insert(OriginDIE); // Track the start label for this inlined function. + //.debug_inlined section specification does not clearly state how + // to emit inlined scope that is split into multiple instruction ranges. + // For now, use first instruction range and emit low_pc/high_pc pair and + // corresponding .debug_inlined section entry for this pair. DenseMap >::iterator I = InlineInfo.find(InlinedSP); @@ -619,200 +371,51 @@ DIE *DwarfDebug::constructInlinedScopeDIE(DbgScope *Scope) { return ScopeDIE; } -/// isUnsignedDIType - Return true if type encoding is unsigned. -static bool isUnsignedDIType(DIType Ty) { - DIDerivedType DTy(Ty); - if (DTy.Verify()) - return isUnsignedDIType(DTy.getTypeDerivedFrom()); - - DIBasicType BTy(Ty); - if (BTy.Verify()) { - unsigned Encoding = BTy.getEncoding(); - if (Encoding == dwarf::DW_ATE_unsigned || - Encoding == dwarf::DW_ATE_unsigned_char) - return true; - } - return false; -} - -/// constructVariableDIE - Construct a DIE for the given DbgVariable. -DIE *DwarfDebug::constructVariableDIE(DbgVariable *DV, DbgScope *Scope) { - StringRef Name = DV->getName(); - if (Name.empty()) - return NULL; - - // Translate tag to proper Dwarf tag. The result variable is dropped for - // now. - unsigned Tag; - switch (DV->getTag()) { - case dwarf::DW_TAG_return_variable: - return NULL; - case dwarf::DW_TAG_arg_variable: - Tag = dwarf::DW_TAG_formal_parameter; - break; - case dwarf::DW_TAG_auto_variable: // fall thru - default: - Tag = dwarf::DW_TAG_variable; - break; - } - - // Define variable debug information entry. - DIE *VariableDie = new DIE(Tag); - CompileUnit *VariableCU = getCompileUnit(DV->getVariable()); - DIE *AbsDIE = NULL; - DenseMap::iterator - V2AVI = VarToAbstractVarMap.find(DV); - if (V2AVI != VarToAbstractVarMap.end()) - AbsDIE = V2AVI->second->getDIE(); - - if (AbsDIE) - VariableCU->addDIEEntry(VariableDie, dwarf::DW_AT_abstract_origin, - dwarf::DW_FORM_ref4, AbsDIE); - else { - VariableCU->addString(VariableDie, dwarf::DW_AT_name, dwarf::DW_FORM_string, - Name); - VariableCU->addSourceLine(VariableDie, DV->getVariable()); - - // Add variable type. - VariableCU->addType(VariableDie, DV->getType()); - } - - if (Tag == dwarf::DW_TAG_formal_parameter && DV->getType().isArtificial()) - VariableCU->addUInt(VariableDie, dwarf::DW_AT_artificial, - dwarf::DW_FORM_flag, 1); - else if (DIVariable(DV->getVariable()).isArtificial()) - VariableCU->addUInt(VariableDie, dwarf::DW_AT_artificial, - dwarf::DW_FORM_flag, 1); - - if (Scope->isAbstractScope()) { - DV->setDIE(VariableDie); - return VariableDie; - } - - // Add variable address. - - unsigned Offset = DV->getDotDebugLocOffset(); - if (Offset != ~0U) { - VariableCU->addLabel(VariableDie, dwarf::DW_AT_location, dwarf::DW_FORM_data4, - Asm->GetTempSymbol("debug_loc", Offset)); - DV->setDIE(VariableDie); - UseDotDebugLocEntry.insert(VariableDie); - return VariableDie; - } - - // Check if variable is described by a DBG_VALUE instruction. - DenseMap::iterator DVI = - DbgVariableToDbgInstMap.find(DV); - if (DVI != DbgVariableToDbgInstMap.end()) { - const MachineInstr *DVInsn = DVI->second; - bool updated = false; - // FIXME : Handle getNumOperands != 3 - if (DVInsn->getNumOperands() == 3) { - if (DVInsn->getOperand(0).isReg()) { - const MachineOperand RegOp = DVInsn->getOperand(0); - const TargetRegisterInfo *TRI = Asm->TM.getRegisterInfo(); - if (DVInsn->getOperand(1).isImm() && - TRI->getFrameRegister(*Asm->MF) == RegOp.getReg()) { - unsigned FrameReg = 0; - const TargetFrameLowering *TFI = Asm->TM.getFrameLowering(); - int Offset = - TFI->getFrameIndexReference(*Asm->MF, - DVInsn->getOperand(1).getImm(), - FrameReg); - MachineLocation Location(FrameReg, Offset); - VariableCU->addVariableAddress(DV, VariableDie, Location); - - } else if (RegOp.getReg()) - VariableCU->addVariableAddress(DV, VariableDie, - MachineLocation(RegOp.getReg())); - updated = true; - } - else if (DVInsn->getOperand(0).isImm()) - updated = - VariableCU->addConstantValue(VariableDie, DVInsn->getOperand(0), - DV->getType()); - else if (DVInsn->getOperand(0).isFPImm()) - updated = - VariableCU->addConstantFPValue(VariableDie, DVInsn->getOperand(0)); - else if (DVInsn->getOperand(0).isCImm()) - updated = - VariableCU->addConstantValue(VariableDie, - DVInsn->getOperand(0).getCImm(), - isUnsignedDIType(DV->getType())); - } else { - VariableCU->addVariableAddress(DV, VariableDie, - Asm->getDebugValueLocation(DVInsn)); - updated = true; - } - if (!updated) { - // If variableDie is not updated then DBG_VALUE instruction does not - // have valid variable info. - delete VariableDie; - return NULL; - } - DV->setDIE(VariableDie); - return VariableDie; - } - - // .. else use frame index, if available. - int FI = 0; - if (findVariableFrameIndex(DV, &FI)) { - unsigned FrameReg = 0; - const TargetFrameLowering *TFI = Asm->TM.getFrameLowering(); - int Offset = - TFI->getFrameIndexReference(*Asm->MF, FI, FrameReg); - MachineLocation Location(FrameReg, Offset); - VariableCU->addVariableAddress(DV, VariableDie, Location); - } - - DV->setDIE(VariableDie); - return VariableDie; - -} - /// constructScopeDIE - Construct a DIE for this scope. -DIE *DwarfDebug::constructScopeDIE(DbgScope *Scope) { +DIE *DwarfDebug::constructScopeDIE(CompileUnit *TheCU, LexicalScope *Scope) { if (!Scope || !Scope->getScopeNode()) return NULL; SmallVector Children; // Collect arguments for current function. - if (Scope == CurrentFnDbgScope) + if (LScopes.isCurrentFunctionScope(Scope)) for (unsigned i = 0, N = CurrentFnArguments.size(); i < N; ++i) if (DbgVariable *ArgDV = CurrentFnArguments[i]) - if (DIE *Arg = constructVariableDIE(ArgDV, Scope)) + if (DIE *Arg = + TheCU->constructVariableDIE(ArgDV, Scope->isAbstractScope())) Children.push_back(Arg); - // Collect lexical scope childrens first. - const SmallVector &Variables = Scope->getDbgVariables(); + // Collect lexical scope children first. + const SmallVector &Variables = ScopeVariables.lookup(Scope); for (unsigned i = 0, N = Variables.size(); i < N; ++i) - if (DIE *Variable = constructVariableDIE(Variables[i], Scope)) + if (DIE *Variable = + TheCU->constructVariableDIE(Variables[i], Scope->isAbstractScope())) Children.push_back(Variable); - const SmallVector &Scopes = Scope->getScopes(); + const SmallVector &Scopes = Scope->getChildren(); for (unsigned j = 0, M = Scopes.size(); j < M; ++j) - if (DIE *Nested = constructScopeDIE(Scopes[j])) + if (DIE *Nested = constructScopeDIE(TheCU, Scopes[j])) Children.push_back(Nested); DIScope DS(Scope->getScopeNode()); DIE *ScopeDIE = NULL; if (Scope->getInlinedAt()) - ScopeDIE = constructInlinedScopeDIE(Scope); + ScopeDIE = constructInlinedScopeDIE(TheCU, Scope); else if (DS.isSubprogram()) { ProcessedSPNodes.insert(DS); if (Scope->isAbstractScope()) { - ScopeDIE = getCompileUnit(DS)->getDIE(DS); + ScopeDIE = TheCU->getDIE(DS); // Note down abstract DIE. if (ScopeDIE) AbstractSPDies.insert(std::make_pair(DS, ScopeDIE)); } else - ScopeDIE = updateSubprogramScopeDIE(DS); + ScopeDIE = updateSubprogramScopeDIE(TheCU, DS); } else { // There is no need to emit empty lexical block DIE. if (Children.empty()) return NULL; - ScopeDIE = constructLexicalScopeDIE(Scope); + ScopeDIE = constructLexicalScopeDIE(TheCU, Scope); } if (!ScopeDIE) return NULL; @@ -823,7 +426,7 @@ DIE *DwarfDebug::constructScopeDIE(DbgScope *Scope) { ScopeDIE->addChild(*I); if (DS.isSubprogram()) - getCompileUnit(DS)->addPubTypes(DISubprogram(DS)); + TheCU->addPubTypes(DISubprogram(DS)); return ScopeDIE; } @@ -862,7 +465,7 @@ unsigned DwarfDebug::GetOrCreateSourceID(StringRef FileName, /// constructCompileUnit - Create new CompileUnit for the given /// metadata node with tag DW_TAG_compile_unit. -void DwarfDebug::constructCompileUnit(const MDNode *N) { +CompileUnit *DwarfDebug::constructCompileUnit(const MDNode *N) { DICompileUnit DIUnit(N); StringRef FN = DIUnit.getFilename(); StringRef Dir = DIUnit.getDirectory(); @@ -893,7 +496,8 @@ void DwarfDebug::constructCompileUnit(const MDNode *N) { StringRef Flags = DIUnit.getFlags(); if (!Flags.empty()) - NewCU->addString(Die, dwarf::DW_AT_APPLE_flags, dwarf::DW_FORM_string, Flags); + NewCU->addString(Die, dwarf::DW_AT_APPLE_flags, dwarf::DW_FORM_string, + Flags); unsigned RVer = DIUnit.getRunTimeVersion(); if (RVer) @@ -903,159 +507,19 @@ void DwarfDebug::constructCompileUnit(const MDNode *N) { if (!FirstCU) FirstCU = NewCU; CUMap.insert(std::make_pair(N, NewCU)); -} - -/// getCompielUnit - Get CompileUnit DIE. -CompileUnit *DwarfDebug::getCompileUnit(const MDNode *N) const { - assert (N && "Invalid DwarfDebug::getCompileUnit argument!"); - DIDescriptor D(N); - const MDNode *CUNode = NULL; - if (D.isCompileUnit()) - CUNode = N; - else if (D.isSubprogram()) - CUNode = DISubprogram(N).getCompileUnit(); - else if (D.isType()) - CUNode = DIType(N).getCompileUnit(); - else if (D.isGlobalVariable()) - CUNode = DIGlobalVariable(N).getCompileUnit(); - else if (D.isVariable()) - CUNode = DIVariable(N).getCompileUnit(); - else if (D.isNameSpace()) - CUNode = DINameSpace(N).getCompileUnit(); - else if (D.isFile()) - CUNode = DIFile(N).getCompileUnit(); - else - return FirstCU; - - DenseMap::const_iterator I - = CUMap.find(CUNode); - if (I == CUMap.end()) - return FirstCU; - return I->second; -} - -// Return const exprssion if value is a GEP to access merged global -// constant. e.g. -// i8* getelementptr ({ i8, i8, i8, i8 }* @_MergedGlobals, i32 0, i32 0) -static const ConstantExpr *getMergedGlobalExpr(const Value *V) { - const ConstantExpr *CE = dyn_cast_or_null(V); - if (!CE || CE->getNumOperands() != 3 || - CE->getOpcode() != Instruction::GetElementPtr) - return NULL; - - // First operand points to a global value. - if (!isa(CE->getOperand(0))) - return NULL; - - // Second operand is zero. - const ConstantInt *CI = - dyn_cast_or_null(CE->getOperand(1)); - if (!CI || !CI->isZero()) - return NULL; - - // Third operand is offset. - if (!isa(CE->getOperand(2))) - return NULL; - - return CE; -} - -/// constructGlobalVariableDIE - Construct global variable DIE. -void DwarfDebug::constructGlobalVariableDIE(const MDNode *N) { - DIGlobalVariable GV(N); - - // If debug information is malformed then ignore it. - if (GV.Verify() == false) - return; - - // Check for pre-existence. - CompileUnit *TheCU = getCompileUnit(N); - if (TheCU->getDIE(GV)) - return; - - DIType GTy = GV.getType(); - DIE *VariableDIE = new DIE(GV.getTag()); - - bool isGlobalVariable = GV.getGlobal() != NULL; - - // Add name. - TheCU->addString(VariableDIE, dwarf::DW_AT_name, dwarf::DW_FORM_string, - GV.getDisplayName()); - StringRef LinkageName = GV.getLinkageName(); - if (!LinkageName.empty() && isGlobalVariable) - TheCU->addString(VariableDIE, dwarf::DW_AT_MIPS_linkage_name, - dwarf::DW_FORM_string, - getRealLinkageName(LinkageName)); - // Add type. - TheCU->addType(VariableDIE, GTy); - - // Add scoping info. - if (!GV.isLocalToUnit()) { - TheCU->addUInt(VariableDIE, dwarf::DW_AT_external, dwarf::DW_FORM_flag, 1); - // Expose as global. - TheCU->addGlobal(GV.getName(), VariableDIE); - } - // Add line number info. - TheCU->addSourceLine(VariableDIE, GV); - // Add to map. - TheCU->insertDIE(N, VariableDIE); - // Add to context owner. - DIDescriptor GVContext = GV.getContext(); - TheCU->addToContextOwner(VariableDIE, GVContext); - // Add location. - if (isGlobalVariable) { - DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); - TheCU->addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_addr); - TheCU->addLabel(Block, 0, dwarf::DW_FORM_udata, - Asm->Mang->getSymbol(GV.getGlobal())); - // Do not create specification DIE if context is either compile unit - // or a subprogram. - if (GV.isDefinition() && !GVContext.isCompileUnit() && - !GVContext.isFile() && !isSubprogramContext(GVContext)) { - // Create specification DIE. - DIE *VariableSpecDIE = new DIE(dwarf::DW_TAG_variable); - TheCU->addDIEEntry(VariableSpecDIE, dwarf::DW_AT_specification, - dwarf::DW_FORM_ref4, VariableDIE); - TheCU->addBlock(VariableSpecDIE, dwarf::DW_AT_location, 0, Block); - TheCU->addUInt(VariableDIE, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag, 1); - TheCU->addDie(VariableSpecDIE); - } else { - TheCU->addBlock(VariableDIE, dwarf::DW_AT_location, 0, Block); - } - } else if (const ConstantInt *CI = - dyn_cast_or_null(GV.getConstant())) - TheCU->addConstantValue(VariableDIE, CI, isUnsignedDIType(GTy)); - else if (const ConstantExpr *CE = getMergedGlobalExpr(N->getOperand(11))) { - // GV is a merged global. - DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); - TheCU->addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_addr); - TheCU->addLabel(Block, 0, dwarf::DW_FORM_udata, - Asm->Mang->getSymbol(cast(CE->getOperand(0)))); - ConstantInt *CII = cast(CE->getOperand(2)); - TheCU->addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_constu); - TheCU->addUInt(Block, 0, dwarf::DW_FORM_udata, CII->getZExtValue()); - TheCU->addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_plus); - TheCU->addBlock(VariableDIE, dwarf::DW_AT_location, 0, Block); - } - - return; + return NewCU; } /// construct SubprogramDIE - Construct subprogram DIE. -void DwarfDebug::constructSubprogramDIE(const MDNode *N) { +void DwarfDebug::constructSubprogramDIE(CompileUnit *TheCU, + const MDNode *N) { DISubprogram SP(N); - - // Check for pre-existence. - CompileUnit *TheCU = getCompileUnit(N); - if (TheCU->getDIE(N)) - return; - if (!SP.isDefinition()) // This is a method declaration which will be handled while constructing // class type. return; - DIE *SubprogramDie = createSubprogramDIE(SP); + DIE *SubprogramDie = TheCU->getOrCreateSubprogramDIE(SP); // Add to map. TheCU->insertDIE(N, SubprogramDie); @@ -1066,71 +530,115 @@ void DwarfDebug::constructSubprogramDIE(const MDNode *N) { // Expose as global. TheCU->addGlobal(SP.getName(), SubprogramDie); + SPMap[N] = TheCU; return; } +/// collectInfoFromNamedMDNodes - Collect debug info from named mdnodes such +/// as llvm.dbg.enum and llvm.dbg.ty +void DwarfDebug::collectInfoFromNamedMDNodes(Module *M) { + if (NamedMDNode *NMD = M->getNamedMetadata("llvm.dbg.sp")) + for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) { + const MDNode *N = NMD->getOperand(i); + if (CompileUnit *CU = CUMap.lookup(DISubprogram(N).getCompileUnit())) + constructSubprogramDIE(CU, N); + } + + if (NamedMDNode *NMD = M->getNamedMetadata("llvm.dbg.gv")) + for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) { + const MDNode *N = NMD->getOperand(i); + if (CompileUnit *CU = CUMap.lookup(DIGlobalVariable(N).getCompileUnit())) + CU->createGlobalVariableDIE(N); + } + + if (NamedMDNode *NMD = M->getNamedMetadata("llvm.dbg.enum")) + for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) { + DIType Ty(NMD->getOperand(i)); + if (CompileUnit *CU = CUMap.lookup(Ty.getCompileUnit())) + CU->getOrCreateTypeDIE(Ty); + } + + if (NamedMDNode *NMD = M->getNamedMetadata("llvm.dbg.ty")) + for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) { + DIType Ty(NMD->getOperand(i)); + if (CompileUnit *CU = CUMap.lookup(Ty.getCompileUnit())) + CU->getOrCreateTypeDIE(Ty); + } +} + +/// collectLegacyDebugInfo - Collect debug info using DebugInfoFinder. +/// FIXME - Remove this when dragon-egg and llvm-gcc switch to DIBuilder. +bool DwarfDebug::collectLegacyDebugInfo(Module *M) { + DebugInfoFinder DbgFinder; + DbgFinder.processModule(*M); + + bool HasDebugInfo = false; + // Scan all the compile-units to see if there are any marked as the main + // unit. If not, we do not generate debug info. + for (DebugInfoFinder::iterator I = DbgFinder.compile_unit_begin(), + E = DbgFinder.compile_unit_end(); I != E; ++I) { + if (DICompileUnit(*I).isMain()) { + HasDebugInfo = true; + break; + } + } + if (!HasDebugInfo) return false; + + // Create all the compile unit DIEs. + for (DebugInfoFinder::iterator I = DbgFinder.compile_unit_begin(), + E = DbgFinder.compile_unit_end(); I != E; ++I) + constructCompileUnit(*I); + + // Create DIEs for each global variable. + for (DebugInfoFinder::iterator I = DbgFinder.global_variable_begin(), + E = DbgFinder.global_variable_end(); I != E; ++I) { + const MDNode *N = *I; + if (CompileUnit *CU = CUMap.lookup(DIGlobalVariable(N).getCompileUnit())) + CU->createGlobalVariableDIE(N); + } + + // Create DIEs for each subprogram. + for (DebugInfoFinder::iterator I = DbgFinder.subprogram_begin(), + E = DbgFinder.subprogram_end(); I != E; ++I) { + const MDNode *N = *I; + if (CompileUnit *CU = CUMap.lookup(DISubprogram(N).getCompileUnit())) + constructSubprogramDIE(CU, N); + } + + return HasDebugInfo; +} + /// beginModule - Emit all Dwarf sections that should come prior to the /// content. Create global DIEs and emit initial debug info sections. -/// This is inovked by the target AsmPrinter. +/// This is invoked by the target AsmPrinter. void DwarfDebug::beginModule(Module *M) { if (DisableDebugInfoPrinting) return; - // If module has named metadata anchors then use them, otherwise scan the module - // using debug info finder to collect debug info. + // If module has named metadata anchors then use them, otherwise scan the + // module using debug info finder to collect debug info. NamedMDNode *CU_Nodes = M->getNamedMetadata("llvm.dbg.cu"); if (CU_Nodes) { - - NamedMDNode *GV_Nodes = M->getNamedMetadata("llvm.dbg.gv"); - NamedMDNode *SP_Nodes = M->getNamedMetadata("llvm.dbg.sp"); - if (!GV_Nodes && !SP_Nodes) - // If there are not any global variables or any functions then - // there is not any debug info in this module. - return; - - for (unsigned i = 0, e = CU_Nodes->getNumOperands(); i != e; ++i) - constructCompileUnit(CU_Nodes->getOperand(i)); - - if (GV_Nodes) - for (unsigned i = 0, e = GV_Nodes->getNumOperands(); i != e; ++i) - constructGlobalVariableDIE(GV_Nodes->getOperand(i)); - - if (SP_Nodes) - for (unsigned i = 0, e = SP_Nodes->getNumOperands(); i != e; ++i) - constructSubprogramDIE(SP_Nodes->getOperand(i)); - - } else { - - DebugInfoFinder DbgFinder; - DbgFinder.processModule(*M); - - bool HasDebugInfo = false; - // Scan all the compile-units to see if there are any marked as the main unit. - // if not, we do not generate debug info. - for (DebugInfoFinder::iterator I = DbgFinder.compile_unit_begin(), - E = DbgFinder.compile_unit_end(); I != E; ++I) { - if (DICompileUnit(*I).isMain()) { - HasDebugInfo = true; - break; - } + for (unsigned i = 0, e = CU_Nodes->getNumOperands(); i != e; ++i) { + DICompileUnit CUNode(CU_Nodes->getOperand(i)); + CompileUnit *CU = constructCompileUnit(CUNode); + DIArray GVs = CUNode.getGlobalVariables(); + for (unsigned i = 0, e = GVs.getNumElements(); i != e; ++i) + CU->createGlobalVariableDIE(GVs.getElement(i)); + DIArray SPs = CUNode.getSubprograms(); + for (unsigned i = 0, e = SPs.getNumElements(); i != e; ++i) + constructSubprogramDIE(CU, SPs.getElement(i)); + DIArray EnumTypes = CUNode.getEnumTypes(); + for (unsigned i = 0, e = EnumTypes.getNumElements(); i != e; ++i) + CU->getOrCreateTypeDIE(EnumTypes.getElement(i)); + DIArray RetainedTypes = CUNode.getRetainedTypes(); + for (unsigned i = 0, e = RetainedTypes.getNumElements(); i != e; ++i) + CU->getOrCreateTypeDIE(RetainedTypes.getElement(i)); } - if (!HasDebugInfo) return; - - // Create all the compile unit DIEs. - for (DebugInfoFinder::iterator I = DbgFinder.compile_unit_begin(), - E = DbgFinder.compile_unit_end(); I != E; ++I) - constructCompileUnit(*I); - - // Create DIEs for each global variable. - for (DebugInfoFinder::iterator I = DbgFinder.global_variable_begin(), - E = DbgFinder.global_variable_end(); I != E; ++I) - constructGlobalVariableDIE(*I); - - // Create DIEs for each subprogram. - for (DebugInfoFinder::iterator I = DbgFinder.subprogram_begin(), - E = DbgFinder.subprogram_end(); I != E; ++I) - constructSubprogramDIE(*I); - } + } else if (!collectLegacyDebugInfo(M)) + return; + + collectInfoFromNamedMDNodes(M); // Tell MMI that we have debug info. MMI->setDebugInfoAvailability(true); @@ -1138,19 +646,6 @@ void DwarfDebug::beginModule(Module *M) { // Emit initial sections. EmitSectionLabels(); - //getOrCreateTypeDIE - if (NamedMDNode *NMD = M->getNamedMetadata("llvm.dbg.enum")) - for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) { - DIType Ty(NMD->getOperand(i)); - getCompileUnit(Ty)->getOrCreateTypeDIE(Ty); - } - - if (NamedMDNode *NMD = M->getNamedMetadata("llvm.dbg.ty")) - for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) { - DIType Ty(NMD->getOperand(i)); - getCompileUnit(Ty)->getOrCreateTypeDIE(Ty); - } - // Prime section data. SectionMap.insert(Asm->getObjFileLowering().getTextSection()); } @@ -1160,38 +655,38 @@ void DwarfDebug::beginModule(Module *M) { void DwarfDebug::endModule() { if (!FirstCU) return; const Module *M = MMI->getModule(); - DenseMap DeadFnScopeMap; - if (NamedMDNode *AllSPs = M->getNamedMetadata("llvm.dbg.sp")) { - for (unsigned SI = 0, SE = AllSPs->getNumOperands(); SI != SE; ++SI) { - if (ProcessedSPNodes.count(AllSPs->getOperand(SI)) != 0) continue; - DISubprogram SP(AllSPs->getOperand(SI)); - if (!SP.Verify()) continue; - - // Collect info for variables that were optimized out. - if (!SP.isDefinition()) continue; - StringRef FName = SP.getLinkageName(); - if (FName.empty()) - FName = SP.getName(); - NamedMDNode *NMD = getFnSpecificMDNode(*(MMI->getModule()), FName); - if (!NMD) continue; - unsigned E = NMD->getNumOperands(); - if (!E) continue; - DbgScope *Scope = new DbgScope(NULL, DIDescriptor(SP), NULL); - DeadFnScopeMap[SP] = Scope; - for (unsigned I = 0; I != E; ++I) { - DIVariable DV(NMD->getOperand(I)); - if (!DV.Verify()) continue; - Scope->addVariable(new DbgVariable(DV)); - } + DenseMap DeadFnScopeMap; - // Construct subprogram DIE and add variables DIEs. - constructSubprogramDIE(SP); - DIE *ScopeDIE = getCompileUnit(SP)->getDIE(SP); - const SmallVector &Variables = Scope->getDbgVariables(); - for (unsigned i = 0, N = Variables.size(); i < N; ++i) { - DIE *VariableDIE = constructVariableDIE(Variables[i], Scope); - if (VariableDIE) - ScopeDIE->addChild(VariableDIE); + // Collect info for variables that were optimized out. + if (NamedMDNode *CU_Nodes = M->getNamedMetadata("llvm.dbg.cu")) { + for (unsigned i = 0, e = CU_Nodes->getNumOperands(); i != e; ++i) { + DICompileUnit TheCU(CU_Nodes->getOperand(i)); + DIArray Subprograms = TheCU.getSubprograms(); + for (unsigned i = 0, e = Subprograms.getNumElements(); i != e; ++i) { + DISubprogram SP(Subprograms.getElement(i)); + if (ProcessedSPNodes.count(SP) != 0) continue; + if (!SP.Verify()) continue; + if (!SP.isDefinition()) continue; + DIArray Variables = SP.getVariables(); + if (Variables.getNumElements() == 0) continue; + + LexicalScope *Scope = + new LexicalScope(NULL, DIDescriptor(SP), NULL, false); + DeadFnScopeMap[SP] = Scope; + + // Construct subprogram DIE and add variables DIEs. + CompileUnit *SPCU = CUMap.lookup(TheCU); + assert (SPCU && "Unable to find Compile Unit!"); + constructSubprogramDIE(SPCU, SP); + DIE *ScopeDIE = SPCU->getDIE(SP); + for (unsigned vi = 0, ve = Variables.getNumElements(); vi != ve; ++vi) { + DIVariable DV(Variables.getElement(vi)); + if (!DV.Verify()) continue; + DbgVariable *NewVar = new DbgVariable(DV, NULL); + if (DIE *VariableDIE = + SPCU->constructVariableDIE(NewVar, Scope->isAbstractScope())) + ScopeDIE->addChild(VariableDIE); + } } } } @@ -1203,15 +698,12 @@ void DwarfDebug::endModule() { FirstCU->addUInt(ISP, dwarf::DW_AT_inline, 0, dwarf::DW_INL_inlined); } - for (DenseMap::iterator CI = ContainingTypeMap.begin(), - CE = ContainingTypeMap.end(); CI != CE; ++CI) { - DIE *SPDie = CI->first; - const MDNode *N = dyn_cast_or_null(CI->second); - if (!N) continue; - DIE *NDie = getCompileUnit(N)->getDIE(N); - if (!NDie) continue; - getCompileUnit(N)->addDIEEntry(SPDie, dwarf::DW_AT_containing_type, - dwarf::DW_FORM_ref4, NDie); + // Emit DW_AT_containing_type attribute to connect types with their + // vtable holding type. + for (DenseMap::iterator CUI = CUMap.begin(), + CUE = CUMap.end(); CUI != CUE; ++CUI) { + CompileUnit *TheCU = CUI->second; + TheCU->constructContainingTypeDIEs(); } // Standard sections final addresses. @@ -1261,6 +753,7 @@ void DwarfDebug::endModule() { // clean up. DeleteContainerSeconds(DeadFnScopeMap); + SPMap.clear(); for (DenseMap::iterator I = CUMap.begin(), E = CUMap.end(); I != E; ++I) delete I->second; @@ -1268,29 +761,30 @@ void DwarfDebug::endModule() { } /// findAbstractVariable - Find abstract variable, if any, associated with Var. -DbgVariable *DwarfDebug::findAbstractVariable(DIVariable &Var, +DbgVariable *DwarfDebug::findAbstractVariable(DIVariable &DV, DebugLoc ScopeLoc) { - + LLVMContext &Ctx = DV->getContext(); + // More then one inlined variable corresponds to one abstract variable. + DIVariable Var = cleanseInlinedVariable(DV, Ctx); DbgVariable *AbsDbgVariable = AbstractVariables.lookup(Var); if (AbsDbgVariable) return AbsDbgVariable; - LLVMContext &Ctx = Var->getContext(); - DbgScope *Scope = AbstractScopes.lookup(ScopeLoc.getScope(Ctx)); + LexicalScope *Scope = LScopes.findAbstractScope(ScopeLoc.getScope(Ctx)); if (!Scope) return NULL; - AbsDbgVariable = new DbgVariable(Var); - Scope->addVariable(AbsDbgVariable); + AbsDbgVariable = new DbgVariable(Var, NULL); + addScopeVariable(Scope, AbsDbgVariable); AbstractVariables[Var] = AbsDbgVariable; return AbsDbgVariable; } -/// addCurrentFnArgument - If Var is an current function argument that add -/// it in CurrentFnArguments list. +/// addCurrentFnArgument - If Var is a current function argument then add +/// it to CurrentFnArguments list. bool DwarfDebug::addCurrentFnArgument(const MachineFunction *MF, - DbgVariable *Var, DbgScope *Scope) { - if (Scope != CurrentFnDbgScope) + DbgVariable *Var, LexicalScope *Scope) { + if (!LScopes.isCurrentFunctionScope(Scope)) return false; DIVariable DV = Var->getVariable(); if (DV.getTag() != dwarf::DW_TAG_arg_variable) @@ -1313,7 +807,7 @@ bool DwarfDebug::addCurrentFnArgument(const MachineFunction *MF, /// collectVariableInfoFromMMITable - Collect variable information from /// side table maintained by MMI. void -DwarfDebug::collectVariableInfoFromMMITable(const MachineFunction * MF, +DwarfDebug::collectVariableInfoFromMMITable(const MachineFunction *MF, SmallPtrSet &Processed) { MachineModuleInfo::VariableDbgInfoMapTy &VMap = MMI->getVariableDbgInfo(); for (MachineModuleInfo::VariableDbgInfoMapTy::iterator VI = VMap.begin(), @@ -1324,21 +818,19 @@ DwarfDebug::collectVariableInfoFromMMITable(const MachineFunction * MF, DIVariable DV(Var); const std::pair &VP = VI->second; - DbgScope *Scope = findDbgScope(VP.second); + LexicalScope *Scope = LScopes.findLexicalScope(VP.second); // If variable scope is not found then skip this variable. if (Scope == 0) continue; DbgVariable *AbsDbgVariable = findAbstractVariable(DV, VP.second); - DbgVariable *RegVar = new DbgVariable(DV); - recordVariableFrameIndex(RegVar, VP.first); + DbgVariable *RegVar = new DbgVariable(DV, AbsDbgVariable); + RegVar->setFrameIndex(VP.first); if (!addCurrentFnArgument(MF, RegVar, Scope)) - Scope->addVariable(RegVar); - if (AbsDbgVariable) { - recordVariableFrameIndex(AbsDbgVariable, VP.first); - VarToAbstractVarMap[RegVar] = AbsDbgVariable; - } + addScopeVariable(Scope, RegVar); + if (AbsDbgVariable) + AbsDbgVariable->setFrameIndex(VP.first); } } @@ -1351,7 +843,7 @@ static bool isDbgValueInDefinedReg(const MachineInstr *MI) { MI->getOperand(1).isImm() && MI->getOperand(1).getImm() == 0; } -/// getDebugLocEntry - Get .debug_loc entry for the instraction range starting +/// getDebugLocEntry - Get .debug_loc entry for the instruction range starting /// at MI. static DotDebugLocEntry getDebugLocEntry(AsmPrinter *Asm, const MCSymbol *FLabel, @@ -1379,7 +871,7 @@ static DotDebugLocEntry getDebugLocEntry(AsmPrinter *Asm, return DotDebugLocEntry(); } -/// collectVariableInfo - Populate DbgScope entries with variables' info. +/// collectVariableInfo - Find variables for each lexical scope. void DwarfDebug::collectVariableInfo(const MachineFunction *MF, SmallPtrSet &Processed) { @@ -1402,30 +894,37 @@ DwarfDebug::collectVariableInfo(const MachineFunction *MF, const MachineInstr *MInsn = History.front(); DIVariable DV(Var); - DbgScope *Scope = NULL; + LexicalScope *Scope = NULL; if (DV.getTag() == dwarf::DW_TAG_arg_variable && DISubprogram(DV.getContext()).describes(MF->getFunction())) - Scope = CurrentFnDbgScope; - else - Scope = findDbgScope(MInsn->getDebugLoc()); + Scope = LScopes.getCurrentFunctionScope(); + else { + if (DV.getVersion() <= LLVMDebugVersion9) + Scope = LScopes.findLexicalScope(MInsn->getDebugLoc()); + else { + if (MDNode *IA = DV.getInlinedAt()) + Scope = LScopes.findInlinedScope(DebugLoc::getFromDILocation(IA)); + else + Scope = LScopes.findLexicalScope(cast(DV->getOperand(1))); + } + } // If variable scope is not found then skip this variable. if (!Scope) continue; Processed.insert(DV); assert(MInsn->isDebugValue() && "History must begin with debug value"); - DbgVariable *RegVar = new DbgVariable(DV); + DbgVariable *AbsVar = findAbstractVariable(DV, MInsn->getDebugLoc()); + DbgVariable *RegVar = new DbgVariable(DV, AbsVar); if (!addCurrentFnArgument(MF, RegVar, Scope)) - Scope->addVariable(RegVar); - if (DbgVariable *AbsVar = findAbstractVariable(DV, MInsn->getDebugLoc())) { - DbgVariableToDbgInstMap[AbsVar] = MInsn; - VarToAbstractVarMap[RegVar] = AbsVar; - } + addScopeVariable(Scope, RegVar); + if (AbsVar) + AbsVar->setMInsn(MInsn); // Simple ranges that are fully coalesced. if (History.size() <= 1 || (History.size() == 2 && MInsn->isIdenticalTo(History.back()))) { - DbgVariableToDbgInstMap[RegVar] = MInsn; + RegVar->setMInsn(MInsn); continue; } @@ -1471,16 +970,14 @@ DwarfDebug::collectVariableInfo(const MachineFunction *MF, } // Collect info for variables that were optimized out. - const Function *F = MF->getFunction(); - if (NamedMDNode *NMD = getFnSpecificMDNode(*(F->getParent()), F->getName())) { - for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) { - DIVariable DV(cast(NMD->getOperand(i))); - if (!DV || !Processed.insert(DV)) - continue; - DbgScope *Scope = DbgScopeMap.lookup(DV.getContext()); - if (Scope) - Scope->addVariable(new DbgVariable(DV)); - } + LexicalScope *FnScope = LScopes.getCurrentFunctionScope(); + DIArray Variables = DISubprogram(FnScope->getScopeNode()).getVariables(); + for (unsigned i = 0, e = Variables.getNumElements(); i != e; ++i) { + DIVariable DV(Variables.getElement(i)); + if (!DV || !DV.Verify() || !Processed.insert(DV)) + continue; + if (LexicalScope *Scope = LScopes.findLexicalScope(DV.getContext())) + addScopeVariable(Scope, new DbgVariable(DV, NULL)); } } @@ -1561,237 +1058,33 @@ void DwarfDebug::endInstruction(const MachineInstr *MI) { I->second = PrevLabel; } -/// getOrCreateDbgScope - Create DbgScope for the scope. -DbgScope *DwarfDebug::getOrCreateDbgScope(DebugLoc DL) { - LLVMContext &Ctx = Asm->MF->getFunction()->getContext(); - MDNode *Scope = NULL; - MDNode *InlinedAt = NULL; - DL.getScopeAndInlinedAt(Scope, InlinedAt, Ctx); - - if (!InlinedAt) { - DbgScope *WScope = DbgScopeMap.lookup(Scope); - if (WScope) - return WScope; - WScope = new DbgScope(NULL, DIDescriptor(Scope), NULL); - DbgScopeMap.insert(std::make_pair(Scope, WScope)); - if (DIDescriptor(Scope).isLexicalBlock()) { - DbgScope *Parent = - getOrCreateDbgScope(DebugLoc::getFromDILexicalBlock(Scope)); - WScope->setParent(Parent); - Parent->addScope(WScope); - } else if (DIDescriptor(Scope).isSubprogram() - && DISubprogram(Scope).describes(Asm->MF->getFunction())) - CurrentFnDbgScope = WScope; - - return WScope; - } - - getOrCreateAbstractScope(Scope); - DbgScope *WScope = DbgScopeMap.lookup(InlinedAt); - if (WScope) - return WScope; - - WScope = new DbgScope(NULL, DIDescriptor(Scope), InlinedAt); - DbgScopeMap.insert(std::make_pair(InlinedAt, WScope)); - InlinedDbgScopeMap[DebugLoc::getFromDILocation(InlinedAt)] = WScope; - DbgScope *Parent = - getOrCreateDbgScope(DebugLoc::getFromDILocation(InlinedAt)); - WScope->setParent(Parent); - Parent->addScope(WScope); - return WScope; -} - -/// calculateDominanceGraph - Calculate dominance graph for DbgScope -/// hierarchy. -static void calculateDominanceGraph(DbgScope *Scope) { - assert (Scope && "Unable to calculate scop edominance graph!"); - SmallVector WorkStack; - WorkStack.push_back(Scope); - unsigned Counter = 0; - while (!WorkStack.empty()) { - DbgScope *WS = WorkStack.back(); - const SmallVector &Children = WS->getScopes(); - bool visitedChildren = false; - for (SmallVector::const_iterator SI = Children.begin(), - SE = Children.end(); SI != SE; ++SI) { - DbgScope *ChildScope = *SI; - if (!ChildScope->getDFSOut()) { - WorkStack.push_back(ChildScope); - visitedChildren = true; - ChildScope->setDFSIn(++Counter); - break; - } - } - if (!visitedChildren) { - WorkStack.pop_back(); - WS->setDFSOut(++Counter); - } - } -} - -/// printDbgScopeInfo - Print DbgScope info for each machine instruction. -static -void printDbgScopeInfo(const MachineFunction *MF, - DenseMap &MI2ScopeMap) -{ -#ifndef NDEBUG - LLVMContext &Ctx = MF->getFunction()->getContext(); - unsigned PrevDFSIn = 0; - for (MachineFunction::const_iterator I = MF->begin(), E = MF->end(); - I != E; ++I) { - for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end(); - II != IE; ++II) { - const MachineInstr *MInsn = II; - MDNode *Scope = NULL; - MDNode *InlinedAt = NULL; - - // Check if instruction has valid location information. - DebugLoc MIDL = MInsn->getDebugLoc(); - if (!MIDL.isUnknown()) { - MIDL.getScopeAndInlinedAt(Scope, InlinedAt, Ctx); - dbgs() << " [ "; - if (InlinedAt) - dbgs() << "*"; - DenseMap::iterator DI = - MI2ScopeMap.find(MInsn); - if (DI != MI2ScopeMap.end()) { - DbgScope *S = DI->second; - dbgs() << S->getDFSIn(); - PrevDFSIn = S->getDFSIn(); - } else - dbgs() << PrevDFSIn; - } else - dbgs() << " [ x" << PrevDFSIn; - dbgs() << " ]"; - MInsn->dump(); - } - dbgs() << "\n"; - } -#endif -} -/// extractScopeInformation - Scan machine instructions in this function -/// and collect DbgScopes. Return true, if at least one scope was found. -bool DwarfDebug::extractScopeInformation() { - // If scope information was extracted using .dbg intrinsics then there is not - // any need to extract these information by scanning each instruction. - if (!DbgScopeMap.empty()) - return false; - - // Scan each instruction and create scopes. First build working set of scopes. - SmallVector MIRanges; - DenseMap MI2ScopeMap; - DebugLoc PrevDL; - const MachineInstr *RangeBeginMI = NULL; - const MachineInstr *PrevMI = NULL; - for (MachineFunction::const_iterator I = Asm->MF->begin(), E = Asm->MF->end(); - I != E; ++I) { - for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end(); - II != IE; ++II) { - const MachineInstr *MInsn = II; - - // Check if instruction has valid location information. - const DebugLoc MIDL = MInsn->getDebugLoc(); - if (MIDL.isUnknown()) { - PrevMI = MInsn; - continue; - } - - // If scope has not changed then skip this instruction. - if (MIDL == PrevDL) { - PrevMI = MInsn; - continue; - } - - // Ignore DBG_VALUE. It does not contribute any instruction in output. - if (MInsn->isDebugValue()) - continue; - - if (RangeBeginMI) { - // If we have alread seen a beginning of a instruction range and - // current instruction scope does not match scope of first instruction - // in this range then create a new instruction range. - DEBUG(dbgs() << "Creating new instruction range :\n"); - DEBUG(dbgs() << "Begin Range at " << *RangeBeginMI); - DEBUG(dbgs() << "End Range at " << *PrevMI); - DEBUG(dbgs() << "Next Range starting at " << *MInsn); - DEBUG(dbgs() << "------------------------\n"); - DbgRange R(RangeBeginMI, PrevMI); - MI2ScopeMap[RangeBeginMI] = getOrCreateDbgScope(PrevDL); - MIRanges.push_back(R); - } - - // This is a beginning of a new instruction range. - RangeBeginMI = MInsn; - - // Reset previous markers. - PrevMI = MInsn; - PrevDL = MIDL; - } - } - - // Create last instruction range. - if (RangeBeginMI && PrevMI && !PrevDL.isUnknown()) { - DbgRange R(RangeBeginMI, PrevMI); - MIRanges.push_back(R); - MI2ScopeMap[RangeBeginMI] = getOrCreateDbgScope(PrevDL); - } - - if (!CurrentFnDbgScope) - return false; - - calculateDominanceGraph(CurrentFnDbgScope); - if (PrintDbgScope) - printDbgScopeInfo(Asm->MF, MI2ScopeMap); - - // Find ranges of instructions covered by each DbgScope; - DbgScope *PrevDbgScope = NULL; - for (SmallVector::const_iterator RI = MIRanges.begin(), - RE = MIRanges.end(); RI != RE; ++RI) { - const DbgRange &R = *RI; - DbgScope *S = MI2ScopeMap.lookup(R.first); - assert (S && "Lost DbgScope for a machine instruction!"); - if (PrevDbgScope && !PrevDbgScope->dominates(S)) - PrevDbgScope->closeInsnRange(S); - S->openInsnRange(R.first); - S->extendInsnRange(R.second); - PrevDbgScope = S; - } - - if (PrevDbgScope) - PrevDbgScope->closeInsnRange(); - - identifyScopeMarkers(); - - return !DbgScopeMap.empty(); -} - /// identifyScopeMarkers() - -/// Each DbgScope has first instruction and last instruction to mark beginning -/// and end of a scope respectively. Create an inverse map that list scopes -/// starts (and ends) with an instruction. One instruction may start (or end) -/// multiple scopes. Ignore scopes that are not reachable. +/// Each LexicalScope has first instruction and last instruction to mark +/// beginning and end of a scope respectively. Create an inverse map that list +/// scopes starts (and ends) with an instruction. One instruction may start (or +/// end) multiple scopes. Ignore scopes that are not reachable. void DwarfDebug::identifyScopeMarkers() { - SmallVector WorkList; - WorkList.push_back(CurrentFnDbgScope); + SmallVector WorkList; + WorkList.push_back(LScopes.getCurrentFunctionScope()); while (!WorkList.empty()) { - DbgScope *S = WorkList.pop_back_val(); + LexicalScope *S = WorkList.pop_back_val(); - const SmallVector &Children = S->getScopes(); + const SmallVector &Children = S->getChildren(); if (!Children.empty()) - for (SmallVector::const_iterator SI = Children.begin(), + for (SmallVector::const_iterator SI = Children.begin(), SE = Children.end(); SI != SE; ++SI) WorkList.push_back(*SI); if (S->isAbstractScope()) continue; - const SmallVector &Ranges = S->getRanges(); + const SmallVector &Ranges = S->getRanges(); if (Ranges.empty()) continue; - for (SmallVector::const_iterator RI = Ranges.begin(), + for (SmallVector::const_iterator RI = Ranges.begin(), RE = Ranges.end(); RI != RE; ++RI) { - assert(RI->first && "DbgRange does not have first instruction!"); - assert(RI->second && "DbgRange does not have second instruction!"); + assert(RI->first && "InsnRange does not have first instruction!"); + assert(RI->second && "InsnRange does not have second instruction!"); requestLabelBeforeInsn(RI->first); requestLabelAfterInsn(RI->second); } @@ -1819,7 +1112,9 @@ static DebugLoc getFnDebugLoc(DebugLoc DL, const LLVMContext &Ctx) { /// emitted immediately after the function entry point. void DwarfDebug::beginFunction(const MachineFunction *MF) { if (!MMI->hasDebugInfo()) return; - if (!extractScopeInformation()) return; + LScopes.initialize(*MF); + if (LScopes.empty()) return; + identifyScopeMarkers(); FunctionBeginSym = Asm->GetTempSymbol("func_begin", Asm->getFunctionNumber()); @@ -1953,7 +1248,8 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) { const MachineInstr *Prev = History.back(); if (Prev->isDebugValue() && isDbgValueInDefinedReg(Prev)) { const MachineBasicBlock *PrevMBB = Prev->getParent(); - MachineBasicBlock::const_iterator LastMI = PrevMBB->getLastNonDebugInstr(); + MachineBasicBlock::const_iterator LastMI = + PrevMBB->getLastNonDebugInstr(); if (LastMI == PrevMBB->end()) // Drop DBG_VALUE for empty range. History.pop_back(); @@ -1985,110 +1281,73 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) { } } +void DwarfDebug::addScopeVariable(LexicalScope *LS, DbgVariable *Var) { +// SmallVector &Vars = ScopeVariables.lookup(LS); + ScopeVariables[LS].push_back(Var); +// Vars.push_back(Var); +} + /// endFunction - Gather and emit post-function debug information. /// void DwarfDebug::endFunction(const MachineFunction *MF) { - if (!MMI->hasDebugInfo() || DbgScopeMap.empty()) return; - - if (CurrentFnDbgScope) { + if (!MMI->hasDebugInfo() || LScopes.empty()) return; - // Define end label for subprogram. - FunctionEndSym = Asm->GetTempSymbol("func_end", - Asm->getFunctionNumber()); - // Assumes in correct section after the entry point. - Asm->OutStreamer.EmitLabel(FunctionEndSym); - - SmallPtrSet ProcessedVars; - collectVariableInfo(MF, ProcessedVars); - - // Construct abstract scopes. - for (SmallVector::iterator AI = AbstractScopesList.begin(), - AE = AbstractScopesList.end(); AI != AE; ++AI) { - DISubprogram SP((*AI)->getScopeNode()); - if (SP.Verify()) { - // Collect info for variables that were optimized out. - StringRef FName = SP.getLinkageName(); - if (FName.empty()) - FName = SP.getName(); - if (NamedMDNode *NMD = - getFnSpecificMDNode(*(MF->getFunction()->getParent()), FName)) { - for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) { - DIVariable DV(cast(NMD->getOperand(i))); - if (!DV || !ProcessedVars.insert(DV)) - continue; - DbgScope *Scope = AbstractScopes.lookup(DV.getContext()); - if (Scope) - Scope->addVariable(new DbgVariable(DV)); - } - } + // Define end label for subprogram. + FunctionEndSym = Asm->GetTempSymbol("func_end", + Asm->getFunctionNumber()); + // Assumes in correct section after the entry point. + Asm->OutStreamer.EmitLabel(FunctionEndSym); + + SmallPtrSet ProcessedVars; + collectVariableInfo(MF, ProcessedVars); + + LexicalScope *FnScope = LScopes.getCurrentFunctionScope(); + CompileUnit *TheCU = SPMap.lookup(FnScope->getScopeNode()); + assert (TheCU && "Unable to find compile unit!"); + + // Construct abstract scopes. + ArrayRef AList = LScopes.getAbstractScopesList(); + for (unsigned i = 0, e = AList.size(); i != e; ++i) { + LexicalScope *AScope = AList[i]; + DISubprogram SP(AScope->getScopeNode()); + if (SP.Verify()) { + // Collect info for variables that were optimized out. + DIArray Variables = SP.getVariables(); + for (unsigned i = 0, e = Variables.getNumElements(); i != e; ++i) { + DIVariable DV(Variables.getElement(i)); + if (!DV || !DV.Verify() || !ProcessedVars.insert(DV)) + continue; + if (LexicalScope *Scope = LScopes.findAbstractScope(DV.getContext())) + addScopeVariable(Scope, new DbgVariable(DV, NULL)); } - if (ProcessedSPNodes.count((*AI)->getScopeNode()) == 0) - constructScopeDIE(*AI); } - - DIE *CurFnDIE = constructScopeDIE(CurrentFnDbgScope); - - if (!DisableFramePointerElim(*MF)) - getCompileUnit(CurrentFnDbgScope->getScopeNode())->addUInt(CurFnDIE, - dwarf::DW_AT_APPLE_omit_frame_ptr, - dwarf::DW_FORM_flag, 1); - - - DebugFrames.push_back(FunctionDebugFrameInfo(Asm->getFunctionNumber(), - MMI->getFrameMoves())); + if (ProcessedSPNodes.count(AScope->getScopeNode()) == 0) + constructScopeDIE(TheCU, AScope); } + + DIE *CurFnDIE = constructScopeDIE(TheCU, FnScope); + + if (!DisableFramePointerElim(*MF)) + TheCU->addUInt(CurFnDIE, dwarf::DW_AT_APPLE_omit_frame_ptr, + dwarf::DW_FORM_flag, 1); + + DebugFrames.push_back(FunctionDebugFrameInfo(Asm->getFunctionNumber(), + MMI->getFrameMoves())); // Clear debug info - CurrentFnDbgScope = NULL; + for (DenseMap >::iterator + I = ScopeVariables.begin(), E = ScopeVariables.end(); I != E; ++I) + DeleteContainerPointers(I->second); + ScopeVariables.clear(); DeleteContainerPointers(CurrentFnArguments); - DbgVariableToFrameIndexMap.clear(); - VarToAbstractVarMap.clear(); - DbgVariableToDbgInstMap.clear(); - InlinedDbgScopeMap.clear(); - DeleteContainerSeconds(DbgScopeMap); UserVariables.clear(); DbgValues.clear(); - DeleteContainerSeconds(AbstractScopes); - AbstractScopesList.clear(); AbstractVariables.clear(); LabelsBeforeInsn.clear(); LabelsAfterInsn.clear(); PrevLabel = NULL; } -/// recordVariableFrameIndex - Record a variable's index. -void DwarfDebug::recordVariableFrameIndex(const DbgVariable *V, int Index) { - assert (V && "Invalid DbgVariable!"); - DbgVariableToFrameIndexMap[V] = Index; -} - -/// findVariableFrameIndex - Return true if frame index for the variable -/// is found. Update FI to hold value of the index. -bool DwarfDebug::findVariableFrameIndex(const DbgVariable *V, int *FI) { - assert (V && "Invalid DbgVariable!"); - DenseMap::iterator I = - DbgVariableToFrameIndexMap.find(V); - if (I == DbgVariableToFrameIndexMap.end()) - return false; - *FI = I->second; - return true; -} - -/// findDbgScope - Find DbgScope for the debug loc. -DbgScope *DwarfDebug::findDbgScope(DebugLoc DL) { - if (DL.isUnknown()) - return NULL; - - DbgScope *Scope = NULL; - LLVMContext &Ctx = Asm->MF->getFunction()->getContext(); - if (MDNode *IA = DL.getInlinedAt(Ctx)) - Scope = InlinedDbgScopeMap.lookup(DebugLoc::getFromDILocation(IA)); - else - Scope = DbgScopeMap.lookup(DL.getScope(Ctx)); - return Scope; -} - - /// recordSourceLine - Register a source line with debug info. Returns the /// unique label that was emitted and which provides correspondence to /// the source line list. @@ -2112,6 +1371,10 @@ void DwarfDebug::recordSourceLine(unsigned Line, unsigned Col, const MDNode *S, DISubprogram SP(S); Fn = SP.getFilename(); Dir = SP.getDirectory(); + } else if (Scope.isLexicalBlockFile()) { + DILexicalBlockFile DBF(S); + Fn = DBF.getFilename(); + Dir = DBF.getDirectory(); } else if (Scope.isLexicalBlock()) { DILexicalBlock DB(S); Fn = DB.getFilename(); @@ -2121,8 +1384,7 @@ void DwarfDebug::recordSourceLine(unsigned Line, unsigned Col, const MDNode *S, Src = GetOrCreateSourceID(Fn, Dir); } - Asm->OutStreamer.EmitDwarfLocDirective(Src, Line, Col, Flags, - 0, 0, Fn); + Asm->OutStreamer.EmitDwarfLocDirective(Src, Line, Col, Flags, 0, 0, Fn); } //===----------------------------------------------------------------------===// @@ -2235,7 +1497,7 @@ void DwarfDebug::EmitSectionLabels() { EmitSectionSym(Asm, TLOF.getDataSection()); } -/// emitDIE - Recusively Emits a debug information entry. +/// emitDIE - Recursively emits a debug information entry. /// void DwarfDebug::emitDIE(DIE *Die) { // Get the abbreviation for this DIE. @@ -2290,10 +1552,9 @@ void DwarfDebug::emitDIE(DIE *Die) { break; } case dwarf::DW_AT_location: { - if (UseDotDebugLocEntry.count(Die) != 0) { - DIELabel *L = cast(Values[i]); + if (DIELabel *L = dyn_cast(Values[i])) Asm->EmitLabelDifference(L->getValue(), DwarfDebugLocSectionSym, 4); - } else + else Values[i]->EmitValue(Asm, Form); break; } @@ -2464,7 +1725,7 @@ void DwarfDebug::emitDebugPubNames() { Asm->OutStreamer.AddComment("End Mark"); Asm->EmitInt32(0); Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("pubnames_end", - TheCU->getID())); + TheCU->getID())); } } @@ -2499,7 +1760,7 @@ void DwarfDebug::emitDebugPubTypes() { for (StringMap::const_iterator GI = Globals.begin(), GE = Globals.end(); GI != GE; ++GI) { const char *Name = GI->getKeyData(); - DIE * Entity = GI->second; + DIE *Entity = GI->second; if (Asm->isVerbose()) Asm->OutStreamer.AddComment("DIE offset"); Asm->EmitInt32(Entity->getOffset()); diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h index b2450064e..35653be5c 100644 --- a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h +++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h @@ -15,7 +15,8 @@ #define CODEGEN_ASMPRINTER_DWARFDEBUG_H__ #include "llvm/CodeGen/AsmPrinter.h" -#include "llvm/CodeGen/MachineLocation.h" +#include "llvm/CodeGen/LexicalScopes.h" +#include "llvm/MC/MachineLocation.h" #include "llvm/Analysis/DebugInfo.h" #include "DIE.h" #include "llvm/ADT/DenseMap.h" @@ -30,7 +31,6 @@ namespace llvm { class CompileUnit; class DbgConcreteScope; -class DbgScope; class DbgVariable; class MachineFrameInfo; class MachineModuleInfo; @@ -125,9 +125,14 @@ class DbgVariable { DIVariable Var; // Variable Descriptor. DIE *TheDIE; // Variable DIE. unsigned DotDebugLocOffset; // Offset in DotDebugLocEntries. + DbgVariable *AbsVar; // Corresponding Abstract variable, if any. + const MachineInstr *MInsn; // DBG_VALUE instruction of the variable. + int FrameIndex; public: // AbsVar may be NULL. - DbgVariable(DIVariable V) : Var(V), TheDIE(0), DotDebugLocOffset(~0U) {} + DbgVariable(DIVariable V, DbgVariable *AV) + : Var(V), TheDIE(0), DotDebugLocOffset(~0U), AbsVar(AV), MInsn(0), + FrameIndex(~0) {} // Accessors. DIVariable getVariable() const { return Var; } @@ -136,7 +141,27 @@ public: void setDotDebugLocOffset(unsigned O) { DotDebugLocOffset = O; } unsigned getDotDebugLocOffset() const { return DotDebugLocOffset; } StringRef getName() const { return Var.getName(); } - unsigned getTag() const { return Var.getTag(); } + DbgVariable *getAbstractVariable() const { return AbsVar; } + const MachineInstr *getMInsn() const { return MInsn; } + void setMInsn(const MachineInstr *M) { MInsn = M; } + int getFrameIndex() const { return FrameIndex; } + void setFrameIndex(int FI) { FrameIndex = FI; } + // Translate tag to proper Dwarf tag. + unsigned getTag() const { + if (Var.getTag() == dwarf::DW_TAG_arg_variable) + return dwarf::DW_TAG_formal_parameter; + + return dwarf::DW_TAG_variable; + } + /// isArtificial - Return true if DbgVariable is artificial. + bool isArtificial() const { + if (Var.isArtificial()) + return true; + if (Var.getTag() == dwarf::DW_TAG_arg_variable + && getType().isArtificial()) + return true; + return false; + } bool variableHasComplexAddress() const { assert(Var.Verify() && "Invalid complex DbgVariable!"); return Var.hasComplexAddress(); @@ -167,8 +192,13 @@ class DwarfDebug { // CompileUnit *FirstCU; + + /// Maps MDNode with its corresponding CompileUnit. DenseMap CUMap; + /// Maps subprogram MDNode with its corresponding CompileUnit. + DenseMap SPMap; + /// AbbreviationsSet - Used to uniquely define abbreviations. /// FoldingSet AbbreviationsSet; @@ -192,63 +222,27 @@ class DwarfDebug { /// UniqueVector SectionMap; - /// CurrentFnDbgScope - Top level scope for the current function. - /// - DbgScope *CurrentFnDbgScope; - /// CurrentFnArguments - List of Arguments (DbgValues) for current function. SmallVector CurrentFnArguments; - /// DbgScopeMap - Tracks the scopes in the current function. Owns the - /// contained DbgScope*s. - DenseMap DbgScopeMap; - - /// InlinedDbgScopeMap - Tracks inlined function scopes in current function. - DenseMap InlinedDbgScopeMap; - - /// AbstractScopes - Tracks the abstract scopes a module. These scopes are - /// not included DbgScopeMap. AbstractScopes owns its DbgScope*s. - DenseMap AbstractScopes; + LexicalScopes LScopes; /// AbstractSPDies - Collection of abstract subprogram DIEs. DenseMap AbstractSPDies; - /// AbstractScopesList - Tracks abstract scopes constructed while processing - /// a function. This list is cleared during endFunction(). - SmallVectorAbstractScopesList; + /// ScopeVariables - Collection of dbg variables of a scope. + DenseMap > ScopeVariables; - /// AbstractVariables - Collection on abstract variables. Owned by the - /// DbgScopes in AbstractScopes. + /// AbstractVariables - Collection on abstract variables. DenseMap AbstractVariables; - /// DbgVariableToFrameIndexMap - Tracks frame index used to find - /// variable's value. - DenseMap DbgVariableToFrameIndexMap; - - /// DbgVariableToDbgInstMap - Maps DbgVariable to corresponding DBG_VALUE - /// machine instruction. - DenseMap DbgVariableToDbgInstMap; - /// DotDebugLocEntries - Collection of DotDebugLocEntry. SmallVector DotDebugLocEntries; - /// UseDotDebugLocEntry - DW_AT_location attributes for the DIEs in this set - /// idetifies corresponding .debug_loc entry offset. - SmallPtrSet UseDotDebugLocEntry; - - /// VarToAbstractVarMap - Maps DbgVariable with corresponding Abstract - /// DbgVariable, if any. - DenseMap VarToAbstractVarMap; - /// InliendSubprogramDIEs - Collection of subprgram DIEs that are marked /// (at the end of the module) as DW_AT_inline. SmallPtrSet InlinedSubprogramDIEs; - /// ContainingTypeMap - This map is used to keep track of subprogram DIEs that - /// need DW_AT_containing_type attribute. This attribute points to a DIE that - /// corresponds to the MDNode mapped with the subprogram DIE. - DenseMap ContainingTypeMap; - /// InlineInfo - Keep track of inlined functions and their location. This /// information is used to populate debug_inlined section. typedef std::pair InlineInfoLabels; @@ -316,10 +310,7 @@ private: /// void assignAbbrevNumber(DIEAbbrev &Abbrev); - /// getOrCreateDbgScope - Create DbgScope for the scope. - DbgScope *getOrCreateDbgScope(DebugLoc DL); - - DbgScope *getOrCreateAbstractScope(const MDNode *N); + void addScopeVariable(LexicalScope *LS, DbgVariable *Var); /// findAbstractVariable - Find abstract variable associated with Var. DbgVariable *findAbstractVariable(DIVariable &Var, DebugLoc Loc); @@ -328,22 +319,22 @@ private: /// attach appropriate DW_AT_low_pc and DW_AT_high_pc attributes. /// If there are global variables in this scope then create and insert /// DIEs for these variables. - DIE *updateSubprogramScopeDIE(const MDNode *SPNode); + DIE *updateSubprogramScopeDIE(CompileUnit *SPCU, const MDNode *SPNode); /// constructLexicalScope - Construct new DW_TAG_lexical_block /// for this scope and attach DW_AT_low_pc/DW_AT_high_pc labels. - DIE *constructLexicalScopeDIE(DbgScope *Scope); + DIE *constructLexicalScopeDIE(CompileUnit *TheCU, LexicalScope *Scope); /// constructInlinedScopeDIE - This scope represents inlined body of /// a function. Construct DIE to represent this concrete inlined copy /// of the function. - DIE *constructInlinedScopeDIE(DbgScope *Scope); + DIE *constructInlinedScopeDIE(CompileUnit *TheCU, LexicalScope *Scope); /// constructVariableDIE - Construct a DIE for the given DbgVariable. - DIE *constructVariableDIE(DbgVariable *DV, DbgScope *S); + DIE *constructVariableDIE(DbgVariable *DV, LexicalScope *S); /// constructScopeDIE - Construct a DIE for this scope. - DIE *constructScopeDIE(DbgScope *Scope); + DIE *constructScopeDIE(CompileUnit *TheCU, LexicalScope *Scope); /// EmitSectionLabels - Emit initial Dwarf sections with a label at /// the start of each one. @@ -424,16 +415,10 @@ private: /// constructCompileUnit - Create new CompileUnit for the given /// metadata node with tag DW_TAG_compile_unit. - void constructCompileUnit(const MDNode *N); - - /// getCompielUnit - Get CompileUnit DIE. - CompileUnit *getCompileUnit(const MDNode *N) const; - - /// constructGlobalVariableDIE - Construct global variable DIE. - void constructGlobalVariableDIE(const MDNode *N); + CompileUnit *constructCompileUnit(const MDNode *N); /// construct SubprogramDIE - Construct subprogram DIE. - void constructSubprogramDIE(const MDNode *N); + void constructSubprogramDIE(CompileUnit *TheCU, const MDNode *N); /// recordSourceLine - Register a source line with debug info. Returns the /// unique label that was emitted and which provides correspondence to @@ -441,30 +426,16 @@ private: void recordSourceLine(unsigned Line, unsigned Col, const MDNode *Scope, unsigned Flags); - /// recordVariableFrameIndex - Record a variable's index. - void recordVariableFrameIndex(const DbgVariable *V, int Index); - - /// findVariableFrameIndex - Return true if frame index for the variable - /// is found. Update FI to hold value of the index. - bool findVariableFrameIndex(const DbgVariable *V, int *FI); - - /// findDbgScope - Find DbgScope for the debug loc. - DbgScope *findDbgScope(DebugLoc DL); - /// identifyScopeMarkers() - Indentify instructions that are marking /// beginning of or end of a scope. void identifyScopeMarkers(); - /// extractScopeInformation - Scan machine instructions in this function - /// and collect DbgScopes. Return true, if atleast one scope was found. - bool extractScopeInformation(); - /// addCurrentFnArgument - If Var is an current function argument that add /// it in CurrentFnArguments list. bool addCurrentFnArgument(const MachineFunction *MF, - DbgVariable *Var, DbgScope *Scope); + DbgVariable *Var, LexicalScope *Scope); - /// collectVariableInfo - Populate DbgScope entries with variables' info. + /// collectVariableInfo - Populate LexicalScope entries with variables' info. void collectVariableInfo(const MachineFunction *, SmallPtrSet &ProcessedVars); @@ -496,6 +467,14 @@ public: DwarfDebug(AsmPrinter *A, Module *M); ~DwarfDebug(); + /// collectInfoFromNamedMDNodes - Collect debug info from named mdnodes such + /// as llvm.dbg.enum and llvm.dbg.ty + void collectInfoFromNamedMDNodes(Module *M); + + /// collectLegacyDebugInfo - Collect debug info using DebugInfoFinder. + /// FIXME - Remove this when dragon-egg and llvm-gcc switch to DIBuilder. + bool collectLegacyDebugInfo(Module *M); + /// beginModule - Emit all Dwarf sections that should come prior to the /// content. void beginModule(Module *M); diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfException.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfException.cpp index 1f992faaa..18b726b17 100644 --- a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfException.cpp +++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfException.cpp @@ -17,7 +17,6 @@ #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" -#include "llvm/CodeGen/MachineLocation.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" @@ -527,29 +526,26 @@ void DwarfException::EmitExceptionTable() { I = CallSites.begin(), E = CallSites.end(); I != E; ++I, ++idx) { const CallSiteEntry &S = *I; + // Offset of the landing pad, counted in 16-byte bundles relative to the + // @LPStart address. if (VerboseAsm) { - // Emit comments that decode the call site. Asm->OutStreamer.AddComment(Twine(">> Call Site ") + llvm::utostr(idx) + " <<"); Asm->OutStreamer.AddComment(Twine(" On exception at call site ") + llvm::utostr(idx)); + } + Asm->EmitULEB128(idx); + // Offset of the first associated action record, relative to the start of + // the action table. This value is biased by 1 (1 indicates the start of + // the action table), and 0 indicates that there are no actions. + if (VerboseAsm) { if (S.Action == 0) Asm->OutStreamer.AddComment(" Action: cleanup"); else Asm->OutStreamer.AddComment(Twine(" Action: ") + llvm::utostr((S.Action - 1) / 2 + 1)); - - Asm->OutStreamer.AddBlankLine(); } - - // Offset of the landing pad, counted in 16-byte bundles relative to the - // @LPStart address. - Asm->EmitULEB128(idx); - - // Offset of the first associated action record, relative to the start of - // the action table. This value is biased by 1 (1 indicates the start of - // the action table), and 0 indicates that there are no actions. Asm->EmitULEB128(S.Action); } } else { @@ -595,46 +591,43 @@ void DwarfException::EmitExceptionTable() { if (EndLabel == 0) EndLabel = Asm->GetTempSymbol("eh_func_end", Asm->getFunctionNumber()); - if (VerboseAsm) { - // Emit comments that decode the call site. - Asm->OutStreamer.AddComment(Twine(">> Call Site ") + - llvm::utostr(++Entry) + " <<"); - Asm->OutStreamer.AddComment(Twine(" Call between ") + - BeginLabel->getName() + " and " + - EndLabel->getName()); - - if (!S.PadLabel) { - Asm->OutStreamer.AddComment(" has no landing pad"); - } else { - Asm->OutStreamer.AddComment(Twine(" jumps to ") + - S.PadLabel->getName()); - - if (S.Action == 0) - Asm->OutStreamer.AddComment(" On action: cleanup"); - else - Asm->OutStreamer.AddComment(Twine(" On action: ") + - llvm::utostr((S.Action - 1) / 2 + 1)); - } - - Asm->OutStreamer.AddBlankLine(); - } // Offset of the call site relative to the previous call site, counted in // number of 16-byte bundles. The first call site is counted relative to // the start of the procedure fragment. + if (VerboseAsm) + Asm->OutStreamer.AddComment(Twine(">> Call Site ") + + llvm::utostr(++Entry) + " <<"); Asm->EmitLabelDifference(BeginLabel, EHFuncBeginSym, 4); + if (VerboseAsm) + Asm->OutStreamer.AddComment(Twine(" Call between ") + + BeginLabel->getName() + " and " + + EndLabel->getName()); Asm->EmitLabelDifference(EndLabel, BeginLabel, 4); // Offset of the landing pad, counted in 16-byte bundles relative to the // @LPStart address. - if (!S.PadLabel) + if (!S.PadLabel) { + if (VerboseAsm) + Asm->OutStreamer.AddComment(" has no landing pad"); Asm->OutStreamer.EmitIntValue(0, 4/*size*/, 0/*addrspace*/); - else + } else { + if (VerboseAsm) + Asm->OutStreamer.AddComment(Twine(" jumps to ") + + S.PadLabel->getName()); Asm->EmitLabelDifference(S.PadLabel, EHFuncBeginSym, 4); + } // Offset of the first associated action record, relative to the start of // the action table. This value is biased by 1 (1 indicates the start of // the action table), and 0 indicates that there are no actions. + if (VerboseAsm) { + if (S.Action == 0) + Asm->OutStreamer.AddComment(" On action: cleanup"); + else + Asm->OutStreamer.AddComment(Twine(" On action: ") + + llvm::utostr((S.Action - 1) / 2 + 1)); + } Asm->EmitULEB128(S.Action); } } @@ -649,13 +642,29 @@ void DwarfException::EmitExceptionTable() { // Emit comments that decode the action table. Asm->OutStreamer.AddComment(Twine(">> Action Record ") + llvm::utostr(++Entry) + " <<"); - if (Action.ValueForTypeID >= 0) + } + + // Type Filter + // + // Used by the runtime to match the type of the thrown exception to the + // type of the catch clauses or the types in the exception specification. + if (VerboseAsm) { + if (Action.ValueForTypeID > 0) Asm->OutStreamer.AddComment(Twine(" Catch TypeInfo ") + llvm::itostr(Action.ValueForTypeID)); - else + else if (Action.ValueForTypeID < 0) Asm->OutStreamer.AddComment(Twine(" Filter TypeInfo ") + llvm::itostr(Action.ValueForTypeID)); + else + Asm->OutStreamer.AddComment(" Cleanup"); + } + Asm->EmitSLEB128(Action.ValueForTypeID); + // Action Record + // + // Self-relative signed displacement in bytes of the next action record, + // or 0 if there is no next action record. + if (VerboseAsm) { if (Action.NextAction == 0) { Asm->OutStreamer.AddComment(" No further actions"); } else { @@ -663,20 +672,7 @@ void DwarfException::EmitExceptionTable() { Asm->OutStreamer.AddComment(Twine(" Continue to action ") + llvm::utostr(NextAction)); } - - Asm->OutStreamer.AddBlankLine(); } - - // Type Filter - // - // Used by the runtime to match the type of the thrown exception to the - // type of the catch clauses or the types in the exception specification. - Asm->EmitSLEB128(Action.ValueForTypeID); - - // Action Record - // - // Self-relative signed displacement in bytes of the next action record, - // or 0 if there is no next action record. Asm->EmitSLEB128(Action.NextAction); } diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/Win64Exception.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/Win64Exception.cpp index c2ad5eba3..b83aa5ae3 100644 --- a/contrib/llvm/lib/CodeGen/AsmPrinter/Win64Exception.cpp +++ b/contrib/llvm/lib/CodeGen/AsmPrinter/Win64Exception.cpp @@ -17,7 +17,6 @@ #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" -#include "llvm/CodeGen/MachineLocation.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" diff --git a/contrib/llvm/lib/CodeGen/BranchFolding.cpp b/contrib/llvm/lib/CodeGen/BranchFolding.cpp index 99090a826..75288b093 100644 --- a/contrib/llvm/lib/CodeGen/BranchFolding.cpp +++ b/contrib/llvm/lib/CodeGen/BranchFolding.cpp @@ -1624,26 +1624,29 @@ bool BranchFolder::HoistCommonCodeInSuccs(MachineBasicBlock *MBB) { if (!TIB->isSafeToMove(TII, 0, DontMoveAcrossStore)) break; + // Remove kills from LocalDefsSet, these registers had short live ranges. + for (unsigned i = 0, e = TIB->getNumOperands(); i != e; ++i) { + MachineOperand &MO = TIB->getOperand(i); + if (!MO.isReg() || !MO.isUse() || !MO.isKill()) + continue; + unsigned Reg = MO.getReg(); + if (!Reg || !LocalDefsSet.count(Reg)) + continue; + for (const unsigned *OR = TRI->getOverlaps(Reg); *OR; ++OR) + LocalDefsSet.erase(*OR); + } + // Track local defs so we can update liveins. for (unsigned i = 0, e = TIB->getNumOperands(); i != e; ++i) { MachineOperand &MO = TIB->getOperand(i); - if (!MO.isReg()) + if (!MO.isReg() || !MO.isDef() || MO.isDead()) continue; unsigned Reg = MO.getReg(); if (!Reg) continue; - if (MO.isDef()) { - if (!MO.isDead()) { - LocalDefs.push_back(Reg); - LocalDefsSet.insert(Reg); - for (const unsigned *SR = TRI->getSubRegisters(Reg); *SR; ++SR) - LocalDefsSet.insert(*SR); - } - } else if (MO.isKill() && LocalDefsSet.count(Reg)) { - LocalDefsSet.erase(Reg); - for (const unsigned *SR = TRI->getSubRegisters(Reg); *SR; ++SR) - LocalDefsSet.erase(*SR); - } + LocalDefs.push_back(Reg); + for (const unsigned *OR = TRI->getOverlaps(Reg); *OR; ++OR) + LocalDefsSet.insert(*OR); } HasDups = true;; diff --git a/contrib/llvm/lib/CodeGen/CalcSpillWeights.cpp b/contrib/llvm/lib/CodeGen/CalcSpillWeights.cpp index e6b3bbca2..ea16a253a 100644 --- a/contrib/llvm/lib/CodeGen/CalcSpillWeights.cpp +++ b/contrib/llvm/lib/CodeGen/CalcSpillWeights.cpp @@ -185,35 +185,3 @@ void VirtRegAuxInfo::CalculateWeightAndHint(LiveInterval &li) { li.weight = normalizeSpillWeight(totalWeight, li.getSize()); } - -void VirtRegAuxInfo::CalculateRegClass(unsigned reg) { - MachineRegisterInfo &MRI = MF.getRegInfo(); - const TargetInstrInfo *TII = MF.getTarget().getInstrInfo(); - const TargetRegisterInfo *TRI = MF.getTarget().getRegisterInfo(); - const TargetRegisterClass *OldRC = MRI.getRegClass(reg); - const TargetRegisterClass *NewRC = TRI->getLargestLegalSuperClass(OldRC); - - // Stop early if there is no room to grow. - if (NewRC == OldRC) - return; - - // Accumulate constraints from all uses. - for (MachineRegisterInfo::reg_nodbg_iterator I = MRI.reg_nodbg_begin(reg), - E = MRI.reg_nodbg_end(); I != E; ++I) { - // TRI doesn't have accurate enough information to model this yet. - if (I.getOperand().getSubReg()) - return; - // Inline asm instuctions don't remember their constraints. - if (I->isInlineAsm()) - return; - const TargetRegisterClass *OpRC = - TII->getRegClass(I->getDesc(), I.getOperandNo(), TRI); - if (OpRC) - NewRC = getCommonSubClass(NewRC, OpRC); - if (!NewRC || NewRC == OldRC) - return; - } - DEBUG(dbgs() << "Inflating " << OldRC->getName() << ':' << PrintReg(reg) - << " to " << NewRC->getName() <<".\n"); - MRI.setRegClass(reg, NewRC); -} diff --git a/contrib/llvm/lib/CodeGen/CodeGen.cpp b/contrib/llvm/lib/CodeGen/CodeGen.cpp index 489746cf3..424535ba2 100644 --- a/contrib/llvm/lib/CodeGen/CodeGen.cpp +++ b/contrib/llvm/lib/CodeGen/CodeGen.cpp @@ -27,6 +27,7 @@ void llvm::initializeCodeGen(PassRegistry &Registry) { initializeLiveIntervalsPass(Registry); initializeLiveStacksPass(Registry); initializeLiveVariablesPass(Registry); + initializeMachineBlockFrequencyInfoPass(Registry); initializeMachineCSEPass(Registry); initializeMachineDominatorTreePass(Registry); initializeMachineLICMPass(Registry); diff --git a/contrib/llvm/lib/CodeGen/DwarfEHPrepare.cpp b/contrib/llvm/lib/CodeGen/DwarfEHPrepare.cpp index 03604b0a1..ed9e409d3 100644 --- a/contrib/llvm/lib/CodeGen/DwarfEHPrepare.cpp +++ b/contrib/llvm/lib/CodeGen/DwarfEHPrepare.cpp @@ -63,6 +63,8 @@ namespace { typedef SmallPtrSet BBSet; BBSet LandingPads; + bool InsertUnwindResumeCalls(); + bool NormalizeLandingPads(); bool LowerUnwindsAndResumes(); bool MoveExceptionValueCalls(); @@ -658,13 +660,76 @@ Instruction *DwarfEHPrepare::CreateExceptionValueCall(BasicBlock *BB) { return CallInst::Create(ExceptionValueIntrinsic, "eh.value.call", Start); } +/// InsertUnwindResumeCalls - Convert the ResumeInsts that are still present +/// into calls to the appropriate _Unwind_Resume function. +bool DwarfEHPrepare::InsertUnwindResumeCalls() { + bool UsesNewEH = false; + SmallVector Resumes; + for (Function::iterator I = F->begin(), E = F->end(); I != E; ++I) { + TerminatorInst *TI = I->getTerminator(); + if (ResumeInst *RI = dyn_cast(TI)) + Resumes.push_back(RI); + else if (InvokeInst *II = dyn_cast(TI)) + UsesNewEH = II->getUnwindDest()->isLandingPad(); + } + + if (Resumes.empty()) + return UsesNewEH; + + // Find the rewind function if we didn't already. + if (!RewindFunction) { + LLVMContext &Ctx = Resumes[0]->getContext(); + FunctionType *FTy = FunctionType::get(Type::getVoidTy(Ctx), + Type::getInt8PtrTy(Ctx), false); + const char *RewindName = TLI->getLibcallName(RTLIB::UNWIND_RESUME); + RewindFunction = F->getParent()->getOrInsertFunction(RewindName, FTy); + } + + // Create the basic block where the _Unwind_Resume call will live. + LLVMContext &Ctx = F->getContext(); + BasicBlock *UnwindBB = BasicBlock::Create(Ctx, "unwind_resume", F); + PHINode *PN = PHINode::Create(Type::getInt8PtrTy(Ctx), Resumes.size(), + "exn.obj", UnwindBB); + + // Extract the exception object from the ResumeInst and add it to the PHI node + // that feeds the _Unwind_Resume call. + BasicBlock *UnwindBBDom = Resumes[0]->getParent(); + for (SmallVectorImpl::iterator + I = Resumes.begin(), E = Resumes.end(); I != E; ++I) { + ResumeInst *RI = *I; + BranchInst::Create(UnwindBB, RI->getParent()); + ExtractValueInst *ExnObj = ExtractValueInst::Create(RI->getOperand(0), + 0, "exn.obj", RI); + PN->addIncoming(ExnObj, RI->getParent()); + UnwindBBDom = DT->findNearestCommonDominator(RI->getParent(), UnwindBBDom); + RI->eraseFromParent(); + } + + // Call the function. + CallInst *CI = CallInst::Create(RewindFunction, PN, "", UnwindBB); + CI->setCallingConv(TLI->getLibcallCallingConv(RTLIB::UNWIND_RESUME)); + + // We never expect _Unwind_Resume to return. + new UnreachableInst(Ctx, UnwindBB); + + // Now update DominatorTree analysis information. + DT->addNewBlock(UnwindBB, UnwindBBDom); + return true; +} + bool DwarfEHPrepare::runOnFunction(Function &Fn) { bool Changed = false; // Initialize internal state. - DT = &getAnalysis(); + DT = &getAnalysis(); // FIXME: We won't need this with the new EH. F = &Fn; + if (InsertUnwindResumeCalls()) { + // FIXME: The reset of this function can go once the new EH is done. + LandingPads.clear(); + return true; + } + // Ensure that only unwind edges end at landing pads (a landing pad is a // basic block where an invoke unwind edge ends). Changed |= NormalizeLandingPads(); diff --git a/contrib/llvm/lib/CodeGen/ELFCodeEmitter.cpp b/contrib/llvm/lib/CodeGen/ELFCodeEmitter.cpp index 3fb087c5e..660424c3c 100644 --- a/contrib/llvm/lib/CodeGen/ELFCodeEmitter.cpp +++ b/contrib/llvm/lib/CodeGen/ELFCodeEmitter.cpp @@ -155,7 +155,7 @@ void ELFCodeEmitter::emitConstantPool(MachineConstantPool *MCP) { CPSections.push_back(CstPool.SectionIdx); if (CPE.isMachineConstantPoolEntry()) - assert("CPE.isMachineConstantPoolEntry not supported yet"); + assert(0 && "CPE.isMachineConstantPoolEntry not supported yet"); // Emit the constant to constant pool section EW.EmitGlobalConstant(CPE.Val.ConstVal, CstPool); diff --git a/contrib/llvm/lib/CodeGen/ELFCodeEmitter.h b/contrib/llvm/lib/CodeGen/ELFCodeEmitter.h index 2ec1f6e87..8671c674e 100644 --- a/contrib/llvm/lib/CodeGen/ELFCodeEmitter.h +++ b/contrib/llvm/lib/CodeGen/ELFCodeEmitter.h @@ -58,13 +58,13 @@ namespace llvm { /// emitLabel - Emits a label virtual void emitLabel(MCSymbol *Label) { - assert("emitLabel not implemented"); + assert(0 && "emitLabel not implemented"); } /// getLabelAddress - Return the address of the specified LabelID, /// only usable after the LabelID has been emitted. virtual uintptr_t getLabelAddress(MCSymbol *Label) const { - assert("getLabelAddress not implemented"); + assert(0 && "getLabelAddress not implemented"); return 0; } diff --git a/contrib/llvm/lib/CodeGen/ELFWriter.cpp b/contrib/llvm/lib/CodeGen/ELFWriter.cpp index d977651c3..f2c218565 100644 --- a/contrib/llvm/lib/CodeGen/ELFWriter.cpp +++ b/contrib/llvm/lib/CodeGen/ELFWriter.cpp @@ -45,12 +45,12 @@ #include "llvm/MC/MCSectionELF.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/Target/Mangler.h" -#include "llvm/Target/TargetAsmInfo.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetELFWriterInfo.h" #include "llvm/Target/TargetLowering.h" #include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetRegisterInfo.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" @@ -65,7 +65,8 @@ char ELFWriter::ID = 0; ELFWriter::ELFWriter(raw_ostream &o, TargetMachine &tm) : MachineFunctionPass(ID), O(o), TM(tm), - OutContext(*new MCContext(*TM.getMCAsmInfo(), new TargetAsmInfo(tm))), + OutContext(*new MCContext(*TM.getMCAsmInfo(), *TM.getRegisterInfo(), + &TM.getTargetLowering()->getObjFileLowering())), TLOF(TM.getTargetLowering()->getObjFileLowering()), is64Bit(TM.getTargetData()->getPointerSizeInBits() == 64), isLittleEndian(TM.getTargetData()->isLittleEndian()), @@ -482,7 +483,7 @@ void ELFWriter::EmitGlobalConstant(const Constant *CV, ELFSection &GblS) { EmitGlobalConstantLargeInt(CI, GblS); return; } else if (const ConstantVector *CP = dyn_cast(CV)) { - const VectorType *PTy = CP->getType(); + VectorType *PTy = CP->getType(); for (unsigned I = 0, E = PTy->getNumElements(); I < E; ++I) EmitGlobalConstant(CP->getOperand(I), GblS); return; @@ -540,8 +541,7 @@ CstExprResTy ELFWriter::ResolveConstantExpr(const Constant *CV) { case Instruction::GetElementPtr: { const Constant *ptrVal = CE->getOperand(0); SmallVector idxVec(CE->op_begin()+1, CE->op_end()); - int64_t Offset = TD->getIndexedOffset(ptrVal->getType(), &idxVec[0], - idxVec.size()); + int64_t Offset = TD->getIndexedOffset(ptrVal->getType(), idxVec); return std::make_pair(ptrVal, Offset); } case Instruction::IntToPtr: { @@ -552,7 +552,7 @@ CstExprResTy ELFWriter::ResolveConstantExpr(const Constant *CV) { } case Instruction::PtrToInt: { Constant *Op = CE->getOperand(0); - const Type *Ty = CE->getType(); + Type *Ty = CE->getType(); // We can emit the pointer value into this slot if the slot is an // integer slot greater or equal to the size of the pointer. diff --git a/contrib/llvm/lib/Target/X86/SSEDomainFix.cpp b/contrib/llvm/lib/CodeGen/ExecutionDepsFix.cpp similarity index 84% rename from contrib/llvm/lib/Target/X86/SSEDomainFix.cpp rename to contrib/llvm/lib/CodeGen/ExecutionDepsFix.cpp index 13680c592..01dccdb71 100644 --- a/contrib/llvm/lib/Target/X86/SSEDomainFix.cpp +++ b/contrib/llvm/lib/CodeGen/ExecutionDepsFix.cpp @@ -1,4 +1,4 @@ -//===- SSEDomainFix.cpp - Use proper int/float domain for SSE ---*- C++ -*-===// +//===- ExecutionDepsFix.cpp - Fix execution dependecy issues ----*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -7,21 +7,25 @@ // //===----------------------------------------------------------------------===// // -// This file contains the SSEDomainFix pass. +// This file contains the execution dependency fix pass. // -// Some SSE instructions like mov, and, or, xor are available in different +// Some X86 SSE instructions like mov, and, or, xor are available in different // variants for different operand types. These variant instructions are // equivalent, but on Nehalem and newer cpus there is extra latency -// transferring data between integer and floating point domains. +// transferring data between integer and floating point domains. ARM cores +// have similar issues when they are configured with both VFP and NEON +// pipelines. // // This pass changes the variant instructions to minimize domain crossings. // //===----------------------------------------------------------------------===// -#define DEBUG_TYPE "sse-domain-fix" -#include "X86InstrInfo.h" +#define DEBUG_TYPE "execution-fix" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetMachine.h" #include "llvm/ADT/DepthFirstIterator.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/Debug.h" @@ -97,25 +101,27 @@ struct DomainValue { }; } -static const unsigned NumRegs = 16; - namespace { -class SSEDomainFixPass : public MachineFunctionPass { +class ExeDepsFix : public MachineFunctionPass { static char ID; SpecificBumpPtrAllocator Allocator; SmallVector Avail; + const TargetRegisterClass *const RC; MachineFunction *MF; - const X86InstrInfo *TII; + const TargetInstrInfo *TII; const TargetRegisterInfo *TRI; MachineBasicBlock *MBB; + std::vector AliasMap; + const unsigned NumRegs; DomainValue **LiveRegs; typedef DenseMap LiveOutMap; LiveOutMap LiveOuts; unsigned Distance; public: - SSEDomainFixPass() : MachineFunctionPass(ID) {} + ExeDepsFix(const TargetRegisterClass *rc) + : MachineFunctionPass(ID), RC(rc), NumRegs(RC->getNumRegs()) {} virtual void getAnalysisUsage(AnalysisUsage &AU) const { AU.setPreservesAll(); @@ -150,17 +156,16 @@ private: }; } -char SSEDomainFixPass::ID = 0; +char ExeDepsFix::ID = 0; /// Translate TRI register number to an index into our smaller tables of /// interesting registers. Return -1 for boring registers. -int SSEDomainFixPass::RegIndex(unsigned reg) { - assert(X86::XMM15 == X86::XMM0+NumRegs-1 && "Unexpected sort"); - reg -= X86::XMM0; - return reg < NumRegs ? (int) reg : -1; +int ExeDepsFix::RegIndex(unsigned Reg) { + assert(Reg < AliasMap.size() && "Invalid register"); + return AliasMap[Reg]; } -DomainValue *SSEDomainFixPass::Alloc(int domain) { +DomainValue *ExeDepsFix::Alloc(int domain) { DomainValue *dv = Avail.empty() ? new(Allocator.Allocate()) DomainValue : Avail.pop_back_val(); @@ -170,14 +175,14 @@ DomainValue *SSEDomainFixPass::Alloc(int domain) { return dv; } -void SSEDomainFixPass::Recycle(DomainValue *dv) { +void ExeDepsFix::Recycle(DomainValue *dv) { assert(dv && "Cannot recycle NULL"); dv->clear(); Avail.push_back(dv); } /// Set LiveRegs[rx] = dv, updating reference counts. -void SSEDomainFixPass::SetLiveReg(int rx, DomainValue *dv) { +void ExeDepsFix::SetLiveReg(int rx, DomainValue *dv) { assert(unsigned(rx) < NumRegs && "Invalid index"); if (!LiveRegs) { LiveRegs = new DomainValue*[NumRegs]; @@ -195,7 +200,7 @@ void SSEDomainFixPass::SetLiveReg(int rx, DomainValue *dv) { } // Kill register rx, recycle or collapse any DomainValue. -void SSEDomainFixPass::Kill(int rx) { +void ExeDepsFix::Kill(int rx) { assert(unsigned(rx) < NumRegs && "Invalid index"); if (!LiveRegs || !LiveRegs[rx]) return; @@ -208,7 +213,7 @@ void SSEDomainFixPass::Kill(int rx) { } /// Force register rx into domain. -void SSEDomainFixPass::Force(int rx, unsigned domain) { +void ExeDepsFix::Force(int rx, unsigned domain) { assert(unsigned(rx) < NumRegs && "Invalid index"); DomainValue *dv; if (LiveRegs && (dv = LiveRegs[rx])) { @@ -217,8 +222,8 @@ void SSEDomainFixPass::Force(int rx, unsigned domain) { else if (dv->hasDomain(domain)) Collapse(dv, domain); else { - // This is an incompatible open DomainValue. Collapse it to whatever and force - // the new value into domain. This costs a domain crossing. + // This is an incompatible open DomainValue. Collapse it to whatever and + // force the new value into domain. This costs a domain crossing. Collapse(dv, dv->getFirstDomain()); assert(LiveRegs[rx] && "Not live after collapse?"); LiveRegs[rx]->addDomain(domain); @@ -231,12 +236,12 @@ void SSEDomainFixPass::Force(int rx, unsigned domain) { /// Collapse open DomainValue into given domain. If there are multiple /// registers using dv, they each get a unique collapsed DomainValue. -void SSEDomainFixPass::Collapse(DomainValue *dv, unsigned domain) { +void ExeDepsFix::Collapse(DomainValue *dv, unsigned domain) { assert(dv->hasDomain(domain) && "Cannot collapse"); // Collapse all the instructions. while (!dv->Instrs.empty()) - TII->SetSSEDomain(dv->Instrs.pop_back_val(), domain); + TII->setExecutionDomain(dv->Instrs.pop_back_val(), domain); dv->setSingleDomain(domain); // If there are multiple users, give them new, unique DomainValues. @@ -248,7 +253,7 @@ void SSEDomainFixPass::Collapse(DomainValue *dv, unsigned domain) { /// Merge - All instructions and registers in B are moved to A, and B is /// released. -bool SSEDomainFixPass::Merge(DomainValue *A, DomainValue *B) { +bool ExeDepsFix::Merge(DomainValue *A, DomainValue *B) { assert(!A->isCollapsed() && "Cannot merge into collapsed"); assert(!B->isCollapsed() && "Cannot merge from collapsed"); if (A == B) @@ -266,7 +271,7 @@ bool SSEDomainFixPass::Merge(DomainValue *A, DomainValue *B) { return true; } -void SSEDomainFixPass::enterBasicBlock() { +void ExeDepsFix::enterBasicBlock() { // Try to coalesce live-out registers from predecessors. for (MachineBasicBlock::livein_iterator i = MBB->livein_begin(), e = MBB->livein_end(); i != e; ++i) { @@ -303,7 +308,7 @@ void SSEDomainFixPass::enterBasicBlock() { // A hard instruction only works in one domain. All input registers will be // forced into that domain. -void SSEDomainFixPass::visitHardInstr(MachineInstr *mi, unsigned domain) { +void ExeDepsFix::visitHardInstr(MachineInstr *mi, unsigned domain) { // Collapse all uses. for (unsigned i = mi->getDesc().getNumDefs(), e = mi->getDesc().getNumOperands(); i != e; ++i) { @@ -326,7 +331,7 @@ void SSEDomainFixPass::visitHardInstr(MachineInstr *mi, unsigned domain) { } // A soft instruction can be changed to work in other domains given by mask. -void SSEDomainFixPass::visitSoftInstr(MachineInstr *mi, unsigned mask) { +void ExeDepsFix::visitSoftInstr(MachineInstr *mi, unsigned mask) { // Bitmask of available domains for this instruction after taking collapsed // operands into account. unsigned available = mask; @@ -362,7 +367,7 @@ void SSEDomainFixPass::visitSoftInstr(MachineInstr *mi, unsigned mask) { // If the collapsed operands force a single domain, propagate the collapse. if (isPowerOf2_32(available)) { unsigned domain = CountTrailingZeros_32(available); - TII->SetSSEDomain(mi, domain); + TII->setExecutionDomain(mi, domain); visitHardInstr(mi, domain); return; } @@ -431,8 +436,8 @@ void SSEDomainFixPass::visitSoftInstr(MachineInstr *mi, unsigned mask) { } } -void SSEDomainFixPass::visitGenericInstr(MachineInstr *mi) { - // Process explicit defs, kill any XMM registers redefined. +void ExeDepsFix::visitGenericInstr(MachineInstr *mi) { + // Process explicit defs, kill any relevant registers redefined. for (unsigned i = 0, e = mi->getDesc().getNumDefs(); i != e; ++i) { MachineOperand &mo = mi->getOperand(i); if (!mo.isReg()) continue; @@ -442,25 +447,36 @@ void SSEDomainFixPass::visitGenericInstr(MachineInstr *mi) { } } -bool SSEDomainFixPass::runOnMachineFunction(MachineFunction &mf) { +bool ExeDepsFix::runOnMachineFunction(MachineFunction &mf) { MF = &mf; - TII = static_cast(MF->getTarget().getInstrInfo()); + TII = MF->getTarget().getInstrInfo(); TRI = MF->getTarget().getRegisterInfo(); MBB = 0; LiveRegs = 0; Distance = 0; - assert(NumRegs == X86::VR128RegClass.getNumRegs() && "Bad regclass"); + assert(NumRegs == RC->getNumRegs() && "Bad regclass"); - // If no XMM registers are used in the function, we can skip it completely. + // If no relevant registers are used in the function, we can skip it + // completely. bool anyregs = false; - for (TargetRegisterClass::const_iterator I = X86::VR128RegClass.begin(), - E = X86::VR128RegClass.end(); I != E; ++I) + for (TargetRegisterClass::const_iterator I = RC->begin(), E = RC->end(); + I != E; ++I) if (MF->getRegInfo().isPhysRegUsed(*I)) { anyregs = true; break; } if (!anyregs) return false; + // Initialize the AliasMap on the first use. + if (AliasMap.empty()) { + // Given a PhysReg, AliasMap[PhysReg] is either the relevant index into RC, + // or -1. + AliasMap.resize(TRI->getNumRegs(), -1); + for (unsigned i = 0, e = RC->getNumRegs(); i != e; ++i) + for (const unsigned *AI = TRI->getOverlaps(RC->getRegister(i)); *AI; ++AI) + AliasMap[*AI] = i; + } + MachineBasicBlock *Entry = MF->begin(); SmallPtrSet Visited; for (df_ext_iterator > @@ -473,7 +489,7 @@ bool SSEDomainFixPass::runOnMachineFunction(MachineFunction &mf) { MachineInstr *mi = I; if (mi->isDebugValue()) continue; ++Distance; - std::pair domp = TII->GetSSEDomain(mi); + std::pair domp = TII->getExecutionDomain(mi); if (domp.first) if (domp.second) visitSoftInstr(mi, domp.second); @@ -501,6 +517,7 @@ bool SSEDomainFixPass::runOnMachineFunction(MachineFunction &mf) { return false; } -FunctionPass *llvm::createSSEDomainFixPass() { - return new SSEDomainFixPass(); +FunctionPass * +llvm::createExecutionDependencyFixPass(const TargetRegisterClass *RC) { + return new ExeDepsFix(RC); } diff --git a/contrib/llvm/lib/CodeGen/LowerSubregs.cpp b/contrib/llvm/lib/CodeGen/ExpandPostRAPseudos.cpp similarity index 69% rename from contrib/llvm/lib/CodeGen/LowerSubregs.cpp rename to contrib/llvm/lib/CodeGen/ExpandPostRAPseudos.cpp index 7871ba9c1..e2a14a8df 100644 --- a/contrib/llvm/lib/CodeGen/LowerSubregs.cpp +++ b/contrib/llvm/lib/CodeGen/ExpandPostRAPseudos.cpp @@ -1,4 +1,4 @@ -//===-- LowerSubregs.cpp - Subregister Lowering instruction pass ----------===// +//===-- ExpandPostRAPseudos.cpp - Pseudo instruction expansion pass -------===// // // The LLVM Compiler Infrastructure // @@ -7,14 +7,12 @@ // //===----------------------------------------------------------------------===// // -// This file defines a MachineFunction pass which runs after register -// allocation that turns subreg insert/extract instructions into register -// copies, as needed. This ensures correct codegen even if the coalescer -// isn't able to remove all subreg instructions. +// This file defines a pass that expands COPY and SUBREG_TO_REG pseudo +// instructions after register allocation. // //===----------------------------------------------------------------------===// -#define DEBUG_TYPE "lowersubregs" +#define DEBUG_TYPE "postrapseudos" #include "llvm/CodeGen/Passes.h" #include "llvm/Function.h" #include "llvm/CodeGen/MachineFunctionPass.h" @@ -29,52 +27,51 @@ using namespace llvm; namespace { - struct LowerSubregsInstructionPass : public MachineFunctionPass { - private: - const TargetRegisterInfo *TRI; - const TargetInstrInfo *TII; +struct ExpandPostRA : public MachineFunctionPass { +private: + const TargetRegisterInfo *TRI; + const TargetInstrInfo *TII; - public: - static char ID; // Pass identification, replacement for typeid - LowerSubregsInstructionPass() : MachineFunctionPass(ID) {} +public: + static char ID; // Pass identification, replacement for typeid + ExpandPostRA() : MachineFunctionPass(ID) {} - const char *getPassName() const { - return "Subregister lowering instruction pass"; - } + const char *getPassName() const { + return "Post-RA pseudo instruction expansion pass"; + } - virtual void getAnalysisUsage(AnalysisUsage &AU) const { - AU.setPreservesCFG(); - AU.addPreservedID(MachineLoopInfoID); - AU.addPreservedID(MachineDominatorsID); - MachineFunctionPass::getAnalysisUsage(AU); - } + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesCFG(); + AU.addPreservedID(MachineLoopInfoID); + AU.addPreservedID(MachineDominatorsID); + MachineFunctionPass::getAnalysisUsage(AU); + } - /// runOnMachineFunction - pass entry point - bool runOnMachineFunction(MachineFunction&); + /// runOnMachineFunction - pass entry point + bool runOnMachineFunction(MachineFunction&); - private: - bool LowerSubregToReg(MachineInstr *MI); - bool LowerCopy(MachineInstr *MI); +private: + bool LowerSubregToReg(MachineInstr *MI); + bool LowerCopy(MachineInstr *MI); - void TransferDeadFlag(MachineInstr *MI, unsigned DstReg, - const TargetRegisterInfo *TRI); - void TransferImplicitDefs(MachineInstr *MI); - }; + void TransferDeadFlag(MachineInstr *MI, unsigned DstReg, + const TargetRegisterInfo *TRI); + void TransferImplicitDefs(MachineInstr *MI); +}; +} // end anonymous namespace - char LowerSubregsInstructionPass::ID = 0; -} +char ExpandPostRA::ID = 0; -FunctionPass *llvm::createLowerSubregsPass() { - return new LowerSubregsInstructionPass(); +FunctionPass *llvm::createExpandPostRAPseudosPass() { + return new ExpandPostRA(); } /// TransferDeadFlag - MI is a pseudo-instruction with DstReg dead, /// and the lowered replacement instructions immediately precede it. /// Mark the replacement instructions with the dead flag. void -LowerSubregsInstructionPass::TransferDeadFlag(MachineInstr *MI, - unsigned DstReg, - const TargetRegisterInfo *TRI) { +ExpandPostRA::TransferDeadFlag(MachineInstr *MI, unsigned DstReg, + const TargetRegisterInfo *TRI) { for (MachineBasicBlock::iterator MII = prior(MachineBasicBlock::iterator(MI)); ; --MII) { if (MII->addRegisterDead(DstReg, TRI)) @@ -88,7 +85,7 @@ LowerSubregsInstructionPass::TransferDeadFlag(MachineInstr *MI, /// replacement instructions immediately precede it. Copy any implicit-def /// operands from MI to the replacement instruction. void -LowerSubregsInstructionPass::TransferImplicitDefs(MachineInstr *MI) { +ExpandPostRA::TransferImplicitDefs(MachineInstr *MI) { MachineBasicBlock::iterator CopyMI = MI; --CopyMI; @@ -100,7 +97,7 @@ LowerSubregsInstructionPass::TransferImplicitDefs(MachineInstr *MI) { } } -bool LowerSubregsInstructionPass::LowerSubregToReg(MachineInstr *MI) { +bool ExpandPostRA::LowerSubregToReg(MachineInstr *MI) { MachineBasicBlock *MBB = MI->getParent(); assert((MI->getOperand(0).isReg() && MI->getOperand(0).isDef()) && MI->getOperand(1).isImm() && @@ -152,7 +149,7 @@ bool LowerSubregsInstructionPass::LowerSubregToReg(MachineInstr *MI) { return true; } -bool LowerSubregsInstructionPass::LowerCopy(MachineInstr *MI) { +bool ExpandPostRA::LowerCopy(MachineInstr *MI) { MachineOperand &DstMO = MI->getOperand(0); MachineOperand &SrcMO = MI->getOperand(1); @@ -191,9 +188,9 @@ bool LowerSubregsInstructionPass::LowerCopy(MachineInstr *MI) { /// runOnMachineFunction - Reduce subregister inserts and extracts to register /// copies. /// -bool LowerSubregsInstructionPass::runOnMachineFunction(MachineFunction &MF) { +bool ExpandPostRA::runOnMachineFunction(MachineFunction &MF) { DEBUG(dbgs() << "Machine Function\n" - << "********** LOWERING SUBREG INSTRS **********\n" + << "********** EXPANDING POST-RA PSEUDO INSTRS **********\n" << "********** Function: " << MF.getFunction()->getName() << '\n'); TRI = MF.getTarget().getRegisterInfo(); @@ -205,17 +202,34 @@ bool LowerSubregsInstructionPass::runOnMachineFunction(MachineFunction &MF) { mbbi != mbbe; ++mbbi) { for (MachineBasicBlock::iterator mi = mbbi->begin(), me = mbbi->end(); mi != me;) { - MachineBasicBlock::iterator nmi = llvm::next(mi); MachineInstr *MI = mi; - assert(!MI->isInsertSubreg() && "INSERT_SUBREG should no longer appear"); - assert(MI->getOpcode() != TargetOpcode::EXTRACT_SUBREG && - "EXTRACT_SUBREG should no longer appear"); - if (MI->isSubregToReg()) { + // Advance iterator here because MI may be erased. + ++mi; + + // Only expand pseudos. + if (!MI->getDesc().isPseudo()) + continue; + + // Give targets a chance to expand even standard pseudos. + if (TII->expandPostRAPseudo(MI)) { + MadeChange = true; + continue; + } + + // Expand standard pseudos. + switch (MI->getOpcode()) { + case TargetOpcode::SUBREG_TO_REG: MadeChange |= LowerSubregToReg(MI); - } else if (MI->isCopy()) { + break; + case TargetOpcode::COPY: MadeChange |= LowerCopy(MI); + break; + case TargetOpcode::DBG_VALUE: + continue; + case TargetOpcode::INSERT_SUBREG: + case TargetOpcode::EXTRACT_SUBREG: + llvm_unreachable("Sub-register pseudos should have been eliminated."); } - mi = nmi; } } diff --git a/contrib/llvm/lib/CodeGen/IfConversion.cpp b/contrib/llvm/lib/CodeGen/IfConversion.cpp index 6cb22778c..ce7ed293d 100644 --- a/contrib/llvm/lib/CodeGen/IfConversion.cpp +++ b/contrib/llvm/lib/CodeGen/IfConversion.cpp @@ -16,14 +16,13 @@ #include "llvm/Function.h" #include "llvm/CodeGen/Passes.h" #include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/MachineBranchProbabilityInfo.h" #include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/CodeGen/MachineLoopInfo.h" #include "llvm/MC/MCInstrItineraries.h" #include "llvm/Target/TargetInstrInfo.h" #include "llvm/Target/TargetLowering.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetRegisterInfo.h" -#include "llvm/Support/BranchProbability.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" @@ -154,7 +153,8 @@ namespace { const TargetInstrInfo *TII; const TargetRegisterInfo *TRI; const InstrItineraryData *InstrItins; - const MachineLoopInfo *MLI; + const MachineBranchProbabilityInfo *MBPI; + bool MadeChange; int FnNum; public: @@ -162,9 +162,9 @@ namespace { IfConverter() : MachineFunctionPass(ID), FnNum(-1) { initializeIfConverterPass(*PassRegistry::getPassRegistry()); } - + virtual void getAnalysisUsage(AnalysisUsage &AU) const { - AU.addRequired(); + AU.addRequired(); MachineFunctionPass::getAnalysisUsage(AU); } @@ -252,7 +252,7 @@ namespace { } INITIALIZE_PASS_BEGIN(IfConverter, "if-converter", "If Converter", false, false) -INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo) +INITIALIZE_PASS_DEPENDENCY(MachineBranchProbabilityInfo) INITIALIZE_PASS_END(IfConverter, "if-converter", "If Converter", false, false) FunctionPass *llvm::createIfConverterPass() { return new IfConverter(); } @@ -261,7 +261,7 @@ bool IfConverter::runOnMachineFunction(MachineFunction &MF) { TLI = MF.getTarget().getTargetLowering(); TII = MF.getTarget().getInstrInfo(); TRI = MF.getTarget().getRegisterInfo(); - MLI = &getAnalysis(); + MBPI = &getAnalysis(); InstrItins = MF.getTarget().getInstrItineraryData(); if (!TII) return false; @@ -790,28 +790,9 @@ IfConverter::BBInfo &IfConverter::AnalyzeBlock(MachineBasicBlock *BB, bool TNeedSub = TrueBBI.Predicate.size() > 0; bool FNeedSub = FalseBBI.Predicate.size() > 0; bool Enqueued = false; - - // Try to predict the branch, using loop info to guide us. - // General heuristics are: - // - backedge -> 90% taken - // - early exit -> 20% taken - // - branch predictor confidence -> 90% - BranchProbability Prediction(5, 10); - MachineLoop *Loop = MLI->getLoopFor(BB); - if (Loop) { - if (TrueBBI.BB == Loop->getHeader()) - Prediction = BranchProbability(9, 10); - else if (FalseBBI.BB == Loop->getHeader()) - Prediction = BranchProbability(1, 10); - - MachineLoop *TrueLoop = MLI->getLoopFor(TrueBBI.BB); - MachineLoop *FalseLoop = MLI->getLoopFor(FalseBBI.BB); - if (!TrueLoop || TrueLoop->getParentLoop() == Loop) - Prediction = BranchProbability(2, 10); - else if (!FalseLoop || FalseLoop->getParentLoop() == Loop) - Prediction = BranchProbability(8, 10); - } - + + BranchProbability Prediction = MBPI->getEdgeProbability(BB, TrueBBI.BB); + if (CanRevCond && ValidDiamond(TrueBBI, FalseBBI, Dups, Dups2) && MeetIfcvtSizeLimit(*TrueBBI.BB, (TrueBBI.NonPredSize - (Dups + Dups2) + TrueBBI.ExtraCost), TrueBBI.ExtraCost2, diff --git a/contrib/llvm/lib/CodeGen/InlineSpiller.cpp b/contrib/llvm/lib/CodeGen/InlineSpiller.cpp index 5547f735b..726af4696 100644 --- a/contrib/llvm/lib/CodeGen/InlineSpiller.cpp +++ b/contrib/llvm/lib/CodeGen/InlineSpiller.cpp @@ -17,6 +17,7 @@ #include "LiveRangeEdit.h" #include "VirtRegMap.h" #include "llvm/ADT/Statistic.h" +#include "llvm/ADT/TinyPtrVector.h" #include "llvm/Analysis/AliasAnalysis.h" #include "llvm/CodeGen/LiveIntervalAnalysis.h" #include "llvm/CodeGen/LiveStackAnalysis.h" @@ -27,22 +28,26 @@ #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; STATISTIC(NumSpilledRanges, "Number of spilled live ranges"); -STATISTIC(NumSnippets, "Number of snippets included in spills"); +STATISTIC(NumSnippets, "Number of spilled snippets"); STATISTIC(NumSpills, "Number of spills inserted"); +STATISTIC(NumSpillsRemoved, "Number of spills removed"); STATISTIC(NumReloads, "Number of reloads inserted"); +STATISTIC(NumReloadsRemoved, "Number of reloads removed"); STATISTIC(NumFolded, "Number of folded stack accesses"); STATISTIC(NumFoldedLoads, "Number of folded loads"); STATISTIC(NumRemats, "Number of rematerialized defs for spilling"); -STATISTIC(NumOmitReloadSpill, "Number of omitted spills after reloads"); -STATISTIC(NumHoistLocal, "Number of locally hoisted spills"); -STATISTIC(NumHoistGlobal, "Number of globally hoisted spills"); -STATISTIC(NumRedundantSpills, "Number of redundant spills identified"); +STATISTIC(NumOmitReloadSpill, "Number of omitted spills of reloads"); +STATISTIC(NumHoists, "Number of hoisted spills"); + +static cl::opt DisableHoisting("disable-spill-hoist", cl::Hidden, + cl::desc("Disable inline spill hoisting")); namespace { class InlineSpiller : public Spiller { @@ -75,26 +80,49 @@ class InlineSpiller : public Spiller { // Values that failed to remat at some point. SmallPtrSet UsedValues; +public: // Information about a value that was defined by a copy from a sibling // register. struct SibValueInfo { // True when all reaching defs were reloads: No spill is necessary. bool AllDefsAreReloads; + // True when value is defined by an original PHI not from splitting. + bool DefByOrigPHI; + + // True when the COPY defining this value killed its source. + bool KillsSource; + // The preferred register to spill. unsigned SpillReg; // The value of SpillReg that should be spilled. VNInfo *SpillVNI; + // The block where SpillVNI should be spilled. Currently, this must be the + // block containing SpillVNI->def. + MachineBasicBlock *SpillMBB; + // A defining instruction that is not a sibling copy or a reload, or NULL. // This can be used as a template for rematerialization. MachineInstr *DefMI; + // List of values that depend on this one. These values are actually the + // same, but live range splitting has placed them in different registers, + // or SSA update needed to insert PHI-defs to preserve SSA form. This is + // copies of the current value and phi-kills. Usually only phi-kills cause + // more than one dependent value. + TinyPtrVector Deps; + SibValueInfo(unsigned Reg, VNInfo *VNI) - : AllDefsAreReloads(false), SpillReg(Reg), SpillVNI(VNI), DefMI(0) {} + : AllDefsAreReloads(true), DefByOrigPHI(false), KillsSource(false), + SpillReg(Reg), SpillVNI(VNI), SpillMBB(0), DefMI(0) {} + + // Returns true when a def has been found. + bool hasDef() const { return DefByOrigPHI || DefMI; } }; +private: // Values in RegsToSpill defined by sibling copies. typedef DenseMap SibValueMap; SibValueMap SibValues; @@ -134,6 +162,7 @@ private: bool isSibling(unsigned Reg); MachineInstr *traceSiblingValue(unsigned, VNInfo*, VNInfo*); + void propagateSiblingValue(SibValueMap::iterator, VNInfo *VNI = 0); void analyzeSiblingValues(); bool hoistSpill(LiveInterval &SpillLI, MachineInstr *CopyMI); @@ -282,6 +311,156 @@ bool InlineSpiller::isSibling(unsigned Reg) { VRM.getOriginal(Reg) == Original; } +#ifndef NDEBUG +static raw_ostream &operator<<(raw_ostream &OS, + const InlineSpiller::SibValueInfo &SVI) { + OS << "spill " << PrintReg(SVI.SpillReg) << ':' + << SVI.SpillVNI->id << '@' << SVI.SpillVNI->def; + if (SVI.SpillMBB) + OS << " in BB#" << SVI.SpillMBB->getNumber(); + if (SVI.AllDefsAreReloads) + OS << " all-reloads"; + if (SVI.DefByOrigPHI) + OS << " orig-phi"; + if (SVI.KillsSource) + OS << " kill"; + OS << " deps["; + for (unsigned i = 0, e = SVI.Deps.size(); i != e; ++i) + OS << ' ' << SVI.Deps[i]->id << '@' << SVI.Deps[i]->def; + OS << " ]"; + if (SVI.DefMI) + OS << " def: " << *SVI.DefMI; + else + OS << '\n'; + return OS; +} +#endif + +/// propagateSiblingValue - Propagate the value in SVI to dependents if it is +/// known. Otherwise remember the dependency for later. +/// +/// @param SVI SibValues entry to propagate. +/// @param VNI Dependent value, or NULL to propagate to all saved dependents. +void InlineSpiller::propagateSiblingValue(SibValueMap::iterator SVI, + VNInfo *VNI) { + // When VNI is non-NULL, add it to SVI's deps, and only propagate to that. + TinyPtrVector FirstDeps; + if (VNI) { + FirstDeps.push_back(VNI); + SVI->second.Deps.push_back(VNI); + } + + // Has the value been completely determined yet? If not, defer propagation. + if (!SVI->second.hasDef()) + return; + + // Work list of values to propagate. It would be nice to use a SetVector + // here, but then we would be forced to use a SmallSet. + SmallVector WorkList(1, SVI); + SmallPtrSet WorkSet; + + do { + SVI = WorkList.pop_back_val(); + WorkSet.erase(SVI->first); + TinyPtrVector *Deps = VNI ? &FirstDeps : &SVI->second.Deps; + VNI = 0; + + SibValueInfo &SV = SVI->second; + if (!SV.SpillMBB) + SV.SpillMBB = LIS.getMBBFromIndex(SV.SpillVNI->def); + + DEBUG(dbgs() << " prop to " << Deps->size() << ": " + << SVI->first->id << '@' << SVI->first->def << ":\t" << SV); + + assert(SV.hasDef() && "Propagating undefined value"); + + // Should this value be propagated as a preferred spill candidate? We don't + // propagate values of registers that are about to spill. + bool PropSpill = !DisableHoisting && !isRegToSpill(SV.SpillReg); + unsigned SpillDepth = ~0u; + + for (TinyPtrVector::iterator DepI = Deps->begin(), + DepE = Deps->end(); DepI != DepE; ++DepI) { + SibValueMap::iterator DepSVI = SibValues.find(*DepI); + assert(DepSVI != SibValues.end() && "Dependent value not in SibValues"); + SibValueInfo &DepSV = DepSVI->second; + if (!DepSV.SpillMBB) + DepSV.SpillMBB = LIS.getMBBFromIndex(DepSV.SpillVNI->def); + + bool Changed = false; + + // Propagate defining instruction. + if (!DepSV.hasDef()) { + Changed = true; + DepSV.DefMI = SV.DefMI; + DepSV.DefByOrigPHI = SV.DefByOrigPHI; + } + + // Propagate AllDefsAreReloads. For PHI values, this computes an AND of + // all predecessors. + if (!SV.AllDefsAreReloads && DepSV.AllDefsAreReloads) { + Changed = true; + DepSV.AllDefsAreReloads = false; + } + + // Propagate best spill value. + if (PropSpill && SV.SpillVNI != DepSV.SpillVNI) { + if (SV.SpillMBB == DepSV.SpillMBB) { + // DepSV is in the same block. Hoist when dominated. + if (DepSV.KillsSource && SV.SpillVNI->def < DepSV.SpillVNI->def) { + // This is an alternative def earlier in the same MBB. + // Hoist the spill as far as possible in SpillMBB. This can ease + // register pressure: + // + // x = def + // y = use x + // s = copy x + // + // Hoisting the spill of s to immediately after the def removes the + // interference between x and y: + // + // x = def + // spill x + // y = use x + // + // This hoist only helps when the DepSV copy kills its source. + Changed = true; + DepSV.SpillReg = SV.SpillReg; + DepSV.SpillVNI = SV.SpillVNI; + DepSV.SpillMBB = SV.SpillMBB; + } + } else { + // DepSV is in a different block. + if (SpillDepth == ~0u) + SpillDepth = Loops.getLoopDepth(SV.SpillMBB); + + // Also hoist spills to blocks with smaller loop depth, but make sure + // that the new value dominates. Non-phi dependents are always + // dominated, phis need checking. + if ((Loops.getLoopDepth(DepSV.SpillMBB) > SpillDepth) && + (!DepSVI->first->isPHIDef() || + MDT.dominates(SV.SpillMBB, DepSV.SpillMBB))) { + Changed = true; + DepSV.SpillReg = SV.SpillReg; + DepSV.SpillVNI = SV.SpillVNI; + DepSV.SpillMBB = SV.SpillMBB; + } + } + } + + if (!Changed) + continue; + + // Something changed in DepSVI. Propagate to dependents. + if (WorkSet.insert(DepSVI->first)) + WorkList.push_back(DepSVI); + + DEBUG(dbgs() << " update " << DepSVI->first->id << '@' + << DepSVI->first->def << " to:\t" << DepSV); + } + } while (!WorkList.empty()); +} + /// traceSiblingValue - Trace a value that is about to be spilled back to the /// real defining instructions by looking through sibling copies. Always stay /// within the range of OrigVNI so the registers are known to carry the same @@ -294,84 +473,101 @@ bool InlineSpiller::isSibling(unsigned Reg) { /// MachineInstr *InlineSpiller::traceSiblingValue(unsigned UseReg, VNInfo *UseVNI, VNInfo *OrigVNI) { + // Check if a cached value already exists. + SibValueMap::iterator SVI; + bool Inserted; + tie(SVI, Inserted) = + SibValues.insert(std::make_pair(UseVNI, SibValueInfo(UseReg, UseVNI))); + if (!Inserted) { + DEBUG(dbgs() << "Cached value " << PrintReg(UseReg) << ':' + << UseVNI->id << '@' << UseVNI->def << ' ' << SVI->second); + return SVI->second.DefMI; + } + DEBUG(dbgs() << "Tracing value " << PrintReg(UseReg) << ':' << UseVNI->id << '@' << UseVNI->def << '\n'); - SmallPtrSet Visited; + + // List of (Reg, VNI) that have been inserted into SibValues, but need to be + // processed. SmallVector, 8> WorkList; WorkList.push_back(std::make_pair(UseReg, UseVNI)); - // Best spill candidate seen so far. This must dominate UseVNI. - SibValueInfo SVI(UseReg, UseVNI); - MachineBasicBlock *UseMBB = LIS.getMBBFromIndex(UseVNI->def); - MachineBasicBlock *SpillMBB = UseMBB; - unsigned SpillDepth = Loops.getLoopDepth(SpillMBB); - bool SeenOrigPHI = false; // Original PHI met. - do { unsigned Reg; VNInfo *VNI; tie(Reg, VNI) = WorkList.pop_back_val(); - if (!Visited.insert(VNI)) - continue; + DEBUG(dbgs() << " " << PrintReg(Reg) << ':' << VNI->id << '@' << VNI->def + << ":\t"); - // Is this value a better spill candidate? - if (!isRegToSpill(Reg)) { - MachineBasicBlock *MBB = LIS.getMBBFromIndex(VNI->def); - if (MBB == SpillMBB) { - // This is an alternative def earlier in the same MBB. - // Hoist the spill as far as possible in SpillMBB. This can ease - // register pressure: - // - // x = def - // y = use x - // s = copy x - // - // Hoisting the spill of s to immediately after the def removes the - // interference between x and y: - // - // x = def - // spill x - // y = use x - // - if (VNI->def < SVI.SpillVNI->def) { - DEBUG(dbgs() << " hoist in BB#" << MBB->getNumber() << ": " - << PrintReg(Reg) << ':' << VNI->id << '@' << VNI->def - << '\n'); - SVI.SpillReg = Reg; - SVI.SpillVNI = VNI; - } - } else if (MBB != UseMBB && MDT.dominates(MBB, UseMBB)) { - // This is a valid spill location dominating UseVNI. - // Prefer to spill at a smaller loop depth. - unsigned Depth = Loops.getLoopDepth(MBB); - if (Depth < SpillDepth) { - DEBUG(dbgs() << " spill depth " << Depth << ": " << PrintReg(Reg) - << ':' << VNI->id << '@' << VNI->def << '\n'); - SVI.SpillReg = Reg; - SVI.SpillVNI = VNI; - SpillMBB = MBB; - SpillDepth = Depth; - } - } - } + // First check if this value has already been computed. + SVI = SibValues.find(VNI); + assert(SVI != SibValues.end() && "Missing SibValues entry"); // Trace through PHI-defs created by live range splitting. if (VNI->isPHIDef()) { + // Stop at original PHIs. We don't know the value at the predecessors. if (VNI->def == OrigVNI->def) { - DEBUG(dbgs() << " orig phi value " << PrintReg(Reg) << ':' - << VNI->id << '@' << VNI->def << '\n'); - SeenOrigPHI = true; + DEBUG(dbgs() << "orig phi value\n"); + SVI->second.DefByOrigPHI = true; + SVI->second.AllDefsAreReloads = false; + propagateSiblingValue(SVI); continue; } - // Get values live-out of predecessors. + + // This is a PHI inserted by live range splitting. We could trace the + // live-out value from predecessor blocks, but that search can be very + // expensive if there are many predecessors and many more PHIs as + // generated by tail-dup when it sees an indirectbr. Instead, look at + // all the non-PHI defs that have the same value as OrigVNI. They must + // jointly dominate VNI->def. This is not optimal since VNI may actually + // be jointly dominated by a smaller subset of defs, so there is a change + // we will miss a AllDefsAreReloads optimization. + + // Separate all values dominated by OrigVNI into PHIs and non-PHIs. + SmallVector PHIs, NonPHIs; LiveInterval &LI = LIS.getInterval(Reg); - MachineBasicBlock *MBB = LIS.getMBBFromIndex(VNI->def); - for (MachineBasicBlock::pred_iterator PI = MBB->pred_begin(), - PE = MBB->pred_end(); PI != PE; ++PI) { - VNInfo *PVNI = LI.getVNInfoAt(LIS.getMBBEndIdx(*PI).getPrevSlot()); - if (PVNI) - WorkList.push_back(std::make_pair(Reg, PVNI)); + LiveInterval &OrigLI = LIS.getInterval(Original); + + for (LiveInterval::vni_iterator VI = LI.vni_begin(), VE = LI.vni_end(); + VI != VE; ++VI) { + VNInfo *VNI2 = *VI; + if (VNI2->isUnused()) + continue; + if (!OrigLI.containsOneValue() && + OrigLI.getVNInfoAt(VNI2->def) != OrigVNI) + continue; + if (VNI2->isPHIDef() && VNI2->def != OrigVNI->def) + PHIs.push_back(VNI2); + else + NonPHIs.push_back(VNI2); + } + DEBUG(dbgs() << "split phi value, checking " << PHIs.size() + << " phi-defs, and " << NonPHIs.size() + << " non-phi/orig defs\n"); + + // Create entries for all the PHIs. Don't add them to the worklist, we + // are processing all of them in one go here. + for (unsigned i = 0, e = PHIs.size(); i != e; ++i) + SibValues.insert(std::make_pair(PHIs[i], SibValueInfo(Reg, PHIs[i]))); + + // Add every PHI as a dependent of all the non-PHIs. + for (unsigned i = 0, e = NonPHIs.size(); i != e; ++i) { + VNInfo *NonPHI = NonPHIs[i]; + // Known value? Try an insertion. + tie(SVI, Inserted) = + SibValues.insert(std::make_pair(NonPHI, SibValueInfo(Reg, NonPHI))); + // Add all the PHIs as dependents of NonPHI. + for (unsigned pi = 0, pe = PHIs.size(); pi != pe; ++pi) + SVI->second.Deps.push_back(PHIs[pi]); + // This is the first time we see NonPHI, add it to the worklist. + if (Inserted) + WorkList.push_back(std::make_pair(Reg, NonPHI)); + else + // Propagate to all inserted PHIs, not just VNI. + propagateSiblingValue(SVI); } + + // Next work list item. continue; } @@ -382,48 +578,49 @@ MachineInstr *InlineSpiller::traceSiblingValue(unsigned UseReg, VNInfo *UseVNI, if (unsigned SrcReg = isFullCopyOf(MI, Reg)) { if (isSibling(SrcReg)) { LiveInterval &SrcLI = LIS.getInterval(SrcReg); - VNInfo *SrcVNI = SrcLI.getVNInfoAt(VNI->def.getUseIndex()); - assert(SrcVNI && "Copy from non-existing value"); - DEBUG(dbgs() << " copy of " << PrintReg(SrcReg) << ':' - << SrcVNI->id << '@' << SrcVNI->def << '\n'); - WorkList.push_back(std::make_pair(SrcReg, SrcVNI)); + LiveRange *SrcLR = SrcLI.getLiveRangeContaining(VNI->def.getUseIndex()); + assert(SrcLR && "Copy from non-existing value"); + // Check if this COPY kills its source. + SVI->second.KillsSource = (SrcLR->end == VNI->def); + VNInfo *SrcVNI = SrcLR->valno; + DEBUG(dbgs() << "copy of " << PrintReg(SrcReg) << ':' + << SrcVNI->id << '@' << SrcVNI->def + << " kill=" << unsigned(SVI->second.KillsSource) << '\n'); + // Known sibling source value? Try an insertion. + tie(SVI, Inserted) = SibValues.insert(std::make_pair(SrcVNI, + SibValueInfo(SrcReg, SrcVNI))); + // This is the first time we see Src, add it to the worklist. + if (Inserted) + WorkList.push_back(std::make_pair(SrcReg, SrcVNI)); + propagateSiblingValue(SVI, VNI); + // Next work list item. continue; } } // Track reachable reloads. + SVI->second.DefMI = MI; + SVI->second.SpillMBB = MI->getParent(); int FI; if (Reg == TII.isLoadFromStackSlot(MI, FI) && FI == StackSlot) { - DEBUG(dbgs() << " reload " << PrintReg(Reg) << ':' - << VNI->id << "@" << VNI->def << '\n'); - SVI.AllDefsAreReloads = true; + DEBUG(dbgs() << "reload\n"); + propagateSiblingValue(SVI); + // Next work list item. continue; } - // We have an 'original' def. Don't record trivial cases. - if (VNI == UseVNI) { - DEBUG(dbgs() << "Not a sibling copy.\n"); - return MI; - } - // Potential remat candidate. - DEBUG(dbgs() << " def " << PrintReg(Reg) << ':' - << VNI->id << '@' << VNI->def << '\t' << *MI); - SVI.DefMI = MI; + DEBUG(dbgs() << "def " << *MI); + SVI->second.AllDefsAreReloads = false; + propagateSiblingValue(SVI); } while (!WorkList.empty()); - if (SeenOrigPHI || SVI.DefMI) - SVI.AllDefsAreReloads = false; - - DEBUG({ - if (SVI.AllDefsAreReloads) - dbgs() << "All defs are reloads.\n"; - else - dbgs() << "Prefer to spill " << PrintReg(SVI.SpillReg) << ':' - << SVI.SpillVNI->id << '@' << SVI.SpillVNI->def << '\n'; - }); - SibValues.insert(std::make_pair(UseVNI, SVI)); - return SVI.DefMI; + // Look up the value we were looking for. We already did this lokup at the + // top of the function, but SibValues may have been invalidated. + SVI = SibValues.find(UseVNI); + assert(SVI != SibValues.end() && "Didn't compute requested info"); + DEBUG(dbgs() << " traced to:\t" << SVI->second); + return SVI->second.DefMI; } /// analyzeSiblingValues - Trace values defined by sibling copies back to @@ -506,6 +703,7 @@ bool InlineSpiller::hoistSpill(LiveInterval &SpillLI, MachineInstr *CopyMI) { // Already spilled everywhere. if (SVI.AllDefsAreReloads) { + DEBUG(dbgs() << "\tno spill needed: " << SVI); ++NumOmitReloadSpill; return true; } @@ -531,10 +729,8 @@ bool InlineSpiller::hoistSpill(LiveInterval &SpillLI, MachineInstr *CopyMI) { VRM.addSpillSlotUse(StackSlot, MII); DEBUG(dbgs() << "\thoisted: " << SVI.SpillVNI->def << '\t' << *MII); - if (MBB == CopyMI->getParent()) - ++NumHoistLocal; - else - ++NumHoistGlobal; + ++NumSpills; + ++NumHoists; return true; } @@ -589,7 +785,8 @@ void InlineSpiller::eliminateRedundantSpills(LiveInterval &SLI, VNInfo *VNI) { // eliminateDeadDefs won't normally remove stores, so switch opcode. MI->setDesc(TII.get(TargetOpcode::KILL)); DeadDefs.push_back(MI); - ++NumRedundantSpills; + ++NumSpillsRemoved; + --NumSpills; } } } while (!WorkList.empty()); @@ -637,7 +834,7 @@ void InlineSpiller::markValueUsed(LiveInterval *LI, VNInfo *VNI) { bool InlineSpiller::reMaterializeFor(LiveInterval &VirtReg, MachineBasicBlock::iterator MI) { SlotIndex UseIdx = LIS.getInstructionIndex(MI).getUseIndex(); - VNInfo *ParentVNI = VirtReg.getVNInfoAt(UseIdx); + VNInfo *ParentVNI = VirtReg.getVNInfoAt(UseIdx.getBaseIndex()); if (!ParentVNI) { DEBUG(dbgs() << "\tadding flags: "); @@ -787,10 +984,10 @@ void InlineSpiller::reMaterializeAll() { /// If MI is a load or store of StackSlot, it can be removed. bool InlineSpiller::coalesceStackAccess(MachineInstr *MI, unsigned Reg) { int FI = 0; - unsigned InstrReg; - if (!(InstrReg = TII.isLoadFromStackSlot(MI, FI)) && - !(InstrReg = TII.isStoreToStackSlot(MI, FI))) - return false; + unsigned InstrReg = TII.isLoadFromStackSlot(MI, FI); + bool IsLoad = InstrReg; + if (!IsLoad) + InstrReg = TII.isStoreToStackSlot(MI, FI); // We have a stack access. Is it the right register and slot? if (InstrReg != Reg || FI != StackSlot) @@ -799,6 +996,15 @@ bool InlineSpiller::coalesceStackAccess(MachineInstr *MI, unsigned Reg) { DEBUG(dbgs() << "Coalescing stack access: " << *MI); LIS.RemoveMachineInstrFromMaps(MI); MI->eraseFromParent(); + + if (IsLoad) { + ++NumReloadsRemoved; + --NumReloads; + } else { + ++NumSpillsRemoved; + --NumSpills; + } + return true; } @@ -810,6 +1016,7 @@ bool InlineSpiller::coalesceStackAccess(MachineInstr *MI, unsigned Reg) { bool InlineSpiller::foldMemoryOperand(MachineBasicBlock::iterator MI, const SmallVectorImpl &Ops, MachineInstr *LoadMI) { + bool WasCopy = MI->isCopy(); // TargetInstrInfo::foldMemoryOperand only expects explicit, non-tied // operands. SmallVector FoldOps; @@ -839,7 +1046,12 @@ bool InlineSpiller::foldMemoryOperand(MachineBasicBlock::iterator MI, VRM.addSpillSlotUse(StackSlot, FoldMI); MI->eraseFromParent(); DEBUG(dbgs() << "\tfolded: " << *FoldMI); - ++NumFolded; + if (!WasCopy) + ++NumFolded; + else if (Ops.front() == 0) + ++NumSpills; + else + ++NumReloads; return true; } @@ -975,8 +1187,16 @@ void InlineSpiller::spillAroundUses(unsigned Reg) { DEBUG(dbgs() << "\trewrite: " << Idx << '\t' << *MI); // FIXME: Use a second vreg if instruction has no tied ops. - if (Writes && hasLiveDef) + if (Writes) { + if (hasLiveDef) insertSpill(NewLI, OldLI, Idx, MI); + else { + // This instruction defines a dead value. We don't need to spill it, + // but do create a live range for the dead value. + VNInfo *VNI = NewLI.getNextValue(Idx, 0, LIS.getVNInfoAllocator()); + NewLI.addRange(LiveRange(Idx, Idx.getNextSlot(), VNI)); + } + } DEBUG(dbgs() << "\tinterval: " << NewLI << '\n'); } diff --git a/contrib/llvm/lib/CodeGen/InterferenceCache.cpp b/contrib/llvm/lib/CodeGen/InterferenceCache.cpp index a09bb39f8..29b47bd67 100644 --- a/contrib/llvm/lib/CodeGen/InterferenceCache.cpp +++ b/contrib/llvm/lib/CodeGen/InterferenceCache.cpp @@ -18,10 +18,13 @@ using namespace llvm; +// Static member used for null interference cursors. +InterferenceCache::BlockInterference InterferenceCache::Cursor::NoInterference; + void InterferenceCache::init(MachineFunction *mf, LiveIntervalUnion *liuarray, SlotIndexes *indexes, - const TargetRegisterInfo *tri) { + const TargetRegisterInfo *tri) { MF = mf; LIUArray = liuarray; TRI = tri; diff --git a/contrib/llvm/lib/CodeGen/InterferenceCache.h b/contrib/llvm/lib/CodeGen/InterferenceCache.h index 7f0a27a41..4df0a9e5c 100644 --- a/contrib/llvm/lib/CodeGen/InterferenceCache.h +++ b/contrib/llvm/lib/CodeGen/InterferenceCache.h @@ -138,6 +138,7 @@ public: class Cursor { Entry *CacheEntry; BlockInterference *Current; + static BlockInterference NoInterference; void setEntry(Entry *E) { Current = 0; @@ -175,7 +176,7 @@ public: /// moveTo - Move cursor to basic block MBBNum. void moveToBlock(unsigned MBBNum) { - Current = CacheEntry->get(MBBNum); + Current = CacheEntry ? CacheEntry->get(MBBNum) : &NoInterference; } /// hasInterference - Return true if the current block has any interference. diff --git a/contrib/llvm/lib/CodeGen/IntrinsicLowering.cpp b/contrib/llvm/lib/CodeGen/IntrinsicLowering.cpp index 611886ff1..0f92c2d06 100644 --- a/contrib/llvm/lib/CodeGen/IntrinsicLowering.cpp +++ b/contrib/llvm/lib/CodeGen/IntrinsicLowering.cpp @@ -27,7 +27,7 @@ using namespace llvm; template static void EnsureFunctionExists(Module &M, const char *Name, ArgIt ArgBegin, ArgIt ArgEnd, - const Type *RetTy) { + Type *RetTy) { // Insert a correctly-typed definition now. std::vector ParamTys; for (ArgIt I = ArgBegin; I != ArgEnd; ++I) @@ -64,7 +64,7 @@ static void EnsureFPIntrinsicsExist(Module &M, Function *Fn, template static CallInst *ReplaceCallWith(const char *NewFn, CallInst *CI, ArgIt ArgBegin, ArgIt ArgEnd, - const Type *RetTy) { + Type *RetTy) { // If we haven't already looked up this function, check to see if the // program already contains a function with this name. Module *M = CI->getParent()->getParent()->getParent(); @@ -462,7 +462,7 @@ void IntrinsicLowering::LowerIntrinsicCall(CallInst *CI) { break; // Strip out annotate intrinsic case Intrinsic::memcpy: { - const IntegerType *IntPtr = TD.getIntPtrType(Context); + IntegerType *IntPtr = TD.getIntPtrType(Context); Value *Size = Builder.CreateIntCast(CI->getArgOperand(2), IntPtr, /* isSigned */ false); Value *Ops[3]; @@ -473,7 +473,7 @@ void IntrinsicLowering::LowerIntrinsicCall(CallInst *CI) { break; } case Intrinsic::memmove: { - const IntegerType *IntPtr = TD.getIntPtrType(Context); + IntegerType *IntPtr = TD.getIntPtrType(Context); Value *Size = Builder.CreateIntCast(CI->getArgOperand(2), IntPtr, /* isSigned */ false); Value *Ops[3]; @@ -484,7 +484,7 @@ void IntrinsicLowering::LowerIntrinsicCall(CallInst *CI) { break; } case Intrinsic::memset: { - const IntegerType *IntPtr = TD.getIntPtrType(Context); + IntegerType *IntPtr = TD.getIntPtrType(Context); Value *Size = Builder.CreateIntCast(CI->getArgOperand(2), IntPtr, /* isSigned */ false); Value *Ops[3]; diff --git a/contrib/llvm/lib/CodeGen/LLVMTargetMachine.cpp b/contrib/llvm/lib/CodeGen/LLVMTargetMachine.cpp index f985af8ba..80ecc2248 100644 --- a/contrib/llvm/lib/CodeGen/LLVMTargetMachine.cpp +++ b/contrib/llvm/lib/CodeGen/LLVMTargetMachine.cpp @@ -27,16 +27,18 @@ #include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSubtargetInfo.h" -#include "llvm/Target/TargetAsmInfo.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetInstrInfo.h" -#include "llvm/Target/TargetRegistry.h" +#include "llvm/Target/TargetLowering.h" +#include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/Target/TargetRegisterInfo.h" #include "llvm/Target/TargetSubtargetInfo.h" #include "llvm/Transforms/Scalar.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/FormattedStream.h" +#include "llvm/Support/TargetRegistry.h" using namespace llvm; namespace llvm { @@ -55,8 +57,12 @@ static cl::opt DisableCodePlace("disable-code-place", cl::Hidden, cl::desc("Disable code placement")); static cl::opt DisableSSC("disable-ssc", cl::Hidden, cl::desc("Disable Stack Slot Coloring")); +static cl::opt DisableMachineDCE("disable-machine-dce", cl::Hidden, + cl::desc("Disable Machine Dead Code Elimination")); static cl::opt DisableMachineLICM("disable-machine-licm", cl::Hidden, cl::desc("Disable Machine LICM")); +static cl::opt DisableMachineCSE("disable-machine-cse", cl::Hidden, + cl::desc("Disable Machine Common Subexpression Elimination")); static cl::opt DisablePostRAMachineLICM("disable-postra-machine-licm", cl::Hidden, cl::desc("Disable Machine LICM")); @@ -103,20 +109,17 @@ EnableFastISelOption("fast-isel", cl::Hidden, cl::desc("Enable the \"fast\" instruction selector")); LLVMTargetMachine::LLVMTargetMachine(const Target &T, StringRef Triple, - StringRef CPU, StringRef FS) + StringRef CPU, StringRef FS, + Reloc::Model RM, CodeModel::Model CM) : TargetMachine(T, Triple, CPU, FS) { + CodeGenInfo = T.createMCCodeGenInfo(Triple, RM, CM); AsmInfo = T.createMCAsmInfo(Triple); -} - -// Set the default code model for the JIT for a generic target. -// FIXME: Is small right here? or .is64Bit() ? Large : Small? -void LLVMTargetMachine::setCodeModelForJIT() { - setCodeModel(CodeModel::Small); -} - -// Set the default code model for static compilation for a generic target. -void LLVMTargetMachine::setCodeModelForStatic() { - setCodeModel(CodeModel::Small); + // TargetSelect.h moved to a different directory between LLVM 2.9 and 3.0, + // and if the old one gets included then MCAsmInfo will be NULL and + // we'll crash later. + // Provide the user with a useful error message about what's wrong. + assert(AsmInfo && "MCAsmInfo not initialized." + "Make sure you include the correct TargetSelect.h!"); } bool LLVMTargetMachine::addPassesToEmitFile(PassManagerBase &PM, @@ -134,21 +137,22 @@ bool LLVMTargetMachine::addPassesToEmitFile(PassManagerBase &PM, Context->setAllowTemporaryLabels(false); const MCAsmInfo &MAI = *getMCAsmInfo(); + const MCSubtargetInfo &STI = getSubtarget(); OwningPtr AsmStreamer; switch (FileType) { default: return true; case CGFT_AssemblyFile: { MCInstPrinter *InstPrinter = - getTarget().createMCInstPrinter(MAI.getAssemblerDialect(), MAI); + getTarget().createMCInstPrinter(MAI.getAssemblerDialect(), MAI, STI); // Create a code emitter if asked to show the encoding. MCCodeEmitter *MCE = 0; - TargetAsmBackend *TAB = 0; + MCAsmBackend *MAB = 0; if (ShowMCEncoding) { const MCSubtargetInfo &STI = getSubtarget(); - MCE = getTarget().createCodeEmitter(*getInstrInfo(), STI, *Context); - TAB = getTarget().createAsmBackend(getTargetTriple()); + MCE = getTarget().createMCCodeEmitter(*getInstrInfo(), STI, *Context); + MAB = getTarget().createMCAsmBackend(getTargetTriple()); } MCStreamer *S = getTarget().createAsmStreamer(*Context, Out, @@ -156,7 +160,7 @@ bool LLVMTargetMachine::addPassesToEmitFile(PassManagerBase &PM, hasMCUseLoc(), hasMCUseCFI(), InstPrinter, - MCE, TAB, + MCE, MAB, ShowMCInst); AsmStreamer.reset(S); break; @@ -164,17 +168,16 @@ bool LLVMTargetMachine::addPassesToEmitFile(PassManagerBase &PM, case CGFT_ObjectFile: { // Create the code emitter for the target if it exists. If not, .o file // emission fails. - const MCSubtargetInfo &STI = getSubtarget(); - MCCodeEmitter *MCE = getTarget().createCodeEmitter(*getInstrInfo(), STI, - *Context); - TargetAsmBackend *TAB = getTarget().createAsmBackend(getTargetTriple()); - if (MCE == 0 || TAB == 0) + MCCodeEmitter *MCE = getTarget().createMCCodeEmitter(*getInstrInfo(), STI, + *Context); + MCAsmBackend *MAB = getTarget().createMCAsmBackend(getTargetTriple()); + if (MCE == 0 || MAB == 0) return true; - AsmStreamer.reset(getTarget().createObjectStreamer(getTargetTriple(), - *Context, *TAB, Out, MCE, - hasMCRelaxAll(), - hasMCNoExecStack())); + AsmStreamer.reset(getTarget().createMCObjectStreamer(getTargetTriple(), + *Context, *MAB, Out, + MCE, hasMCRelaxAll(), + hasMCNoExecStack())); AsmStreamer.get()->InitSections(); break; } @@ -198,8 +201,6 @@ bool LLVMTargetMachine::addPassesToEmitFile(PassManagerBase &PM, PM.add(Printer); - // Make sure the code model is set. - setCodeModelForStatic(); PM.add(createGCInfoDeleter()); return false; } @@ -214,9 +215,6 @@ bool LLVMTargetMachine::addPassesToEmitMachineCode(PassManagerBase &PM, JITCodeEmitter &JCE, CodeGenOpt::Level OptLevel, bool DisableVerify) { - // Make sure the code model is set. - setCodeModelForJIT(); - // Add common CodeGen passes. MCContext *Ctx = 0; if (addCommonCodeGenPasses(PM, OptLevel, DisableVerify, Ctx)) @@ -248,16 +246,16 @@ bool LLVMTargetMachine::addPassesToEmitMC(PassManagerBase &PM, // Create the code emitter for the target if it exists. If not, .o file // emission fails. const MCSubtargetInfo &STI = getSubtarget(); - MCCodeEmitter *MCE = getTarget().createCodeEmitter(*getInstrInfo(),STI, *Ctx); - TargetAsmBackend *TAB = getTarget().createAsmBackend(getTargetTriple()); - if (MCE == 0 || TAB == 0) + MCCodeEmitter *MCE = getTarget().createMCCodeEmitter(*getInstrInfo(),STI, *Ctx); + MCAsmBackend *MAB = getTarget().createMCAsmBackend(getTargetTriple()); + if (MCE == 0 || MAB == 0) return true; OwningPtr AsmStreamer; - AsmStreamer.reset(getTarget().createObjectStreamer(getTargetTriple(), *Ctx, - *TAB, Out, MCE, - hasMCRelaxAll(), - hasMCNoExecStack())); + AsmStreamer.reset(getTarget().createMCObjectStreamer(getTargetTriple(), *Ctx, + *MAB, Out, MCE, + hasMCRelaxAll(), + hasMCNoExecStack())); AsmStreamer.get()->InitSections(); // Create the AsmPrinter, which takes ownership of AsmStreamer if successful. @@ -270,9 +268,6 @@ bool LLVMTargetMachine::addPassesToEmitMC(PassManagerBase &PM, PM.add(Printer); - // Make sure the code model is set. - setCodeModelForJIT(); - return false; // success! } @@ -369,8 +364,9 @@ bool LLVMTargetMachine::addCommonCodeGenPasses(PassManagerBase &PM, // Install a MachineModuleInfo class, which is an immutable pass that holds // all the per-module stuff we're generating, including MCContext. - TargetAsmInfo *TAI = new TargetAsmInfo(*this); - MachineModuleInfo *MMI = new MachineModuleInfo(*getMCAsmInfo(), TAI); + MachineModuleInfo *MMI = new MachineModuleInfo(*getMCAsmInfo(), + *getRegisterInfo(), + &getTargetLowering()->getObjFileLowering()); PM.add(MMI); OutContext = &MMI->getContext(); // Return the MCContext specifically by-ref. @@ -412,12 +408,14 @@ bool LLVMTargetMachine::addCommonCodeGenPasses(PassManagerBase &PM, // there is one known exception: lowered code for arguments that are only // used by tail calls, where the tail calls reuse the incoming stack // arguments directly (see t11 in test/CodeGen/X86/sibcall.ll). - PM.add(createDeadMachineInstructionElimPass()); + if (!DisableMachineDCE) + PM.add(createDeadMachineInstructionElimPass()); printAndVerify(PM, "After codegen DCE pass"); if (!DisableMachineLICM) PM.add(createMachineLICMPass()); - PM.add(createMachineCSEPass()); + if (!DisableMachineCSE) + PM.add(createMachineCSEPass()); if (!DisableMachineSink) PM.add(createMachineSinkingPass()); printAndVerify(PM, "After Machine LICM, CSE and Sinking passes"); @@ -452,8 +450,8 @@ bool LLVMTargetMachine::addCommonCodeGenPasses(PassManagerBase &PM, if (addPostRegAlloc(PM, OptLevel)) printAndVerify(PM, "After PostRegAlloc passes"); - PM.add(createLowerSubregsPass()); - printAndVerify(PM, "After LowerSubregs"); + PM.add(createExpandPostRAPseudosPass()); + printAndVerify(PM, "After ExpandPostRAPseudos"); // Insert prolog/epilog code. Eliminate abstract frame index references... PM.add(createPrologEpilogCodeInserter()); diff --git a/contrib/llvm/lib/CodeGen/LexicalScopes.cpp b/contrib/llvm/lib/CodeGen/LexicalScopes.cpp new file mode 100644 index 000000000..a12e1a36d --- /dev/null +++ b/contrib/llvm/lib/CodeGen/LexicalScopes.cpp @@ -0,0 +1,335 @@ +//===- LexicalScopes.cpp - Collecting lexical scope info ------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements LexicalScopes analysis. +// +// This pass collects lexical scope information and maps machine instructions +// to respective lexical scopes. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "lexicalscopes" +#include "llvm/CodeGen/LexicalScopes.h" +#include "llvm/Function.h" +#include "llvm/Analysis/DebugInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/FormattedStream.h" +using namespace llvm; + +LexicalScopes::~LexicalScopes() { + releaseMemory(); +} + +/// releaseMemory - release memory. +void LexicalScopes::releaseMemory() { + MF = NULL; + CurrentFnLexicalScope = NULL; + DeleteContainerSeconds(LexicalScopeMap); + DeleteContainerSeconds(AbstractScopeMap); + InlinedLexicalScopeMap.clear(); + AbstractScopesList.clear(); +} + +/// initialize - Scan machine function and constuct lexical scope nest. +void LexicalScopes::initialize(const MachineFunction &Fn) { + releaseMemory(); + MF = &Fn; + SmallVector MIRanges; + DenseMap MI2ScopeMap; + extractLexicalScopes(MIRanges, MI2ScopeMap); + if (CurrentFnLexicalScope) { + constructScopeNest(CurrentFnLexicalScope); + assignInstructionRanges(MIRanges, MI2ScopeMap); + } +} + +/// extractLexicalScopes - Extract instruction ranges for each lexical scopes +/// for the given machine function. +void LexicalScopes:: +extractLexicalScopes(SmallVectorImpl &MIRanges, + DenseMap &MI2ScopeMap) { + + // Scan each instruction and create scopes. First build working set of scopes. + for (MachineFunction::const_iterator I = MF->begin(), E = MF->end(); + I != E; ++I) { + const MachineInstr *RangeBeginMI = NULL; + const MachineInstr *PrevMI = NULL; + DebugLoc PrevDL; + for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end(); + II != IE; ++II) { + const MachineInstr *MInsn = II; + + // Check if instruction has valid location information. + const DebugLoc MIDL = MInsn->getDebugLoc(); + if (MIDL.isUnknown()) { + PrevMI = MInsn; + continue; + } + + // If scope has not changed then skip this instruction. + if (MIDL == PrevDL) { + PrevMI = MInsn; + continue; + } + + // Ignore DBG_VALUE. It does not contribute to any instruction in output. + if (MInsn->isDebugValue()) + continue; + + if (RangeBeginMI) { + // If we have already seen a beginning of an instruction range and + // current instruction scope does not match scope of first instruction + // in this range then create a new instruction range. + InsnRange R(RangeBeginMI, PrevMI); + MI2ScopeMap[RangeBeginMI] = getOrCreateLexicalScope(PrevDL); + MIRanges.push_back(R); + } + + // This is a beginning of a new instruction range. + RangeBeginMI = MInsn; + + // Reset previous markers. + PrevMI = MInsn; + PrevDL = MIDL; + } + + // Create last instruction range. + if (RangeBeginMI && PrevMI && !PrevDL.isUnknown()) { + InsnRange R(RangeBeginMI, PrevMI); + MIRanges.push_back(R); + MI2ScopeMap[RangeBeginMI] = getOrCreateLexicalScope(PrevDL); + } + } +} + +/// findLexicalScope - Find lexical scope, either regular or inlined, for the +/// given DebugLoc. Return NULL if not found. +LexicalScope *LexicalScopes::findLexicalScope(DebugLoc DL) { + MDNode *Scope = NULL; + MDNode *IA = NULL; + DL.getScopeAndInlinedAt(Scope, IA, MF->getFunction()->getContext()); + if (!Scope) return NULL; + + // The scope that we were created with could have an extra file - which + // isn't what we care about in this case. + DIDescriptor D = DIDescriptor(Scope); + if (D.isLexicalBlockFile()) + Scope = DILexicalBlockFile(Scope).getScope(); + + if (IA) + return InlinedLexicalScopeMap.lookup(DebugLoc::getFromDILocation(IA)); + return LexicalScopeMap.lookup(Scope); +} + +/// getOrCreateLexicalScope - Find lexical scope for the given DebugLoc. If +/// not available then create new lexical scope. +LexicalScope *LexicalScopes::getOrCreateLexicalScope(DebugLoc DL) { + MDNode *Scope = NULL; + MDNode *InlinedAt = NULL; + DL.getScopeAndInlinedAt(Scope, InlinedAt, MF->getFunction()->getContext()); + + if (InlinedAt) { + // Create an abstract scope for inlined function. + getOrCreateAbstractScope(Scope); + // Create an inlined scope for inlined function. + return getOrCreateInlinedScope(Scope, InlinedAt); + } + + return getOrCreateRegularScope(Scope); +} + +/// getOrCreateRegularScope - Find or create a regular lexical scope. +LexicalScope *LexicalScopes::getOrCreateRegularScope(MDNode *Scope) { + DIDescriptor D = DIDescriptor(Scope); + if (D.isLexicalBlockFile()) { + Scope = DILexicalBlockFile(Scope).getScope(); + D = DIDescriptor(Scope); + } + + LexicalScope *WScope = LexicalScopeMap.lookup(Scope); + if (WScope) + return WScope; + + LexicalScope *Parent = NULL; + if (D.isLexicalBlock()) + Parent = getOrCreateLexicalScope(DebugLoc::getFromDILexicalBlock(Scope)); + WScope = new LexicalScope(Parent, DIDescriptor(Scope), NULL, false); + LexicalScopeMap.insert(std::make_pair(Scope, WScope)); + if (!Parent && DIDescriptor(Scope).isSubprogram() + && DISubprogram(Scope).describes(MF->getFunction())) + CurrentFnLexicalScope = WScope; + + return WScope; +} + +/// getOrCreateInlinedScope - Find or create an inlined lexical scope. +LexicalScope *LexicalScopes::getOrCreateInlinedScope(MDNode *Scope, + MDNode *InlinedAt) { + LexicalScope *InlinedScope = LexicalScopeMap.lookup(InlinedAt); + if (InlinedScope) + return InlinedScope; + + DebugLoc InlinedLoc = DebugLoc::getFromDILocation(InlinedAt); + InlinedScope = new LexicalScope(getOrCreateLexicalScope(InlinedLoc), + DIDescriptor(Scope), InlinedAt, false); + InlinedLexicalScopeMap[InlinedLoc] = InlinedScope; + LexicalScopeMap[InlinedAt] = InlinedScope; + return InlinedScope; +} + +/// getOrCreateAbstractScope - Find or create an abstract lexical scope. +LexicalScope *LexicalScopes::getOrCreateAbstractScope(const MDNode *N) { + assert(N && "Invalid Scope encoding!"); + + DIDescriptor Scope(N); + if (Scope.isLexicalBlockFile()) + Scope = DILexicalBlockFile(Scope).getScope(); + LexicalScope *AScope = AbstractScopeMap.lookup(N); + if (AScope) + return AScope; + + LexicalScope *Parent = NULL; + if (Scope.isLexicalBlock()) { + DILexicalBlock DB(N); + DIDescriptor ParentDesc = DB.getContext(); + Parent = getOrCreateAbstractScope(ParentDesc); + } + AScope = new LexicalScope(Parent, DIDescriptor(N), NULL, true); + AbstractScopeMap[N] = AScope; + if (DIDescriptor(N).isSubprogram()) + AbstractScopesList.push_back(AScope); + return AScope; +} + +/// constructScopeNest +void LexicalScopes::constructScopeNest(LexicalScope *Scope) { + assert (Scope && "Unable to calculate scop edominance graph!"); + SmallVector WorkStack; + WorkStack.push_back(Scope); + unsigned Counter = 0; + while (!WorkStack.empty()) { + LexicalScope *WS = WorkStack.back(); + const SmallVector &Children = WS->getChildren(); + bool visitedChildren = false; + for (SmallVector::const_iterator SI = Children.begin(), + SE = Children.end(); SI != SE; ++SI) { + LexicalScope *ChildScope = *SI; + if (!ChildScope->getDFSOut()) { + WorkStack.push_back(ChildScope); + visitedChildren = true; + ChildScope->setDFSIn(++Counter); + break; + } + } + if (!visitedChildren) { + WorkStack.pop_back(); + WS->setDFSOut(++Counter); + } + } +} + +/// assignInstructionRanges - Find ranges of instructions covered by each +/// lexical scope. +void LexicalScopes:: +assignInstructionRanges(SmallVectorImpl &MIRanges, + DenseMap &MI2ScopeMap) +{ + + LexicalScope *PrevLexicalScope = NULL; + for (SmallVectorImpl::const_iterator RI = MIRanges.begin(), + RE = MIRanges.end(); RI != RE; ++RI) { + const InsnRange &R = *RI; + LexicalScope *S = MI2ScopeMap.lookup(R.first); + assert (S && "Lost LexicalScope for a machine instruction!"); + if (PrevLexicalScope && !PrevLexicalScope->dominates(S)) + PrevLexicalScope->closeInsnRange(S); + S->openInsnRange(R.first); + S->extendInsnRange(R.second); + PrevLexicalScope = S; + } + + if (PrevLexicalScope) + PrevLexicalScope->closeInsnRange(); +} + +/// getMachineBasicBlocks - Populate given set using machine basic blocks which +/// have machine instructions that belong to lexical scope identified by +/// DebugLoc. +void LexicalScopes:: +getMachineBasicBlocks(DebugLoc DL, + SmallPtrSet &MBBs) { + MBBs.clear(); + LexicalScope *Scope = getOrCreateLexicalScope(DL); + if (!Scope) + return; + + if (Scope == CurrentFnLexicalScope) { + for (MachineFunction::const_iterator I = MF->begin(), E = MF->end(); + I != E; ++I) + MBBs.insert(I); + return; + } + + SmallVector &InsnRanges = Scope->getRanges(); + for (SmallVector::iterator I = InsnRanges.begin(), + E = InsnRanges.end(); I != E; ++I) { + InsnRange &R = *I; + MBBs.insert(R.first->getParent()); + } +} + +/// dominates - Return true if DebugLoc's lexical scope dominates at least one +/// machine instruction's lexical scope in a given machine basic block. +bool LexicalScopes::dominates(DebugLoc DL, MachineBasicBlock *MBB) { + LexicalScope *Scope = getOrCreateLexicalScope(DL); + if (!Scope) + return false; + + // Current function scope covers all basic blocks in the function. + if (Scope == CurrentFnLexicalScope && MBB->getParent() == MF) + return true; + + bool Result = false; + for (MachineBasicBlock::iterator I = MBB->begin(), E = MBB->end(); + I != E; ++I) { + DebugLoc IDL = I->getDebugLoc(); + if (IDL.isUnknown()) + continue; + if (LexicalScope *IScope = getOrCreateLexicalScope(IDL)) + if (Scope->dominates(IScope)) + return true; + } + return Result; +} + +/// dump - Print data structures. +void LexicalScope::dump() const { +#ifndef NDEBUG + raw_ostream &err = dbgs(); + err.indent(IndentLevel); + err << "DFSIn: " << DFSIn << " DFSOut: " << DFSOut << "\n"; + const MDNode *N = Desc; + N->dump(); + if (AbstractScope) + err << "Abstract Scope\n"; + + IndentLevel += 2; + if (!Children.empty()) + err << "Children ...\n"; + for (unsigned i = 0, e = Children.size(); i != e; ++i) + if (Children[i] != this) + Children[i]->dump(); + + IndentLevel -= 2; +#endif +} + diff --git a/contrib/llvm/lib/CodeGen/LiveDebugVariables.cpp b/contrib/llvm/lib/CodeGen/LiveDebugVariables.cpp index 5d38c83b4..3dfe4c0e8 100644 --- a/contrib/llvm/lib/CodeGen/LiveDebugVariables.cpp +++ b/contrib/llvm/lib/CodeGen/LiveDebugVariables.cpp @@ -25,7 +25,10 @@ #include "llvm/Constants.h" #include "llvm/Metadata.h" #include "llvm/Value.h" +#include "llvm/Analysis/DebugInfo.h" #include "llvm/ADT/IntervalMap.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/CodeGen/LexicalScopes.h" #include "llvm/CodeGen/LiveIntervalAnalysis.h" #include "llvm/CodeGen/MachineDominators.h" #include "llvm/CodeGen/MachineFunction.h" @@ -44,6 +47,7 @@ static cl::opt EnableLDV("live-debug-variables", cl::init(true), cl::desc("Enable the live debug variables pass"), cl::Hidden); +STATISTIC(NumInsertedDebugValues, "Number of DBG_VALUEs inserted"); char LiveDebugVariables::ID = 0; INITIALIZE_PASS_BEGIN(LiveDebugVariables, "livedebugvars", @@ -67,6 +71,29 @@ LiveDebugVariables::LiveDebugVariables() : MachineFunctionPass(ID), pImpl(0) { /// LocMap - Map of where a user value is live, and its location. typedef IntervalMap LocMap; +namespace { +/// UserValueScopes - Keeps track of lexical scopes associated with an +/// user value's source location. +class UserValueScopes { + DebugLoc DL; + LexicalScopes &LS; + SmallPtrSet LBlocks; + +public: + UserValueScopes(DebugLoc D, LexicalScopes &L) : DL(D), LS(L) {} + + /// dominates - Return true if current scope dominates at least one machine + /// instruction in a given machine basic block. + bool dominates(MachineBasicBlock *MBB) { + if (LBlocks.empty()) + LS.getMachineBasicBlocks(DL, LBlocks); + if (LBlocks.count(MBB) != 0 || LS.dominates(DL, MBB)) + return true; + return false; + } +}; +} // end anonymous namespace + /// UserValue - A user value is a part of a debug info user variable. /// /// A DBG_VALUE instruction notes that (a sub-register of) a virtual register @@ -179,6 +206,9 @@ public: LocMap::iterator I = locInts.find(Idx); if (!I.valid() || I.start() != Idx) I.insert(Idx, Idx.getNextSlot(), getLocationNo(LocMO)); + else + // A later DBG_VALUE at the same SlotIndex overrides the old location. + I.setValue(getLocationNo(LocMO)); } /// extendDef - Extend the current definition as far as possible down the @@ -195,7 +225,8 @@ public: void extendDef(SlotIndex Idx, unsigned LocNo, LiveInterval *LI, const VNInfo *VNI, SmallVectorImpl *Kills, - LiveIntervals &LIS, MachineDominatorTree &MDT); + LiveIntervals &LIS, MachineDominatorTree &MDT, + UserValueScopes &UVS); /// addDefsFromCopies - The value in LI/LocNo may be copies to other /// registers. Determine if any of the copies are available at the kill @@ -213,7 +244,8 @@ public: /// computeIntervals - Compute the live intervals of all locations after /// collecting all their def points. void computeIntervals(MachineRegisterInfo &MRI, - LiveIntervals &LIS, MachineDominatorTree &MDT); + LiveIntervals &LIS, MachineDominatorTree &MDT, + UserValueScopes &UVS); /// renameRegister - Update locations to rewrite OldReg as NewReg:SubIdx. void renameRegister(unsigned OldReg, unsigned NewReg, unsigned SubIdx, @@ -236,6 +268,9 @@ public: /// Only first one needs DebugLoc to identify variable's lexical scope /// in source file. DebugLoc findDebugLoc(); + + /// getDebugLoc - Return DebugLoc of this UserValue. + DebugLoc getDebugLoc() { return dl;} void print(raw_ostream&, const TargetMachine*); }; } // namespace @@ -247,6 +282,7 @@ class LDVImpl { LocMap::Allocator allocator; MachineFunction *MF; LiveIntervals *LIS; + LexicalScopes LS; MachineDominatorTree *MDT; const TargetRegisterInfo *TRI; @@ -312,8 +348,10 @@ public: } // namespace void UserValue::print(raw_ostream &OS, const TargetMachine *TM) { - if (const MDString *MDS = dyn_cast(variable->getOperand(2))) - OS << "!\"" << MDS->getString() << "\"\t"; + DIVariable DV(variable); + OS << "!\""; + DV.printExtendedName(OS); + OS << "\"\t"; if (offset) OS << '+' << offset; for (LocMap::const_iterator I = locInts.begin(); I.valid(); ++I) { @@ -447,10 +485,10 @@ bool LDVImpl::collectDebugValues(MachineFunction &mf) { void UserValue::extendDef(SlotIndex Idx, unsigned LocNo, LiveInterval *LI, const VNInfo *VNI, SmallVectorImpl *Kills, - LiveIntervals &LIS, MachineDominatorTree &MDT) { + LiveIntervals &LIS, MachineDominatorTree &MDT, + UserValueScopes &UVS) { SmallVector Todo; Todo.push_back(Idx); - do { SlotIndex Start = Todo.pop_back_val(); MachineBasicBlock *MBB = LIS.getMBBFromIndex(Start); @@ -497,8 +535,11 @@ void UserValue::extendDef(SlotIndex Idx, unsigned LocNo, continue; const std::vector &Children = MDT.getNode(MBB)->getChildren(); - for (unsigned i = 0, e = Children.size(); i != e; ++i) - Todo.push_back(LIS.getMBBStartIdx(Children[i]->getBlock())); + for (unsigned i = 0, e = Children.size(); i != e; ++i) { + MachineBasicBlock *MBB = Children[i]->getBlock(); + if (UVS.dominates(MBB)) + Todo.push_back(LIS.getMBBStartIdx(MBB)); + } } while (!Todo.empty()); } @@ -578,7 +619,8 @@ UserValue::addDefsFromCopies(LiveInterval *LI, unsigned LocNo, void UserValue::computeIntervals(MachineRegisterInfo &MRI, LiveIntervals &LIS, - MachineDominatorTree &MDT) { + MachineDominatorTree &MDT, + UserValueScopes &UVS) { SmallVector, 16> Defs; // Collect all defs to be extended (Skipping undefs). @@ -597,10 +639,10 @@ UserValue::computeIntervals(MachineRegisterInfo &MRI, LiveInterval *LI = &LIS.getInterval(Loc.getReg()); const VNInfo *VNI = LI->getVNInfoAt(Idx); SmallVector Kills; - extendDef(Idx, LocNo, LI, VNI, &Kills, LIS, MDT); + extendDef(Idx, LocNo, LI, VNI, &Kills, LIS, MDT, UVS); addDefsFromCopies(LI, LocNo, Kills, Defs, MRI, LIS); } else - extendDef(Idx, LocNo, 0, 0, 0, LIS, MDT); + extendDef(Idx, LocNo, 0, 0, 0, LIS, MDT, UVS); } // Finally, erase all the undefs. @@ -613,7 +655,8 @@ UserValue::computeIntervals(MachineRegisterInfo &MRI, void LDVImpl::computeIntervals() { for (unsigned i = 0, e = userValues.size(); i != e; ++i) { - userValues[i]->computeIntervals(MF->getRegInfo(), *LIS, *MDT); + UserValueScopes UVS(userValues[i]->getDebugLoc(), LS); + userValues[i]->computeIntervals(MF->getRegInfo(), *LIS, *MDT, UVS); userValues[i]->mapVirtRegs(this); } } @@ -624,6 +667,7 @@ bool LDVImpl::runOnMachineFunction(MachineFunction &mf) { MDT = &pass.getAnalysis(); TRI = mf.getTarget().getRegisterInfo(); clear(); + LS.initialize(mf); DEBUG(dbgs() << "********** COMPUTING LIVE DEBUG VARIABLES: " << ((Value*)mf.getFunction())->getName() << " **********\n"); @@ -631,6 +675,7 @@ bool LDVImpl::runOnMachineFunction(MachineFunction &mf) { bool Changed = collectDebugValues(mf); computeIntervals(); DEBUG(print(dbgs())); + LS.releaseMemory(); return Changed; } @@ -891,6 +936,7 @@ void UserValue::insertDebugValue(MachineBasicBlock *MBB, SlotIndex Idx, const TargetInstrInfo &TII) { MachineBasicBlock::iterator I = findInsertLocation(MBB, Idx, LIS); MachineOperand &Loc = locations[LocNo]; + ++NumInsertedDebugValues; // Frame index locations may require a target callback. if (Loc.isFI()) { @@ -921,7 +967,6 @@ void UserValue::emitDebugValues(VirtRegMap *VRM, LiveIntervals &LIS, DEBUG(dbgs() << " BB#" << MBB->getNumber() << '-' << MBBEnd); insertDebugValue(MBB, Start, LocNo, LIS, TII); - // This interval may span multiple basic blocks. // Insert a DBG_VALUE into each one. while(Stop > MBBEnd) { diff --git a/contrib/llvm/lib/CodeGen/LiveInterval.cpp b/contrib/llvm/lib/CodeGen/LiveInterval.cpp index cfade24b8..b69945aea 100644 --- a/contrib/llvm/lib/CodeGen/LiveInterval.cpp +++ b/contrib/llvm/lib/CodeGen/LiveInterval.cpp @@ -148,7 +148,6 @@ void LiveInterval::markValNoForDeletion(VNInfo *ValNo) { /// remaining unused values. void LiveInterval::RenumberValues(LiveIntervals &lis) { SmallPtrSet Seen; - bool seenPHIDef = false; valnos.clear(); for (const_iterator I = begin(), E = end(); I != E; ++I) { VNInfo *VNI = I->valno; @@ -157,26 +156,6 @@ void LiveInterval::RenumberValues(LiveIntervals &lis) { assert(!VNI->isUnused() && "Unused valno used by live range"); VNI->id = (unsigned)valnos.size(); valnos.push_back(VNI); - VNI->setHasPHIKill(false); - if (VNI->isPHIDef()) - seenPHIDef = true; - } - - // Recompute phi kill flags. - if (!seenPHIDef) - return; - for (const_vni_iterator I = vni_begin(), E = vni_end(); I != E; ++I) { - VNInfo *VNI = *I; - if (!VNI->isPHIDef()) - continue; - const MachineBasicBlock *PHIBB = lis.getMBBFromIndex(VNI->def); - assert(PHIBB && "No basic block for phi-def"); - for (MachineBasicBlock::const_pred_iterator PI = PHIBB->pred_begin(), - PE = PHIBB->pred_end(); PI != PE; ++PI) { - VNInfo *KVNI = getVNInfoAt(lis.getMBBEndIdx(*PI).getPrevSlot()); - if (KVNI) - KVNI->setHasPHIKill(true); - } } } @@ -294,20 +273,20 @@ LiveInterval::addRangeFrom(LiveRange LR, iterator From) { return ranges.insert(it, LR); } -/// extendInBlock - If this interval is live before UseIdx in the basic -/// block that starts at StartIdx, extend it to be live at UseIdx and return -/// the value. If there is no live range before UseIdx, return NULL. -VNInfo *LiveInterval::extendInBlock(SlotIndex StartIdx, SlotIndex UseIdx) { +/// extendInBlock - If this interval 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. +VNInfo *LiveInterval::extendInBlock(SlotIndex StartIdx, SlotIndex Kill) { if (empty()) return 0; - iterator I = std::upper_bound(begin(), end(), UseIdx); + iterator I = std::upper_bound(begin(), end(), Kill.getPrevSlot()); if (I == begin()) return 0; --I; if (I->end <= StartIdx) return 0; - if (I->end <= UseIdx) - extendIntervalEndTo(I, UseIdx.getNextSlot()); + if (I->end < Kill) + extendIntervalEndTo(I, Kill); return I->valno; } diff --git a/contrib/llvm/lib/CodeGen/LiveIntervalAnalysis.cpp b/contrib/llvm/lib/CodeGen/LiveIntervalAnalysis.cpp index 9257191f7..b1e202a27 100644 --- a/contrib/llvm/lib/CodeGen/LiveIntervalAnalysis.cpp +++ b/contrib/llvm/lib/CodeGen/LiveIntervalAnalysis.cpp @@ -304,8 +304,19 @@ void LiveIntervals::handleVirtualRegisterDef(MachineBasicBlock *mbb, // Make sure the first definition is not a partial redefinition. Add an // of the full register. - if (MO.getSubReg()) + // FIXME: LiveIntervals shouldn't modify the code like this. Whoever + // created the machine instruction should annotate it with flags + // as needed. Then we can simply assert here. The REG_SEQUENCE lowering + // is the main suspect. + if (MO.getSubReg()) { mi->addRegisterDefined(interval.reg); + // Mark all defs of interval.reg on this instruction as reading . + for (unsigned i = MOIdx, e = mi->getNumOperands(); i != e; ++i) { + MachineOperand &MO2 = mi->getOperand(i); + if (MO2.isReg() && MO2.getReg() == interval.reg && MO2.getSubReg()) + MO2.setIsUndef(); + } + } MachineInstr *CopyMI = NULL; if (mi->isCopyLike()) { @@ -747,6 +758,9 @@ bool LiveIntervals::shrinkToUses(LiveInterval *li, // Find all the values used, including PHI kills. SmallVector, 16> WorkList; + // Blocks that have already been added to WorkList as live-out. + SmallPtrSet LiveOut; + // Visit all instructions reading li->reg. for (MachineRegisterInfo::reg_iterator I = mri_->reg_begin(li->reg); MachineInstr *UseMI = I.skipInstruction();) { @@ -780,8 +794,6 @@ bool LiveIntervals::shrinkToUses(LiveInterval *li, VNInfo *VNI = *I; if (VNI->isUnused()) continue; - // We may eliminate PHI values, so recompute PHIKill flags. - VNI->setHasPHIKill(false); NewLI.addRange(LiveRange(VNI->def, VNI->def.getNextSlot(), VNI)); // A use tied to an early-clobber def ends at the load slot and isn't caught @@ -804,7 +816,7 @@ bool LiveIntervals::shrinkToUses(LiveInterval *li, SlotIndex BlockStart = getMBBStartIdx(MBB); // Extend the live range for VNI to be live at Idx. - if (VNInfo *ExtVNI = NewLI.extendInBlock(BlockStart, Idx)) { + if (VNInfo *ExtVNI = NewLI.extendInBlock(BlockStart, Idx.getNextSlot())) { (void)ExtVNI; assert(ExtVNI == VNI && "Unexpected existing value number"); // Is this a PHIDef we haven't seen before? @@ -813,13 +825,12 @@ bool LiveIntervals::shrinkToUses(LiveInterval *li, // The PHI is live, make sure the predecessors are live-out. for (MachineBasicBlock::const_pred_iterator PI = MBB->pred_begin(), PE = MBB->pred_end(); PI != PE; ++PI) { + if (!LiveOut.insert(*PI)) + continue; SlotIndex Stop = getMBBEndIdx(*PI).getPrevSlot(); - VNInfo *PVNI = li->getVNInfoAt(Stop); // A predecessor is not required to have a live-out value for a PHI. - if (PVNI) { - PVNI->setHasPHIKill(true); + if (VNInfo *PVNI = li->getVNInfoAt(Stop)) WorkList.push_back(std::make_pair(Stop, PVNI)); - } } continue; } @@ -831,6 +842,8 @@ bool LiveIntervals::shrinkToUses(LiveInterval *li, // Make sure VNI is live-out from the predecessors. for (MachineBasicBlock::const_pred_iterator PI = MBB->pred_begin(), PE = MBB->pred_end(); PI != PE; ++PI) { + if (!LiveOut.insert(*PI)) + continue; SlotIndex Stop = getMBBEndIdx(*PI).getPrevSlot(); assert(li->getVNInfoAt(Stop) == VNI && "Wrong value out of predecessor"); WorkList.push_back(std::make_pair(Stop, VNI)); diff --git a/contrib/llvm/lib/CodeGen/LiveIntervalUnion.cpp b/contrib/llvm/lib/CodeGen/LiveIntervalUnion.cpp index 70003e7cc..110fe1e62 100644 --- a/contrib/llvm/lib/CodeGen/LiveIntervalUnion.cpp +++ b/contrib/llvm/lib/CodeGen/LiveIntervalUnion.cpp @@ -91,25 +91,6 @@ LiveIntervalUnion::print(raw_ostream &OS, const TargetRegisterInfo *TRI) const { OS << '\n'; } -void LiveIntervalUnion::InterferenceResult::print(raw_ostream &OS, - const TargetRegisterInfo *TRI) const { - OS << '[' << start() << ';' << stop() << "):" - << PrintReg(interference()->reg, TRI); -} - -void LiveIntervalUnion::Query::print(raw_ostream &OS, - const TargetRegisterInfo *TRI) { - OS << "Interferences with "; - LiveUnion->print(OS, TRI); - InterferenceResult IR = firstInterference(); - while (isInterference(IR)) { - OS << " "; - IR.print(OS, TRI); - OS << '\n'; - nextInterference(IR); - } -} - #ifndef NDEBUG // Verify the live intervals in this union and add them to the visited set. void LiveIntervalUnion::verify(LiveVirtRegBitSet& VisitedVRegs) { @@ -118,114 +99,6 @@ void LiveIntervalUnion::verify(LiveVirtRegBitSet& VisitedVRegs) { } #endif //!NDEBUG -// Private interface accessed by Query. -// -// Find a pair of segments that intersect, one in the live virtual register -// (LiveInterval), and the other in this LiveIntervalUnion. The caller (Query) -// is responsible for advancing the LiveIntervalUnion segments to find a -// "notable" intersection, which requires query-specific logic. -// -// This design assumes only a fast mechanism for intersecting a single live -// virtual register segment with a set of LiveIntervalUnion segments. This may -// be ok since most virtual registers have very few segments. If we had a data -// structure that optimizd MxN intersection of segments, then we would bypass -// the loop that advances within the LiveInterval. -// -// If no intersection exists, set VirtRegI = VirtRegEnd, and set SI to the first -// segment whose start point is greater than LiveInterval's end point. -// -// Assumes that segments are sorted by start position in both -// LiveInterval and LiveSegments. -void LiveIntervalUnion::Query::findIntersection(InterferenceResult &IR) const { - // Search until reaching the end of the LiveUnion segments. - LiveInterval::iterator VirtRegEnd = VirtReg->end(); - if (IR.VirtRegI == VirtRegEnd) - return; - while (IR.LiveUnionI.valid()) { - // Slowly advance the live virtual reg iterator until we surpass the next - // segment in LiveUnion. - // - // Note: If this is ever used for coalescing of fixed registers and we have - // a live vreg with thousands of segments, then change this code to use - // upperBound instead. - IR.VirtRegI = VirtReg->advanceTo(IR.VirtRegI, IR.LiveUnionI.start()); - if (IR.VirtRegI == VirtRegEnd) - break; // Retain current (nonoverlapping) LiveUnionI - - // VirtRegI may have advanced far beyond LiveUnionI, catch up. - IR.LiveUnionI.advanceTo(IR.VirtRegI->start); - - // Check if no LiveUnionI exists with VirtRegI->Start < LiveUnionI.end - if (!IR.LiveUnionI.valid()) - break; - if (IR.LiveUnionI.start() < IR.VirtRegI->end) { - assert(overlap(*IR.VirtRegI, IR.LiveUnionI) && - "upperBound postcondition"); - break; - } - } - if (!IR.LiveUnionI.valid()) - IR.VirtRegI = VirtRegEnd; -} - -// Find the first intersection, and cache interference info -// (retain segment iterators into both VirtReg and LiveUnion). -const LiveIntervalUnion::InterferenceResult & -LiveIntervalUnion::Query::firstInterference() { - if (CheckedFirstInterference) - return FirstInterference; - CheckedFirstInterference = true; - InterferenceResult &IR = FirstInterference; - IR.LiveUnionI.setMap(LiveUnion->getMap()); - - // Quickly skip interference check for empty sets. - if (VirtReg->empty() || LiveUnion->empty()) { - IR.VirtRegI = VirtReg->end(); - } else if (VirtReg->beginIndex() < LiveUnion->startIndex()) { - // VirtReg starts first, perform double binary search. - IR.VirtRegI = VirtReg->find(LiveUnion->startIndex()); - if (IR.VirtRegI != VirtReg->end()) - IR.LiveUnionI.find(IR.VirtRegI->start); - } else { - // LiveUnion starts first, perform double binary search. - IR.LiveUnionI.find(VirtReg->beginIndex()); - if (IR.LiveUnionI.valid()) - IR.VirtRegI = VirtReg->find(IR.LiveUnionI.start()); - else - IR.VirtRegI = VirtReg->end(); - } - findIntersection(FirstInterference); - assert((IR.VirtRegI == VirtReg->end() || IR.LiveUnionI.valid()) - && "Uninitialized iterator"); - return FirstInterference; -} - -// Treat the result as an iterator and advance to the next interfering pair -// of segments. This is a plain iterator with no filter. -bool LiveIntervalUnion::Query::nextInterference(InterferenceResult &IR) const { - assert(isInterference(IR) && "iteration past end of interferences"); - - // Advance either the VirtReg or LiveUnion segment to ensure that we visit all - // unique overlapping pairs. - if (IR.VirtRegI->end < IR.LiveUnionI.stop()) { - if (++IR.VirtRegI == VirtReg->end()) - return false; - } - else { - if (!(++IR.LiveUnionI).valid()) { - IR.VirtRegI = VirtReg->end(); - return false; - } - } - // Short-circuit findIntersection() if possible. - if (overlap(*IR.VirtRegI, IR.LiveUnionI)) - return true; - - // Find the next intersection. - findIntersection(IR); - return isInterference(IR); -} - // Scan the vector of interfering virtual registers in this union. Assume it's // quite small. bool LiveIntervalUnion::Query::isSeenInterference(LiveInterval *VirtReg) const { @@ -234,64 +107,75 @@ bool LiveIntervalUnion::Query::isSeenInterference(LiveInterval *VirtReg) const { return I != InterferingVRegs.end(); } -// Count the number of virtual registers in this union that interfere with this +// Collect virtual registers in this union that interfere with this // query's live virtual register. // -// The number of times that we either advance IR.VirtRegI or call -// LiveUnion.upperBound() will be no more than the number of holes in -// VirtReg. So each invocation of collectInterferingVRegs() takes -// time proportional to |VirtReg Holes| * time(LiveUnion.upperBound()). +// The query state is one of: +// +// 1. CheckedFirstInterference == false: Iterators are uninitialized. +// 2. SeenAllInterferences == true: InterferingVRegs complete, iterators unused. +// 3. Iterators left at the last seen intersection. // -// For comments on how to speed it up, see Query::findIntersection(). unsigned LiveIntervalUnion::Query:: collectInterferingVRegs(unsigned MaxInterferingRegs) { - InterferenceResult IR = firstInterference(); - LiveInterval::iterator VirtRegEnd = VirtReg->end(); - LiveInterval *RecentInterferingVReg = NULL; - if (IR.VirtRegI != VirtRegEnd) while (IR.LiveUnionI.valid()) { - // Advance the union's iterator to reach an unseen interfering vreg. - do { - if (IR.LiveUnionI.value() == RecentInterferingVReg) - continue; + // Fast path return if we already have the desired information. + if (SeenAllInterferences || InterferingVRegs.size() >= MaxInterferingRegs) + return InterferingVRegs.size(); + + // Set up iterators on the first call. + if (!CheckedFirstInterference) { + CheckedFirstInterference = true; + + // Quickly skip interference check for empty sets. + if (VirtReg->empty() || LiveUnion->empty()) { + SeenAllInterferences = true; + return 0; + } - if (!isSeenInterference(IR.LiveUnionI.value())) - break; + // In most cases, the union will start before VirtReg. + VirtRegI = VirtReg->begin(); + LiveUnionI.setMap(LiveUnion->getMap()); + LiveUnionI.find(VirtRegI->start); + } - // Cache the most recent interfering vreg to bypass isSeenInterference. - RecentInterferingVReg = IR.LiveUnionI.value(); + LiveInterval::iterator VirtRegEnd = VirtReg->end(); + LiveInterval *RecentReg = 0; + while (LiveUnionI.valid()) { + assert(VirtRegI != VirtRegEnd && "Reached end of VirtReg"); + + // Check for overlapping interference. + while (VirtRegI->start < LiveUnionI.stop() && + VirtRegI->end > LiveUnionI.start()) { + // This is an overlap, record the interfering register. + LiveInterval *VReg = LiveUnionI.value(); + if (VReg != RecentReg && !isSeenInterference(VReg)) { + RecentReg = VReg; + InterferingVRegs.push_back(VReg); + if (InterferingVRegs.size() >= MaxInterferingRegs) + return InterferingVRegs.size(); + } + // This LiveUnion segment is no longer interesting. + if (!(++LiveUnionI).valid()) { + SeenAllInterferences = true; + return InterferingVRegs.size(); + } + } - } while ((++IR.LiveUnionI).valid()); - if (!IR.LiveUnionI.valid()) - break; + // The iterators are now not overlapping, LiveUnionI has been advanced + // beyond VirtRegI. + assert(VirtRegI->end <= LiveUnionI.start() && "Expected non-overlap"); - // Advance the VirtReg iterator until surpassing the next segment in - // LiveUnion. - IR.VirtRegI = VirtReg->advanceTo(IR.VirtRegI, IR.LiveUnionI.start()); - if (IR.VirtRegI == VirtRegEnd) + // Advance the iterator that ends first. + VirtRegI = VirtReg->advanceTo(VirtRegI, LiveUnionI.start()); + if (VirtRegI == VirtRegEnd) break; - // Check for intersection with the union's segment. - if (overlap(*IR.VirtRegI, IR.LiveUnionI)) { - - if (!IR.LiveUnionI.value()->isSpillable()) - SeenUnspillableVReg = true; - - if (InterferingVRegs.size() == MaxInterferingRegs) - // Leave SeenAllInterferences set to false to indicate that at least one - // interference exists beyond those we collected. - return MaxInterferingRegs; - - InterferingVRegs.push_back(IR.LiveUnionI.value()); - - // Cache the most recent interfering vreg to bypass isSeenInterference. - RecentInterferingVReg = IR.LiveUnionI.value(); - ++IR.LiveUnionI; - + // Detect overlap, handle above. + if (VirtRegI->start < LiveUnionI.stop()) continue; - } - // VirtRegI may have advanced far beyond LiveUnionI, - // do a fast intersection test to "catch up" - IR.LiveUnionI.advanceTo(IR.VirtRegI->start); + + // Still not overlapping. Catch up LiveUnionI. + LiveUnionI.advanceTo(VirtRegI->start); } SeenAllInterferences = true; return InterferingVRegs.size(); diff --git a/contrib/llvm/lib/CodeGen/LiveIntervalUnion.h b/contrib/llvm/lib/CodeGen/LiveIntervalUnion.h index 5e78d5e85..5d64d285f 100644 --- a/contrib/llvm/lib/CodeGen/LiveIntervalUnion.h +++ b/contrib/llvm/lib/CodeGen/LiveIntervalUnion.h @@ -59,7 +59,6 @@ public: // LiveIntervalUnions share an external allocator. typedef LiveSegments::Allocator Allocator; - class InterferenceResult; class Query; private: @@ -106,62 +105,13 @@ public: void verify(LiveVirtRegBitSet& VisitedVRegs); #endif - /// Cache a single interference test result in the form of two intersecting - /// segments. This allows efficiently iterating over the interferences. The - /// iteration logic is handled by LiveIntervalUnion::Query which may - /// filter interferences depending on the type of query. - class InterferenceResult { - friend class Query; - - LiveInterval::iterator VirtRegI; // current position in VirtReg - SegmentIter LiveUnionI; // current position in LiveUnion - - // Internal ctor. - InterferenceResult(LiveInterval::iterator VRegI, SegmentIter UnionI) - : VirtRegI(VRegI), LiveUnionI(UnionI) {} - - public: - // Public default ctor. - InterferenceResult(): VirtRegI(), LiveUnionI() {} - - /// start - Return the start of the current overlap. - SlotIndex start() const { - return std::max(VirtRegI->start, LiveUnionI.start()); - } - - /// stop - Return the end of the current overlap. - SlotIndex stop() const { - return std::min(VirtRegI->end, LiveUnionI.stop()); - } - - /// interference - Return the register that is interfering here. - LiveInterval *interference() const { return LiveUnionI.value(); } - - // Note: this interface provides raw access to the iterators because the - // result has no way to tell if it's valid to dereference them. - - // Access the VirtReg segment. - LiveInterval::iterator virtRegPos() const { return VirtRegI; } - - // Access the LiveUnion segment. - const SegmentIter &liveUnionPos() const { return LiveUnionI; } - - bool operator==(const InterferenceResult &IR) const { - return VirtRegI == IR.VirtRegI && LiveUnionI == IR.LiveUnionI; - } - bool operator!=(const InterferenceResult &IR) const { - return !operator==(IR); - } - - void print(raw_ostream &OS, const TargetRegisterInfo *TRI) const; - }; - /// Query interferences between a single live virtual register and a live /// interval union. class Query { LiveIntervalUnion *LiveUnion; LiveInterval *VirtReg; - InterferenceResult FirstInterference; + LiveInterval::iterator VirtRegI; // current position in VirtReg + SegmentIter LiveUnionI; // current position in LiveUnion SmallVector InterferingVRegs; bool CheckedFirstInterference; bool SeenAllInterferences; @@ -206,26 +156,8 @@ public: return *VirtReg; } - bool isInterference(const InterferenceResult &IR) const { - if (IR.VirtRegI != VirtReg->end()) { - assert(overlap(*IR.VirtRegI, IR.LiveUnionI) && - "invalid segment iterators"); - return true; - } - return false; - } - // Does this live virtual register interfere with the union? - bool checkInterference() { return isInterference(firstInterference()); } - - // Get the first pair of interfering segments, or a noninterfering result. - // This initializes the firstInterference_ cache. - const InterferenceResult &firstInterference(); - - // Treat the result as an iterator and advance to the next interfering pair - // of segments. Visiting each unique interfering pairs means that the same - // VirtReg or LiveUnion segment may be visited multiple times. - bool nextInterference(InterferenceResult &IR) const; + bool checkInterference() { return collectInterferingVRegs(1); } // Count the virtual registers in this union that interfere with this // query's live virtual register, up to maxInterferingRegs. @@ -249,13 +181,9 @@ public: /// Loop. bool checkLoopInterference(MachineLoopRange*); - void print(raw_ostream &OS, const TargetRegisterInfo *TRI); private: Query(const Query&); // DO NOT IMPLEMENT void operator=(const Query&); // DO NOT IMPLEMENT - - // Private interface for queries - void findIntersection(InterferenceResult &IR) const; }; }; diff --git a/contrib/llvm/lib/CodeGen/LiveRangeCalc.cpp b/contrib/llvm/lib/CodeGen/LiveRangeCalc.cpp new file mode 100644 index 000000000..a7d5af519 --- /dev/null +++ b/contrib/llvm/lib/CodeGen/LiveRangeCalc.cpp @@ -0,0 +1,270 @@ +//===---- LiveRangeCalc.cpp - Calculate live ranges -----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Implementation of the LiveRangeCalc class. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "regalloc" +#include "LiveRangeCalc.h" +#include "llvm/CodeGen/MachineDominators.h" + +using namespace llvm; + +void LiveRangeCalc::reset(const MachineFunction *MF) { + unsigned N = MF->getNumBlockIDs(); + Seen.clear(); + Seen.resize(N); + LiveOut.resize(N); + LiveIn.clear(); +} + + +// Transfer information from the LiveIn vector to the live ranges. +void LiveRangeCalc::updateLiveIns(VNInfo *OverrideVNI, SlotIndexes *Indexes) { + for (SmallVectorImpl::iterator I = LiveIn.begin(), + E = LiveIn.end(); I != E; ++I) { + if (!I->DomNode) + continue; + MachineBasicBlock *MBB = I->DomNode->getBlock(); + + VNInfo *VNI = OverrideVNI ? OverrideVNI : I->Value; + assert(VNI && "No live-in value found"); + + SlotIndex Start, End; + tie(Start, End) = Indexes->getMBBRange(MBB); + + if (I->Kill.isValid()) + I->LI->addRange(LiveRange(Start, I->Kill, VNI)); + else { + I->LI->addRange(LiveRange(Start, End, VNI)); + // The value is live-through, update LiveOut as well. Defer the Domtree + // lookup until it is needed. + assert(Seen.test(MBB->getNumber())); + LiveOut[MBB] = LiveOutPair(VNI, (MachineDomTreeNode *)0); + } + } + LiveIn.clear(); +} + + +void LiveRangeCalc::extend(LiveInterval *LI, + SlotIndex Kill, + SlotIndexes *Indexes, + MachineDominatorTree *DomTree, + VNInfo::Allocator *Alloc) { + assert(LI && "Missing live range"); + assert(Kill.isValid() && "Invalid SlotIndex"); + assert(Indexes && "Missing SlotIndexes"); + assert(DomTree && "Missing dominator tree"); + + MachineBasicBlock *KillMBB = Indexes->getMBBFromIndex(Kill.getPrevSlot()); + assert(Kill && "No MBB at Kill"); + + // Is there a def in the same MBB we can extend? + if (LI->extendInBlock(Indexes->getMBBStartIdx(KillMBB), Kill)) + return; + + // Find the single reaching def, or determine if Kill is jointly dominated by + // multiple values, and we may need to create even more phi-defs to preserve + // VNInfo SSA form. Perform a search for all predecessor blocks where we + // know the dominating VNInfo. + VNInfo *VNI = findReachingDefs(LI, KillMBB, Kill, Indexes, DomTree); + + // When there were multiple different values, we may need new PHIs. + if (!VNI) + updateSSA(Indexes, DomTree, Alloc); + + updateLiveIns(VNI, Indexes); +} + + +// This function is called by a client after using the low-level API to add +// live-out and live-in blocks. The unique value optimization is not +// available, SplitEditor::transferValues handles that case directly anyway. +void LiveRangeCalc::calculateValues(SlotIndexes *Indexes, + MachineDominatorTree *DomTree, + VNInfo::Allocator *Alloc) { + assert(Indexes && "Missing SlotIndexes"); + assert(DomTree && "Missing dominator tree"); + updateSSA(Indexes, DomTree, Alloc); + updateLiveIns(0, Indexes); +} + + +VNInfo *LiveRangeCalc::findReachingDefs(LiveInterval *LI, + MachineBasicBlock *KillMBB, + SlotIndex Kill, + SlotIndexes *Indexes, + MachineDominatorTree *DomTree) { + // Blocks where LI should be live-in. + SmallVector WorkList(1, KillMBB); + + // Remember if we have seen more than one value. + bool UniqueVNI = true; + VNInfo *TheVNI = 0; + + // Using Seen as a visited set, perform a BFS for all reaching defs. + for (unsigned i = 0; i != WorkList.size(); ++i) { + MachineBasicBlock *MBB = WorkList[i]; + assert(!MBB->pred_empty() && "Value live-in to entry block?"); + for (MachineBasicBlock::pred_iterator PI = MBB->pred_begin(), + PE = MBB->pred_end(); PI != PE; ++PI) { + MachineBasicBlock *Pred = *PI; + + // Is this a known live-out block? + if (Seen.test(Pred->getNumber())) { + if (VNInfo *VNI = LiveOut[Pred].first) { + if (TheVNI && TheVNI != VNI) + UniqueVNI = false; + TheVNI = VNI; + } + continue; + } + + SlotIndex Start, End; + tie(Start, End) = Indexes->getMBBRange(Pred); + + // First time we see Pred. Try to determine the live-out value, but set + // it as null if Pred is live-through with an unknown value. + VNInfo *VNI = LI->extendInBlock(Start, End); + setLiveOutValue(Pred, VNI); + if (VNI) { + if (TheVNI && TheVNI != VNI) + UniqueVNI = false; + TheVNI = VNI; + continue; + } + + // No, we need a live-in value for Pred as well + if (Pred != KillMBB) + WorkList.push_back(Pred); + else + // Loopback to KillMBB, so value is really live through. + Kill = SlotIndex(); + } + } + + // Transfer WorkList to LiveInBlocks in reverse order. + // This ordering works best with updateSSA(). + LiveIn.clear(); + LiveIn.reserve(WorkList.size()); + while(!WorkList.empty()) + addLiveInBlock(LI, DomTree->getNode(WorkList.pop_back_val())); + + // The kill block may not be live-through. + assert(LiveIn.back().DomNode->getBlock() == KillMBB); + LiveIn.back().Kill = Kill; + + return UniqueVNI ? TheVNI : 0; +} + + +// This is essentially the same iterative algorithm that SSAUpdater uses, +// except we already have a dominator tree, so we don't have to recompute it. +void LiveRangeCalc::updateSSA(SlotIndexes *Indexes, + MachineDominatorTree *DomTree, + VNInfo::Allocator *Alloc) { + assert(Indexes && "Missing SlotIndexes"); + assert(DomTree && "Missing dominator tree"); + + // Interate until convergence. + unsigned Changes; + do { + Changes = 0; + // Propagate live-out values down the dominator tree, inserting phi-defs + // when necessary. + for (SmallVectorImpl::iterator I = LiveIn.begin(), + E = LiveIn.end(); I != E; ++I) { + MachineDomTreeNode *Node = I->DomNode; + // Skip block if the live-in value has already been determined. + if (!Node) + continue; + MachineBasicBlock *MBB = Node->getBlock(); + MachineDomTreeNode *IDom = Node->getIDom(); + LiveOutPair IDomValue; + + // We need a live-in value to a block with no immediate dominator? + // This is probably an unreachable block that has survived somehow. + bool needPHI = !IDom || !Seen.test(IDom->getBlock()->getNumber()); + + // IDom dominates all of our predecessors, but it may not be their + // immediate dominator. Check if any of them have live-out values that are + // properly dominated by IDom. If so, we need a phi-def here. + if (!needPHI) { + IDomValue = LiveOut[IDom->getBlock()]; + + // Cache the DomTree node that defined the value. + if (IDomValue.first && !IDomValue.second) + LiveOut[IDom->getBlock()].second = IDomValue.second = + DomTree->getNode(Indexes->getMBBFromIndex(IDomValue.first->def)); + + for (MachineBasicBlock::pred_iterator PI = MBB->pred_begin(), + PE = MBB->pred_end(); PI != PE; ++PI) { + LiveOutPair &Value = LiveOut[*PI]; + if (!Value.first || Value.first == IDomValue.first) + continue; + + // Cache the DomTree node that defined the value. + if (!Value.second) + Value.second = + DomTree->getNode(Indexes->getMBBFromIndex(Value.first->def)); + + // This predecessor is carrying something other than IDomValue. + // It could be because IDomValue hasn't propagated yet, or it could be + // because MBB is in the dominance frontier of that value. + if (DomTree->dominates(IDom, Value.second)) { + needPHI = true; + break; + } + } + } + + // The value may be live-through even if Kill is set, as can happen when + // we are called from extendRange. In that case LiveOutSeen is true, and + // LiveOut indicates a foreign or missing value. + LiveOutPair &LOP = LiveOut[MBB]; + + // Create a phi-def if required. + if (needPHI) { + ++Changes; + assert(Alloc && "Need VNInfo allocator to create PHI-defs"); + SlotIndex Start, End; + tie(Start, End) = Indexes->getMBBRange(MBB); + VNInfo *VNI = I->LI->getNextValue(Start, 0, *Alloc); + VNI->setIsPHIDef(true); + I->Value = VNI; + // This block is done, we know the final value. + I->DomNode = 0; + + // Add liveness since updateLiveIns now skips this node. + if (I->Kill.isValid()) + I->LI->addRange(LiveRange(Start, I->Kill, VNI)); + else { + I->LI->addRange(LiveRange(Start, End, VNI)); + LOP = LiveOutPair(VNI, Node); + } + } else if (IDomValue.first) { + // No phi-def here. Remember incoming value. + I->Value = IDomValue.first; + + // If the IDomValue is killed in the block, don't propagate through. + if (I->Kill.isValid()) + continue; + + // Propagate IDomValue if it isn't killed: + // MBB is live-out and doesn't define its own value. + if (LOP.first == IDomValue.first) + continue; + ++Changes; + LOP = IDomValue; + } + } + } while (Changes); +} diff --git a/contrib/llvm/lib/CodeGen/LiveRangeCalc.h b/contrib/llvm/lib/CodeGen/LiveRangeCalc.h new file mode 100644 index 000000000..b8c858584 --- /dev/null +++ b/contrib/llvm/lib/CodeGen/LiveRangeCalc.h @@ -0,0 +1,226 @@ +//===---- LiveRangeCalc.h - Calculate live ranges ---------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// The LiveRangeCalc class can be used to compute live ranges from scratch. It +// caches information about values in the CFG to speed up repeated operations +// on the same live range. The cache can be shared by non-overlapping live +// ranges. SplitKit uses that when computing the live range of split products. +// +// A low-level interface is available to clients that know where a variable is +// live, but don't know which value it has as every point. LiveRangeCalc will +// propagate values down the dominator tree, and even insert PHI-defs where +// needed. SplitKit uses this faster interface when possible. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_LIVERANGECALC_H +#define LLVM_CODEGEN_LIVERANGECALC_H + +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/IndexedMap.h" +#include "llvm/CodeGen/LiveInterval.h" + +namespace llvm { + +/// Forward declarations for MachineDominators.h: +class MachineDominatorTree; +template class DomTreeNodeBase; +typedef DomTreeNodeBase MachineDomTreeNode; + +class LiveRangeCalc { + /// Seen - Bit vector of active entries in LiveOut, also used as a visited + /// set by findReachingDefs. One entry per basic block, indexed by block + /// number. This is kept as a separate bit vector because it can be cleared + /// quickly when switching live ranges. + BitVector Seen; + + /// LiveOutPair - A value and the block that defined it. The domtree node is + /// redundant, it can be computed as: MDT[Indexes.getMBBFromIndex(VNI->def)]. + typedef std::pair LiveOutPair; + + /// LiveOutMap - Map basic blocks to the value leaving the block. + typedef IndexedMap LiveOutMap; + + /// LiveOut - Map each basic block where a live range is live out to the + /// live-out value and its defining block. + /// + /// For every basic block, MBB, one of these conditions shall be true: + /// + /// 1. !Seen.count(MBB->getNumber()) + /// Blocks without a Seen bit are ignored. + /// 2. LiveOut[MBB].second.getNode() == MBB + /// The live-out value is defined in MBB. + /// 3. forall P in preds(MBB): LiveOut[P] == LiveOut[MBB] + /// The live-out value passses through MBB. All predecessors must carry + /// the same value. + /// + /// The domtree node may be null, it can be computed. + /// + /// The map can be shared by multiple live ranges as long as no two are + /// live-out of the same block. + LiveOutMap LiveOut; + + /// LiveInBlock - Information about a basic block where a live range is known + /// to be live-in, but the value has not yet been determined. + struct LiveInBlock { + // LI - The live range that is live-in to this block. The algorithms can + // handle multiple non-overlapping live ranges simultaneously. + LiveInterval *LI; + + // DomNode - Dominator tree node for the block. + // Cleared when the final value has been determined and LI has been updated. + MachineDomTreeNode *DomNode; + + // Position in block where the live-in range ends, or SlotIndex() if the + // range passes through the block. When the final value has been + // determined, the range from the block start to Kill will be added to LI. + SlotIndex Kill; + + // Live-in value filled in by updateSSA once it is known. + VNInfo *Value; + + LiveInBlock(LiveInterval *li, MachineDomTreeNode *node, SlotIndex kill) + : LI(li), DomNode(node), Kill(kill), Value(0) {} + }; + + /// LiveIn - Work list of blocks where the live-in value has yet to be + /// determined. This list is typically computed by findReachingDefs() and + /// used as a work list by updateSSA(). The low-level interface may also be + /// used to add entries directly. + SmallVector LiveIn; + + /// findReachingDefs - Assuming that LI is live-in to KillMBB and killed at + /// Kill, search for values that can reach KillMBB. All blocks that need LI + /// to be live-in are added to LiveIn. If a unique reaching def is found, + /// its value is returned, if Kill is jointly dominated by multiple values, + /// NULL is returned. + VNInfo *findReachingDefs(LiveInterval *LI, + MachineBasicBlock *KillMBB, + SlotIndex Kill, + SlotIndexes *Indexes, + MachineDominatorTree *DomTree); + + /// updateSSA - Compute the values that will be live in to all requested + /// blocks in LiveIn. Create PHI-def values as required to preserve SSA form. + /// + /// Every live-in block must be jointly dominated by the added live-out + /// blocks. No values are read from the live ranges. + void updateSSA(SlotIndexes *Indexes, + MachineDominatorTree *DomTree, + VNInfo::Allocator *Alloc); + + /// updateLiveIns - Add liveness as specified in the LiveIn vector, using VNI + /// as a wildcard value for LiveIn entries without a value. + void updateLiveIns(VNInfo *VNI, SlotIndexes*); + +public: + //===--------------------------------------------------------------------===// + // High-level interface. + //===--------------------------------------------------------------------===// + // + // Calculate live ranges from scratch. + // + + /// reset - Prepare caches for a new set of non-overlapping live ranges. The + /// caches must be reset before attempting calculations with a live range + /// that may overlap a previously computed live range, and before the first + /// live range in a function. If live ranges are not known to be + /// non-overlapping, call reset before each. + void reset(const MachineFunction *MF); + + /// calculate - Calculate the live range of a virtual register from its defs + /// and uses. LI must be empty with no values. + void calculate(LiveInterval *LI, + MachineRegisterInfo *MRI, + SlotIndexes *Indexes, + VNInfo::Allocator *Alloc); + + //===--------------------------------------------------------------------===// + // Mid-level interface. + //===--------------------------------------------------------------------===// + // + // Modify existing live ranges. + // + + /// extend - Extend the live range of LI to reach Kill. + /// + /// The existing values in LI must be live so they jointly dominate Kill. If + /// Kill is not dominated by a single existing value, PHI-defs are inserted + /// as required to preserve SSA form. If Kill is known to be dominated by a + /// single existing value, Alloc may be null. + void extend(LiveInterval *LI, + SlotIndex Kill, + SlotIndexes *Indexes, + MachineDominatorTree *DomTree, + VNInfo::Allocator *Alloc); + + /// extendToUses - Extend the live range of LI to reach all uses. + /// + /// All uses must be jointly dominated by existing liveness. PHI-defs are + /// inserted as needed to preserve SSA form. + void extendToUses(LiveInterval *LI, + MachineRegisterInfo *MRI, + SlotIndexes *Indexes, + MachineDominatorTree *DomTree, + VNInfo::Allocator *Alloc); + + //===--------------------------------------------------------------------===// + // Low-level interface. + //===--------------------------------------------------------------------===// + // + // These functions can be used to compute live ranges where the live-in and + // live-out blocks are already known, but the SSA value in each block is + // unknown. + // + // After calling reset(), add known live-out values and known live-in blocks. + // Then call calculateValues() to compute the actual value that is + // live-in to each block, and add liveness to the live ranges. + // + + /// setLiveOutValue - Indicate that VNI is live out from MBB. The + /// calculateValues() function will not add liveness for MBB, the caller + /// should take care of that. + /// + /// VNI may be null only if MBB is a live-through block also passed to + /// addLiveInBlock(). + void setLiveOutValue(MachineBasicBlock *MBB, VNInfo *VNI) { + Seen.set(MBB->getNumber()); + LiveOut[MBB] = LiveOutPair(VNI, (MachineDomTreeNode *)0); + } + + /// addLiveInBlock - Add a block with an unknown live-in value. This + /// function can only be called once per basic block. Once the live-in value + /// has been determined, calculateValues() will add liveness to LI. + /// + /// @param LI The live range that is live-in to the block. + /// @param DomNode The domtree node for the block. + /// @param Kill Index in block where LI is killed. If the value is + /// live-through, set Kill = SLotIndex() and also call + /// setLiveOutValue(MBB, 0). + void addLiveInBlock(LiveInterval *LI, + MachineDomTreeNode *DomNode, + SlotIndex Kill = SlotIndex()) { + LiveIn.push_back(LiveInBlock(LI, DomNode, Kill)); + } + + /// calculateValues - Calculate the value that will be live-in to each block + /// added with addLiveInBlock. Add PHI-def values as needed to preserve SSA + /// form. Add liveness to all live-in blocks up to the Kill point, or the + /// whole block for live-through blocks. + /// + /// Every predecessor of a live-in block must have been given a value with + /// setLiveOutValue, the value may be null for live-trough blocks. + void calculateValues(SlotIndexes *Indexes, + MachineDominatorTree *DomTree, + VNInfo::Allocator *Alloc); +}; + +} // end namespace llvm + +#endif diff --git a/contrib/llvm/lib/CodeGen/LiveRangeEdit.cpp b/contrib/llvm/lib/CodeGen/LiveRangeEdit.cpp index b385fb36b..b23f85165 100644 --- a/contrib/llvm/lib/CodeGen/LiveRangeEdit.cpp +++ b/contrib/llvm/lib/CodeGen/LiveRangeEdit.cpp @@ -319,9 +319,12 @@ void LiveRangeEdit::calculateRegClassAndHint(MachineFunction &MF, LiveIntervals &LIS, const MachineLoopInfo &Loops) { VirtRegAuxInfo VRAI(MF, LIS, Loops); + MachineRegisterInfo &MRI = MF.getRegInfo(); for (iterator I = begin(), E = end(); I != E; ++I) { LiveInterval &LI = **I; - VRAI.CalculateRegClass(LI.reg); + if (MRI.recomputeRegClass(LI.reg, MF.getTarget())) + DEBUG(dbgs() << "Inflated " << PrintReg(LI.reg) << " to " + << MRI.getRegClass(LI.reg)->getName() << '\n'); VRAI.CalculateWeightAndHint(LI); } } diff --git a/contrib/llvm/lib/CodeGen/LiveRangeEdit.h b/contrib/llvm/lib/CodeGen/LiveRangeEdit.h index db6740c1f..9b0a671ea 100644 --- a/contrib/llvm/lib/CodeGen/LiveRangeEdit.h +++ b/contrib/llvm/lib/CodeGen/LiveRangeEdit.h @@ -115,7 +115,7 @@ public: LiveInterval *get(unsigned idx) const { return newRegs_[idx+firstNew_]; } ArrayRef regs() const { - return ArrayRef(newRegs_).slice(firstNew_); + return makeArrayRef(newRegs_).slice(firstNew_); } /// FIXME: Temporary accessors until we can get rid of diff --git a/contrib/llvm/lib/CodeGen/LiveStackAnalysis.cpp b/contrib/llvm/lib/CodeGen/LiveStackAnalysis.cpp index c75196a47..939e795b4 100644 --- a/contrib/llvm/lib/CodeGen/LiveStackAnalysis.cpp +++ b/contrib/llvm/lib/CodeGen/LiveStackAnalysis.cpp @@ -44,7 +44,8 @@ void LiveStacks::releaseMemory() { S2RCMap.clear(); } -bool LiveStacks::runOnMachineFunction(MachineFunction &) { +bool LiveStacks::runOnMachineFunction(MachineFunction &MF) { + TRI = MF.getTarget().getRegisterInfo(); // FIXME: No analysis is being done right now. We are relying on the // register allocators to provide the information. return false; @@ -61,7 +62,7 @@ LiveStacks::getOrCreateInterval(int Slot, const TargetRegisterClass *RC) { } else { // Use the largest common subclass register class. const TargetRegisterClass *OldRC = S2RCMap[Slot]; - S2RCMap[Slot] = getCommonSubClass(OldRC, RC); + S2RCMap[Slot] = TRI->getCommonSubClass(OldRC, RC); } return I->second; } diff --git a/contrib/llvm/lib/CodeGen/LiveVariables.cpp b/contrib/llvm/lib/CodeGen/LiveVariables.cpp index 20bad60de..2ca90f9f0 100644 --- a/contrib/llvm/lib/CodeGen/LiveVariables.cpp +++ b/contrib/llvm/lib/CodeGen/LiveVariables.cpp @@ -662,7 +662,7 @@ void LiveVariables::removeVirtualRegistersKilled(MachineInstr *MI) { if (TargetRegisterInfo::isVirtualRegister(Reg)) { bool removed = getVarInfo(Reg).removeKill(MI); assert(removed && "kill not in register's VarInfo?"); - removed = true; + (void)removed; } } } diff --git a/contrib/llvm/lib/CodeGen/MachineBasicBlock.cpp b/contrib/llvm/lib/CodeGen/MachineBasicBlock.cpp index 8f0fb4687..4c5fe4c48 100644 --- a/contrib/llvm/lib/CodeGen/MachineBasicBlock.cpp +++ b/contrib/llvm/lib/CodeGen/MachineBasicBlock.cpp @@ -571,6 +571,11 @@ MachineBasicBlock::SplitCriticalEdge(MachineBasicBlock *Succ, Pass *P) { if (i->getOperand(ni+1).getMBB() == this) i->getOperand(ni+1).setMBB(NMBB); + // Inherit live-ins from the successor + for (MachineBasicBlock::livein_iterator I = Succ->livein_begin(), + E = Succ->livein_end(); I != E; ++I) + NMBB->addLiveIn(*I); + // Update LiveVariables. if (LV) { // Restore kills of virtual registers that were killed by the terminators. diff --git a/contrib/llvm/lib/CodeGen/MachineBlockFrequency.cpp b/contrib/llvm/lib/CodeGen/MachineBlockFrequencyInfo.cpp similarity index 51% rename from contrib/llvm/lib/CodeGen/MachineBlockFrequency.cpp rename to contrib/llvm/lib/CodeGen/MachineBlockFrequencyInfo.cpp index 893a320a6..b92cda961 100644 --- a/contrib/llvm/lib/CodeGen/MachineBlockFrequency.cpp +++ b/contrib/llvm/lib/CodeGen/MachineBlockFrequencyInfo.cpp @@ -1,4 +1,4 @@ -//====----- MachineBlockFrequency.cpp - Machine Block Frequency Analysis ----====// +//====----- MachineBlockFrequencyInfo.cpp - Machine Block Frequency Analysis ----====// // // The LLVM Compiler Infrastructure // @@ -13,47 +13,49 @@ #include "llvm/InitializePasses.h" #include "llvm/Analysis/BlockFrequencyImpl.h" -#include "llvm/CodeGen/MachineBlockFrequency.h" +#include "llvm/CodeGen/MachineBlockFrequencyInfo.h" #include "llvm/CodeGen/Passes.h" #include "llvm/CodeGen/MachineBranchProbabilityInfo.h" using namespace llvm; -INITIALIZE_PASS_BEGIN(MachineBlockFrequency, "machine-block-freq", +INITIALIZE_PASS_BEGIN(MachineBlockFrequencyInfo, "machine-block-freq", "Machine Block Frequency Analysis", true, true) INITIALIZE_PASS_DEPENDENCY(MachineBranchProbabilityInfo) -INITIALIZE_PASS_END(MachineBlockFrequency, "machine-block-freq", +INITIALIZE_PASS_END(MachineBlockFrequencyInfo, "machine-block-freq", "Machine Block Frequency Analysis", true, true) -char MachineBlockFrequency::ID = 0; +char MachineBlockFrequencyInfo::ID = 0; -MachineBlockFrequency::MachineBlockFrequency() : MachineFunctionPass(ID) { - initializeMachineBlockFrequencyPass(*PassRegistry::getPassRegistry()); +MachineBlockFrequencyInfo::MachineBlockFrequencyInfo() : MachineFunctionPass(ID) { + initializeMachineBlockFrequencyInfoPass(*PassRegistry::getPassRegistry()); MBFI = new BlockFrequencyImpl(); } -MachineBlockFrequency::~MachineBlockFrequency() { +MachineBlockFrequencyInfo::~MachineBlockFrequencyInfo() { delete MBFI; } -void MachineBlockFrequency::getAnalysisUsage(AnalysisUsage &AU) const { +void MachineBlockFrequencyInfo::getAnalysisUsage(AnalysisUsage &AU) const { AU.addRequired(); AU.setPreservesAll(); + MachineFunctionPass::getAnalysisUsage(AU); } -bool MachineBlockFrequency::runOnMachineFunction(MachineFunction &F) { +bool MachineBlockFrequencyInfo::runOnMachineFunction(MachineFunction &F) { MachineBranchProbabilityInfo &MBPI = getAnalysis(); MBFI->doFunction(&F, &MBPI); return false; } -/// getblockFreq - Return block frequency. Never return 0, value must be -/// positive. 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. +/// 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. /// -uint32_t MachineBlockFrequency::getBlockFreq(MachineBasicBlock *MBB) { +BlockFrequency MachineBlockFrequencyInfo:: +getBlockFreq(MachineBasicBlock *MBB) const { return MBFI->getBlockFreq(MBB); } diff --git a/contrib/llvm/lib/CodeGen/MachineCSE.cpp b/contrib/llvm/lib/CodeGen/MachineCSE.cpp index 3a60a37af..7eda8c129 100644 --- a/contrib/llvm/lib/CodeGen/MachineCSE.cpp +++ b/contrib/llvm/lib/CodeGen/MachineCSE.cpp @@ -430,13 +430,24 @@ bool MachineCSE::ProcessBlock(MachineBasicBlock *MBB) { unsigned NewReg = CSMI->getOperand(i).getReg(); if (OldReg == NewReg) continue; + assert(TargetRegisterInfo::isVirtualRegister(OldReg) && TargetRegisterInfo::isVirtualRegister(NewReg) && "Do not CSE physical register defs!"); + if (!isProfitableToCSE(NewReg, OldReg, CSMI, MI)) { DoCSE = false; break; } + + // Don't perform CSE if the result of the old instruction cannot exist + // within the register class of the new instruction. + const TargetRegisterClass *OldRC = MRI->getRegClass(OldReg); + if (!MRI->constrainRegClass(NewReg, OldRC)) { + DoCSE = false; + break; + } + CSEPairs.push_back(std::make_pair(OldReg, NewReg)); --NumDefs; } diff --git a/contrib/llvm/lib/CodeGen/MachineFunction.cpp b/contrib/llvm/lib/CodeGen/MachineFunction.cpp index cd2515652..20066a067 100644 --- a/contrib/llvm/lib/CodeGen/MachineFunction.cpp +++ b/contrib/llvm/lib/CodeGen/MachineFunction.cpp @@ -619,7 +619,7 @@ void MachineJumpTableInfo::dump() const { print(dbgs()); } // MachineConstantPool implementation //===----------------------------------------------------------------------===// -const Type *MachineConstantPoolEntry::getType() const { +Type *MachineConstantPoolEntry::getType() const { if (isMachineConstantPoolEntry()) return Val.MachineCPVal->getType(); return Val.ConstVal->getType(); diff --git a/contrib/llvm/lib/CodeGen/MachineInstr.cpp b/contrib/llvm/lib/CodeGen/MachineInstr.cpp index 143a29b08..a240667f7 100644 --- a/contrib/llvm/lib/CodeGen/MachineInstr.cpp +++ b/contrib/llvm/lib/CodeGen/MachineInstr.cpp @@ -51,7 +51,7 @@ using namespace llvm; /// explicitly nulled out. void MachineOperand::AddRegOperandToRegInfo(MachineRegisterInfo *RegInfo) { assert(isReg() && "Can only add reg operand to use lists"); - + // If the reginfo pointer is null, just explicitly null out or next/prev // pointers, to ensure they are not garbage. if (RegInfo == 0) { @@ -59,23 +59,23 @@ void MachineOperand::AddRegOperandToRegInfo(MachineRegisterInfo *RegInfo) { Contents.Reg.Next = 0; return; } - + // Otherwise, add this operand to the head of the registers use/def list. MachineOperand **Head = &RegInfo->getRegUseDefListHead(getReg()); - + // For SSA values, we prefer to keep the definition at the start of the list. // we do this by skipping over the definition if it is at the head of the // list. if (*Head && (*Head)->isDef()) Head = &(*Head)->Contents.Reg.Next; - + Contents.Reg.Next = *Head; if (Contents.Reg.Next) { assert(getReg() == Contents.Reg.Next->getReg() && "Different regs on the same list!"); Contents.Reg.Next->Contents.Reg.Prev = &Contents.Reg.Next; } - + Contents.Reg.Prev = Head; *Head = this; } @@ -86,7 +86,7 @@ void MachineOperand::RemoveRegOperandFromRegInfo() { assert(isOnRegUseList() && "Reg operand is not on a use list"); // Unlink this from the doubly linked list of operands. MachineOperand *NextOp = Contents.Reg.Next; - *Contents.Reg.Prev = NextOp; + *Contents.Reg.Prev = NextOp; if (NextOp) { assert(NextOp->getReg() == getReg() && "Corrupt reg use/def chain!"); NextOp->Contents.Reg.Prev = Contents.Reg.Prev; @@ -97,7 +97,7 @@ void MachineOperand::RemoveRegOperandFromRegInfo() { void MachineOperand::setReg(unsigned Reg) { if (getReg() == Reg) return; // No change. - + // Otherwise, we have to change the register. If this operand is embedded // into a machine function, we need to update the old and new register's // use/def lists. @@ -109,7 +109,7 @@ void MachineOperand::setReg(unsigned Reg) { AddRegOperandToRegInfo(&MF->getRegInfo()); return; } - + // Otherwise, just change the register, no problem. :) SmallContents.RegNo = Reg; } @@ -144,7 +144,7 @@ void MachineOperand::ChangeToImmediate(int64_t ImmVal) { if (isReg() && getParent() && getParent()->getParent() && getParent()->getParent()->getParent()) RemoveRegOperandFromRegInfo(); - + OpKind = MO_Immediate; Contents.ImmVal = ImmVal; } @@ -155,7 +155,7 @@ void MachineOperand::ChangeToImmediate(int64_t ImmVal) { void MachineOperand::ChangeToRegister(unsigned Reg, bool isDef, bool isImp, bool isKill, bool isDead, bool isUndef, bool isDebug) { - // If this operand is already a register operand, use setReg to update the + // If this operand is already a register operand, use setReg to update the // register's use/def lists. if (isReg()) { assert(!isEarlyClobber()); @@ -189,7 +189,7 @@ bool MachineOperand::isIdenticalTo(const MachineOperand &Other) const { if (getType() != Other.getType() || getTargetFlags() != Other.getTargetFlags()) return false; - + switch (getType()) { default: llvm_unreachable("Unrecognized operand type"); case MachineOperand::MO_Register: @@ -322,7 +322,7 @@ void MachineOperand::print(raw_ostream &OS, const TargetMachine *TM) const { default: llvm_unreachable("Unrecognized operand type"); } - + if (unsigned TF = getTargetFlags()) OS << "[TF=" << TF << ']'; } @@ -408,7 +408,7 @@ uint64_t MachineMemOperand::getAlignment() const { raw_ostream &llvm::operator<<(raw_ostream &OS, const MachineMemOperand &MMO) { assert((MMO.isLoad() || MMO.isStore()) && "SV has to be a load, store or both."); - + if (MMO.isVolatile()) OS << "Volatile "; @@ -417,7 +417,7 @@ raw_ostream &llvm::operator<<(raw_ostream &OS, const MachineMemOperand &MMO) { if (MMO.isStore()) OS << "ST"; OS << MMO.getSize(); - + // Print the address information. OS << "["; if (!MMO.getValue()) @@ -464,7 +464,7 @@ raw_ostream &llvm::operator<<(raw_ostream &OS, const MachineMemOperand &MMO) { /// MachineInstr ctor - This constructor creates a dummy MachineInstr with /// MCID NULL and no operands. MachineInstr::MachineInstr() - : MCID(0), NumImplicitOps(0), Flags(0), AsmPrinterFlags(0), + : MCID(0), Flags(0), AsmPrinterFlags(0), MemRefs(0), MemRefsEnd(0), Parent(0) { // Make sure that we get added to a machine basicblock @@ -484,8 +484,9 @@ void MachineInstr::addImplicitDefUseOperands() { /// implicit operands. It reserves space for the number of operands specified by /// the MCInstrDesc. MachineInstr::MachineInstr(const MCInstrDesc &tid, bool NoImp) - : MCID(&tid), NumImplicitOps(0), Flags(0), AsmPrinterFlags(0), + : MCID(&tid), Flags(0), AsmPrinterFlags(0), MemRefs(0), MemRefsEnd(0), Parent(0) { + unsigned NumImplicitOps = 0; if (!NoImp) NumImplicitOps = MCID->getNumImplicitDefs() + MCID->getNumImplicitUses(); Operands.reserve(NumImplicitOps + MCID->getNumOperands()); @@ -498,8 +499,9 @@ MachineInstr::MachineInstr(const MCInstrDesc &tid, bool NoImp) /// MachineInstr ctor - As above, but with a DebugLoc. MachineInstr::MachineInstr(const MCInstrDesc &tid, const DebugLoc dl, bool NoImp) - : MCID(&tid), NumImplicitOps(0), Flags(0), AsmPrinterFlags(0), + : MCID(&tid), Flags(0), AsmPrinterFlags(0), MemRefs(0), MemRefsEnd(0), Parent(0), debugLoc(dl) { + unsigned NumImplicitOps = 0; if (!NoImp) NumImplicitOps = MCID->getNumImplicitDefs() + MCID->getNumImplicitUses(); Operands.reserve(NumImplicitOps + MCID->getNumOperands()); @@ -510,13 +512,14 @@ MachineInstr::MachineInstr(const MCInstrDesc &tid, const DebugLoc dl, } /// MachineInstr ctor - Work exactly the same as the ctor two above, except -/// that the MachineInstr is created and added to the end of the specified +/// that the MachineInstr is created and added to the end of the specified /// basic block. MachineInstr::MachineInstr(MachineBasicBlock *MBB, const MCInstrDesc &tid) - : MCID(&tid), NumImplicitOps(0), Flags(0), AsmPrinterFlags(0), + : MCID(&tid), Flags(0), AsmPrinterFlags(0), MemRefs(0), MemRefsEnd(0), Parent(0) { assert(MBB && "Cannot use inserting ctor with null basic block!"); - NumImplicitOps = MCID->getNumImplicitDefs() + MCID->getNumImplicitUses(); + unsigned NumImplicitOps = + MCID->getNumImplicitDefs() + MCID->getNumImplicitUses(); Operands.reserve(NumImplicitOps + MCID->getNumOperands()); addImplicitDefUseOperands(); // Make sure that we get added to a machine basicblock @@ -528,10 +531,11 @@ MachineInstr::MachineInstr(MachineBasicBlock *MBB, const MCInstrDesc &tid) /// MachineInstr::MachineInstr(MachineBasicBlock *MBB, const DebugLoc dl, const MCInstrDesc &tid) - : MCID(&tid), NumImplicitOps(0), Flags(0), AsmPrinterFlags(0), + : MCID(&tid), Flags(0), AsmPrinterFlags(0), MemRefs(0), MemRefsEnd(0), Parent(0), debugLoc(dl) { assert(MBB && "Cannot use inserting ctor with null basic block!"); - NumImplicitOps = MCID->getNumImplicitDefs() + MCID->getNumImplicitUses(); + unsigned NumImplicitOps = + MCID->getNumImplicitDefs() + MCID->getNumImplicitUses(); Operands.reserve(NumImplicitOps + MCID->getNumOperands()); addImplicitDefUseOperands(); // Make sure that we get added to a machine basicblock @@ -542,7 +546,7 @@ MachineInstr::MachineInstr(MachineBasicBlock *MBB, const DebugLoc dl, /// MachineInstr ctor - Copies MachineInstr arg exactly /// MachineInstr::MachineInstr(MachineFunction &MF, const MachineInstr &MI) - : MCID(&MI.getDesc()), NumImplicitOps(0), Flags(0), AsmPrinterFlags(0), + : MCID(&MI.getDesc()), Flags(0), AsmPrinterFlags(0), MemRefs(MI.MemRefs), MemRefsEnd(MI.MemRefsEnd), Parent(0), debugLoc(MI.getDebugLoc()) { Operands.reserve(MI.getNumOperands()); @@ -550,7 +554,6 @@ MachineInstr::MachineInstr(MachineFunction &MF, const MachineInstr &MI) // Add operands for (unsigned i = 0; i != MI.getNumOperands(); ++i) addOperand(MI.getOperand(i)); - NumImplicitOps = MI.NumImplicitOps; // Copy all the flags. Flags = MI.Flags; @@ -605,102 +608,74 @@ void MachineInstr::AddRegOperandsToUseLists(MachineRegisterInfo &RegInfo) { /// addOperand - Add the specified operand to the instruction. If it is an /// implicit operand, it is added to the end of the operand list. If it is /// an explicit operand it is added at the end of the explicit operand list -/// (before the first implicit operand). +/// (before the first implicit operand). void MachineInstr::addOperand(const MachineOperand &Op) { + assert(MCID && "Cannot add operands before providing an instr descriptor"); bool isImpReg = Op.isReg() && Op.isImplicit(); - assert((isImpReg || !OperandsComplete()) && - "Trying to add an operand to a machine instr that is already done!"); - MachineRegisterInfo *RegInfo = getRegInfo(); - // If we are adding the operand to the end of the list, our job is simpler. - // This is true most of the time, so this is a reasonable optimization. - if (isImpReg || NumImplicitOps == 0) { - // We can only do this optimization if we know that the operand list won't - // reallocate. - if (Operands.empty() || Operands.size()+1 <= Operands.capacity()) { - Operands.push_back(Op); - - // Set the parent of the operand. - Operands.back().ParentMI = this; - - // If the operand is a register, update the operand's use list. - if (Op.isReg()) { - Operands.back().AddRegOperandToRegInfo(RegInfo); - // If the register operand is flagged as early, mark the operand as such - unsigned OpNo = Operands.size() - 1; - if (MCID->getOperandConstraint(OpNo, MCOI::EARLY_CLOBBER) != -1) - Operands[OpNo].setIsEarlyClobber(true); - } - return; + // If the Operands backing store is reallocated, all register operands must + // be removed and re-added to RegInfo. It is storing pointers to operands. + bool Reallocate = RegInfo && + !Operands.empty() && Operands.size() == Operands.capacity(); + + // Find the insert location for the new operand. Implicit registers go at + // the end, everything goes before the implicit regs. + unsigned OpNo = Operands.size(); + + // Remove all the implicit operands from RegInfo if they need to be shifted. + // FIXME: Allow mixed explicit and implicit operands on inline asm. + // InstrEmitter::EmitSpecialNode() is marking inline asm clobbers as + // implicit-defs, but they must not be moved around. See the FIXME in + // InstrEmitter.cpp. + if (!isImpReg && !isInlineAsm()) { + while (OpNo && Operands[OpNo-1].isReg() && Operands[OpNo-1].isImplicit()) { + --OpNo; + if (RegInfo) + Operands[OpNo].RemoveRegOperandFromRegInfo(); } } - - // Otherwise, we have to insert a real operand before any implicit ones. - unsigned OpNo = Operands.size()-NumImplicitOps; - // If this instruction isn't embedded into a function, then we don't need to - // update any operand lists. - if (RegInfo == 0) { - // Simple insertion, no reginfo update needed for other register operands. - Operands.insert(Operands.begin()+OpNo, Op); - Operands[OpNo].ParentMI = this; - - // Do explicitly set the reginfo for this operand though, to ensure the - // next/prev fields are properly nulled out. - if (Operands[OpNo].isReg()) { - Operands[OpNo].AddRegOperandToRegInfo(0); - // If the register operand is flagged as early, mark the operand as such - if (MCID->getOperandConstraint(OpNo, MCOI::EARLY_CLOBBER) != -1) - Operands[OpNo].setIsEarlyClobber(true); - } + // OpNo now points as the desired insertion point. Unless this is a variadic + // instruction, only implicit regs are allowed beyond MCID->getNumOperands(). + assert((isImpReg || MCID->isVariadic() || OpNo < MCID->getNumOperands()) && + "Trying to add an operand to a machine instr that is already done!"); - } else if (Operands.size()+1 <= Operands.capacity()) { - // Otherwise, we have to remove register operands from their register use - // list, add the operand, then add the register operands back to their use - // list. This also must handle the case when the operand list reallocates - // to somewhere else. - - // If insertion of this operand won't cause reallocation of the operand - // list, just remove the implicit operands, add the operand, then re-add all - // the rest of the operands. - for (unsigned i = OpNo, e = Operands.size(); i != e; ++i) { - assert(Operands[i].isReg() && "Should only be an implicit reg!"); - Operands[i].RemoveRegOperandFromRegInfo(); - } - - // Add the operand. If it is a register, add it to the reg list. - Operands.insert(Operands.begin()+OpNo, Op); - Operands[OpNo].ParentMI = this; - - if (Operands[OpNo].isReg()) { - Operands[OpNo].AddRegOperandToRegInfo(RegInfo); - // If the register operand is flagged as early, mark the operand as such - if (MCID->getOperandConstraint(OpNo, MCOI::EARLY_CLOBBER) != -1) - Operands[OpNo].setIsEarlyClobber(true); - } - - // Re-add all the implicit ops. - for (unsigned i = OpNo+1, e = Operands.size(); i != e; ++i) { + // All operands from OpNo have been removed from RegInfo. If the Operands + // backing store needs to be reallocated, we also need to remove any other + // register operands. + if (Reallocate) + for (unsigned i = 0; i != OpNo; ++i) + if (Operands[i].isReg()) + Operands[i].RemoveRegOperandFromRegInfo(); + + // Insert the new operand at OpNo. + Operands.insert(Operands.begin() + OpNo, Op); + Operands[OpNo].ParentMI = this; + + // The Operands backing store has now been reallocated, so we can re-add the + // operands before OpNo. + if (Reallocate) + for (unsigned i = 0; i != OpNo; ++i) + if (Operands[i].isReg()) + Operands[i].AddRegOperandToRegInfo(RegInfo); + + // When adding a register operand, tell RegInfo about it. + if (Operands[OpNo].isReg()) { + // Add the new operand to RegInfo, even when RegInfo is NULL. + // This will initialize the linked list pointers. + Operands[OpNo].AddRegOperandToRegInfo(RegInfo); + // If the register operand is flagged as early, mark the operand as such. + if (MCID->getOperandConstraint(OpNo, MCOI::EARLY_CLOBBER) != -1) + Operands[OpNo].setIsEarlyClobber(true); + } + + // Re-add all the implicit ops. + if (RegInfo) { + for (unsigned i = OpNo + 1, e = Operands.size(); i != e; ++i) { assert(Operands[i].isReg() && "Should only be an implicit reg!"); Operands[i].AddRegOperandToRegInfo(RegInfo); } - } else { - // Otherwise, we will be reallocating the operand list. Remove all reg - // operands from their list, then readd them after the operand list is - // reallocated. - RemoveRegOperandsFromUseLists(); - - Operands.insert(Operands.begin()+OpNo, Op); - Operands[OpNo].ParentMI = this; - - // Re-add all the operands. - AddRegOperandsToUseLists(*RegInfo); - - // If the register operand is flagged as early, mark the operand as such - if (Operands[OpNo].isReg() - && MCID->getOperandConstraint(OpNo, MCOI::EARLY_CLOBBER) != -1) - Operands[OpNo].setIsEarlyClobber(true); } } @@ -709,13 +684,13 @@ void MachineInstr::addOperand(const MachineOperand &Op) { /// void MachineInstr::RemoveOperand(unsigned OpNo) { assert(OpNo < Operands.size() && "Invalid operand number"); - + // Special case removing the last one. if (OpNo == Operands.size()-1) { // If needed, remove from the reg def/use list. if (Operands.back().isReg() && Operands.back().isOnRegUseList()) Operands.back().RemoveRegOperandFromRegInfo(); - + Operands.pop_back(); return; } @@ -730,7 +705,7 @@ void MachineInstr::RemoveOperand(unsigned OpNo) { Operands[i].RemoveRegOperandFromRegInfo(); } } - + Operands.erase(Operands.begin()+OpNo); if (RegInfo) { @@ -827,15 +802,6 @@ void MachineInstr::eraseFromParent() { } -/// OperandComplete - Return true if it's illegal to add a new operand -/// -bool MachineInstr::OperandsComplete() const { - unsigned short NumOperands = MCID->getNumOperands(); - if (!MCID->isVariadic() && getNumOperands()-NumImplicitOps >= NumOperands) - return true; // Broken: we have all the operands of this instruction! - return false; -} - /// getNumExplicitOperands - Returns the number of non-implicit operands. /// unsigned MachineInstr::getNumExplicitOperands() const { @@ -860,6 +826,67 @@ bool MachineInstr::isStackAligningInlineAsm() const { return false; } +int MachineInstr::findInlineAsmFlagIdx(unsigned OpIdx, + unsigned *GroupNo) const { + assert(isInlineAsm() && "Expected an inline asm instruction"); + assert(OpIdx < getNumOperands() && "OpIdx out of range"); + + // Ignore queries about the initial operands. + if (OpIdx < InlineAsm::MIOp_FirstOperand) + return -1; + + unsigned Group = 0; + unsigned NumOps; + for (unsigned i = InlineAsm::MIOp_FirstOperand, e = getNumOperands(); i < e; + i += NumOps) { + const MachineOperand &FlagMO = getOperand(i); + // If we reach the implicit register operands, stop looking. + if (!FlagMO.isImm()) + return -1; + NumOps = 1 + InlineAsm::getNumOperandRegisters(FlagMO.getImm()); + if (i + NumOps > OpIdx) { + if (GroupNo) + *GroupNo = Group; + return i; + } + ++Group; + } + return -1; +} + +const TargetRegisterClass* +MachineInstr::getRegClassConstraint(unsigned OpIdx, + const TargetInstrInfo *TII, + const TargetRegisterInfo *TRI) const { + // Most opcodes have fixed constraints in their MCInstrDesc. + if (!isInlineAsm()) + return TII->getRegClass(getDesc(), OpIdx, TRI); + + if (!getOperand(OpIdx).isReg()) + return NULL; + + // For tied uses on inline asm, get the constraint from the def. + unsigned DefIdx; + if (getOperand(OpIdx).isUse() && isRegTiedToDefOperand(OpIdx, &DefIdx)) + OpIdx = DefIdx; + + // Inline asm stores register class constraints in the flag word. + int FlagIdx = findInlineAsmFlagIdx(OpIdx); + if (FlagIdx < 0) + return NULL; + + unsigned Flag = getOperand(FlagIdx).getImm(); + unsigned RCID; + if (InlineAsm::hasRegClassConstraint(Flag, RCID)) + return TRI->getRegClass(RCID); + + // Assume that all registers in a memory operand are pointers. + if (InlineAsm::getKind(Flag) == InlineAsm::Kind_Mem) + return TRI->getPointerRegClass(); + + return NULL; +} + /// findRegisterUseOperandIdx() - Returns the MachineOperand that is a use of /// the specific register or -1 if it is not found. It further tightens /// the search criteria to a use that kills the register if isKill is true. @@ -901,7 +928,8 @@ MachineInstr::readsWritesVirtualRegister(unsigned Reg, Ops->push_back(i); if (MO.isUse()) Use |= !MO.isUndef(); - else if (MO.getSubReg()) + else if (MO.getSubReg() && !MO.isUndef()) + // A partial doesn't count as reading the register. PartDef = true; else FullDef = true; @@ -941,6 +969,10 @@ MachineInstr::findRegisterDefOperandIdx(unsigned Reg, bool isDead, bool Overlap, /// operand list that is used to represent the predicate. It returns -1 if /// none is found. int MachineInstr::findFirstPredOperandIdx() const { + // Don't call MCID.findFirstPredOperandIdx() because this variant + // is sometimes called on an instruction that's not yet complete, and + // so the number of operands is less than the MCID indicates. In + // particular, the PTX target does this. const MCInstrDesc &MCID = getDesc(); if (MCID.isPredicable()) { for (unsigned i = 0, e = getNumOperands(); i != e; ++i) @@ -950,7 +982,7 @@ int MachineInstr::findFirstPredOperandIdx() const { return -1; } - + /// isRegTiedToUseOperand - Given the index of a register def operand, /// check if the register def is tied to a source operand, due to either /// two-address elimination or inline assembly constraints. Returns the @@ -964,23 +996,13 @@ isRegTiedToUseOperand(unsigned DefOpIdx, unsigned *UseOpIdx) const { return false; // Determine the actual operand index that corresponds to this index. unsigned DefNo = 0; - unsigned DefPart = 0; - for (unsigned i = InlineAsm::MIOp_FirstOperand, e = getNumOperands(); - i < e; ) { - const MachineOperand &FMO = getOperand(i); - // After the normal asm operands there may be additional imp-def regs. - if (!FMO.isImm()) - return false; - // Skip over this def. - unsigned NumOps = InlineAsm::getNumOperandRegisters(FMO.getImm()); - unsigned PrevDef = i + 1; - i = PrevDef + NumOps; - if (i > DefOpIdx) { - DefPart = DefOpIdx - PrevDef; - break; - } - ++DefNo; - } + int FlagIdx = findInlineAsmFlagIdx(DefOpIdx, &DefNo); + if (FlagIdx < 0) + return false; + + // Which part of the group is DefOpIdx? + unsigned DefPart = DefOpIdx - (FlagIdx + 1); + for (unsigned i = InlineAsm::MIOp_FirstOperand, e = getNumOperands(); i != e; ++i) { const MachineOperand &FMO = getOperand(i); @@ -1024,20 +1046,10 @@ isRegTiedToDefOperand(unsigned UseOpIdx, unsigned *DefOpIdx) const { return false; // Find the flag operand corresponding to UseOpIdx - unsigned FlagIdx, NumOps=0; - for (FlagIdx = InlineAsm::MIOp_FirstOperand; - FlagIdx < UseOpIdx; FlagIdx += NumOps+1) { - const MachineOperand &UFMO = getOperand(FlagIdx); - // After the normal asm operands there may be additional imp-def regs. - if (!UFMO.isImm()) - return false; - NumOps = InlineAsm::getNumOperandRegisters(UFMO.getImm()); - assert(NumOps < getNumOperands() && "Invalid inline asm flag"); - if (UseOpIdx < FlagIdx+NumOps+1) - break; - } - if (FlagIdx >= UseOpIdx) + int FlagIdx = findInlineAsmFlagIdx(UseOpIdx); + if (FlagIdx < 0) return false; + const MachineOperand &UFMO = getOperand(FlagIdx); unsigned DefNo; if (InlineAsm::isUseOperandTiedToDef(UFMO.getImm(), DefNo)) { @@ -1211,7 +1223,7 @@ bool MachineInstr::hasVolatileMemoryRef() const { // conservatively assume it wasn't preserved. if (memoperands_empty()) return true; - + // Check the memory reference information for volatile references. for (mmo_iterator I = memoperands_begin(), E = memoperands_end(); I != E; ++I) if ((*I)->isVolatile()) @@ -1318,7 +1330,7 @@ void MachineInstr::dump() const { dbgs() << " " << *this; } -static void printDebugLoc(DebugLoc DL, const MachineFunction *MF, +static void printDebugLoc(DebugLoc DL, const MachineFunction *MF, raw_ostream &CommentOS) { const LLVMContext &Ctx = MF->getFunction()->getContext(); if (!DL.isUnknown()) { // Print source line info. @@ -1380,7 +1392,7 @@ void MachineInstr::print(raw_ostream &OS, const TargetMachine *TM) const { unsigned AsmDescOp = ~0u; unsigned AsmOpCount = 0; - if (isInlineAsm()) { + if (isInlineAsm() && e >= InlineAsm::MIOp_FirstOperand) { // Print asm string. OS << " "; getOperand(InlineAsm::MIOp_AsmString).print(OS, TM); @@ -1451,18 +1463,28 @@ void MachineInstr::print(raw_ostream &OS, const TargetMachine *TM) const { OS << '$' << AsmOpCount++; unsigned Flag = MO.getImm(); switch (InlineAsm::getKind(Flag)) { - case InlineAsm::Kind_RegUse: OS << ":[reguse]"; break; - case InlineAsm::Kind_RegDef: OS << ":[regdef]"; break; - case InlineAsm::Kind_RegDefEarlyClobber: OS << ":[regdef-ec]"; break; - case InlineAsm::Kind_Clobber: OS << ":[clobber]"; break; - case InlineAsm::Kind_Imm: OS << ":[imm]"; break; - case InlineAsm::Kind_Mem: OS << ":[mem]"; break; - default: OS << ":[??" << InlineAsm::getKind(Flag) << ']'; break; + case InlineAsm::Kind_RegUse: OS << ":[reguse"; break; + case InlineAsm::Kind_RegDef: OS << ":[regdef"; break; + case InlineAsm::Kind_RegDefEarlyClobber: OS << ":[regdef-ec"; break; + case InlineAsm::Kind_Clobber: OS << ":[clobber"; break; + case InlineAsm::Kind_Imm: OS << ":[imm"; break; + case InlineAsm::Kind_Mem: OS << ":[mem"; break; + default: OS << ":[??" << InlineAsm::getKind(Flag); break; + } + + unsigned RCID = 0; + if (InlineAsm::hasRegClassConstraint(Flag, RCID)) { + if (TM) + OS << ':' << TM->getRegisterInfo()->getRegClass(RCID)->getName(); + else + OS << ":RC" << RCID; } unsigned TiedTo = 0; if (InlineAsm::isUseOperandTiedToDef(Flag, TiedTo)) - OS << " [tiedto:$" << TiedTo << ']'; + OS << " tiedto:$" << TiedTo; + + OS << ']'; // Compute the index of the next operand descriptor. AsmDescOp += 1 + InlineAsm::getNumOperandRegisters(Flag); @@ -1516,7 +1538,19 @@ void MachineInstr::print(raw_ostream &OS, const TargetMachine *TM) const { } // Print debug location information. - if (!debugLoc.isUnknown() && MF) { + if (isDebugValue() && getOperand(e - 1).isMetadata()) { + if (!HaveSemi) OS << ";"; HaveSemi = true; + DIVariable DV(getOperand(e - 1).getMetadata()); + OS << " line no:" << DV.getLineNumber(); + if (MDNode *InlinedAt = DV.getInlinedAt()) { + DebugLoc InlinedAtDL = DebugLoc::getFromDILocation(InlinedAt); + if (!InlinedAtDL.isUnknown()) { + OS << " inlined @[ "; + printDebugLoc(InlinedAtDL, MF, OS); + OS << " ]"; + } + } + } else if (!debugLoc.isUnknown() && MF) { if (!HaveSemi) OS << ";"; HaveSemi = true; OS << " dbg:"; printDebugLoc(debugLoc, MF, OS); @@ -1627,7 +1661,7 @@ bool MachineInstr::addRegisterDead(unsigned IncomingReg, // new implicit operand if required. if (Found || !AddIfNotFound) return Found; - + addOperand(MachineOperand::CreateReg(IncomingReg, true /*IsDef*/, true /*IsImp*/, diff --git a/contrib/llvm/lib/CodeGen/MachineLICM.cpp b/contrib/llvm/lib/CodeGen/MachineLICM.cpp index 722ceb202..a1f80d528 100644 --- a/contrib/llvm/lib/CodeGen/MachineLICM.cpp +++ b/contrib/llvm/lib/CodeGen/MachineLICM.cpp @@ -37,10 +37,16 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/Statistic.h" +#include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; +static cl::opt +AvoidSpeculation("avoid-speculation", + cl::desc("MachineLICM should avoid speculation"), + cl::init(false), cl::Hidden); + STATISTIC(NumHoisted, "Number of machine instructions hoisted out of loops"); STATISTIC(NumLowRP, @@ -91,6 +97,17 @@ namespace { // For each opcode, keep a list of potential CSE instructions. DenseMap > CSEMap; + enum { + SpeculateFalse = 0, + SpeculateTrue = 1, + SpeculateUnknown = 2 + }; + + // If a MBB does not dominate loop exiting blocks then it may not safe + // to hoist loads from this block. + // Tri-state: 0 - false, 1 - true, 2 - unknown + unsigned SpeculationState; + public: static char ID; // Pass identification, replacement for typeid MachineLICM() : @@ -194,6 +211,10 @@ namespace { /// hoist the given loop invariant. bool IsProfitableToHoist(MachineInstr &MI); + /// IsGuaranteedToExecute - Check if this mbb is guaranteed to execute. + /// If not then a load from this mbb may not be safe to hoist. + bool IsGuaranteedToExecute(MachineBasicBlock *BB); + /// HoistRegion - Walk the specified region of the CFG (defined by all /// blocks dominated by the specified block, and that are in the current /// loop) in depth first order w.r.t the DominatorTree. This allows us to @@ -202,6 +223,13 @@ namespace { /// void HoistRegion(MachineDomTreeNode *N, bool IsHeader = false); + /// getRegisterClassIDAndCost - For a given MI, register, and the operand + /// index, return the ID and cost of its representative register class by + /// reference. + void getRegisterClassIDAndCost(const MachineInstr *MI, + unsigned Reg, unsigned OpIdx, + unsigned &RCId, unsigned &RCCost) const; + /// InitRegPressure - Find all virtual register references that are liveout /// of the preheader to initialize the starting "register pressure". Note /// this does not count live through (livein but not used) registers. @@ -229,6 +257,10 @@ namespace { bool EliminateCSE(MachineInstr *MI, DenseMap >::iterator &CI); + /// MayCSE - Return true if the given instruction will be CSE'd if it's + /// hoisted out of the loop. + bool MayCSE(MachineInstr *MI); + /// Hoist - When an instruction is found to only use loop invariant operands /// that is safe to hoist, this instruction is called to do the dirty work. /// It returns true if the instruction is hoisted. @@ -441,6 +473,12 @@ void MachineLICM::HoistRegionPostRA() { const std::vector Blocks = CurLoop->getBlocks(); for (unsigned i = 0, e = Blocks.size(); i != e; ++i) { MachineBasicBlock *BB = Blocks[i]; + + // If the header of the loop containing this basic block is a landing pad, + // then don't try to hoist instructions out of this loop. + const MachineLoop *ML = MLI->getLoopFor(BB); + if (ML && ML->getHeader()->isLandingPad()) continue; + // Conservatively treat live-in's as an external def. // FIXME: That means a reload that're reused in successor block(s) will not // be LICM'ed. @@ -452,6 +490,7 @@ void MachineLICM::HoistRegionPostRA() { ++PhysRegDefs[*AS]; } + SpeculationState = SpeculateUnknown; for (MachineBasicBlock::iterator MII = BB->begin(), E = BB->end(); MII != E; ++MII) { MachineInstr *MI = &*MII; @@ -545,6 +584,27 @@ void MachineLICM::HoistPostRA(MachineInstr *MI, unsigned Def) { Changed = true; } +// IsGuaranteedToExecute - Check if this mbb is guaranteed to execute. +// If not then a load from this mbb may not be safe to hoist. +bool MachineLICM::IsGuaranteedToExecute(MachineBasicBlock *BB) { + if (SpeculationState != SpeculateUnknown) + return SpeculationState == SpeculateFalse; + + if (BB != CurLoop->getHeader()) { + // Check loop exiting blocks. + SmallVector CurrentLoopExitingBlocks; + CurLoop->getExitingBlocks(CurrentLoopExitingBlocks); + for (unsigned i = 0, e = CurrentLoopExitingBlocks.size(); i != e; ++i) + if (!DT->dominates(BB, CurrentLoopExitingBlocks[i])) { + SpeculationState = SpeculateTrue; + return false; + } + } + + SpeculationState = SpeculateFalse; + return true; +} + /// HoistRegion - Walk the specified region of the CFG (defined by all blocks /// dominated by the specified block, and that are in the current loop) in depth /// first order w.r.t the DominatorTree. This allows us to visit definitions @@ -554,6 +614,11 @@ void MachineLICM::HoistRegion(MachineDomTreeNode *N, bool IsHeader) { assert(N != 0 && "Null dominator tree node?"); MachineBasicBlock *BB = N->getBlock(); + // If the header of the loop containing this basic block is a landing pad, + // then don't try to hoist instructions out of this loop. + const MachineLoop *ML = MLI->getLoopFor(BB); + if (ML && ML->getHeader()->isLandingPad()) return; + // If this subregion is not in the top level loop at all, exit. if (!CurLoop->contains(BB)) return; @@ -571,6 +636,7 @@ void MachineLICM::HoistRegion(MachineDomTreeNode *N, bool IsHeader) { // Remember livein register pressure. BackTrace.push_back(RegPressure); + SpeculationState = SpeculateUnknown; for (MachineBasicBlock::iterator MII = BB->begin(), E = BB->end(); MII != E; ) { MachineBasicBlock::iterator NextMII = MII; ++NextMII; @@ -596,6 +662,23 @@ static bool isOperandKill(const MachineOperand &MO, MachineRegisterInfo *MRI) { return MO.isKill() || MRI->hasOneNonDBGUse(MO.getReg()); } +/// getRegisterClassIDAndCost - For a given MI, register, and the operand +/// index, return the ID and cost of its representative register class. +void +MachineLICM::getRegisterClassIDAndCost(const MachineInstr *MI, + unsigned Reg, unsigned OpIdx, + unsigned &RCId, unsigned &RCCost) const { + const TargetRegisterClass *RC = MRI->getRegClass(Reg); + EVT VT = *RC->vt_begin(); + if (VT == MVT::untyped) { + RCId = RC->getID(); + RCCost = 1; + } else { + RCId = TLI->getRepRegClassFor(VT)->getID(); + RCCost = TLI->getRepRegClassCostFor(VT); + } +} + /// InitRegPressure - Find all virtual register references that are liveout of /// the preheader to initialize the starting "register pressure". Note this /// does not count live through (livein but not used) registers. @@ -625,18 +708,17 @@ void MachineLICM::InitRegPressure(MachineBasicBlock *BB) { continue; bool isNew = RegSeen.insert(Reg); - const TargetRegisterClass *RC = MRI->getRegClass(Reg); - EVT VT = *RC->vt_begin(); - unsigned RCId = TLI->getRepRegClassFor(VT)->getID(); + unsigned RCId, RCCost; + getRegisterClassIDAndCost(MI, Reg, i, RCId, RCCost); if (MO.isDef()) - RegPressure[RCId] += TLI->getRepRegClassCostFor(VT); + RegPressure[RCId] += RCCost; else { bool isKill = isOperandKill(MO, MRI); if (isNew && !isKill) // Haven't seen this, it must be a livein. - RegPressure[RCId] += TLI->getRepRegClassCostFor(VT); + RegPressure[RCId] += RCCost; else if (!isNew && isKill) - RegPressure[RCId] -= TLI->getRepRegClassCostFor(VT); + RegPressure[RCId] -= RCCost; } } } @@ -661,11 +743,8 @@ void MachineLICM::UpdateRegPressure(const MachineInstr *MI) { if (MO.isDef()) Defs.push_back(Reg); else if (!isNew && isOperandKill(MO, MRI)) { - const TargetRegisterClass *RC = MRI->getRegClass(Reg); - EVT VT = *RC->vt_begin(); - unsigned RCId = TLI->getRepRegClassFor(VT)->getID(); - unsigned RCCost = TLI->getRepRegClassCostFor(VT); - + unsigned RCId, RCCost; + getRegisterClassIDAndCost(MI, Reg, i, RCId, RCCost); if (RCCost > RegPressure[RCId]) RegPressure[RCId] = 0; else @@ -673,13 +752,13 @@ void MachineLICM::UpdateRegPressure(const MachineInstr *MI) { } } + unsigned Idx = 0; while (!Defs.empty()) { unsigned Reg = Defs.pop_back_val(); - const TargetRegisterClass *RC = MRI->getRegClass(Reg); - EVT VT = *RC->vt_begin(); - unsigned RCId = TLI->getRepRegClassFor(VT)->getID(); - unsigned RCCost = TLI->getRepRegClassCostFor(VT); + unsigned RCId, RCCost; + getRegisterClassIDAndCost(MI, Reg, Idx, RCId, RCCost); RegPressure[RCId] += RCCost; + ++Idx; } } @@ -691,7 +770,14 @@ bool MachineLICM::IsLICMCandidate(MachineInstr &I) { bool DontMoveAcrossStore = true; if (!I.isSafeToMove(TII, AA, DontMoveAcrossStore)) return false; - + + // If it is load then check if it is guaranteed to execute by making sure that + // it dominates all exiting blocks. If it doesn't, then there is a path out of + // the loop which does not execute this load, so we can't hoist it. + // Stores and side effects are already checked by isSafeToMove. + if (I.getDesc().mayLoad() && !IsGuaranteedToExecute(I.getParent())) + return false; + return true; } @@ -879,10 +965,8 @@ void MachineLICM::UpdateBackTraceRegPressure(const MachineInstr *MI) { if (!TargetRegisterInfo::isVirtualRegister(Reg)) continue; - const TargetRegisterClass *RC = MRI->getRegClass(Reg); - EVT VT = *RC->vt_begin(); - unsigned RCId = TLI->getRepRegClassFor(VT)->getID(); - unsigned RCCost = TLI->getRepRegClassCostFor(VT); + unsigned RCId, RCCost; + getRegisterClassIDAndCost(MI, Reg, i, RCId, RCCost); if (MO.isDef()) { DenseMap::iterator CI = Cost.find(RCId); if (CI != Cost.end()) @@ -941,16 +1025,15 @@ bool MachineLICM::IsProfitableToHoist(MachineInstr &MI) { unsigned Reg = MO.getReg(); if (!TargetRegisterInfo::isVirtualRegister(Reg)) continue; + + unsigned RCId, RCCost; + getRegisterClassIDAndCost(&MI, Reg, i, RCId, RCCost); if (MO.isDef()) { if (HasHighOperandLatency(MI, i, Reg)) { ++NumHighLatency; return true; } - const TargetRegisterClass *RC = MRI->getRegClass(Reg); - EVT VT = *RC->vt_begin(); - unsigned RCId = TLI->getRepRegClassFor(VT)->getID(); - unsigned RCCost = TLI->getRepRegClassCostFor(VT); DenseMap::iterator CI = Cost.find(RCId); if (CI != Cost.end()) CI->second += RCCost; @@ -960,10 +1043,6 @@ bool MachineLICM::IsProfitableToHoist(MachineInstr &MI) { // Is a virtual register use is a kill, hoisting it out of the loop // may actually reduce register pressure or be register pressure // neutral. - const TargetRegisterClass *RC = MRI->getRegClass(Reg); - EVT VT = *RC->vt_begin(); - unsigned RCId = TLI->getRepRegClassFor(VT)->getID(); - unsigned RCCost = TLI->getRepRegClassCostFor(VT); DenseMap::iterator CI = Cost.find(RCId); if (CI != Cost.end()) CI->second -= RCCost; @@ -979,6 +1058,13 @@ bool MachineLICM::IsProfitableToHoist(MachineInstr &MI) { return true; } + // Do not "speculate" in high register pressure situation. If an + // instruction is not guaranteed to be executed in the loop, it's best to be + // conservative. + if (AvoidSpeculation && + (!IsGuaranteedToExecute(MI.getParent()) && !MayCSE(&MI))) + return false; + // High register pressure situation, only hoist if the instruction is going to // be remat'ed. if (!TII->isTriviallyReMaterializable(&MI, AA) && @@ -1116,6 +1202,20 @@ bool MachineLICM::EliminateCSE(MachineInstr *MI, return false; } +/// MayCSE - Return true if the given instruction will be CSE'd if it's +/// hoisted out of the loop. +bool MachineLICM::MayCSE(MachineInstr *MI) { + unsigned Opcode = MI->getOpcode(); + DenseMap >::iterator + CI = CSEMap.find(Opcode); + // Do not CSE implicit_def so ProcessImplicitDefs can properly propagate + // the undef property onto uses. + if (CI == CSEMap.end() || MI->isImplicitDef()) + return false; + + return LookForDuplicate(MI, CI->second) != 0; +} + /// Hoist - When an instruction is found to use only loop invariant operands /// that are safe to hoist, this instruction is called to do the dirty work. /// diff --git a/contrib/llvm/lib/CodeGen/MachineModuleInfo.cpp b/contrib/llvm/lib/CodeGen/MachineModuleInfo.cpp index fadc594ef..80c485423 100644 --- a/contrib/llvm/lib/CodeGen/MachineModuleInfo.cpp +++ b/contrib/llvm/lib/CodeGen/MachineModuleInfo.cpp @@ -17,9 +17,7 @@ #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/Passes.h" -#include "llvm/Target/TargetInstrInfo.h" -#include "llvm/Target/TargetMachine.h" -#include "llvm/Target/TargetOptions.h" +#include "llvm/MC/MCObjectFileInfo.h" #include "llvm/MC/MCSymbol.h" #include "llvm/ADT/PointerUnion.h" #include "llvm/Support/Dwarf.h" @@ -254,11 +252,12 @@ void MMIAddrLabelMapCallbackPtr::allUsesReplacedWith(Value *V2) { //===----------------------------------------------------------------------===// MachineModuleInfo::MachineModuleInfo(const MCAsmInfo &MAI, - const TargetAsmInfo *TAI) -: ImmutablePass(ID), Context(MAI, TAI), - ObjFileMMI(0), - CurCallSite(0), CallsEHReturn(0), CallsUnwindInit(0), DbgInfoAvailable(false), - CallsExternalVAFunctionWithFloatingPointArguments(false) { + const MCRegisterInfo &MRI, + const MCObjectFileInfo *MOFI) + : ImmutablePass(ID), Context(MAI, MRI, MOFI), + ObjFileMMI(0), CompactUnwindEncoding(0), CurCallSite(0), CallsEHReturn(0), + CallsUnwindInit(0), DbgInfoAvailable(false), + CallsExternalVAFunctionWithFloatingPointArguments(false) { initializeMachineModuleInfoPass(*PassRegistry::getPassRegistry()); // Always emit some info, by default "no personality" info. Personalities.push_back(NULL); @@ -267,7 +266,8 @@ MachineModuleInfo::MachineModuleInfo(const MCAsmInfo &MAI, } MachineModuleInfo::MachineModuleInfo() -: ImmutablePass(ID), Context(*(MCAsmInfo*)0, NULL) { + : ImmutablePass(ID), + Context(*(MCAsmInfo*)0, *(MCRegisterInfo*)0, (MCObjectFileInfo*)0) { assert(0 && "This MachineModuleInfo constructor should never be called, MMI " "should always be explicitly constructed by LLVMTargetMachine"); abort(); @@ -311,6 +311,7 @@ void MachineModuleInfo::EndFunction() { FilterEnds.clear(); CallsEHReturn = 0; CallsUnwindInit = 0; + CompactUnwindEncoding = 0; VariableDbgInfo.clear(); } @@ -426,8 +427,9 @@ void MachineModuleInfo::addPersonality(MachineBasicBlock *LandingPad, /// addCatchTypeInfo - Provide the catch typeinfo for a landing pad. /// -void MachineModuleInfo::addCatchTypeInfo(MachineBasicBlock *LandingPad, - std::vector &TyInfo) { +void MachineModuleInfo:: +addCatchTypeInfo(MachineBasicBlock *LandingPad, + ArrayRef TyInfo) { LandingPadInfo &LP = getOrCreateLandingPadInfo(LandingPad); for (unsigned N = TyInfo.size(); N; --N) LP.TypeIds.push_back(getTypeIDFor(TyInfo[N - 1])); @@ -435,8 +437,9 @@ void MachineModuleInfo::addCatchTypeInfo(MachineBasicBlock *LandingPad, /// addFilterTypeInfo - Provide the filter typeinfo for a landing pad. /// -void MachineModuleInfo::addFilterTypeInfo(MachineBasicBlock *LandingPad, - std::vector &TyInfo) { +void MachineModuleInfo:: +addFilterTypeInfo(MachineBasicBlock *LandingPad, + ArrayRef TyInfo) { LandingPadInfo &LP = getOrCreateLandingPadInfo(LandingPad); std::vector IdsInFilter(TyInfo.size()); for (unsigned I = 0, E = TyInfo.size(); I != E; ++I) @@ -496,6 +499,14 @@ void MachineModuleInfo::TidyLandingPads(DenseMap *LPMap) { } } +/// setCallSiteLandingPad - Map the landing pad's EH symbol to the call site +/// indexes. +void MachineModuleInfo::setCallSiteLandingPad(MCSymbol *Sym, + ArrayRef Sites) { + for (unsigned I = 0, E = Sites.size(); I != E; ++I) + LPadToCallSiteMap[Sym].push_back(Sites[I]); +} + /// getTypeIDFor - Return the type id for the specified typeinfo. This is /// function wide. unsigned MachineModuleInfo::getTypeIDFor(const GlobalVariable *TI) { diff --git a/contrib/llvm/lib/CodeGen/MachineRegisterInfo.cpp b/contrib/llvm/lib/CodeGen/MachineRegisterInfo.cpp index 4b3e64c25..266ebf64a 100644 --- a/contrib/llvm/lib/CodeGen/MachineRegisterInfo.cpp +++ b/contrib/llvm/lib/CodeGen/MachineRegisterInfo.cpp @@ -14,10 +14,11 @@ #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/Target/TargetInstrInfo.h" -#include "llvm/Support/CommandLine.h" +#include "llvm/Target/TargetMachine.h" using namespace llvm; -MachineRegisterInfo::MachineRegisterInfo(const TargetRegisterInfo &TRI) { +MachineRegisterInfo::MachineRegisterInfo(const TargetRegisterInfo &TRI) + : TRI(&TRI), IsSSA(true) { VRegInfo.reserve(256); RegAllocHints.reserve(256); UsedPhysRegs.resize(TRI.getNumRegs()); @@ -48,18 +49,47 @@ MachineRegisterInfo::setRegClass(unsigned Reg, const TargetRegisterClass *RC) { const TargetRegisterClass * MachineRegisterInfo::constrainRegClass(unsigned Reg, - const TargetRegisterClass *RC) { + const TargetRegisterClass *RC, + unsigned MinNumRegs) { const TargetRegisterClass *OldRC = getRegClass(Reg); if (OldRC == RC) return RC; - const TargetRegisterClass *NewRC = getCommonSubClass(OldRC, RC); - if (!NewRC) + const TargetRegisterClass *NewRC = TRI->getCommonSubClass(OldRC, RC); + if (!NewRC || NewRC == OldRC) + return NewRC; + if (NewRC->getNumRegs() < MinNumRegs) return 0; - if (NewRC != OldRC) - setRegClass(Reg, NewRC); + setRegClass(Reg, NewRC); return NewRC; } +bool +MachineRegisterInfo::recomputeRegClass(unsigned Reg, const TargetMachine &TM) { + const TargetInstrInfo *TII = TM.getInstrInfo(); + const TargetRegisterClass *OldRC = getRegClass(Reg); + const TargetRegisterClass *NewRC = TRI->getLargestLegalSuperClass(OldRC); + + // Stop early if there is no room to grow. + if (NewRC == OldRC) + return false; + + // Accumulate constraints from all uses. + for (reg_nodbg_iterator I = reg_nodbg_begin(Reg), E = reg_nodbg_end(); I != E; + ++I) { + // TRI doesn't have accurate enough information to model this yet. + if (I.getOperand().getSubReg()) + return false; + const TargetRegisterClass *OpRC = + I->getRegClassConstraint(I.getOperandNo(), TII, TRI); + if (OpRC) + NewRC = TRI->getCommonSubClass(NewRC, OpRC); + if (!NewRC || NewRC == OldRC) + return false; + } + setRegClass(Reg, NewRC); + return true; +} + /// createVirtualRegister - Create and return a new virtual register in the /// function with the specified register class. /// diff --git a/contrib/llvm/lib/CodeGen/MachineSink.cpp b/contrib/llvm/lib/CodeGen/MachineSink.cpp index 916dff70a..29cfb4995 100644 --- a/contrib/llvm/lib/CodeGen/MachineSink.cpp +++ b/contrib/llvm/lib/CodeGen/MachineSink.cpp @@ -382,6 +382,25 @@ static bool AvoidsSinking(MachineInstr *MI, MachineRegisterInfo *MRI) { return MI->isInsertSubreg() || MI->isSubregToReg() || MI->isRegSequence(); } +/// collectDebgValues - Scan instructions following MI and collect any +/// matching DBG_VALUEs. +static void collectDebugValues(MachineInstr *MI, + SmallVector & DbgValues) { + DbgValues.clear(); + if (!MI->getOperand(0).isReg()) + return; + + MachineBasicBlock::iterator DI = MI; ++DI; + for (MachineBasicBlock::iterator DE = MI->getParent()->end(); + DI != DE; ++DI) { + if (!DI->isDebugValue()) + return; + if (DI->getOperand(0).isReg() && + DI->getOperand(0).getReg() == MI->getOperand(0).getReg()) + DbgValues.push_back(DI); + } +} + /// SinkInstruction - Determine whether it is safe to sink the specified machine /// instruction out of its current block into a successor. bool MachineSinking::SinkInstruction(MachineInstr *MI, bool &SawStore) { @@ -598,10 +617,22 @@ bool MachineSinking::SinkInstruction(MachineInstr *MI, bool &SawStore) { while (InsertPos != SuccToSinkTo->end() && InsertPos->isPHI()) ++InsertPos; + // collect matching debug values. + SmallVector DbgValuesToSink; + collectDebugValues(MI, DbgValuesToSink); + // Move the instruction. SuccToSinkTo->splice(InsertPos, ParentBlock, MI, ++MachineBasicBlock::iterator(MI)); + // Move debug values. + for (SmallVector::iterator DBI = DbgValuesToSink.begin(), + DBE = DbgValuesToSink.end(); DBI != DBE; ++DBI) { + MachineInstr *DbgMI = *DBI; + SuccToSinkTo->splice(InsertPos, ParentBlock, DbgMI, + ++MachineBasicBlock::iterator(DbgMI)); + } + // Conservatively, clear any kill flags, since it's possible that they are no // longer correct. MI->clearKillInfo(); diff --git a/contrib/llvm/lib/CodeGen/MachineVerifier.cpp b/contrib/llvm/lib/CodeGen/MachineVerifier.cpp index 7a55852a1..26847d39e 100644 --- a/contrib/llvm/lib/CodeGen/MachineVerifier.cpp +++ b/contrib/llvm/lib/CodeGen/MachineVerifier.cpp @@ -72,6 +72,8 @@ namespace { typedef DenseSet RegSet; typedef DenseMap RegMap; + const MachineInstr *FirstTerminator; + BitVector regsReserved; RegSet regsLive; RegVector regsDefined, regsDead, regsKilled; @@ -389,6 +391,8 @@ static bool matchPair(MachineBasicBlock::const_succ_iterator i, void MachineVerifier::visitMachineBasicBlockBefore(const MachineBasicBlock *MBB) { + FirstTerminator = 0; + // Count the number of landing pad successors. SmallPtrSet LandingPadSuccs; for (MachineBasicBlock::const_succ_iterator I = MBB->succ_begin(), @@ -570,6 +574,18 @@ void MachineVerifier::visitMachineInstrBefore(const MachineInstr *MI) { } } + // Ensure non-terminators don't follow terminators. + if (MCID.isTerminator()) { + if (!FirstTerminator) + FirstTerminator = MI; + } else if (FirstTerminator) { + report("Non-terminator instruction after the first terminator", MI); + *OS << "First terminator was:\t" << *FirstTerminator; + } + + StringRef ErrorInfo; + if (!TII->verifyInstruction(MI, ErrorInfo)) + report(ErrorInfo.data(), MI); } void @@ -686,6 +702,11 @@ MachineVerifier::visitMachineOperand(const MachineOperand *MO, unsigned MONum) { else addRegWithSubRegs(regsDefined, Reg); + // Verify SSA form. + if (MRI->isSSA() && TargetRegisterInfo::isVirtualRegister(Reg) && + llvm::next(MRI->def_begin(Reg)) != MRI->def_end()) + report("Multiple virtual register defs in SSA form", MO, MONum); + // Check LiveInts for a live range, but only for virtual registers. if (LiveInts && TargetRegisterInfo::isVirtualRegister(Reg) && !LiveInts->isNotInMIMap(MI)) { @@ -714,20 +735,14 @@ MachineVerifier::visitMachineOperand(const MachineOperand *MO, unsigned MONum) { unsigned SubIdx = MO->getSubReg(); if (TargetRegisterInfo::isPhysicalRegister(Reg)) { - unsigned sr = Reg; if (SubIdx) { - unsigned s = TRI->getSubReg(Reg, SubIdx); - if (!s) { - report("Invalid subregister index for physical register", - MO, MONum); - return; - } - sr = s; + report("Illegal subregister index for physical register", MO, MONum); + return; } if (const TargetRegisterClass *DRC = TII->getRegClass(MCID,MONum,TRI)) { - if (!DRC->contains(sr)) { + if (!DRC->contains(Reg)) { report("Illegal physical register for instruction", MO, MONum); - *OS << TRI->getName(sr) << " is not a " + *OS << TRI->getName(Reg) << " is not a " << DRC->getName() << " register.\n"; } } @@ -735,16 +750,35 @@ MachineVerifier::visitMachineOperand(const MachineOperand *MO, unsigned MONum) { // Virtual register. const TargetRegisterClass *RC = MRI->getRegClass(Reg); if (SubIdx) { - const TargetRegisterClass *SRC = RC->getSubRegisterRegClass(SubIdx); + const TargetRegisterClass *SRC = + TRI->getSubClassWithSubReg(RC, SubIdx); if (!SRC) { report("Invalid subregister index for virtual register", MO, MONum); *OS << "Register class " << RC->getName() << " does not support subreg index " << SubIdx << "\n"; return; } - RC = SRC; + if (RC != SRC) { + report("Invalid register class for subregister index", MO, MONum); + *OS << "Register class " << RC->getName() + << " does not fully support subreg index " << SubIdx << "\n"; + return; + } } if (const TargetRegisterClass *DRC = TII->getRegClass(MCID,MONum,TRI)) { + if (SubIdx) { + const TargetRegisterClass *SuperRC = + TRI->getLargestLegalSuperClass(RC); + if (!SuperRC) { + report("No largest legal super class exists.", MO, MONum); + return; + } + DRC = TRI->getMatchingSuperRegClass(SuperRC, DRC, SubIdx); + if (!DRC) { + report("No matching super-reg register class.", MO, MONum); + return; + } + } if (!RC->hasSuperClassEq(DRC)) { report("Illegal virtual register for instruction", MO, MONum); *OS << "Expected a " << DRC->getName() << " register, but got a " @@ -1161,18 +1195,8 @@ void MachineVerifier::verifyLiveIntervals() { SlotIndex PEnd = LiveInts->getMBBEndIdx(*PI).getPrevSlot(); const VNInfo *PVNI = LI.getVNInfoAt(PEnd); - if (VNI->isPHIDef() && VNI->def == LiveInts->getMBBStartIdx(MFI)) { - if (PVNI && !PVNI->hasPHIKill()) { - report("Value live out of predecessor doesn't have PHIKill", MF); - *OS << "Valno #" << PVNI->id << " live out of BB#" - << (*PI)->getNumber() << '@' << PEnd - << " doesn't have PHIKill, but Valno #" << VNI->id - << " is PHIDef and defined at the beginning of BB#" - << MFI->getNumber() << '@' << LiveInts->getMBBStartIdx(MFI) - << " in " << LI << '\n'; - } + if (VNI->isPHIDef() && VNI->def == LiveInts->getMBBStartIdx(MFI)) continue; - } if (!PVNI) { report("Register not marked live out of predecessor", *PI); diff --git a/contrib/llvm/lib/CodeGen/PHIElimination.cpp b/contrib/llvm/lib/CodeGen/PHIElimination.cpp index af65f13bf..6994aa58f 100644 --- a/contrib/llvm/lib/CodeGen/PHIElimination.cpp +++ b/contrib/llvm/lib/CodeGen/PHIElimination.cpp @@ -109,6 +109,9 @@ bool PHIElimination::runOnMachineFunction(MachineFunction &MF) { bool Changed = false; + // This pass takes the function out of SSA form. + MRI->leaveSSA(); + // Split critical edges to help the coalescer if (!DisableEdgeSplitting) { if (LiveVariables *LV = getAnalysisIfAvailable()) { diff --git a/contrib/llvm/lib/CodeGen/PeepholeOptimizer.cpp b/contrib/llvm/lib/CodeGen/PeepholeOptimizer.cpp index c523e39bc..bbc7ce2d0 100644 --- a/contrib/llvm/lib/CodeGen/PeepholeOptimizer.cpp +++ b/contrib/llvm/lib/CodeGen/PeepholeOptimizer.cpp @@ -295,7 +295,6 @@ bool PeepholeOptimizer::OptimizeBitcastInstr(MachineInstr *MI, if (!DefMI || !DefMI->getDesc().isBitcast()) return false; - unsigned SrcDef = 0; unsigned SrcSrc = 0; NumDefs = DefMI->getDesc().getNumDefs(); NumSrcs = DefMI->getDesc().getNumOperands() - NumDefs; @@ -308,13 +307,13 @@ bool PeepholeOptimizer::OptimizeBitcastInstr(MachineInstr *MI, unsigned Reg = MO.getReg(); if (!Reg) continue; - if (MO.isDef()) - SrcDef = Reg; - else if (SrcSrc) - // Multiple sources? - return false; - else - SrcSrc = Reg; + if (!MO.isDef()) { + if (SrcSrc) + // Multiple sources? + return false; + else + SrcSrc = Reg; + } } if (MRI->getRegClass(SrcSrc) != MRI->getRegClass(Def)) @@ -434,6 +433,7 @@ bool PeepholeOptimizer::runOnMachineFunction(MachineFunction &MF) { if (MCID.isBitcast()) { if (OptimizeBitcastInstr(MI, MBB)) { // MI is deleted. + LocalMIs.erase(MI); Changed = true; MII = First ? I->begin() : llvm::next(PMII); continue; @@ -441,6 +441,7 @@ bool PeepholeOptimizer::runOnMachineFunction(MachineFunction &MF) { } else if (MCID.isCompare()) { if (OptimizeCmpInstr(MI, MBB)) { // MI is deleted. + LocalMIs.erase(MI); Changed = true; MII = First ? I->begin() : llvm::next(PMII); continue; diff --git a/contrib/llvm/lib/CodeGen/ProcessImplicitDefs.cpp b/contrib/llvm/lib/CodeGen/ProcessImplicitDefs.cpp index c04d65637..b1d8c9760 100644 --- a/contrib/llvm/lib/CodeGen/ProcessImplicitDefs.cpp +++ b/contrib/llvm/lib/CodeGen/ProcessImplicitDefs.cpp @@ -125,8 +125,14 @@ bool ProcessImplicitDefs::runOnMachineFunction(MachineFunction &fn) { LiveVariables::VarInfo& vi = LV->getVarInfo(MO.getReg()); vi.removeKill(MI); } + unsigned Reg = MI->getOperand(0).getReg(); MI->eraseFromParent(); Changed = true; + + // A REG_SEQUENCE may have been expanded into partial definitions. + // If this was the last one, mark Reg as implicitly defined. + if (TargetRegisterInfo::isVirtualRegister(Reg) && MRI->def_empty(Reg)) + ImpDefRegs.insert(Reg); continue; } } diff --git a/contrib/llvm/lib/CodeGen/PrologEpilogInserter.cpp b/contrib/llvm/lib/CodeGen/PrologEpilogInserter.cpp index a901c5fef..32c932552 100644 --- a/contrib/llvm/lib/CodeGen/PrologEpilogInserter.cpp +++ b/contrib/llvm/lib/CodeGen/PrologEpilogInserter.cpp @@ -29,6 +29,7 @@ #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/RegisterScavenging.h" #include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" #include "llvm/Target/TargetRegisterInfo.h" #include "llvm/Target/TargetFrameLowering.h" #include "llvm/Target/TargetInstrInfo.h" @@ -54,6 +55,8 @@ INITIALIZE_PASS_END(PEI, "prologepilog", STATISTIC(NumVirtualFrameRegs, "Number of virtual frame regs encountered"); STATISTIC(NumScavengedRegs, "Number of frame index regs scavenged"); +STATISTIC(NumBytesStackSpace, + "Number of bytes used for stack in all functions"); /// createPrologEpilogCodeInserter - This function returns a pass that inserts /// prolog and epilog code, and eliminates abstract frame references. @@ -677,7 +680,9 @@ void PEI::calculateFrameObjectOffsets(MachineFunction &Fn) { } // Update frame info to pretend that this is part of the stack... - MFI->setStackSize(Offset - LocalAreaOffset); + int64_t StackSize = Offset - LocalAreaOffset; + MFI->setStackSize(StackSize); + NumBytesStackSpace += StackSize; } /// insertPrologEpilogCode - Scan the function for modified callee saved @@ -696,6 +701,13 @@ void PEI::insertPrologEpilogCode(MachineFunction &Fn) { if (!I->empty() && I->back().getDesc().isReturn()) TFI.emitEpilogue(Fn, *I); } + + // Emit additional code that is required to support segmented stacks, if + // we've been asked for it. This, when linked with a runtime with support + // for segmented stacks (libgcc is one), will result in allocating stack + // space in small chunks instead of one large contiguous block. + if (EnableSegmentedStacks) + TFI.adjustForSegmentedStacks(Fn); } /// replaceFrameIndices - Replace all MO_FrameIndex operands with physical diff --git a/contrib/llvm/lib/CodeGen/RegAllocBasic.cpp b/contrib/llvm/lib/CodeGen/RegAllocBasic.cpp index 5ea26adc7..5496d69fd 100644 --- a/contrib/llvm/lib/CodeGen/RegAllocBasic.cpp +++ b/contrib/llvm/lib/CodeGen/RegAllocBasic.cpp @@ -20,7 +20,6 @@ #include "RenderMachineFunction.h" #include "Spiller.h" #include "VirtRegMap.h" -#include "RegisterCoalescer.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/Statistic.h" #include "llvm/Analysis/AliasAnalysis.h" @@ -160,7 +159,7 @@ void RABasic::getAnalysisUsage(AnalysisUsage &AU) const { AU.addPreserved(); if (StrongPHIElim) AU.addRequiredID(StrongPHIEliminationID); - AU.addRequiredTransitive(); + AU.addRequiredTransitiveID(RegisterCoalescerPassID); AU.addRequired(); AU.addRequired(); AU.addPreserved(); @@ -439,6 +438,7 @@ void RegAllocBase::addMBBLiveIns(MachineFunction *MF) { LiveIntervalUnion &LiveUnion = PhysReg2LiveUnion[PhysReg]; if (LiveUnion.empty()) continue; + DEBUG(dbgs() << PrintReg(PhysReg, TRI) << " live-in:"); MachineFunction::iterator MBB = llvm::next(MF->begin()); MachineFunction::iterator MFE = MF->end(); SlotIndex Start, Stop; @@ -449,6 +449,8 @@ void RegAllocBase::addMBBLiveIns(MachineFunction *MF) { if (SI.start() <= Start) { if (!MBB->isLiveIn(PhysReg)) MBB->addLiveIn(PhysReg); + DEBUG(dbgs() << "\tBB#" << MBB->getNumber() << ':' + << PrintReg(SI.value()->reg, TRI)); } else if (SI.start() > Stop) MBB = Indexes->getMBBFromIndex(SI.start().getPrevIndex()); if (++MBB == MFE) @@ -456,6 +458,7 @@ void RegAllocBase::addMBBLiveIns(MachineFunction *MF) { tie(Start, Stop) = Indexes->getMBBRange(MBB); SI.advanceTo(Start); } + DEBUG(dbgs() << '\n'); } } @@ -495,8 +498,9 @@ unsigned RABasic::selectOrSplit(LiveInterval &VirtReg, // Found an available register. return PhysReg; } + Queries[interfReg].collectInterferingVRegs(1); LiveInterval *interferingVirtReg = - Queries[interfReg].firstInterference().liveUnionPos().value(); + Queries[interfReg].interferingVRegs().front(); // The current VirtReg must either be spillable, or one of its interferences // must have less spill weight. diff --git a/contrib/llvm/lib/CodeGen/RegAllocGreedy.cpp b/contrib/llvm/lib/CodeGen/RegAllocGreedy.cpp index e235e87b5..f54a2c85d 100644 --- a/contrib/llvm/lib/CodeGen/RegAllocGreedy.cpp +++ b/contrib/llvm/lib/CodeGen/RegAllocGreedy.cpp @@ -22,7 +22,6 @@ #include "SpillPlacement.h" #include "SplitKit.h" #include "VirtRegMap.h" -#include "RegisterCoalescer.h" #include "llvm/ADT/Statistic.h" #include "llvm/Analysis/AliasAnalysis.h" #include "llvm/Function.h" @@ -38,6 +37,7 @@ #include "llvm/CodeGen/Passes.h" #include "llvm/CodeGen/RegAllocRegistry.h" #include "llvm/Target/TargetOptions.h" +#include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" @@ -51,6 +51,15 @@ STATISTIC(NumGlobalSplits, "Number of split global live ranges"); STATISTIC(NumLocalSplits, "Number of split local live ranges"); STATISTIC(NumEvicted, "Number of interferences evicted"); +static cl::opt +SplitSpillMode("split-spill-mode", cl::Hidden, + cl::desc("Spill mode for splitting live ranges"), + cl::values(clEnumValN(SplitEditor::SM_Partition, "default", "Default"), + clEnumValN(SplitEditor::SM_Size, "size", "Optimize for size"), + clEnumValN(SplitEditor::SM_Speed, "speed", "Optimize for speed"), + clEnumValEnd), + cl::init(SplitEditor::SM_Partition)); + static RegisterRegAlloc greedyRegAlloc("greedy", "greedy register allocator", createGreedyRegisterAllocator); @@ -90,12 +99,26 @@ class RAGreedy : public MachineFunctionPass, // range splitting algorithm terminates, something that is otherwise hard to // ensure. enum LiveRangeStage { - RS_New, ///< Never seen before. - RS_First, ///< First time in the queue. - RS_Second, ///< Second time in the queue. - RS_Global, ///< Produced by global splitting. - RS_Local, ///< Produced by local splitting. - RS_Spill ///< Produced by spilling. + /// Newly created live range that has never been queued. + RS_New, + + /// Only attempt assignment and eviction. Then requeue as RS_Split. + RS_Assign, + + /// Attempt live range splitting if assignment is impossible. + RS_Split, + + /// Attempt more aggressive live range splitting that is guaranteed to make + /// progress. This is used for split products that may not be making + /// progress. + RS_Split2, + + /// Live range will be spilled. No more splitting will be attempted. + RS_Spill, + + /// There is nothing more we can do to this live range. Abort compilation + /// if it can't be assigned. + RS_Done }; static const char *const StageName[]; @@ -157,17 +180,38 @@ class RAGreedy : public MachineFunctionPass, /// Global live range splitting candidate info. struct GlobalSplitCandidate { + // Register intended for assignment, or 0. unsigned PhysReg; + + // SplitKit interval index for this candidate. + unsigned IntvIdx; + + // Interference for PhysReg. InterferenceCache::Cursor Intf; + + // Bundles where this candidate should be live. BitVector LiveBundles; SmallVector ActiveBlocks; void reset(InterferenceCache &Cache, unsigned Reg) { PhysReg = Reg; + IntvIdx = 0; Intf.setPhysReg(Cache, Reg); LiveBundles.clear(); ActiveBlocks.clear(); } + + // Set B[i] = C for every live bundle where B[i] was NoCand. + unsigned getBundles(SmallVectorImpl &B, unsigned C) { + unsigned Count = 0; + for (int i = LiveBundles.find_first(); i >= 0; + i = LiveBundles.find_next(i)) + if (B[i] == NoCand) { + B[i] = C; + Count++; + } + return Count; + } }; /// Candidate info for for each PhysReg in AllocationOrder. @@ -175,6 +219,12 @@ class RAGreedy : public MachineFunctionPass, /// class. SmallVector GlobalCand; + enum { NoCand = ~0u }; + + /// Candidate map. Each edge bundle is assigned to a GlobalCand entry, or to + /// NoCand which indicates the stack interval. + SmallVector BundleCand; + public: RAGreedy(); @@ -208,8 +258,8 @@ private: void addThroughConstraints(InterferenceCache::Cursor, ArrayRef); void growRegion(GlobalSplitCandidate &Cand); float calcGlobalSplitCost(GlobalSplitCandidate&); - void splitAroundRegion(LiveInterval&, GlobalSplitCandidate&, - SmallVectorImpl&); + bool calcCompactRegion(GlobalSplitCandidate&); + void splitAroundRegion(LiveRangeEdit&, ArrayRef); void calcGapWeights(unsigned, SmallVectorImpl&); bool shouldEvict(LiveInterval &A, bool, LiveInterval &B, bool); bool canEvictInterference(LiveInterval&, unsigned, bool, EvictionCost&); @@ -222,6 +272,8 @@ private: SmallVectorImpl&, unsigned = ~0u); unsigned tryRegionSplit(LiveInterval&, AllocationOrder&, SmallVectorImpl&); + unsigned tryBlockSplit(LiveInterval&, AllocationOrder&, + SmallVectorImpl&); unsigned tryLocalSplit(LiveInterval&, AllocationOrder&, SmallVectorImpl&); unsigned trySplit(LiveInterval&, AllocationOrder&, @@ -233,12 +285,12 @@ char RAGreedy::ID = 0; #ifndef NDEBUG const char *const RAGreedy::StageName[] = { - "RS_New", - "RS_First", - "RS_Second", - "RS_Global", - "RS_Local", - "RS_Spill" + "RS_New", + "RS_Assign", + "RS_Split", + "RS_Split2", + "RS_Spill", + "RS_Done" }; #endif @@ -278,7 +330,7 @@ void RAGreedy::getAnalysisUsage(AnalysisUsage &AU) const { AU.addPreserved(); if (StrongPHIElim) AU.addRequiredID(StrongPHIEliminationID); - AU.addRequiredTransitive(); + AU.addRequiredTransitiveID(RegisterCoalescerPassID); AU.addRequired(); AU.addRequired(); AU.addPreserved(); @@ -325,9 +377,15 @@ void RAGreedy::LRE_WillShrinkVirtReg(unsigned VirtReg) { } void RAGreedy::LRE_DidCloneVirtReg(unsigned New, unsigned Old) { + // Cloning a register we haven't even heard about yet? Just ignore it. + if (!ExtraRegInfo.inBounds(Old)) + return; + // LRE may clone a virtual register because dead code elimination causes it to - // be split into connected components. Ensure that the new register gets the + // be split into connected components. The new components are much smaller + // than the original, so they should get a new chance at being assigned. // same stage as the parent. + ExtraRegInfo[Old].Stage = RS_Assign; ExtraRegInfo.grow(New); ExtraRegInfo[New] = ExtraRegInfo[Old]; } @@ -350,16 +408,15 @@ void RAGreedy::enqueue(LiveInterval *LI) { ExtraRegInfo.grow(Reg); if (ExtraRegInfo[Reg].Stage == RS_New) - ExtraRegInfo[Reg].Stage = RS_First; + ExtraRegInfo[Reg].Stage = RS_Assign; - if (ExtraRegInfo[Reg].Stage == RS_Second) + if (ExtraRegInfo[Reg].Stage == RS_Split) { // Unsplit ranges that couldn't be allocated immediately are deferred until - // everything else has been allocated. Long ranges are allocated last so - // they are split against realistic interference. - Prio = (1u << 31) - Size; - else { - // Everything else is allocated in long->short order. Long ranges that don't - // fit should be spilled ASAP so they don't create interference. + // everything else has been allocated. + Prio = Size; + } else { + // Everything is allocated in long->short order. Long ranges that don't fit + // should be spilled (or split) ASAP so they don't create interference. Prio = (1u << 31) + Size; // Boost ranges that have a physical register hint. @@ -442,7 +499,7 @@ unsigned RAGreedy::tryAssign(LiveInterval &VirtReg, /// @param BreaksHint True when B is already assigned to its preferred register. bool RAGreedy::shouldEvict(LiveInterval &A, bool IsHint, LiveInterval &B, bool BreaksHint) { - bool CanSplit = getStage(B) <= RS_Second; + bool CanSplit = getStage(B) < RS_Spill; // Be fairly aggressive about following hints as long as the evictee can be // split. @@ -487,7 +544,7 @@ bool RAGreedy::canEvictInterference(LiveInterval &VirtReg, unsigned PhysReg, if (TargetRegisterInfo::isPhysicalRegister(Intf->reg)) return false; // Never evict spill products. They cannot split or spill. - if (getStage(*Intf) == RS_Spill) + if (getStage(*Intf) == RS_Done) return false; // Once a live range becomes small enough, it is urgent that we find a // register for it. This is indicated by an infinite spill weight. These @@ -627,6 +684,7 @@ bool RAGreedy::addSplitConstraints(InterferenceCache::Cursor Intf, Intf.moveToBlock(BC.Number); BC.Entry = BI.LiveIn ? SpillPlacement::PrefReg : SpillPlacement::DontCare; BC.Exit = BI.LiveOut ? SpillPlacement::PrefReg : SpillPlacement::DontCare; + BC.ChangesValue = BI.FirstDef; if (!Intf.hasInterference()) continue; @@ -638,9 +696,9 @@ bool RAGreedy::addSplitConstraints(InterferenceCache::Cursor Intf, if (BI.LiveIn) { if (Intf.first() <= Indexes->getMBBStartIdx(BC.Number)) BC.Entry = SpillPlacement::MustSpill, ++Ins; - else if (Intf.first() < BI.FirstUse) + else if (Intf.first() < BI.FirstInstr) BC.Entry = SpillPlacement::PrefSpill, ++Ins; - else if (Intf.first() < BI.LastUse) + else if (Intf.first() < BI.LastInstr) ++Ins; } @@ -648,9 +706,9 @@ bool RAGreedy::addSplitConstraints(InterferenceCache::Cursor Intf, if (BI.LiveOut) { if (Intf.last() >= SA->getLastSplitPoint(BC.Number)) BC.Exit = SpillPlacement::MustSpill, ++Ins; - else if (Intf.last() > BI.LastUse) + else if (Intf.last() > BI.LastInstr) BC.Exit = SpillPlacement::PrefSpill, ++Ins; - else if (Intf.last() > BI.FirstUse) + else if (Intf.last() > BI.FirstInstr) ++Ins; } @@ -684,7 +742,7 @@ void RAGreedy::addThroughConstraints(InterferenceCache::Cursor Intf, assert(T < GroupSize && "Array overflow"); TBS[T] = Number; if (++T == GroupSize) { - SpillPlacer->addLinks(ArrayRef(TBS, T)); + SpillPlacer->addLinks(makeArrayRef(TBS, T)); T = 0; } continue; @@ -714,7 +772,7 @@ void RAGreedy::addThroughConstraints(InterferenceCache::Cursor Intf, ArrayRef Array(BCS, B); SpillPlacer->addConstraints(Array); - SpillPlacer->addLinks(ArrayRef(TBS, T)); + SpillPlacer->addLinks(makeArrayRef(TBS, T)); } void RAGreedy::growRegion(GlobalSplitCandidate &Cand) { @@ -749,8 +807,16 @@ void RAGreedy::growRegion(GlobalSplitCandidate &Cand) { // Any new blocks to add? if (ActiveBlocks.size() == AddedTo) break; - addThroughConstraints(Cand.Intf, - ArrayRef(ActiveBlocks).slice(AddedTo)); + + // Compute through constraints from the interference, or assume that all + // through blocks prefer spilling when forming compact regions. + ArrayRef NewBlocks = makeArrayRef(ActiveBlocks).slice(AddedTo); + if (Cand.PhysReg) + addThroughConstraints(Cand.Intf, NewBlocks); + else + // Provide a strong negative bias on through blocks to prevent unwanted + // liveness on loop backedges. + SpillPlacer->addPrefSpill(NewBlocks, /* Strong= */ true); AddedTo = ActiveBlocks.size(); // Perhaps iterating can enable more bundles? @@ -759,11 +825,55 @@ void RAGreedy::growRegion(GlobalSplitCandidate &Cand) { DEBUG(dbgs() << ", v=" << Visited); } +/// calcCompactRegion - Compute the set of edge bundles that should be live +/// when splitting the current live range into compact regions. Compact +/// regions can be computed without looking at interference. They are the +/// regions formed by removing all the live-through blocks from the live range. +/// +/// Returns false if the current live range is already compact, or if the +/// compact regions would form single block regions anyway. +bool RAGreedy::calcCompactRegion(GlobalSplitCandidate &Cand) { + // Without any through blocks, the live range is already compact. + if (!SA->getNumThroughBlocks()) + return false; + + // Compact regions don't correspond to any physreg. + Cand.reset(IntfCache, 0); + + DEBUG(dbgs() << "Compact region bundles"); + + // Use the spill placer to determine the live bundles. GrowRegion pretends + // that all the through blocks have interference when PhysReg is unset. + SpillPlacer->prepare(Cand.LiveBundles); + + // The static split cost will be zero since Cand.Intf reports no interference. + float Cost; + if (!addSplitConstraints(Cand.Intf, Cost)) { + DEBUG(dbgs() << ", none.\n"); + return false; + } + + growRegion(Cand); + SpillPlacer->finish(); + + if (!Cand.LiveBundles.any()) { + DEBUG(dbgs() << ", none.\n"); + return false; + } + + DEBUG({ + for (int i = Cand.LiveBundles.find_first(); i>=0; + i = Cand.LiveBundles.find_next(i)) + dbgs() << " EB#" << i; + dbgs() << ".\n"; + }); + return true; +} + /// calcSpillCost - Compute how expensive it would be to split the live range in /// SA around all use blocks instead of forming bundle regions. float RAGreedy::calcSpillCost() { float Cost = 0; - const LiveInterval &LI = SA->getParent(); ArrayRef UseBlocks = SA->getUseBlocks(); for (unsigned i = 0; i != UseBlocks.size(); ++i) { const SplitAnalysis::BlockInfo &BI = UseBlocks[i]; @@ -772,16 +882,8 @@ float RAGreedy::calcSpillCost() { Cost += SpillPlacer->getBlockFrequency(Number); // Unless the value is redefined in the block. - if (BI.LiveIn && BI.LiveOut) { - SlotIndex Start, Stop; - tie(Start, Stop) = Indexes->getMBBRange(Number); - LiveInterval::const_iterator I = LI.find(Start); - assert(I != LI.end() && "Expected live-in value"); - // Is there a different live-out value? If so, we need an extra spill - // instruction. - if (I->end < Stop) - Cost += SpillPlacer->getBlockFrequency(Number); - } + if (BI.LiveIn && BI.LiveOut && BI.FirstDef) + Cost += SpillPlacer->getBlockFrequency(Number); } return Cost; } @@ -828,81 +930,115 @@ float RAGreedy::calcGlobalSplitCost(GlobalSplitCandidate &Cand) { return GlobalCost; } -/// splitAroundRegion - Split VirtReg around the region determined by -/// LiveBundles. Make an effort to avoid interference from PhysReg. +/// splitAroundRegion - Split the current live range around the regions +/// determined by BundleCand and GlobalCand. /// -/// The 'register' interval is going to contain as many uses as possible while -/// avoiding interference. The 'stack' interval is the complement constructed by -/// SplitEditor. It will contain the rest. +/// Before calling this function, GlobalCand and BundleCand must be initialized +/// so each bundle is assigned to a valid candidate, or NoCand for the +/// stack-bound bundles. The shared SA/SE SplitAnalysis and SplitEditor +/// objects must be initialized for the current live range, and intervals +/// created for the used candidates. /// -void RAGreedy::splitAroundRegion(LiveInterval &VirtReg, - GlobalSplitCandidate &Cand, - SmallVectorImpl &NewVRegs) { - const BitVector &LiveBundles = Cand.LiveBundles; - - DEBUG({ - dbgs() << "Splitting around region for " << PrintReg(Cand.PhysReg, TRI) - << " with bundles"; - for (int i = LiveBundles.find_first(); i>=0; i = LiveBundles.find_next(i)) - dbgs() << " EB#" << i; - dbgs() << ".\n"; - }); - - InterferenceCache::Cursor &Intf = Cand.Intf; - LiveRangeEdit LREdit(VirtReg, NewVRegs, this); - SE->reset(LREdit); - - // Create the main cross-block interval. - const unsigned MainIntv = SE->openIntv(); +/// @param LREdit The LiveRangeEdit object handling the current split. +/// @param UsedCands List of used GlobalCand entries. Every BundleCand value +/// must appear in this list. +void RAGreedy::splitAroundRegion(LiveRangeEdit &LREdit, + ArrayRef UsedCands) { + // These are the intervals created for new global ranges. We may create more + // intervals for local ranges. + const unsigned NumGlobalIntvs = LREdit.size(); + DEBUG(dbgs() << "splitAroundRegion with " << NumGlobalIntvs << " globals.\n"); + assert(NumGlobalIntvs && "No global intervals configured"); + + // Isolate even single instructions when dealing with a proper sub-class. + // That guarantees register class inflation for the stack interval because it + // is all copies. + unsigned Reg = SA->getParent().reg; + bool SingleInstrs = RegClassInfo.isProperSubClass(MRI->getRegClass(Reg)); // First handle all the blocks with uses. ArrayRef UseBlocks = SA->getUseBlocks(); for (unsigned i = 0; i != UseBlocks.size(); ++i) { const SplitAnalysis::BlockInfo &BI = UseBlocks[i]; - bool RegIn = BI.LiveIn && - LiveBundles[Bundles->getBundle(BI.MBB->getNumber(), 0)]; - bool RegOut = BI.LiveOut && - LiveBundles[Bundles->getBundle(BI.MBB->getNumber(), 1)]; + unsigned Number = BI.MBB->getNumber(); + unsigned IntvIn = 0, IntvOut = 0; + SlotIndex IntfIn, IntfOut; + if (BI.LiveIn) { + unsigned CandIn = BundleCand[Bundles->getBundle(Number, 0)]; + if (CandIn != NoCand) { + GlobalSplitCandidate &Cand = GlobalCand[CandIn]; + IntvIn = Cand.IntvIdx; + Cand.Intf.moveToBlock(Number); + IntfIn = Cand.Intf.first(); + } + } + if (BI.LiveOut) { + unsigned CandOut = BundleCand[Bundles->getBundle(Number, 1)]; + if (CandOut != NoCand) { + GlobalSplitCandidate &Cand = GlobalCand[CandOut]; + IntvOut = Cand.IntvIdx; + Cand.Intf.moveToBlock(Number); + IntfOut = Cand.Intf.last(); + } + } // Create separate intervals for isolated blocks with multiple uses. - if (!RegIn && !RegOut) { + if (!IntvIn && !IntvOut) { DEBUG(dbgs() << "BB#" << BI.MBB->getNumber() << " isolated.\n"); - if (!BI.isOneInstr()) { + if (SA->shouldSplitSingleBlock(BI, SingleInstrs)) SE->splitSingleBlock(BI); - SE->selectIntv(MainIntv); - } continue; } - Intf.moveToBlock(BI.MBB->getNumber()); - - if (RegIn && RegOut) - SE->splitLiveThroughBlock(BI.MBB->getNumber(), - MainIntv, Intf.first(), - MainIntv, Intf.last()); - else if (RegIn) - SE->splitRegInBlock(BI, MainIntv, Intf.first()); + if (IntvIn && IntvOut) + SE->splitLiveThroughBlock(Number, IntvIn, IntfIn, IntvOut, IntfOut); + else if (IntvIn) + SE->splitRegInBlock(BI, IntvIn, IntfIn); else - SE->splitRegOutBlock(BI, MainIntv, Intf.last()); + SE->splitRegOutBlock(BI, IntvOut, IntfOut); } - // Handle live-through blocks. - for (unsigned i = 0, e = Cand.ActiveBlocks.size(); i != e; ++i) { - unsigned Number = Cand.ActiveBlocks[i]; - bool RegIn = LiveBundles[Bundles->getBundle(Number, 0)]; - bool RegOut = LiveBundles[Bundles->getBundle(Number, 1)]; - if (!RegIn && !RegOut) - continue; - Intf.moveToBlock(Number); - SE->splitLiveThroughBlock(Number, RegIn ? MainIntv : 0, Intf.first(), - RegOut ? MainIntv : 0, Intf.last()); + // Handle live-through blocks. The relevant live-through blocks are stored in + // the ActiveBlocks list with each candidate. We need to filter out + // duplicates. + BitVector Todo = SA->getThroughBlocks(); + for (unsigned c = 0; c != UsedCands.size(); ++c) { + ArrayRef Blocks = GlobalCand[UsedCands[c]].ActiveBlocks; + for (unsigned i = 0, e = Blocks.size(); i != e; ++i) { + unsigned Number = Blocks[i]; + if (!Todo.test(Number)) + continue; + Todo.reset(Number); + + unsigned IntvIn = 0, IntvOut = 0; + SlotIndex IntfIn, IntfOut; + + unsigned CandIn = BundleCand[Bundles->getBundle(Number, 0)]; + if (CandIn != NoCand) { + GlobalSplitCandidate &Cand = GlobalCand[CandIn]; + IntvIn = Cand.IntvIdx; + Cand.Intf.moveToBlock(Number); + IntfIn = Cand.Intf.first(); + } + + unsigned CandOut = BundleCand[Bundles->getBundle(Number, 1)]; + if (CandOut != NoCand) { + GlobalSplitCandidate &Cand = GlobalCand[CandOut]; + IntvOut = Cand.IntvIdx; + Cand.Intf.moveToBlock(Number); + IntfOut = Cand.Intf.last(); + } + if (!IntvIn && !IntvOut) + continue; + SE->splitLiveThroughBlock(Number, IntvIn, IntfIn, IntvOut, IntfOut); + } } ++NumGlobalSplits; SmallVector IntvMap; SE->finish(&IntvMap); - DebugVars->splitRegister(VirtReg.reg, LREdit.regs()); + DebugVars->splitRegister(Reg, LREdit.regs()); ExtraRegInfo.resize(MRI->getNumVirtRegs()); unsigned OrigBlocks = SA->getNumLiveBlocks(); @@ -922,18 +1058,18 @@ void RAGreedy::splitAroundRegion(LiveInterval &VirtReg, // Remainder interval. Don't try splitting again, spill if it doesn't // allocate. if (IntvMap[i] == 0) { - setStage(Reg, RS_Global); + setStage(Reg, RS_Spill); continue; } - // Main interval. Allow repeated splitting as long as the number of live + // Global intervals. Allow repeated splitting as long as the number of live // blocks is strictly decreasing. - if (IntvMap[i] == MainIntv) { + if (IntvMap[i] < NumGlobalIntvs) { if (SA->countLiveBlocks(&Reg) >= OrigBlocks) { DEBUG(dbgs() << "Main interval covers the same " << OrigBlocks << " blocks as original.\n"); // Don't allow repeated splitting as a safe guard against looping. - setStage(Reg, RS_Global); + setStage(Reg, RS_Split2); } continue; } @@ -948,11 +1084,23 @@ void RAGreedy::splitAroundRegion(LiveInterval &VirtReg, unsigned RAGreedy::tryRegionSplit(LiveInterval &VirtReg, AllocationOrder &Order, SmallVectorImpl &NewVRegs) { - float BestCost = Hysteresis * calcSpillCost(); - DEBUG(dbgs() << "Cost of isolating all blocks = " << BestCost << '\n'); - const unsigned NoCand = ~0u; - unsigned BestCand = NoCand; unsigned NumCands = 0; + unsigned BestCand = NoCand; + float BestCost; + SmallVector UsedCands; + + // Check if we can split this live range around a compact region. + bool HasCompact = calcCompactRegion(GlobalCand.front()); + if (HasCompact) { + // Yes, keep GlobalCand[0] as the compact region candidate. + NumCands = 1; + BestCost = HUGE_VALF; + } else { + // No benefit from the compact region, our fallback will be per-block + // splitting. Make sure we find a solution that is cheaper than spilling. + BestCost = Hysteresis * calcSpillCost(); + DEBUG(dbgs() << "Cost of isolating all blocks = " << BestCost << '\n'); + } Order.rewind(); while (unsigned PhysReg = Order.next()) { @@ -962,7 +1110,7 @@ unsigned RAGreedy::tryRegionSplit(LiveInterval &VirtReg, AllocationOrder &Order, unsigned WorstCount = ~0u; unsigned Worst = 0; for (unsigned i = 0; i != NumCands; ++i) { - if (i == BestCand) + if (i == BestCand || !GlobalCand[i].PhysReg) continue; unsigned Count = GlobalCand[i].LiveBundles.count(); if (Count < WorstCount) @@ -1019,14 +1167,93 @@ unsigned RAGreedy::tryRegionSplit(LiveInterval &VirtReg, AllocationOrder &Order, ++NumCands; } - if (BestCand == NoCand) + // No solutions found, fall back to single block splitting. + if (!HasCompact && BestCand == NoCand) return 0; - splitAroundRegion(VirtReg, GlobalCand[BestCand], NewVRegs); + // Prepare split editor. + LiveRangeEdit LREdit(VirtReg, NewVRegs, this); + SE->reset(LREdit, SplitSpillMode); + + // Assign all edge bundles to the preferred candidate, or NoCand. + BundleCand.assign(Bundles->getNumBundles(), NoCand); + + // Assign bundles for the best candidate region. + if (BestCand != NoCand) { + GlobalSplitCandidate &Cand = GlobalCand[BestCand]; + if (unsigned B = Cand.getBundles(BundleCand, BestCand)) { + UsedCands.push_back(BestCand); + Cand.IntvIdx = SE->openIntv(); + DEBUG(dbgs() << "Split for " << PrintReg(Cand.PhysReg, TRI) << " in " + << B << " bundles, intv " << Cand.IntvIdx << ".\n"); + (void)B; + } + } + + // Assign bundles for the compact region. + if (HasCompact) { + GlobalSplitCandidate &Cand = GlobalCand.front(); + assert(!Cand.PhysReg && "Compact region has no physreg"); + if (unsigned B = Cand.getBundles(BundleCand, 0)) { + UsedCands.push_back(0); + Cand.IntvIdx = SE->openIntv(); + DEBUG(dbgs() << "Split for compact region in " << B << " bundles, intv " + << Cand.IntvIdx << ".\n"); + (void)B; + } + } + + splitAroundRegion(LREdit, UsedCands); return 0; } +//===----------------------------------------------------------------------===// +// Per-Block Splitting +//===----------------------------------------------------------------------===// + +/// tryBlockSplit - Split a global live range around every block with uses. This +/// creates a lot of local live ranges, that will be split by tryLocalSplit if +/// they don't allocate. +unsigned RAGreedy::tryBlockSplit(LiveInterval &VirtReg, AllocationOrder &Order, + SmallVectorImpl &NewVRegs) { + assert(&SA->getParent() == &VirtReg && "Live range wasn't analyzed"); + unsigned Reg = VirtReg.reg; + bool SingleInstrs = RegClassInfo.isProperSubClass(MRI->getRegClass(Reg)); + LiveRangeEdit LREdit(VirtReg, NewVRegs, this); + SE->reset(LREdit, SplitSpillMode); + ArrayRef UseBlocks = SA->getUseBlocks(); + for (unsigned i = 0; i != UseBlocks.size(); ++i) { + const SplitAnalysis::BlockInfo &BI = UseBlocks[i]; + if (SA->shouldSplitSingleBlock(BI, SingleInstrs)) + SE->splitSingleBlock(BI); + } + // No blocks were split. + if (LREdit.empty()) + return 0; + + // We did split for some blocks. + SmallVector IntvMap; + SE->finish(&IntvMap); + + // Tell LiveDebugVariables about the new ranges. + DebugVars->splitRegister(Reg, LREdit.regs()); + + ExtraRegInfo.resize(MRI->getNumVirtRegs()); + + // Sort out the new intervals created by splitting. The remainder interval + // goes straight to spilling, the new local ranges get to stay RS_New. + for (unsigned i = 0, e = LREdit.size(); i != e; ++i) { + LiveInterval &LI = *LREdit.get(i); + if (getStage(LI) == RS_New && IntvMap[i] == 0) + setStage(LI, RS_Spill); + } + + if (VerifyEnabled) + MF->verify(this, "After splitting live range around basic blocks"); + return 0; +} + //===----------------------------------------------------------------------===// // Local Splitting //===----------------------------------------------------------------------===// @@ -1045,8 +1272,10 @@ void RAGreedy::calcGapWeights(unsigned PhysReg, const unsigned NumGaps = Uses.size()-1; // Start and end points for the interference check. - SlotIndex StartIdx = BI.LiveIn ? BI.FirstUse.getBaseIndex() : BI.FirstUse; - SlotIndex StopIdx = BI.LiveOut ? BI.LastUse.getBoundaryIndex() : BI.LastUse; + SlotIndex StartIdx = + BI.LiveIn ? BI.FirstInstr.getBaseIndex() : BI.FirstInstr; + SlotIndex StopIdx = + BI.LiveOut ? BI.LastInstr.getBoundaryIndex() : BI.LastInstr; GapWeight.assign(NumGaps, 0.0f); @@ -1056,8 +1285,8 @@ void RAGreedy::calcGapWeights(unsigned PhysReg, .checkInterference()) continue; - // We know that VirtReg is a continuous interval from FirstUse to LastUse, - // so we don't need InterferenceQuery. + // We know that VirtReg is a continuous interval from FirstInstr to + // LastInstr, so we don't need InterferenceQuery. // // Interference that overlaps an instruction is counted in both gaps // surrounding the instruction. The exception is interference before @@ -1097,8 +1326,8 @@ unsigned RAGreedy::tryLocalSplit(LiveInterval &VirtReg, AllocationOrder &Order, // while only covering a single block - A phi-def can use undef values from // predecessors, and the block could be a single-block loop. // We don't bother doing anything clever about such a case, we simply assume - // that the interval is continuous from FirstUse to LastUse. We should make - // sure that we don't do anything illegal to such an interval, though. + // that the interval is continuous from FirstInstr to LastInstr. We should + // make sure that we don't do anything illegal to such an interval, though. const SmallVectorImpl &Uses = SA->UseSlots; if (Uses.size() <= 2) @@ -1120,17 +1349,17 @@ unsigned RAGreedy::tryLocalSplit(LiveInterval &VirtReg, AllocationOrder &Order, // // Instead we use these rules: // - // 1. Allow any split for ranges with getStage() < RS_Local. (Except for the + // 1. Allow any split for ranges with getStage() < RS_Split2. (Except for the // noop split, of course). - // 2. Require progress be made for ranges with getStage() >= RS_Local. All + // 2. Require progress be made for ranges with getStage() == RS_Split2. All // the new ranges must have fewer instructions than before the split. - // 3. New ranges with the same number of instructions are marked RS_Local, + // 3. New ranges with the same number of instructions are marked RS_Split2, // smaller ranges are marked RS_New. // // These rules allow a 3 -> 2+3 split once, which we need. They also prevent // excessive splitting and infinite loops. // - bool ProgressRequired = getStage(VirtReg) >= RS_Local; + bool ProgressRequired = getStage(VirtReg) >= RS_Split2; // Best split candidate. unsigned BestBefore = NumGaps; @@ -1249,7 +1478,7 @@ unsigned RAGreedy::tryLocalSplit(LiveInterval &VirtReg, AllocationOrder &Order, DebugVars->splitRegister(VirtReg.reg, LREdit.regs()); // If the new range has the same number of instructions as before, mark it as - // RS_Local so the next split will be forced to make progress. Otherwise, + // RS_Split2 so the next split will be forced to make progress. Otherwise, // leave the new intervals as RS_New so they can compete. bool LiveBefore = BestBefore != 0 || BI.LiveIn; bool LiveAfter = BestAfter != NumGaps || BI.LiveOut; @@ -1259,7 +1488,7 @@ unsigned RAGreedy::tryLocalSplit(LiveInterval &VirtReg, AllocationOrder &Order, assert(!ProgressRequired && "Didn't make progress when it was required."); for (unsigned i = 0, e = IntvMap.size(); i != e; ++i) if (IntvMap[i] == 1) { - setStage(*LREdit.get(i), RS_Local); + setStage(*LREdit.get(i), RS_Split2); DEBUG(dbgs() << PrintReg(LREdit.get(i)->reg)); } DEBUG(dbgs() << '\n'); @@ -1278,6 +1507,10 @@ unsigned RAGreedy::tryLocalSplit(LiveInterval &VirtReg, AllocationOrder &Order, /// @return Physreg when VirtReg may be assigned and/or new NewVRegs. unsigned RAGreedy::trySplit(LiveInterval &VirtReg, AllocationOrder &Order, SmallVectorImpl&NewVRegs) { + // Ranges must be Split2 or less. + if (getStage(VirtReg) >= RS_Spill) + return 0; + // Local intervals are handled separately. if (LIS->intervalIsInOneMBB(VirtReg)) { NamedRegionTimer T("Local Splitting", TimerGroupName, TimePassesIsEnabled); @@ -1287,11 +1520,6 @@ unsigned RAGreedy::trySplit(LiveInterval &VirtReg, AllocationOrder &Order, NamedRegionTimer T("Global Splitting", TimerGroupName, TimePassesIsEnabled); - // Don't iterate global splitting. - // Move straight to spilling if this range was produced by a global split. - if (getStage(VirtReg) >= RS_Global) - return 0; - SA->analyze(&VirtReg); // FIXME: SplitAnalysis may repair broken live ranges coming from the @@ -1305,24 +1533,17 @@ unsigned RAGreedy::trySplit(LiveInterval &VirtReg, AllocationOrder &Order, return PhysReg; } - // First try to split around a region spanning multiple blocks. - unsigned PhysReg = tryRegionSplit(VirtReg, Order, NewVRegs); - if (PhysReg || !NewVRegs.empty()) - return PhysReg; - - // Then isolate blocks with multiple uses. - SplitAnalysis::BlockPtrSet Blocks; - if (SA->getMultiUseBlocks(Blocks)) { - LiveRangeEdit LREdit(VirtReg, NewVRegs, this); - SE->reset(LREdit); - SE->splitSingleBlocks(Blocks); - setStage(NewVRegs.begin(), NewVRegs.end(), RS_Global); - if (VerifyEnabled) - MF->verify(this, "After splitting live range around basic blocks"); + // First try to split around a region spanning multiple blocks. RS_Split2 + // ranges already made dubious progress with region splitting, so they go + // straight to single block splitting. + if (getStage(VirtReg) < RS_Split2) { + unsigned PhysReg = tryRegionSplit(VirtReg, Order, NewVRegs); + if (PhysReg || !NewVRegs.empty()) + return PhysReg; } - // Don't assign any physregs. - return 0; + // Then isolate blocks. + return tryBlockSplit(VirtReg, Order, NewVRegs); } @@ -1342,9 +1563,9 @@ unsigned RAGreedy::selectOrSplit(LiveInterval &VirtReg, << " Cascade " << ExtraRegInfo[VirtReg.reg].Cascade << '\n'); // Try to evict a less worthy live range, but only for ranges from the primary - // queue. The RS_Second ranges already failed to do this, and they should not + // queue. The RS_Split ranges already failed to do this, and they should not // get a second chance until they have been split. - if (Stage != RS_Second) + if (Stage != RS_Split) if (unsigned PhysReg = tryEvict(VirtReg, Order, NewVRegs)) return PhysReg; @@ -1353,8 +1574,8 @@ unsigned RAGreedy::selectOrSplit(LiveInterval &VirtReg, // The first time we see a live range, don't try to split or spill. // Wait until the second time, when all smaller ranges have been allocated. // This gives a better picture of the interference to split around. - if (Stage == RS_First) { - setStage(VirtReg, RS_Second); + if (Stage < RS_Split) { + setStage(VirtReg, RS_Split); DEBUG(dbgs() << "wait for second round\n"); NewVRegs.push_back(&VirtReg); return 0; @@ -1362,7 +1583,7 @@ unsigned RAGreedy::selectOrSplit(LiveInterval &VirtReg, // If we couldn't allocate a register from spilling, there is probably some // invalid inline assembly. The base class wil report it. - if (Stage >= RS_Spill || !VirtReg.isSpillable()) + if (Stage >= RS_Done || !VirtReg.isSpillable()) return ~0u; // Try splitting VirtReg or interferences. @@ -1374,7 +1595,7 @@ unsigned RAGreedy::selectOrSplit(LiveInterval &VirtReg, NamedRegionTimer T("Spiller", TimerGroupName, TimePassesIsEnabled); LiveRangeEdit LRE(VirtReg, NewVRegs, this); spiller().spill(LRE); - setStage(NewVRegs.begin(), NewVRegs.end(), RS_Spill); + setStage(NewVRegs.begin(), NewVRegs.end(), RS_Done); if (VerifyEnabled) MF->verify(this, "After spilling"); @@ -1408,6 +1629,7 @@ bool RAGreedy::runOnMachineFunction(MachineFunction &mf) { ExtraRegInfo.resize(MRI->getNumVirtRegs()); NextCascade = 1; IntfCache.init(MF, &PhysReg2LiveUnion[0], Indexes, TRI); + GlobalCand.resize(32); // This will grow as needed. allocatePhysRegs(); addMBBLiveIns(MF); @@ -1420,7 +1642,10 @@ bool RAGreedy::runOnMachineFunction(MachineFunction &mf) { } // Write out new DBG_VALUE instructions. - DebugVars->emitDebugValues(VRM); + { + NamedRegionTimer T("Emit Debug Info", TimerGroupName, TimePassesIsEnabled); + DebugVars->emitDebugValues(VRM); + } // The pass output is in VirtRegMap. Release all the transient data. releaseMemory(); diff --git a/contrib/llvm/lib/CodeGen/RegAllocLinearScan.cpp b/contrib/llvm/lib/CodeGen/RegAllocLinearScan.cpp index 0dd3c598c..ce3fb90b1 100644 --- a/contrib/llvm/lib/CodeGen/RegAllocLinearScan.cpp +++ b/contrib/llvm/lib/CodeGen/RegAllocLinearScan.cpp @@ -18,7 +18,6 @@ #include "VirtRegRewriter.h" #include "RegisterClassInfo.h" #include "Spiller.h" -#include "RegisterCoalescer.h" #include "llvm/Analysis/AliasAnalysis.h" #include "llvm/Function.h" #include "llvm/CodeGen/CalcSpillWeights.h" @@ -209,7 +208,7 @@ namespace { AU.addRequiredID(StrongPHIEliminationID); // Make sure PassManager knows which analyses to make available // to coalescing and which analyses coalescing invalidates. - AU.addRequiredTransitive(); + AU.addRequiredTransitiveID(RegisterCoalescerPassID); AU.addRequired(); AU.addRequiredID(LiveStacksID); AU.addPreservedID(LiveStacksID); diff --git a/contrib/llvm/lib/CodeGen/RegAllocPBQP.cpp b/contrib/llvm/lib/CodeGen/RegAllocPBQP.cpp index 72230d4b0..0d2cf2d61 100644 --- a/contrib/llvm/lib/CodeGen/RegAllocPBQP.cpp +++ b/contrib/llvm/lib/CodeGen/RegAllocPBQP.cpp @@ -450,7 +450,7 @@ void RegAllocPBQP::getAnalysisUsage(AnalysisUsage &au) const { au.addPreserved(); au.addRequired(); //au.addRequiredID(SplitCriticalEdgesID); - au.addRequired(); + au.addRequiredID(RegisterCoalescerPassID); if (customPassID) au.addRequiredID(*customPassID); au.addRequired(); diff --git a/contrib/llvm/lib/CodeGen/RegisterClassInfo.cpp b/contrib/llvm/lib/CodeGen/RegisterClassInfo.cpp index 5a77e47bc..786d279c2 100644 --- a/contrib/llvm/lib/CodeGen/RegisterClassInfo.cpp +++ b/contrib/llvm/lib/CodeGen/RegisterClassInfo.cpp @@ -99,11 +99,16 @@ void RegisterClassInfo::compute(const TargetRegisterClass *RC) const { // CSR aliases go after the volatile registers, preserve the target's order. std::copy(CSRAlias.begin(), CSRAlias.end(), &RCI.Order[N]); + // Check if RC is a proper sub-class. + if (const TargetRegisterClass *Super = TRI->getLargestLegalSuperClass(RC)) + if (Super != RC && getNumAllocatableRegs(Super) > RCI.NumRegs) + RCI.ProperSubClass = true; + DEBUG({ dbgs() << "AllocationOrder(" << RC->getName() << ") = ["; for (unsigned I = 0; I != RCI.NumRegs; ++I) dbgs() << ' ' << PrintReg(RCI.Order[I], TRI); - dbgs() << " ]\n"; + dbgs() << (RCI.ProperSubClass ? " ] (sub-class)\n" : " ]\n"); }); // RCI is now up-to-date. diff --git a/contrib/llvm/lib/CodeGen/RegisterClassInfo.h b/contrib/llvm/lib/CodeGen/RegisterClassInfo.h index d21fd67ef..2c1407096 100644 --- a/contrib/llvm/lib/CodeGen/RegisterClassInfo.h +++ b/contrib/llvm/lib/CodeGen/RegisterClassInfo.h @@ -28,11 +28,12 @@ class RegisterClassInfo { struct RCInfo { unsigned Tag; unsigned NumRegs; + bool ProperSubClass; OwningArrayPtr Order; - RCInfo() : Tag(0), NumRegs(0) {} + RCInfo() : Tag(0), NumRegs(0), ProperSubClass(false) {} operator ArrayRef() const { - return ArrayRef(Order.get(), NumRegs); + return makeArrayRef(Order.get(), NumRegs); } }; @@ -87,6 +88,16 @@ public: return get(RC); } + /// isProperSubClass - Returns true if RC has a legal super-class with more + /// allocatable registers. + /// + /// Register classes like GR32_NOSP are not proper sub-classes because %esp + /// is not allocatable. Similarly, tGPR is not a proper sub-class in Thumb + /// mode because the GPR super-class is not legal. + bool isProperSubClass(const TargetRegisterClass *RC) const { + return get(RC).ProperSubClass; + } + /// getLastCalleeSavedAlias - Returns the last callee saved register that /// overlaps PhysReg, or 0 if Reg doesn't overlap a CSR. unsigned getLastCalleeSavedAlias(unsigned PhysReg) const { diff --git a/contrib/llvm/lib/CodeGen/RegisterCoalescer.cpp b/contrib/llvm/lib/CodeGen/RegisterCoalescer.cpp index b91f92c6a..9b414d621 100644 --- a/contrib/llvm/lib/CodeGen/RegisterCoalescer.cpp +++ b/contrib/llvm/lib/CodeGen/RegisterCoalescer.cpp @@ -15,8 +15,9 @@ #define DEBUG_TYPE "regcoalescing" #include "RegisterCoalescer.h" -#include "VirtRegMap.h" #include "LiveDebugVariables.h" +#include "RegisterClassInfo.h" +#include "VirtRegMap.h" #include "llvm/Pass.h" #include "llvm/Value.h" @@ -54,6 +55,7 @@ STATISTIC(numExtends , "Number of copies extended"); STATISTIC(NumReMats , "Number of instructions re-materialized"); STATISTIC(numPeep , "Number of identity moves eliminated after coalescing"); STATISTIC(numAborts , "Number of times interval joining aborted"); +STATISTIC(NumInflated , "Number of register classes inflated"); static cl::opt EnableJoining("join-liveintervals", @@ -75,6 +77,128 @@ VerifyCoalescing("verify-coalescing", cl::desc("Verify machine instrs before and after register coalescing"), cl::Hidden); +namespace { + class RegisterCoalescer : public MachineFunctionPass { + MachineFunction* MF; + MachineRegisterInfo* MRI; + const TargetMachine* TM; + const TargetRegisterInfo* TRI; + const TargetInstrInfo* TII; + LiveIntervals *LIS; + LiveDebugVariables *LDV; + const MachineLoopInfo* Loops; + AliasAnalysis *AA; + RegisterClassInfo RegClassInfo; + + /// JoinedCopies - Keep track of copies eliminated due to coalescing. + /// + SmallPtrSet JoinedCopies; + + /// ReMatCopies - Keep track of copies eliminated due to remat. + /// + SmallPtrSet ReMatCopies; + + /// ReMatDefs - Keep track of definition instructions which have + /// been remat'ed. + SmallPtrSet ReMatDefs; + + /// joinIntervals - join compatible live intervals + void joinIntervals(); + + /// CopyCoalesceInMBB - Coalesce copies in the specified MBB, putting + /// copies that cannot yet be coalesced into the "TryAgain" list. + void CopyCoalesceInMBB(MachineBasicBlock *MBB, + std::vector &TryAgain); + + /// JoinCopy - Attempt to join intervals corresponding to SrcReg/DstReg, + /// which are the src/dst of the copy instruction CopyMI. This returns + /// true if the copy was successfully coalesced away. If it is not + /// currently possible to coalesce this interval, but it may be possible if + /// other things get coalesced, then it returns true by reference in + /// 'Again'. + bool JoinCopy(MachineInstr *TheCopy, bool &Again); + + /// JoinIntervals - Attempt to join these two intervals. On failure, this + /// returns false. The output "SrcInt" will not have been modified, so we + /// can use this information below to update aliases. + bool JoinIntervals(CoalescerPair &CP); + + /// AdjustCopiesBackFrom - We found a non-trivially-coalescable copy. If + /// the source value number is defined by a copy from the destination reg + /// see if we can merge these two destination reg valno# into a single + /// value number, eliminating a copy. + bool AdjustCopiesBackFrom(const CoalescerPair &CP, MachineInstr *CopyMI); + + /// HasOtherReachingDefs - Return true if there are definitions of IntB + /// other than BValNo val# that can reach uses of AValno val# of IntA. + bool HasOtherReachingDefs(LiveInterval &IntA, LiveInterval &IntB, + VNInfo *AValNo, VNInfo *BValNo); + + /// RemoveCopyByCommutingDef - We found a non-trivially-coalescable copy. + /// If the source value number is defined by a commutable instruction and + /// its other operand is coalesced to the copy dest register, see if we + /// can transform the copy into a noop by commuting the definition. + bool RemoveCopyByCommutingDef(const CoalescerPair &CP,MachineInstr *CopyMI); + + /// ReMaterializeTrivialDef - If the source of a copy is defined by a + /// trivial computation, replace the copy by rematerialize the definition. + /// If PreserveSrcInt is true, make sure SrcInt is valid after the call. + bool ReMaterializeTrivialDef(LiveInterval &SrcInt, bool PreserveSrcInt, + unsigned DstReg, MachineInstr *CopyMI); + + /// shouldJoinPhys - Return true if a physreg copy should be joined. + bool shouldJoinPhys(CoalescerPair &CP); + + /// isWinToJoinCrossClass - Return true if it's profitable to coalesce + /// two virtual registers from different register classes. + bool isWinToJoinCrossClass(unsigned SrcReg, + unsigned DstReg, + const TargetRegisterClass *SrcRC, + const TargetRegisterClass *DstRC, + const TargetRegisterClass *NewRC); + + /// UpdateRegDefsUses - Replace all defs and uses of SrcReg to DstReg and + /// update the subregister number if it is not zero. If DstReg is a + /// physical register and the existing subregister number of the def / use + /// being updated is not zero, make sure to set it to the correct physical + /// subregister. + void UpdateRegDefsUses(const CoalescerPair &CP); + + /// RemoveDeadDef - If a def of a live interval is now determined dead, + /// remove the val# it defines. If the live interval becomes empty, remove + /// it as well. + bool RemoveDeadDef(LiveInterval &li, MachineInstr *DefMI); + + /// RemoveCopyFlag - If DstReg is no longer defined by CopyMI, clear the + /// VNInfo copy flag for DstReg and all aliases. + void RemoveCopyFlag(unsigned DstReg, const MachineInstr *CopyMI); + + /// markAsJoined - Remember that CopyMI has already been joined. + void markAsJoined(MachineInstr *CopyMI); + + /// eliminateUndefCopy - Handle copies of undef values. + bool eliminateUndefCopy(MachineInstr *CopyMI, const CoalescerPair &CP); + + public: + static char ID; // Class identification, replacement for typeinfo + RegisterCoalescer() : MachineFunctionPass(ID) { + initializeRegisterCoalescerPass(*PassRegistry::getPassRegistry()); + } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const; + + virtual void releaseMemory(); + + /// runOnMachineFunction - pass entry point + virtual bool runOnMachineFunction(MachineFunction&); + + /// print - Implement the dump method. + virtual void print(raw_ostream &O, const Module* = 0) const; + }; +} /// end anonymous namespace + +char &llvm::RegisterCoalescerPassID = RegisterCoalescer::ID; + INITIALIZE_PASS_BEGIN(RegisterCoalescer, "simple-register-coalescing", "Simple Register Coalescing", false, false) INITIALIZE_PASS_DEPENDENCY(LiveIntervals) @@ -116,14 +240,14 @@ static bool isMoveInstr(const TargetRegisterInfo &tri, const MachineInstr *MI, } bool CoalescerPair::setRegisters(const MachineInstr *MI) { - srcReg_ = dstReg_ = subIdx_ = 0; - newRC_ = 0; - flipped_ = crossClass_ = false; + SrcReg = DstReg = SubIdx = 0; + NewRC = 0; + Flipped = CrossClass = false; unsigned Src, Dst, SrcSub, DstSub; - if (!isMoveInstr(tri_, MI, Src, Dst, SrcSub, DstSub)) + if (!isMoveInstr(TRI, MI, Src, Dst, SrcSub, DstSub)) return false; - partial_ = SrcSub || DstSub; + Partial = SrcSub || DstSub; // If one register is a physreg, it must be Dst. if (TargetRegisterInfo::isPhysicalRegister(Src)) { @@ -131,7 +255,7 @@ bool CoalescerPair::setRegisters(const MachineInstr *MI) { return false; std::swap(Src, Dst); std::swap(SrcSub, DstSub); - flipped_ = true; + Flipped = true; } const MachineRegisterInfo &MRI = MI->getParent()->getParent()->getRegInfo(); @@ -139,14 +263,14 @@ bool CoalescerPair::setRegisters(const MachineInstr *MI) { if (TargetRegisterInfo::isPhysicalRegister(Dst)) { // Eliminate DstSub on a physreg. if (DstSub) { - Dst = tri_.getSubReg(Dst, DstSub); + Dst = TRI.getSubReg(Dst, DstSub); if (!Dst) return false; DstSub = 0; } // Eliminate SrcSub by picking a corresponding Dst superregister. if (SrcSub) { - Dst = tri_.getMatchingSuperReg(Dst, SrcSub, MRI.getRegClass(Src)); + Dst = TRI.getMatchingSuperReg(Dst, SrcSub, MRI.getRegClass(Src)); if (!Dst) return false; SrcSub = 0; } else if (!MRI.getRegClass(Src)->contains(Dst)) { @@ -164,7 +288,7 @@ bool CoalescerPair::setRegisters(const MachineInstr *MI) { return false; const TargetRegisterClass *SrcRC = MRI.getRegClass(Src); const TargetRegisterClass *DstRC = MRI.getRegClass(Dst); - if (!getCommonSubClass(DstRC, SrcRC)) + if (!TRI.getCommonSubClass(DstRC, SrcRC)) return false; SrcSub = DstSub = 0; } @@ -174,36 +298,36 @@ bool CoalescerPair::setRegisters(const MachineInstr *MI) { std::swap(Src, Dst); DstSub = SrcSub; SrcSub = 0; - assert(!flipped_ && "Unexpected flip"); - flipped_ = true; + assert(!Flipped && "Unexpected flip"); + Flipped = true; } // Find the new register class. const TargetRegisterClass *SrcRC = MRI.getRegClass(Src); const TargetRegisterClass *DstRC = MRI.getRegClass(Dst); if (DstSub) - newRC_ = tri_.getMatchingSuperRegClass(DstRC, SrcRC, DstSub); + NewRC = TRI.getMatchingSuperRegClass(DstRC, SrcRC, DstSub); else - newRC_ = getCommonSubClass(DstRC, SrcRC); - if (!newRC_) + NewRC = TRI.getCommonSubClass(DstRC, SrcRC); + if (!NewRC) return false; - crossClass_ = newRC_ != DstRC || newRC_ != SrcRC; + CrossClass = NewRC != DstRC || NewRC != SrcRC; } // Check our invariants assert(TargetRegisterInfo::isVirtualRegister(Src) && "Src must be virtual"); assert(!(TargetRegisterInfo::isPhysicalRegister(Dst) && DstSub) && "Cannot have a physical SubIdx"); - srcReg_ = Src; - dstReg_ = Dst; - subIdx_ = DstSub; + SrcReg = Src; + DstReg = Dst; + SubIdx = DstSub; return true; } bool CoalescerPair::flip() { - if (subIdx_ || TargetRegisterInfo::isPhysicalRegister(dstReg_)) + if (SubIdx || TargetRegisterInfo::isPhysicalRegister(DstReg)) return false; - std::swap(srcReg_, dstReg_); - flipped_ = !flipped_; + std::swap(SrcReg, DstReg); + Flipped = !Flipped; return true; } @@ -211,36 +335,36 @@ bool CoalescerPair::isCoalescable(const MachineInstr *MI) const { if (!MI) return false; unsigned Src, Dst, SrcSub, DstSub; - if (!isMoveInstr(tri_, MI, Src, Dst, SrcSub, DstSub)) + if (!isMoveInstr(TRI, MI, Src, Dst, SrcSub, DstSub)) return false; - // Find the virtual register that is srcReg_. - if (Dst == srcReg_) { + // Find the virtual register that is SrcReg. + if (Dst == SrcReg) { std::swap(Src, Dst); std::swap(SrcSub, DstSub); - } else if (Src != srcReg_) { + } else if (Src != SrcReg) { return false; } - // Now check that Dst matches dstReg_. - if (TargetRegisterInfo::isPhysicalRegister(dstReg_)) { + // Now check that Dst matches DstReg. + if (TargetRegisterInfo::isPhysicalRegister(DstReg)) { if (!TargetRegisterInfo::isPhysicalRegister(Dst)) return false; - assert(!subIdx_ && "Inconsistent CoalescerPair state."); + assert(!SubIdx && "Inconsistent CoalescerPair state."); // DstSub could be set for a physreg from INSERT_SUBREG. if (DstSub) - Dst = tri_.getSubReg(Dst, DstSub); + Dst = TRI.getSubReg(Dst, DstSub); // Full copy of Src. if (!SrcSub) - return dstReg_ == Dst; + return DstReg == Dst; // This is a partial register copy. Check that the parts match. - return tri_.getSubReg(dstReg_, SrcSub) == Dst; + return TRI.getSubReg(DstReg, SrcSub) == Dst; } else { - // dstReg_ is virtual. - if (dstReg_ != Dst) + // DstReg is virtual. + if (DstReg != Dst) return false; // Registers match, do the subregisters line up? - return compose(tri_, subIdx_, SrcSub) == DstSub; + return compose(TRI, SubIdx, SrcSub) == DstSub; } } @@ -292,14 +416,14 @@ bool RegisterCoalescer::AdjustCopiesBackFrom(const CoalescerPair &CP, MachineInstr *CopyMI) { // Bail if there is no dst interval - can happen when merging physical subreg // operations. - if (!li_->hasInterval(CP.getDstReg())) + if (!LIS->hasInterval(CP.getDstReg())) return false; LiveInterval &IntA = - li_->getInterval(CP.isFlipped() ? CP.getDstReg() : CP.getSrcReg()); + LIS->getInterval(CP.isFlipped() ? CP.getDstReg() : CP.getSrcReg()); LiveInterval &IntB = - li_->getInterval(CP.isFlipped() ? CP.getSrcReg() : CP.getDstReg()); - SlotIndex CopyIdx = li_->getInstructionIndex(CopyMI).getDefIndex(); + LIS->getInterval(CP.isFlipped() ? CP.getSrcReg() : CP.getDstReg()); + SlotIndex CopyIdx = LIS->getInstructionIndex(CopyMI).getDefIndex(); // BValNo is a value number in B that is defined by a copy from A. 'B3' in // the example above. @@ -355,7 +479,7 @@ bool RegisterCoalescer::AdjustCopiesBackFrom(const CoalescerPair &CP, // Make sure that the end of the live range is inside the same block as // CopyMI. MachineInstr *ValLREndInst = - li_->getInstructionFromIndex(ValLR->end.getPrevSlot()); + LIS->getInstructionFromIndex(ValLR->end.getPrevSlot()); if (!ValLREndInst || ValLREndInst->getParent() != CopyMI->getParent()) return false; @@ -368,11 +492,11 @@ bool RegisterCoalescer::AdjustCopiesBackFrom(const CoalescerPair &CP, // of its aliases is overlapping the live interval of the virtual register. // If so, do not coalesce. if (TargetRegisterInfo::isPhysicalRegister(IntB.reg)) { - for (const unsigned *AS = tri_->getAliasSet(IntB.reg); *AS; ++AS) - if (li_->hasInterval(*AS) && IntA.overlaps(li_->getInterval(*AS))) { + for (const unsigned *AS = TRI->getAliasSet(IntB.reg); *AS; ++AS) + if (LIS->hasInterval(*AS) && IntA.overlaps(LIS->getInterval(*AS))) { DEBUG({ dbgs() << "\t\tInterfere with alias "; - li_->getInterval(*AS).print(dbgs(), tri_); + LIS->getInterval(*AS).print(dbgs(), TRI); }); return false; } @@ -380,7 +504,7 @@ bool RegisterCoalescer::AdjustCopiesBackFrom(const CoalescerPair &CP, DEBUG({ dbgs() << "Extending: "; - IntB.print(dbgs(), tri_); + IntB.print(dbgs(), TRI); }); SlotIndex FillerStart = ValLR->end, FillerEnd = BLR->start; @@ -398,13 +522,13 @@ bool RegisterCoalescer::AdjustCopiesBackFrom(const CoalescerPair &CP, // If the IntB live range is assigned to a physical register, and if that // physreg has sub-registers, update their live intervals as well. if (TargetRegisterInfo::isPhysicalRegister(IntB.reg)) { - for (const unsigned *SR = tri_->getSubRegisters(IntB.reg); *SR; ++SR) { - if (!li_->hasInterval(*SR)) + for (const unsigned *SR = TRI->getSubRegisters(IntB.reg); *SR; ++SR) { + if (!LIS->hasInterval(*SR)) continue; - LiveInterval &SRLI = li_->getInterval(*SR); + LiveInterval &SRLI = LIS->getInterval(*SR); SRLI.addRange(LiveRange(FillerStart, FillerEnd, SRLI.getNextValue(FillerStart, 0, - li_->getVNInfoAllocator()))); + LIS->getVNInfoAllocator()))); } } @@ -419,7 +543,7 @@ bool RegisterCoalescer::AdjustCopiesBackFrom(const CoalescerPair &CP, } DEBUG({ dbgs() << " result = "; - IntB.print(dbgs(), tri_); + IntB.print(dbgs(), TRI); dbgs() << "\n"; }); @@ -434,7 +558,7 @@ bool RegisterCoalescer::AdjustCopiesBackFrom(const CoalescerPair &CP, // merge, find the last use and trim the live range. That will also add the // isKill marker. if (ALR->end == CopyIdx) - li_->shrinkToUses(&IntA); + LIS->shrinkToUses(&IntA); ++numExtends; return true; @@ -498,15 +622,15 @@ bool RegisterCoalescer::RemoveCopyByCommutingDef(const CoalescerPair &CP, return false; // Bail if there is no dst interval. - if (!li_->hasInterval(CP.getDstReg())) + if (!LIS->hasInterval(CP.getDstReg())) return false; - SlotIndex CopyIdx = li_->getInstructionIndex(CopyMI).getDefIndex(); + SlotIndex CopyIdx = LIS->getInstructionIndex(CopyMI).getDefIndex(); LiveInterval &IntA = - li_->getInterval(CP.isFlipped() ? CP.getDstReg() : CP.getSrcReg()); + LIS->getInterval(CP.isFlipped() ? CP.getDstReg() : CP.getSrcReg()); LiveInterval &IntB = - li_->getInterval(CP.isFlipped() ? CP.getSrcReg() : CP.getDstReg()); + LIS->getInterval(CP.isFlipped() ? CP.getSrcReg() : CP.getDstReg()); // BValNo is a value number in B that is defined by a copy from A. 'B3' in // the example above. @@ -524,7 +648,7 @@ bool RegisterCoalescer::RemoveCopyByCommutingDef(const CoalescerPair &CP, // the optimization. if (AValNo->isPHIDef() || AValNo->isUnused() || AValNo->hasPHIKill()) return false; - MachineInstr *DefMI = li_->getInstructionFromIndex(AValNo->def); + MachineInstr *DefMI = LIS->getInstructionFromIndex(AValNo->def); if (!DefMI) return false; const MCInstrDesc &MCID = DefMI->getDesc(); @@ -538,7 +662,7 @@ bool RegisterCoalescer::RemoveCopyByCommutingDef(const CoalescerPair &CP, if (!DefMI->isRegTiedToUseOperand(DefIdx, &UseOpIdx)) return false; unsigned Op1, Op2, NewDstIdx; - if (!tii_->findCommutedOpIndices(DefMI, Op1, Op2)) + if (!TII->findCommutedOpIndices(DefMI, Op1, Op2)) return false; if (Op1 == UseOpIdx) NewDstIdx = Op2; @@ -560,18 +684,18 @@ bool RegisterCoalescer::RemoveCopyByCommutingDef(const CoalescerPair &CP, // Abort if the aliases of IntB.reg have values that are not simply the // clobbers from the superreg. if (TargetRegisterInfo::isPhysicalRegister(IntB.reg)) - for (const unsigned *AS = tri_->getAliasSet(IntB.reg); *AS; ++AS) - if (li_->hasInterval(*AS) && - HasOtherReachingDefs(IntA, li_->getInterval(*AS), AValNo, 0)) + for (const unsigned *AS = TRI->getAliasSet(IntB.reg); *AS; ++AS) + if (LIS->hasInterval(*AS) && + HasOtherReachingDefs(IntA, LIS->getInterval(*AS), AValNo, 0)) return false; // If some of the uses of IntA.reg is already coalesced away, return false. // It's not possible to determine whether it's safe to perform the coalescing. - for (MachineRegisterInfo::use_nodbg_iterator UI = - mri_->use_nodbg_begin(IntA.reg), - UE = mri_->use_nodbg_end(); UI != UE; ++UI) { + for (MachineRegisterInfo::use_nodbg_iterator UI = + MRI->use_nodbg_begin(IntA.reg), + UE = MRI->use_nodbg_end(); UI != UE; ++UI) { MachineInstr *UseMI = &*UI; - SlotIndex UseIdx = li_->getInstructionIndex(UseMI); + SlotIndex UseIdx = LIS->getInstructionIndex(UseMI); LiveInterval::iterator ULR = IntA.FindLiveRangeContaining(UseIdx); if (ULR == IntA.end()) continue; @@ -585,15 +709,15 @@ bool RegisterCoalescer::RemoveCopyByCommutingDef(const CoalescerPair &CP, // At this point we have decided that it is legal to do this // transformation. Start by commuting the instruction. MachineBasicBlock *MBB = DefMI->getParent(); - MachineInstr *NewMI = tii_->commuteInstruction(DefMI); + MachineInstr *NewMI = TII->commuteInstruction(DefMI); if (!NewMI) return false; if (TargetRegisterInfo::isVirtualRegister(IntA.reg) && TargetRegisterInfo::isVirtualRegister(IntB.reg) && - !mri_->constrainRegClass(IntB.reg, mri_->getRegClass(IntA.reg))) + !MRI->constrainRegClass(IntB.reg, MRI->getRegClass(IntA.reg))) return false; if (NewMI != DefMI) { - li_->ReplaceMachineInstrInMaps(DefMI, NewMI); + LIS->ReplaceMachineInstrInMaps(DefMI, NewMI); MBB->insert(DefMI, NewMI); MBB->erase(DefMI); } @@ -610,8 +734,8 @@ bool RegisterCoalescer::RemoveCopyByCommutingDef(const CoalescerPair &CP, // = B // Update uses of IntA of the specific Val# with IntB. - for (MachineRegisterInfo::use_iterator UI = mri_->use_begin(IntA.reg), - UE = mri_->use_end(); UI != UE;) { + for (MachineRegisterInfo::use_iterator UI = MRI->use_begin(IntA.reg), + UE = MRI->use_end(); UI != UE;) { MachineOperand &UseMO = UI.getOperand(); MachineInstr *UseMI = &*UI; ++UI; @@ -623,12 +747,12 @@ bool RegisterCoalescer::RemoveCopyByCommutingDef(const CoalescerPair &CP, UseMO.setReg(NewReg); continue; } - SlotIndex UseIdx = li_->getInstructionIndex(UseMI).getUseIndex(); + SlotIndex UseIdx = LIS->getInstructionIndex(UseMI).getUseIndex(); LiveInterval::iterator ULR = IntA.FindLiveRangeContaining(UseIdx); if (ULR == IntA.end() || ULR->valno != AValNo) continue; if (TargetRegisterInfo::isPhysicalRegister(NewReg)) - UseMO.substPhysReg(NewReg, *tri_); + UseMO.substPhysReg(NewReg, *TRI); else UseMO.setReg(NewReg); if (UseMI == CopyMI) @@ -674,27 +798,24 @@ bool RegisterCoalescer::RemoveCopyByCommutingDef(const CoalescerPair &CP, bool RegisterCoalescer::ReMaterializeTrivialDef(LiveInterval &SrcInt, bool preserveSrcInt, unsigned DstReg, - unsigned DstSubIdx, MachineInstr *CopyMI) { - SlotIndex CopyIdx = li_->getInstructionIndex(CopyMI).getUseIndex(); + SlotIndex CopyIdx = LIS->getInstructionIndex(CopyMI).getUseIndex(); LiveInterval::iterator SrcLR = SrcInt.FindLiveRangeContaining(CopyIdx); assert(SrcLR != SrcInt.end() && "Live range not found!"); VNInfo *ValNo = SrcLR->valno; - // If other defs can reach uses of this def, then it's not safe to perform - // the optimization. - if (ValNo->isPHIDef() || ValNo->isUnused() || ValNo->hasPHIKill()) + if (ValNo->isPHIDef() || ValNo->isUnused()) return false; - MachineInstr *DefMI = li_->getInstructionFromIndex(ValNo->def); + MachineInstr *DefMI = LIS->getInstructionFromIndex(ValNo->def); if (!DefMI) return false; assert(DefMI && "Defining instruction disappeared"); const MCInstrDesc &MCID = DefMI->getDesc(); if (!MCID.isAsCheapAsAMove()) return false; - if (!tii_->isTriviallyReMaterializable(DefMI, AA)) + if (!TII->isTriviallyReMaterializable(DefMI, AA)) return false; bool SawStore = false; - if (!DefMI->isSafeToMove(tii_, AA, SawStore)) + if (!DefMI->isSafeToMove(TII, AA, SawStore)) return false; if (MCID.getNumDefs() != 1) return false; @@ -702,36 +823,20 @@ bool RegisterCoalescer::ReMaterializeTrivialDef(LiveInterval &SrcInt, // Make sure the copy destination register class fits the instruction // definition register class. The mismatch can happen as a result of earlier // extract_subreg, insert_subreg, subreg_to_reg coalescing. - const TargetRegisterClass *RC = tii_->getRegClass(MCID, 0, tri_); + const TargetRegisterClass *RC = TII->getRegClass(MCID, 0, TRI); if (TargetRegisterInfo::isVirtualRegister(DstReg)) { - if (mri_->getRegClass(DstReg) != RC) + if (MRI->getRegClass(DstReg) != RC) return false; } else if (!RC->contains(DstReg)) return false; } - // If destination register has a sub-register index on it, make sure it - // matches the instruction register class. - if (DstSubIdx) { - const MCInstrDesc &MCID = DefMI->getDesc(); - if (MCID.getNumDefs() != 1) - return false; - const TargetRegisterClass *DstRC = mri_->getRegClass(DstReg); - const TargetRegisterClass *DstSubRC = - DstRC->getSubRegisterRegClass(DstSubIdx); - const TargetRegisterClass *DefRC = tii_->getRegClass(MCID, 0, tri_); - if (DefRC == DstRC) - DstSubIdx = 0; - else if (DefRC != DstSubRC) - return false; - } - RemoveCopyFlag(DstReg, CopyMI); MachineBasicBlock *MBB = CopyMI->getParent(); MachineBasicBlock::iterator MII = llvm::next(MachineBasicBlock::iterator(CopyMI)); - tii_->reMaterialize(*MBB, MII, DstReg, DstSubIdx, DefMI, *tri_); + TII->reMaterialize(*MBB, MII, DstReg, 0, DefMI, *TRI); MachineInstr *NewMI = prior(MII); // CopyMI may have implicit operands, transfer them over to the newly @@ -746,7 +851,7 @@ bool RegisterCoalescer::ReMaterializeTrivialDef(LiveInterval &SrcInt, } NewMI->copyImplicitOps(CopyMI); - li_->ReplaceMachineInstrInMaps(CopyMI, NewMI); + LIS->ReplaceMachineInstrInMaps(CopyMI, NewMI); CopyMI->eraseFromParent(); ReMatCopies.insert(CopyMI); ReMatDefs.insert(DefMI); @@ -755,8 +860,51 @@ bool RegisterCoalescer::ReMaterializeTrivialDef(LiveInterval &SrcInt, // The source interval can become smaller because we removed a use. if (preserveSrcInt) - li_->shrinkToUses(&SrcInt); + LIS->shrinkToUses(&SrcInt); + + return true; +} + +/// eliminateUndefCopy - ProcessImpicitDefs may leave some copies of +/// values, it only removes local variables. When we have a copy like: +/// +/// %vreg1 = COPY %vreg2 +/// +/// We delete the copy and remove the corresponding value number from %vreg1. +/// Any uses of that value number are marked as . +bool RegisterCoalescer::eliminateUndefCopy(MachineInstr *CopyMI, + const CoalescerPair &CP) { + SlotIndex Idx = LIS->getInstructionIndex(CopyMI); + LiveInterval *SrcInt = &LIS->getInterval(CP.getSrcReg()); + if (SrcInt->liveAt(Idx)) + return false; + LiveInterval *DstInt = &LIS->getInterval(CP.getDstReg()); + if (DstInt->liveAt(Idx)) + return false; + // No intervals are live-in to CopyMI - it is undef. + if (CP.isFlipped()) + DstInt = SrcInt; + SrcInt = 0; + + VNInfo *DeadVNI = DstInt->getVNInfoAt(Idx.getDefIndex()); + assert(DeadVNI && "No value defined in DstInt"); + DstInt->removeValNo(DeadVNI); + + // Find new undef uses. + for (MachineRegisterInfo::reg_nodbg_iterator + I = MRI->reg_nodbg_begin(DstInt->reg), E = MRI->reg_nodbg_end(); + I != E; ++I) { + MachineOperand &MO = I.getOperand(); + if (MO.isDef() || MO.isUndef()) + continue; + MachineInstr *MI = MO.getParent(); + SlotIndex Idx = LIS->getInstructionIndex(MI); + if (DstInt->liveAt(Idx)) + continue; + MO.setIsUndef(true); + DEBUG(dbgs() << "\tnew undef: " << Idx << '\t' << *MI); + } return true; } @@ -773,22 +921,20 @@ RegisterCoalescer::UpdateRegDefsUses(const CoalescerPair &CP) { unsigned SubIdx = CP.getSubIdx(); // Update LiveDebugVariables. - ldv_->renameRegister(SrcReg, DstReg, SubIdx); + LDV->renameRegister(SrcReg, DstReg, SubIdx); - for (MachineRegisterInfo::reg_iterator I = mri_->reg_begin(SrcReg); + for (MachineRegisterInfo::reg_iterator I = MRI->reg_begin(SrcReg); MachineInstr *UseMI = I.skipInstruction();) { // A PhysReg copy that won't be coalesced can perhaps be rematerialized // instead. if (DstIsPhys) { - if (UseMI->isCopy() && - !UseMI->getOperand(1).getSubReg() && - !UseMI->getOperand(0).getSubReg() && + if (UseMI->isFullCopy() && UseMI->getOperand(1).getReg() == SrcReg && UseMI->getOperand(0).getReg() != SrcReg && UseMI->getOperand(0).getReg() != DstReg && !JoinedCopies.count(UseMI) && - ReMaterializeTrivialDef(li_->getInterval(SrcReg), false, - UseMI->getOperand(0).getReg(), 0, UseMI)) + ReMaterializeTrivialDef(LIS->getInterval(SrcReg), false, + UseMI->getOperand(0).getReg(), UseMI)) continue; } @@ -803,10 +949,18 @@ RegisterCoalescer::UpdateRegDefsUses(const CoalescerPair &CP) { Kills |= MO.isKill(); Deads |= MO.isDead(); + // Make sure we don't create read-modify-write defs accidentally. We + // assume here that a SrcReg def cannot be joined into a live DstReg. If + // RegisterCoalescer starts tracking partially live registers, we will + // need to check the actual LiveInterval to determine if DstReg is live + // here. + if (SubIdx && !Reads) + MO.setIsUndef(); + if (DstIsPhys) - MO.substPhysReg(DstReg, *tri_); + MO.substPhysReg(DstReg, *TRI); else - MO.substVirtReg(DstReg, SubIdx, *tri_); + MO.substVirtReg(DstReg, SubIdx, *TRI); } // This instruction is a copy that will be removed. @@ -817,19 +971,19 @@ RegisterCoalescer::UpdateRegDefsUses(const CoalescerPair &CP) { // If UseMI was a simple SrcReg def, make sure we didn't turn it into a // read-modify-write of DstReg. if (Deads) - UseMI->addRegisterDead(DstReg, tri_); + UseMI->addRegisterDead(DstReg, TRI); else if (!Reads && Writes) - UseMI->addRegisterDefined(DstReg, tri_); + UseMI->addRegisterDefined(DstReg, TRI); // Kill flags apply to the whole physical register. if (DstIsPhys && Kills) - UseMI->addRegisterKilled(DstReg, tri_); + UseMI->addRegisterKilled(DstReg, TRI); } DEBUG({ dbgs() << "\t\tupdated: "; if (!UseMI->isDebugValue()) - dbgs() << li_->getInstructionIndex(UseMI) << "\t"; + dbgs() << LIS->getInstructionIndex(UseMI) << "\t"; dbgs() << *UseMI; }); } @@ -838,18 +992,18 @@ RegisterCoalescer::UpdateRegDefsUses(const CoalescerPair &CP) { /// removeIntervalIfEmpty - Check if the live interval of a physical register /// is empty, if so remove it and also remove the empty intervals of its /// sub-registers. Return true if live interval is removed. -static bool removeIntervalIfEmpty(LiveInterval &li, LiveIntervals *li_, - const TargetRegisterInfo *tri_) { +static bool removeIntervalIfEmpty(LiveInterval &li, LiveIntervals *LIS, + const TargetRegisterInfo *TRI) { if (li.empty()) { if (TargetRegisterInfo::isPhysicalRegister(li.reg)) - for (const unsigned* SR = tri_->getSubRegisters(li.reg); *SR; ++SR) { - if (!li_->hasInterval(*SR)) + for (const unsigned* SR = TRI->getSubRegisters(li.reg); *SR; ++SR) { + if (!LIS->hasInterval(*SR)) continue; - LiveInterval &sli = li_->getInterval(*SR); + LiveInterval &sli = LIS->getInterval(*SR); if (sli.empty()) - li_->removeInterval(*SR); + LIS->removeInterval(*SR); } - li_->removeInterval(li.reg); + LIS->removeInterval(li.reg); return true; } return false; @@ -859,29 +1013,29 @@ static bool removeIntervalIfEmpty(LiveInterval &li, LiveIntervals *li_, /// the val# it defines. If the live interval becomes empty, remove it as well. bool RegisterCoalescer::RemoveDeadDef(LiveInterval &li, MachineInstr *DefMI) { - SlotIndex DefIdx = li_->getInstructionIndex(DefMI).getDefIndex(); + SlotIndex DefIdx = LIS->getInstructionIndex(DefMI).getDefIndex(); LiveInterval::iterator MLR = li.FindLiveRangeContaining(DefIdx); if (DefIdx != MLR->valno->def) return false; li.removeValNo(MLR->valno); - return removeIntervalIfEmpty(li, li_, tri_); + return removeIntervalIfEmpty(li, LIS, TRI); } void RegisterCoalescer::RemoveCopyFlag(unsigned DstReg, const MachineInstr *CopyMI) { - SlotIndex DefIdx = li_->getInstructionIndex(CopyMI).getDefIndex(); - if (li_->hasInterval(DstReg)) { - LiveInterval &LI = li_->getInterval(DstReg); + SlotIndex DefIdx = LIS->getInstructionIndex(CopyMI).getDefIndex(); + if (LIS->hasInterval(DstReg)) { + LiveInterval &LI = LIS->getInterval(DstReg); if (const LiveRange *LR = LI.getLiveRangeContaining(DefIdx)) if (LR->valno->def == DefIdx) LR->valno->setCopy(0); } if (!TargetRegisterInfo::isPhysicalRegister(DstReg)) return; - for (const unsigned* AS = tri_->getAliasSet(DstReg); *AS; ++AS) { - if (!li_->hasInterval(*AS)) + for (const unsigned* AS = TRI->getAliasSet(DstReg); *AS; ++AS) { + if (!LIS->hasInterval(*AS)) continue; - LiveInterval &LI = li_->getInterval(*AS); + LiveInterval &LI = LIS->getInterval(*AS); if (const LiveRange *LR = LI.getLiveRangeContaining(DefIdx)) if (LR->valno->def == DefIdx) LR->valno->setCopy(0); @@ -894,8 +1048,8 @@ void RegisterCoalescer::RemoveCopyFlag(unsigned DstReg, /// are not spillable! If the destination interval uses are far away, think /// twice about coalescing them! bool RegisterCoalescer::shouldJoinPhys(CoalescerPair &CP) { - bool Allocatable = li_->isAllocatable(CP.getDstReg()); - LiveInterval &JoinVInt = li_->getInterval(CP.getSrcReg()); + bool Allocatable = LIS->isAllocatable(CP.getDstReg()); + LiveInterval &JoinVInt = LIS->getInterval(CP.getSrcReg()); /// Always join simple intervals that are defined by a single copy from a /// reserved register. This doesn't increase register pressure, so it is @@ -918,8 +1072,8 @@ bool RegisterCoalescer::shouldJoinPhys(CoalescerPair &CP) { // Don't join with physregs that have a ridiculous number of live // ranges. The data structure performance is really bad when that // happens. - if (li_->hasInterval(CP.getDstReg()) && - li_->getInterval(CP.getDstReg()).ranges.size() > 1000) { + if (LIS->hasInterval(CP.getDstReg()) && + LIS->getInterval(CP.getDstReg()).ranges.size() > 1000) { ++numAborts; DEBUG(dbgs() << "\tPhysical register live interval too complicated, abort!\n"); @@ -929,9 +1083,9 @@ bool RegisterCoalescer::shouldJoinPhys(CoalescerPair &CP) { // FIXME: Why are we skipping this test for partial copies? // CodeGen/X86/phys_subreg_coalesce-3.ll needs it. if (!CP.isPartial()) { - const TargetRegisterClass *RC = mri_->getRegClass(CP.getSrcReg()); + const TargetRegisterClass *RC = MRI->getRegClass(CP.getSrcReg()); unsigned Threshold = RegClassInfo.getNumAllocatableRegs(RC) * 2; - unsigned Length = li_->getApproximateInstructionCount(JoinVInt); + unsigned Length = LIS->getApproximateInstructionCount(JoinVInt); if (Length > Threshold) { ++numAborts; DEBUG(dbgs() << "\tMay tie down a physical register, abort!\n"); @@ -957,12 +1111,12 @@ RegisterCoalescer::isWinToJoinCrossClass(unsigned SrcReg, // Early exit if the function is fairly small, coalesce aggressively if // that's the case. For really special register classes with 3 or // fewer registers, be a bit more careful. - (li_->getFuncInstructionCount() / NewRCCount) < 8) + (LIS->getFuncInstructionCount() / NewRCCount) < 8) return true; - LiveInterval &SrcInt = li_->getInterval(SrcReg); - LiveInterval &DstInt = li_->getInterval(DstReg); - unsigned SrcSize = li_->getApproximateInstructionCount(SrcInt); - unsigned DstSize = li_->getApproximateInstructionCount(DstInt); + LiveInterval &SrcInt = LIS->getInterval(SrcReg); + LiveInterval &DstInt = LIS->getInterval(DstReg); + unsigned SrcSize = LIS->getApproximateInstructionCount(SrcInt); + unsigned DstSize = LIS->getApproximateInstructionCount(DstInt); // Coalesce aggressively if the intervals are small compared to the number of // registers in the new class. The number 4 is fairly arbitrary, chosen to be @@ -972,10 +1126,10 @@ RegisterCoalescer::isWinToJoinCrossClass(unsigned SrcReg, return true; // Estimate *register use density*. If it doubles or more, abort. - unsigned SrcUses = std::distance(mri_->use_nodbg_begin(SrcReg), - mri_->use_nodbg_end()); - unsigned DstUses = std::distance(mri_->use_nodbg_begin(DstReg), - mri_->use_nodbg_end()); + unsigned SrcUses = std::distance(MRI->use_nodbg_begin(SrcReg), + MRI->use_nodbg_end()); + unsigned DstUses = std::distance(MRI->use_nodbg_begin(DstReg), + MRI->use_nodbg_end()); unsigned NewUses = SrcUses + DstUses; unsigned NewSize = SrcSize + DstSize; if (SrcRC != NewRC && SrcSize > ThresSize) { @@ -1003,9 +1157,9 @@ bool RegisterCoalescer::JoinCopy(MachineInstr *CopyMI, bool &Again) { if (JoinedCopies.count(CopyMI) || ReMatCopies.count(CopyMI)) return false; // Already done. - DEBUG(dbgs() << li_->getInstructionIndex(CopyMI) << '\t' << *CopyMI); + DEBUG(dbgs() << LIS->getInstructionIndex(CopyMI) << '\t' << *CopyMI); - CoalescerPair CP(*tii_, *tri_); + CoalescerPair CP(*TII, *TRI); if (!CP.setRegisters(CopyMI)) { DEBUG(dbgs() << "\tNot coalescable.\n"); return false; @@ -1018,8 +1172,15 @@ bool RegisterCoalescer::JoinCopy(MachineInstr *CopyMI, bool &Again) { return false; // Not coalescable. } - DEBUG(dbgs() << "\tConsidering merging " << PrintReg(CP.getSrcReg(), tri_) - << " with " << PrintReg(CP.getDstReg(), tri_, CP.getSubIdx()) + // Eliminate undefs. + if (!CP.isPhys() && eliminateUndefCopy(CopyMI, CP)) { + markAsJoined(CopyMI); + DEBUG(dbgs() << "\tEliminated copy of value.\n"); + return false; // Not coalescable. + } + + DEBUG(dbgs() << "\tConsidering merging " << PrintReg(CP.getSrcReg(), TRI) + << " with " << PrintReg(CP.getDstReg(), TRI, CP.getSubIdx()) << "\n"); // Enforce policies. @@ -1028,8 +1189,8 @@ bool RegisterCoalescer::JoinCopy(MachineInstr *CopyMI, bool &Again) { // Before giving up coalescing, if definition of source is defined by // trivial computation, try rematerializing it. if (!CP.isFlipped() && - ReMaterializeTrivialDef(li_->getInterval(CP.getSrcReg()), true, - CP.getDstReg(), 0, CopyMI)) + ReMaterializeTrivialDef(LIS->getInterval(CP.getSrcReg()), true, + CP.getDstReg(), CopyMI)) return true; return false; } @@ -1042,8 +1203,8 @@ bool RegisterCoalescer::JoinCopy(MachineInstr *CopyMI, bool &Again) { return false; } if (!isWinToJoinCrossClass(CP.getSrcReg(), CP.getDstReg(), - mri_->getRegClass(CP.getSrcReg()), - mri_->getRegClass(CP.getDstReg()), + MRI->getRegClass(CP.getSrcReg()), + MRI->getRegClass(CP.getDstReg()), CP.getNewRC())) { DEBUG(dbgs() << "\tAvoid coalescing to constrained register class.\n"); Again = true; // May be possible to coalesce later. @@ -1052,8 +1213,8 @@ bool RegisterCoalescer::JoinCopy(MachineInstr *CopyMI, bool &Again) { } // When possible, let DstReg be the larger interval. - if (!CP.getSubIdx() && li_->getInterval(CP.getSrcReg()).ranges.size() > - li_->getInterval(CP.getDstReg()).ranges.size()) + if (!CP.getSubIdx() && LIS->getInterval(CP.getSrcReg()).ranges.size() > + LIS->getInterval(CP.getDstReg()).ranges.size()) CP.flip(); } @@ -1067,8 +1228,8 @@ bool RegisterCoalescer::JoinCopy(MachineInstr *CopyMI, bool &Again) { // If definition of source is defined by trivial computation, try // rematerializing it. if (!CP.isFlipped() && - ReMaterializeTrivialDef(li_->getInterval(CP.getSrcReg()), true, - CP.getDstReg(), 0, CopyMI)) + ReMaterializeTrivialDef(LIS->getInterval(CP.getSrcReg()), true, + CP.getDstReg(), CopyMI)) return true; // If we can eliminate the copy without merging the live ranges, do so now. @@ -1091,7 +1252,7 @@ bool RegisterCoalescer::JoinCopy(MachineInstr *CopyMI, bool &Again) { // other. Make sure the resulting register is set to the right register class. if (CP.isCrossClass()) { ++numCrossRCs; - mri_->setRegClass(CP.getDstReg(), CP.getNewRC()); + MRI->setRegClass(CP.getDstReg(), CP.getNewRC()); } // Remember to delete the copy instruction. @@ -1105,10 +1266,10 @@ bool RegisterCoalescer::JoinCopy(MachineInstr *CopyMI, bool &Again) { SmallVector BlockSeq; // JoinIntervals invalidates the VNInfos in SrcInt, but we only need the // ranges for this, and they are preserved. - LiveInterval &SrcInt = li_->getInterval(CP.getSrcReg()); + LiveInterval &SrcInt = LIS->getInterval(CP.getSrcReg()); for (LiveInterval::const_iterator I = SrcInt.begin(), E = SrcInt.end(); I != E; ++I ) { - li_->findLiveInMBBs(I->start, I->end, BlockSeq); + LIS->findLiveInMBBs(I->start, I->end, BlockSeq); for (unsigned idx = 0, size = BlockSeq.size(); idx != size; ++idx) { MachineBasicBlock &block = *BlockSeq[idx]; if (!block.isLiveIn(CP.getDstReg())) @@ -1120,15 +1281,15 @@ bool RegisterCoalescer::JoinCopy(MachineInstr *CopyMI, bool &Again) { // SrcReg is guarateed to be the register whose live interval that is // being merged. - li_->removeInterval(CP.getSrcReg()); + LIS->removeInterval(CP.getSrcReg()); // Update regalloc hint. - tri_->UpdateRegAllocHint(CP.getSrcReg(), CP.getDstReg(), *mf_); + TRI->UpdateRegAllocHint(CP.getSrcReg(), CP.getDstReg(), *MF); DEBUG({ - LiveInterval &DstInt = li_->getInterval(CP.getDstReg()); + LiveInterval &DstInt = LIS->getInterval(CP.getDstReg()); dbgs() << "\tJoined. Result = "; - DstInt.print(dbgs(), tri_); + DstInt.print(dbgs(), TRI); dbgs() << "\n"; }); @@ -1197,6 +1358,7 @@ static unsigned ComputeUltimateVN(VNInfo *VNI, // which allows us to coalesce A and B. // VNI is the definition of B. LR is the life range of A that includes // the slot just before B. If we return true, we add "B = X" to DupCopies. +// This implies that A dominates B. static bool RegistersDefinedFromSameValue(LiveIntervals &li, const TargetRegisterInfo &tri, CoalescerPair &CP, @@ -1248,7 +1410,9 @@ static bool RegistersDefinedFromSameValue(LiveIntervals &li, // If the copies use two different value numbers of X, we cannot merge // A and B. LiveInterval &SrcInt = li.getInterval(Src); - if (SrcInt.getVNInfoAt(Other->def) != SrcInt.getVNInfoAt(VNI->def)) + // getVNInfoBefore returns NULL for undef copies. In this case, the + // optimization is still safe. + if (SrcInt.getVNInfoBefore(Other->def) != SrcInt.getVNInfoBefore(VNI->def)) return false; DupCopies.push_back(MI); @@ -1259,18 +1423,18 @@ static bool RegistersDefinedFromSameValue(LiveIntervals &li, /// JoinIntervals - Attempt to join these two intervals. On failure, this /// returns false. bool RegisterCoalescer::JoinIntervals(CoalescerPair &CP) { - LiveInterval &RHS = li_->getInterval(CP.getSrcReg()); - DEBUG({ dbgs() << "\t\tRHS = "; RHS.print(dbgs(), tri_); dbgs() << "\n"; }); + LiveInterval &RHS = LIS->getInterval(CP.getSrcReg()); + DEBUG({ dbgs() << "\t\tRHS = "; RHS.print(dbgs(), TRI); dbgs() << "\n"; }); // If a live interval is a physical register, check for interference with any // aliases. The interference check implemented here is a bit more conservative // than the full interfeence check below. We allow overlapping live ranges // only when one is a copy of the other. if (CP.isPhys()) { - for (const unsigned *AS = tri_->getAliasSet(CP.getDstReg()); *AS; ++AS){ - if (!li_->hasInterval(*AS)) + for (const unsigned *AS = TRI->getAliasSet(CP.getDstReg()); *AS; ++AS){ + if (!LIS->hasInterval(*AS)) continue; - const LiveInterval &LHS = li_->getInterval(*AS); + const LiveInterval &LHS = LIS->getInterval(*AS); LiveInterval::const_iterator LI = LHS.begin(); for (LiveInterval::const_iterator RI = RHS.begin(), RE = RHS.end(); RI != RE; ++RI) { @@ -1278,10 +1442,10 @@ bool RegisterCoalescer::JoinIntervals(CoalescerPair &CP) { // Does LHS have an overlapping live range starting before RI? if ((LI != LHS.begin() && LI[-1].end > RI->start) && (RI->start != RI->valno->def || - !CP.isCoalescable(li_->getInstructionFromIndex(RI->start)))) { + !CP.isCoalescable(LIS->getInstructionFromIndex(RI->start)))) { DEBUG({ dbgs() << "\t\tInterference from alias: "; - LHS.print(dbgs(), tri_); + LHS.print(dbgs(), TRI); dbgs() << "\n\t\tOverlap at " << RI->start << " and no copy.\n"; }); return false; @@ -1290,10 +1454,10 @@ bool RegisterCoalescer::JoinIntervals(CoalescerPair &CP) { // Check that LHS ranges beginning in this range are copies. for (; LI != LHS.end() && LI->start < RI->end; ++LI) { if (LI->start != LI->valno->def || - !CP.isCoalescable(li_->getInstructionFromIndex(LI->start))) { + !CP.isCoalescable(LIS->getInstructionFromIndex(LI->start))) { DEBUG({ dbgs() << "\t\tInterference from alias: "; - LHS.print(dbgs(), tri_); + LHS.print(dbgs(), TRI); dbgs() << "\n\t\tDef at " << LI->start << " is not a copy.\n"; }); return false; @@ -1313,8 +1477,8 @@ bool RegisterCoalescer::JoinIntervals(CoalescerPair &CP) { SmallVector DupCopies; - LiveInterval &LHS = li_->getOrCreateInterval(CP.getDstReg()); - DEBUG({ dbgs() << "\t\tLHS = "; LHS.print(dbgs(), tri_); dbgs() << "\n"; }); + LiveInterval &LHS = LIS->getOrCreateInterval(CP.getDstReg()); + DEBUG({ dbgs() << "\t\tLHS = "; LHS.print(dbgs(), TRI); dbgs() << "\n"; }); // Loop over the value numbers of the LHS, seeing if any are defined from // the RHS. @@ -1337,7 +1501,7 @@ bool RegisterCoalescer::JoinIntervals(CoalescerPair &CP) { // from the RHS interval, we can use its value #. MachineInstr *MI = VNI->getCopy(); if (!CP.isCoalescable(MI) && - !RegistersDefinedFromSameValue(*li_, *tri_, CP, VNI, lr, DupCopies)) + !RegistersDefinedFromSameValue(*LIS, *TRI, CP, VNI, lr, DupCopies)) continue; LHSValsDefinedFromRHS[VNI] = lr->valno; @@ -1364,7 +1528,7 @@ bool RegisterCoalescer::JoinIntervals(CoalescerPair &CP) { // from the LHS interval, we can use its value #. MachineInstr *MI = VNI->getCopy(); if (!CP.isCoalescable(MI) && - !RegistersDefinedFromSameValue(*li_, *tri_, CP, VNI, lr, DupCopies)) + !RegistersDefinedFromSameValue(*LIS, *TRI, CP, VNI, lr, DupCopies)) continue; RHSValsDefinedFromLHS[VNI] = lr->valno; @@ -1486,7 +1650,7 @@ bool RegisterCoalescer::JoinIntervals(CoalescerPair &CP) { // and mark the X as coalesced to keep the illusion. unsigned Src = MI->getOperand(1).getReg(); SourceRegisters.push_back(Src); - MI->getOperand(0).substVirtReg(Src, 0, *tri_); + MI->getOperand(0).substVirtReg(Src, 0, *TRI); markAsJoined(MI); } @@ -1495,13 +1659,13 @@ bool RegisterCoalescer::JoinIntervals(CoalescerPair &CP) { // that B = X is gone. for (SmallVector::iterator I = SourceRegisters.begin(), E = SourceRegisters.end(); I != E; ++I) { - li_->shrinkToUses(&li_->getInterval(*I)); + LIS->shrinkToUses(&LIS->getInterval(*I)); } // If we get here, we know that we can coalesce the live ranges. Ask the // intervals to coalesce themselves now. LHS.join(RHS, &LHSValNoAssignments[0], &RHSValNoAssignments[0], NewVNInfo, - mri_); + MRI); return true; } @@ -1552,7 +1716,7 @@ void RegisterCoalescer::CopyCoalesceInMBB(MachineBasicBlock *MBB, bool SrcIsPhys = TargetRegisterInfo::isPhysicalRegister(SrcReg); bool DstIsPhys = TargetRegisterInfo::isPhysicalRegister(DstReg); - if (li_->hasInterval(SrcReg) && li_->getInterval(SrcReg).empty()) + if (LIS->hasInterval(SrcReg) && LIS->getInterval(SrcReg).empty()) ImpDefCopies.push_back(Inst); else if (SrcIsPhys || DstIsPhys) PhysCopies.push_back(Inst); @@ -1590,9 +1754,9 @@ void RegisterCoalescer::joinIntervals() { DEBUG(dbgs() << "********** JOINING INTERVALS ***********\n"); std::vector TryAgainList; - if (loopInfo->empty()) { + if (Loops->empty()) { // If there are no loops in the function, join intervals in function order. - for (MachineFunction::iterator I = mf_->begin(), E = mf_->end(); + for (MachineFunction::iterator I = MF->begin(), E = MF->end(); I != E; ++I) CopyCoalesceInMBB(I, TryAgainList); } else { @@ -1603,9 +1767,9 @@ void RegisterCoalescer::joinIntervals() { // Join intervals in the function prolog first. We want to join physical // registers with virtual registers before the intervals got too long. std::vector > MBBs; - for (MachineFunction::iterator I = mf_->begin(), E = mf_->end();I != E;++I){ + for (MachineFunction::iterator I = MF->begin(), E = MF->end();I != E;++I){ MachineBasicBlock *MBB = I; - MBBs.push_back(std::make_pair(loopInfo->getLoopDepth(MBB), I)); + MBBs.push_back(std::make_pair(Loops->getLoopDepth(MBB), I)); } // Sort by loop depth. @@ -1644,22 +1808,22 @@ void RegisterCoalescer::releaseMemory() { } bool RegisterCoalescer::runOnMachineFunction(MachineFunction &fn) { - mf_ = &fn; - mri_ = &fn.getRegInfo(); - tm_ = &fn.getTarget(); - tri_ = tm_->getRegisterInfo(); - tii_ = tm_->getInstrInfo(); - li_ = &getAnalysis(); - ldv_ = &getAnalysis(); + MF = &fn; + MRI = &fn.getRegInfo(); + TM = &fn.getTarget(); + TRI = TM->getRegisterInfo(); + TII = TM->getInstrInfo(); + LIS = &getAnalysis(); + LDV = &getAnalysis(); AA = &getAnalysis(); - loopInfo = &getAnalysis(); + Loops = &getAnalysis(); DEBUG(dbgs() << "********** SIMPLE REGISTER COALESCING **********\n" << "********** Function: " - << ((Value*)mf_->getFunction())->getName() << '\n'); + << ((Value*)MF->getFunction())->getName() << '\n'); if (VerifyCoalescing) - mf_->verify(this, "Before register coalescing"); + MF->verify(this, "Before register coalescing"); RegClassInfo.runOnMachineFunction(fn); @@ -1668,9 +1832,9 @@ bool RegisterCoalescer::runOnMachineFunction(MachineFunction &fn) { joinIntervals(); DEBUG({ dbgs() << "********** INTERVALS POST JOINING **********\n"; - for (LiveIntervals::iterator I = li_->begin(), E = li_->end(); + for (LiveIntervals::iterator I = LIS->begin(), E = LIS->end(); I != E; ++I){ - I->second->print(dbgs(), tri_); + I->second->print(dbgs(), TRI); dbgs() << "\n"; } }); @@ -1678,8 +1842,8 @@ bool RegisterCoalescer::runOnMachineFunction(MachineFunction &fn) { // Perform a final pass over the instructions and compute spill weights // and remove identity moves. - SmallVector DeadDefs; - for (MachineFunction::iterator mbbi = mf_->begin(), mbbe = mf_->end(); + SmallVector DeadDefs, InflateRegs; + for (MachineFunction::iterator mbbi = MF->begin(), mbbe = MF->end(); mbbi != mbbe; ++mbbi) { MachineBasicBlock* mbb = mbbi; for (MachineBasicBlock::iterator mii = mbb->begin(), mie = mbb->end(); @@ -1690,6 +1854,16 @@ bool RegisterCoalescer::runOnMachineFunction(MachineFunction &fn) { bool DoDelete = true; assert(MI->isCopyLike() && "Unrecognized copy instruction"); unsigned SrcReg = MI->getOperand(MI->isSubregToReg() ? 2 : 1).getReg(); + unsigned DstReg = MI->getOperand(0).getReg(); + + // Collect candidates for register class inflation. + if (TargetRegisterInfo::isVirtualRegister(SrcReg) && + RegClassInfo.isProperSubClass(MRI->getRegClass(SrcReg))) + InflateRegs.push_back(SrcReg); + if (TargetRegisterInfo::isVirtualRegister(DstReg) && + RegClassInfo.isProperSubClass(MRI->getRegClass(DstReg))) + InflateRegs.push_back(DstReg); + if (TargetRegisterInfo::isPhysicalRegister(SrcReg) && MI->getNumOperands() > 2) // Do not delete extract_subreg, insert_subreg of physical @@ -1701,8 +1875,8 @@ bool RegisterCoalescer::runOnMachineFunction(MachineFunction &fn) { if (MI->allDefsAreDead()) { if (TargetRegisterInfo::isVirtualRegister(SrcReg) && - li_->hasInterval(SrcReg)) - li_->shrinkToUses(&li_->getInterval(SrcReg)); + LIS->hasInterval(SrcReg)) + LIS->shrinkToUses(&LIS->getInterval(SrcReg)); DoDelete = true; } if (!DoDelete) { @@ -1711,10 +1885,10 @@ bool RegisterCoalescer::runOnMachineFunction(MachineFunction &fn) { MI->RemoveOperand(3); MI->RemoveOperand(1); } - MI->setDesc(tii_->get(TargetOpcode::KILL)); + MI->setDesc(TII->get(TargetOpcode::KILL)); mii = llvm::next(mii); } else { - li_->RemoveMachineInstrFromMaps(MI); + LIS->RemoveMachineInstrFromMaps(MI); mii = mbbi->erase(mii); ++numPeep; } @@ -1731,12 +1905,16 @@ bool RegisterCoalescer::runOnMachineFunction(MachineFunction &fn) { unsigned Reg = MO.getReg(); if (!Reg) continue; - if (TargetRegisterInfo::isVirtualRegister(Reg)) + if (TargetRegisterInfo::isVirtualRegister(Reg)) { DeadDefs.push_back(Reg); + // Remat may also enable register class inflation. + if (RegClassInfo.isProperSubClass(MRI->getRegClass(Reg))) + InflateRegs.push_back(Reg); + } if (MO.isDead()) continue; if (TargetRegisterInfo::isPhysicalRegister(Reg) || - !mri_->use_nodbg_empty(Reg)) { + !MRI->use_nodbg_empty(Reg)) { isDead = false; break; } @@ -1745,9 +1923,9 @@ bool RegisterCoalescer::runOnMachineFunction(MachineFunction &fn) { while (!DeadDefs.empty()) { unsigned DeadDef = DeadDefs.back(); DeadDefs.pop_back(); - RemoveDeadDef(li_->getInterval(DeadDef), MI); + RemoveDeadDef(LIS->getInterval(DeadDef), MI); } - li_->RemoveMachineInstrFromMaps(mii); + LIS->RemoveMachineInstrFromMaps(mii); mii = mbbi->erase(mii); continue; } else @@ -1757,14 +1935,14 @@ bool RegisterCoalescer::runOnMachineFunction(MachineFunction &fn) { ++mii; // Check for now unnecessary kill flags. - if (li_->isNotInMIMap(MI)) continue; - SlotIndex DefIdx = li_->getInstructionIndex(MI).getDefIndex(); + if (LIS->isNotInMIMap(MI)) continue; + SlotIndex DefIdx = LIS->getInstructionIndex(MI).getDefIndex(); for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { MachineOperand &MO = MI->getOperand(i); if (!MO.isReg() || !MO.isKill()) continue; unsigned reg = MO.getReg(); - if (!reg || !li_->hasInterval(reg)) continue; - if (!li_->getInterval(reg).killedAt(DefIdx)) { + if (!reg || !LIS->hasInterval(reg)) continue; + if (!LIS->getInterval(reg).killedAt(DefIdx)) { MO.setIsKill(false); continue; } @@ -1772,26 +1950,40 @@ bool RegisterCoalescer::runOnMachineFunction(MachineFunction &fn) { // remain alive. if (!TargetRegisterInfo::isPhysicalRegister(reg)) continue; - for (const unsigned *SR = tri_->getSubRegisters(reg); + for (const unsigned *SR = TRI->getSubRegisters(reg); unsigned S = *SR; ++SR) - if (li_->hasInterval(S) && li_->getInterval(S).liveAt(DefIdx)) - MI->addRegisterDefined(S, tri_); + if (LIS->hasInterval(S) && LIS->getInterval(S).liveAt(DefIdx)) + MI->addRegisterDefined(S, TRI); } } } + // After deleting a lot of copies, register classes may be less constrained. + // Removing sub-register opreands may alow GR32_ABCD -> GR32 and DPR_VFP2 -> + // DPR inflation. + array_pod_sort(InflateRegs.begin(), InflateRegs.end()); + InflateRegs.erase(std::unique(InflateRegs.begin(), InflateRegs.end()), + InflateRegs.end()); + DEBUG(dbgs() << "Trying to inflate " << InflateRegs.size() << " regs.\n"); + for (unsigned i = 0, e = InflateRegs.size(); i != e; ++i) { + unsigned Reg = InflateRegs[i]; + if (MRI->reg_nodbg_empty(Reg)) + continue; + if (MRI->recomputeRegClass(Reg, *TM)) { + DEBUG(dbgs() << PrintReg(Reg) << " inflated to " + << MRI->getRegClass(Reg)->getName() << '\n'); + ++NumInflated; + } + } + DEBUG(dump()); - DEBUG(ldv_->dump()); + DEBUG(LDV->dump()); if (VerifyCoalescing) - mf_->verify(this, "After register coalescing"); + MF->verify(this, "After register coalescing"); return true; } /// print - Implement the dump method. void RegisterCoalescer::print(raw_ostream &O, const Module* m) const { - li_->print(O, m); -} - -RegisterCoalescer *llvm::createRegisterCoalescer() { - return new RegisterCoalescer(); + LIS->print(O, m); } diff --git a/contrib/llvm/lib/CodeGen/RegisterCoalescer.h b/contrib/llvm/lib/CodeGen/RegisterCoalescer.h index 4131d91c0..472c48377 100644 --- a/contrib/llvm/lib/CodeGen/RegisterCoalescer.h +++ b/contrib/llvm/lib/CodeGen/RegisterCoalescer.h @@ -12,198 +12,60 @@ // //===----------------------------------------------------------------------===// -#include "RegisterClassInfo.h" -#include "llvm/Support/IncludeFile.h" -#include "llvm/CodeGen/LiveInterval.h" -#include "llvm/ADT/SmallPtrSet.h" - #ifndef LLVM_CODEGEN_REGISTER_COALESCER_H #define LLVM_CODEGEN_REGISTER_COALESCER_H namespace llvm { - class MachineFunction; - class RegallocQuery; - class AnalysisUsage; class MachineInstr; class TargetRegisterInfo; class TargetRegisterClass; class TargetInstrInfo; - class LiveDebugVariables; - class VirtRegMap; - class MachineLoopInfo; - - class CoalescerPair; - - /// An abstract interface for register coalescers. Coalescers must - /// implement this interface to be part of the coalescer analysis - /// group. - class RegisterCoalescer : public MachineFunctionPass { - MachineFunction* mf_; - MachineRegisterInfo* mri_; - const TargetMachine* tm_; - const TargetRegisterInfo* tri_; - const TargetInstrInfo* tii_; - LiveIntervals *li_; - LiveDebugVariables *ldv_; - const MachineLoopInfo* loopInfo; - AliasAnalysis *AA; - RegisterClassInfo RegClassInfo; - - /// JoinedCopies - Keep track of copies eliminated due to coalescing. - /// - SmallPtrSet JoinedCopies; - - /// ReMatCopies - Keep track of copies eliminated due to remat. - /// - SmallPtrSet ReMatCopies; - - /// ReMatDefs - Keep track of definition instructions which have - /// been remat'ed. - SmallPtrSet ReMatDefs; - - /// joinIntervals - join compatible live intervals - void joinIntervals(); - - /// CopyCoalesceInMBB - Coalesce copies in the specified MBB, putting - /// copies that cannot yet be coalesced into the "TryAgain" list. - void CopyCoalesceInMBB(MachineBasicBlock *MBB, - std::vector &TryAgain); - - /// JoinCopy - Attempt to join intervals corresponding to SrcReg/DstReg, - /// which are the src/dst of the copy instruction CopyMI. This returns true - /// if the copy was successfully coalesced away. If it is not currently - /// possible to coalesce this interval, but it may be possible if other - /// things get coalesced, then it returns true by reference in 'Again'. - bool JoinCopy(MachineInstr *TheCopy, bool &Again); - - /// JoinIntervals - Attempt to join these two intervals. On failure, this - /// returns false. The output "SrcInt" will not have been modified, so we can - /// use this information below to update aliases. - bool JoinIntervals(CoalescerPair &CP); - - /// AdjustCopiesBackFrom - We found a non-trivially-coalescable copy. If - /// the source value number is defined by a copy from the destination reg - /// see if we can merge these two destination reg valno# into a single - /// value number, eliminating a copy. - bool AdjustCopiesBackFrom(const CoalescerPair &CP, MachineInstr *CopyMI); - - /// HasOtherReachingDefs - Return true if there are definitions of IntB - /// other than BValNo val# that can reach uses of AValno val# of IntA. - bool HasOtherReachingDefs(LiveInterval &IntA, LiveInterval &IntB, - VNInfo *AValNo, VNInfo *BValNo); - - /// RemoveCopyByCommutingDef - We found a non-trivially-coalescable copy. - /// If the source value number is defined by a commutable instruction and - /// its other operand is coalesced to the copy dest register, see if we - /// can transform the copy into a noop by commuting the definition. - bool RemoveCopyByCommutingDef(const CoalescerPair &CP,MachineInstr *CopyMI); - - /// ReMaterializeTrivialDef - If the source of a copy is defined by a trivial - /// computation, replace the copy by rematerialize the definition. - /// If PreserveSrcInt is true, make sure SrcInt is valid after the call. - bool ReMaterializeTrivialDef(LiveInterval &SrcInt, bool PreserveSrcInt, - unsigned DstReg, unsigned DstSubIdx, - MachineInstr *CopyMI); - - /// shouldJoinPhys - Return true if a physreg copy should be joined. - bool shouldJoinPhys(CoalescerPair &CP); - - /// isWinToJoinCrossClass - Return true if it's profitable to coalesce - /// two virtual registers from different register classes. - bool isWinToJoinCrossClass(unsigned SrcReg, - unsigned DstReg, - const TargetRegisterClass *SrcRC, - const TargetRegisterClass *DstRC, - const TargetRegisterClass *NewRC); - - /// UpdateRegDefsUses - Replace all defs and uses of SrcReg to DstReg and - /// update the subregister number if it is not zero. If DstReg is a - /// physical register and the existing subregister number of the def / use - /// being updated is not zero, make sure to set it to the correct physical - /// subregister. - void UpdateRegDefsUses(const CoalescerPair &CP); - - /// RemoveDeadDef - If a def of a live interval is now determined dead, - /// remove the val# it defines. If the live interval becomes empty, remove - /// it as well. - bool RemoveDeadDef(LiveInterval &li, MachineInstr *DefMI); - - /// RemoveCopyFlag - If DstReg is no longer defined by CopyMI, clear the - /// VNInfo copy flag for DstReg and all aliases. - void RemoveCopyFlag(unsigned DstReg, const MachineInstr *CopyMI); - - /// markAsJoined - Remember that CopyMI has already been joined. - void markAsJoined(MachineInstr *CopyMI); - - public: - static char ID; // Class identification, replacement for typeinfo - RegisterCoalescer() : MachineFunctionPass(ID) { - initializeRegisterCoalescerPass(*PassRegistry::getPassRegistry()); - } - - /// Register allocators must call this from their own - /// getAnalysisUsage to cover the case where the coalescer is not - /// a Pass in the proper sense and isn't managed by PassManager. - /// PassManager needs to know which analyses to make available and - /// which to invalidate when running the register allocator or any - /// pass that might call coalescing. The long-term solution is to - /// allow hierarchies of PassManagers. - virtual void getAnalysisUsage(AnalysisUsage &AU) const; - - virtual void releaseMemory(); - - /// runOnMachineFunction - pass entry point - virtual bool runOnMachineFunction(MachineFunction&); - - /// print - Implement the dump method. - virtual void print(raw_ostream &O, const Module* = 0) const; - }; /// CoalescerPair - A helper class for register coalescers. When deciding if /// two registers can be coalesced, CoalescerPair can determine if a copy /// instruction would become an identity copy after coalescing. class CoalescerPair { - const TargetInstrInfo &tii_; - const TargetRegisterInfo &tri_; + const TargetInstrInfo &TII; + const TargetRegisterInfo &TRI; - /// dstReg_ - The register that will be left after coalescing. It can be a + /// DstReg - The register that will be left after coalescing. It can be a /// virtual or physical register. - unsigned dstReg_; + unsigned DstReg; - /// srcReg_ - the virtual register that will be coalesced into dstReg. - unsigned srcReg_; + /// SrcReg - the virtual register that will be coalesced into dstReg. + unsigned SrcReg; - /// subReg_ - The subregister index of srcReg in dstReg_. It is possible the - /// coalesce srcReg_ into a subreg of the larger dstReg_ when dstReg_ is a + /// subReg_ - The subregister index of srcReg in DstReg. It is possible the + /// coalesce SrcReg into a subreg of the larger DstReg when DstReg is a /// virtual register. - unsigned subIdx_; + unsigned SubIdx; - /// partial_ - True when the original copy was a partial subregister copy. - bool partial_; + /// Partial - True when the original copy was a partial subregister copy. + bool Partial; - /// crossClass_ - True when both regs are virtual, and newRC is constrained. - bool crossClass_; + /// CrossClass - True when both regs are virtual, and newRC is constrained. + bool CrossClass; - /// flipped_ - True when DstReg and SrcReg are reversed from the oriignal copy - /// instruction. - bool flipped_; + /// Flipped - True when DstReg and SrcReg are reversed from the oriignal + /// copy instruction. + bool Flipped; - /// newRC_ - The register class of the coalesced register, or NULL if dstReg_ + /// NewRC - The register class of the coalesced register, or NULL if DstReg /// is a physreg. - const TargetRegisterClass *newRC_; + const TargetRegisterClass *NewRC; public: CoalescerPair(const TargetInstrInfo &tii, const TargetRegisterInfo &tri) - : tii_(tii), tri_(tri), dstReg_(0), srcReg_(0), subIdx_(0), - partial_(false), crossClass_(false), flipped_(false), newRC_(0) {} + : TII(tii), TRI(tri), DstReg(0), SrcReg(0), SubIdx(0), + Partial(false), CrossClass(false), Flipped(false), NewRC(0) {} /// setRegisters - set registers to match the copy instruction MI. Return /// false if MI is not a coalescable copy instruction. bool setRegisters(const MachineInstr*); - /// flip - Swap srcReg_ and dstReg_. Return false if swapping is impossible - /// because dstReg_ is a physical register, or subIdx_ is set. + /// flip - Swap SrcReg and DstReg. Return false if swapping is impossible + /// because DstReg is a physical register, or SubIdx is set. bool flip(); /// isCoalescable - Return true if MI is a copy instruction that will become @@ -211,32 +73,33 @@ namespace llvm { bool isCoalescable(const MachineInstr*) const; /// isPhys - Return true if DstReg is a physical register. - bool isPhys() const { return !newRC_; } + bool isPhys() const { return !NewRC; } - /// isPartial - Return true if the original copy instruction did not copy the - /// full register, but was a subreg operation. - bool isPartial() const { return partial_; } + /// isPartial - Return true if the original copy instruction did not copy + /// the full register, but was a subreg operation. + bool isPartial() const { return Partial; } - /// isCrossClass - Return true if DstReg is virtual and NewRC is a smaller register class than DstReg's. - bool isCrossClass() const { return crossClass_; } + /// isCrossClass - Return true if DstReg is virtual and NewRC is a smaller + /// register class than DstReg's. + bool isCrossClass() const { return CrossClass; } /// isFlipped - Return true when getSrcReg is the register being defined by /// the original copy instruction. - bool isFlipped() const { return flipped_; } + bool isFlipped() const { return Flipped; } /// getDstReg - Return the register (virtual or physical) that will remain /// after coalescing. - unsigned getDstReg() const { return dstReg_; } + unsigned getDstReg() const { return DstReg; } /// getSrcReg - Return the virtual register that will be coalesced away. - unsigned getSrcReg() const { return srcReg_; } + unsigned getSrcReg() const { return SrcReg; } /// getSubIdx - Return the subregister index in DstReg that SrcReg will be /// coalesced into, or 0. - unsigned getSubIdx() const { return subIdx_; } + unsigned getSubIdx() const { return SubIdx; } /// getNewRC - Return the register class of the coalesced register. - const TargetRegisterClass *getNewRC() const { return newRC_; } + const TargetRegisterClass *getNewRC() const { return NewRC; } }; } // End llvm namespace diff --git a/contrib/llvm/lib/CodeGen/RegisterScavenging.cpp b/contrib/llvm/lib/CodeGen/RegisterScavenging.cpp index 9e9a145b0..ca02aa1b8 100644 --- a/contrib/llvm/lib/CodeGen/RegisterScavenging.cpp +++ b/contrib/llvm/lib/CodeGen/RegisterScavenging.cpp @@ -206,6 +206,7 @@ void RegScavenger::forward() { break; } assert(SubUsed && "Using an undefined register!"); + (void)SubUsed; } assert((!EarlyClobberRegs.test(Reg) || MI->isRegTiedToDefOperand(i)) && "Using an early clobbered register!"); diff --git a/contrib/llvm/lib/CodeGen/ScheduleDAG.cpp b/contrib/llvm/lib/CodeGen/ScheduleDAG.cpp index 21375b286..1e9b5c89f 100644 --- a/contrib/llvm/lib/CodeGen/ScheduleDAG.cpp +++ b/contrib/llvm/lib/CodeGen/ScheduleDAG.cpp @@ -26,7 +26,7 @@ using namespace llvm; #ifndef NDEBUG -cl::opt StressSchedOpt( +static cl::opt StressSchedOpt( "stress-sched", cl::Hidden, cl::init(false), cl::desc("Stress test instruction scheduling")); #endif @@ -140,6 +140,7 @@ void SUnit::removePred(const SDep &D) { break; } assert(FoundSucc && "Mismatching preds / succs lists!"); + (void)FoundSucc; Preds.erase(I); // Update the bookkeeping. if (P.getKind() == SDep::Data) { diff --git a/contrib/llvm/lib/CodeGen/ScheduleDAGInstrs.cpp b/contrib/llvm/lib/CodeGen/ScheduleDAGInstrs.cpp index 446adfc2b..34b8ab0b4 100644 --- a/contrib/llvm/lib/CodeGen/ScheduleDAGInstrs.cpp +++ b/contrib/llvm/lib/CodeGen/ScheduleDAGInstrs.cpp @@ -36,7 +36,7 @@ ScheduleDAGInstrs::ScheduleDAGInstrs(MachineFunction &mf, const MachineDominatorTree &mdt) : ScheduleDAG(mf), MLI(mli), MDT(mdt), MFI(mf.getFrameInfo()), InstrItins(mf.getTarget().getInstrItineraryData()), - Defs(TRI->getNumRegs()), Uses(TRI->getNumRegs()), + Defs(TRI->getNumRegs()), Uses(TRI->getNumRegs()), LoopRegs(MLI, MDT), FirstDbgValue(0) { DbgValues.clear(); } @@ -134,6 +134,7 @@ static const Value *getUnderlyingObjectForInstr(const MachineInstr *MI, } void ScheduleDAGInstrs::StartBlock(MachineBasicBlock *BB) { + LoopRegs.Deps.clear(); if (MachineLoop *ML = MLI.getLoopFor(BB)) if (BB == ML->getLoopLatch()) { MachineBasicBlock *Header = ML->getHeader(); diff --git a/contrib/llvm/lib/CodeGen/ScheduleDAGInstrs.h b/contrib/llvm/lib/CodeGen/ScheduleDAGInstrs.h index 8a4ea8552..666bdf548 100644 --- a/contrib/llvm/lib/CodeGen/ScheduleDAGInstrs.h +++ b/contrib/llvm/lib/CodeGen/ScheduleDAGInstrs.h @@ -48,7 +48,8 @@ namespace llvm { /// VisitLoop - Clear out any previous state and analyze the given loop. /// void VisitLoop(const MachineLoop *Loop) { - Deps.clear(); + assert(Deps.empty() && "stale loop dependencies"); + MachineBasicBlock *Header = Loop->getHeader(); SmallSet LoopLiveIns; for (MachineBasicBlock::livein_iterator LI = Header->livein_begin(), @@ -109,7 +110,7 @@ namespace llvm { /// initialized and destructed for each block. std::vector > Defs; std::vector > Uses; - + /// PendingLoads - Remember where unknown loads are after the most recent /// unknown store, as we iterate. As with Defs and Uses, this is here /// to minimize construction/destruction. @@ -127,7 +128,7 @@ namespace llvm { protected: /// DbgValues - Remember instruction that preceeds DBG_VALUE. - typedef std::vector > + typedef std::vector > DbgValueVector; DbgValueVector DbgValues; MachineInstr *FirstDbgValue; diff --git a/contrib/llvm/lib/CodeGen/ScoreboardHazardRecognizer.cpp b/contrib/llvm/lib/CodeGen/ScoreboardHazardRecognizer.cpp index 0e005d351..b80c01ed5 100644 --- a/contrib/llvm/lib/CodeGen/ScoreboardHazardRecognizer.cpp +++ b/contrib/llvm/lib/CodeGen/ScoreboardHazardRecognizer.cpp @@ -213,7 +213,6 @@ void ScoreboardHazardRecognizer::EmitInstruction(SUnit *SU) { freeUnits = freeUnit & (freeUnit - 1); } while (freeUnits); - assert(freeUnit && "No function unit available!"); if (IS->getReservationKind() == InstrStage::Required) RequiredScoreboard[cycle + i] |= freeUnit; else diff --git a/contrib/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/contrib/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index 4f0d2caca..7b878688d 100644 --- a/contrib/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/contrib/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -216,6 +216,7 @@ namespace { SDValue visitEXTRACT_VECTOR_ELT(SDNode *N); SDValue visitBUILD_VECTOR(SDNode *N); SDValue visitCONCAT_VECTORS(SDNode *N); + SDValue visitEXTRACT_SUBVECTOR(SDNode *N); SDValue visitVECTOR_SHUFFLE(SDNode *N); SDValue visitMEMBARRIER(SDNode *N); @@ -1105,6 +1106,7 @@ SDValue DAGCombiner::visit(SDNode *N) { case ISD::EXTRACT_VECTOR_ELT: return visitEXTRACT_VECTOR_ELT(N); case ISD::BUILD_VECTOR: return visitBUILD_VECTOR(N); case ISD::CONCAT_VECTORS: return visitCONCAT_VECTORS(N); + case ISD::EXTRACT_SUBVECTOR: return visitEXTRACT_SUBVECTOR(N); case ISD::VECTOR_SHUFFLE: return visitVECTOR_SHUFFLE(N); case ISD::MEMBARRIER: return visitMEMBARRIER(N); } @@ -1526,12 +1528,6 @@ SDValue DAGCombiner::visitADDE(SDNode *N) { ConstantSDNode *N0C = dyn_cast(N0); ConstantSDNode *N1C = dyn_cast(N1); - // If both operands are null we know that carry out will always be false. - if (N0C && N0C->isNullValue() && N0 == N1) - DAG.ReplaceAllUsesOfValueWith(SDValue(N, 1), DAG.getNode(ISD::CARRY_FALSE, - N->getDebugLoc(), - MVT::Glue)); - // canonicalize constant to RHS if (N0C && !N1C) return DAG.getNode(ISD::ADDE, N->getDebugLoc(), N->getVTList(), @@ -3763,7 +3759,7 @@ SDValue DAGCombiner::visitSELECT(SDNode *N) { if (VT.isInteger() && (VT0 == MVT::i1 || (VT0.isInteger() && - TLI.getBooleanContents() == TargetLowering::ZeroOrOneBooleanContent)) && + TLI.getBooleanContents(false) == TargetLowering::ZeroOrOneBooleanContent)) && N1C && N2C && N1C->isNullValue() && N2C->getAPIntValue() == 1) { SDValue XORNode; if (VT == VT0) @@ -4118,7 +4114,7 @@ SDValue DAGCombiner::visitSIGN_EXTEND(SDNode *N) { // we know that the element size of the sext'd result matches the // element size of the compare operands. if (VT.getSizeInBits() == N0VT.getSizeInBits()) - return DAG.getVSetCC(N->getDebugLoc(), VT, N0.getOperand(0), + return DAG.getSetCC(N->getDebugLoc(), VT, N0.getOperand(0), N0.getOperand(1), cast(N0.getOperand(2))->get()); // If the desired elements are smaller or larger than the source @@ -4132,7 +4128,7 @@ SDValue DAGCombiner::visitSIGN_EXTEND(SDNode *N) { EVT::getVectorVT(*DAG.getContext(), MatchingElementType, N0VT.getVectorNumElements()); SDValue VsetCC = - DAG.getVSetCC(N->getDebugLoc(), MatchingVectorType, N0.getOperand(0), + DAG.getSetCC(N->getDebugLoc(), MatchingVectorType, N0.getOperand(0), N0.getOperand(1), cast(N0.getOperand(2))->get()); return DAG.getSExtOrTrunc(VsetCC, N->getDebugLoc(), VT); @@ -4348,7 +4344,7 @@ SDValue DAGCombiner::visitZERO_EXTEND(SDNode *N) { // we know that the element size of the sext'd result matches the // element size of the compare operands. return DAG.getNode(ISD::AND, N->getDebugLoc(), VT, - DAG.getVSetCC(N->getDebugLoc(), VT, N0.getOperand(0), + DAG.getSetCC(N->getDebugLoc(), VT, N0.getOperand(0), N0.getOperand(1), cast(N0.getOperand(2))->get()), DAG.getNode(ISD::BUILD_VECTOR, N->getDebugLoc(), VT, @@ -4364,7 +4360,7 @@ SDValue DAGCombiner::visitZERO_EXTEND(SDNode *N) { EVT::getVectorVT(*DAG.getContext(), MatchingElementType, N0VT.getVectorNumElements()); SDValue VsetCC = - DAG.getVSetCC(N->getDebugLoc(), MatchingVectorType, N0.getOperand(0), + DAG.getSetCC(N->getDebugLoc(), MatchingVectorType, N0.getOperand(0), N0.getOperand(1), cast(N0.getOperand(2))->get()); return DAG.getNode(ISD::AND, N->getDebugLoc(), VT, @@ -4532,7 +4528,7 @@ SDValue DAGCombiner::visitANY_EXTEND(SDNode *N) { // we know that the element size of the sext'd result matches the // element size of the compare operands. if (VT.getSizeInBits() == N0VT.getSizeInBits()) - return DAG.getVSetCC(N->getDebugLoc(), VT, N0.getOperand(0), + return DAG.getSetCC(N->getDebugLoc(), VT, N0.getOperand(0), N0.getOperand(1), cast(N0.getOperand(2))->get()); // If the desired elements are smaller or larger than the source @@ -4546,7 +4542,7 @@ SDValue DAGCombiner::visitANY_EXTEND(SDNode *N) { EVT::getVectorVT(*DAG.getContext(), MatchingElementType, N0VT.getVectorNumElements()); SDValue VsetCC = - DAG.getVSetCC(N->getDebugLoc(), MatchingVectorType, N0.getOperand(0), + DAG.getSetCC(N->getDebugLoc(), MatchingVectorType, N0.getOperand(0), N0.getOperand(1), cast(N0.getOperand(2))->get()); return DAG.getSExtOrTrunc(VsetCC, N->getDebugLoc(), VT); @@ -6479,7 +6475,7 @@ SDValue DAGCombiner::ReduceLoadOpStoreWidth(SDNode *N) { PtrOff = (BitWidth + 7 - NewBW) / 8 - PtrOff; unsigned NewAlign = MinAlign(LD->getAlignment(), PtrOff); - const Type *NewVTTy = NewVT.getTypeForEVT(*DAG.getContext()); + Type *NewVTTy = NewVT.getTypeForEVT(*DAG.getContext()); if (NewAlign < TLI.getTargetData()->getABITypeAlignment(NewVTTy)) return SDValue(); @@ -6542,7 +6538,7 @@ SDValue DAGCombiner::TransformFPLoadStorePair(SDNode *N) { unsigned LDAlign = LD->getAlignment(); unsigned STAlign = ST->getAlignment(); - const Type *IntVTTy = IntVT.getTypeForEVT(*DAG.getContext()); + Type *IntVTTy = IntVT.getTypeForEVT(*DAG.getContext()); unsigned ABIAlign = TLI.getTargetData()->getABITypeAlignment(IntVTTy); if (LDAlign < ABIAlign || STAlign < ABIAlign) return SDValue(); @@ -6776,6 +6772,7 @@ SDValue DAGCombiner::visitINSERT_VECTOR_ELT(SDNode *N) { SDValue InVec = N->getOperand(0); SDValue InVal = N->getOperand(1); SDValue EltNo = N->getOperand(2); + DebugLoc dl = N->getDebugLoc(); // If the inserted element is an UNDEF, just use the input vector. if (InVal.getOpcode() == ISD::UNDEF) @@ -6787,32 +6784,40 @@ SDValue DAGCombiner::visitINSERT_VECTOR_ELT(SDNode *N) { if (LegalOperations && !TLI.isOperationLegal(ISD::BUILD_VECTOR, VT)) return SDValue(); - // If the invec is a BUILD_VECTOR and if EltNo is a constant, build a new - // vector with the inserted element. - if (InVec.getOpcode() == ISD::BUILD_VECTOR && isa(EltNo)) { - unsigned Elt = cast(EltNo)->getZExtValue(); - SmallVector Ops(InVec.getNode()->op_begin(), - InVec.getNode()->op_end()); - if (Elt < Ops.size()) - Ops[Elt] = InVal; - return DAG.getNode(ISD::BUILD_VECTOR, N->getDebugLoc(), - VT, &Ops[0], Ops.size()); - } - // If the invec is an UNDEF and if EltNo is a constant, create a new - // BUILD_VECTOR with undef elements and the inserted element. - if (InVec.getOpcode() == ISD::UNDEF && - isa(EltNo)) { - EVT EltVT = VT.getVectorElementType(); + // Check that we know which element is being inserted + if (!isa(EltNo)) + return SDValue(); + unsigned Elt = cast(EltNo)->getZExtValue(); + + // Check that the operand is a BUILD_VECTOR (or UNDEF, which can essentially + // be converted to a BUILD_VECTOR). Fill in the Ops vector with the + // vector elements. + SmallVector Ops; + if (InVec.getOpcode() == ISD::BUILD_VECTOR) { + Ops.append(InVec.getNode()->op_begin(), + InVec.getNode()->op_end()); + } else if (InVec.getOpcode() == ISD::UNDEF) { unsigned NElts = VT.getVectorNumElements(); - SmallVector Ops(NElts, DAG.getUNDEF(EltVT)); + Ops.append(NElts, DAG.getUNDEF(InVal.getValueType())); + } else { + return SDValue(); + } - unsigned Elt = cast(EltNo)->getZExtValue(); - if (Elt < Ops.size()) - Ops[Elt] = InVal; - return DAG.getNode(ISD::BUILD_VECTOR, N->getDebugLoc(), - VT, &Ops[0], Ops.size()); + // Insert the element + if (Elt < Ops.size()) { + // All the operands of BUILD_VECTOR must have the same type; + // we enforce that here. + EVT OpVT = Ops[0].getValueType(); + if (InVal.getValueType() != OpVT) + InVal = OpVT.bitsGT(InVal.getValueType()) ? + DAG.getNode(ISD::ANY_EXTEND, dl, OpVT, InVal) : + DAG.getNode(ISD::TRUNCATE, dl, OpVT, InVal); + Ops[Elt] = InVal; } - return SDValue(); + + // Return the new vector + return DAG.getNode(ISD::BUILD_VECTOR, dl, + VT, &Ops[0], Ops.size()); } SDValue DAGCombiner::visitEXTRACT_VECTOR_ELT(SDNode *N) { @@ -6896,7 +6901,7 @@ SDValue DAGCombiner::visitEXTRACT_VECTOR_ELT(SDNode *N) { // If Idx was -1 above, Elt is going to be -1, so just return undef. if (Elt == -1) - return DAG.getUNDEF(LN0->getBasePtr().getValueType()); + return DAG.getUNDEF(LVT); unsigned Align = LN0->getAlignment(); if (NewLoad) { @@ -7028,6 +7033,36 @@ SDValue DAGCombiner::visitCONCAT_VECTORS(SDNode *N) { return SDValue(); } +SDValue DAGCombiner::visitEXTRACT_SUBVECTOR(SDNode* N) { + EVT NVT = N->getValueType(0); + SDValue V = N->getOperand(0); + + if (V->getOpcode() == ISD::INSERT_SUBVECTOR) { + // Handle only simple case where vector being inserted and vector + // being extracted are of same type, and are half size of larger vectors. + EVT BigVT = V->getOperand(0).getValueType(); + EVT SmallVT = V->getOperand(1).getValueType(); + if (NVT != SmallVT || NVT.getSizeInBits()*2 != BigVT.getSizeInBits()) + return SDValue(); + + // Combine: + // (extract_subvec (insert_subvec V1, V2, InsIdx), ExtIdx) + // Into: + // indicies are equal => V1 + // otherwise => (extract_subvec V1, ExtIdx) + // + SDValue InsIdx = N->getOperand(1); + SDValue ExtIdx = V->getOperand(2); + + if (InsIdx == ExtIdx) + return V->getOperand(1); + return DAG.getNode(ISD::EXTRACT_SUBVECTOR, N->getDebugLoc(), NVT, + V->getOperand(0), N->getOperand(1)); + } + + return SDValue(); +} + SDValue DAGCombiner::visitVECTOR_SHUFFLE(SDNode *N) { EVT VT = N->getValueType(0); unsigned NumElts = VT.getVectorNumElements(); @@ -7447,7 +7482,7 @@ SDValue DAGCombiner::SimplifySelectCC(DebugLoc DL, SDValue N0, SDValue N1, const_cast(FV->getConstantFPValue()), const_cast(TV->getConstantFPValue()) }; - const Type *FPTy = Elts[0]->getType(); + Type *FPTy = Elts[0]->getType(); const TargetData &TD = *TLI.getTargetData(); // Create a ConstantArray of the two constants. @@ -7465,10 +7500,13 @@ SDValue DAGCombiner::SimplifySelectCC(DebugLoc DL, SDValue N0, SDValue N1, SDValue Cond = DAG.getSetCC(DL, TLI.getSetCCResultType(N0.getValueType()), N0, N1, CC); + AddToWorkList(Cond.getNode()); SDValue CstOffset = DAG.getNode(ISD::SELECT, DL, Zero.getValueType(), Cond, One, Zero); + AddToWorkList(CstOffset.getNode()); CPIdx = DAG.getNode(ISD::ADD, DL, TLI.getPointerTy(), CPIdx, CstOffset); + AddToWorkList(CPIdx.getNode()); return DAG.getLoad(TV->getValueType(0), DL, DAG.getEntryNode(), CPIdx, MachinePointerInfo::getConstantPool(), false, false, Alignment); @@ -7553,7 +7591,8 @@ SDValue DAGCombiner::SimplifySelectCC(DebugLoc DL, SDValue N0, SDValue N1, // fold select C, 16, 0 -> shl C, 4 if (N2C && N3C && N3C->isNullValue() && N2C->getAPIntValue().isPowerOf2() && - TLI.getBooleanContents() == TargetLowering::ZeroOrOneBooleanContent) { + TLI.getBooleanContents(N0.getValueType().isVector()) == + TargetLowering::ZeroOrOneBooleanContent) { // If the caller doesn't want us to simplify this into a zext of a compare, // don't do it. diff --git a/contrib/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp b/contrib/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp index 54a7d43f4..e8f8c73d6 100644 --- a/contrib/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp +++ b/contrib/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp @@ -66,17 +66,22 @@ using namespace llvm; void FastISel::startNewBlock() { LocalValueMap.clear(); - // Start out as null, meaining no local-value instructions have - // been emitted. - LastLocalValue = 0; + EmitStartPt = 0; - // Advance the last local value past any EH_LABEL instructions. + // Advance the emit start point past any EH_LABEL instructions. MachineBasicBlock::iterator I = FuncInfo.MBB->begin(), E = FuncInfo.MBB->end(); while (I != E && I->getOpcode() == TargetOpcode::EH_LABEL) { - LastLocalValue = I; + EmitStartPt = I; ++I; } + LastLocalValue = EmitStartPt; +} + +void FastISel::flushLocalValueMap() { + LocalValueMap.clear(); + LastLocalValue = EmitStartPt; + recomputeInsertPt(); } bool FastISel::hasTrivialKill(const Value *V) const { @@ -183,7 +188,7 @@ unsigned FastISel::materializeRegForValue(const Value *V, MVT VT) { (void) Flt.convertToInteger(x, IntBitWidth, /*isSigned=*/true, APFloat::rmTowardZero, &isExact); if (isExact) { - APInt IntVal(IntBitWidth, 2, x); + APInt IntVal(IntBitWidth, x); unsigned IntegerReg = getRegForValue(ConstantInt::get(V->getContext(), IntVal)); @@ -422,12 +427,12 @@ bool FastISel::SelectGetElementPtr(const User *I) { bool NIsKill = hasTrivialKill(I->getOperand(0)); - const Type *Ty = I->getOperand(0)->getType(); + Type *Ty = I->getOperand(0)->getType(); MVT VT = TLI.getPointerTy(); for (GetElementPtrInst::const_op_iterator OI = I->op_begin()+1, E = I->op_end(); OI != E; ++OI) { const Value *Idx = *OI; - if (const StructType *StTy = dyn_cast(Ty)) { + if (StructType *StTy = dyn_cast(Ty)) { unsigned Field = cast(Idx)->getZExtValue(); if (Field) { // N = N + Offset @@ -489,7 +494,7 @@ bool FastISel::SelectCall(const User *I) { const CallInst *Call = cast(I); // Handle simple inline asms. - if (const InlineAsm *IA = dyn_cast(Call->getArgOperand(0))) { + if (const InlineAsm *IA = dyn_cast(Call->getCalledValue())) { // Don't attempt to handle constraints. if (!IA->getConstraintString().empty()) return false; @@ -526,13 +531,10 @@ bool FastISel::SelectCall(const User *I) { unsigned Reg = 0; unsigned Offset = 0; if (const Argument *Arg = dyn_cast(Address)) { - if (Arg->hasByValAttr()) { - // Byval arguments' frame index is recorded during argument lowering. - // Use this info directly. - Offset = FuncInfo.getByValArgumentFrameIndex(Arg); - if (Offset) - Reg = TRI.getFrameRegister(*FuncInfo.MF); - } + // Some arguments' frame index is recorded during argument lowering. + Offset = FuncInfo.getArgumentFrameIndex(Arg); + if (Offset) + Reg = TRI.getFrameRegister(*FuncInfo.MF); } if (!Reg) Reg = getRegForValue(Address); @@ -645,6 +647,16 @@ bool FastISel::SelectCall(const User *I) { } } + // Usually, it does not make sense to initialize a value, + // make an unrelated function call and use the value, because + // it tends to be spilled on the stack. So, we move the pointer + // to the last local value to the beginning of the block, so that + // all the values which have already been materialized, + // appear after the call. It also makes sense to skip intrinsics + // since they tend to be inlined. + if (!isa(F)) + flushLocalValueMap(); + // An arbitrary call. Bail. return false; } @@ -839,7 +851,7 @@ FastISel::SelectExtractValue(const User *U) { return false; const Value *Op0 = EVI->getOperand(0); - const Type *AggTy = Op0->getType(); + Type *AggTy = Op0->getType(); // Get the base result register. unsigned ResultReg; @@ -1074,7 +1086,7 @@ unsigned FastISel::FastEmit_ri_(MVT VT, unsigned Opcode, if (MaterialReg == 0) { // This is a bit ugly/slow, but failing here means falling out of // fast-isel, which would be very slow. - const IntegerType *ITy = IntegerType::get(FuncInfo.Fn->getContext(), + IntegerType *ITy = IntegerType::get(FuncInfo.Fn->getContext(), VT.getSizeInBits()); MaterialReg = getRegForValue(ConstantInt::get(ITy, Imm)); } diff --git a/contrib/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp b/contrib/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp index d518b5d34..b052740a1 100644 --- a/contrib/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp +++ b/contrib/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp @@ -78,7 +78,7 @@ void FunctionLoweringInfo::set(const Function &fn, MachineFunction &mf) { for (BasicBlock::const_iterator I = BB->begin(), E = BB->end(); I != E; ++I) if (const AllocaInst *AI = dyn_cast(I)) if (const ConstantInt *CUI = dyn_cast(AI->getArraySize())) { - const Type *Ty = AI->getAllocatedType(); + Type *Ty = AI->getAllocatedType(); uint64_t TySize = TLI.getTargetData()->getTypeAllocSize(Ty); unsigned Align = std::max((unsigned)TLI.getTargetData()->getPrefTypeAlignment(Ty), @@ -216,7 +216,7 @@ unsigned FunctionLoweringInfo::CreateReg(EVT VT) { /// In the case that the given value has struct or array type, this function /// will assign registers for each member or element. /// -unsigned FunctionLoweringInfo::CreateRegs(const Type *Ty) { +unsigned FunctionLoweringInfo::CreateRegs(Type *Ty) { SmallVector ValueVTs; ComputeValueVTs(TLI, Ty, ValueVTs); @@ -260,7 +260,7 @@ FunctionLoweringInfo::GetLiveOutRegInfo(unsigned Reg, unsigned BitWidth) { /// ComputePHILiveOutRegInfo - Compute LiveOutInfo for a PHI's destination /// register based on the LiveOutInfo of its operands. void FunctionLoweringInfo::ComputePHILiveOutRegInfo(const PHINode *PN) { - const Type *Ty = PN->getType(); + Type *Ty = PN->getType(); if (!Ty->isIntegerTy() || Ty->isVectorTy()) return; @@ -351,20 +351,18 @@ void FunctionLoweringInfo::ComputePHILiveOutRegInfo(const PHINode *PN) { } } -/// setByValArgumentFrameIndex - Record frame index for the byval +/// setArgumentFrameIndex - Record frame index for the byval /// argument. This overrides previous frame index entry for this argument, /// if any. -void FunctionLoweringInfo::setByValArgumentFrameIndex(const Argument *A, +void FunctionLoweringInfo::setArgumentFrameIndex(const Argument *A, int FI) { - assert (A->hasByValAttr() && "Argument does not have byval attribute!"); ByValArgFrameIndexMap[A] = FI; } -/// getByValArgumentFrameIndex - Get frame index for the byval argument. +/// getArgumentFrameIndex - Get frame index for the byval argument. /// If the argument does not have any assigned frame index then 0 is /// returned. -int FunctionLoweringInfo::getByValArgumentFrameIndex(const Argument *A) { - assert (A->hasByValAttr() && "Argument does not have byval attribute!"); +int FunctionLoweringInfo::getArgumentFrameIndex(const Argument *A) { DenseMap::iterator I = ByValArgFrameIndexMap.find(A); if (I != ByValArgFrameIndexMap.end()) @@ -454,3 +452,34 @@ void llvm::CopyCatchInfo(const BasicBlock *SuccBB, const BasicBlock *LPad, break; } } + +/// AddLandingPadInfo - Extract the exception handling information from the +/// landingpad instruction and add them to the specified machine module info. +void llvm::AddLandingPadInfo(const LandingPadInst &I, MachineModuleInfo &MMI, + MachineBasicBlock *MBB) { + MMI.addPersonality(MBB, + cast(I.getPersonalityFn()->stripPointerCasts())); + + if (I.isCleanup()) + MMI.addCleanup(MBB); + + // FIXME: New EH - Add the clauses in reverse order. This isn't 100% correct, + // but we need to do it this way because of how the DWARF EH emitter + // processes the clauses. + for (unsigned i = I.getNumClauses(); i != 0; --i) { + Value *Val = I.getClause(i - 1); + if (I.isCatch(i - 1)) { + MMI.addCatchTypeInfo(MBB, + dyn_cast(Val->stripPointerCasts())); + } else { + // Add filters in a list. + Constant *CVal = cast(Val); + SmallVector FilterList; + for (User::op_iterator + II = CVal->op_begin(), IE = CVal->op_end(); II != IE; ++II) + FilterList.push_back(cast((*II)->stripPointerCasts())); + + MMI.addFilterTypeInfo(MBB, FilterList); + } + } +} diff --git a/contrib/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp b/contrib/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp index f0f474329..2ff66f8f8 100644 --- a/contrib/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp +++ b/contrib/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp @@ -30,6 +30,12 @@ #include "llvm/Support/MathExtras.h" using namespace llvm; +/// MinRCSize - Smallest register class we allow when constraining virtual +/// registers. If satisfying all register class constraints would require +/// using a smaller register class, emit a COPY to a new virtual register +/// instead. +const unsigned MinRCSize = 4; + /// CountResults - The results of target nodes have register or immediate /// operands first, then an optional chain, and optional glue operands (which do /// not go into the resulting MachineInstr). @@ -87,7 +93,7 @@ EmitCopyFromReg(SDNode *Node, unsigned ResNo, bool IsClone, bool IsCloned, UI != E; ++UI) { SDNode *User = *UI; bool Match = true; - if (User->getOpcode() == ISD::CopyToReg && + if (User->getOpcode() == ISD::CopyToReg && User->getOperand(2).getNode() == Node && User->getOperand(2).getResNo() == ResNo) { unsigned DestReg = cast(User->getOperand(1))->getReg(); @@ -113,7 +119,8 @@ EmitCopyFromReg(SDNode *Node, unsigned ResNo, bool IsClone, bool IsCloned, if (!UseRC) UseRC = RC; else if (RC) { - const TargetRegisterClass *ComRC = getCommonSubClass(UseRC, RC); + const TargetRegisterClass *ComRC = + TRI->getCommonSubClass(UseRC, RC); // If multiple uses expect disjoint register classes, we emit // copies in AddRegisterOperand. if (ComRC) @@ -139,7 +146,7 @@ EmitCopyFromReg(SDNode *Node, unsigned ResNo, bool IsClone, bool IsCloned, } else { DstRC = TLI->getRegClassFor(VT); } - + // If all uses are reading from the src physical register and copying the // register is either impossible or very expensive, then don't create a copy. if (MatchReg && SrcRC->getCopyCost() < 0) { @@ -167,7 +174,7 @@ unsigned InstrEmitter::getDstOfOnlyCopyToRegUse(SDNode *Node, return 0; SDNode *User = *Node->use_begin(); - if (User->getOpcode() == ISD::CopyToReg && + if (User->getOpcode() == ISD::CopyToReg && User->getOperand(2).getNode() == Node && User->getOperand(2).getResNo() == ResNo) { unsigned Reg = cast(User->getOperand(1))->getReg(); @@ -202,7 +209,7 @@ void InstrEmitter::CreateVirtualRegisters(SDNode *Node, MachineInstr *MI, for (SDNode::use_iterator UI = Node->use_begin(), E = Node->use_end(); UI != E; ++UI) { SDNode *User = *UI; - if (User->getOpcode() == ISD::CopyToReg && + if (User->getOpcode() == ISD::CopyToReg && User->getOperand(2).getNode() == Node && User->getOperand(2).getResNo() == i) { unsigned Reg = cast(User->getOperand(1))->getReg(); @@ -280,15 +287,16 @@ InstrEmitter::AddRegisterOperand(MachineInstr *MI, SDValue Op, MCID.OpInfo[IIOpNum].isOptionalDef(); // If the instruction requires a register in a different class, create - // a new virtual register and copy the value into it. + // a new virtual register and copy the value into it, but first attempt to + // shrink VReg's register class within reason. For example, if VReg == GR32 + // and II requires a GR32_NOSP, just constrain VReg to GR32_NOSP. if (II) { - const TargetRegisterClass *SrcRC = MRI->getRegClass(VReg); const TargetRegisterClass *DstRC = 0; if (IIOpNum < II->getNumOperands()) DstRC = TII->getRegClass(*II, IIOpNum, TRI); assert((DstRC || (MCID.isVariadic() && IIOpNum >= MCID.getNumOperands())) && "Don't have operand info for this instruction!"); - if (DstRC && !SrcRC->hasSuperClassEq(DstRC)) { + if (DstRC && !MRI->constrainRegClass(VReg, DstRC, MinRCSize)) { unsigned NewVReg = MRI->createVirtualRegister(DstRC); BuildMI(*MBB, InsertPos, Op.getNode()->getDebugLoc(), TII->get(TargetOpcode::COPY), NewVReg).addReg(VReg); @@ -326,7 +334,7 @@ InstrEmitter::AddRegisterOperand(MachineInstr *MI, SDValue Op, /// AddOperand - Add the specified operand to the specified machine instr. II /// specifies the instruction information for the node, and IIOpNum is the -/// operand number (in the II) that we are adding. IIOpNum and II are used for +/// operand number (in the II) that we are adding. IIOpNum and II are used for /// assertions only. void InstrEmitter::AddOperand(MachineInstr *MI, SDValue Op, unsigned IIOpNum, @@ -356,7 +364,7 @@ void InstrEmitter::AddOperand(MachineInstr *MI, SDValue Op, } else if (ConstantPoolSDNode *CP = dyn_cast(Op)) { int Offset = CP->getOffset(); unsigned Align = CP->getAlignment(); - const Type *Type = CP->getType(); + Type *Type = CP->getType(); // MachineConstantPool wants an explicit alignment. if (Align == 0) { Align = TM->getTargetData()->getPrefTypeAlignment(Type); @@ -365,7 +373,7 @@ void InstrEmitter::AddOperand(MachineInstr *MI, SDValue Op, Align = TM->getTargetData()->getTypeAllocSize(Type); } } - + unsigned Idx; MachineConstantPool *MCP = MF->getConstantPool(); if (CP->isMachineConstantPoolEntry()) @@ -389,35 +397,44 @@ void InstrEmitter::AddOperand(MachineInstr *MI, SDValue Op, } } -/// getSuperRegisterRegClass - Returns the register class of a superreg A whose -/// "SubIdx"'th sub-register class is the specified register class and whose -/// type matches the specified type. -static const TargetRegisterClass* -getSuperRegisterRegClass(const TargetRegisterClass *TRC, - unsigned SubIdx, EVT VT) { - // Pick the register class of the superegister for this type - for (TargetRegisterInfo::regclass_iterator I = TRC->superregclasses_begin(), - E = TRC->superregclasses_end(); I != E; ++I) - if ((*I)->hasType(VT) && (*I)->getSubRegisterRegClass(SubIdx) == TRC) - return *I; - assert(false && "Couldn't find the register class"); - return 0; +unsigned InstrEmitter::ConstrainForSubReg(unsigned VReg, unsigned SubIdx, + EVT VT, DebugLoc DL) { + const TargetRegisterClass *VRC = MRI->getRegClass(VReg); + const TargetRegisterClass *RC = TRI->getSubClassWithSubReg(VRC, SubIdx); + + // RC is a sub-class of VRC that supports SubIdx. Try to constrain VReg + // within reason. + if (RC && RC != VRC) + RC = MRI->constrainRegClass(VReg, RC, MinRCSize); + + // VReg has been adjusted. It can be used with SubIdx operands now. + if (RC) + return VReg; + + // VReg couldn't be reasonably constrained. Emit a COPY to a new virtual + // register instead. + RC = TRI->getSubClassWithSubReg(TLI->getRegClassFor(VT), SubIdx); + assert(RC && "No legal register class for VT supports that SubIdx"); + unsigned NewReg = MRI->createVirtualRegister(RC); + BuildMI(*MBB, InsertPos, DL, TII->get(TargetOpcode::COPY), NewReg) + .addReg(VReg); + return NewReg; } /// EmitSubregNode - Generate machine code for subreg nodes. /// -void InstrEmitter::EmitSubregNode(SDNode *Node, +void InstrEmitter::EmitSubregNode(SDNode *Node, DenseMap &VRBaseMap, bool IsClone, bool IsCloned) { unsigned VRBase = 0; unsigned Opc = Node->getMachineOpcode(); - + // If the node is only used by a CopyToReg and the dest reg is a vreg, use // the CopyToReg'd destination register instead of creating a new vreg. for (SDNode::use_iterator UI = Node->use_begin(), E = Node->use_end(); UI != E; ++UI) { SDNode *User = *UI; - if (User->getOpcode() == ISD::CopyToReg && + if (User->getOpcode() == ISD::CopyToReg && User->getOperand(2).getNode() == Node) { unsigned DestReg = cast(User->getOperand(1))->getReg(); if (TargetRegisterInfo::isVirtualRegister(DestReg)) { @@ -426,12 +443,14 @@ void InstrEmitter::EmitSubregNode(SDNode *Node, } } } - + if (Opc == TargetOpcode::EXTRACT_SUBREG) { - // EXTRACT_SUBREG is lowered as %dst = COPY %src:sub + // EXTRACT_SUBREG is lowered as %dst = COPY %src:sub. There are no + // constraints on the %dst register, COPY can target all legal register + // classes. unsigned SubIdx = cast(Node->getOperand(1))->getZExtValue(); + const TargetRegisterClass *TRC = TLI->getRegClassFor(Node->getValueType(0)); - // Figure out the register class to create for the destreg. unsigned VReg = getVR(Node->getOperand(0), VRBaseMap); MachineInstr *DefMI = MRI->getVRegDef(VReg); unsigned SrcReg, DstReg, DefSubIdx; @@ -443,62 +462,57 @@ void InstrEmitter::EmitSubregNode(SDNode *Node, // r1026 = extract_subreg r1025, 4 // to a copy // r1026 = copy r1024 - const TargetRegisterClass *TRC = MRI->getRegClass(SrcReg); VRBase = MRI->createVirtualRegister(TRC); BuildMI(*MBB, InsertPos, Node->getDebugLoc(), TII->get(TargetOpcode::COPY), VRBase).addReg(SrcReg); } else { - const TargetRegisterClass *TRC = MRI->getRegClass(VReg); - const TargetRegisterClass *SRC = TRC->getSubRegisterRegClass(SubIdx); - assert(SRC && "Invalid subregister index in EXTRACT_SUBREG"); - - // Figure out the register class to create for the destreg. - // Note that if we're going to directly use an existing register, - // it must be precisely the required class, and not a subclass - // thereof. - if (VRBase == 0 || SRC != MRI->getRegClass(VRBase)) { - // Create the reg - assert(SRC && "Couldn't find source register class"); - VRBase = MRI->createVirtualRegister(SRC); - } + // VReg may not support a SubIdx sub-register, and we may need to + // constrain its register class or issue a COPY to a compatible register + // class. + VReg = ConstrainForSubReg(VReg, SubIdx, + Node->getOperand(0).getValueType(), + Node->getDebugLoc()); - // Create the extract_subreg machine instruction. - MachineInstr *MI = BuildMI(*MF, Node->getDebugLoc(), - TII->get(TargetOpcode::COPY), VRBase); + // Create the destreg if it is missing. + if (VRBase == 0) + VRBase = MRI->createVirtualRegister(TRC); - // Add source, and subreg index - AddOperand(MI, Node->getOperand(0), 0, 0, VRBaseMap, /*IsDebug=*/false, - IsClone, IsCloned); - assert(TargetRegisterInfo::isVirtualRegister(MI->getOperand(1).getReg())&& - "Cannot yet extract from physregs"); - MI->getOperand(1).setSubReg(SubIdx); - MBB->insert(InsertPos, MI); + // Create the extract_subreg machine instruction. + BuildMI(*MBB, InsertPos, Node->getDebugLoc(), + TII->get(TargetOpcode::COPY), VRBase).addReg(VReg, 0, SubIdx); } } else if (Opc == TargetOpcode::INSERT_SUBREG || Opc == TargetOpcode::SUBREG_TO_REG) { SDValue N0 = Node->getOperand(0); SDValue N1 = Node->getOperand(1); SDValue N2 = Node->getOperand(2); - unsigned SubReg = getVR(N1, VRBaseMap); unsigned SubIdx = cast(N2)->getZExtValue(); - const TargetRegisterClass *TRC = MRI->getRegClass(SubReg); - const TargetRegisterClass *SRC = - getSuperRegisterRegClass(TRC, SubIdx, Node->getValueType(0)); - - // Figure out the register class to create for the destreg. - // Note that if we're going to directly use an existing register, - // it must be precisely the required class, and not a subclass - // thereof. - if (VRBase == 0 || SRC != MRI->getRegClass(VRBase)) { - // Create the reg - assert(SRC && "Couldn't find source register class"); + + // Figure out the register class to create for the destreg. It should be + // the largest legal register class supporting SubIdx sub-registers. + // RegisterCoalescer will constrain it further if it decides to eliminate + // the INSERT_SUBREG instruction. + // + // %dst = INSERT_SUBREG %src, %sub, SubIdx + // + // is lowered by TwoAddressInstructionPass to: + // + // %dst = COPY %src + // %dst:SubIdx = COPY %sub + // + // There is no constraint on the %src register class. + // + const TargetRegisterClass *SRC = TLI->getRegClassFor(Node->getValueType(0)); + SRC = TRI->getSubClassWithSubReg(SRC, SubIdx); + assert(SRC && "No register class supports VT and SubIdx for INSERT_SUBREG"); + + if (VRBase == 0 || !SRC->hasSubClassEq(MRI->getRegClass(VRBase))) VRBase = MRI->createVirtualRegister(SRC); - } // Create the insert_subreg or subreg_to_reg machine instruction. MachineInstr *MI = BuildMI(*MF, Node->getDebugLoc(), TII->get(Opc)); MI->addOperand(MachineOperand::CreateReg(VRBase, true)); - + // If creating a subreg_to_reg, then the first input operand // is an implicit value immediate, otherwise it's a register if (Opc == TargetOpcode::SUBREG_TO_REG) { @@ -514,7 +528,7 @@ void InstrEmitter::EmitSubregNode(SDNode *Node, MBB->insert(InsertPos, MI); } else llvm_unreachable("Node is not insert_subreg, extract_subreg, or subreg_to_reg"); - + SDValue Op(Node, 0); bool isNew = VRBaseMap.insert(std::make_pair(Op, VRBase)).second; (void)isNew; // Silence compiler warning. @@ -643,9 +657,9 @@ void InstrEmitter:: EmitMachineNode(SDNode *Node, bool IsClone, bool IsCloned, DenseMap &VRBaseMap) { unsigned Opc = Node->getMachineOpcode(); - + // Handle subreg insert/extract specially - if (Opc == TargetOpcode::EXTRACT_SUBREG || + if (Opc == TargetOpcode::EXTRACT_SUBREG || Opc == TargetOpcode::INSERT_SUBREG || Opc == TargetOpcode::SUBREG_TO_REG) { EmitSubregNode(Node, VRBaseMap, IsClone, IsCloned); @@ -667,7 +681,7 @@ EmitMachineNode(SDNode *Node, bool IsClone, bool IsCloned, if (Opc == TargetOpcode::IMPLICIT_DEF) // We want a unique VR for each IMPLICIT_DEF use. return; - + const MCInstrDesc &II = TII->get(Opc); unsigned NumResults = CountResults(Node); unsigned NodeOperands = CountOperands(Node); @@ -712,12 +726,12 @@ EmitMachineNode(SDNode *Node, bool IsClone, bool IsCloned, // Then mark unused registers as dead. MI->setPhysRegsDeadExcept(UsedRegs, *TRI); } - + // Add result register values for things that are defined by this // instruction. if (NumResults) CreateVirtualRegisters(Node, MI, II, IsClone, IsCloned, VRBaseMap); - + // Emit all of the actual operands of this instruction, adding them to the // instruction as appropriate. bool HasOptPRefs = II.getNumDefs() > NumResults; @@ -751,7 +765,7 @@ EmitMachineNode(SDNode *Node, bool IsClone, bool IsCloned, MI->addRegisterDead(Reg, TRI); } } - + // If the instruction has implicit defs and the node doesn't, mark the // implicit def as dead. If the node has any glue outputs, we don't do this // because we don't know what implicit defs are being used by glued nodes. @@ -761,6 +775,12 @@ EmitMachineNode(SDNode *Node, bool IsClone, bool IsCloned, i != e; ++i) MI->addRegisterDead(IDList[i-II.getNumDefs()], TRI); } + + // Run post-isel target hook to adjust this instruction if needed. +#ifdef NDEBUG + if (II.hasPostISelHook()) +#endif + TLI->AdjustInstrPostInstrSelection(MI, Node); } /// EmitSpecialNode - Generate machine code for a target-independent node and @@ -788,7 +808,7 @@ EmitSpecialNode(SDNode *Node, bool IsClone, bool IsCloned, SrcReg = R->getReg(); else SrcReg = getVR(SrcVal, VRBaseMap); - + unsigned DestReg = cast(Node->getOperand(1))->getReg(); if (SrcReg == DestReg) // Coalesced away the copy? Ignore. break; @@ -808,12 +828,12 @@ EmitSpecialNode(SDNode *Node, bool IsClone, bool IsCloned, TII->get(TargetOpcode::EH_LABEL)).addSym(S); break; } - + case ISD::INLINEASM: { unsigned NumOps = Node->getNumOperands(); if (Node->getOperand(NumOps-1).getValueType() == MVT::Glue) --NumOps; // Ignore the glue operand. - + // Create the inline asm machine instruction. MachineInstr *MI = BuildMI(*MF, Node->getDebugLoc(), TII->get(TargetOpcode::INLINEASM)); @@ -822,7 +842,7 @@ EmitSpecialNode(SDNode *Node, bool IsClone, bool IsCloned, SDValue AsmStrV = Node->getOperand(InlineAsm::Op_AsmString); const char *AsmStr = cast(AsmStrV)->getSymbol(); MI->addOperand(MachineOperand::CreateES(AsmStr)); - + // Add the HasSideEffect and isAlignStack bits. int64_t ExtraInfo = cast(Node->getOperand(InlineAsm::Op_ExtraInfo))-> @@ -834,10 +854,10 @@ EmitSpecialNode(SDNode *Node, bool IsClone, bool IsCloned, unsigned Flags = cast(Node->getOperand(i))->getZExtValue(); unsigned NumVals = InlineAsm::getNumOperandRegisters(Flags); - + MI->addOperand(MachineOperand::CreateImm(Flags)); ++i; // Skip the ID value. - + switch (InlineAsm::getKind(Flags)) { default: llvm_unreachable("Bad flags!"); case InlineAsm::Kind_RegDef: @@ -873,13 +893,13 @@ EmitSpecialNode(SDNode *Node, bool IsClone, bool IsCloned, break; } } - + // Get the mdnode from the asm if it exists and add it to the instruction. SDValue MDV = Node->getOperand(InlineAsm::Op_MDNode); const MDNode *MD = cast(MDV)->getMD(); if (MD) MI->addOperand(MachineOperand::CreateMetadata(MD)); - + MBB->insert(InsertPos, MI); break; } diff --git a/contrib/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.h b/contrib/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.h index 19fc0445b..c081f38be 100644 --- a/contrib/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.h +++ b/contrib/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.h @@ -77,6 +77,12 @@ class InstrEmitter { DenseMap &VRBaseMap, bool IsDebug, bool IsClone, bool IsCloned); + /// ConstrainForSubReg - Try to constrain VReg to a register class that + /// supports SubIdx sub-registers. Emit a copy if that isn't possible. + /// Return the virtual register to use. + unsigned ConstrainForSubReg(unsigned VReg, unsigned SubIdx, + EVT VT, DebugLoc DL); + /// EmitSubregNode - Generate machine code for subreg nodes. /// void EmitSubregNode(SDNode *Node, DenseMap &VRBaseMap, diff --git a/contrib/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/contrib/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index d06e2bdce..63255ae2e 100644 --- a/contrib/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/contrib/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -53,10 +53,15 @@ class SelectionDAGLegalize { // Libcall insertion helpers. - /// LastCALLSEQ - This keeps track of the CALLSEQ_END node that has been + /// LastCALLSEQ_END - This keeps track of the CALLSEQ_END node that has been /// legalized. We use this to ensure that calls are properly serialized /// against each other, including inserted libcalls. - SmallVector LastCALLSEQ; + SDValue LastCALLSEQ_END; + + /// IsLegalizingCall - This member is used *only* for purposes of providing + /// helpful assertions that a libcall isn't created while another call is + /// being legalized (which could lead to non-serialized call sequences). + bool IsLegalizingCall; /// LegalizedNodes - For nodes that are of legal width, and that have more /// than one use, this map indicates what regularized operand to use. This @@ -149,15 +154,6 @@ private: void ExpandNode(SDNode *Node, SmallVectorImpl &Results); void PromoteNode(SDNode *Node, SmallVectorImpl &Results); - - SDValue getLastCALLSEQ() { return LastCALLSEQ.back(); } - void setLastCALLSEQ(const SDValue s) { LastCALLSEQ.back() = s; } - void pushLastCALLSEQ(SDValue s) { - LastCALLSEQ.push_back(s); - } - void popLastCALLSEQ() { - LastCALLSEQ.pop_back(); - } }; } @@ -199,7 +195,8 @@ SelectionDAGLegalize::SelectionDAGLegalize(SelectionDAG &dag) } void SelectionDAGLegalize::LegalizeDAG() { - pushLastCALLSEQ(DAG.getEntryNode()); + LastCALLSEQ_END = DAG.getEntryNode(); + IsLegalizingCall = false; // The legalize process is inherently a bottom-up recursive process (users // legalize their uses before themselves). Given infinite stack space, we @@ -227,15 +224,14 @@ void SelectionDAGLegalize::LegalizeDAG() { /// FindCallEndFromCallStart - Given a chained node that is part of a call /// sequence, find the CALLSEQ_END node that terminates the call sequence. static SDNode *FindCallEndFromCallStart(SDNode *Node, int depth = 0) { - int next_depth = depth; + // Nested CALLSEQ_START/END constructs aren't yet legal, + // but we can DTRT and handle them correctly here. if (Node->getOpcode() == ISD::CALLSEQ_START) - next_depth = depth + 1; - if (Node->getOpcode() == ISD::CALLSEQ_END) { - assert(depth > 0 && "negative depth!"); - if (depth == 1) + depth++; + else if (Node->getOpcode() == ISD::CALLSEQ_END) { + depth--; + if (depth == 0) return Node; - else - next_depth = depth - 1; } if (Node->use_empty()) return 0; // No CallSeqEnd @@ -266,7 +262,7 @@ static SDNode *FindCallEndFromCallStart(SDNode *Node, int depth = 0) { SDNode *User = *UI; for (unsigned i = 0, e = User->getNumOperands(); i != e; ++i) if (User->getOperand(i) == TheChain) - if (SDNode *Result = FindCallEndFromCallStart(User, next_depth)) + if (SDNode *Result = FindCallEndFromCallStart(User, depth)) return Result; } return 0; @@ -287,7 +283,6 @@ static SDNode *FindCallStartFromCallEnd(SDNode *Node) { case ISD::CALLSEQ_START: if (!nested) return Node; - Node = Node->getOperand(0).getNode(); nested--; break; case ISD::CALLSEQ_END: @@ -295,7 +290,7 @@ static SDNode *FindCallStartFromCallEnd(SDNode *Node) { break; } } - return (Node->getOpcode() == ISD::CALLSEQ_START) ? Node : 0; + return 0; } /// LegalizeAllNodesNotLeadingTo - Recursively walk the uses of N, looking to @@ -365,7 +360,7 @@ static SDValue ExpandConstantFP(ConstantFPSDNode *CFP, bool UseCP, // smaller type. TLI.isLoadExtLegal(ISD::EXTLOAD, SVT) && TLI.ShouldShrinkFPConstant(OrigVT)) { - const Type *SType = SVT.getTypeForEVT(*DAG.getContext()); + Type *SType = SVT.getTypeForEVT(*DAG.getContext()); LLVMC = cast(ConstantExpr::getFPTrunc(LLVMC, SType)); VT = SVT; Extend = true; @@ -819,6 +814,11 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { Action = TLI.getOperationAction(Node->getOpcode(), InnerType); break; } + case ISD::ATOMIC_STORE: { + Action = TLI.getOperationAction(Node->getOpcode(), + Node->getOperand(2).getValueType()); + break; + } case ISD::SELECT_CC: case ISD::SETCC: case ISD::BR_CC: { @@ -872,7 +872,8 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { if (Action == TargetLowering::Legal) Action = TargetLowering::Expand; break; - case ISD::TRAMPOLINE: + case ISD::INIT_TRAMPOLINE: + case ISD::ADJUST_TRAMPOLINE: case ISD::FRAMEADDR: case ISD::RETURNADDR: // These operations lie about being legal: when they claim to be legal, @@ -912,12 +913,11 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { case ISD::BR_JT: case ISD::BR_CC: case ISD::BRCOND: - assert(LastCALLSEQ.size() == 1 && "branch inside CALLSEQ_BEGIN/END?"); - // Branches tweak the chain to include LastCALLSEQ + // Branches tweak the chain to include LastCALLSEQ_END Ops[0] = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Ops[0], - getLastCALLSEQ()); + LastCALLSEQ_END); Ops[0] = LegalizeOp(Ops[0]); - setLastCALLSEQ(DAG.getEntryNode()); + LastCALLSEQ_END = DAG.getEntryNode(); break; case ISD::SHL: case ISD::SRL: @@ -989,6 +989,31 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { #endif assert(0 && "Do not know how to legalize this operator!"); + case ISD::SRA: + case ISD::SRL: + case ISD::SHL: { + // Scalarize vector SRA/SRL/SHL. + EVT VT = Node->getValueType(0); + assert(VT.isVector() && "Unable to legalize non-vector shift"); + assert(TLI.isTypeLegal(VT.getScalarType())&& "Element type must be legal"); + unsigned NumElem = VT.getVectorNumElements(); + + SmallVector Scalars; + for (unsigned Idx = 0; Idx < NumElem; Idx++) { + SDValue Ex = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, + VT.getScalarType(), + Node->getOperand(0), DAG.getIntPtrConstant(Idx)); + SDValue Sh = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, + VT.getScalarType(), + Node->getOperand(1), DAG.getIntPtrConstant(Idx)); + Scalars.push_back(DAG.getNode(Node->getOpcode(), dl, + VT.getScalarType(), Ex, Sh)); + } + Result = DAG.getNode(ISD::BUILD_VECTOR, dl, Node->getValueType(0), + &Scalars[0], Scalars.size()); + break; + } + case ISD::BUILD_VECTOR: switch (TLI.getOperationAction(ISD::BUILD_VECTOR, Node->getValueType(0))) { default: assert(0 && "This action is not supported yet!"); @@ -1006,7 +1031,6 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { break; case ISD::CALLSEQ_START: { SDNode *CallEnd = FindCallEndFromCallStart(Node); - assert(CallEnd && "didn't find CALLSEQ_END!"); // Recursively Legalize all of the inputs of the call end that do not lead // to this call start. This ensures that any libcalls that need be inserted @@ -1023,9 +1047,9 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { // Merge in the last call to ensure that this call starts after the last // call ended. - if (getLastCALLSEQ().getOpcode() != ISD::EntryToken) { + if (LastCALLSEQ_END.getOpcode() != ISD::EntryToken) { Tmp1 = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, - Tmp1, getLastCALLSEQ()); + Tmp1, LastCALLSEQ_END); Tmp1 = LegalizeOp(Tmp1); } @@ -1046,29 +1070,25 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { // sequence have been legalized, legalize the call itself. During this // process, no libcalls can/will be inserted, guaranteeing that no calls // can overlap. + assert(!IsLegalizingCall && "Inconsistent sequentialization of calls!"); // Note that we are selecting this call! - setLastCALLSEQ(SDValue(CallEnd, 0)); + LastCALLSEQ_END = SDValue(CallEnd, 0); + IsLegalizingCall = true; // Legalize the call, starting from the CALLSEQ_END. - LegalizeOp(getLastCALLSEQ()); + LegalizeOp(LastCALLSEQ_END); + assert(!IsLegalizingCall && "CALLSEQ_END should have cleared this!"); return Result; } case ISD::CALLSEQ_END: - { - SDNode *myCALLSEQ_BEGIN = FindCallStartFromCallEnd(Node); - - // If the CALLSEQ_START node hasn't been legalized first, legalize it. - // This will cause this node to be legalized as well as handling libcalls - // right. - if (getLastCALLSEQ().getNode() != Node) { - LegalizeOp(SDValue(myCALLSEQ_BEGIN, 0)); - DenseMap::iterator I = LegalizedNodes.find(Op); - assert(I != LegalizedNodes.end() && - "Legalizing the call start should have legalized this node!"); - return I->second; - } - - pushLastCALLSEQ(SDValue(myCALLSEQ_BEGIN, 0)); + // If the CALLSEQ_START node hasn't been legalized first, legalize it. This + // will cause this node to be legalized as well as handling libcalls right. + if (LastCALLSEQ_END.getNode() != Node) { + LegalizeOp(SDValue(FindCallStartFromCallEnd(Node), 0)); + DenseMap::iterator I = LegalizedNodes.find(Op); + assert(I != LegalizedNodes.end() && + "Legalizing the call start should have legalized this node!"); + return I->second; } // Otherwise, the call start has been legalized and everything is going @@ -1096,8 +1116,9 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { Result.getResNo()); } } + assert(IsLegalizingCall && "Call sequence imbalance between start/end?"); // This finishes up call legalization. - popLastCALLSEQ(); + IsLegalizingCall = false; // If the CALLSEQ_END node has a flag, remember that we legalized it. AddLegalizedOperand(SDValue(Node, 0), Result.getValue(0)); @@ -1124,7 +1145,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { // If this is an unaligned load and the target doesn't support it, // expand it. if (!TLI.allowsUnalignedMemoryAccesses(LD->getMemoryVT())) { - const Type *Ty = LD->getMemoryVT().getTypeForEVT(*DAG.getContext()); + Type *Ty = LD->getMemoryVT().getTypeForEVT(*DAG.getContext()); unsigned ABIAlignment = TLI.getTargetData()->getABITypeAlignment(Ty); if (LD->getAlignment() < ABIAlignment){ Result = ExpandUnalignedLoad(cast(Result.getNode()), @@ -1311,7 +1332,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { // If this is an unaligned load and the target doesn't support it, // expand it. if (!TLI.allowsUnalignedMemoryAccesses(LD->getMemoryVT())) { - const Type *Ty = + Type *Ty = LD->getMemoryVT().getTypeForEVT(*DAG.getContext()); unsigned ABIAlignment = TLI.getTargetData()->getABITypeAlignment(Ty); @@ -1491,7 +1512,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { // If this is an unaligned store and the target doesn't support it, // expand it. if (!TLI.allowsUnalignedMemoryAccesses(ST->getMemoryVT())) { - const Type *Ty = ST->getMemoryVT().getTypeForEVT(*DAG.getContext()); + Type *Ty = ST->getMemoryVT().getTypeForEVT(*DAG.getContext()); unsigned ABIAlignment= TLI.getTargetData()->getABITypeAlignment(Ty); if (ST->getAlignment() < ABIAlignment) Result = ExpandUnalignedStore(cast(Result.getNode()), @@ -1596,7 +1617,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { // If this is an unaligned store and the target doesn't support it, // expand it. if (!TLI.allowsUnalignedMemoryAccesses(ST->getMemoryVT())) { - const Type *Ty = ST->getMemoryVT().getTypeForEVT(*DAG.getContext()); + Type *Ty = ST->getMemoryVT().getTypeForEVT(*DAG.getContext()); unsigned ABIAlignment= TLI.getTargetData()->getABITypeAlignment(Ty); if (ST->getAlignment() < ABIAlignment) Result = ExpandUnalignedStore(cast(Result.getNode()), @@ -1611,82 +1632,101 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { EVT WideScalarVT = Tmp3.getValueType().getScalarType(); EVT NarrowScalarVT = StVT.getScalarType(); - // The Store type is illegal, must scalarize the vector store. - SmallVector Stores; - bool ScalarLegal = TLI.isTypeLegal(WideScalarVT); - if (!TLI.isTypeLegal(StVT) && StVT.isVector() && ScalarLegal) { + if (StVT.isVector()) { unsigned NumElem = StVT.getVectorNumElements(); + // The type of the data we want to save + EVT RegVT = Tmp3.getValueType(); + EVT RegSclVT = RegVT.getScalarType(); + // The type of data as saved in memory. + EVT MemSclVT = StVT.getScalarType(); + + bool RegScalarLegal = TLI.isTypeLegal(RegSclVT); + bool MemScalarLegal = TLI.isTypeLegal(MemSclVT); + + // We need to expand this store. If the register element type + // is legal then we can scalarize the vector and use + // truncating stores. + if (RegScalarLegal) { + // Cast floats into integers + unsigned ScalarSize = MemSclVT.getSizeInBits(); + EVT EltVT = EVT::getIntegerVT(*DAG.getContext(), ScalarSize); + + // Round odd types to the next pow of two. + if (!isPowerOf2_32(ScalarSize)) + ScalarSize = NextPowerOf2(ScalarSize); + + // Store Stride in bytes + unsigned Stride = ScalarSize/8; + // Extract each of the elements from the original vector + // and save them into memory individually. + SmallVector Stores; + for (unsigned Idx = 0; Idx < NumElem; Idx++) { + SDValue Ex = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, + RegSclVT, Tmp3, DAG.getIntPtrConstant(Idx)); + + Tmp2 = DAG.getNode(ISD::ADD, dl, Tmp2.getValueType(), Tmp2, + DAG.getIntPtrConstant(Stride)); + + // This scalar TruncStore may be illegal, but we lehalize it + // later. + SDValue Store = DAG.getTruncStore(Tmp1, dl, Ex, Tmp2, + ST->getPointerInfo().getWithOffset(Idx*Stride), MemSclVT, + isVolatile, isNonTemporal, Alignment); - unsigned ScalarSize = StVT.getScalarType().getSizeInBits(); - // Round odd types to the next pow of two. - if (!isPowerOf2_32(ScalarSize)) - ScalarSize = NextPowerOf2(ScalarSize); - // Types smaller than 8 bits are promoted to 8 bits. - ScalarSize = std::max(ScalarSize, 8); - // Store stride - unsigned Stride = ScalarSize/8; - assert(isPowerOf2_32(Stride) && "Stride must be a power of two"); - - for (unsigned Idx=0; IdxgetPointerInfo().getWithOffset(Idx*Stride), - isVolatile, isNonTemporal, Alignment); - Stores.push_back(Store); + Result = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, + &Stores[0], Stores.size()); + break; } - Result = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, - &Stores[0], Stores.size()); - break; - } - // The Store type is illegal, must scalarize the vector store. - // However, the scalar type is illegal. Must bitcast the result - // and store it in smaller parts. - if (!TLI.isTypeLegal(StVT) && StVT.isVector()) { - unsigned WideNumElem = StVT.getVectorNumElements(); - unsigned Stride = NarrowScalarVT.getSizeInBits()/8; - - unsigned SizeRatio = - (WideScalarVT.getSizeInBits() / NarrowScalarVT.getSizeInBits()); - - EVT CastValueVT = EVT::getVectorVT(*DAG.getContext(), NarrowScalarVT, - SizeRatio*WideNumElem); - - // Cast the wide elem vector to wider vec with smaller elem type. - // Example <2 x i64> -> <4 x i32> - Tmp3 = DAG.getNode(ISD::BITCAST, dl, CastValueVT, Tmp3); - - for (unsigned Idx=0; IdxgetPointerInfo().getWithOffset(Idx*Stride), - isVolatile, isNonTemporal, Alignment); - Stores.push_back(Store); + // The scalar register type is illegal. + // For example saving <2 x i64> -> <2 x i32> on a x86. + // In here we bitcast the value into a vector of smaller parts and + // save it using smaller scalars. + if (!RegScalarLegal && MemScalarLegal) { + // Store Stride in bytes + unsigned Stride = MemSclVT.getSizeInBits()/8; + + unsigned SizeRatio = + (RegSclVT.getSizeInBits() / MemSclVT.getSizeInBits()); + + EVT CastValueVT = EVT::getVectorVT(*DAG.getContext(), + MemSclVT, + SizeRatio * NumElem); + + // Cast the wide elem vector to wider vec with smaller elem type. + // Example <2 x i64> -> <4 x i32> + Tmp3 = DAG.getNode(ISD::BITCAST, dl, CastValueVT, Tmp3); + + SmallVector Stores; + for (unsigned Idx=0; Idx < NumElem * SizeRatio; Idx++) { + // Extract the Ith element. + SDValue Ex = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, + NarrowScalarVT, Tmp3, DAG.getIntPtrConstant(Idx)); + // Bump pointer. + Tmp2 = DAG.getNode(ISD::ADD, dl, Tmp2.getValueType(), Tmp2, + DAG.getIntPtrConstant(Stride)); + + // Store if, this element is: + // - First element on big endian, or + // - Last element on little endian + if (( TLI.isBigEndian() && (Idx % SizeRatio == 0)) || + ((!TLI.isBigEndian() && (Idx % SizeRatio == SizeRatio-1)))) { + SDValue Store = DAG.getStore(Tmp1, dl, Ex, Tmp2, + ST->getPointerInfo().getWithOffset(Idx*Stride), + isVolatile, isNonTemporal, Alignment); + Stores.push_back(Store); + } } + Result = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, + &Stores[0], Stores.size()); + break; } - Result = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, - &Stores[0], Stores.size()); - break; - } + + assert(false && "Unable to legalize the vector trunc store!"); + }// is vector // TRUNCSTORE:i16 i32 -> STORE i16 @@ -1999,7 +2039,7 @@ SDValue SelectionDAGLegalize::EmitStackConvert(SDValue SrcOp, unsigned SrcSize = SrcOp.getValueType().getSizeInBits(); unsigned SlotSize = SlotVT.getSizeInBits(); unsigned DestSize = DestVT.getSizeInBits(); - const Type *DestType = DestVT.getTypeForEVT(*DAG.getContext()); + Type *DestType = DestVT.getTypeForEVT(*DAG.getContext()); unsigned DestAlign = TLI.getTargetData()->getPrefTypeAlignment(DestType); // Emit a store to the stack slot. Use a truncstore if the input value is @@ -2106,7 +2146,7 @@ SDValue SelectionDAGLegalize::ExpandBUILD_VECTOR(SDNode *Node) { } } else { assert(Node->getOperand(i).getOpcode() == ISD::UNDEF); - const Type *OpNTy = EltVT.getTypeForEVT(*DAG.getContext()); + Type *OpNTy = EltVT.getTypeForEVT(*DAG.getContext()); CV.push_back(UndefValue::get(OpNTy)); } } @@ -2150,6 +2190,7 @@ SDValue SelectionDAGLegalize::ExpandBUILD_VECTOR(SDNode *Node) { // and leave the Hi part unset. SDValue SelectionDAGLegalize::ExpandLibCall(RTLIB::Libcall LC, SDNode *Node, bool isSigned) { + assert(!IsLegalizingCall && "Cannot overlap legalization of calls!"); // The input chain to this libcall is the entry node of the function. // Legalizing the call will automatically add the previous call to the // dependence. @@ -2159,7 +2200,7 @@ SDValue SelectionDAGLegalize::ExpandLibCall(RTLIB::Libcall LC, SDNode *Node, TargetLowering::ArgListEntry Entry; for (unsigned i = 0, e = Node->getNumOperands(); i != e; ++i) { EVT ArgVT = Node->getOperand(i).getValueType(); - const Type *ArgTy = ArgVT.getTypeForEVT(*DAG.getContext()); + Type *ArgTy = ArgVT.getTypeForEVT(*DAG.getContext()); Entry.Node = Node->getOperand(i); Entry.Ty = ArgTy; Entry.isSExt = isSigned; Entry.isZExt = !isSigned; @@ -2169,7 +2210,7 @@ SDValue SelectionDAGLegalize::ExpandLibCall(RTLIB::Libcall LC, SDNode *Node, TLI.getPointerTy()); // Splice the libcall in wherever FindInputOutputChains tells us to. - const Type *RetTy = Node->getValueType(0).getTypeForEVT(*DAG.getContext()); + Type *RetTy = Node->getValueType(0).getTypeForEVT(*DAG.getContext()); // isTailCall may be true since the callee does not reference caller stack // frame. Check if it's in the right position. @@ -2185,7 +2226,7 @@ SDValue SelectionDAGLegalize::ExpandLibCall(RTLIB::Libcall LC, SDNode *Node, return DAG.getRoot(); // Legalize the call sequence, starting with the chain. This will advance - // the LastCALLSEQ to the legalized version of the CALLSEQ_END node that + // the LastCALLSEQ_END to the legalized version of the CALLSEQ_END node that // was added by LowerCallTo (guaranteeing proper serialization of calls). LegalizeOp(CallInfo.second); return CallInfo.first; @@ -2210,7 +2251,7 @@ SDValue SelectionDAGLegalize::ExpandLibCall(RTLIB::Libcall LC, EVT RetVT, SDValue Callee = DAG.getExternalSymbol(TLI.getLibcallName(LC), TLI.getPointerTy()); - const Type *RetTy = RetVT.getTypeForEVT(*DAG.getContext()); + Type *RetTy = RetVT.getTypeForEVT(*DAG.getContext()); std::pair CallInfo = TLI.LowerCallTo(DAG.getEntryNode(), RetTy, isSigned, !isSigned, false, false, 0, TLI.getLibcallCallingConv(LC), false, @@ -2231,13 +2272,14 @@ std::pair SelectionDAGLegalize::ExpandChainLibCall(RTLIB::Libcall LC, SDNode *Node, bool isSigned) { + assert(!IsLegalizingCall && "Cannot overlap legalization of calls!"); SDValue InChain = Node->getOperand(0); TargetLowering::ArgListTy Args; TargetLowering::ArgListEntry Entry; for (unsigned i = 1, e = Node->getNumOperands(); i != e; ++i) { EVT ArgVT = Node->getOperand(i).getValueType(); - const Type *ArgTy = ArgVT.getTypeForEVT(*DAG.getContext()); + Type *ArgTy = ArgVT.getTypeForEVT(*DAG.getContext()); Entry.Node = Node->getOperand(i); Entry.Ty = ArgTy; Entry.isSExt = isSigned; @@ -2248,7 +2290,7 @@ SelectionDAGLegalize::ExpandChainLibCall(RTLIB::Libcall LC, TLI.getPointerTy()); // Splice the libcall in wherever FindInputOutputChains tells us to. - const Type *RetTy = Node->getValueType(0).getTypeForEVT(*DAG.getContext()); + Type *RetTy = Node->getValueType(0).getTypeForEVT(*DAG.getContext()); std::pair CallInfo = TLI.LowerCallTo(InChain, RetTy, isSigned, !isSigned, false, false, 0, TLI.getLibcallCallingConv(LC), /*isTailCall=*/false, @@ -2256,7 +2298,7 @@ SelectionDAGLegalize::ExpandChainLibCall(RTLIB::Libcall LC, Callee, Args, DAG, Node->getDebugLoc()); // Legalize the call sequence, starting with the chain. This will advance - // the LastCALLSEQ to the legalized version of the CALLSEQ_END node that + // the LastCALLSEQ_END to the legalized version of the CALLSEQ_END node that // was added by LowerCallTo (guaranteeing proper serialization of calls). LegalizeOp(CallInfo.second); return CallInfo; @@ -2360,13 +2402,13 @@ SelectionDAGLegalize::ExpandDivRemLibCall(SDNode *Node, SDValue InChain = DAG.getEntryNode(); EVT RetVT = Node->getValueType(0); - const Type *RetTy = RetVT.getTypeForEVT(*DAG.getContext()); + Type *RetTy = RetVT.getTypeForEVT(*DAG.getContext()); TargetLowering::ArgListTy Args; TargetLowering::ArgListEntry Entry; for (unsigned i = 0, e = Node->getNumOperands(); i != e; ++i) { EVT ArgVT = Node->getOperand(i).getValueType(); - const Type *ArgTy = ArgVT.getTypeForEVT(*DAG.getContext()); + Type *ArgTy = ArgVT.getTypeForEVT(*DAG.getContext()); Entry.Node = Node->getOperand(i); Entry.Ty = ArgTy; Entry.isSExt = isSigned; Entry.isZExt = !isSigned; @@ -2397,7 +2439,7 @@ SelectionDAGLegalize::ExpandDivRemLibCall(SDNode *Node, LegalizeOp(CallInfo.second); // Remainder is loaded back from the stack frame. - SDValue Rem = DAG.getLoad(RetVT, dl, getLastCALLSEQ(), FIPtr, + SDValue Rem = DAG.getLoad(RetVT, dl, LastCALLSEQ_END, FIPtr, MachinePointerInfo(), false, false, 0); Results.push_back(CallInfo.first); Results.push_back(Rem); @@ -2955,8 +2997,10 @@ void SelectionDAGLegalize::ExpandNode(SDNode *Node, Results.push_back(DAG.getConstant(0, MVT::i32)); Results.push_back(Node->getOperand(0)); break; + case ISD::ATOMIC_FENCE: case ISD::MEMBARRIER: { // If the target didn't lower this, lower it to '__sync_synchronize()' call + // FIXME: handle "fence singlethread" more efficiently. TargetLowering::ArgListTy Args; std::pair CallResult = TLI.LowerCallTo(Node->getOperand(0), Type::getVoidTy(*DAG.getContext()), @@ -2969,6 +3013,32 @@ void SelectionDAGLegalize::ExpandNode(SDNode *Node, Results.push_back(CallResult.second); break; } + case ISD::ATOMIC_LOAD: { + // There is no libcall for atomic load; fake it with ATOMIC_CMP_SWAP. + SDValue Zero = DAG.getConstant(0, Node->getValueType(0)); + SDValue Swap = DAG.getAtomic(ISD::ATOMIC_CMP_SWAP, dl, + cast(Node)->getMemoryVT(), + Node->getOperand(0), + Node->getOperand(1), Zero, Zero, + cast(Node)->getMemOperand(), + cast(Node)->getOrdering(), + cast(Node)->getSynchScope()); + Results.push_back(Swap.getValue(0)); + Results.push_back(Swap.getValue(1)); + break; + } + case ISD::ATOMIC_STORE: { + // There is no libcall for atomic store; fake it with ATOMIC_SWAP. + SDValue Swap = DAG.getAtomic(ISD::ATOMIC_SWAP, dl, + cast(Node)->getMemoryVT(), + Node->getOperand(0), + Node->getOperand(1), Node->getOperand(2), + cast(Node)->getMemOperand(), + cast(Node)->getOrdering(), + cast(Node)->getSynchScope()); + Results.push_back(Swap.getValue(1)); + break; + } // By default, atomic intrinsics are marked Legal and lowered. Targets // which don't support them directly, however, may want libcalls, in which // case they mark them Expand, and we get here. @@ -3727,8 +3797,7 @@ void SelectionDAGLegalize::ExpandNode(SDNode *Node, LegalizeSetCCCondCode(TLI.getSetCCResultType(Tmp2.getValueType()), Tmp2, Tmp3, Tmp4, dl); - assert(LastCALLSEQ.size() == 1 && "branch inside CALLSEQ_BEGIN/END?"); - setLastCALLSEQ(DAG.getEntryNode()); + LastCALLSEQ_END = DAG.getEntryNode(); assert(!Tmp3.getNode() && "Can't legalize BR_CC with legal condition!"); Tmp3 = DAG.getConstant(0, Tmp2.getValueType()); diff --git a/contrib/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp b/contrib/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp index e6835d87f..7c1cc69d6 100644 --- a/contrib/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp +++ b/contrib/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp @@ -55,6 +55,7 @@ void DAGTypeLegalizer::SoftenFloatResult(SDNode *N, unsigned ResNo) { #endif llvm_unreachable("Do not know how to soften the result of this operator!"); + case ISD::MERGE_VALUES:R = SoftenFloatRes_MERGE_VALUES(N, ResNo); break; case ISD::BITCAST: R = SoftenFloatRes_BITCAST(N); break; case ISD::BUILD_PAIR: R = SoftenFloatRes_BUILD_PAIR(N); break; case ISD::ConstantFP: @@ -107,6 +108,12 @@ SDValue DAGTypeLegalizer::SoftenFloatRes_BITCAST(SDNode *N) { return BitConvertToInteger(N->getOperand(0)); } +SDValue DAGTypeLegalizer::SoftenFloatRes_MERGE_VALUES(SDNode *N, + unsigned ResNo) { + SDValue Op = DisintegrateMERGE_VALUES(N, ResNo); + return BitConvertToInteger(Op); +} + SDValue DAGTypeLegalizer::SoftenFloatRes_BUILD_PAIR(SDNode *N) { // Convert the inputs to integers, and build a new pair out of them. return DAG.getNode(ISD::BUILD_PAIR, N->getDebugLoc(), @@ -827,11 +834,11 @@ void DAGTypeLegalizer::ExpandFloatResult(SDNode *N, unsigned ResNo) { #endif llvm_unreachable("Do not know how to expand the result of this operator!"); - case ISD::MERGE_VALUES: SplitRes_MERGE_VALUES(N, Lo, Hi); break; case ISD::UNDEF: SplitRes_UNDEF(N, Lo, Hi); break; case ISD::SELECT: SplitRes_SELECT(N, Lo, Hi); break; case ISD::SELECT_CC: SplitRes_SELECT_CC(N, Lo, Hi); break; + case ISD::MERGE_VALUES: ExpandRes_MERGE_VALUES(N, ResNo, Lo, Hi); break; case ISD::BITCAST: ExpandRes_BITCAST(N, Lo, Hi); break; case ISD::BUILD_PAIR: ExpandRes_BUILD_PAIR(N, Lo, Hi); break; case ISD::EXTRACT_ELEMENT: ExpandRes_EXTRACT_ELEMENT(N, Lo, Hi); break; @@ -879,10 +886,10 @@ void DAGTypeLegalizer::ExpandFloatRes_ConstantFP(SDNode *N, SDValue &Lo, assert(NVT.getSizeInBits() == integerPartWidth && "Do not know how to expand this float constant!"); APInt C = cast(N)->getValueAPF().bitcastToAPInt(); - Lo = DAG.getConstantFP(APFloat(APInt(integerPartWidth, 1, - &C.getRawData()[1])), NVT); - Hi = DAG.getConstantFP(APFloat(APInt(integerPartWidth, 1, - &C.getRawData()[0])), NVT); + Lo = DAG.getConstantFP(APFloat(APInt(integerPartWidth, C.getRawData()[1])), + NVT); + Hi = DAG.getConstantFP(APFloat(APInt(integerPartWidth, C.getRawData()[0])), + NVT); } void DAGTypeLegalizer::ExpandFloatRes_FABS(SDNode *N, SDValue &Lo, @@ -1201,7 +1208,7 @@ void DAGTypeLegalizer::ExpandFloatRes_XINT_TO_FP(SDNode *N, SDValue &Lo, static const uint64_t TwoE32[] = { 0x41f0000000000000LL, 0 }; static const uint64_t TwoE64[] = { 0x43f0000000000000LL, 0 }; static const uint64_t TwoE128[] = { 0x47f0000000000000LL, 0 }; - const uint64_t *Parts = 0; + ArrayRef Parts; switch (SrcVT.getSimpleVT().SimpleTy) { default: @@ -1218,7 +1225,7 @@ void DAGTypeLegalizer::ExpandFloatRes_XINT_TO_FP(SDNode *N, SDValue &Lo, } Lo = DAG.getNode(ISD::FADD, dl, VT, Hi, - DAG.getConstantFP(APFloat(APInt(128, 2, Parts)), + DAG.getConstantFP(APFloat(APInt(128, Parts)), MVT::ppcf128)); Lo = DAG.getNode(ISD::SELECT_CC, dl, VT, Src, DAG.getConstant(0, SrcVT), Lo, Hi, DAG.getCondCode(ISD::SETLT)); @@ -1291,8 +1298,7 @@ void DAGTypeLegalizer::FloatExpandSetCCOperands(SDValue &NewLHS, GetExpandedFloat(NewLHS, LHSLo, LHSHi); GetExpandedFloat(NewRHS, RHSLo, RHSHi); - EVT VT = NewLHS.getValueType(); - assert(VT == MVT::ppcf128 && "Unsupported setcc type!"); + assert(NewLHS.getValueType() == MVT::ppcf128 && "Unsupported setcc type!"); // FIXME: This generated code sucks. We want to generate // FCMPU crN, hi1, hi2 @@ -1373,7 +1379,7 @@ SDValue DAGTypeLegalizer::ExpandFloatOp_FP_TO_UINT(SDNode *N) { assert(N->getOperand(0).getValueType() == MVT::ppcf128 && "Logic only correct for ppcf128!"); const uint64_t TwoE31[] = {0x41e0000000000000LL, 0}; - APFloat APF = APFloat(APInt(128, 2, TwoE31)); + APFloat APF = APFloat(APInt(128, TwoE31)); SDValue Tmp = DAG.getConstantFP(APF, MVT::ppcf128); // X>=2^31 ? (int)(X-2^31)+0x80000000 : (int)X // FIXME: generated code sucks. @@ -1445,6 +1451,7 @@ SDValue DAGTypeLegalizer::ExpandFloatOp_STORE(SDNode *N, unsigned OpNo) { ST->getValue().getValueType()); assert(NVT.isByteSized() && "Expanded type not byte sized!"); assert(ST->getMemoryVT().bitsLE(NVT) && "Float type not round?"); + (void)NVT; SDValue Lo, Hi; GetExpandedOp(ST->getValue(), Lo, Hi); diff --git a/contrib/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp b/contrib/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp index e7c77dd10..a5c4c2ded 100644 --- a/contrib/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp +++ b/contrib/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp @@ -48,6 +48,7 @@ void DAGTypeLegalizer::PromoteIntegerResult(SDNode *N, unsigned ResNo) { N->dump(&DAG); dbgs() << "\n"; #endif llvm_unreachable("Do not know how to promote this operator!"); + case ISD::MERGE_VALUES:Res = PromoteIntRes_MERGE_VALUES(N, ResNo); break; case ISD::AssertSext: Res = PromoteIntRes_AssertSext(N); break; case ISD::AssertZext: Res = PromoteIntRes_AssertZext(N); break; case ISD::BITCAST: Res = PromoteIntRes_BITCAST(N); break; @@ -63,6 +64,7 @@ void DAGTypeLegalizer::PromoteIntegerResult(SDNode *N, unsigned ResNo) { Res = PromoteIntRes_EXTRACT_VECTOR_ELT(N); break; case ISD::LOAD: Res = PromoteIntRes_LOAD(cast(N));break; case ISD::SELECT: Res = PromoteIntRes_SELECT(N); break; + case ISD::VSELECT: Res = PromoteIntRes_VSELECT(N); break; case ISD::SELECT_CC: Res = PromoteIntRes_SELECT_CC(N); break; case ISD::SETCC: Res = PromoteIntRes_SETCC(N); break; case ISD::SHL: Res = PromoteIntRes_SHL(N); break; @@ -84,6 +86,8 @@ void DAGTypeLegalizer::PromoteIntegerResult(SDNode *N, unsigned ResNo) { Res = PromoteIntRes_BUILD_VECTOR(N); break; case ISD::SCALAR_TO_VECTOR: Res = PromoteIntRes_SCALAR_TO_VECTOR(N); break; + case ISD::CONCAT_VECTORS: + Res = PromoteIntRes_CONCAT_VECTORS(N); break; case ISD::SIGN_EXTEND: case ISD::ZERO_EXTEND: @@ -114,6 +118,9 @@ void DAGTypeLegalizer::PromoteIntegerResult(SDNode *N, unsigned ResNo) { case ISD::SMULO: case ISD::UMULO: Res = PromoteIntRes_XMULO(N, ResNo); break; + case ISD::ATOMIC_LOAD: + Res = PromoteIntRes_Atomic0(cast(N)); break; + case ISD::ATOMIC_LOAD_ADD: case ISD::ATOMIC_LOAD_SUB: case ISD::ATOMIC_LOAD_AND: @@ -136,6 +143,12 @@ void DAGTypeLegalizer::PromoteIntegerResult(SDNode *N, unsigned ResNo) { SetPromotedInteger(SDValue(N, ResNo), Res); } +SDValue DAGTypeLegalizer::PromoteIntRes_MERGE_VALUES(SDNode *N, + unsigned ResNo) { + SDValue Op = DisintegrateMERGE_VALUES(N, ResNo); + return GetPromotedInteger(Op); +} + SDValue DAGTypeLegalizer::PromoteIntRes_AssertSext(SDNode *N) { // Sign-extend the new bits, and continue the assertion. SDValue Op = SExtPromotedInteger(N->getOperand(0)); @@ -150,12 +163,26 @@ SDValue DAGTypeLegalizer::PromoteIntRes_AssertZext(SDNode *N) { Op.getValueType(), Op, N->getOperand(1)); } +SDValue DAGTypeLegalizer::PromoteIntRes_Atomic0(AtomicSDNode *N) { + EVT ResVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + SDValue Res = DAG.getAtomic(N->getOpcode(), N->getDebugLoc(), + N->getMemoryVT(), ResVT, + N->getChain(), N->getBasePtr(), + N->getMemOperand(), N->getOrdering(), + N->getSynchScope()); + // Legalized the chain result - switch anything that used the old chain to + // use the new one. + ReplaceValueWith(SDValue(N, 1), Res.getValue(1)); + return Res; +} + SDValue DAGTypeLegalizer::PromoteIntRes_Atomic1(AtomicSDNode *N) { SDValue Op2 = GetPromotedInteger(N->getOperand(2)); SDValue Res = DAG.getAtomic(N->getOpcode(), N->getDebugLoc(), N->getMemoryVT(), N->getChain(), N->getBasePtr(), - Op2, N->getMemOperand()); + Op2, N->getMemOperand(), N->getOrdering(), + N->getSynchScope()); // Legalized the chain result - switch anything that used the old chain to // use the new one. ReplaceValueWith(SDValue(N, 1), Res.getValue(1)); @@ -167,7 +194,8 @@ SDValue DAGTypeLegalizer::PromoteIntRes_Atomic2(AtomicSDNode *N) { SDValue Op3 = GetPromotedInteger(N->getOperand(3)); SDValue Res = DAG.getAtomic(N->getOpcode(), N->getDebugLoc(), N->getMemoryVT(), N->getChain(), N->getBasePtr(), - Op2, Op3, N->getMemOperand()); + Op2, Op3, N->getMemOperand(), N->getOrdering(), + N->getSynchScope()); // Legalized the chain result - switch anything that used the old chain to // use the new one. ReplaceValueWith(SDValue(N, 1), Res.getValue(1)); @@ -457,6 +485,14 @@ SDValue DAGTypeLegalizer::PromoteIntRes_SELECT(SDNode *N) { LHS.getValueType(), N->getOperand(0),LHS,RHS); } +SDValue DAGTypeLegalizer::PromoteIntRes_VSELECT(SDNode *N) { + SDValue Mask = GetPromotedInteger(N->getOperand(0)); + SDValue LHS = GetPromotedInteger(N->getOperand(1)); + SDValue RHS = GetPromotedInteger(N->getOperand(2)); + return DAG.getNode(ISD::VSELECT, N->getDebugLoc(), + LHS.getValueType(), Mask, LHS, RHS); +} + SDValue DAGTypeLegalizer::PromoteIntRes_SELECT_CC(SDNode *N) { SDValue LHS = GetPromotedInteger(N->getOperand(2)); SDValue RHS = GetPromotedInteger(N->getOperand(3)); @@ -467,16 +503,24 @@ SDValue DAGTypeLegalizer::PromoteIntRes_SELECT_CC(SDNode *N) { SDValue DAGTypeLegalizer::PromoteIntRes_SETCC(SDNode *N) { EVT SVT = TLI.getSetCCResultType(N->getOperand(0).getValueType()); - assert(isTypeLegal(SVT) && "Illegal SetCC type!"); + + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + + // Only use the result of getSetCCResultType if it is legal, + // otherwise just use the promoted result type (NVT). + if (!TLI.isTypeLegal(SVT)) + SVT = NVT; + DebugLoc dl = N->getDebugLoc(); + assert(SVT.isVector() == N->getOperand(0).getValueType().isVector() && + "Vector compare must return a vector result!"); // Get the SETCC result using the canonical SETCC type. - SDValue SetCC = DAG.getNode(ISD::SETCC, dl, SVT, N->getOperand(0), + SDValue SetCC = DAG.getNode(N->getOpcode(), dl, SVT, N->getOperand(0), N->getOperand(1), N->getOperand(2)); - // Convert to the expected type. - EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); assert(NVT.bitsLE(SVT) && "Integer type overpromoted?"); + // Convert to the expected type. return DAG.getNode(ISD::TRUNCATE, dl, NVT, SetCC); } @@ -707,6 +751,9 @@ bool DAGTypeLegalizer::PromoteIntegerOperand(SDNode *N, unsigned OpNo) { llvm_unreachable("Do not know how to promote this operator's operand!"); case ISD::ANY_EXTEND: Res = PromoteIntOp_ANY_EXTEND(N); break; + case ISD::ATOMIC_STORE: + Res = PromoteIntOp_ATOMIC_STORE(cast(N)); + break; case ISD::BITCAST: Res = PromoteIntOp_BITCAST(N); break; case ISD::BR_CC: Res = PromoteIntOp_BR_CC(N, OpNo); break; case ISD::BRCOND: Res = PromoteIntOp_BRCOND(N, OpNo); break; @@ -721,6 +768,7 @@ bool DAGTypeLegalizer::PromoteIntegerOperand(SDNode *N, unsigned OpNo) { case ISD::MEMBARRIER: Res = PromoteIntOp_MEMBARRIER(N); break; case ISD::SCALAR_TO_VECTOR: Res = PromoteIntOp_SCALAR_TO_VECTOR(N); break; + case ISD::VSELECT: case ISD::SELECT: Res = PromoteIntOp_SELECT(N, OpNo); break; case ISD::SELECT_CC: Res = PromoteIntOp_SELECT_CC(N, OpNo); break; case ISD::SETCC: Res = PromoteIntOp_SETCC(N, OpNo); break; @@ -791,6 +839,13 @@ SDValue DAGTypeLegalizer::PromoteIntOp_ANY_EXTEND(SDNode *N) { return DAG.getNode(ISD::ANY_EXTEND, N->getDebugLoc(), N->getValueType(0), Op); } +SDValue DAGTypeLegalizer::PromoteIntOp_ATOMIC_STORE(AtomicSDNode *N) { + SDValue Op2 = GetPromotedInteger(N->getOperand(2)); + return DAG.getAtomic(N->getOpcode(), N->getDebugLoc(), N->getMemoryVT(), + N->getChain(), N->getBasePtr(), Op2, N->getMemOperand(), + N->getOrdering(), N->getSynchScope()); +} + SDValue DAGTypeLegalizer::PromoteIntOp_BITCAST(SDNode *N) { // This should only occur in unusual situations like bitcasting to an // x86_fp80, so just turn it into a store+load @@ -913,14 +968,17 @@ SDValue DAGTypeLegalizer::PromoteIntOp_SCALAR_TO_VECTOR(SDNode *N) { } SDValue DAGTypeLegalizer::PromoteIntOp_SELECT(SDNode *N, unsigned OpNo) { - assert(OpNo == 0 && "Only know how to promote condition"); + assert(OpNo == 0 && "Only know how to promote the condition!"); + SDValue Cond = N->getOperand(0); + EVT OpTy = N->getOperand(1).getValueType(); // Promote all the way up to the canonical SetCC type. - EVT SVT = TLI.getSetCCResultType(N->getOperand(1).getValueType()); - SDValue Cond = PromoteTargetBoolean(N->getOperand(0), SVT); + EVT SVT = TLI.getSetCCResultType(N->getOpcode() == ISD::SELECT ? + OpTy.getScalarType() : OpTy); + Cond = PromoteTargetBoolean(Cond, SVT); - return SDValue(DAG.UpdateNodeOperands(N, Cond, - N->getOperand(1), N->getOperand(2)), 0); + return SDValue(DAG.UpdateNodeOperands(N, Cond, N->getOperand(1), + N->getOperand(2)), 0); } SDValue DAGTypeLegalizer::PromoteIntOp_SELECT_CC(SDNode *N, unsigned OpNo) { @@ -1024,7 +1082,7 @@ void DAGTypeLegalizer::ExpandIntegerResult(SDNode *N, unsigned ResNo) { #endif llvm_unreachable("Do not know how to expand the result of this operator!"); - case ISD::MERGE_VALUES: SplitRes_MERGE_VALUES(N, Lo, Hi); break; + case ISD::MERGE_VALUES: SplitRes_MERGE_VALUES(N, ResNo, Lo, Hi); break; case ISD::SELECT: SplitRes_SELECT(N, Lo, Hi); break; case ISD::SELECT_CC: SplitRes_SELECT_CC(N, Lo, Hi); break; case ISD::UNDEF: SplitRes_UNDEF(N, Lo, Hi); break; @@ -1055,6 +1113,7 @@ void DAGTypeLegalizer::ExpandIntegerResult(SDNode *N, unsigned ResNo) { case ISD::UDIV: ExpandIntRes_UDIV(N, Lo, Hi); break; case ISD::UREM: ExpandIntRes_UREM(N, Lo, Hi); break; case ISD::ZERO_EXTEND: ExpandIntRes_ZERO_EXTEND(N, Lo, Hi); break; + case ISD::ATOMIC_LOAD: ExpandIntRes_ATOMIC_LOAD(N, Lo, Hi); break; case ISD::ATOMIC_LOAD_ADD: case ISD::ATOMIC_LOAD_SUB: @@ -1546,6 +1605,12 @@ void DAGTypeLegalizer::ExpandIntRes_ADDSUBE(SDNode *N, ReplaceValueWith(SDValue(N, 1), Hi.getValue(1)); } +void DAGTypeLegalizer::ExpandIntRes_MERGE_VALUES(SDNode *N, unsigned ResNo, + SDValue &Lo, SDValue &Hi) { + SDValue Res = DisintegrateMERGE_VALUES(N, ResNo); + SplitInteger(Res, Lo, Hi); +} + void DAGTypeLegalizer::ExpandIntRes_ANY_EXTEND(SDNode *N, SDValue &Lo, SDValue &Hi) { EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); @@ -2176,9 +2241,9 @@ void DAGTypeLegalizer::ExpandIntRes_UADDSUBO(SDNode *N, void DAGTypeLegalizer::ExpandIntRes_XMULO(SDNode *N, SDValue &Lo, SDValue &Hi) { EVT VT = N->getValueType(0); - const Type *RetTy = VT.getTypeForEVT(*DAG.getContext()); + Type *RetTy = VT.getTypeForEVT(*DAG.getContext()); EVT PtrVT = TLI.getPointerTy(); - const Type *PtrTy = PtrVT.getTypeForEVT(*DAG.getContext()); + Type *PtrTy = PtrVT.getTypeForEVT(*DAG.getContext()); DebugLoc dl = N->getDebugLoc(); // A divide for UMULO should be faster than a function call. @@ -2222,7 +2287,7 @@ void DAGTypeLegalizer::ExpandIntRes_XMULO(SDNode *N, TargetLowering::ArgListEntry Entry; for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) { EVT ArgVT = N->getOperand(i).getValueType(); - const Type *ArgTy = ArgVT.getTypeForEVT(*DAG.getContext()); + Type *ArgTy = ArgVT.getTypeForEVT(*DAG.getContext()); Entry.Node = N->getOperand(i); Entry.Ty = ArgTy; Entry.isSExt = true; @@ -2321,6 +2386,20 @@ void DAGTypeLegalizer::ExpandIntRes_ZERO_EXTEND(SDNode *N, } } +void DAGTypeLegalizer::ExpandIntRes_ATOMIC_LOAD(SDNode *N, + SDValue &Lo, SDValue &Hi) { + DebugLoc dl = N->getDebugLoc(); + EVT VT = cast(N)->getMemoryVT(); + SDValue Zero = DAG.getConstant(0, VT); + SDValue Swap = DAG.getAtomic(ISD::ATOMIC_CMP_SWAP, dl, VT, + N->getOperand(0), + N->getOperand(1), Zero, Zero, + cast(N)->getMemOperand(), + cast(N)->getOrdering(), + cast(N)->getSynchScope()); + ReplaceValueWith(SDValue(N, 0), Swap.getValue(0)); + ReplaceValueWith(SDValue(N, 1), Swap.getValue(1)); +} //===----------------------------------------------------------------------===// // Integer Operand Expansion @@ -2365,6 +2444,8 @@ bool DAGTypeLegalizer::ExpandIntegerOperand(SDNode *N, unsigned OpNo) { case ISD::ROTR: Res = ExpandIntOp_Shift(N); break; case ISD::RETURNADDR: case ISD::FRAMEADDR: Res = ExpandIntOp_RETURNADDR(N); break; + + case ISD::ATOMIC_STORE: Res = ExpandIntOp_ATOMIC_STORE(N); break; } // If the result is null, the sub-method took care of registering results etc. @@ -2742,6 +2823,19 @@ SDValue DAGTypeLegalizer::ExpandIntOp_UINT_TO_FP(SDNode *N) { return MakeLibCall(LC, DstVT, &Op, 1, true, dl); } +SDValue DAGTypeLegalizer::ExpandIntOp_ATOMIC_STORE(SDNode *N) { + DebugLoc dl = N->getDebugLoc(); + SDValue Swap = DAG.getAtomic(ISD::ATOMIC_SWAP, dl, + cast(N)->getMemoryVT(), + N->getOperand(0), + N->getOperand(1), N->getOperand(2), + cast(N)->getMemOperand(), + cast(N)->getOrdering(), + cast(N)->getSynchScope()); + return Swap.getValue(1); +} + + SDValue DAGTypeLegalizer::PromoteIntRes_EXTRACT_SUBVECTOR(SDNode *N) { SDValue InOp0 = N->getOperand(0); EVT InVT = InOp0.getValueType(); @@ -2775,7 +2869,6 @@ SDValue DAGTypeLegalizer::PromoteIntRes_EXTRACT_SUBVECTOR(SDNode *N) { SDValue DAGTypeLegalizer::PromoteIntRes_VECTOR_SHUFFLE(SDNode *N) { - ShuffleVectorSDNode *SV = cast(N); EVT VT = N->getValueType(0); DebugLoc dl = N->getDebugLoc(); @@ -2830,6 +2923,46 @@ SDValue DAGTypeLegalizer::PromoteIntRes_SCALAR_TO_VECTOR(SDNode *N) { return DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, NOutVT, Op); } +SDValue DAGTypeLegalizer::PromoteIntRes_CONCAT_VECTORS(SDNode *N) { + DebugLoc dl = N->getDebugLoc(); + + SDValue Op0 = N->getOperand(1); + SDValue Op1 = N->getOperand(1); + assert(Op0.getValueType() == Op1.getValueType() && + "Invalid input vector types"); + + EVT OutVT = N->getValueType(0); + EVT NOutVT = TLI.getTypeToTransformTo(*DAG.getContext(), OutVT); + assert(NOutVT.isVector() && "This type must be promoted to a vector type"); + + EVT OutElemTy = NOutVT.getVectorElementType(); + + unsigned NumElem0 = Op0.getValueType().getVectorNumElements(); + unsigned NumElem1 = Op1.getValueType().getVectorNumElements(); + unsigned NumOutElem = NOutVT.getVectorNumElements(); + assert(NumElem0 + NumElem1 == NumOutElem && + "Invalid number of incoming elements"); + + // Take the elements from the first vector. + SmallVector Ops(NumOutElem); + for (unsigned i = 0; i < NumElem0; ++i) { + SDValue Ext = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, + Op0.getValueType().getScalarType(), Op0, + DAG.getIntPtrConstant(i)); + Ops[i] = DAG.getNode(ISD::ANY_EXTEND, dl, OutElemTy, Ext); + } + + // Take the elements from the second vector + for (unsigned i = 0; i < NumElem1; ++i) { + SDValue Ext = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, + Op1.getValueType().getScalarType(), Op1, + DAG.getIntPtrConstant(i)); + Ops[i + NumElem0] = DAG.getNode(ISD::ANY_EXTEND, dl, OutElemTy, Ext); + } + + return DAG.getNode(ISD::BUILD_VECTOR, dl, NOutVT, &Ops[0], Ops.size()); +} + SDValue DAGTypeLegalizer::PromoteIntRes_INSERT_VECTOR_ELT(SDNode *N) { EVT OutVT = N->getValueType(0); EVT NOutVT = TLI.getTypeToTransformTo(*DAG.getContext(), OutVT); @@ -2838,14 +2971,12 @@ SDValue DAGTypeLegalizer::PromoteIntRes_INSERT_VECTOR_ELT(SDNode *N) { EVT NOutVTElem = NOutVT.getVectorElementType(); DebugLoc dl = N->getDebugLoc(); - - SDValue ConvertedVector = DAG.getNode(ISD::ANY_EXTEND, dl, NOutVT, - N->getOperand(0)); + SDValue V0 = GetPromotedInteger(N->getOperand(0)); SDValue ConvElem = DAG.getNode(ISD::ANY_EXTEND, dl, NOutVTElem, N->getOperand(1)); - return DAG.getNode(ISD::INSERT_VECTOR_ELT, dl,NOutVT, - ConvertedVector, ConvElem, N->getOperand(2)); + return DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, NOutVT, + V0, ConvElem, N->getOperand(2)); } SDValue DAGTypeLegalizer::PromoteIntOp_EXTRACT_VECTOR_ELT(SDNode *N) { @@ -2855,20 +2986,23 @@ SDValue DAGTypeLegalizer::PromoteIntOp_EXTRACT_VECTOR_ELT(SDNode *N) { SDValue Ext = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, V0->getValueType(0).getScalarType(), V0, V1); - return DAG.getNode(ISD::TRUNCATE, dl, N->getValueType(0), Ext); - + // EXTRACT_VECTOR_ELT can return types which are wider than the incoming + // element types. If this is the case then we need to expand the outgoing + // value and not truncate it. + return DAG.getAnyExtOrTrunc(Ext, dl, N->getValueType(0)); } SDValue DAGTypeLegalizer::PromoteIntOp_CONCAT_VECTORS(SDNode *N) { - DebugLoc dl = N->getDebugLoc(); + unsigned NumElems = N->getNumOperands(); EVT RetSclrTy = N->getValueType(0).getVectorElementType(); SmallVector NewOps; + NewOps.reserve(NumElems); // For each incoming vector - for (unsigned VecIdx = 0, E = N->getNumOperands(); VecIdx!= E; ++VecIdx) { + for (unsigned VecIdx = 0; VecIdx != NumElems; ++VecIdx) { SDValue Incoming = GetPromotedInteger(N->getOperand(VecIdx)); EVT SclrTy = Incoming->getValueType(0).getVectorElementType(); unsigned NumElem = Incoming->getValueType(0).getVectorNumElements(); diff --git a/contrib/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp b/contrib/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp index ba658b022..a4bb57743 100644 --- a/contrib/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp +++ b/contrib/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp @@ -946,6 +946,13 @@ bool DAGTypeLegalizer::CustomWidenLowerNode(SDNode *N, EVT VT) { return true; } +SDValue DAGTypeLegalizer::DisintegrateMERGE_VALUES(SDNode *N, unsigned ResNo) { + for (unsigned i = 0, e = N->getNumValues(); i != e; ++i) + if (i != ResNo) + ReplaceValueWith(SDValue(N, i), SDValue(N->getOperand(i))); + return SDValue(N, ResNo); +} + /// GetSplitDestVTs - Compute the VTs needed for the low/hi parts of a type /// which is split into two not necessarily identical pieces. void DAGTypeLegalizer::GetSplitDestVTs(EVT InVT, EVT &LoVT, EVT &HiVT) { @@ -1046,7 +1053,7 @@ SDValue DAGTypeLegalizer::MakeLibCall(RTLIB::Libcall LC, EVT RetVT, SDValue Callee = DAG.getExternalSymbol(TLI.getLibcallName(LC), TLI.getPointerTy()); - const Type *RetTy = RetVT.getTypeForEVT(*DAG.getContext()); + Type *RetTy = RetVT.getTypeForEVT(*DAG.getContext()); std::pair CallInfo = TLI.LowerCallTo(DAG.getEntryNode(), RetTy, isSigned, !isSigned, false, false, 0, TLI.getLibcallCallingConv(LC), false, @@ -1067,7 +1074,7 @@ DAGTypeLegalizer::ExpandChainLibCall(RTLIB::Libcall LC, TargetLowering::ArgListEntry Entry; for (unsigned i = 1, e = Node->getNumOperands(); i != e; ++i) { EVT ArgVT = Node->getOperand(i).getValueType(); - const Type *ArgTy = ArgVT.getTypeForEVT(*DAG.getContext()); + Type *ArgTy = ArgVT.getTypeForEVT(*DAG.getContext()); Entry.Node = Node->getOperand(i); Entry.Ty = ArgTy; Entry.isSExt = isSigned; @@ -1078,7 +1085,7 @@ DAGTypeLegalizer::ExpandChainLibCall(RTLIB::Libcall LC, TLI.getPointerTy()); // Splice the libcall in wherever FindInputOutputChains tells us to. - const Type *RetTy = Node->getValueType(0).getTypeForEVT(*DAG.getContext()); + Type *RetTy = Node->getValueType(0).getTypeForEVT(*DAG.getContext()); std::pair CallInfo = TLI.LowerCallTo(InChain, RetTy, isSigned, !isSigned, false, false, 0, TLI.getLibcallCallingConv(LC), /*isTailCall=*/false, @@ -1093,24 +1100,8 @@ DAGTypeLegalizer::ExpandChainLibCall(RTLIB::Libcall LC, /// type i1, the bits of which conform to getBooleanContents. SDValue DAGTypeLegalizer::PromoteTargetBoolean(SDValue Bool, EVT VT) { DebugLoc dl = Bool.getDebugLoc(); - ISD::NodeType ExtendCode; - switch (TLI.getBooleanContents()) { - default: - assert(false && "Unknown BooleanContent!"); - case TargetLowering::UndefinedBooleanContent: - // Extend to VT by adding rubbish bits. - ExtendCode = ISD::ANY_EXTEND; - break; - case TargetLowering::ZeroOrOneBooleanContent: - // Extend to VT by adding zero bits. - ExtendCode = ISD::ZERO_EXTEND; - break; - case TargetLowering::ZeroOrNegativeOneBooleanContent: { - // Extend to VT by copying the sign bit. - ExtendCode = ISD::SIGN_EXTEND; - break; - } - } + ISD::NodeType ExtendCode = + TargetLowering::getExtendForContent(TLI.getBooleanContents(VT.isVector())); return DAG.getNode(ExtendCode, dl, VT, Bool); } diff --git a/contrib/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h b/contrib/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h index 952797dc7..abacdac68 100644 --- a/contrib/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h +++ b/contrib/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h @@ -148,15 +148,22 @@ private: SDValue CreateStackStoreLoad(SDValue Op, EVT DestVT); bool CustomLowerNode(SDNode *N, EVT VT, bool LegalizeResult); bool CustomWidenLowerNode(SDNode *N, EVT VT); + + /// DisintegrateMERGE_VALUES - Replace each result of the given MERGE_VALUES + /// node with the corresponding input operand, except for the result 'ResNo', + /// which is returned. + SDValue DisintegrateMERGE_VALUES(SDNode *N, unsigned ResNo); + SDValue GetVectorElementPointer(SDValue VecPtr, EVT EltVT, SDValue Index); SDValue JoinIntegers(SDValue Lo, SDValue Hi); SDValue LibCallify(RTLIB::Libcall LC, SDNode *N, bool isSigned); SDValue MakeLibCall(RTLIB::Libcall LC, EVT RetVT, const SDValue *Ops, unsigned NumOps, bool isSigned, DebugLoc dl); - std::pair ExpandChainLibCall(RTLIB::Libcall LC, - SDNode *Node, bool isSigned); - std::pair ExpandAtomic(SDNode *Node); + + std::pair ExpandChainLibCall(RTLIB::Libcall LC, + SDNode *Node, bool isSigned); + std::pair ExpandAtomic(SDNode *Node); SDValue PromoteTargetBoolean(SDValue Bool, EVT VT); void ReplaceValueWith(SDValue From, SDValue To); @@ -206,8 +213,10 @@ private: // Integer Result Promotion. void PromoteIntegerResult(SDNode *N, unsigned ResNo); + SDValue PromoteIntRes_MERGE_VALUES(SDNode *N, unsigned ResNo); SDValue PromoteIntRes_AssertSext(SDNode *N); SDValue PromoteIntRes_AssertZext(SDNode *N); + SDValue PromoteIntRes_Atomic0(AtomicSDNode *N); SDValue PromoteIntRes_Atomic1(AtomicSDNode *N); SDValue PromoteIntRes_Atomic2(AtomicSDNode *N); SDValue PromoteIntRes_EXTRACT_SUBVECTOR(SDNode *N); @@ -215,6 +224,7 @@ private: SDValue PromoteIntRes_BUILD_VECTOR(SDNode *N); SDValue PromoteIntRes_SCALAR_TO_VECTOR(SDNode *N); SDValue PromoteIntRes_INSERT_VECTOR_ELT(SDNode *N); + SDValue PromoteIntRes_CONCAT_VECTORS(SDNode *N); SDValue PromoteIntRes_BITCAST(SDNode *N); SDValue PromoteIntRes_BSWAP(SDNode *N); SDValue PromoteIntRes_BUILD_PAIR(SDNode *N); @@ -232,6 +242,7 @@ private: SDValue PromoteIntRes_SADDSUBO(SDNode *N, unsigned ResNo); SDValue PromoteIntRes_SDIV(SDNode *N); SDValue PromoteIntRes_SELECT(SDNode *N); + SDValue PromoteIntRes_VSELECT(SDNode *N); SDValue PromoteIntRes_SELECT_CC(SDNode *N); SDValue PromoteIntRes_SETCC(SDNode *N); SDValue PromoteIntRes_SHL(SDNode *N); @@ -249,6 +260,7 @@ private: // Integer Operand Promotion. bool PromoteIntegerOperand(SDNode *N, unsigned OperandNo); SDValue PromoteIntOp_ANY_EXTEND(SDNode *N); + SDValue PromoteIntOp_ATOMIC_STORE(AtomicSDNode *N); SDValue PromoteIntOp_BITCAST(SDNode *N); SDValue PromoteIntOp_BUILD_PAIR(SDNode *N); SDValue PromoteIntOp_BR_CC(SDNode *N, unsigned OpNo); @@ -264,6 +276,7 @@ private: SDValue PromoteIntOp_SELECT(SDNode *N, unsigned OpNo); SDValue PromoteIntOp_SELECT_CC(SDNode *N, unsigned OpNo); SDValue PromoteIntOp_SETCC(SDNode *N, unsigned OpNo); + SDValue PromoteIntOp_VSETCC(SDNode *N, unsigned OpNo); SDValue PromoteIntOp_Shift(SDNode *N); SDValue PromoteIntOp_SIGN_EXTEND(SDNode *N); SDValue PromoteIntOp_SINT_TO_FP(SDNode *N); @@ -289,6 +302,8 @@ private: // Integer Result Expansion. void ExpandIntegerResult(SDNode *N, unsigned ResNo); + void ExpandIntRes_MERGE_VALUES (SDNode *N, unsigned ResNo, + SDValue &Lo, SDValue &Hi); void ExpandIntRes_ANY_EXTEND (SDNode *N, SDValue &Lo, SDValue &Hi); void ExpandIntRes_AssertSext (SDNode *N, SDValue &Lo, SDValue &Hi); void ExpandIntRes_AssertZext (SDNode *N, SDValue &Lo, SDValue &Hi); @@ -320,6 +335,8 @@ private: void ExpandIntRes_UADDSUBO (SDNode *N, SDValue &Lo, SDValue &Hi); void ExpandIntRes_XMULO (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandIntRes_ATOMIC_LOAD (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandShiftByConstant(SDNode *N, unsigned Amt, SDValue &Lo, SDValue &Hi); bool ExpandShiftWithKnownAmountBit(SDNode *N, SDValue &Lo, SDValue &Hi); @@ -339,6 +356,7 @@ private: SDValue ExpandIntOp_TRUNCATE(SDNode *N); SDValue ExpandIntOp_UINT_TO_FP(SDNode *N); SDValue ExpandIntOp_RETURNADDR(SDNode *N); + SDValue ExpandIntOp_ATOMIC_STORE(SDNode *N); void IntegerExpandSetCCOperands(SDValue &NewLHS, SDValue &NewRHS, ISD::CondCode &CCCode, DebugLoc dl); @@ -362,6 +380,7 @@ private: // Result Float to Integer Conversion. void SoftenFloatResult(SDNode *N, unsigned OpNo); + SDValue SoftenFloatRes_MERGE_VALUES(SDNode *N, unsigned ResNo); SDValue SoftenFloatRes_BITCAST(SDNode *N); SDValue SoftenFloatRes_BUILD_PAIR(SDNode *N); SDValue SoftenFloatRes_ConstantFP(ConstantFPSDNode *N); @@ -488,6 +507,7 @@ private: // Vector Result Scalarization: <1 x ty> -> ty. void ScalarizeVectorResult(SDNode *N, unsigned OpNo); + SDValue ScalarizeVecRes_MERGE_VALUES(SDNode *N, unsigned ResNo); SDValue ScalarizeVecRes_BinOp(SDNode *N); SDValue ScalarizeVecRes_UnaryOp(SDNode *N); SDValue ScalarizeVecRes_InregOp(SDNode *N); @@ -559,6 +579,7 @@ private: SDValue SplitVecOp_EXTRACT_VECTOR_ELT(SDNode *N); SDValue SplitVecOp_STORE(StoreSDNode *N, unsigned OpNo); SDValue SplitVecOp_CONCAT_VECTORS(SDNode *N); + SDValue SplitVecOp_VSETCC(SDNode *N); SDValue SplitVecOp_FP_ROUND(SDNode *N); //===--------------------------------------------------------------------===// @@ -581,6 +602,7 @@ private: // Widen Vector Result Promotion. void WidenVectorResult(SDNode *N, unsigned ResNo); + SDValue WidenVecRes_MERGE_VALUES(SDNode* N, unsigned ResNo); SDValue WidenVecRes_BITCAST(SDNode* N); SDValue WidenVecRes_BUILD_VECTOR(SDNode* N); SDValue WidenVecRes_CONCAT_VECTORS(SDNode* N); @@ -677,7 +699,8 @@ private: void GetPairElements(SDValue Pair, SDValue &Lo, SDValue &Hi); // Generic Result Splitting. - void SplitRes_MERGE_VALUES(SDNode *N, SDValue &Lo, SDValue &Hi); + void SplitRes_MERGE_VALUES(SDNode *N, unsigned ResNo, + SDValue &Lo, SDValue &Hi); void SplitRes_SELECT (SDNode *N, SDValue &Lo, SDValue &Hi); void SplitRes_SELECT_CC (SDNode *N, SDValue &Lo, SDValue &Hi); void SplitRes_UNDEF (SDNode *N, SDValue &Lo, SDValue &Hi); @@ -699,6 +722,8 @@ private: } // Generic Result Expansion. + void ExpandRes_MERGE_VALUES (SDNode *N, unsigned ResNo, + SDValue &Lo, SDValue &Hi); void ExpandRes_BITCAST (SDNode *N, SDValue &Lo, SDValue &Hi); void ExpandRes_BUILD_PAIR (SDNode *N, SDValue &Lo, SDValue &Hi); void ExpandRes_EXTRACT_ELEMENT (SDNode *N, SDValue &Lo, SDValue &Hi); diff --git a/contrib/llvm/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp b/contrib/llvm/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp index 85ea6b662..8e7e4985e 100644 --- a/contrib/llvm/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp +++ b/contrib/llvm/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp @@ -31,6 +31,11 @@ using namespace llvm; // These routines assume that the Lo/Hi part is stored first in memory on // little/big-endian machines, followed by the Hi/Lo part. This means that // they cannot be used as is on vectors, for which Lo is always stored first. +void DAGTypeLegalizer::ExpandRes_MERGE_VALUES(SDNode *N, unsigned ResNo, + SDValue &Lo, SDValue &Hi) { + SDValue Op = DisintegrateMERGE_VALUES(N, ResNo); + GetExpandedOp(Op, Lo, Hi); +} void DAGTypeLegalizer::ExpandRes_BITCAST(SDNode *N, SDValue &Lo, SDValue &Hi) { EVT OutVT = N->getValueType(0); @@ -426,37 +431,34 @@ SDValue DAGTypeLegalizer::ExpandOp_NormalStore(SDNode *N, unsigned OpNo) { // bytes; for integers and floats it is Lo first if and only if the machine is // little-endian). -void DAGTypeLegalizer::SplitRes_MERGE_VALUES(SDNode *N, +void DAGTypeLegalizer::SplitRes_MERGE_VALUES(SDNode *N, unsigned ResNo, SDValue &Lo, SDValue &Hi) { - // A MERGE_VALUES node can produce any number of values. We know that the - // first illegal one needs to be expanded into Lo/Hi. - unsigned i; - - // The string of legal results gets turned into input operands, which have - // the same type. - for (i = 0; isTypeLegal(N->getValueType(i)); ++i) - ReplaceValueWith(SDValue(N, i), SDValue(N->getOperand(i))); - - // The first illegal result must be the one that needs to be expanded. - GetSplitOp(N->getOperand(i), Lo, Hi); - - // Legalize the rest of the results into the input operands whether they are - // legal or not. - unsigned e = N->getNumValues(); - for (++i; i != e; ++i) - ReplaceValueWith(SDValue(N, i), SDValue(N->getOperand(i))); + SDValue Op = DisintegrateMERGE_VALUES(N, ResNo); + GetSplitOp(Op, Lo, Hi); } void DAGTypeLegalizer::SplitRes_SELECT(SDNode *N, SDValue &Lo, SDValue &Hi) { - SDValue LL, LH, RL, RH; + SDValue LL, LH, RL, RH, CL, CH; DebugLoc dl = N->getDebugLoc(); GetSplitOp(N->getOperand(1), LL, LH); GetSplitOp(N->getOperand(2), RL, RH); SDValue Cond = N->getOperand(0); - Lo = DAG.getNode(ISD::SELECT, dl, LL.getValueType(), Cond, LL, RL); - Hi = DAG.getNode(ISD::SELECT, dl, LH.getValueType(), Cond, LH, RH); + CL = CH = Cond; + if (Cond.getValueType().isVector()) { + assert(Cond.getValueType().getVectorElementType() == MVT::i1 && + "Condition legalized before result?"); + unsigned NumElements = Cond.getValueType().getVectorNumElements(); + EVT VCondTy = EVT::getVectorVT(*DAG.getContext(), MVT::i1, NumElements / 2); + CL = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, VCondTy, Cond, + DAG.getIntPtrConstant(0)); + CH = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, VCondTy, Cond, + DAG.getIntPtrConstant(NumElements / 2)); + } + + Lo = DAG.getNode(N->getOpcode(), dl, LL.getValueType(), CL, LL, RL); + Hi = DAG.getNode(N->getOpcode(), dl, LH.getValueType(), CH, LH, RH); } void DAGTypeLegalizer::SplitRes_SELECT_CC(SDNode *N, SDValue &Lo, diff --git a/contrib/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp b/contrib/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp index ffff10ce2..f815b00db 100644 --- a/contrib/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp +++ b/contrib/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp @@ -61,6 +61,9 @@ class VectorLegalizer { // Implements expansion for UINT_TO_FLOAT; falls back to UnrollVectorOp if // SINT_TO_FLOAT and SHR on vectors isn't legal. SDValue ExpandUINT_TO_FLOAT(SDValue Op); + // Implement vselect in terms of XOR, AND, OR when blend is not supported + // by the target. + SDValue ExpandVSELECT(SDValue Op); SDValue ExpandFNEG(SDValue Op); // Implements vector promotion; this is essentially just bitcasting the // operands to a different type and bitcasting the result back to the @@ -157,8 +160,9 @@ SDValue VectorLegalizer::LegalizeOp(SDValue Op) { case ISD::CTLZ: case ISD::CTPOP: case ISD::SELECT: + case ISD::VSELECT: case ISD::SELECT_CC: - case ISD::VSETCC: + case ISD::SETCC: case ISD::ZERO_EXTEND: case ISD::ANY_EXTEND: case ISD::TRUNCATE: @@ -210,11 +214,13 @@ SDValue VectorLegalizer::LegalizeOp(SDValue Op) { // FALL THROUGH } case TargetLowering::Expand: - if (Node->getOpcode() == ISD::UINT_TO_FP) + if (Node->getOpcode() == ISD::VSELECT) + Result = ExpandVSELECT(Op); + else if (Node->getOpcode() == ISD::UINT_TO_FP) Result = ExpandUINT_TO_FLOAT(Op); else if (Node->getOpcode() == ISD::FNEG) Result = ExpandFNEG(Op); - else if (Node->getOpcode() == ISD::VSETCC) + else if (Node->getOpcode() == ISD::SETCC) Result = UnrollVSETCC(Op); else Result = DAG.UnrollVectorOp(Op.getNode()); @@ -256,9 +262,41 @@ SDValue VectorLegalizer::PromoteVectorOp(SDValue Op) { return DAG.getNode(ISD::BITCAST, dl, VT, Op); } -SDValue VectorLegalizer::ExpandUINT_TO_FLOAT(SDValue Op) { +SDValue VectorLegalizer::ExpandVSELECT(SDValue Op) { + // Implement VSELECT in terms of XOR, AND, OR + // on platforms which do not support blend natively. + EVT VT = Op.getOperand(0).getValueType(); + DebugLoc DL = Op.getDebugLoc(); + SDValue Mask = Op.getOperand(0); + SDValue Op1 = Op.getOperand(1); + SDValue Op2 = Op.getOperand(2); + + // If we can't even use the basic vector operations of + // AND,OR,XOR, we will have to scalarize the op. + if (!TLI.isOperationLegalOrCustom(ISD::AND, VT) || + !TLI.isOperationLegalOrCustom(ISD::XOR, VT) || + !TLI.isOperationLegalOrCustom(ISD::OR, VT)) + return DAG.UnrollVectorOp(Op.getNode()); + + assert(VT.getSizeInBits() == Op.getOperand(1).getValueType().getSizeInBits() + && "Invalid mask size"); + // Bitcast the operands to be the same type as the mask. + // This is needed when we select between FP types because + // the mask is a vector of integers. + Op1 = DAG.getNode(ISD::BITCAST, DL, VT, Op1); + Op2 = DAG.getNode(ISD::BITCAST, DL, VT, Op2); + + SDValue AllOnes = DAG.getConstant( + APInt::getAllOnesValue(VT.getScalarType().getSizeInBits()), VT); + SDValue NotMask = DAG.getNode(ISD::XOR, DL, VT, Mask, AllOnes); + + Op1 = DAG.getNode(ISD::AND, DL, VT, Op1, Mask); + Op2 = DAG.getNode(ISD::AND, DL, VT, Op2, NotMask); + return DAG.getNode(ISD::OR, DL, VT, Op1, Op2); +} +SDValue VectorLegalizer::ExpandUINT_TO_FLOAT(SDValue Op) { EVT VT = Op.getOperand(0).getValueType(); DebugLoc DL = Op.getDebugLoc(); diff --git a/contrib/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp b/contrib/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp index b5698f9c6..107a42b29 100644 --- a/contrib/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp +++ b/contrib/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp @@ -44,8 +44,10 @@ void DAGTypeLegalizer::ScalarizeVectorResult(SDNode *N, unsigned ResNo) { N->dump(&DAG); dbgs() << "\n"; #endif - llvm_unreachable("Do not know how to scalarize the result of this operator!"); + report_fatal_error("Do not know how to scalarize the result of this " + "operator!\n"); + case ISD::MERGE_VALUES: R = ScalarizeVecRes_MERGE_VALUES(N, ResNo);break; case ISD::BITCAST: R = ScalarizeVecRes_BITCAST(N); break; case ISD::BUILD_VECTOR: R = N->getOperand(0); break; case ISD::CONVERT_RNDSAT: R = ScalarizeVecRes_CONVERT_RNDSAT(N); break; @@ -62,8 +64,6 @@ void DAGTypeLegalizer::ScalarizeVectorResult(SDNode *N, unsigned ResNo) { case ISD::SETCC: R = ScalarizeVecRes_SETCC(N); break; case ISD::UNDEF: R = ScalarizeVecRes_UNDEF(N); break; case ISD::VECTOR_SHUFFLE: R = ScalarizeVecRes_VECTOR_SHUFFLE(N); break; - case ISD::VSETCC: R = ScalarizeVecRes_VSETCC(N); break; - case ISD::ANY_EXTEND: case ISD::CTLZ: case ISD::CTPOP: @@ -129,6 +129,12 @@ SDValue DAGTypeLegalizer::ScalarizeVecRes_BinOp(SDNode *N) { LHS.getValueType(), LHS, RHS); } +SDValue DAGTypeLegalizer::ScalarizeVecRes_MERGE_VALUES(SDNode *N, + unsigned ResNo) { + SDValue Op = DisintegrateMERGE_VALUES(N, ResNo); + return GetScalarizedVector(Op); +} + SDValue DAGTypeLegalizer::ScalarizeVecRes_BITCAST(SDNode *N) { EVT NewVT = N->getValueType(0).getVectorElementType(); return DAG.getNode(ISD::BITCAST, N->getDebugLoc(), @@ -237,6 +243,12 @@ SDValue DAGTypeLegalizer::ScalarizeVecRes_SELECT_CC(SDNode *N) { } SDValue DAGTypeLegalizer::ScalarizeVecRes_SETCC(SDNode *N) { + assert(N->getValueType(0).isVector() == + N->getOperand(0).getValueType().isVector() && + "Scalar/Vector type mismatch"); + + if (N->getValueType(0).isVector()) return ScalarizeVecRes_VSETCC(N); + SDValue LHS = GetScalarizedVector(N->getOperand(0)); SDValue RHS = GetScalarizedVector(N->getOperand(1)); DebugLoc DL = N->getDebugLoc(); @@ -259,35 +271,23 @@ SDValue DAGTypeLegalizer::ScalarizeVecRes_VECTOR_SHUFFLE(SDNode *N) { } SDValue DAGTypeLegalizer::ScalarizeVecRes_VSETCC(SDNode *N) { + assert(N->getValueType(0).isVector() && + N->getOperand(0).getValueType().isVector() && + "Operand types must be vectors"); + SDValue LHS = GetScalarizedVector(N->getOperand(0)); SDValue RHS = GetScalarizedVector(N->getOperand(1)); EVT NVT = N->getValueType(0).getVectorElementType(); - EVT SVT = TLI.getSetCCResultType(LHS.getValueType()); DebugLoc DL = N->getDebugLoc(); // Turn it into a scalar SETCC. - SDValue Res = DAG.getNode(ISD::SETCC, DL, SVT, LHS, RHS, N->getOperand(2)); - - // VSETCC always returns a sign-extended value, while SETCC may not. The - // SETCC result type may not match the vector element type. Correct these. - if (NVT.bitsLE(SVT)) { - // The SETCC result type is bigger than the vector element type. - // Ensure the SETCC result is sign-extended. - if (TLI.getBooleanContents() != - TargetLowering::ZeroOrNegativeOneBooleanContent) - Res = DAG.getNode(ISD::SIGN_EXTEND_INREG, DL, SVT, Res, - DAG.getValueType(MVT::i1)); - // Truncate to the final type. - return DAG.getNode(ISD::TRUNCATE, DL, NVT, Res); - } - - // The SETCC result type is smaller than the vector element type. - // If the SetCC result is not sign-extended, chop it down to MVT::i1. - if (TLI.getBooleanContents() != - TargetLowering::ZeroOrNegativeOneBooleanContent) - Res = DAG.getNode(ISD::TRUNCATE, DL, MVT::i1, Res); - // Sign extend to the final type. - return DAG.getNode(ISD::SIGN_EXTEND, DL, NVT, Res); + SDValue Res = DAG.getNode(ISD::SETCC, DL, MVT::i1, LHS, RHS, + N->getOperand(2)); + // Vectors may have a different boolean contents to scalars. Promote the + // value appropriately. + ISD::NodeType ExtendCode = + TargetLowering::getExtendForContent(TLI.getBooleanContents(true)); + return DAG.getNode(ExtendCode, DL, NVT, Res); } @@ -415,7 +415,8 @@ void DAGTypeLegalizer::SplitVectorResult(SDNode *N, unsigned ResNo) { #endif llvm_unreachable("Do not know how to split the result of this operator!"); - case ISD::MERGE_VALUES: SplitRes_MERGE_VALUES(N, Lo, Hi); break; + case ISD::MERGE_VALUES: SplitRes_MERGE_VALUES(N, ResNo, Lo, Hi); break; + case ISD::VSELECT: case ISD::SELECT: SplitRes_SELECT(N, Lo, Hi); break; case ISD::SELECT_CC: SplitRes_SELECT_CC(N, Lo, Hi); break; case ISD::UNDEF: SplitRes_UNDEF(N, Lo, Hi); break; @@ -432,7 +433,6 @@ void DAGTypeLegalizer::SplitVectorResult(SDNode *N, unsigned ResNo) { SplitVecRes_LOAD(cast(N), Lo, Hi); break; case ISD::SETCC: - case ISD::VSETCC: SplitVecRes_SETCC(N, Lo, Hi); break; case ISD::VECTOR_SHUFFLE: @@ -524,12 +524,11 @@ void DAGTypeLegalizer::SplitVecRes_BITCAST(SDNode *N, SDValue &Lo, // Handle some special cases efficiently. switch (getTypeAction(InVT)) { - default: - assert(false && "Unknown type action!"); case TargetLowering::TypeLegal: case TargetLowering::TypePromoteInteger: case TargetLowering::TypeSoftenFloat: case TargetLowering::TypeScalarizeVector: + case TargetLowering::TypeWidenVector: break; case TargetLowering::TypeExpandInteger: case TargetLowering::TypeExpandFloat: @@ -670,7 +669,7 @@ void DAGTypeLegalizer::SplitVecRes_INSERT_VECTOR_ELT(SDNode *N, SDValue &Lo, // Store the new element. This may be larger than the vector element type, // so use a truncating store. SDValue EltPtr = GetVectorElementPointer(StackPtr, EltVT, Idx); - const Type *VecType = VecVT.getTypeForEVT(*DAG.getContext()); + Type *VecType = VecVT.getTypeForEVT(*DAG.getContext()); unsigned Alignment = TLI.getTargetData()->getPrefTypeAlignment(VecType); Store = DAG.getTruncStore(Store, dl, Elt, EltPtr, MachinePointerInfo(), EltVT, @@ -740,6 +739,10 @@ void DAGTypeLegalizer::SplitVecRes_LOAD(LoadSDNode *LD, SDValue &Lo, } void DAGTypeLegalizer::SplitVecRes_SETCC(SDNode *N, SDValue &Lo, SDValue &Hi) { + assert(N->getValueType(0).isVector() && + N->getOperand(0).getValueType().isVector() && + "Operand types must be vectors"); + EVT LoVT, HiVT; DebugLoc DL = N->getDebugLoc(); GetSplitDestVTs(N->getValueType(0), LoVT, HiVT); @@ -965,7 +968,7 @@ bool DAGTypeLegalizer::SplitVectorOperand(SDNode *N, unsigned OpNo) { dbgs() << "\n"; #endif llvm_unreachable("Do not know how to split this operator's operand!"); - + case ISD::SETCC: Res = SplitVecOp_VSETCC(N); break; case ISD::BITCAST: Res = SplitVecOp_BITCAST(N); break; case ISD::EXTRACT_SUBVECTOR: Res = SplitVecOp_EXTRACT_SUBVECTOR(N); break; case ISD::EXTRACT_VECTOR_ELT:Res = SplitVecOp_EXTRACT_VECTOR_ELT(N); break; @@ -1163,6 +1166,26 @@ SDValue DAGTypeLegalizer::SplitVecOp_CONCAT_VECTORS(SDNode *N) { &Elts[0], Elts.size()); } +SDValue DAGTypeLegalizer::SplitVecOp_VSETCC(SDNode *N) { + assert(N->getValueType(0).isVector() && + N->getOperand(0).getValueType().isVector() && + "Operand types must be vectors"); + // The result has a legal vector type, but the input needs splitting. + SDValue Lo0, Hi0, Lo1, Hi1, LoRes, HiRes; + DebugLoc DL = N->getDebugLoc(); + GetSplitVector(N->getOperand(0), Lo0, Hi0); + GetSplitVector(N->getOperand(1), Lo1, Hi1); + unsigned PartElements = Lo0.getValueType().getVectorNumElements(); + EVT PartResVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1, PartElements); + EVT WideResVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1, 2*PartElements); + + LoRes = DAG.getNode(ISD::SETCC, DL, PartResVT, Lo0, Lo1, N->getOperand(2)); + HiRes = DAG.getNode(ISD::SETCC, DL, PartResVT, Hi0, Hi1, N->getOperand(2)); + SDValue Con = DAG.getNode(ISD::CONCAT_VECTORS, DL, WideResVT, LoRes, HiRes); + return PromoteTargetBoolean(Con, N->getValueType(0)); +} + + SDValue DAGTypeLegalizer::SplitVecOp_FP_ROUND(SDNode *N) { // The result has a legal vector type, but the input needs splitting. EVT ResVT = N->getValueType(0); @@ -1205,6 +1228,7 @@ void DAGTypeLegalizer::WidenVectorResult(SDNode *N, unsigned ResNo) { #endif llvm_unreachable("Do not know how to widen the result of this operator!"); + case ISD::MERGE_VALUES: Res = WidenVecRes_MERGE_VALUES(N, ResNo); break; case ISD::BITCAST: Res = WidenVecRes_BITCAST(N); break; case ISD::BUILD_VECTOR: Res = WidenVecRes_BUILD_VECTOR(N); break; case ISD::CONCAT_VECTORS: Res = WidenVecRes_CONCAT_VECTORS(N); break; @@ -1222,10 +1246,6 @@ void DAGTypeLegalizer::WidenVectorResult(SDNode *N, unsigned ResNo) { case ISD::VECTOR_SHUFFLE: Res = WidenVecRes_VECTOR_SHUFFLE(cast(N)); break; - case ISD::VSETCC: - Res = WidenVecRes_VSETCC(N); - break; - case ISD::ADD: case ISD::AND: case ISD::BSWAP: @@ -1557,6 +1577,11 @@ SDValue DAGTypeLegalizer::WidenVecRes_InregOp(SDNode *N) { WidenVT, WidenLHS, DAG.getValueType(ExtVT)); } +SDValue DAGTypeLegalizer::WidenVecRes_MERGE_VALUES(SDNode *N, unsigned ResNo) { + SDValue WidenVec = DisintegrateMERGE_VALUES(N, ResNo); + return GetWidenedVector(WidenVec); +} + SDValue DAGTypeLegalizer::WidenVecRes_BITCAST(SDNode *N) { SDValue InOp = N->getOperand(0); EVT InVT = InOp.getValueType(); @@ -1661,6 +1686,7 @@ SDValue DAGTypeLegalizer::WidenVecRes_CONCAT_VECTORS(SDNode *N) { EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); DebugLoc dl = N->getDebugLoc(); unsigned WidenNumElts = WidenVT.getVectorNumElements(); + unsigned NumInElts = InVT.getVectorNumElements(); unsigned NumOperands = N->getNumOperands(); bool InputWidened = false; // Indicates we need to widen the input. @@ -1686,17 +1712,17 @@ SDValue DAGTypeLegalizer::WidenVecRes_CONCAT_VECTORS(SDNode *N) { if (N->getOperand(i).getOpcode() != ISD::UNDEF) break; - if (i > NumOperands) + if (i == NumOperands) // Everything but the first operand is an UNDEF so just return the // widened first operand. return GetWidenedVector(N->getOperand(0)); if (NumOperands == 2) { // Replace concat of two operands with a shuffle. - SmallVector MaskOps(WidenNumElts); - for (unsigned i=0; i < WidenNumElts/2; ++i) { + SmallVector MaskOps(WidenNumElts, -1); + for (unsigned i = 0; i < NumInElts; ++i) { MaskOps[i] = i; - MaskOps[i+WidenNumElts/2] = i+WidenNumElts; + MaskOps[i + NumInElts] = i + WidenNumElts; } return DAG.getVectorShuffle(WidenVT, dl, GetWidenedVector(N->getOperand(0)), @@ -1708,7 +1734,6 @@ SDValue DAGTypeLegalizer::WidenVecRes_CONCAT_VECTORS(SDNode *N) { // Fall back to use extracts and build vector. EVT EltVT = WidenVT.getVectorElementType(); - unsigned NumInElts = InVT.getVectorNumElements(); SmallVector Ops(WidenNumElts); unsigned Idx = 0; for (unsigned i=0; i < NumOperands; ++i) { @@ -1916,6 +1941,11 @@ SDValue DAGTypeLegalizer::WidenVecRes_SELECT_CC(SDNode *N) { } SDValue DAGTypeLegalizer::WidenVecRes_SETCC(SDNode *N) { + assert(N->getValueType(0).isVector() == + N->getOperand(0).getValueType().isVector() && + "Scalar/Vector type mismatch"); + if (N->getValueType(0).isVector()) return WidenVecRes_VSETCC(N); + EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); SDValue InOp1 = GetWidenedVector(N->getOperand(0)); SDValue InOp2 = GetWidenedVector(N->getOperand(1)); @@ -1954,6 +1984,9 @@ SDValue DAGTypeLegalizer::WidenVecRes_VECTOR_SHUFFLE(ShuffleVectorSDNode *N) { } SDValue DAGTypeLegalizer::WidenVecRes_VSETCC(SDNode *N) { + assert(N->getValueType(0).isVector() && + N->getOperand(0).getValueType().isVector() && + "Operands must be vectors"); EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); unsigned WidenNumElts = WidenVT.getVectorNumElements(); @@ -1970,7 +2003,8 @@ SDValue DAGTypeLegalizer::WidenVecRes_VSETCC(SDNode *N) { assert(InOp1.getValueType() == WidenInVT && InOp2.getValueType() == WidenInVT && "Input not widened to expected type!"); - return DAG.getNode(ISD::VSETCC, N->getDebugLoc(), + (void)WidenInVT; + return DAG.getNode(ISD::SETCC, N->getDebugLoc(), WidenVT, InOp1, InOp2, N->getOperand(2)); } diff --git a/contrib/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp b/contrib/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp index 12b183804..e757defd3 100644 --- a/contrib/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp +++ b/contrib/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp @@ -2621,6 +2621,39 @@ bool RegReductionPQBase::canClobber(const SUnit *SU, const SUnit *Op) { return false; } +/// canClobberReachingPhysRegUse - True if SU would clobber one of it's +/// successor's explicit physregs whose definition can reach DepSU. +/// i.e. DepSU should not be scheduled above SU. +static bool canClobberReachingPhysRegUse(const SUnit *DepSU, const SUnit *SU, + ScheduleDAGRRList *scheduleDAG, + const TargetInstrInfo *TII, + const TargetRegisterInfo *TRI) { + const unsigned *ImpDefs + = TII->get(SU->getNode()->getMachineOpcode()).getImplicitDefs(); + if(!ImpDefs) + return false; + + for (SUnit::const_succ_iterator SI = SU->Succs.begin(), SE = SU->Succs.end(); + SI != SE; ++SI) { + SUnit *SuccSU = SI->getSUnit(); + for (SUnit::const_pred_iterator PI = SuccSU->Preds.begin(), + PE = SuccSU->Preds.end(); PI != PE; ++PI) { + if (!PI->isAssignedRegDep()) + continue; + + for (const unsigned *ImpDef = ImpDefs; *ImpDef; ++ImpDef) { + // Return true if SU clobbers this physical register use and the + // definition of the register reaches from DepSU. IsReachable queries a + // topological forward sort of the DAG (following the successors). + if (TRI->regsOverlap(*ImpDef, PI->getReg()) && + scheduleDAG->IsReachable(DepSU, PI->getSUnit())) + return true; + } + } + } + return false; +} + /// canClobberPhysRegDefs - True if SU would clobber one of SuccSU's /// physical register defs. static bool canClobberPhysRegDefs(const SUnit *SuccSU, const SUnit *SU, @@ -2837,7 +2870,8 @@ void RegReductionPQBase::AddPseudoTwoAddrDeps() { SuccOpc == TargetOpcode::INSERT_SUBREG || SuccOpc == TargetOpcode::SUBREG_TO_REG) continue; - if ((!canClobber(SuccSU, DUSU) || + if (!canClobberReachingPhysRegUse(SuccSU, SU, scheduleDAG, TII, TRI) && + (!canClobber(SuccSU, DUSU) || (isLiveOut && !hasOnlyLiveOutUses(SuccSU)) || (!SU->isCommutable && SuccSU->isCommutable)) && !scheduleDAG->IsReachable(SuccSU, SU)) { diff --git a/contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index 35ea0bb94..20bea8e4c 100644 --- a/contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -403,7 +403,7 @@ static void AddNodeIDCustom(FoldingSetNodeID &ID, const SDNode *N) { ID.AddInteger(CP->getAlignment()); ID.AddInteger(CP->getOffset()); if (CP->isMachineConstantPoolEntry()) - CP->getMachineCPVal()->AddSelectionDAGCSEId(ID); + CP->getMachineCPVal()->addSelectionDAGCSEId(ID); else ID.AddPointer(CP->getConstVal()); ID.AddInteger(CP->getTargetFlags()); @@ -432,7 +432,9 @@ static void AddNodeIDCustom(FoldingSetNodeID &ID, const SDNode *N) { case ISD::ATOMIC_LOAD_MIN: case ISD::ATOMIC_LOAD_MAX: case ISD::ATOMIC_LOAD_UMIN: - case ISD::ATOMIC_LOAD_UMAX: { + case ISD::ATOMIC_LOAD_UMAX: + case ISD::ATOMIC_LOAD: + case ISD::ATOMIC_STORE: { const AtomicSDNode *AT = cast(N); ID.AddInteger(AT->getMemoryVT().getRawBits()); ID.AddInteger(AT->getRawSubclassData()); @@ -769,11 +771,14 @@ static void VerifyNodeCommon(SDNode *N) { assert(N->getNumOperands() == N->getValueType(0).getVectorNumElements() && "Wrong number of operands!"); EVT EltVT = N->getValueType(0).getVectorElementType(); - for (SDNode::op_iterator I = N->op_begin(), E = N->op_end(); I != E; ++I) + for (SDNode::op_iterator I = N->op_begin(), E = N->op_end(); I != E; ++I) { assert((I->getValueType() == EltVT || (EltVT.isInteger() && I->getValueType().isInteger() && EltVT.bitsLE(I->getValueType()))) && "Wrong operand type!"); + assert(I->getValueType() == N->getOperand(0).getValueType() && + "Operands must all have the same type"); + } break; } } @@ -821,7 +826,7 @@ static void VerifyMachineNode(SDNode *N) { /// given type. /// unsigned SelectionDAG::getEVTAlignment(EVT VT) const { - const Type *Ty = VT == MVT::iPTR ? + Type *Ty = VT == MVT::iPTR ? PointerType::get(Type::getInt8Ty(*getContext()), 0) : VT.getTypeForEVT(*getContext()); @@ -876,6 +881,12 @@ void SelectionDAG::clear() { DbgInfo->clear(); } +SDValue SelectionDAG::getAnyExtOrTrunc(SDValue Op, DebugLoc DL, EVT VT) { + return VT.bitsGT(Op.getValueType()) ? + getNode(ISD::ANY_EXTEND, DL, VT, Op) : + getNode(ISD::TRUNCATE, DL, VT, Op); +} + SDValue SelectionDAG::getSExtOrTrunc(SDValue Op, DebugLoc DL, EVT VT) { return VT.bitsGT(Op.getValueType()) ? getNode(ISD::SIGN_EXTEND, DL, VT, Op) : @@ -925,13 +936,25 @@ SDValue SelectionDAG::getConstant(const ConstantInt &Val, EVT VT, bool isT) { assert(VT.isInteger() && "Cannot create FP integer constant!"); EVT EltVT = VT.getScalarType(); - assert(Val.getBitWidth() == EltVT.getSizeInBits() && - "APInt size does not match type size!"); + const ConstantInt *Elt = &Val; + // In some cases the vector type is legal but the element type is illegal and + // needs to be promoted, for example v8i8 on ARM. In this case, promote the + // inserted value (the type does not need to match the vector element type). + // Any extra bits introduced will be truncated away. + if (VT.isVector() && TLI.getTypeAction(*getContext(), EltVT) == + TargetLowering::TypePromoteInteger) { + EltVT = TLI.getTypeToTransformTo(*getContext(), EltVT); + APInt NewVal = Elt->getValue().zext(EltVT.getSizeInBits()); + Elt = ConstantInt::get(*getContext(), NewVal); + } + + assert(Elt->getBitWidth() == EltVT.getSizeInBits() && + "APInt size does not match type size!"); unsigned Opc = isT ? ISD::TargetConstant : ISD::Constant; FoldingSetNodeID ID; AddNodeIDNode(ID, Opc, getVTList(EltVT), 0, 0); - ID.AddPointer(&Val); + ID.AddPointer(Elt); void *IP = 0; SDNode *N = NULL; if ((N = CSEMap.FindNodeOrInsertPos(ID, IP))) @@ -939,7 +962,7 @@ SDValue SelectionDAG::getConstant(const ConstantInt &Val, EVT VT, bool isT) { return SDValue(N, 0); if (!N) { - N = new (NodeAllocator) ConstantSDNode(isT, &Val, EltVT); + N = new (NodeAllocator) ConstantSDNode(isT, Elt, EltVT); CSEMap.InsertNode(N, IP); AllNodes.push_back(N); } @@ -1131,7 +1154,7 @@ SDValue SelectionDAG::getConstantPool(MachineConstantPoolValue *C, EVT VT, AddNodeIDNode(ID, Opc, getVTList(VT), 0, 0); ID.AddInteger(Alignment); ID.AddInteger(Offset); - C->AddSelectionDAGCSEId(ID); + C->addSelectionDAGCSEId(ID); ID.AddInteger(TargetFlags); void *IP = 0; if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) @@ -1432,7 +1455,7 @@ SDValue SelectionDAG::getShiftAmountOperand(EVT LHSTy, SDValue Op) { SDValue SelectionDAG::CreateStackTemporary(EVT VT, unsigned minAlign) { MachineFrameInfo *FrameInfo = getMachineFunction().getFrameInfo(); unsigned ByteSize = VT.getStoreSize(); - const Type *Ty = VT.getTypeForEVT(*getContext()); + Type *Ty = VT.getTypeForEVT(*getContext()); unsigned StackAlign = std::max((unsigned)TLI.getTargetData()->getPrefTypeAlignment(Ty), minAlign); @@ -1445,8 +1468,8 @@ SDValue SelectionDAG::CreateStackTemporary(EVT VT, unsigned minAlign) { SDValue SelectionDAG::CreateStackTemporary(EVT VT1, EVT VT2) { unsigned Bytes = std::max(VT1.getStoreSizeInBits(), VT2.getStoreSizeInBits())/8; - const Type *Ty1 = VT1.getTypeForEVT(*getContext()); - const Type *Ty2 = VT2.getTypeForEVT(*getContext()); + Type *Ty1 = VT1.getTypeForEVT(*getContext()); + Type *Ty2 = VT2.getTypeForEVT(*getContext()); const TargetData *TD = TLI.getTargetData(); unsigned Align = std::max(TD->getPrefTypeAlignment(Ty1), TD->getPrefTypeAlignment(Ty2)); @@ -1718,8 +1741,8 @@ void SelectionDAG::ComputeMaskedBits(SDValue Op, const APInt &Mask, // The boolean result conforms to getBooleanContents. Fall through. case ISD::SETCC: // If we know the result of a setcc has the top bits zero, use this info. - if (TLI.getBooleanContents() == TargetLowering::ZeroOrOneBooleanContent && - BitWidth > 1) + if (TLI.getBooleanContents(Op.getValueType().isVector()) == + TargetLowering::ZeroOrOneBooleanContent && BitWidth > 1) KnownZero |= APInt::getHighBitsSet(BitWidth, BitWidth - 1); return; case ISD::SHL: @@ -2153,7 +2176,7 @@ unsigned SelectionDAG::ComputeNumSignBits(SDValue Op, unsigned Depth) const{ // The boolean result conforms to getBooleanContents. Fall through. case ISD::SETCC: // If setcc returns 0/-1, all bits are sign bits. - if (TLI.getBooleanContents() == + if (TLI.getBooleanContents(Op.getValueType().isVector()) == TargetLowering::ZeroOrNegativeOneBooleanContent) return VTBits; break; @@ -2437,7 +2460,7 @@ SDValue SelectionDAG::getNode(unsigned Opcode, DebugLoc DL, APFloat::rmTowardZero, &ignored); if (s==APFloat::opInvalidOp) // inexact is OK, in fact usual break; - APInt api(VT.getSizeInBits(), 2, x); + APInt api(VT.getSizeInBits(), x); return getConstant(api, VT); } case ISD::BITCAST: @@ -2777,6 +2800,7 @@ SDValue SelectionDAG::getNode(unsigned Opcode, DebugLoc DL, EVT VT, EVT.getVectorNumElements() == VT.getVectorNumElements()) && "Vector element counts must match in FP_ROUND_INREG"); assert(EVT.bitsLE(VT) && "Not rounding down!"); + (void)EVT; if (cast(N2)->getVT() == VT) return N1; // Not actually rounding. break; } @@ -2884,6 +2908,7 @@ SDValue SelectionDAG::getNode(unsigned Opcode, DebugLoc DL, EVT VT, assert(N2C && (unsigned)N2C->getZExtValue() < 2 && "Bad EXTRACT_ELEMENT!"); assert(!N1.getValueType().isVector() && !VT.isVector() && (N1.getValueType().isInteger() == VT.isInteger()) && + N1.getValueType() != VT && "Wrong types for EXTRACT_ELEMENT!"); // EXTRACT_ELEMENT of BUILD_PAIR is often formed while legalize is expanding @@ -3425,7 +3450,7 @@ static SDValue getMemcpyLoadsAndStores(SelectionDAG &DAG, DebugLoc dl, return SDValue(); if (DstAlignCanChange) { - const Type *Ty = MemOps[0].getTypeForEVT(*DAG.getContext()); + Type *Ty = MemOps[0].getTypeForEVT(*DAG.getContext()); unsigned NewAlign = (unsigned) TLI.getTargetData()->getABITypeAlignment(Ty); if (NewAlign > Align) { // Give the stack frame object a larger alignment if needed. @@ -3514,7 +3539,7 @@ static SDValue getMemmoveLoadsAndStores(SelectionDAG &DAG, DebugLoc dl, return SDValue(); if (DstAlignCanChange) { - const Type *Ty = MemOps[0].getTypeForEVT(*DAG.getContext()); + Type *Ty = MemOps[0].getTypeForEVT(*DAG.getContext()); unsigned NewAlign = (unsigned) TLI.getTargetData()->getABITypeAlignment(Ty); if (NewAlign > Align) { // Give the stack frame object a larger alignment if needed. @@ -3589,7 +3614,7 @@ static SDValue getMemsetStores(SelectionDAG &DAG, DebugLoc dl, return SDValue(); if (DstAlignCanChange) { - const Type *Ty = MemOps[0].getTypeForEVT(*DAG.getContext()); + Type *Ty = MemOps[0].getTypeForEVT(*DAG.getContext()); unsigned NewAlign = (unsigned) TLI.getTargetData()->getABITypeAlignment(Ty); if (NewAlign > Align) { // Give the stack frame object a larger alignment if needed. @@ -3782,7 +3807,7 @@ SDValue SelectionDAG::getMemset(SDValue Chain, DebugLoc dl, SDValue Dst, return Result; // Emit a library call. - const Type *IntPtrTy = TLI.getTargetData()->getIntPtrType(*getContext()); + Type *IntPtrTy = TLI.getTargetData()->getIntPtrType(*getContext()); TargetLowering::ArgListTy Args; TargetLowering::ArgListEntry Entry; Entry.Node = Dst; Entry.Ty = IntPtrTy; @@ -3815,7 +3840,9 @@ SDValue SelectionDAG::getMemset(SDValue Chain, DebugLoc dl, SDValue Dst, SDValue SelectionDAG::getAtomic(unsigned Opcode, DebugLoc dl, EVT MemVT, SDValue Chain, SDValue Ptr, SDValue Cmp, SDValue Swp, MachinePointerInfo PtrInfo, - unsigned Alignment) { + unsigned Alignment, + AtomicOrdering Ordering, + SynchronizationScope SynchScope) { if (Alignment == 0) // Ensure that codegen never sees alignment 0 Alignment = getEVTAlignment(MemVT); @@ -3823,18 +3850,23 @@ SDValue SelectionDAG::getAtomic(unsigned Opcode, DebugLoc dl, EVT MemVT, unsigned Flags = MachineMemOperand::MOLoad | MachineMemOperand::MOStore; // For now, atomics are considered to be volatile always. + // FIXME: Volatile isn't really correct; we should keep track of atomic + // orderings in the memoperand. Flags |= MachineMemOperand::MOVolatile; MachineMemOperand *MMO = MF.getMachineMemOperand(PtrInfo, Flags, MemVT.getStoreSize(), Alignment); - return getAtomic(Opcode, dl, MemVT, Chain, Ptr, Cmp, Swp, MMO); + return getAtomic(Opcode, dl, MemVT, Chain, Ptr, Cmp, Swp, MMO, + Ordering, SynchScope); } SDValue SelectionDAG::getAtomic(unsigned Opcode, DebugLoc dl, EVT MemVT, SDValue Chain, SDValue Ptr, SDValue Cmp, - SDValue Swp, MachineMemOperand *MMO) { + SDValue Swp, MachineMemOperand *MMO, + AtomicOrdering Ordering, + SynchronizationScope SynchScope) { assert(Opcode == ISD::ATOMIC_CMP_SWAP && "Invalid Atomic Op"); assert(Cmp.getValueType() == Swp.getValueType() && "Invalid Atomic Op Types"); @@ -3851,7 +3883,8 @@ SDValue SelectionDAG::getAtomic(unsigned Opcode, DebugLoc dl, EVT MemVT, return SDValue(E, 0); } SDNode *N = new (NodeAllocator) AtomicSDNode(Opcode, dl, VTs, MemVT, Chain, - Ptr, Cmp, Swp, MMO); + Ptr, Cmp, Swp, MMO, Ordering, + SynchScope); CSEMap.InsertNode(N, IP); AllNodes.push_back(N); return SDValue(N, 0); @@ -3861,27 +3894,39 @@ SDValue SelectionDAG::getAtomic(unsigned Opcode, DebugLoc dl, EVT MemVT, SDValue Chain, SDValue Ptr, SDValue Val, const Value* PtrVal, - unsigned Alignment) { + unsigned Alignment, + AtomicOrdering Ordering, + SynchronizationScope SynchScope) { if (Alignment == 0) // Ensure that codegen never sees alignment 0 Alignment = getEVTAlignment(MemVT); MachineFunction &MF = getMachineFunction(); - unsigned Flags = MachineMemOperand::MOLoad | MachineMemOperand::MOStore; + // A monotonic store does not load; a release store "loads" in the sense + // that other stores cannot be sunk past it. + // (An atomicrmw obviously both loads and stores.) + unsigned Flags = MachineMemOperand::MOStore; + if (Opcode != ISD::ATOMIC_STORE || Ordering > Monotonic) + Flags |= MachineMemOperand::MOLoad; // For now, atomics are considered to be volatile always. + // FIXME: Volatile isn't really correct; we should keep track of atomic + // orderings in the memoperand. Flags |= MachineMemOperand::MOVolatile; MachineMemOperand *MMO = MF.getMachineMemOperand(MachinePointerInfo(PtrVal), Flags, MemVT.getStoreSize(), Alignment); - return getAtomic(Opcode, dl, MemVT, Chain, Ptr, Val, MMO); + return getAtomic(Opcode, dl, MemVT, Chain, Ptr, Val, MMO, + Ordering, SynchScope); } SDValue SelectionDAG::getAtomic(unsigned Opcode, DebugLoc dl, EVT MemVT, SDValue Chain, SDValue Ptr, SDValue Val, - MachineMemOperand *MMO) { + MachineMemOperand *MMO, + AtomicOrdering Ordering, + SynchronizationScope SynchScope) { assert((Opcode == ISD::ATOMIC_LOAD_ADD || Opcode == ISD::ATOMIC_LOAD_SUB || Opcode == ISD::ATOMIC_LOAD_AND || @@ -3892,12 +3937,14 @@ SDValue SelectionDAG::getAtomic(unsigned Opcode, DebugLoc dl, EVT MemVT, Opcode == ISD::ATOMIC_LOAD_MAX || Opcode == ISD::ATOMIC_LOAD_UMIN || Opcode == ISD::ATOMIC_LOAD_UMAX || - Opcode == ISD::ATOMIC_SWAP) && + Opcode == ISD::ATOMIC_SWAP || + Opcode == ISD::ATOMIC_STORE) && "Invalid Atomic Op"); EVT VT = Val.getValueType(); - SDVTList VTs = getVTList(VT, MVT::Other); + SDVTList VTs = Opcode == ISD::ATOMIC_STORE ? getVTList(MVT::Other) : + getVTList(VT, MVT::Other); FoldingSetNodeID ID; ID.AddInteger(MemVT.getRawBits()); SDValue Ops[] = {Chain, Ptr, Val}; @@ -3908,7 +3955,63 @@ SDValue SelectionDAG::getAtomic(unsigned Opcode, DebugLoc dl, EVT MemVT, return SDValue(E, 0); } SDNode *N = new (NodeAllocator) AtomicSDNode(Opcode, dl, VTs, MemVT, Chain, - Ptr, Val, MMO); + Ptr, Val, MMO, + Ordering, SynchScope); + CSEMap.InsertNode(N, IP); + AllNodes.push_back(N); + return SDValue(N, 0); +} + +SDValue SelectionDAG::getAtomic(unsigned Opcode, DebugLoc dl, EVT MemVT, + EVT VT, SDValue Chain, + SDValue Ptr, + const Value* PtrVal, + unsigned Alignment, + AtomicOrdering Ordering, + SynchronizationScope SynchScope) { + if (Alignment == 0) // Ensure that codegen never sees alignment 0 + Alignment = getEVTAlignment(MemVT); + + MachineFunction &MF = getMachineFunction(); + // A monotonic load does not store; an acquire load "stores" in the sense + // that other loads cannot be hoisted past it. + unsigned Flags = MachineMemOperand::MOLoad; + if (Ordering > Monotonic) + Flags |= MachineMemOperand::MOStore; + + // For now, atomics are considered to be volatile always. + // FIXME: Volatile isn't really correct; we should keep track of atomic + // orderings in the memoperand. + Flags |= MachineMemOperand::MOVolatile; + + MachineMemOperand *MMO = + MF.getMachineMemOperand(MachinePointerInfo(PtrVal), Flags, + MemVT.getStoreSize(), Alignment); + + return getAtomic(Opcode, dl, MemVT, VT, Chain, Ptr, MMO, + Ordering, SynchScope); +} + +SDValue SelectionDAG::getAtomic(unsigned Opcode, DebugLoc dl, EVT MemVT, + EVT VT, SDValue Chain, + SDValue Ptr, + MachineMemOperand *MMO, + AtomicOrdering Ordering, + SynchronizationScope SynchScope) { + assert(Opcode == ISD::ATOMIC_LOAD && "Invalid Atomic Op"); + + SDVTList VTs = getVTList(VT, MVT::Other); + FoldingSetNodeID ID; + ID.AddInteger(MemVT.getRawBits()); + SDValue Ops[] = {Chain, Ptr}; + AddNodeIDNode(ID, Opcode, VTs, Ops, 2); + void* IP = 0; + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { + cast(E)->refineAlignment(MMO); + return SDValue(E, 0); + } + SDNode *N = new (NodeAllocator) AtomicSDNode(Opcode, dl, VTs, MemVT, Chain, + Ptr, MMO, Ordering, SynchScope); CSEMap.InsertNode(N, IP); AllNodes.push_back(N); return SDValue(N, 0); @@ -5769,6 +5872,7 @@ std::string SDNode::getOperationName(const SelectionDAG *G) const { #endif case ISD::PREFETCH: return "Prefetch"; case ISD::MEMBARRIER: return "MemBarrier"; + case ISD::ATOMIC_FENCE: return "AtomicFence"; case ISD::ATOMIC_CMP_SWAP: return "AtomicCmpSwap"; case ISD::ATOMIC_SWAP: return "AtomicSwap"; case ISD::ATOMIC_LOAD_ADD: return "AtomicLoadAdd"; @@ -5781,6 +5885,8 @@ std::string SDNode::getOperationName(const SelectionDAG *G) const { case ISD::ATOMIC_LOAD_MAX: return "AtomicLoadMax"; case ISD::ATOMIC_LOAD_UMIN: return "AtomicLoadUMin"; case ISD::ATOMIC_LOAD_UMAX: return "AtomicLoadUMax"; + case ISD::ATOMIC_LOAD: return "AtomicLoad"; + case ISD::ATOMIC_STORE: return "AtomicStore"; case ISD::PCMARKER: return "PCMarker"; case ISD::READCYCLECOUNTER: return "ReadCycleCounter"; case ISD::SRCVALUE: return "SrcValue"; @@ -5896,8 +6002,8 @@ std::string SDNode::getOperationName(const SelectionDAG *G) const { case ISD::FPOWI: return "fpowi"; case ISD::SETCC: return "setcc"; - case ISD::VSETCC: return "vsetcc"; case ISD::SELECT: return "select"; + case ISD::VSELECT: return "vselect"; case ISD::SELECT_CC: return "select_cc"; case ISD::INSERT_VECTOR_ELT: return "insert_vector_elt"; case ISD::EXTRACT_VECTOR_ELT: return "extract_vector_elt"; @@ -5985,7 +6091,8 @@ std::string SDNode::getOperationName(const SelectionDAG *G) const { case ISD::CTLZ: return "ctlz"; // Trampolines - case ISD::TRAMPOLINE: return "trampoline"; + case ISD::INIT_TRAMPOLINE: return "init_trampoline"; + case ISD::ADJUST_TRAMPOLINE: return "adjust_trampoline"; case ISD::CONDCODE: switch (cast(this)->get()) { @@ -6245,8 +6352,7 @@ void SDNode::print(raw_ostream &OS, const SelectionDAG *G) const { static void printrWithDepthHelper(raw_ostream &OS, const SDNode *N, const SelectionDAG *G, unsigned depth, - unsigned indent) -{ + unsigned indent) { if (depth == 0) return; @@ -6340,6 +6446,10 @@ SDValue SelectionDAG::UnrollVectorOp(SDNode *N, unsigned ResNE) { Scalars.push_back(getNode(N->getOpcode(), dl, EltVT, &Operands[0], Operands.size())); break; + case ISD::VSELECT: + Scalars.push_back(getNode(ISD::SELECT, dl, EltVT, + &Operands[0], Operands.size())); + break; case ISD::SHL: case ISD::SRA: case ISD::SRL: @@ -6427,6 +6537,8 @@ unsigned SelectionDAG::InferPtrAlignment(SDValue Ptr) const { Align = TD->getPreferredAlignment(GVar); } } + if (!Align) + Align = TLI.getTargetData()->getABITypeAlignment(GV->getType()); } return MinAlign(Align, GVOffset); } @@ -6528,7 +6640,7 @@ unsigned GlobalAddressSDNode::getAddressSpace() const { } -const Type *ConstantPoolSDNode::getType() const { +Type *ConstantPoolSDNode::getType() const { if (isMachineConstantPoolEntry()) return Val.MachineCPVal->getType(); return Val.ConstVal->getType(); diff --git a/contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index 81b03ee76..7ed46a695 100644 --- a/contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -578,7 +578,7 @@ namespace { : ValueVTs(1, valuevt), RegVTs(1, regvt), Regs(regs) {} RegsForValue(LLVMContext &Context, const TargetLowering &tli, - unsigned Reg, const Type *Ty) { + unsigned Reg, Type *Ty) { ComputeValueVTs(tli, Ty, ValueVTs); for (unsigned Value = 0, e = ValueVTs.size(); Value != e; ++Value) { @@ -788,6 +788,18 @@ void RegsForValue::AddInlineAsmOperands(unsigned Code, bool HasMatching, unsigned Flag = InlineAsm::getFlagWord(Code, Regs.size()); if (HasMatching) Flag = InlineAsm::getFlagWordForMatchingOp(Flag, MatchingIdx); + else if (!Regs.empty() && + TargetRegisterInfo::isVirtualRegister(Regs.front())) { + // Put the register class of the virtual registers in the flag word. That + // way, later passes can recompute register class constraints for inline + // assembly as well as normal instructions. + // Don't do this for tied operands that can use the regclass information + // from the def. + const MachineRegisterInfo &MRI = DAG.getMachineFunction().getRegInfo(); + const TargetRegisterClass *RC = MRI.getRegClass(Regs.front()); + Flag = InlineAsm::getFlagWordForRegClass(Flag, RC->getID()); + } + SDValue Res = DAG.getTargetConstant(Flag, MVT::i32); Ops.push_back(Res); @@ -805,6 +817,7 @@ void SelectionDAGBuilder::init(GCFunctionInfo *gfi, AliasAnalysis &aa) { AA = &aa; GFI = gfi; TD = DAG.getTarget().getTargetData(); + LPadToCallSiteMap.clear(); } /// clear - Clear out the current SelectionDAG and the associated @@ -956,7 +969,7 @@ void SelectionDAGBuilder::resolveDanglingDebugInfo(const Value *V, } } -// getValue - Return an SDValue for the given Value. +/// getValue - Return an SDValue for the given Value. SDValue SelectionDAGBuilder::getValue(const Value *V) { // If we already have an SDValue for this value, use it. It's important // to do this first, so that we don't create a CopyFromReg if we already @@ -971,7 +984,7 @@ SDValue SelectionDAGBuilder::getValue(const Value *V) { unsigned InReg = It->second; RegsForValue RFV(*DAG.getContext(), TLI, InReg, V->getType()); SDValue Chain = DAG.getEntryNode(); - N = RFV.getCopyFromRegs(DAG, FuncInfo, getCurDebugLoc(), Chain,NULL); + N = RFV.getCopyFromRegs(DAG, FuncInfo, getCurDebugLoc(), Chain, NULL); resolveDanglingDebugInfo(V, N); return N; } @@ -1069,7 +1082,7 @@ SDValue SelectionDAGBuilder::getValueImpl(const Value *V) { if (const BlockAddress *BA = dyn_cast(C)) return DAG.getBlockAddress(BA, VT); - const VectorType *VecTy = cast(V->getType()); + VectorType *VecTy = cast(V->getType()); unsigned NumElements = VecTy->getNumElements(); // Now that we know the number and type of the elements, get that number of @@ -1277,15 +1290,17 @@ uint32_t SelectionDAGBuilder::getEdgeWeight(MachineBasicBlock *Src, BranchProbabilityInfo *BPI = FuncInfo.BPI; if (!BPI) return 0; - BasicBlock *SrcBB = const_cast(Src->getBasicBlock()); - BasicBlock *DstBB = const_cast(Dst->getBasicBlock()); + const BasicBlock *SrcBB = Src->getBasicBlock(); + const BasicBlock *DstBB = Dst->getBasicBlock(); return BPI->getEdgeWeight(SrcBB, DstBB); } -void SelectionDAGBuilder::addSuccessorWithWeight(MachineBasicBlock *Src, - MachineBasicBlock *Dst) { - uint32_t weight = getEdgeWeight(Src, Dst); - Src->addSuccessor(Dst, weight); +void SelectionDAGBuilder:: +addSuccessorWithWeight(MachineBasicBlock *Src, MachineBasicBlock *Dst, + uint32_t Weight /* = 0 */) { + if (!Weight) + Weight = getEdgeWeight(Src, Dst); + Src->addSuccessor(Dst, Weight); } @@ -1558,8 +1573,8 @@ void SelectionDAGBuilder::visitSwitchCase(CaseBlock &CB, } // Update successor info - addSuccessorWithWeight(SwitchBB, CB.TrueBB); - addSuccessorWithWeight(SwitchBB, CB.FalseBB); + addSuccessorWithWeight(SwitchBB, CB.TrueBB, CB.TrueWeight); + addSuccessorWithWeight(SwitchBB, CB.FalseBB, CB.FalseWeight); // Set NextBlock to be the MBB immediately after the current one, if any. // This is used to avoid emitting unnecessary branches to the next block. @@ -1677,7 +1692,7 @@ void SelectionDAGBuilder::visitBitTestHeader(BitTestBlock &B, UsePtrType = true; else { for (unsigned i = 0, e = B.Cases.size(); i != e; ++i) - if ((uint64_t)((int64_t)B.Cases[i].Mask >> VT.getSizeInBits()) + 1 >= 2) { + if (!isUIntN(VT.getSizeInBits(), B.Cases[i].Mask)) { // Switch table case range are encoded into series of masks. // Just use pointer type, it's guaranteed to fit. UsePtrType = true; @@ -1808,6 +1823,49 @@ void SelectionDAGBuilder::visitInvoke(const InvokeInst &I) { void SelectionDAGBuilder::visitUnwind(const UnwindInst &I) { } +void SelectionDAGBuilder::visitResume(const ResumeInst &RI) { + llvm_unreachable("SelectionDAGBuilder shouldn't visit resume instructions!"); +} + +void SelectionDAGBuilder::visitLandingPad(const LandingPadInst &LP) { + assert(FuncInfo.MBB->isLandingPad() && + "Call to landingpad not in landing pad!"); + + MachineBasicBlock *MBB = FuncInfo.MBB; + MachineModuleInfo &MMI = DAG.getMachineFunction().getMMI(); + AddLandingPadInfo(LP, MMI, MBB); + + SmallVector ValueVTs; + ComputeValueVTs(TLI, LP.getType(), ValueVTs); + + // Insert the EXCEPTIONADDR instruction. + assert(FuncInfo.MBB->isLandingPad() && + "Call to eh.exception not in landing pad!"); + SDVTList VTs = DAG.getVTList(TLI.getPointerTy(), MVT::Other); + SDValue Ops[2]; + Ops[0] = DAG.getRoot(); + SDValue Op1 = DAG.getNode(ISD::EXCEPTIONADDR, getCurDebugLoc(), VTs, Ops, 1); + SDValue Chain = Op1.getValue(1); + + // Insert the EHSELECTION instruction. + VTs = DAG.getVTList(TLI.getPointerTy(), MVT::Other); + Ops[0] = Op1; + Ops[1] = Chain; + SDValue Op2 = DAG.getNode(ISD::EHSELECTION, getCurDebugLoc(), VTs, Ops, 2); + Chain = Op2.getValue(1); + Op2 = DAG.getSExtOrTrunc(Op2, getCurDebugLoc(), MVT::i32); + + Ops[0] = Op1; + Ops[1] = Op2; + SDValue Res = DAG.getNode(ISD::MERGE_VALUES, getCurDebugLoc(), + DAG.getVTList(&ValueVTs[0], ValueVTs.size()), + &Ops[0], 2); + + std::pair RetPair = std::make_pair(Res, Chain); + setValue(&LP, RetPair.first); + DAG.setRoot(RetPair.second); +} + /// handleSmallSwitchCaseRange - Emit a series of specific tests (suitable for /// small case ranges). bool SelectionDAGBuilder::handleSmallSwitchRange(CaseRec& CR, @@ -1866,8 +1924,8 @@ bool SelectionDAGBuilder::handleSmallSwitchRange(CaseRec& CR, ISD::SETEQ); // Update successor info. - SwitchBB->addSuccessor(Small.BB); - SwitchBB->addSuccessor(Default); + addSuccessorWithWeight(SwitchBB, Small.BB); + addSuccessorWithWeight(SwitchBB, Default); // Insert the true branch. SDValue BrCond = DAG.getNode(ISD::BRCOND, DL, MVT::Other, @@ -1923,7 +1981,11 @@ bool SelectionDAGBuilder::handleSmallSwitchRange(CaseRec& CR, CC = ISD::SETLE; LHS = I->Low; MHS = SV; RHS = I->High; } - CaseBlock CB(CC, LHS, RHS, MHS, I->BB, FallThrough, CurBlock); + + uint32_t ExtraWeight = I->ExtraWeight; + CaseBlock CB(CC, LHS, RHS, MHS, /* truebb */ I->BB, /* falsebb */ FallThrough, + /* me */ CurBlock, + /* trueweight */ ExtraWeight / 2, /* falseweight */ ExtraWeight / 2); // If emitting the first comparison, just call visitSwitchCase to emit the // code into the current block. Otherwise, push the CaseBlock onto the @@ -1953,10 +2015,10 @@ static APInt ComputeRange(const APInt &First, const APInt &Last) { } /// handleJTSwitchCase - Emit jumptable for current switch case range -bool SelectionDAGBuilder::handleJTSwitchCase(CaseRec& CR, - CaseRecVector& WorkList, - const Value* SV, - MachineBasicBlock* Default, +bool SelectionDAGBuilder::handleJTSwitchCase(CaseRec &CR, + CaseRecVector &WorkList, + const Value *SV, + MachineBasicBlock *Default, MachineBasicBlock *SwitchBB) { Case& FrontCase = *CR.Range.first; Case& BackCase = *(CR.Range.second-1); @@ -1965,8 +2027,7 @@ bool SelectionDAGBuilder::handleJTSwitchCase(CaseRec& CR, const APInt &Last = cast(BackCase.High)->getValue(); APInt TSize(First.getBitWidth(), 0); - for (CaseItr I = CR.Range.first, E = CR.Range.second; - I!=E; ++I) + for (CaseItr I = CR.Range.first, E = CR.Range.second; I != E; ++I) TSize += I->size(); if (!areJTsAllowed(TLI) || TSize.ult(4)) @@ -2044,7 +2105,6 @@ bool SelectionDAGBuilder::handleJTSwitchCase(CaseRec& CR, visitJumpTableHeader(JT, JTH, SwitchBB); JTCases.push_back(JumpTableBlock(JTH, JT)); - return true; } @@ -2318,12 +2378,17 @@ size_t SelectionDAGBuilder::Clusterify(CaseVector& Cases, const SwitchInst& SI) { size_t numCmps = 0; + BranchProbabilityInfo *BPI = FuncInfo.BPI; // Start with "simple" cases for (size_t i = 1; i < SI.getNumSuccessors(); ++i) { - MachineBasicBlock *SMBB = FuncInfo.MBBMap[SI.getSuccessor(i)]; + BasicBlock *SuccBB = SI.getSuccessor(i); + MachineBasicBlock *SMBB = FuncInfo.MBBMap[SuccBB]; + + uint32_t ExtraWeight = BPI ? BPI->getEdgeWeight(SI.getParent(), SuccBB) : 0; + Cases.push_back(Case(SI.getSuccessorValue(i), SI.getSuccessorValue(i), - SMBB)); + SMBB, ExtraWeight)); } std::sort(Cases.begin(), Cases.end(), CaseCmp()); @@ -2343,6 +2408,16 @@ size_t SelectionDAGBuilder::Clusterify(CaseVector& Cases, if ((nextValue - currentValue == 1) && (currentBB == nextBB)) { I->High = J->High; J = Cases.erase(J); + + if (BranchProbabilityInfo *BPI = FuncInfo.BPI) { + uint32_t CurWeight = currentBB->getBasicBlock() ? + BPI->getEdgeWeight(SI.getParent(), currentBB->getBasicBlock()) : 16; + uint32_t NextWeight = nextBB->getBasicBlock() ? + BPI->getEdgeWeight(SI.getParent(), nextBB->getBasicBlock()) : 16; + + BPI->setEdgeWeight(SI.getParent(), currentBB->getBasicBlock(), + CurWeight + NextWeight); + } } else { I = J++; } @@ -2379,7 +2454,7 @@ void SelectionDAGBuilder::visitSwitch(const SwitchInst &SI) { // If there is only the default destination, branch to it if it is not the // next basic block. Otherwise, just fall through. - if (SI.getNumOperands() == 2) { + if (SI.getNumCases() == 1) { // Update machine-CFG edges. // If this is not a fall-through branch, emit the branch. @@ -2399,12 +2474,12 @@ void SelectionDAGBuilder::visitSwitch(const SwitchInst &SI) { size_t numCmps = Clusterify(Cases, SI); DEBUG(dbgs() << "Clusterify finished. Total clusters: " << Cases.size() << ". Total compares: " << numCmps << '\n'); - numCmps = 0; + (void)numCmps; // Get the Value to be switched on and default basic blocks, which will be // inserted into CaseBlock records, representing basic blocks in the binary // search tree. - const Value *SV = SI.getOperand(0); + const Value *SV = SI.getCondition(); // Push the initial CaseRec onto the worklist CaseRecVector WorkList; @@ -2458,7 +2533,7 @@ void SelectionDAGBuilder::visitIndirectBr(const IndirectBrInst &I) { void SelectionDAGBuilder::visitFSub(const User &I) { // -0.0 - X --> fneg - const Type *Ty = I.getType(); + Type *Ty = I.getType(); if (isa(I.getOperand(0)) && I.getOperand(0) == ConstantFP::getZeroValueForNegation(Ty)) { SDValue Op2 = getValue(I.getOperand(1)); @@ -2562,10 +2637,12 @@ void SelectionDAGBuilder::visitSelect(const User &I) { SDValue Cond = getValue(I.getOperand(0)); SDValue TrueVal = getValue(I.getOperand(1)); SDValue FalseVal = getValue(I.getOperand(2)); + ISD::NodeType OpCode = Cond.getValueType().isVector() ? + ISD::VSELECT : ISD::SELECT; for (unsigned i = 0; i != NumValues; ++i) - Values[i] = DAG.getNode(ISD::SELECT, getCurDebugLoc(), - TrueVal.getNode()->getValueType(TrueVal.getResNo()+i), + Values[i] = DAG.getNode(OpCode, getCurDebugLoc(), + TrueVal.getNode()->getValueType(TrueVal.getResNo()+i), Cond, SDValue(TrueVal.getNode(), TrueVal.getResNo() + i), @@ -2778,7 +2855,8 @@ void SelectionDAGBuilder::visitShuffleVector(const User &I) { // Analyze the access pattern of the vector to see if we can extract // two subvectors and do the shuffle. The analysis is done by calculating // the range of elements the mask access on both vectors. - int MinRange[2] = { SrcNumElts+1, SrcNumElts+1}; + int MinRange[2] = { static_cast(SrcNumElts+1), + static_cast(SrcNumElts+1)}; int MaxRange[2] = {-1, -1}; for (unsigned i = 0; i != MaskNumElts; ++i) { @@ -2886,8 +2964,8 @@ void SelectionDAGBuilder::visitShuffleVector(const User &I) { void SelectionDAGBuilder::visitInsertValue(const InsertValueInst &I) { const Value *Op0 = I.getOperand(0); const Value *Op1 = I.getOperand(1); - const Type *AggTy = I.getType(); - const Type *ValTy = Op1->getType(); + Type *AggTy = I.getType(); + Type *ValTy = Op1->getType(); bool IntoUndef = isa(Op0); bool FromUndef = isa(Op1); @@ -2927,8 +3005,8 @@ void SelectionDAGBuilder::visitInsertValue(const InsertValueInst &I) { void SelectionDAGBuilder::visitExtractValue(const ExtractValueInst &I) { const Value *Op0 = I.getOperand(0); - const Type *AggTy = Op0->getType(); - const Type *ValTy = I.getType(); + Type *AggTy = Op0->getType(); + Type *ValTy = I.getType(); bool OutOfUndef = isa(Op0); unsigned LinearIndex = ComputeLinearIndex(AggTy, I.getIndices()); @@ -2961,12 +3039,12 @@ void SelectionDAGBuilder::visitExtractValue(const ExtractValueInst &I) { void SelectionDAGBuilder::visitGetElementPtr(const User &I) { SDValue N = getValue(I.getOperand(0)); - const Type *Ty = I.getOperand(0)->getType(); + Type *Ty = I.getOperand(0)->getType(); for (GetElementPtrInst::const_op_iterator OI = I.op_begin()+1, E = I.op_end(); OI != E; ++OI) { const Value *Idx = *OI; - if (const StructType *StTy = dyn_cast(Ty)) { + if (StructType *StTy = dyn_cast(Ty)) { unsigned Field = cast(Idx)->getZExtValue(); if (Field) { // N = N + Offset @@ -3037,7 +3115,7 @@ void SelectionDAGBuilder::visitAlloca(const AllocaInst &I) { if (FuncInfo.StaticAllocaMap.count(&I)) return; // getValue will auto-populate this. - const Type *Ty = I.getAllocatedType(); + Type *Ty = I.getAllocatedType(); uint64_t TySize = TLI.getTargetData()->getTypeAllocSize(Ty); unsigned Align = std::max((unsigned)TLI.getTargetData()->getPrefTypeAlignment(Ty), @@ -3084,10 +3162,13 @@ void SelectionDAGBuilder::visitAlloca(const AllocaInst &I) { } void SelectionDAGBuilder::visitLoad(const LoadInst &I) { + if (I.isAtomic()) + return visitAtomicLoad(I); + const Value *SV = I.getOperand(0); SDValue Ptr = getValue(SV); - const Type *Ty = I.getType(); + Type *Ty = I.getType(); bool isVolatile = I.isVolatile(); bool isNonTemporal = I.getMetadata("nontemporal") != 0; @@ -3161,6 +3242,9 @@ void SelectionDAGBuilder::visitLoad(const LoadInst &I) { } void SelectionDAGBuilder::visitStore(const StoreInst &I) { + if (I.isAtomic()) + return visitAtomicStore(I); + const Value *SrcV = I.getOperand(0); const Value *PtrV = I.getOperand(1); @@ -3211,6 +3295,179 @@ void SelectionDAGBuilder::visitStore(const StoreInst &I) { DAG.setRoot(StoreNode); } +static SDValue InsertFenceForAtomic(SDValue Chain, AtomicOrdering Order, + SynchronizationScope Scope, + bool Before, DebugLoc dl, + SelectionDAG &DAG, + const TargetLowering &TLI) { + // Fence, if necessary + if (Before) { + if (Order == AcquireRelease || Order == SequentiallyConsistent) + Order = Release; + else if (Order == Acquire || Order == Monotonic) + return Chain; + } else { + if (Order == AcquireRelease) + Order = Acquire; + else if (Order == Release || Order == Monotonic) + return Chain; + } + SDValue Ops[3]; + Ops[0] = Chain; + Ops[1] = DAG.getConstant(Order, TLI.getPointerTy()); + Ops[2] = DAG.getConstant(Scope, TLI.getPointerTy()); + return DAG.getNode(ISD::ATOMIC_FENCE, dl, MVT::Other, Ops, 3); +} + +void SelectionDAGBuilder::visitAtomicCmpXchg(const AtomicCmpXchgInst &I) { + DebugLoc dl = getCurDebugLoc(); + AtomicOrdering Order = I.getOrdering(); + SynchronizationScope Scope = I.getSynchScope(); + + SDValue InChain = getRoot(); + + if (TLI.getInsertFencesForAtomic()) + InChain = InsertFenceForAtomic(InChain, Order, Scope, true, dl, + DAG, TLI); + + SDValue L = + DAG.getAtomic(ISD::ATOMIC_CMP_SWAP, dl, + getValue(I.getCompareOperand()).getValueType().getSimpleVT(), + InChain, + getValue(I.getPointerOperand()), + getValue(I.getCompareOperand()), + getValue(I.getNewValOperand()), + MachinePointerInfo(I.getPointerOperand()), 0 /* Alignment */, + TLI.getInsertFencesForAtomic() ? Monotonic : Order, + Scope); + + SDValue OutChain = L.getValue(1); + + if (TLI.getInsertFencesForAtomic()) + OutChain = InsertFenceForAtomic(OutChain, Order, Scope, false, dl, + DAG, TLI); + + setValue(&I, L); + DAG.setRoot(OutChain); +} + +void SelectionDAGBuilder::visitAtomicRMW(const AtomicRMWInst &I) { + DebugLoc dl = getCurDebugLoc(); + ISD::NodeType NT; + switch (I.getOperation()) { + default: llvm_unreachable("Unknown atomicrmw operation"); return; + case AtomicRMWInst::Xchg: NT = ISD::ATOMIC_SWAP; break; + case AtomicRMWInst::Add: NT = ISD::ATOMIC_LOAD_ADD; break; + case AtomicRMWInst::Sub: NT = ISD::ATOMIC_LOAD_SUB; break; + case AtomicRMWInst::And: NT = ISD::ATOMIC_LOAD_AND; break; + case AtomicRMWInst::Nand: NT = ISD::ATOMIC_LOAD_NAND; break; + case AtomicRMWInst::Or: NT = ISD::ATOMIC_LOAD_OR; break; + case AtomicRMWInst::Xor: NT = ISD::ATOMIC_LOAD_XOR; break; + case AtomicRMWInst::Max: NT = ISD::ATOMIC_LOAD_MAX; break; + case AtomicRMWInst::Min: NT = ISD::ATOMIC_LOAD_MIN; break; + case AtomicRMWInst::UMax: NT = ISD::ATOMIC_LOAD_UMAX; break; + case AtomicRMWInst::UMin: NT = ISD::ATOMIC_LOAD_UMIN; break; + } + AtomicOrdering Order = I.getOrdering(); + SynchronizationScope Scope = I.getSynchScope(); + + SDValue InChain = getRoot(); + + if (TLI.getInsertFencesForAtomic()) + InChain = InsertFenceForAtomic(InChain, Order, Scope, true, dl, + DAG, TLI); + + SDValue L = + DAG.getAtomic(NT, dl, + getValue(I.getValOperand()).getValueType().getSimpleVT(), + InChain, + getValue(I.getPointerOperand()), + getValue(I.getValOperand()), + I.getPointerOperand(), 0 /* Alignment */, + TLI.getInsertFencesForAtomic() ? Monotonic : Order, + Scope); + + SDValue OutChain = L.getValue(1); + + if (TLI.getInsertFencesForAtomic()) + OutChain = InsertFenceForAtomic(OutChain, Order, Scope, false, dl, + DAG, TLI); + + setValue(&I, L); + DAG.setRoot(OutChain); +} + +void SelectionDAGBuilder::visitFence(const FenceInst &I) { + DebugLoc dl = getCurDebugLoc(); + SDValue Ops[3]; + Ops[0] = getRoot(); + Ops[1] = DAG.getConstant(I.getOrdering(), TLI.getPointerTy()); + Ops[2] = DAG.getConstant(I.getSynchScope(), TLI.getPointerTy()); + DAG.setRoot(DAG.getNode(ISD::ATOMIC_FENCE, dl, MVT::Other, Ops, 3)); +} + +void SelectionDAGBuilder::visitAtomicLoad(const LoadInst &I) { + DebugLoc dl = getCurDebugLoc(); + AtomicOrdering Order = I.getOrdering(); + SynchronizationScope Scope = I.getSynchScope(); + + SDValue InChain = getRoot(); + + EVT VT = EVT::getEVT(I.getType()); + + if (I.getAlignment() * 8 < VT.getSizeInBits()) + report_fatal_error("Cannot generate unaligned atomic load"); + + SDValue L = + DAG.getAtomic(ISD::ATOMIC_LOAD, dl, VT, VT, InChain, + getValue(I.getPointerOperand()), + I.getPointerOperand(), I.getAlignment(), + TLI.getInsertFencesForAtomic() ? Monotonic : Order, + Scope); + + SDValue OutChain = L.getValue(1); + + if (TLI.getInsertFencesForAtomic()) + OutChain = InsertFenceForAtomic(OutChain, Order, Scope, false, dl, + DAG, TLI); + + setValue(&I, L); + DAG.setRoot(OutChain); +} + +void SelectionDAGBuilder::visitAtomicStore(const StoreInst &I) { + DebugLoc dl = getCurDebugLoc(); + + AtomicOrdering Order = I.getOrdering(); + SynchronizationScope Scope = I.getSynchScope(); + + SDValue InChain = getRoot(); + + EVT VT = EVT::getEVT(I.getValueOperand()->getType()); + + if (I.getAlignment() * 8 < VT.getSizeInBits()) + report_fatal_error("Cannot generate unaligned atomic store"); + + if (TLI.getInsertFencesForAtomic()) + InChain = InsertFenceForAtomic(InChain, Order, Scope, true, dl, + DAG, TLI); + + SDValue OutChain = + DAG.getAtomic(ISD::ATOMIC_STORE, dl, VT, + InChain, + getValue(I.getPointerOperand()), + getValue(I.getValueOperand()), + I.getPointerOperand(), I.getAlignment(), + TLI.getInsertFencesForAtomic() ? Monotonic : Order, + Scope); + + if (TLI.getInsertFencesForAtomic()) + OutChain = InsertFenceForAtomic(OutChain, Order, Scope, false, dl, + DAG, TLI); + + DAG.setRoot(OutChain); +} + /// visitTargetIntrinsic - Lower a call of a target intrinsic to an INTRINSIC /// node. void SelectionDAGBuilder::visitTargetIntrinsic(const CallInst &I, @@ -3290,7 +3547,7 @@ void SelectionDAGBuilder::visitTargetIntrinsic(const CallInst &I, } if (!I.getType()->isVoidTy()) { - if (const VectorType *PTy = dyn_cast(I.getType())) { + if (VectorType *PTy = dyn_cast(I.getType())) { EVT VT = TLI.getValueType(PTy); Result = DAG.getNode(ISD::BITCAST, getCurDebugLoc(), VT, Result); } @@ -3337,25 +3594,6 @@ getF32Constant(SelectionDAG &DAG, unsigned Flt) { return DAG.getConstantFP(APFloat(APInt(32, Flt)), MVT::f32); } -/// Inlined utility function to implement binary input atomic intrinsics for -/// visitIntrinsicCall: I is a call instruction -/// Op is the associated NodeType for I -const char * -SelectionDAGBuilder::implVisitBinaryAtomic(const CallInst& I, - ISD::NodeType Op) { - SDValue Root = getRoot(); - SDValue L = - DAG.getAtomic(Op, getCurDebugLoc(), - getValue(I.getArgOperand(1)).getValueType().getSimpleVT(), - Root, - getValue(I.getArgOperand(0)), - getValue(I.getArgOperand(1)), - I.getArgOperand(0)); - setValue(&I, L); - DAG.setRoot(L.getValue(1)); - return 0; -} - // implVisitAluOverflow - Lower arithmetic overflow instrinsics. const char * SelectionDAGBuilder::implVisitAluOverflow(const CallInst &I, ISD::NodeType Op) { @@ -4154,17 +4392,12 @@ SelectionDAGBuilder::EmitFuncArgumentDbgValue(const Value *V, MDNode *Variable, return false; unsigned Reg = 0; - if (Arg->hasByValAttr()) { - // Byval arguments' frame index is recorded during argument lowering. - // Use this info directly. - Reg = TRI->getFrameRegister(MF); - Offset = FuncInfo.getByValArgumentFrameIndex(Arg); - // If byval argument ofset is not recorded then ignore this. - if (!Offset) - Reg = 0; - } + // Some arguments' frame index is recorded during argument lowering. + Offset = FuncInfo.getArgumentFrameIndex(Arg); + if (Offset) + Reg = TRI->getFrameRegister(MF); - if (N.getNode()) { + if (!Reg && N.getNode()) { if (N.getOpcode() == ISD::CopyFromReg) Reg = cast(N.getOperand(1))->getReg(); else @@ -4295,7 +4528,7 @@ SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, unsigned Intrinsic) { const DbgDeclareInst &DI = cast(I); MDNode *Variable = DI.getVariable(); const Value *Address = DI.getAddress(); - if (!Address || !DIVariable(DI.getVariable()).Verify()) + if (!Address || !DIVariable(Variable).Verify()) return 0; // Build an entry in DbgOrdering. Debug info input nodes get an SDNodeOrder @@ -4385,7 +4618,7 @@ SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, unsigned Intrinsic) { // debug info exists. ++SDNodeOrder; SDDbgValue *SDV; - if (isa(V) || isa(V)) { + if (isa(V) || isa(V) || isa(V)) { SDV = DAG.getDbgValue(Variable, V, Offset, dl, SDNodeOrder); DAG.AddDbgValue(SDV, 0, false); } else { @@ -4514,9 +4747,24 @@ SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, unsigned Intrinsic) { MMI.setCurrentCallSite(CI->getZExtValue()); return 0; } + case Intrinsic::eh_sjlj_functioncontext: { + // Get and store the index of the function context. + MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo(); + AllocaInst *FnCtx = + cast(I.getArgOperand(0)->stripPointerCasts()); + int FI = FuncInfo.StaticAllocaMap[FnCtx]; + MFI->setFunctionContextIndex(FI); + return 0; + } case Intrinsic::eh_sjlj_setjmp: { - setValue(&I, DAG.getNode(ISD::EH_SJLJ_SETJMP, dl, MVT::i32, getRoot(), - getValue(I.getArgOperand(0)))); + SDValue Ops[2]; + Ops[0] = getRoot(); + Ops[1] = getValue(I.getArgOperand(0)); + SDValue Op = DAG.getNode(ISD::EH_SJLJ_SETJMP, dl, + DAG.getVTList(MVT::i32, MVT::Other), + Ops, 2); + setValue(&I, Op.getValue(0)); + DAG.setRoot(Op.getValue(1)); return 0; } case Intrinsic::eh_sjlj_longjmp: { @@ -4778,12 +5026,15 @@ SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, unsigned Intrinsic) { Ops[4] = DAG.getSrcValue(I.getArgOperand(0)); Ops[5] = DAG.getSrcValue(F); - Res = DAG.getNode(ISD::TRAMPOLINE, dl, - DAG.getVTList(TLI.getPointerTy(), MVT::Other), - Ops, 6); + Res = DAG.getNode(ISD::INIT_TRAMPOLINE, dl, MVT::Other, Ops, 6); - setValue(&I, Res); - DAG.setRoot(Res.getValue(1)); + DAG.setRoot(Res); + return 0; + } + case Intrinsic::adjust_trampoline: { + setValue(&I, DAG.getNode(ISD::ADJUST_TRAMPOLINE, dl, + TLI.getPointerTy(), + getValue(I.getArgOperand(0)))); return 0; } case Intrinsic::gcroot: @@ -4857,51 +5108,6 @@ SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, unsigned Intrinsic) { rw==1)); /* write */ return 0; } - case Intrinsic::memory_barrier: { - SDValue Ops[6]; - Ops[0] = getRoot(); - for (int x = 1; x < 6; ++x) - Ops[x] = getValue(I.getArgOperand(x - 1)); - - DAG.setRoot(DAG.getNode(ISD::MEMBARRIER, dl, MVT::Other, &Ops[0], 6)); - return 0; - } - case Intrinsic::atomic_cmp_swap: { - SDValue Root = getRoot(); - SDValue L = - DAG.getAtomic(ISD::ATOMIC_CMP_SWAP, getCurDebugLoc(), - getValue(I.getArgOperand(1)).getValueType().getSimpleVT(), - Root, - getValue(I.getArgOperand(0)), - getValue(I.getArgOperand(1)), - getValue(I.getArgOperand(2)), - MachinePointerInfo(I.getArgOperand(0))); - setValue(&I, L); - DAG.setRoot(L.getValue(1)); - return 0; - } - case Intrinsic::atomic_load_add: - return implVisitBinaryAtomic(I, ISD::ATOMIC_LOAD_ADD); - case Intrinsic::atomic_load_sub: - return implVisitBinaryAtomic(I, ISD::ATOMIC_LOAD_SUB); - case Intrinsic::atomic_load_or: - return implVisitBinaryAtomic(I, ISD::ATOMIC_LOAD_OR); - case Intrinsic::atomic_load_xor: - return implVisitBinaryAtomic(I, ISD::ATOMIC_LOAD_XOR); - case Intrinsic::atomic_load_and: - return implVisitBinaryAtomic(I, ISD::ATOMIC_LOAD_AND); - case Intrinsic::atomic_load_nand: - return implVisitBinaryAtomic(I, ISD::ATOMIC_LOAD_NAND); - case Intrinsic::atomic_load_max: - return implVisitBinaryAtomic(I, ISD::ATOMIC_LOAD_MAX); - case Intrinsic::atomic_load_min: - return implVisitBinaryAtomic(I, ISD::ATOMIC_LOAD_MIN); - case Intrinsic::atomic_load_umin: - return implVisitBinaryAtomic(I, ISD::ATOMIC_LOAD_UMIN); - case Intrinsic::atomic_load_umax: - return implVisitBinaryAtomic(I, ISD::ATOMIC_LOAD_UMAX); - case Intrinsic::atomic_swap: - return implVisitBinaryAtomic(I, ISD::ATOMIC_SWAP); case Intrinsic::invariant_start: case Intrinsic::lifetime_start: @@ -4918,9 +5124,9 @@ SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, unsigned Intrinsic) { void SelectionDAGBuilder::LowerCallTo(ImmutableCallSite CS, SDValue Callee, bool isTailCall, MachineBasicBlock *LandingPad) { - const PointerType *PT = cast(CS.getCalledValue()->getType()); - const FunctionType *FTy = cast(PT->getElementType()); - const Type *RetTy = FTy->getReturnType(); + PointerType *PT = cast(CS.getCalledValue()->getType()); + FunctionType *FTy = cast(PT->getElementType()); + Type *RetTy = FTy->getReturnType(); MachineModuleInfo &MMI = DAG.getMachineFunction().getMMI(); MCSymbol *BeginLabel = 0; @@ -4949,7 +5155,7 @@ void SelectionDAGBuilder::LowerCallTo(ImmutableCallSite CS, SDValue Callee, FTy->getReturnType()); MachineFunction &MF = DAG.getMachineFunction(); DemoteStackIdx = MF.getFrameInfo()->CreateStackObject(TySize, Align, false); - const Type *StackSlotPtrType = PointerType::getUnqual(FTy->getReturnType()); + Type *StackSlotPtrType = PointerType::getUnqual(FTy->getReturnType()); DemoteStackSlot = DAG.getFrameIndex(DemoteStackIdx, TLI.getPointerTy()); Entry.Node = DemoteStackSlot; @@ -4997,6 +5203,8 @@ void SelectionDAGBuilder::LowerCallTo(ImmutableCallSite CS, SDValue Callee, unsigned CallSiteIndex = MMI.getCurrentCallSite(); if (CallSiteIndex) { MMI.setCallSiteBeginLabel(BeginLabel, CallSiteIndex); + LPadToCallSiteMap[LandingPad].push_back(CallSiteIndex); + // Now that the call site is handled, stop tracking it. MMI.setCurrentCallSite(0); } @@ -5037,7 +5245,7 @@ void SelectionDAGBuilder::LowerCallTo(ImmutableCallSite CS, SDValue Callee, // The instruction result is the result of loading from the // hidden sret parameter. SmallVector PVTs; - const Type *PtrRetTy = PointerType::getUnqual(FTy->getReturnType()); + Type *PtrRetTy = PointerType::getUnqual(FTy->getReturnType()); ComputeValueVTs(TLI, PtrRetTy, PVTs); assert(PVTs.size() == 1 && "Pointers should fit in one register"); @@ -5130,7 +5338,7 @@ static bool IsOnlyUsedInZeroEqualityComparison(const Value *V) { } static SDValue getMemCmpLoad(const Value *PtrVal, MVT LoadVT, - const Type *LoadTy, + Type *LoadTy, SelectionDAGBuilder &Builder) { // Check to see if this load can be trivially constant folded, e.g. if the @@ -5193,7 +5401,7 @@ bool SelectionDAGBuilder::visitMemCmpCall(const CallInst &I) { if (Size && IsOnlyUsedInZeroEqualityComparison(&I)) { bool ActuallyDoIt = true; MVT LoadVT; - const Type *LoadTy; + Type *LoadTy; switch (Size->getZExtValue()) { default: LoadVT = MVT::Other; @@ -5261,14 +5469,14 @@ void SelectionDAGBuilder::visitCall(const CallInst &I) { // See if any floating point values are being passed to this function. This is // used to emit an undefined reference to fltused on Windows. - const FunctionType *FT = + FunctionType *FT = cast(I.getCalledValue()->getType()->getContainedType(0)); MachineModuleInfo &MMI = DAG.getMachineFunction().getMMI(); if (FT->isVarArg() && !MMI.callsExternalVAFunctionWithFloatingPointArguments()) { for (unsigned i = 0, e = I.getNumArgOperands(); i != e; ++i) { - const Type* T = I.getArgOperand(i)->getType(); - for (po_iterator i = po_begin(T), e = po_end(T); + Type* T = I.getArgOperand(i)->getType(); + for (po_iterator i = po_begin(T), e = po_end(T); i != e; ++i) { if (!i->isFloatingPointTy()) continue; MMI.setCallsExternalVAFunctionWithFloatingPointArguments(true); @@ -5412,20 +5620,20 @@ public: if (isa(CallOperandVal)) return TLI.getPointerTy(); - const llvm::Type *OpTy = CallOperandVal->getType(); + llvm::Type *OpTy = CallOperandVal->getType(); // FIXME: code duplicated from TargetLowering::ParseConstraints(). // If this is an indirect operand, the operand is a pointer to the // accessed type. if (isIndirect) { - const llvm::PointerType *PtrTy = dyn_cast(OpTy); + llvm::PointerType *PtrTy = dyn_cast(OpTy); if (!PtrTy) report_fatal_error("Indirect operand for inline asm not a pointer!"); OpTy = PtrTy->getElementType(); } // Look for vector wrapped in a struct. e.g. { <16 x i8> }. - if (const StructType *STy = dyn_cast(OpTy)) + if (StructType *STy = dyn_cast(OpTy)) if (STy->getNumElements() == 1) OpTy = STy->getElementType(0); @@ -5637,9 +5845,8 @@ void SelectionDAGBuilder::visitInlineAsm(ImmutableCallSite CS) { // The return value of the call is this value. As such, there is no // corresponding argument. - assert(!CS.getType()->isVoidTy() && - "Bad inline asm!"); - if (const StructType *STy = dyn_cast(CS.getType())) { + assert(!CS.getType()->isVoidTy() && "Bad inline asm!"); + if (StructType *STy = dyn_cast(CS.getType())) { OpVT = TLI.getValueType(STy->getElementType(ResNo)); } else { assert(ResNo == 0 && "Asm only has one result!"); @@ -5707,9 +5914,11 @@ void SelectionDAGBuilder::visitInlineAsm(ImmutableCallSite CS) { if (OpInfo.ConstraintVT != Input.ConstraintVT) { std::pair MatchRC = - TLI.getRegForInlineAsmConstraint(OpInfo.ConstraintCode, OpInfo.ConstraintVT); + TLI.getRegForInlineAsmConstraint(OpInfo.ConstraintCode, + OpInfo.ConstraintVT); std::pair InputRC = - TLI.getRegForInlineAsmConstraint(Input.ConstraintCode, Input.ConstraintVT); + TLI.getRegForInlineAsmConstraint(Input.ConstraintCode, + Input.ConstraintVT); if ((OpInfo.ConstraintVT.isInteger() != Input.ConstraintVT.isInteger()) || (MatchRC.second != InputRC.second)) { @@ -5750,7 +5959,7 @@ void SelectionDAGBuilder::visitInlineAsm(ImmutableCallSite CS) { } else { // Otherwise, create a stack slot and emit a store to it before the // asm. - const Type *Ty = OpVal->getType(); + Type *Ty = OpVal->getType(); uint64_t TySize = TLI.getTargetData()->getTypeAllocSize(Ty); unsigned Align = TLI.getTargetData()->getPrefTypeAlignment(Ty); MachineFunction &MF = DAG.getMachineFunction(); @@ -6111,7 +6320,7 @@ void SelectionDAGBuilder::visitVACopy(const CallInst &I) { /// FIXME: When all targets are /// migrated to using LowerCall, this hook should be integrated into SDISel. std::pair -TargetLowering::LowerCallTo(SDValue Chain, const Type *RetTy, +TargetLowering::LowerCallTo(SDValue Chain, Type *RetTy, bool RetSExt, bool RetZExt, bool isVarArg, bool isInreg, unsigned NumFixedArgs, CallingConv::ID CallConv, bool isTailCall, @@ -6128,7 +6337,7 @@ TargetLowering::LowerCallTo(SDValue Chain, const Type *RetTy, for (unsigned Value = 0, NumValues = ValueVTs.size(); Value != NumValues; ++Value) { EVT VT = ValueVTs[Value]; - const Type *ArgTy = VT.getTypeForEVT(RetTy->getContext()); + Type *ArgTy = VT.getTypeForEVT(RetTy->getContext()); SDValue Op = SDValue(Args[i].Node.getNode(), Args[i].Node.getResNo() + Value); ISD::ArgFlagsTy Flags; @@ -6145,8 +6354,8 @@ TargetLowering::LowerCallTo(SDValue Chain, const Type *RetTy, Flags.setSRet(); if (Args[i].isByVal) { Flags.setByVal(); - const PointerType *Ty = cast(Args[i].Ty); - const Type *ElementTy = Ty->getElementType(); + PointerType *Ty = cast(Args[i].Ty); + Type *ElementTy = Ty->getElementType(); Flags.setByValSize(getTargetData()->getTypeAllocSize(ElementTy)); // For ByVal, alignment should come from FE. BE will guess if this // info is not there but there are cases it cannot get right. @@ -6356,7 +6565,7 @@ void SelectionDAGISel::LowerArguments(const BasicBlock *LLVMBB) { for (unsigned Value = 0, NumValues = ValueVTs.size(); Value != NumValues; ++Value) { EVT VT = ValueVTs[Value]; - const Type *ArgTy = VT.getTypeForEVT(*DAG.getContext()); + Type *ArgTy = VT.getTypeForEVT(*DAG.getContext()); ISD::ArgFlagsTy Flags; unsigned OriginalAlignment = TD->getABITypeAlignment(ArgTy); @@ -6371,8 +6580,8 @@ void SelectionDAGISel::LowerArguments(const BasicBlock *LLVMBB) { Flags.setSRet(); if (F.paramHasAttr(Idx, Attribute::ByVal)) { Flags.setByVal(); - const PointerType *Ty = cast(I->getType()); - const Type *ElementTy = Ty->getElementType(); + PointerType *Ty = cast(I->getType()); + Type *ElementTy = Ty->getElementType(); Flags.setByValSize(TD->getTypeAllocSize(ElementTy)); // For ByVal, alignment should be passed from FE. BE will guess if // this info is not there but there are cases it cannot get right. @@ -6487,15 +6696,22 @@ void SelectionDAGISel::LowerArguments(const BasicBlock *LLVMBB) { if (ArgValues.empty()) continue; - // Note down frame index for byval arguments. - if (I->hasByValAttr()) - if (FrameIndexSDNode *FI = - dyn_cast(ArgValues[0].getNode())) - FuncInfo->setByValArgumentFrameIndex(I, FI->getIndex()); + // Note down frame index. + if (FrameIndexSDNode *FI = + dyn_cast(ArgValues[0].getNode())) + FuncInfo->setArgumentFrameIndex(I, FI->getIndex()); SDValue Res = DAG.getMergeValues(&ArgValues[0], NumValues, SDB->getCurDebugLoc()); + SDB->setValue(I, Res); + if (!EnableFastISel && Res.getOpcode() == ISD::BUILD_PAIR) { + if (LoadSDNode *LNode = + dyn_cast(Res.getOperand(0).getNode())) + if (FrameIndexSDNode *FI = + dyn_cast(LNode->getBasePtr().getNode())) + FuncInfo->setArgumentFrameIndex(I, FI->getIndex()); + } // If this argument is live outside of the entry block, insert a copy from // wherever we got it to the vreg that other BB's will reference it as. diff --git a/contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h b/contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h index a0884ebf5..0a21ca347 100644 --- a/contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h +++ b/contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h @@ -132,10 +132,13 @@ private: Constant* Low; Constant* High; MachineBasicBlock* BB; + uint32_t ExtraWeight; + + Case() : Low(0), High(0), BB(0), ExtraWeight(0) { } + Case(Constant* low, Constant* high, MachineBasicBlock* bb, + uint32_t extraweight) : Low(low), High(high), BB(bb), + ExtraWeight(extraweight) { } - Case() : Low(0), High(0), BB(0) { } - Case(Constant* low, Constant* high, MachineBasicBlock* bb) : - Low(low), High(high), BB(bb) { } APInt size() const { const APInt &rHigh = cast(High)->getValue(); const APInt &rLow = cast(Low)->getValue(); @@ -203,20 +206,30 @@ private: CaseBlock(ISD::CondCode cc, const Value *cmplhs, const Value *cmprhs, const Value *cmpmiddle, MachineBasicBlock *truebb, MachineBasicBlock *falsebb, - MachineBasicBlock *me) + MachineBasicBlock *me, + uint32_t trueweight = 0, uint32_t falseweight = 0) : CC(cc), CmpLHS(cmplhs), CmpMHS(cmpmiddle), CmpRHS(cmprhs), - TrueBB(truebb), FalseBB(falsebb), ThisBB(me) {} + TrueBB(truebb), FalseBB(falsebb), ThisBB(me), + TrueWeight(trueweight), FalseWeight(falseweight) { } + // CC - the condition code to use for the case block's setcc node ISD::CondCode CC; + // CmpLHS/CmpRHS/CmpMHS - The LHS/MHS/RHS of the comparison to emit. // Emit by default LHS op RHS. MHS is used for range comparisons: // If MHS is not null: (LHS <= MHS) and (MHS <= RHS). const Value *CmpLHS, *CmpMHS, *CmpRHS; + // TrueBB/FalseBB - the block to branch to if the setcc is true/false. MachineBasicBlock *TrueBB, *FalseBB; + // ThisBB - the block into which to emit the code for the setcc and branches MachineBasicBlock *ThisBB; + + // TrueWeight/FalseWeight - branch weights. + uint32_t TrueWeight, FalseWeight; }; + struct JumpTable { JumpTable(unsigned R, unsigned J, MachineBasicBlock *M, MachineBasicBlock *D): Reg(R), JTI(J), MBB(M), Default(D) {} @@ -307,6 +320,9 @@ public: /// GFI - Garbage collection metadata for the function. GCFunctionInfo *GFI; + /// LPadToCallSiteMap - Map a landing pad to the call site indexes. + DenseMap > LPadToCallSiteMap; + /// HasTailCall - This is set to true if a call in the current /// block has been translated as a tail call. In this case, /// no subsequent DAG nodes should be created. @@ -436,7 +452,8 @@ private: MachineBasicBlock *SwitchBB); uint32_t getEdgeWeight(MachineBasicBlock *Src, MachineBasicBlock *Dst); - void addSuccessorWithWeight(MachineBasicBlock *Src, MachineBasicBlock *Dst); + void addSuccessorWithWeight(MachineBasicBlock *Src, MachineBasicBlock *Dst, + uint32_t Weight = 0); public: void visitSwitchCase(CaseBlock &CB, MachineBasicBlock *SwitchBB); @@ -453,6 +470,7 @@ public: private: // These all get lowered before this pass. void visitInvoke(const InvokeInst &I); + void visitResume(const ResumeInst &I); void visitUnwind(const UnwindInst &I); void visitBinary(const User &I, unsigned OpCode); @@ -497,6 +515,7 @@ private: void visitExtractValue(const ExtractValueInst &I); void visitInsertValue(const InsertValueInst &I); + void visitLandingPad(const LandingPadInst &I); void visitGetElementPtr(const User &I); void visitSelect(const User &I); @@ -504,10 +523,15 @@ private: void visitAlloca(const AllocaInst &I); void visitLoad(const LoadInst &I); void visitStore(const StoreInst &I); + void visitAtomicCmpXchg(const AtomicCmpXchgInst &I); + void visitAtomicRMW(const AtomicRMWInst &I); + void visitFence(const FenceInst &I); void visitPHI(const PHINode &I); void visitCall(const CallInst &I); bool visitMemCmpCall(const CallInst &I); - + void visitAtomicLoad(const LoadInst &I); + void visitAtomicStore(const StoreInst &I); + void visitInlineAsm(ImmutableCallSite CS); const char *visitIntrinsicCall(const CallInst &I, unsigned Intrinsic); void visitTargetIntrinsic(const CallInst &I, unsigned Intrinsic); @@ -531,7 +555,6 @@ private: llvm_unreachable("UserOp2 should not exist at instruction selection time!"); } - const char *implVisitBinaryAtomic(const CallInst& I, ISD::NodeType Op); const char *implVisitAluOverflow(const CallInst &I, ISD::NodeType Op); void HandlePHINodesInSuccessorBlocks(const BasicBlock *LLVMBB); diff --git a/contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index 87bb296b8..68b9146ad 100644 --- a/contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/contrib/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -177,6 +177,13 @@ TargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, return 0; } +void TargetLowering::AdjustInstrPostInstrSelection(MachineInstr *MI, + SDNode *Node) const { + assert(!MI->getDesc().hasPostISelHook() && + "If a target marks an instruction with 'hasPostISelHook', " + "it must implement TargetLowering::AdjustInstrPostInstrSelection!"); +} + //===----------------------------------------------------------------------===// // SelectionDAGISel code //===----------------------------------------------------------------------===// @@ -463,6 +470,7 @@ void SelectionDAGISel::CodeGenAndEmitDAG() { GroupName = "Instruction Selection and Scheduling"; std::string BlockName; int BlockNumber = -1; + (void)BlockNumber; #ifdef NDEBUG if (ViewDAGCombine1 || ViewLegalizeTypesDAGs || ViewLegalizeDAGs || ViewDAGCombine2 || ViewDAGCombineLT || ViewISelDAGs || ViewSchedDAGs || @@ -677,21 +685,26 @@ void SelectionDAGISel::DoInstructionSelection() { /// PrepareEHLandingPad - Emit an EH_LABEL, set up live-in registers, and /// do other setup for EH landing-pad blocks. void SelectionDAGISel::PrepareEHLandingPad() { + MachineBasicBlock *MBB = FuncInfo->MBB; + // Add a label to mark the beginning of the landing pad. Deletion of the // landing pad can thus be detected via the MachineModuleInfo. - MCSymbol *Label = MF->getMMI().addLandingPad(FuncInfo->MBB); + MCSymbol *Label = MF->getMMI().addLandingPad(MBB); + // Assign the call site to the landing pad's begin label. + MF->getMMI().setCallSiteLandingPad(Label, SDB->LPadToCallSiteMap[MBB]); + const MCInstrDesc &II = TM.getInstrInfo()->get(TargetOpcode::EH_LABEL); - BuildMI(*FuncInfo->MBB, FuncInfo->InsertPt, SDB->getCurDebugLoc(), II) + BuildMI(*MBB, FuncInfo->InsertPt, SDB->getCurDebugLoc(), II) .addSym(Label); // Mark exception register as live in. unsigned Reg = TLI.getExceptionAddressRegister(); - if (Reg) FuncInfo->MBB->addLiveIn(Reg); + if (Reg) MBB->addLiveIn(Reg); // Mark exception selector register as live in. Reg = TLI.getExceptionSelectorRegister(); - if (Reg) FuncInfo->MBB->addLiveIn(Reg); + if (Reg) MBB->addLiveIn(Reg); // FIXME: Hack around an exception handling flaw (PR1508): the personality // function and list of typeids logically belong to the invoke (or, if you @@ -704,7 +717,7 @@ void SelectionDAGISel::PrepareEHLandingPad() { // in exceptions not being caught because no typeids are associated with // the invoke. This may not be the only way things can go wrong, but it // is the only way we try to work around for the moment. - const BasicBlock *LLVMBB = FuncInfo->MBB->getBasicBlock(); + const BasicBlock *LLVMBB = MBB->getBasicBlock(); const BranchInst *Br = dyn_cast(LLVMBB->getTerminator()); if (Br && Br->isUnconditional()) { // Critical edge? @@ -719,8 +732,6 @@ void SelectionDAGISel::PrepareEHLandingPad() { } } - - /// TryToFoldFastISelLoad - We're checking to see if we can fold the specified /// load into the specified FoldInst. Note that we could have a sequence where /// multiple LLVM IR instructions are folded into the same machineinstr. For @@ -741,7 +752,7 @@ bool SelectionDAGISel::TryToFoldFastISelLoad(const LoadInst *LI, // isn't one of the folded instructions, then we can't succeed here. Handle // this by scanning the single-use users of the load until we get to FoldInst. unsigned MaxUsers = 6; // Don't scan down huge single-use chains of instrs. - + const Instruction *TheUser = LI->use_back(); while (TheUser != FoldInst && // Scan up until we find FoldInst. // Stay in the right block. @@ -750,10 +761,15 @@ bool SelectionDAGISel::TryToFoldFastISelLoad(const LoadInst *LI, // If there are multiple or no uses of this instruction, then bail out. if (!TheUser->hasOneUse()) return false; - + TheUser = TheUser->use_back(); } - + + // If we didn't find the fold instruction, then we failed to collapse the + // sequence. + if (TheUser != FoldInst) + return false; + // Don't try to fold volatile loads. Target has to deal with alignment // constraints. if (LI->isVolatile()) return false; @@ -802,6 +818,7 @@ static bool isFoldedOrDeadInstruction(const Instruction *I, return !I->mayWriteToMemory() && // Side-effecting instructions aren't folded. !isa(I) && // Terminators aren't folded. !isa(I) && // Debug instructions aren't folded. + !isa(I) && // Landingpad instructions aren't folded. !FuncInfo->isExportedInst(I); // Exported instrs must be computed. } diff --git a/contrib/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/contrib/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp index 2626ac3bb..907d8d9da 100644 --- a/contrib/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ b/contrib/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -317,7 +317,7 @@ static void InitLibcallNames(const char **Names) { Names[RTLIB::SYNC_FETCH_AND_OR_8] = "__sync_fetch_and_or_8"; Names[RTLIB::SYNC_FETCH_AND_XOR_1] = "__sync_fetch_and_xor_1"; Names[RTLIB::SYNC_FETCH_AND_XOR_2] = "__sync_fetch_and_xor_2"; - Names[RTLIB::SYNC_FETCH_AND_XOR_4] = "__sync_fetch_and-xor_4"; + Names[RTLIB::SYNC_FETCH_AND_XOR_4] = "__sync_fetch_and_xor_4"; Names[RTLIB::SYNC_FETCH_AND_XOR_8] = "__sync_fetch_and_xor_8"; Names[RTLIB::SYNC_FETCH_AND_NAND_1] = "__sync_fetch_and_nand_1"; Names[RTLIB::SYNC_FETCH_AND_NAND_2] = "__sync_fetch_and_nand_2"; @@ -609,6 +609,7 @@ TargetLowering::TargetLowering(const TargetMachine &tm, ExceptionPointerRegister = 0; ExceptionSelectorRegister = 0; BooleanContents = UndefinedBooleanContent; + BooleanVectorContents = UndefinedBooleanContent; SchedPreferenceInfo = Sched::Latency; JumpBufSize = 0; JumpBufAlignment = 0; @@ -617,6 +618,7 @@ TargetLowering::TargetLowering(const TargetMachine &tm, PrefLoopAlignment = 0; MinStackArgumentAlignment = 1; ShouldFoldAtomicFences = false; + InsertFencesForAtomic = false; InitLibcallNames(LibcallRoutineNames); InitCmpLibcallCCs(CmpLibcallCCs); @@ -914,7 +916,8 @@ const char *TargetLowering::getTargetNodeName(unsigned Opcode) const { } -MVT::SimpleValueType TargetLowering::getSetCCResultType(EVT VT) const { +EVT TargetLowering::getSetCCResultType(EVT VT) const { + assert(!VT.isVector() && "No default SetCC type for vectors!"); return PointerTy.SimpleTy; } @@ -996,7 +999,7 @@ unsigned TargetLowering::getVectorTypeBreakdown(LLVMContext &Context, EVT VT, /// type of the given function. This does not require a DAG or a return value, /// and is suitable for use before any DAGs for the function are constructed. /// TODO: Move this out of TargetLowering.cpp. -void llvm::GetReturnInfo(const Type* ReturnType, Attributes attr, +void llvm::GetReturnInfo(Type* ReturnType, Attributes attr, SmallVectorImpl &Outs, const TargetLowering &TLI, SmallVectorImpl *Offsets) { @@ -1054,7 +1057,7 @@ void llvm::GetReturnInfo(const Type* ReturnType, Attributes attr, /// getByValTypeAlignment - Return the desired alignment for ByVal aggregate /// function arguments in the caller parameter area. This is the actual /// alignment, not its logarithm. -unsigned TargetLowering::getByValTypeAlignment(const Type *Ty) const { +unsigned TargetLowering::getByValTypeAlignment(Type *Ty) const { return TD->getCallFrameTypeAlignment(Ty); } @@ -1764,17 +1767,16 @@ bool TargetLowering::SimplifyDemandedBits(SDValue Op, break; } case ISD::AssertZext: { - // Demand all the bits of the input that are demanded in the output. - // The low bits are obvious; the high bits are demanded because we're - // asserting that they're zero here. - if (SimplifyDemandedBits(Op.getOperand(0), NewMask, + // AssertZext demands all of the high bits, plus any of the low bits + // demanded by its users. + EVT VT = cast(Op.getOperand(1))->getVT(); + APInt InMask = APInt::getLowBitsSet(BitWidth, + VT.getSizeInBits()); + if (SimplifyDemandedBits(Op.getOperand(0), ~InMask | NewMask, KnownZero, KnownOne, TLO, Depth+1)) return true; assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); - EVT VT = cast(Op.getOperand(1))->getVT(); - APInt InMask = APInt::getLowBitsSet(BitWidth, - VT.getSizeInBits()); KnownZero |= ~InMask & NewMask; break; } @@ -2191,7 +2193,7 @@ TargetLowering::SimplifySetCC(EVT VT, SDValue N0, SDValue N1, } } else if (N1C->getAPIntValue() == 1 && (VT == MVT::i1 || - getBooleanContents() == ZeroOrOneBooleanContent)) { + getBooleanContents(false) == ZeroOrOneBooleanContent)) { SDValue Op0 = N0; if (Op0.getOpcode() == ISD::TRUNCATE) Op0 = Op0.getOperand(0); @@ -2758,16 +2760,8 @@ getRegForInlineAsmConstraint(const std::string &Constraint, // If none of the value types for this register class are valid, we // can't use it. For example, 64-bit reg classes on 32-bit targets. - bool isLegal = false; - for (TargetRegisterClass::vt_iterator I = RC->vt_begin(), E = RC->vt_end(); - I != E; ++I) { - if (isTypeLegal(*I)) { - isLegal = true; - break; - } - } - - if (!isLegal) continue; + if (!isLegalRC(RC)) + continue; for (TargetRegisterClass::iterator I = RC->begin(), E = RC->end(); I != E; ++I) { @@ -2840,7 +2834,7 @@ TargetLowering::AsmOperandInfoVector TargetLowering::ParseConstraints( // corresponding argument. assert(!CS.getType()->isVoidTy() && "Bad inline asm!"); - if (const StructType *STy = dyn_cast(CS.getType())) { + if (StructType *STy = dyn_cast(CS.getType())) { OpInfo.ConstraintVT = getValueType(STy->getElementType(ResNo)); } else { assert(ResNo == 0 && "Asm only has one result!"); @@ -2857,16 +2851,16 @@ TargetLowering::AsmOperandInfoVector TargetLowering::ParseConstraints( } if (OpInfo.CallOperandVal) { - const llvm::Type *OpTy = OpInfo.CallOperandVal->getType(); + llvm::Type *OpTy = OpInfo.CallOperandVal->getType(); if (OpInfo.isIndirect) { - const llvm::PointerType *PtrTy = dyn_cast(OpTy); + llvm::PointerType *PtrTy = dyn_cast(OpTy); if (!PtrTy) report_fatal_error("Indirect operand for inline asm not a pointer!"); OpTy = PtrTy->getElementType(); } // Look for vector wrapped in a struct. e.g. { <16 x i8> }. - if (const StructType *STy = dyn_cast(OpTy)) + if (StructType *STy = dyn_cast(OpTy)) if (STy->getNumElements() == 1) OpTy = STy->getElementType(0); @@ -3187,7 +3181,7 @@ void TargetLowering::ComputeConstraintToUse(AsmOperandInfo &OpInfo, /// isLegalAddressingMode - Return true if the addressing mode represented /// by AM is legal for this target, for a load/store of the specified type. bool TargetLowering::isLegalAddressingMode(const AddrMode &AM, - const Type *Ty) const { + Type *Ty) const { // The default implementation of this implements a conservative RISCy, r+r and // r+i addr mode. diff --git a/contrib/llvm/lib/CodeGen/ShadowStackGC.cpp b/contrib/llvm/lib/CodeGen/ShadowStackGC.cpp index 5a253a4d9..2609256c8 100644 --- a/contrib/llvm/lib/CodeGen/ShadowStackGC.cpp +++ b/contrib/llvm/lib/CodeGen/ShadowStackGC.cpp @@ -61,7 +61,7 @@ namespace { private: bool IsNullValue(Value *V); Constant *GetFrameMap(Function &F); - const Type* GetConcreteStackEntryType(Function &F); + Type* GetConcreteStackEntryType(Function &F); void CollectRoots(Function &F); static GetElementPtrInst *CreateGEP(LLVMContext &Context, IRBuilder<> &B, Value *BasePtr, @@ -109,13 +109,15 @@ namespace { State = 1; case 1: - // Find all 'return' and 'unwind' instructions. + // Find all 'return', 'resume', and 'unwind' instructions. while (StateBB != StateE) { BasicBlock *CurBB = StateBB++; - // Branches and invokes do not escape, only unwind and return do. + // Branches and invokes do not escape, only unwind, resume, and return + // do. TerminatorInst *TI = CurBB->getTerminator(); - if (!isa(TI) && !isa(TI)) + if (!isa(TI) && !isa(TI) && + !isa(TI)) continue; Builder.SetInsertPoint(TI->getParent(), TI); @@ -139,9 +141,19 @@ namespace { return 0; // Create a cleanup block. - BasicBlock *CleanupBB = BasicBlock::Create(F.getContext(), - CleanupBBName, &F); - UnwindInst *UI = new UnwindInst(F.getContext(), CleanupBB); + LLVMContext &C = F.getContext(); + BasicBlock *CleanupBB = BasicBlock::Create(C, CleanupBBName, &F); + Type *ExnTy = StructType::get(Type::getInt8PtrTy(C), + Type::getInt32Ty(C), NULL); + Constant *PersFn = + F.getParent()-> + getOrInsertFunction("__gcc_personality_v0", + FunctionType::get(Type::getInt32Ty(C), true)); + LandingPadInst *LPad = LandingPadInst::Create(ExnTy, PersFn, 1, + "cleanup.lpad", + CleanupBB); + LPad->setCleanup(true); + ResumeInst *RI = ResumeInst::Create(LPad, CleanupBB); // Transform the 'call' instructions into 'invoke's branching to the // cleanup block. Go in reverse order to make prettier BB names. @@ -172,7 +184,7 @@ namespace { delete CI; } - Builder.SetInsertPoint(UI->getParent(), UI); + Builder.SetInsertPoint(RI->getParent(), RI); return &Builder; } } @@ -190,7 +202,7 @@ ShadowStackGC::ShadowStackGC() : Head(0), StackEntryTy(0) { Constant *ShadowStackGC::GetFrameMap(Function &F) { // doInitialization creates the abstract type of this value. - const Type *VoidPtr = Type::getInt8PtrTy(F.getContext()); + Type *VoidPtr = Type::getInt8PtrTy(F.getContext()); // Truncate the ShadowStackDescriptor if some metadata is null. unsigned NumMeta = 0; @@ -203,7 +215,7 @@ Constant *ShadowStackGC::GetFrameMap(Function &F) { } Metadata.resize(NumMeta); - const Type *Int32Ty = Type::getInt32Ty(F.getContext()); + Type *Int32Ty = Type::getInt32Ty(F.getContext()); Constant *BaseElts[] = { ConstantInt::get(Int32Ty, Roots.size(), false), @@ -216,7 +228,7 @@ Constant *ShadowStackGC::GetFrameMap(Function &F) { }; Type *EltTys[] = { DescriptorElts[0]->getType(),DescriptorElts[1]->getType()}; - StructType *STy = StructType::createNamed("gc_map."+utostr(NumMeta), EltTys); + StructType *STy = StructType::create(EltTys, "gc_map."+utostr(NumMeta)); Constant *FrameMap = ConstantStruct::get(STy, DescriptorElts); @@ -241,17 +253,17 @@ Constant *ShadowStackGC::GetFrameMap(Function &F) { ConstantInt::get(Type::getInt32Ty(F.getContext()), 0), ConstantInt::get(Type::getInt32Ty(F.getContext()), 0) }; - return ConstantExpr::getGetElementPtr(GV, GEPIndices, 2); + return ConstantExpr::getGetElementPtr(GV, GEPIndices); } -const Type* ShadowStackGC::GetConcreteStackEntryType(Function &F) { +Type* ShadowStackGC::GetConcreteStackEntryType(Function &F) { // doInitialization creates the generic version of this type. std::vector EltTys; EltTys.push_back(StackEntryTy); for (size_t I = 0; I != Roots.size(); I++) EltTys.push_back(Roots[I].second->getAllocatedType()); - return StructType::createNamed("gc_stackentry."+F.getName().str(), EltTys); + return StructType::create(EltTys, "gc_stackentry."+F.getName().str()); } /// doInitialization - If this module uses the GC intrinsics, find them now. If @@ -267,7 +279,7 @@ bool ShadowStackGC::initializeCustomLowering(Module &M) { EltTys.push_back(Type::getInt32Ty(M.getContext())); // Specifies length of variable length array. EltTys.push_back(Type::getInt32Ty(M.getContext())); - FrameMapTy = StructType::createNamed("gc_map", EltTys); + FrameMapTy = StructType::create(EltTys, "gc_map"); PointerType *FrameMapPtrTy = PointerType::getUnqual(FrameMapTy); // struct StackEntry { @@ -276,13 +288,13 @@ bool ShadowStackGC::initializeCustomLowering(Module &M) { // void *Roots[]; // Stack roots (in-place array, so we pretend). // }; - StackEntryTy = StructType::createNamed(M.getContext(), "gc_stackentry"); + StackEntryTy = StructType::create(M.getContext(), "gc_stackentry"); EltTys.clear(); EltTys.push_back(PointerType::getUnqual(StackEntryTy)); EltTys.push_back(FrameMapPtrTy); StackEntryTy->setBody(EltTys); - const PointerType *StackEntryPtrTy = PointerType::getUnqual(StackEntryTy); + PointerType *StackEntryPtrTy = PointerType::getUnqual(StackEntryTy); // Get the root chain if it already exists. Head = M.getGlobalVariable("llvm_gc_root_chain"); @@ -340,7 +352,7 @@ ShadowStackGC::CreateGEP(LLVMContext &Context, IRBuilder<> &B, Value *BasePtr, Value *Indices[] = { ConstantInt::get(Type::getInt32Ty(Context), 0), ConstantInt::get(Type::getInt32Ty(Context), Idx), ConstantInt::get(Type::getInt32Ty(Context), Idx2) }; - Value* Val = B.CreateGEP(BasePtr, Indices, Indices + 3, Name); + Value* Val = B.CreateGEP(BasePtr, Indices, Name); assert(isa(Val) && "Unexpected folded constant"); @@ -352,7 +364,7 @@ ShadowStackGC::CreateGEP(LLVMContext &Context, IRBuilder<> &B, Value *BasePtr, int Idx, const char *Name) { Value *Indices[] = { ConstantInt::get(Type::getInt32Ty(Context), 0), ConstantInt::get(Type::getInt32Ty(Context), Idx) }; - Value *Val = B.CreateGEP(BasePtr, Indices, Indices + 2, Name); + Value *Val = B.CreateGEP(BasePtr, Indices, Name); assert(isa(Val) && "Unexpected folded constant"); @@ -373,7 +385,7 @@ bool ShadowStackGC::performCustomLowering(Function &F) { // Build the constant map and figure the type of the shadow stack entry. Value *FrameMap = GetFrameMap(F); - const Type *ConcreteStackEntryTy = GetConcreteStackEntryType(F); + Type *ConcreteStackEntryTy = GetConcreteStackEntryType(F); // Build the shadow stack entry at the very start of the function. BasicBlock::iterator IP = F.getEntryBlock().begin(); diff --git a/contrib/llvm/lib/CodeGen/SjLjEHPrepare.cpp b/contrib/llvm/lib/CodeGen/SjLjEHPrepare.cpp index 65a33da93..ded2459d4 100644 --- a/contrib/llvm/lib/CodeGen/SjLjEHPrepare.cpp +++ b/contrib/llvm/lib/CodeGen/SjLjEHPrepare.cpp @@ -21,26 +21,31 @@ #include "llvm/LLVMContext.h" #include "llvm/Module.h" #include "llvm/Pass.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/Statistic.h" #include "llvm/CodeGen/Passes.h" -#include "llvm/Support/Debug.h" +#include "llvm/Target/TargetData.h" #include "llvm/Target/TargetLowering.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h" #include "llvm/Transforms/Utils/Local.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/IRBuilder.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/Statistic.h" #include using namespace llvm; +static cl::opt DisableOldSjLjEH("disable-old-sjlj-eh", cl::Hidden, + cl::desc("Disable the old SjLj EH preparation pass")); + STATISTIC(NumInvokes, "Number of invokes replaced"); STATISTIC(NumUnwinds, "Number of unwinds replaced"); STATISTIC(NumSpilled, "Number of registers live across unwind edges"); namespace { class SjLjEHPass : public FunctionPass { - const TargetLowering *TLI; - - const Type *FunctionContextTy; + Type *FunctionContextTy; Constant *RegisterFn; Constant *UnregisterFn; Constant *BuiltinSetjmpFn; @@ -53,8 +58,9 @@ namespace { Constant *ExceptionFn; Constant *CallSiteFn; Constant *DispatchSetupFn; - + Constant *FuncCtxFn; Value *CallSite; + DenseMap LPadSuccMap; public: static char ID; // Pass identification, replacement for typeid explicit SjLjEHPass(const TargetLowering *tli = NULL) @@ -62,16 +68,22 @@ namespace { bool doInitialization(Module &M); bool runOnFunction(Function &F); - virtual void getAnalysisUsage(AnalysisUsage &AU) const { } + virtual void getAnalysisUsage(AnalysisUsage &AU) const {} const char *getPassName() const { return "SJLJ Exception Handling preparation"; } private: + bool setupEntryBlockAndCallSites(Function &F); + Value *setupFunctionContext(Function &F, ArrayRef LPads); + void lowerIncomingArguments(Function &F); + void lowerAcrossUnwindEdges(Function &F, ArrayRef Invokes); + void insertCallSiteStore(Instruction *I, int Number, Value *CallSite); void markInvokeCallSite(InvokeInst *II, int InvokeNo, Value *CallSite, SwitchInst *CatchSwitch); void splitLiveRangesAcrossInvokes(SmallVector &Invokes); + void splitLandingPad(InvokeInst *II); bool insertSjLjEHSupport(Function &F); }; } // end anonymous namespace @@ -116,6 +128,7 @@ bool SjLjEHPass::doInitialization(Module &M) { CallSiteFn = Intrinsic::getDeclaration(&M, Intrinsic::eh_sjlj_callsite); DispatchSetupFn = Intrinsic::getDeclaration(&M, Intrinsic::eh_sjlj_dispatch_setup); + FuncCtxFn = Intrinsic::getDeclaration(&M, Intrinsic::eh_sjlj_functioncontext); PersonalityFn = 0; return true; @@ -131,6 +144,42 @@ void SjLjEHPass::insertCallSiteStore(Instruction *I, int Number, new StoreInst(CallSiteNoC, CallSite, true, I); // volatile } +/// splitLandingPad - Split a landing pad. This takes considerable care because +/// of PHIs and other nasties. The problem is that the jump table needs to jump +/// to the landing pad block. However, the landing pad block can be jumped to +/// only by an invoke instruction. So we clone the landingpad instruction into +/// its own basic block, have the invoke jump to there. The landingpad +/// instruction's basic block's successor is now the target for the jump table. +/// +/// But because of PHI nodes, we need to create another basic block for the jump +/// table to jump to. This is definitely a hack, because the values for the PHI +/// nodes may not be defined on the edge from the jump table. But that's okay, +/// because the jump table is simply a construct to mimic what is happening in +/// the CFG. So the values are mysteriously there, even though there is no value +/// for the PHI from the jump table's edge (hence calling this a hack). +void SjLjEHPass::splitLandingPad(InvokeInst *II) { + SmallVector NewBBs; + SplitLandingPadPredecessors(II->getUnwindDest(), II->getParent(), + ".1", ".2", this, NewBBs); + + // Create an empty block so that the jump table has something to jump to + // which doesn't have any PHI nodes. + BasicBlock *LPad = NewBBs[0]; + BasicBlock *Succ = *succ_begin(LPad); + BasicBlock *JumpTo = BasicBlock::Create(II->getContext(), "jt.land", + LPad->getParent(), Succ); + LPad->getTerminator()->eraseFromParent(); + BranchInst::Create(JumpTo, LPad); + BranchInst::Create(Succ, JumpTo); + LPadSuccMap[II] = JumpTo; + + for (BasicBlock::iterator I = Succ->begin(); isa(I); ++I) { + PHINode *PN = cast(I); + Value *Val = PN->removeIncomingValue(LPad, false); + PN->addIncoming(Val, JumpTo); + } +} + /// markInvokeCallSite - Insert code to mark the call_site for this invoke void SjLjEHPass::markInvokeCallSite(InvokeInst *II, int InvokeNo, Value *CallSite, @@ -140,11 +189,15 @@ void SjLjEHPass::markInvokeCallSite(InvokeInst *II, int InvokeNo, // The runtime comes back to the dispatcher with the call_site - 1 in // the context. Odd, but there it is. ConstantInt *SwitchValC = ConstantInt::get(Type::getInt32Ty(II->getContext()), - InvokeNo - 1); + InvokeNo - 1); // If the unwind edge has phi nodes, split the edge. if (isa(II->getUnwindDest()->begin())) { - SplitCriticalEdge(II, 1, this); + // FIXME: New EH - This if-condition will be always true in the new scheme. + if (II->getUnwindDest()->isLandingPad()) + splitLandingPad(II); + else + SplitCriticalEdge(II, 1, this); // If there are any phi nodes left, they must have a single predecessor. while (PHINode *PN = dyn_cast(II->getUnwindDest()->begin())) { @@ -161,7 +214,12 @@ void SjLjEHPass::markInvokeCallSite(InvokeInst *II, int InvokeNo, CallInst::Create(CallSiteFn, CallSiteNoC, "", II); // Add a switch case to our unwind block. - CatchSwitch->addCase(SwitchValC, II->getUnwindDest()); + if (BasicBlock *SuccBB = LPadSuccMap[II]) { + CatchSwitch->addCase(SwitchValC, SuccBB); + } else { + CatchSwitch->addCase(SwitchValC, II->getUnwindDest()); + } + // We still want this to look like an invoke so we emit the LSDA properly, // so we don't transform the invoke into a call here. } @@ -187,10 +245,16 @@ splitLiveRangesAcrossInvokes(SmallVector &Invokes) { for (unsigned i = 0, e = Invokes.size(); i != e; ++i) { InvokeInst *II = Invokes[i]; SplitCriticalEdge(II, 0, this); - SplitCriticalEdge(II, 1, this); + + // FIXME: New EH - This if-condition will be always true in the new scheme. + if (II->getUnwindDest()->isLandingPad()) + splitLandingPad(II); + else + SplitCriticalEdge(II, 1, this); + assert(!isa(II->getNormalDest()) && !isa(II->getUnwindDest()) && - "critical edge splitting left single entry phi nodes?"); + "Critical edge splitting left single entry phi nodes?"); } Function *F = Invokes.back()->getParent()->getParent(); @@ -204,7 +268,7 @@ splitLiveRangesAcrossInvokes(SmallVector &Invokes) { ++AfterAllocaInsertPt; for (Function::arg_iterator AI = F->arg_begin(), E = F->arg_end(); AI != E; ++AI) { - const Type *Ty = AI->getType(); + Type *Ty = AI->getType(); // Aggregate types can't be cast, but are legal argument types, so we have // to handle them differently. We use an extract/insert pair as a // lightweight method to achieve the same goal. @@ -283,9 +347,8 @@ splitLiveRangesAcrossInvokes(SmallVector &Invokes) { bool NeedsSpill = false; for (unsigned i = 0, e = Invokes.size(); i != e; ++i) { BasicBlock *UnwindBlock = Invokes[i]->getUnwindDest(); - if (UnwindBlock != BB && LiveBBs.count(UnwindBlock)) { + if (UnwindBlock != BB && LiveBBs.count(UnwindBlock)) NeedsSpill = true; - } } // If we decided we need a spill, do it. @@ -299,6 +362,44 @@ splitLiveRangesAcrossInvokes(SmallVector &Invokes) { } } +/// CreateLandingPadLoad - Load the exception handling values and insert them +/// into a structure. +static Instruction *CreateLandingPadLoad(Function &F, Value *ExnAddr, + Value *SelAddr, + BasicBlock::iterator InsertPt) { + Value *Exn = new LoadInst(ExnAddr, "exn", false, + InsertPt); + Type *Ty = Type::getInt8PtrTy(F.getContext()); + Exn = CastInst::Create(Instruction::IntToPtr, Exn, Ty, "", InsertPt); + Value *Sel = new LoadInst(SelAddr, "sel", false, InsertPt); + + Ty = StructType::get(Exn->getType(), Sel->getType(), NULL); + InsertValueInst *LPadVal = InsertValueInst::Create(llvm::UndefValue::get(Ty), + Exn, 0, + "lpad.val", InsertPt); + return InsertValueInst::Create(LPadVal, Sel, 1, "lpad.val", InsertPt); +} + +/// ReplaceLandingPadVal - Replace the landingpad instruction's value with a +/// load from the stored values (via CreateLandingPadLoad). This looks through +/// PHI nodes, and removes them if they are dead. +static void ReplaceLandingPadVal(Function &F, Instruction *Inst, Value *ExnAddr, + Value *SelAddr) { + if (Inst->use_empty()) return; + + while (!Inst->use_empty()) { + Instruction *I = cast(Inst->use_back()); + + if (PHINode *PN = dyn_cast(I)) { + ReplaceLandingPadVal(F, PN, ExnAddr, SelAddr); + if (PN->use_empty()) PN->eraseFromParent(); + continue; + } + + I->replaceUsesOfWith(Inst, CreateLandingPadLoad(F, ExnAddr, SelAddr, I)); + } +} + bool SjLjEHPass::insertSjLjEHSupport(Function &F) { SmallVector Returns; SmallVector Unwinds; @@ -337,10 +438,23 @@ bool SjLjEHPass::insertSjLjEHSupport(Function &F) { SmallVector EH_Exceptions; SmallVector JmpbufUpdatePoints; - // Note: Skip the entry block since there's nothing there that interests - // us. eh.selector and eh.exception shouldn't ever be there, and we - // want to disregard any allocas that are there. - for (Function::iterator BB = F.begin(), E = F.end(); ++BB != E;) { + for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) { + // Note: Skip the entry block since there's nothing there that interests + // us. eh.selector and eh.exception shouldn't ever be there, and we + // want to disregard any allocas that are there. + // + // FIXME: This is awkward. The new EH scheme won't need to skip the entry + // block. + if (BB == F.begin()) { + if (InvokeInst *II = dyn_cast(F.begin()->getTerminator())) { + // FIXME: This will be always non-NULL in the new EH. + if (LandingPadInst *LPI = II->getUnwindDest()->getLandingPadInst()) + if (!PersonalityFn) PersonalityFn = LPI->getPersonalityFn(); + } + + continue; + } + for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) { if (CallInst *CI = dyn_cast(I)) { if (CI->getCalledFunction() == SelectorFn) { @@ -353,6 +467,10 @@ bool SjLjEHPass::insertSjLjEHSupport(Function &F) { } } else if (AllocaInst *AI = dyn_cast(I)) { JmpbufUpdatePoints.push_back(AI); + } else if (InvokeInst *II = dyn_cast(I)) { + // FIXME: This will be always non-NULL in the new EH. + if (LandingPadInst *LPI = II->getUnwindDest()->getLandingPadInst()) + if (!PersonalityFn) PersonalityFn = LPI->getPersonalityFn(); } } } @@ -371,6 +489,16 @@ bool SjLjEHPass::insertSjLjEHSupport(Function &F) { // invoke's. splitLiveRangesAcrossInvokes(Invokes); + + SmallVector LandingPads; + for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) { + if (InvokeInst *II = dyn_cast(BB->getTerminator())) + // FIXME: This will be always non-NULL in the new EH. + if (LandingPadInst *LPI = II->getUnwindDest()->getLandingPadInst()) + LandingPads.push_back(LPI); + } + + BasicBlock *EntryBB = F.begin(); // Create an alloca for the incoming jump buffer ptr and the new jump buffer // that needs to be restored on all exits from the function. This is an @@ -381,27 +509,25 @@ bool SjLjEHPass::insertSjLjEHSupport(Function &F) { "fcn_context", F.begin()->begin()); Value *Idxs[2]; - const Type *Int32Ty = Type::getInt32Ty(F.getContext()); + Type *Int32Ty = Type::getInt32Ty(F.getContext()); Value *Zero = ConstantInt::get(Int32Ty, 0); // We need to also keep around a reference to the call_site field Idxs[0] = Zero; Idxs[1] = ConstantInt::get(Int32Ty, 1); - CallSite = GetElementPtrInst::Create(FunctionContext, Idxs, Idxs+2, - "call_site", + CallSite = GetElementPtrInst::Create(FunctionContext, Idxs, "call_site", EntryBB->getTerminator()); // The exception selector comes back in context->data[1] Idxs[1] = ConstantInt::get(Int32Ty, 2); - Value *FCData = GetElementPtrInst::Create(FunctionContext, Idxs, Idxs+2, - "fc_data", + Value *FCData = GetElementPtrInst::Create(FunctionContext, Idxs, "fc_data", EntryBB->getTerminator()); Idxs[1] = ConstantInt::get(Int32Ty, 1); - Value *SelectorAddr = GetElementPtrInst::Create(FCData, Idxs, Idxs+2, + Value *SelectorAddr = GetElementPtrInst::Create(FCData, Idxs, "exc_selector_gep", EntryBB->getTerminator()); // The exception value comes back in context->data[0] Idxs[1] = Zero; - Value *ExceptionAddr = GetElementPtrInst::Create(FCData, Idxs, Idxs+2, + Value *ExceptionAddr = GetElementPtrInst::Create(FCData, Idxs, "exception_gep", EntryBB->getTerminator()); @@ -423,13 +549,16 @@ bool SjLjEHPass::insertSjLjEHSupport(Function &F) { // instruction hasn't already been removed. if (!I->getParent()) continue; Value *Val = new LoadInst(ExceptionAddr, "exception", true, I); - const Type *Ty = Type::getInt8PtrTy(F.getContext()); + Type *Ty = Type::getInt8PtrTy(F.getContext()); Val = CastInst::Create(Instruction::IntToPtr, Val, Ty, "", I); I->replaceAllUsesWith(Val); I->eraseFromParent(); } + for (unsigned i = 0, e = LandingPads.size(); i != e; ++i) + ReplaceLandingPadVal(F, LandingPads[i], ExceptionAddr, SelectorAddr); + // The entry block changes to have the eh.sjlj.setjmp, with a conditional // branch to a dispatch block for non-zero returns. If we return normally, // we're not handling an exception and just register the function context and @@ -466,8 +595,7 @@ bool SjLjEHPass::insertSjLjEHSupport(Function &F) { Idxs[0] = Zero; Idxs[1] = ConstantInt::get(Int32Ty, 4); Value *LSDAFieldPtr = - GetElementPtrInst::Create(FunctionContext, Idxs, Idxs+2, - "lsda_gep", + GetElementPtrInst::Create(FunctionContext, Idxs, "lsda_gep", EntryBB->getTerminator()); Value *LSDA = CallInst::Create(LSDAAddrFn, "lsda_addr", EntryBB->getTerminator()); @@ -475,8 +603,7 @@ bool SjLjEHPass::insertSjLjEHSupport(Function &F) { Idxs[1] = ConstantInt::get(Int32Ty, 3); Value *PersonalityFieldPtr = - GetElementPtrInst::Create(FunctionContext, Idxs, Idxs+2, - "lsda_gep", + GetElementPtrInst::Create(FunctionContext, Idxs, "lsda_gep", EntryBB->getTerminator()); new StoreInst(PersonalityFn, PersonalityFieldPtr, true, EntryBB->getTerminator()); @@ -484,12 +611,11 @@ bool SjLjEHPass::insertSjLjEHSupport(Function &F) { // Save the frame pointer. Idxs[1] = ConstantInt::get(Int32Ty, 5); Value *JBufPtr - = GetElementPtrInst::Create(FunctionContext, Idxs, Idxs+2, - "jbuf_gep", + = GetElementPtrInst::Create(FunctionContext, Idxs, "jbuf_gep", EntryBB->getTerminator()); Idxs[1] = ConstantInt::get(Int32Ty, 0); Value *FramePtr = - GetElementPtrInst::Create(JBufPtr, Idxs, Idxs+2, "jbuf_fp_gep", + GetElementPtrInst::Create(JBufPtr, Idxs, "jbuf_fp_gep", EntryBB->getTerminator()); Value *Val = CallInst::Create(FrameAddrFn, @@ -501,7 +627,7 @@ bool SjLjEHPass::insertSjLjEHSupport(Function &F) { // Save the stack pointer. Idxs[1] = ConstantInt::get(Int32Ty, 2); Value *StackPtr = - GetElementPtrInst::Create(JBufPtr, Idxs, Idxs+2, "jbuf_sp_gep", + GetElementPtrInst::Create(JBufPtr, Idxs, "jbuf_sp_gep", EntryBB->getTerminator()); Val = CallInst::Create(StackAddrFn, "sp", EntryBB->getTerminator()); @@ -513,7 +639,7 @@ bool SjLjEHPass::insertSjLjEHSupport(Function &F) { Type::getInt8PtrTy(F.getContext()), "", EntryBB->getTerminator()); Value *DispatchVal = CallInst::Create(BuiltinSetjmpFn, SetjmpArg, - "dispatch", + "", EntryBB->getTerminator()); // Add a call to dispatch_setup after the setjmp call. This is expanded to any @@ -554,6 +680,8 @@ bool SjLjEHPass::insertSjLjEHSupport(Function &F) { if (Callee != SelectorFn && Callee != ExceptionFn && !CI->doesNotThrow()) insertCallSiteStore(CI, -1, CallSite); + } else if (ResumeInst *RI = dyn_cast(I)) { + insertCallSiteStore(RI, -1, CallSite); } } @@ -582,7 +710,317 @@ bool SjLjEHPass::insertSjLjEHSupport(Function &F) { return true; } +/// setupFunctionContext - Allocate the function context on the stack and fill +/// it with all of the data that we know at this point. +Value *SjLjEHPass:: +setupFunctionContext(Function &F, ArrayRef LPads) { + BasicBlock *EntryBB = F.begin(); + + // Create an alloca for the incoming jump buffer ptr and the new jump buffer + // that needs to be restored on all exits from the function. This is an alloca + // because the value needs to be added to the global context list. + unsigned Align = + TLI->getTargetData()->getPrefTypeAlignment(FunctionContextTy); + AllocaInst *FuncCtx = + new AllocaInst(FunctionContextTy, 0, Align, "fn_context", EntryBB->begin()); + + // Fill in the function context structure. + Value *Idxs[2]; + Type *Int32Ty = Type::getInt32Ty(F.getContext()); + Value *Zero = ConstantInt::get(Int32Ty, 0); + Value *One = ConstantInt::get(Int32Ty, 1); + + // Keep around a reference to the call_site field. + Idxs[0] = Zero; + Idxs[1] = One; + CallSite = GetElementPtrInst::Create(FuncCtx, Idxs, "call_site", + EntryBB->getTerminator()); + + // Reference the __data field. + Idxs[1] = ConstantInt::get(Int32Ty, 2); + Value *FCData = GetElementPtrInst::Create(FuncCtx, Idxs, "__data", + EntryBB->getTerminator()); + + // The exception value comes back in context->__data[0]. + Idxs[1] = Zero; + Value *ExceptionAddr = GetElementPtrInst::Create(FCData, Idxs, + "exception_gep", + EntryBB->getTerminator()); + + // The exception selector comes back in context->__data[1]. + Idxs[1] = One; + Value *SelectorAddr = GetElementPtrInst::Create(FCData, Idxs, + "exn_selector_gep", + EntryBB->getTerminator()); + + for (unsigned I = 0, E = LPads.size(); I != E; ++I) { + LandingPadInst *LPI = LPads[I]; + IRBuilder<> Builder(LPI->getParent()->getFirstInsertionPt()); + + Value *ExnVal = Builder.CreateLoad(ExceptionAddr, true, "exn_val"); + ExnVal = Builder.CreateIntToPtr(ExnVal, Type::getInt8PtrTy(F.getContext())); + Value *SelVal = Builder.CreateLoad(SelectorAddr, true, "exn_selector_val"); + + Type *LPadType = LPI->getType(); + Value *LPadVal = UndefValue::get(LPadType); + LPadVal = Builder.CreateInsertValue(LPadVal, ExnVal, 0, "lpad.val"); + LPadVal = Builder.CreateInsertValue(LPadVal, SelVal, 1, "lpad.val"); + + LPI->replaceAllUsesWith(LPadVal); + } + + // Personality function + Idxs[1] = ConstantInt::get(Int32Ty, 3); + if (!PersonalityFn) + PersonalityFn = LPads[0]->getPersonalityFn(); + Value *PersonalityFieldPtr = + GetElementPtrInst::Create(FuncCtx, Idxs, "pers_fn_gep", + EntryBB->getTerminator()); + new StoreInst(PersonalityFn, PersonalityFieldPtr, true, + EntryBB->getTerminator()); + + // LSDA address + Idxs[1] = ConstantInt::get(Int32Ty, 4); + Value *LSDAFieldPtr = GetElementPtrInst::Create(FuncCtx, Idxs, "lsda_gep", + EntryBB->getTerminator()); + Value *LSDA = CallInst::Create(LSDAAddrFn, "lsda_addr", + EntryBB->getTerminator()); + new StoreInst(LSDA, LSDAFieldPtr, true, EntryBB->getTerminator()); + + return FuncCtx; +} + +/// lowerIncomingArguments - To avoid having to handle incoming arguments +/// specially, we lower each arg to a copy instruction in the entry block. This +/// ensures that the argument value itself cannot be live out of the entry +/// block. +void SjLjEHPass::lowerIncomingArguments(Function &F) { + BasicBlock::iterator AfterAllocaInsPt = F.begin()->begin(); + while (isa(AfterAllocaInsPt) && + isa(cast(AfterAllocaInsPt)->getArraySize())) + ++AfterAllocaInsPt; + + for (Function::arg_iterator + AI = F.arg_begin(), AE = F.arg_end(); AI != AE; ++AI) { + Type *Ty = AI->getType(); + + // Aggregate types can't be cast, but are legal argument types, so we have + // to handle them differently. We use an extract/insert pair as a + // lightweight method to achieve the same goal. + if (isa(Ty) || isa(Ty) || isa(Ty)) { + Instruction *EI = ExtractValueInst::Create(AI, 0, "", AfterAllocaInsPt); + Instruction *NI = InsertValueInst::Create(AI, EI, 0); + NI->insertAfter(EI); + AI->replaceAllUsesWith(NI); + + // Set the operand of the instructions back to the AllocaInst. + EI->setOperand(0, AI); + NI->setOperand(0, AI); + } else { + // This is always a no-op cast because we're casting AI to AI->getType() + // so src and destination types are identical. BitCast is the only + // possibility. + CastInst *NC = + new BitCastInst(AI, AI->getType(), AI->getName() + ".tmp", + AfterAllocaInsPt); + AI->replaceAllUsesWith(NC); + + // Set the operand of the cast instruction back to the AllocaInst. + // Normally it's forbidden to replace a CastInst's operand because it + // could cause the opcode to reflect an illegal conversion. However, we're + // replacing it here with the same value it was constructed with. We do + // this because the above replaceAllUsesWith() clobbered the operand, but + // we want this one to remain. + NC->setOperand(0, AI); + } + } +} + +/// lowerAcrossUnwindEdges - Find all variables which are alive across an unwind +/// edge and spill them. +void SjLjEHPass::lowerAcrossUnwindEdges(Function &F, + ArrayRef Invokes) { + // Finally, scan the code looking for instructions with bad live ranges. + for (Function::iterator + BB = F.begin(), BBE = F.end(); BB != BBE; ++BB) { + for (BasicBlock::iterator + II = BB->begin(), IIE = BB->end(); II != IIE; ++II) { + // Ignore obvious cases we don't have to handle. In particular, most + // instructions either have no uses or only have a single use inside the + // current block. Ignore them quickly. + Instruction *Inst = II; + if (Inst->use_empty()) continue; + if (Inst->hasOneUse() && + cast(Inst->use_back())->getParent() == BB && + !isa(Inst->use_back())) continue; + + // If this is an alloca in the entry block, it's not a real register + // value. + if (AllocaInst *AI = dyn_cast(Inst)) + if (isa(AI->getArraySize()) && BB == F.begin()) + continue; + + // Avoid iterator invalidation by copying users to a temporary vector. + SmallVector Users; + for (Value::use_iterator + UI = Inst->use_begin(), E = Inst->use_end(); UI != E; ++UI) { + Instruction *User = cast(*UI); + if (User->getParent() != BB || isa(User)) + Users.push_back(User); + } + + // Find all of the blocks that this value is live in. + std::set LiveBBs; + LiveBBs.insert(Inst->getParent()); + while (!Users.empty()) { + Instruction *U = Users.back(); + Users.pop_back(); + + if (!isa(U)) { + MarkBlocksLiveIn(U->getParent(), LiveBBs); + } else { + // Uses for a PHI node occur in their predecessor block. + PHINode *PN = cast(U); + for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) + if (PN->getIncomingValue(i) == Inst) + MarkBlocksLiveIn(PN->getIncomingBlock(i), LiveBBs); + } + } + + // Now that we know all of the blocks that this thing is live in, see if + // it includes any of the unwind locations. + bool NeedsSpill = false; + for (unsigned i = 0, e = Invokes.size(); i != e; ++i) { + BasicBlock *UnwindBlock = Invokes[i]->getUnwindDest(); + if (UnwindBlock != BB && LiveBBs.count(UnwindBlock)) { + NeedsSpill = true; + } + } + + // If we decided we need a spill, do it. + // FIXME: Spilling this way is overkill, as it forces all uses of + // the value to be reloaded from the stack slot, even those that aren't + // in the unwind blocks. We should be more selective. + if (NeedsSpill) { + ++NumSpilled; + DemoteRegToStack(*Inst, true); + } + } + } +} + +/// setupEntryBlockAndCallSites - Setup the entry block by creating and filling +/// the function context and marking the call sites with the appropriate +/// values. These values are used by the DWARF EH emitter. +bool SjLjEHPass::setupEntryBlockAndCallSites(Function &F) { + SmallVector Returns; + SmallVector Invokes; + SmallVector LPads; + + // Look through the terminators of the basic blocks to find invokes. + for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) + if (InvokeInst *II = dyn_cast(BB->getTerminator())) { + Invokes.push_back(II); + LPads.push_back(II->getUnwindDest()->getLandingPadInst()); + } else if (ReturnInst *RI = dyn_cast(BB->getTerminator())) { + Returns.push_back(RI); + } + + if (Invokes.empty()) return false; + + lowerIncomingArguments(F); + lowerAcrossUnwindEdges(F, Invokes); + + Value *FuncCtx = setupFunctionContext(F, LPads); + BasicBlock *EntryBB = F.begin(); + Type *Int32Ty = Type::getInt32Ty(F.getContext()); + + Value *Idxs[2] = { + ConstantInt::get(Int32Ty, 0), 0 + }; + + // Get a reference to the jump buffer. + Idxs[1] = ConstantInt::get(Int32Ty, 5); + Value *JBufPtr = GetElementPtrInst::Create(FuncCtx, Idxs, "jbuf_gep", + EntryBB->getTerminator()); + + // Save the frame pointer. + Idxs[1] = ConstantInt::get(Int32Ty, 0); + Value *FramePtr = GetElementPtrInst::Create(JBufPtr, Idxs, "jbuf_fp_gep", + EntryBB->getTerminator()); + + Value *Val = CallInst::Create(FrameAddrFn, + ConstantInt::get(Int32Ty, 0), + "fp", + EntryBB->getTerminator()); + new StoreInst(Val, FramePtr, true, EntryBB->getTerminator()); + + // Save the stack pointer. + Idxs[1] = ConstantInt::get(Int32Ty, 2); + Value *StackPtr = GetElementPtrInst::Create(JBufPtr, Idxs, "jbuf_sp_gep", + EntryBB->getTerminator()); + + Val = CallInst::Create(StackAddrFn, "sp", EntryBB->getTerminator()); + new StoreInst(Val, StackPtr, true, EntryBB->getTerminator()); + + // Call the setjmp instrinsic. It fills in the rest of the jmpbuf. + Value *SetjmpArg = CastInst::Create(Instruction::BitCast, JBufPtr, + Type::getInt8PtrTy(F.getContext()), "", + EntryBB->getTerminator()); + CallInst::Create(BuiltinSetjmpFn, SetjmpArg, "", EntryBB->getTerminator()); + + // Store a pointer to the function context so that the back-end will know + // where to look for it. + Value *FuncCtxArg = CastInst::Create(Instruction::BitCast, FuncCtx, + Type::getInt8PtrTy(F.getContext()), "", + EntryBB->getTerminator()); + CallInst::Create(FuncCtxFn, FuncCtxArg, "", EntryBB->getTerminator()); + + // At this point, we are all set up, update the invoke instructions to mark + // their call_site values. + for (unsigned I = 0, E = Invokes.size(); I != E; ++I) { + insertCallSiteStore(Invokes[I], I + 1, CallSite); + + ConstantInt *CallSiteNum = + ConstantInt::get(Type::getInt32Ty(F.getContext()), I + 1); + + // Record the call site value for the back end so it stays associated with + // the invoke. + CallInst::Create(CallSiteFn, CallSiteNum, "", Invokes[I]); + } + + // Mark call instructions that aren't nounwind as no-action (call_site == + // -1). Skip the entry block, as prior to then, no function context has been + // created for this function and any unexpected exceptions thrown will go + // directly to the caller's context, which is what we want anyway, so no need + // to do anything here. + for (Function::iterator BB = F.begin(), E = F.end(); ++BB != E;) + for (BasicBlock::iterator I = BB->begin(), end = BB->end(); I != end; ++I) + if (CallInst *CI = dyn_cast(I)) { + if (!CI->doesNotThrow()) + insertCallSiteStore(CI, -1, CallSite); + } else if (ResumeInst *RI = dyn_cast(I)) { + insertCallSiteStore(RI, -1, CallSite); + } + + // Register the function context and make sure it's known to not throw + CallInst *Register = CallInst::Create(RegisterFn, FuncCtx, "", + EntryBB->getTerminator()); + Register->setDoesNotThrow(); + + // Finally, for any returns from this function, if this function contains an + // invoke, add a call to unregister the function context. + for (unsigned I = 0, E = Returns.size(); I != E; ++I) + CallInst::Create(UnregisterFn, FuncCtx, "", Returns[I]); + + return true; +} + bool SjLjEHPass::runOnFunction(Function &F) { - bool Res = insertSjLjEHSupport(F); + bool Res = false; + if (!DisableOldSjLjEH) + Res = insertSjLjEHSupport(F); + else + Res = setupEntryBlockAndCallSites(F); return Res; } diff --git a/contrib/llvm/lib/CodeGen/SpillPlacement.cpp b/contrib/llvm/lib/CodeGen/SpillPlacement.cpp index 694961863..6f33f5465 100644 --- a/contrib/llvm/lib/CodeGen/SpillPlacement.cpp +++ b/contrib/llvm/lib/CodeGen/SpillPlacement.cpp @@ -220,6 +220,7 @@ void SpillPlacement::addConstraints(ArrayRef LiveBlocks) { 0, // DontCare, 1, // PrefReg, -1, // PrefSpill + 0, // PrefBoth -HUGE_VALF // MustSpill }; @@ -239,6 +240,22 @@ void SpillPlacement::addConstraints(ArrayRef LiveBlocks) { } } +/// addPrefSpill - Same as addConstraints(PrefSpill) +void SpillPlacement::addPrefSpill(ArrayRef Blocks, bool Strong) { + for (ArrayRef::iterator I = Blocks.begin(), E = Blocks.end(); + I != E; ++I) { + float Freq = getBlockFrequency(*I); + if (Strong) + Freq += Freq; + unsigned ib = bundles->getBundle(*I, 0); + unsigned ob = bundles->getBundle(*I, 1); + activate(ib); + activate(ob); + nodes[ib].addBias(-Freq, 1); + nodes[ob].addBias(-Freq, 0); + } +} + void SpillPlacement::addLinks(ArrayRef Links) { for (ArrayRef::iterator I = Links.begin(), E = Links.end(); I != E; ++I) { diff --git a/contrib/llvm/lib/CodeGen/SpillPlacement.h b/contrib/llvm/lib/CodeGen/SpillPlacement.h index 6952ad800..fc412f817 100644 --- a/contrib/llvm/lib/CodeGen/SpillPlacement.h +++ b/contrib/llvm/lib/CodeGen/SpillPlacement.h @@ -71,6 +71,7 @@ public: DontCare, ///< Block doesn't care / variable not live. PrefReg, ///< Block entry/exit prefers a register. PrefSpill, ///< Block entry/exit prefers a stack slot. + PrefBoth, ///< Block entry prefers both register and stack. MustSpill ///< A register is impossible, variable must be spilled. }; @@ -79,6 +80,11 @@ public: unsigned Number; ///< Basic block number (from MBB::getNumber()). BorderConstraint Entry : 8; ///< Constraint on block entry. BorderConstraint Exit : 8; ///< Constraint on block exit. + + /// True when this block changes the value of the live range. This means + /// the block has a non-PHI def. When this is false, a live-in value on + /// the stack can be live-out on the stack without inserting a spill. + bool ChangesValue; }; /// prepare - Reset state and prepare for a new spill placement computation. @@ -96,6 +102,14 @@ public: /// live out. void addConstraints(ArrayRef LiveBlocks); + /// addPrefSpill - Add PrefSpill constraints to all blocks listed. This is + /// equivalent to calling addConstraint with identical BlockConstraints with + /// Entry = Exit = PrefSpill, and ChangesValue = false. + /// + /// @param Blocks Array of block numbers that prefer to spill in and out. + /// @param Strong When true, double the negative bias for these blocks. + void addPrefSpill(ArrayRef Blocks, bool Strong); + /// addLinks - Add transparent blocks with the given numbers. void addLinks(ArrayRef Links); diff --git a/contrib/llvm/lib/CodeGen/SplitKit.cpp b/contrib/llvm/lib/CodeGen/SplitKit.cpp index 761cab7ce..63627800a 100644 --- a/contrib/llvm/lib/CodeGen/SplitKit.cpp +++ b/contrib/llvm/lib/CodeGen/SplitKit.cpp @@ -20,6 +20,7 @@ #include "llvm/CodeGen/LiveIntervalAnalysis.h" #include "llvm/CodeGen/MachineDominators.h" #include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineLoopInfo.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" @@ -178,45 +179,55 @@ bool SplitAnalysis::calcLiveBlockInfo() { return false; } else { // This block has uses. Find the first and last uses in the block. - BI.FirstUse = *UseI; - assert(BI.FirstUse >= Start); + BI.FirstInstr = *UseI; + assert(BI.FirstInstr >= Start); do ++UseI; while (UseI != UseE && *UseI < Stop); - BI.LastUse = UseI[-1]; - assert(BI.LastUse < Stop); + BI.LastInstr = UseI[-1]; + assert(BI.LastInstr < Stop); // LVI is the first live segment overlapping MBB. BI.LiveIn = LVI->start <= Start; + // When not live in, the first use should be a def. + if (!BI.LiveIn) { + assert(LVI->start == LVI->valno->def && "Dangling LiveRange start"); + assert(LVI->start == BI.FirstInstr && "First instr should be a def"); + BI.FirstDef = BI.FirstInstr; + } + // Look for gaps in the live range. BI.LiveOut = true; while (LVI->end < Stop) { SlotIndex LastStop = LVI->end; if (++LVI == LVE || LVI->start >= Stop) { BI.LiveOut = false; - BI.LastUse = LastStop; + BI.LastInstr = LastStop; break; } + if (LastStop < LVI->start) { // There is a gap in the live range. Create duplicate entries for the // live-in snippet and the live-out snippet. ++NumGapBlocks; // Push the Live-in part. - BI.LiveThrough = false; BI.LiveOut = false; UseBlocks.push_back(BI); - UseBlocks.back().LastUse = LastStop; + UseBlocks.back().LastInstr = LastStop; // Set up BI for the live-out part. BI.LiveIn = false; BI.LiveOut = true; - BI.FirstUse = LVI->start; + BI.FirstInstr = BI.FirstDef = LVI->start; } + + // A LiveRange that starts in the middle of the block must be a def. + assert(LVI->start == LVI->valno->def && "Dangling LiveRange start"); + if (!BI.FirstDef) + BI.FirstDef = LVI->start; } - // Don't set LiveThrough when the block has a gap. - BI.LiveThrough = BI.LiveIn && BI.LiveOut; UseBlocks.push_back(BI); // LVI is now at LVE or LVI->end >= Stop. @@ -299,17 +310,21 @@ SplitEditor::SplitEditor(SplitAnalysis &sa, TRI(*vrm.getMachineFunction().getTarget().getRegisterInfo()), Edit(0), OpenIdx(0), + SpillMode(SM_Partition), RegAssign(Allocator) {} -void SplitEditor::reset(LiveRangeEdit &lre) { - Edit = &lre; +void SplitEditor::reset(LiveRangeEdit &LRE, ComplementSpillMode SM) { + Edit = &LRE; + SpillMode = SM; OpenIdx = 0; RegAssign.clear(); Values.clear(); - // We don't need to clear LiveOutCache, only LiveOutSeen entries are read. - LiveOutSeen.clear(); + // Reset the LiveRangeCalc instances needed for this spill mode. + LRCalc[0].reset(&VRM.getMachineFunction()); + if (SpillMode) + LRCalc[1].reset(&VRM.getMachineFunction()); // We don't need an AliasAnalysis since we will only be performing // cheap-as-a-copy remats anyway. @@ -340,7 +355,8 @@ VNInfo *SplitEditor::defValue(unsigned RegIdx, // Use insert for lookup, so we can add missing values with a second lookup. std::pair InsP = - Values.insert(std::make_pair(std::make_pair(RegIdx, ParentVNI->id), VNI)); + Values.insert(std::make_pair(std::make_pair(RegIdx, ParentVNI->id), + ValueForcePair(VNI, false))); // This was the first time (RegIdx, ParentVNI) was mapped. // Keep it as a simple def without any liveness. @@ -348,11 +364,11 @@ VNInfo *SplitEditor::defValue(unsigned RegIdx, return VNI; // If the previous value was a simple mapping, add liveness for it now. - if (VNInfo *OldVNI = InsP.first->second) { + if (VNInfo *OldVNI = InsP.first->second.getPointer()) { SlotIndex Def = OldVNI->def; LI->addRange(LiveRange(Def, Def.getNextSlot(), OldVNI)); - // No longer a simple mapping. - InsP.first->second = 0; + // No longer a simple mapping. Switch to a complex, non-forced mapping. + InsP.first->second = ValueForcePair(); } // This is a complex mapping, add liveness for VNI @@ -362,230 +378,24 @@ VNInfo *SplitEditor::defValue(unsigned RegIdx, return VNI; } -void SplitEditor::markComplexMapped(unsigned RegIdx, const VNInfo *ParentVNI) { +void SplitEditor::forceRecompute(unsigned RegIdx, const VNInfo *ParentVNI) { assert(ParentVNI && "Mapping NULL value"); - VNInfo *&VNI = Values[std::make_pair(RegIdx, ParentVNI->id)]; + ValueForcePair &VFP = Values[std::make_pair(RegIdx, ParentVNI->id)]; + VNInfo *VNI = VFP.getPointer(); - // ParentVNI was either unmapped or already complex mapped. Either way. - if (!VNI) + // ParentVNI was either unmapped or already complex mapped. Either way, just + // set the force bit. + if (!VNI) { + VFP.setInt(true); return; + } // This was previously a single mapping. Make sure the old def is represented // by a trivial live range. SlotIndex Def = VNI->def; Edit->get(RegIdx)->addRange(LiveRange(Def, Def.getNextSlot(), VNI)); - VNI = 0; -} - -// extendRange - Extend the live range to reach Idx. -// Potentially create phi-def values. -void SplitEditor::extendRange(unsigned RegIdx, SlotIndex Idx) { - assert(Idx.isValid() && "Invalid SlotIndex"); - MachineBasicBlock *IdxMBB = LIS.getMBBFromIndex(Idx); - assert(IdxMBB && "No MBB at Idx"); - LiveInterval *LI = Edit->get(RegIdx); - - // Is there a def in the same MBB we can extend? - if (LI->extendInBlock(LIS.getMBBStartIdx(IdxMBB), Idx)) - return; - - // Now for the fun part. We know that ParentVNI potentially has multiple defs, - // and we may need to create even more phi-defs to preserve VNInfo SSA form. - // Perform a search for all predecessor blocks where we know the dominating - // VNInfo. - VNInfo *VNI = findReachingDefs(LI, IdxMBB, Idx.getNextSlot()); - - // When there were multiple different values, we may need new PHIs. - if (!VNI) - return updateSSA(); - - // Poor man's SSA update for the single-value case. - LiveOutPair LOP(VNI, MDT[LIS.getMBBFromIndex(VNI->def)]); - for (SmallVectorImpl::iterator I = LiveInBlocks.begin(), - E = LiveInBlocks.end(); I != E; ++I) { - MachineBasicBlock *MBB = I->DomNode->getBlock(); - SlotIndex Start = LIS.getMBBStartIdx(MBB); - if (I->Kill.isValid()) - LI->addRange(LiveRange(Start, I->Kill, VNI)); - else { - LiveOutCache[MBB] = LOP; - LI->addRange(LiveRange(Start, LIS.getMBBEndIdx(MBB), VNI)); - } - } -} - -/// findReachingDefs - Search the CFG for known live-out values. -/// Add required live-in blocks to LiveInBlocks. -VNInfo *SplitEditor::findReachingDefs(LiveInterval *LI, - MachineBasicBlock *KillMBB, - SlotIndex Kill) { - // Initialize the live-out cache the first time it is needed. - if (LiveOutSeen.empty()) { - unsigned N = VRM.getMachineFunction().getNumBlockIDs(); - LiveOutSeen.resize(N); - LiveOutCache.resize(N); - } - - // Blocks where LI should be live-in. - SmallVector WorkList(1, KillMBB); - - // Remember if we have seen more than one value. - bool UniqueVNI = true; - VNInfo *TheVNI = 0; - - // Using LiveOutCache as a visited set, perform a BFS for all reaching defs. - for (unsigned i = 0; i != WorkList.size(); ++i) { - MachineBasicBlock *MBB = WorkList[i]; - assert(!MBB->pred_empty() && "Value live-in to entry block?"); - for (MachineBasicBlock::pred_iterator PI = MBB->pred_begin(), - PE = MBB->pred_end(); PI != PE; ++PI) { - MachineBasicBlock *Pred = *PI; - LiveOutPair &LOP = LiveOutCache[Pred]; - - // Is this a known live-out block? - if (LiveOutSeen.test(Pred->getNumber())) { - if (VNInfo *VNI = LOP.first) { - if (TheVNI && TheVNI != VNI) - UniqueVNI = false; - TheVNI = VNI; - } - continue; - } - - // First time. LOP is garbage and must be cleared below. - LiveOutSeen.set(Pred->getNumber()); - - // Does Pred provide a live-out value? - SlotIndex Start, Last; - tie(Start, Last) = LIS.getSlotIndexes()->getMBBRange(Pred); - Last = Last.getPrevSlot(); - VNInfo *VNI = LI->extendInBlock(Start, Last); - LOP.first = VNI; - if (VNI) { - LOP.second = MDT[LIS.getMBBFromIndex(VNI->def)]; - if (TheVNI && TheVNI != VNI) - UniqueVNI = false; - TheVNI = VNI; - continue; - } - LOP.second = 0; - - // No, we need a live-in value for Pred as well - if (Pred != KillMBB) - WorkList.push_back(Pred); - else - // Loopback to KillMBB, so value is really live through. - Kill = SlotIndex(); - } - } - - // Transfer WorkList to LiveInBlocks in reverse order. - // This ordering works best with updateSSA(). - LiveInBlocks.clear(); - LiveInBlocks.reserve(WorkList.size()); - while(!WorkList.empty()) - LiveInBlocks.push_back(MDT[WorkList.pop_back_val()]); - - // The kill block may not be live-through. - assert(LiveInBlocks.back().DomNode->getBlock() == KillMBB); - LiveInBlocks.back().Kill = Kill; - - return UniqueVNI ? TheVNI : 0; -} - -void SplitEditor::updateSSA() { - // This is essentially the same iterative algorithm that SSAUpdater uses, - // except we already have a dominator tree, so we don't have to recompute it. - unsigned Changes; - do { - Changes = 0; - // Propagate live-out values down the dominator tree, inserting phi-defs - // when necessary. - for (SmallVectorImpl::iterator I = LiveInBlocks.begin(), - E = LiveInBlocks.end(); I != E; ++I) { - MachineDomTreeNode *Node = I->DomNode; - // Skip block if the live-in value has already been determined. - if (!Node) - continue; - MachineBasicBlock *MBB = Node->getBlock(); - MachineDomTreeNode *IDom = Node->getIDom(); - LiveOutPair IDomValue; - - // We need a live-in value to a block with no immediate dominator? - // This is probably an unreachable block that has survived somehow. - bool needPHI = !IDom || !LiveOutSeen.test(IDom->getBlock()->getNumber()); - - // IDom dominates all of our predecessors, but it may not be their - // immediate dominator. Check if any of them have live-out values that are - // properly dominated by IDom. If so, we need a phi-def here. - if (!needPHI) { - IDomValue = LiveOutCache[IDom->getBlock()]; - for (MachineBasicBlock::pred_iterator PI = MBB->pred_begin(), - PE = MBB->pred_end(); PI != PE; ++PI) { - LiveOutPair Value = LiveOutCache[*PI]; - if (!Value.first || Value.first == IDomValue.first) - continue; - // This predecessor is carrying something other than IDomValue. - // It could be because IDomValue hasn't propagated yet, or it could be - // because MBB is in the dominance frontier of that value. - if (MDT.dominates(IDom, Value.second)) { - needPHI = true; - break; - } - } - } - - // The value may be live-through even if Kill is set, as can happen when - // we are called from extendRange. In that case LiveOutSeen is true, and - // LiveOutCache indicates a foreign or missing value. - LiveOutPair &LOP = LiveOutCache[MBB]; - - // Create a phi-def if required. - if (needPHI) { - ++Changes; - SlotIndex Start = LIS.getMBBStartIdx(MBB); - unsigned RegIdx = RegAssign.lookup(Start); - LiveInterval *LI = Edit->get(RegIdx); - VNInfo *VNI = LI->getNextValue(Start, 0, LIS.getVNInfoAllocator()); - VNI->setIsPHIDef(true); - I->Value = VNI; - // This block is done, we know the final value. - I->DomNode = 0; - if (I->Kill.isValid()) - LI->addRange(LiveRange(Start, I->Kill, VNI)); - else { - LI->addRange(LiveRange(Start, LIS.getMBBEndIdx(MBB), VNI)); - LOP = LiveOutPair(VNI, Node); - } - } else if (IDomValue.first) { - // No phi-def here. Remember incoming value. - I->Value = IDomValue.first; - if (I->Kill.isValid()) - continue; - // Propagate IDomValue if needed: - // MBB is live-out and doesn't define its own value. - if (LOP.second != Node && LOP.first != IDomValue.first) { - ++Changes; - LOP = IDomValue; - } - } - } - } while (Changes); - - // The values in LiveInBlocks are now accurate. No more phi-defs are needed - // for these blocks, so we can color the live ranges. - for (SmallVectorImpl::iterator I = LiveInBlocks.begin(), - E = LiveInBlocks.end(); I != E; ++I) { - if (!I->DomNode) - continue; - assert(I->Value && "No live-in value found"); - MachineBasicBlock *MBB = I->DomNode->getBlock(); - SlotIndex Start = LIS.getMBBStartIdx(MBB); - unsigned RegIdx = RegAssign.lookup(Start); - LiveInterval *LI = Edit->get(RegIdx); - LI->addRange(LiveRange(Start, I->Kill.isValid() ? - I->Kill : LIS.getMBBEndIdx(MBB), I->Value)); - } + // Mark as complex mapped, forced. + VFP = ValueForcePair(0, true); } VNInfo *SplitEditor::defFromParent(unsigned RegIdx, @@ -710,17 +520,28 @@ SlotIndex SplitEditor::leaveIntvAfter(SlotIndex Idx) { DEBUG(dbgs() << " leaveIntvAfter " << Idx); // The interval must be live beyond the instruction at Idx. - Idx = Idx.getBoundaryIndex(); - VNInfo *ParentVNI = Edit->getParent().getVNInfoAt(Idx); + SlotIndex Boundary = Idx.getBoundaryIndex(); + VNInfo *ParentVNI = Edit->getParent().getVNInfoAt(Boundary); if (!ParentVNI) { DEBUG(dbgs() << ": not live\n"); - return Idx.getNextSlot(); + return Boundary.getNextSlot(); } DEBUG(dbgs() << ": valno " << ParentVNI->id << '\n'); - - MachineInstr *MI = LIS.getInstructionFromIndex(Idx); + MachineInstr *MI = LIS.getInstructionFromIndex(Boundary); assert(MI && "No instruction at index"); - VNInfo *VNI = defFromParent(0, ParentVNI, Idx, *MI->getParent(), + + // In spill mode, make live ranges as short as possible by inserting the copy + // before MI. This is only possible if that instruction doesn't redefine the + // value. The inserted COPY is not a kill, and we don't need to recompute + // the source live range. The spiller also won't try to hoist this copy. + if (SpillMode && !SlotIndex::isSameInstr(ParentVNI->def, Idx) && + MI->readsVirtualRegister(Edit->getReg())) { + forceRecompute(0, ParentVNI); + defFromParent(0, ParentVNI, Idx, *MI->getParent(), MI); + return Idx; + } + + VNInfo *VNI = defFromParent(0, ParentVNI, Boundary, *MI->getParent(), llvm::next(MachineBasicBlock::iterator(MI))); return VNI->def; } @@ -730,7 +551,7 @@ SlotIndex SplitEditor::leaveIntvBefore(SlotIndex Idx) { DEBUG(dbgs() << " leaveIntvBefore " << Idx); // The interval must be live into the instruction at Idx. - Idx = Idx.getBoundaryIndex(); + Idx = Idx.getBaseIndex(); VNInfo *ParentVNI = Edit->getParent().getVNInfoAt(Idx); if (!ParentVNI) { DEBUG(dbgs() << ": not live\n"); @@ -770,19 +591,219 @@ void SplitEditor::overlapIntv(SlotIndex Start, SlotIndex End) { assert(LIS.getMBBFromIndex(Start) == LIS.getMBBFromIndex(End) && "Range cannot span basic blocks"); - // The complement interval will be extended as needed by extendRange(). + // The complement interval will be extended as needed by LRCalc.extend(). if (ParentVNI) - markComplexMapped(0, ParentVNI); + forceRecompute(0, ParentVNI); DEBUG(dbgs() << " overlapIntv [" << Start << ';' << End << "):"); RegAssign.insert(Start, End, OpenIdx); DEBUG(dump()); } +//===----------------------------------------------------------------------===// +// Spill modes +//===----------------------------------------------------------------------===// + +void SplitEditor::removeBackCopies(SmallVectorImpl &Copies) { + LiveInterval *LI = Edit->get(0); + DEBUG(dbgs() << "Removing " << Copies.size() << " back-copies.\n"); + RegAssignMap::iterator AssignI; + AssignI.setMap(RegAssign); + + for (unsigned i = 0, e = Copies.size(); i != e; ++i) { + VNInfo *VNI = Copies[i]; + SlotIndex Def = VNI->def; + MachineInstr *MI = LIS.getInstructionFromIndex(Def); + assert(MI && "No instruction for back-copy"); + + MachineBasicBlock *MBB = MI->getParent(); + MachineBasicBlock::iterator MBBI(MI); + bool AtBegin; + do AtBegin = MBBI == MBB->begin(); + while (!AtBegin && (--MBBI)->isDebugValue()); + + DEBUG(dbgs() << "Removing " << Def << '\t' << *MI); + LI->removeValNo(VNI); + LIS.RemoveMachineInstrFromMaps(MI); + MI->eraseFromParent(); + + // Adjust RegAssign if a register assignment is killed at VNI->def. We + // want to avoid calculating the live range of the source register if + // possible. + AssignI.find(VNI->def.getPrevSlot()); + if (!AssignI.valid() || AssignI.start() >= Def) + continue; + // If MI doesn't kill the assigned register, just leave it. + if (AssignI.stop() != Def) + continue; + unsigned RegIdx = AssignI.value(); + if (AtBegin || !MBBI->readsVirtualRegister(Edit->getReg())) { + DEBUG(dbgs() << " cannot find simple kill of RegIdx " << RegIdx << '\n'); + forceRecompute(RegIdx, Edit->getParent().getVNInfoAt(Def)); + } else { + SlotIndex Kill = LIS.getInstructionIndex(MBBI).getDefIndex(); + DEBUG(dbgs() << " move kill to " << Kill << '\t' << *MBBI); + AssignI.setStop(Kill); + } + } +} + +MachineBasicBlock* +SplitEditor::findShallowDominator(MachineBasicBlock *MBB, + MachineBasicBlock *DefMBB) { + if (MBB == DefMBB) + return MBB; + assert(MDT.dominates(DefMBB, MBB) && "MBB must be dominated by the def."); + + const MachineLoopInfo &Loops = SA.Loops; + const MachineLoop *DefLoop = Loops.getLoopFor(DefMBB); + MachineDomTreeNode *DefDomNode = MDT[DefMBB]; + + // Best candidate so far. + MachineBasicBlock *BestMBB = MBB; + unsigned BestDepth = UINT_MAX; + + for (;;) { + const MachineLoop *Loop = Loops.getLoopFor(MBB); + + // MBB isn't in a loop, it doesn't get any better. All dominators have a + // higher frequency by definition. + if (!Loop) { + DEBUG(dbgs() << "Def in BB#" << DefMBB->getNumber() << " dominates BB#" + << MBB->getNumber() << " at depth 0\n"); + return MBB; + } + + // We'll never be able to exit the DefLoop. + if (Loop == DefLoop) { + DEBUG(dbgs() << "Def in BB#" << DefMBB->getNumber() << " dominates BB#" + << MBB->getNumber() << " in the same loop\n"); + return MBB; + } + + // Least busy dominator seen so far. + unsigned Depth = Loop->getLoopDepth(); + if (Depth < BestDepth) { + BestMBB = MBB; + BestDepth = Depth; + DEBUG(dbgs() << "Def in BB#" << DefMBB->getNumber() << " dominates BB#" + << MBB->getNumber() << " at depth " << Depth << '\n'); + } + + // Leave loop by going to the immediate dominator of the loop header. + // This is a bigger stride than simply walking up the dominator tree. + MachineDomTreeNode *IDom = MDT[Loop->getHeader()]->getIDom(); + + // Too far up the dominator tree? + if (!IDom || !MDT.dominates(DefDomNode, IDom)) + return BestMBB; + + MBB = IDom->getBlock(); + } +} + +void SplitEditor::hoistCopiesForSize() { + // Get the complement interval, always RegIdx 0. + LiveInterval *LI = Edit->get(0); + LiveInterval *Parent = &Edit->getParent(); + + // Track the nearest common dominator for all back-copies for each ParentVNI, + // indexed by ParentVNI->id. + typedef std::pair DomPair; + SmallVector NearestDom(Parent->getNumValNums()); + + // Find the nearest common dominator for parent values with multiple + // back-copies. If a single back-copy dominates, put it in DomPair.second. + for (LiveInterval::vni_iterator VI = LI->vni_begin(), VE = LI->vni_end(); + VI != VE; ++VI) { + VNInfo *VNI = *VI; + VNInfo *ParentVNI = Edit->getParent().getVNInfoAt(VNI->def); + assert(ParentVNI && "Parent not live at complement def"); + + // Don't hoist remats. The complement is probably going to disappear + // completely anyway. + if (Edit->didRematerialize(ParentVNI)) + continue; + + MachineBasicBlock *ValMBB = LIS.getMBBFromIndex(VNI->def); + DomPair &Dom = NearestDom[ParentVNI->id]; + + // Keep directly defined parent values. This is either a PHI or an + // instruction in the complement range. All other copies of ParentVNI + // should be eliminated. + if (VNI->def == ParentVNI->def) { + DEBUG(dbgs() << "Direct complement def at " << VNI->def << '\n'); + Dom = DomPair(ValMBB, VNI->def); + continue; + } + // Skip the singly mapped values. There is nothing to gain from hoisting a + // single back-copy. + if (Values.lookup(std::make_pair(0, ParentVNI->id)).getPointer()) { + DEBUG(dbgs() << "Single complement def at " << VNI->def << '\n'); + continue; + } + + if (!Dom.first) { + // First time we see ParentVNI. VNI dominates itself. + Dom = DomPair(ValMBB, VNI->def); + } else if (Dom.first == ValMBB) { + // Two defs in the same block. Pick the earlier def. + if (!Dom.second.isValid() || VNI->def < Dom.second) + Dom.second = VNI->def; + } else { + // Different basic blocks. Check if one dominates. + MachineBasicBlock *Near = + MDT.findNearestCommonDominator(Dom.first, ValMBB); + if (Near == ValMBB) + // Def ValMBB dominates. + Dom = DomPair(ValMBB, VNI->def); + else if (Near != Dom.first) + // None dominate. Hoist to common dominator, need new def. + Dom = DomPair(Near, SlotIndex()); + } + + DEBUG(dbgs() << "Multi-mapped complement " << VNI->id << '@' << VNI->def + << " for parent " << ParentVNI->id << '@' << ParentVNI->def + << " hoist to BB#" << Dom.first->getNumber() << ' ' + << Dom.second << '\n'); + } + + // Insert the hoisted copies. + for (unsigned i = 0, e = Parent->getNumValNums(); i != e; ++i) { + DomPair &Dom = NearestDom[i]; + if (!Dom.first || Dom.second.isValid()) + continue; + // This value needs a hoisted copy inserted at the end of Dom.first. + VNInfo *ParentVNI = Parent->getValNumInfo(i); + MachineBasicBlock *DefMBB = LIS.getMBBFromIndex(ParentVNI->def); + // Get a less loopy dominator than Dom.first. + Dom.first = findShallowDominator(Dom.first, DefMBB); + SlotIndex Last = LIS.getMBBEndIdx(Dom.first).getPrevSlot(); + Dom.second = + defFromParent(0, ParentVNI, Last, *Dom.first, + LIS.getLastSplitPoint(Edit->getParent(), Dom.first))->def; + } + + // Remove redundant back-copies that are now known to be dominated by another + // def with the same value. + SmallVector BackCopies; + for (LiveInterval::vni_iterator VI = LI->vni_begin(), VE = LI->vni_end(); + VI != VE; ++VI) { + VNInfo *VNI = *VI; + VNInfo *ParentVNI = Edit->getParent().getVNInfoAt(VNI->def); + const DomPair &Dom = NearestDom[ParentVNI->id]; + if (!Dom.first || Dom.second == VNI->def) + continue; + BackCopies.push_back(VNI); + forceRecompute(0, ParentVNI); + } + removeBackCopies(BackCopies); +} + + /// transferValues - Transfer all possible values to the new live ranges. -/// Values that were rematerialized are left alone, they need extendRange(). +/// Values that were rematerialized are left alone, they need LRCalc.extend(). bool SplitEditor::transferValues() { bool Skipped = false; - LiveInBlocks.clear(); RegAssignMap::const_iterator AssignI = RegAssign.begin(); for (LiveInterval::const_iterator ParentI = Edit->getParent().begin(), ParentE = Edit->getParent().end(); ParentI != ParentE; ++ParentI) { @@ -812,28 +833,23 @@ bool SplitEditor::transferValues() { LiveInterval *LI = Edit->get(RegIdx); // Check for a simply defined value that can be blitted directly. - if (VNInfo *VNI = Values.lookup(std::make_pair(RegIdx, ParentVNI->id))) { + ValueForcePair VFP = Values.lookup(std::make_pair(RegIdx, ParentVNI->id)); + if (VNInfo *VNI = VFP.getPointer()) { DEBUG(dbgs() << ':' << VNI->id); LI->addRange(LiveRange(Start, End, VNI)); Start = End; continue; } - // Skip rematerialized values, we need to use extendRange() and - // extendPHIKillRanges() to completely recompute the live ranges. - if (Edit->didRematerialize(ParentVNI)) { - DEBUG(dbgs() << "(remat)"); + // Skip values with forced recomputation. + if (VFP.getInt()) { + DEBUG(dbgs() << "(recalc)"); Skipped = true; Start = End; continue; } - // Initialize the live-out cache the first time it is needed. - if (LiveOutSeen.empty()) { - unsigned N = VRM.getMachineFunction().getNumBlockIDs(); - LiveOutSeen.resize(N); - LiveOutCache.resize(N); - } + LiveRangeCalc &LRC = getLRCalc(RegIdx); // This value has multiple defs in RegIdx, but it wasn't rematerialized, // so the live range is accurate. Add live-in blocks in [Start;End) to the @@ -844,15 +860,13 @@ bool SplitEditor::transferValues() { // The first block may be live-in, or it may have its own def. if (Start != BlockStart) { - VNInfo *VNI = LI->extendInBlock(BlockStart, - std::min(BlockEnd, End).getPrevSlot()); + VNInfo *VNI = LI->extendInBlock(BlockStart, std::min(BlockEnd, End)); assert(VNI && "Missing def for complex mapped value"); DEBUG(dbgs() << ':' << VNI->id << "*BB#" << MBB->getNumber()); // MBB has its own def. Is it also live-out? - if (BlockEnd <= End) { - LiveOutSeen.set(MBB->getNumber()); - LiveOutCache[MBB] = LiveOutPair(VNI, MDT[MBB]); - } + if (BlockEnd <= End) + LRC.setLiveOutValue(MBB, VNI); + // Skip to the next block for live-in. ++MBB; BlockStart = BlockEnd; @@ -866,25 +880,19 @@ bool SplitEditor::transferValues() { if (BlockStart == ParentVNI->def) { // This block has the def of a parent PHI, so it isn't live-in. assert(ParentVNI->isPHIDef() && "Non-phi defined at block start?"); - VNInfo *VNI = LI->extendInBlock(BlockStart, - std::min(BlockEnd, End).getPrevSlot()); + VNInfo *VNI = LI->extendInBlock(BlockStart, std::min(BlockEnd, End)); assert(VNI && "Missing def for complex mapped parent PHI"); - if (End >= BlockEnd) { - // Live-out as well. - LiveOutSeen.set(MBB->getNumber()); - LiveOutCache[MBB] = LiveOutPair(VNI, MDT[MBB]); - } + if (End >= BlockEnd) + LRC.setLiveOutValue(MBB, VNI); // Live-out as well. } else { - // This block needs a live-in value. - LiveInBlocks.push_back(MDT[MBB]); - // The last block covered may not be live-out. + // This block needs a live-in value. The last block covered may not + // be live-out. if (End < BlockEnd) - LiveInBlocks.back().Kill = End; + LRC.addLiveInBlock(LI, MDT[MBB], End); else { - // Live-out, but we need updateSSA to tell us the value. - LiveOutSeen.set(MBB->getNumber()); - LiveOutCache[MBB] = LiveOutPair((VNInfo*)0, - (MachineDomTreeNode*)0); + // Live-through, and we don't know the value. + LRC.addLiveInBlock(LI, MDT[MBB]); + LRC.setLiveOutValue(MBB, 0); } } BlockStart = BlockEnd; @@ -895,8 +903,11 @@ bool SplitEditor::transferValues() { DEBUG(dbgs() << '\n'); } - if (!LiveInBlocks.empty()) - updateSSA(); + LRCalc[0].calculateValues(LIS.getSlotIndexes(), &MDT, + &LIS.getVNInfoAllocator()); + if (SpillMode) + LRCalc[1].calculateValues(LIS.getSlotIndexes(), &MDT, + &LIS.getVNInfoAllocator()); return Skipped; } @@ -909,16 +920,20 @@ void SplitEditor::extendPHIKillRanges() { if (PHIVNI->isUnused() || !PHIVNI->isPHIDef()) continue; unsigned RegIdx = RegAssign.lookup(PHIVNI->def); + LiveInterval *LI = Edit->get(RegIdx); + LiveRangeCalc &LRC = getLRCalc(RegIdx); MachineBasicBlock *MBB = LIS.getMBBFromIndex(PHIVNI->def); for (MachineBasicBlock::pred_iterator PI = MBB->pred_begin(), PE = MBB->pred_end(); PI != PE; ++PI) { - SlotIndex End = LIS.getMBBEndIdx(*PI).getPrevSlot(); + SlotIndex End = LIS.getMBBEndIdx(*PI); + SlotIndex LastUse = End.getPrevSlot(); // The predecessor may not have a live-out value. That is OK, like an // undef PHI operand. - if (Edit->getParent().liveAt(End)) { - assert(RegAssign.lookup(End) == RegIdx && + if (Edit->getParent().liveAt(LastUse)) { + assert(RegAssign.lookup(LastUse) == RegIdx && "Different register assignment in phi predecessor"); - extendRange(RegIdx, End); + LRC.extend(LI, End, + LIS.getSlotIndexes(), &MDT, &LIS.getVNInfoAllocator()); } } } @@ -938,25 +953,22 @@ void SplitEditor::rewriteAssigned(bool ExtendRanges) { continue; } - // operands don't really read the register, so just assign them to - // the complement. - if (MO.isUse() && MO.isUndef()) { - MO.setReg(Edit->get(0)->reg); - continue; - } - + // operands don't really read the register, so it doesn't matter + // which register we choose. When the use operand is tied to a def, we must + // use the same register as the def, so just do that always. SlotIndex Idx = LIS.getInstructionIndex(MI); - if (MO.isDef()) + if (MO.isDef() || MO.isUndef()) Idx = MO.isEarlyClobber() ? Idx.getUseIndex() : Idx.getDefIndex(); // Rewrite to the mapped register at Idx. unsigned RegIdx = RegAssign.lookup(Idx); - MO.setReg(Edit->get(RegIdx)->reg); + LiveInterval *LI = Edit->get(RegIdx); + MO.setReg(LI->reg); DEBUG(dbgs() << " rewr BB#" << MI->getParent()->getNumber() << '\t' << Idx << ':' << RegIdx << '\t' << *MI); // Extend liveness to Idx if the instruction reads reg. - if (!ExtendRanges) + if (!ExtendRanges || MO.isUndef()) continue; // Skip instructions that don't read Reg. @@ -971,7 +983,8 @@ void SplitEditor::rewriteAssigned(bool ExtendRanges) { } else Idx = Idx.getUseIndex(); - extendRange(RegIdx, Idx); + getLRCalc(RegIdx).extend(LI, Idx.getNextSlot(), LIS.getSlotIndexes(), + &MDT, &LIS.getVNInfoAllocator()); } } @@ -1019,11 +1032,24 @@ void SplitEditor::finish(SmallVectorImpl *LRMap) { VNI->setIsPHIDef(ParentVNI->isPHIDef()); VNI->setCopy(ParentVNI->getCopy()); - // Mark rematted values as complex everywhere to force liveness computation. + // Force rematted values to be recomputed everywhere. // The new live ranges may be truncated. if (Edit->didRematerialize(ParentVNI)) for (unsigned i = 0, e = Edit->size(); i != e; ++i) - markComplexMapped(i, ParentVNI); + forceRecompute(i, ParentVNI); + } + + // Hoist back-copies to the complement interval when in spill mode. + switch (SpillMode) { + case SM_Partition: + // Leave all back-copies as is. + break; + case SM_Size: + hoistCopiesForSize(); + break; + case SM_Speed: + llvm_unreachable("Spill mode 'speed' not implemented yet"); + break; } // Transfer the simply mapped values, check if any are skipped. @@ -1081,50 +1107,39 @@ void SplitEditor::finish(SmallVectorImpl *LRMap) { // Single Block Splitting //===----------------------------------------------------------------------===// -/// getMultiUseBlocks - if CurLI has more than one use in a basic block, it -/// may be an advantage to split CurLI for the duration of the block. -bool SplitAnalysis::getMultiUseBlocks(BlockPtrSet &Blocks) { - // If CurLI is local to one block, there is no point to splitting it. - if (UseBlocks.size() <= 1) +bool SplitAnalysis::shouldSplitSingleBlock(const BlockInfo &BI, + bool SingleInstrs) const { + // Always split for multiple instructions. + if (!BI.isOneInstr()) + return true; + // Don't split for single instructions unless explicitly requested. + if (!SingleInstrs) return false; - // Add blocks with multiple uses. - for (unsigned i = 0, e = UseBlocks.size(); i != e; ++i) { - const BlockInfo &BI = UseBlocks[i]; - if (BI.FirstUse == BI.LastUse) - continue; - Blocks.insert(BI.MBB); - } - return !Blocks.empty(); + // Splitting a live-through range always makes progress. + if (BI.LiveIn && BI.LiveOut) + return true; + // No point in isolating a copy. It has no register class constraints. + if (LIS.getInstructionFromIndex(BI.FirstInstr)->isCopyLike()) + return false; + // Finally, don't isolate an end point that was created by earlier splits. + return isOriginalEndpoint(BI.FirstInstr); } void SplitEditor::splitSingleBlock(const SplitAnalysis::BlockInfo &BI) { openIntv(); SlotIndex LastSplitPoint = SA.getLastSplitPoint(BI.MBB->getNumber()); - SlotIndex SegStart = enterIntvBefore(std::min(BI.FirstUse, + SlotIndex SegStart = enterIntvBefore(std::min(BI.FirstInstr, LastSplitPoint)); - if (!BI.LiveOut || BI.LastUse < LastSplitPoint) { - useIntv(SegStart, leaveIntvAfter(BI.LastUse)); + if (!BI.LiveOut || BI.LastInstr < LastSplitPoint) { + useIntv(SegStart, leaveIntvAfter(BI.LastInstr)); } else { // The last use is after the last valid split point. SlotIndex SegStop = leaveIntvBefore(LastSplitPoint); useIntv(SegStart, SegStop); - overlapIntv(SegStop, BI.LastUse); + overlapIntv(SegStop, BI.LastInstr); } } -/// splitSingleBlocks - Split CurLI into a separate live interval inside each -/// basic block in Blocks. -void SplitEditor::splitSingleBlocks(const SplitAnalysis::BlockPtrSet &Blocks) { - DEBUG(dbgs() << " splitSingleBlocks for " << Blocks.size() << " blocks.\n"); - ArrayRef UseBlocks = SA.getUseBlocks(); - for (unsigned i = 0; i != UseBlocks.size(); ++i) { - const SplitAnalysis::BlockInfo &BI = UseBlocks[i]; - if (Blocks.count(BI.MBB)) - splitSingleBlock(BI); - } - finish(); -} - //===----------------------------------------------------------------------===// // Global Live Range Splitting Support @@ -1149,6 +1164,12 @@ void SplitEditor::splitLiveThroughBlock(unsigned MBBNum, assert((IntvIn || IntvOut) && "Use splitSingleBlock for isolated blocks"); + assert((!LeaveBefore || LeaveBefore < Stop) && "Interference after block"); + assert((!IntvIn || !LeaveBefore || LeaveBefore > Start) && "Impossible intf"); + assert((!EnterAfter || EnterAfter >= Start) && "Interference before block"); + + MachineBasicBlock *MBB = VRM.getMachineFunction().getBlockNumbered(MBBNum); + if (!IntvOut) { DEBUG(dbgs() << ", spill on entry.\n"); // @@ -1157,7 +1178,6 @@ void SplitEditor::splitLiveThroughBlock(unsigned MBBNum, // -____________ Spill on entry. // selectIntv(IntvIn); - MachineBasicBlock *MBB = VRM.getMachineFunction().getBlockNumbered(MBBNum); SlotIndex Idx = leaveIntvAtTop(*MBB); assert((!LeaveBefore || Idx <= LeaveBefore) && "Interference"); (void)Idx; @@ -1172,7 +1192,6 @@ void SplitEditor::splitLiveThroughBlock(unsigned MBBNum, // ___________-- Reload on exit. // selectIntv(IntvOut); - MachineBasicBlock *MBB = VRM.getMachineFunction().getBlockNumbered(MBBNum); SlotIndex Idx = enterIntvAtEnd(*MBB); assert((!EnterAfter || Idx >= EnterAfter) && "Interference"); (void)Idx; @@ -1192,6 +1211,7 @@ void SplitEditor::splitLiveThroughBlock(unsigned MBBNum, // We cannot legally insert splits after LSP. SlotIndex LSP = SA.getLastSplitPoint(MBBNum); + assert((!IntvOut || !EnterAfter || EnterAfter < LSP) && "Impossible intf"); if (IntvIn != IntvOut && (!LeaveBefore || !EnterAfter || LeaveBefore.getBaseIndex() > EnterAfter.getBoundaryIndex())) { @@ -1201,10 +1221,14 @@ void SplitEditor::splitLiveThroughBlock(unsigned MBBNum, // |-----------| Live through. // ------======= Switch intervals between interference. // - SlotIndex Cut = (LeaveBefore && LeaveBefore < LSP) ? LeaveBefore : LSP; selectIntv(IntvOut); - SlotIndex Idx = enterIntvBefore(Cut); - useIntv(Idx, Stop); + SlotIndex Idx; + if (LeaveBefore && LeaveBefore < LSP) { + Idx = enterIntvBefore(LeaveBefore); + useIntv(Idx, Stop); + } else { + Idx = enterIntvAtEnd(*MBB); + } selectIntv(IntvIn); useIntv(Start, Idx); assert((!LeaveBefore || Idx <= LeaveBefore) && "Interference"); @@ -1238,7 +1262,7 @@ void SplitEditor::splitRegInBlock(const SplitAnalysis::BlockInfo &BI, tie(Start, Stop) = LIS.getSlotIndexes()->getMBBRange(BI.MBB); DEBUG(dbgs() << "BB#" << BI.MBB->getNumber() << " [" << Start << ';' << Stop - << "), uses " << BI.FirstUse << '-' << BI.LastUse + << "), uses " << BI.FirstInstr << '-' << BI.LastInstr << ", reg-in " << IntvIn << ", leave before " << LeaveBefore << (BI.LiveOut ? ", stack-out" : ", killed in block")); @@ -1246,7 +1270,7 @@ void SplitEditor::splitRegInBlock(const SplitAnalysis::BlockInfo &BI, assert(BI.LiveIn && "Must be live-in"); assert((!LeaveBefore || LeaveBefore > Start) && "Bad interference"); - if (!BI.LiveOut && (!LeaveBefore || LeaveBefore >= BI.LastUse)) { + if (!BI.LiveOut && (!LeaveBefore || LeaveBefore >= BI.LastInstr)) { DEBUG(dbgs() << " before interference.\n"); // // <<< Interference after kill. @@ -1254,13 +1278,13 @@ void SplitEditor::splitRegInBlock(const SplitAnalysis::BlockInfo &BI, // ========= Use IntvIn everywhere. // selectIntv(IntvIn); - useIntv(Start, BI.LastUse); + useIntv(Start, BI.LastInstr); return; } SlotIndex LSP = SA.getLastSplitPoint(BI.MBB->getNumber()); - if (!LeaveBefore || LeaveBefore > BI.LastUse.getBoundaryIndex()) { + if (!LeaveBefore || LeaveBefore > BI.LastInstr.getBoundaryIndex()) { // // <<< Possible interference after last use. // |---o---o---| Live-out on stack. @@ -1271,17 +1295,17 @@ void SplitEditor::splitRegInBlock(const SplitAnalysis::BlockInfo &BI, // ============ Copy to stack after LSP, overlap IntvIn. // \_____ Stack interval is live-out. // - if (BI.LastUse < LSP) { + if (BI.LastInstr < LSP) { DEBUG(dbgs() << ", spill after last use before interference.\n"); selectIntv(IntvIn); - SlotIndex Idx = leaveIntvAfter(BI.LastUse); + SlotIndex Idx = leaveIntvAfter(BI.LastInstr); useIntv(Start, Idx); assert((!LeaveBefore || Idx <= LeaveBefore) && "Interference"); } else { DEBUG(dbgs() << ", spill before last split point.\n"); selectIntv(IntvIn); SlotIndex Idx = leaveIntvBefore(LSP); - overlapIntv(Idx, BI.LastUse); + overlapIntv(Idx, BI.LastInstr); useIntv(Start, Idx); assert((!LeaveBefore || Idx <= LeaveBefore) && "Interference"); } @@ -1295,13 +1319,13 @@ void SplitEditor::splitRegInBlock(const SplitAnalysis::BlockInfo &BI, (void)LocalIntv; DEBUG(dbgs() << ", creating local interval " << LocalIntv << ".\n"); - if (!BI.LiveOut || BI.LastUse < LSP) { + if (!BI.LiveOut || BI.LastInstr < LSP) { // // <<<<<<< Interference overlapping uses. // |---o---o---| Live-out on stack. // =====----____ Leave IntvIn before interference, then spill. // - SlotIndex To = leaveIntvAfter(BI.LastUse); + SlotIndex To = leaveIntvAfter(BI.LastInstr); SlotIndex From = enterIntvBefore(LeaveBefore); useIntv(From, To); selectIntv(IntvIn); @@ -1316,7 +1340,7 @@ void SplitEditor::splitRegInBlock(const SplitAnalysis::BlockInfo &BI, // \_____ Stack interval is live-out. // SlotIndex To = leaveIntvBefore(LSP); - overlapIntv(To, BI.LastUse); + overlapIntv(To, BI.LastInstr); SlotIndex From = enterIntvBefore(std::min(To, LeaveBefore)); useIntv(From, To); selectIntv(IntvIn); @@ -1330,7 +1354,7 @@ void SplitEditor::splitRegOutBlock(const SplitAnalysis::BlockInfo &BI, tie(Start, Stop) = LIS.getSlotIndexes()->getMBBRange(BI.MBB); DEBUG(dbgs() << "BB#" << BI.MBB->getNumber() << " [" << Start << ';' << Stop - << "), uses " << BI.FirstUse << '-' << BI.LastUse + << "), uses " << BI.FirstInstr << '-' << BI.LastInstr << ", reg-out " << IntvOut << ", enter after " << EnterAfter << (BI.LiveIn ? ", stack-in" : ", defined in block")); @@ -1340,7 +1364,7 @@ void SplitEditor::splitRegOutBlock(const SplitAnalysis::BlockInfo &BI, assert(BI.LiveOut && "Must be live-out"); assert((!EnterAfter || EnterAfter < LSP) && "Bad interference"); - if (!BI.LiveIn && (!EnterAfter || EnterAfter <= BI.FirstUse)) { + if (!BI.LiveIn && (!EnterAfter || EnterAfter <= BI.FirstInstr)) { DEBUG(dbgs() << " after interference.\n"); // // >>>> Interference before def. @@ -1348,11 +1372,11 @@ void SplitEditor::splitRegOutBlock(const SplitAnalysis::BlockInfo &BI, // ========= Use IntvOut everywhere. // selectIntv(IntvOut); - useIntv(BI.FirstUse, Stop); + useIntv(BI.FirstInstr, Stop); return; } - if (!EnterAfter || EnterAfter < BI.FirstUse.getBaseIndex()) { + if (!EnterAfter || EnterAfter < BI.FirstInstr.getBaseIndex()) { DEBUG(dbgs() << ", reload after interference.\n"); // // >>>> Interference before def. @@ -1360,7 +1384,7 @@ void SplitEditor::splitRegOutBlock(const SplitAnalysis::BlockInfo &BI, // ____========= Enter IntvOut before first use. // selectIntv(IntvOut); - SlotIndex Idx = enterIntvBefore(std::min(LSP, BI.FirstUse)); + SlotIndex Idx = enterIntvBefore(std::min(LSP, BI.FirstInstr)); useIntv(Idx, Stop); assert((!EnterAfter || Idx >= EnterAfter) && "Interference"); return; @@ -1381,6 +1405,6 @@ void SplitEditor::splitRegOutBlock(const SplitAnalysis::BlockInfo &BI, assert((!EnterAfter || Idx >= EnterAfter) && "Interference"); openIntv(); - SlotIndex From = enterIntvBefore(std::min(Idx, BI.FirstUse)); + SlotIndex From = enterIntvBefore(std::min(Idx, BI.FirstInstr)); useIntv(From, Idx); } diff --git a/contrib/llvm/lib/CodeGen/SplitKit.h b/contrib/llvm/lib/CodeGen/SplitKit.h index 7948b725f..d8fc2122a 100644 --- a/contrib/llvm/lib/CodeGen/SplitKit.h +++ b/contrib/llvm/lib/CodeGen/SplitKit.h @@ -15,13 +15,11 @@ #ifndef LLVM_CODEGEN_SPLITKIT_H #define LLVM_CODEGEN_SPLITKIT_H +#include "LiveRangeCalc.h" #include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/BitVector.h" #include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/IndexedMap.h" #include "llvm/ADT/IntervalMap.h" #include "llvm/ADT/SmallPtrSet.h" -#include "llvm/CodeGen/SlotIndexes.h" namespace llvm { @@ -38,12 +36,6 @@ class VirtRegMap; class VNInfo; class raw_ostream; -/// At some point we should just include MachineDominators.h: -class MachineDominatorTree; -template class DomTreeNodeBase; -typedef DomTreeNodeBase MachineDomTreeNode; - - /// SplitAnalysis - Analyze a LiveInterval, looking for live range splitting /// opportunities. class SplitAnalysis { @@ -76,16 +68,16 @@ public: /// struct BlockInfo { MachineBasicBlock *MBB; - SlotIndex FirstUse; ///< First instr using current reg. - SlotIndex LastUse; ///< Last instr using current reg. - bool LiveThrough; ///< Live in whole block (Templ 5. above). + SlotIndex FirstInstr; ///< First instr accessing current reg. + SlotIndex LastInstr; ///< Last instr accessing current reg. + SlotIndex FirstDef; ///< First non-phi valno->def, or SlotIndex(). bool LiveIn; ///< Current reg is live in. bool LiveOut; ///< Current reg is live out. /// isOneInstr - Returns true when this BlockInfo describes a single /// instruction. bool isOneInstr() const { - return SlotIndex::isSameInstr(FirstUse, LastUse); + return SlotIndex::isSameInstr(FirstInstr, LastInstr); } }; @@ -185,10 +177,15 @@ public: typedef SmallPtrSet BlockPtrSet; - /// getMultiUseBlocks - Add basic blocks to Blocks that may benefit from - /// having CurLI split to a new live interval. Return true if Blocks can be - /// passed to SplitEditor::splitSingleBlocks. - bool getMultiUseBlocks(BlockPtrSet &Blocks); + /// shouldSplitSingleBlock - Returns true if it would help to create a local + /// live range for the instructions in BI. There is normally no benefit to + /// creating a live range for a single instruction, but it does enable + /// register class inflation if the instruction has a restricted register + /// class. + /// + /// @param BI The block to be isolated. + /// @param SingleInstrs True when single instructions should be isolated. + bool shouldSplitSingleBlock(const BlockInfo &BI, bool SingleInstrs) const; }; @@ -212,6 +209,36 @@ class SplitEditor { const TargetInstrInfo &TII; const TargetRegisterInfo &TRI; +public: + + /// ComplementSpillMode - Select how the complement live range should be + /// created. SplitEditor automatically creates interval 0 to contain + /// anything that isn't added to another interval. This complement interval + /// can get quite complicated, and it can sometimes be an advantage to allow + /// it to overlap the other intervals. If it is going to spill anyway, no + /// registers are wasted by keeping a value in two places at the same time. + enum ComplementSpillMode { + /// SM_Partition(Default) - Try to create the complement interval so it + /// doesn't overlap any other intervals, and the original interval is + /// partitioned. This may require a large number of back copies and extra + /// PHI-defs. Only segments marked with overlapIntv will be overlapping. + SM_Partition, + + /// SM_Size - Overlap intervals to minimize the number of inserted COPY + /// instructions. Copies to the complement interval are hoisted to their + /// common dominator, so only one COPY is required per value in the + /// complement interval. This also means that no extra PHI-defs need to be + /// inserted in the complement interval. + SM_Size, + + /// SM_Speed - Overlap intervals to minimize the expected execution + /// frequency of the inserted copies. This is very similar to SM_Size, but + /// the complement interval may get some extra PHI-defs. + SM_Speed + }; + +private: + /// Edit - The current parent register and new intervals created. LiveRangeEdit *Edit; @@ -220,6 +247,9 @@ class SplitEditor { /// openIntv will be 1. unsigned OpenIdx; + /// The current spill mode, selected by reset(). + ComplementSpillMode SpillMode; + typedef IntervalMap RegAssignMap; /// Allocator for the interval map. This will eventually be shared with @@ -231,65 +261,34 @@ class SplitEditor { /// Idx. RegAssignMap RegAssign; - typedef DenseMap, VNInfo*> ValueMap; + typedef PointerIntPair ValueForcePair; + typedef DenseMap, ValueForcePair> ValueMap; /// Values - keep track of the mapping from parent values to values in the new /// intervals. Given a pair (RegIdx, ParentVNI->id), Values contains: /// /// 1. No entry - the value is not mapped to Edit.get(RegIdx). - /// 2. Null - the value is mapped to multiple values in Edit.get(RegIdx). - /// Each value is represented by a minimal live range at its def. - /// 3. A non-null VNInfo - the value is mapped to a single new value. + /// 2. (Null, false) - the value is mapped to multiple values in + /// Edit.get(RegIdx). Each value is represented by a minimal live range at + /// its def. The full live range can be inferred exactly from the range + /// of RegIdx in RegAssign. + /// 3. (Null, true). As above, but the ranges in RegAssign are too large, and + /// the live range must be recomputed using LiveRangeCalc::extend(). + /// 4. (VNI, false) The value is mapped to a single new value. /// The new value has no live ranges anywhere. ValueMap Values; - typedef std::pair LiveOutPair; - typedef IndexedMap LiveOutMap; - - // LiveOutCache - Map each basic block where a new register is live out to the - // live-out value and its defining block. - // One of these conditions shall be true: - // - // 1. !LiveOutCache.count(MBB) - // 2. LiveOutCache[MBB].second.getNode() == MBB - // 3. forall P in preds(MBB): LiveOutCache[P] == LiveOutCache[MBB] - // - // This is only a cache, the values can be computed as: - // - // VNI = Edit.get(RegIdx)->getVNInfoAt(LIS.getMBBEndIdx(MBB)) - // Node = mbt_[LIS.getMBBFromIndex(VNI->def)] - // - // The cache is also used as a visited set by extendRange(). It can be shared - // by all the new registers because at most one is live out of each block. - LiveOutMap LiveOutCache; - - // LiveOutSeen - Indexed by MBB->getNumber(), a bit is set for each valid - // entry in LiveOutCache. - BitVector LiveOutSeen; - - /// LiveInBlock - Info for updateSSA() about a block where a register is - /// live-in. - /// The updateSSA caller provides DomNode and Kill inside MBB, updateSSA() - /// adds the computed live-in value. - struct LiveInBlock { - // Dominator tree node for the block. - // Cleared by updateSSA when the final value has been determined. - MachineDomTreeNode *DomNode; - - // Live-in value filled in by updateSSA once it is known. - VNInfo *Value; - - // Position in block where the live-in range ends, or SlotIndex() if the - // range passes through the block. - SlotIndex Kill; - - LiveInBlock(MachineDomTreeNode *node) : DomNode(node), Value(0) {} - }; + /// LRCalc - Cache for computing live ranges and SSA update. Each instance + /// can only handle non-overlapping live ranges, so use a separate + /// LiveRangeCalc instance for the complement interval when in spill mode. + LiveRangeCalc LRCalc[2]; - /// LiveInBlocks - List of live-in blocks used by findReachingDefs() and - /// updateSSA(). This list is usually empty, it exists here to avoid frequent - /// reallocations. - SmallVector LiveInBlocks; + /// getLRCalc - Return the LRCalc to use for RegIdx. In spill mode, the + /// complement interval can overlap the other intervals, so it gets its own + /// LRCalc instance. When not in spill mode, all intervals can share one. + LiveRangeCalc &getLRCalc(unsigned RegIdx) { + return LRCalc[SpillMode != SM_Partition && RegIdx != 0]; + } /// defValue - define a value in RegIdx from ParentVNI at Idx. /// Idx does not have to be ParentVNI->def, but it must be contained within @@ -298,9 +297,11 @@ class SplitEditor { /// Return the new LI value. VNInfo *defValue(unsigned RegIdx, const VNInfo *ParentVNI, SlotIndex Idx); - /// markComplexMapped - Mark ParentVNI as complex mapped in RegIdx regardless - /// of the number of defs. - void markComplexMapped(unsigned RegIdx, const VNInfo *ParentVNI); + /// forceRecompute - Force the live range of ParentVNI in RegIdx to be + /// recomputed by LiveRangeCalc::extend regardless of the number of defs. + /// This is used for values whose live range doesn't match RegAssign exactly. + /// They could have rematerialized, or back-copies may have been moved. + void forceRecompute(unsigned RegIdx, const VNInfo *ParentVNI); /// defFromParent - Define Reg from ParentVNI at UseIdx using either /// rematerialization or a COPY from parent. Return the new value. @@ -310,22 +311,18 @@ class SplitEditor { MachineBasicBlock &MBB, MachineBasicBlock::iterator I); - /// extendRange - Extend the live range of Edit.get(RegIdx) so it reaches Idx. - /// Insert PHIDefs as needed to preserve SSA form. - void extendRange(unsigned RegIdx, SlotIndex Idx); + /// removeBackCopies - Remove the copy instructions that defines the values + /// in the vector in the complement interval. + void removeBackCopies(SmallVectorImpl &Copies); - /// findReachingDefs - Starting from MBB, add blocks to LiveInBlocks until all - /// reaching defs for LI are found. - /// @param LI Live interval whose value is needed. - /// @param MBB Block where LI should be live-in. - /// @param Kill Kill point in MBB. - /// @return Unique value seen, or NULL. - VNInfo *findReachingDefs(LiveInterval *LI, MachineBasicBlock *MBB, - SlotIndex Kill); + /// getShallowDominator - Returns the least busy dominator of MBB that is + /// also dominated by DefMBB. Busy is measured by loop depth. + MachineBasicBlock *findShallowDominator(MachineBasicBlock *MBB, + MachineBasicBlock *DefMBB); - /// updateSSA - Compute and insert PHIDefs such that all blocks in - // LiveInBlocks get a known live-in value. Add live ranges to the blocks. - void updateSSA(); + /// hoistCopiesForSize - Hoist back-copies to the complement interval in a + /// way that minimizes code size. This implements the SM_Size spill mode. + void hoistCopiesForSize(); /// transferValues - Transfer values to the new ranges. /// Return true if any ranges were skipped. @@ -348,7 +345,7 @@ public: MachineDominatorTree&); /// reset - Prepare for a new split. - void reset(LiveRangeEdit&); + void reset(LiveRangeEdit&, ComplementSpillMode = SM_Partition); /// Create a new virtual register and live interval. /// Return the interval index, starting from 1. Interval index 0 is the @@ -423,10 +420,6 @@ public: /// split, and doesn't call finish(). void splitSingleBlock(const SplitAnalysis::BlockInfo &BI); - /// splitSingleBlocks - Split CurLI into a separate live interval inside each - /// basic block in Blocks. - void splitSingleBlocks(const SplitAnalysis::BlockPtrSet &Blocks); - /// splitLiveThroughBlock - Split CurLI in the given block such that it /// enters the block in IntvIn and leaves it in IntvOut. There may be uses in /// the block, but they will be ignored when placing split points. diff --git a/contrib/llvm/lib/CodeGen/Splitter.cpp b/contrib/llvm/lib/CodeGen/Splitter.cpp index ec75df4b7..77973b72b 100644 --- a/contrib/llvm/lib/CodeGen/Splitter.cpp +++ b/contrib/llvm/lib/CodeGen/Splitter.cpp @@ -11,7 +11,6 @@ #include "Splitter.h" -#include "RegisterCoalescer.h" #include "llvm/Module.h" #include "llvm/CodeGen/CalcSpillWeights.h" #include "llvm/CodeGen/LiveIntervalAnalysis.h" @@ -20,6 +19,7 @@ #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/Passes.h" #include "llvm/CodeGen/SlotIndexes.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" @@ -262,7 +262,7 @@ namespace llvm { au.addPreserved(); au.addRequired(); au.addPreserved(); - au.addPreserved(); + au.addPreservedID(RegisterCoalescerPassID); au.addPreserved(); au.addPreserved(); au.addRequired(); diff --git a/contrib/llvm/lib/CodeGen/StackProtector.cpp b/contrib/llvm/lib/CodeGen/StackProtector.cpp index d3cbd15b6..1f0e5a271 100644 --- a/contrib/llvm/lib/CodeGen/StackProtector.cpp +++ b/contrib/llvm/lib/CodeGen/StackProtector.cpp @@ -123,7 +123,7 @@ bool StackProtector::RequiresStackProtector() const { // protectors. return true; - if (const ArrayType *AT = dyn_cast(AI->getAllocatedType())) { + if (ArrayType *AT = dyn_cast(AI->getAllocatedType())) { // We apparently only care about character arrays. if (!AT->getElementType()->isIntegerTy(8)) continue; @@ -165,7 +165,7 @@ bool StackProtector::InsertStackProtectors() { // StackGuard = load __stack_chk_guard // call void @llvm.stackprotect.create(StackGuard, StackGuardSlot) // - const PointerType *PtrTy = Type::getInt8PtrTy(RI->getContext()); + PointerType *PtrTy = Type::getInt8PtrTy(RI->getContext()); unsigned AddressSpace, Offset; if (TLI->getStackCookieLocation(AddressSpace, Offset)) { Constant *OffsetVal = diff --git a/contrib/llvm/lib/CodeGen/StrongPHIElimination.cpp b/contrib/llvm/lib/CodeGen/StrongPHIElimination.cpp index 227eb47e6..260cc0ee5 100644 --- a/contrib/llvm/lib/CodeGen/StrongPHIElimination.cpp +++ b/contrib/llvm/lib/CodeGen/StrongPHIElimination.cpp @@ -47,6 +47,7 @@ #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/Target/TargetInstrInfo.h" +#include "llvm/ADT/DenseSet.h" #include "llvm/ADT/Statistic.h" #include "llvm/Support/Debug.h" using namespace llvm; @@ -673,7 +674,7 @@ void StrongPHIElimination::InsertCopiesForPHI(MachineInstr *PHI, if (PHIColor && SrcColor == PHIColor) { LiveInterval &SrcInterval = LI->getInterval(SrcReg); SlotIndex PredIndex = LI->getMBBEndIdx(PredBB); - VNInfo *SrcVNI = SrcInterval.getVNInfoAt(PredIndex.getPrevIndex()); + VNInfo *SrcVNI = SrcInterval.getVNInfoBefore(PredIndex); assert(SrcVNI); SrcVNI->setHasPHIKill(true); continue; diff --git a/contrib/llvm/lib/CodeGen/TailDuplication.cpp b/contrib/llvm/lib/CodeGen/TailDuplication.cpp index 6b801cbf6..3a6211a0f 100644 --- a/contrib/llvm/lib/CodeGen/TailDuplication.cpp +++ b/contrib/llvm/lib/CodeGen/TailDuplication.cpp @@ -25,6 +25,7 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/DenseSet.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SetVector.h" #include "llvm/ADT/Statistic.h" diff --git a/contrib/llvm/lib/CodeGen/TargetInstrInfoImpl.cpp b/contrib/llvm/lib/CodeGen/TargetInstrInfoImpl.cpp index 86e71d8cc..f32678f12 100644 --- a/contrib/llvm/lib/CodeGen/TargetInstrInfoImpl.cpp +++ b/contrib/llvm/lib/CodeGen/TargetInstrInfoImpl.cpp @@ -74,23 +74,25 @@ MachineInstr *TargetInstrInfoImpl::commuteInstruction(MachineInstr *MI, assert(MI->getOperand(Idx1).isReg() && MI->getOperand(Idx2).isReg() && "This only knows how to commute register operands so far"); + unsigned Reg0 = HasDef ? MI->getOperand(0).getReg() : 0; unsigned Reg1 = MI->getOperand(Idx1).getReg(); unsigned Reg2 = MI->getOperand(Idx2).getReg(); bool Reg1IsKill = MI->getOperand(Idx1).isKill(); bool Reg2IsKill = MI->getOperand(Idx2).isKill(); - bool ChangeReg0 = false; - if (HasDef && MI->getOperand(0).getReg() == Reg1) { - // Must be two address instruction! - assert(MI->getDesc().getOperandConstraint(0, MCOI::TIED_TO) && - "Expecting a two-address instruction!"); + // If destination is tied to either of the commuted source register, then + // it must be updated. + if (HasDef && Reg0 == Reg1 && + MI->getDesc().getOperandConstraint(Idx1, MCOI::TIED_TO) == 0) { Reg2IsKill = false; - ChangeReg0 = true; + Reg0 = Reg2; + } else if (HasDef && Reg0 == Reg2 && + MI->getDesc().getOperandConstraint(Idx2, MCOI::TIED_TO) == 0) { + Reg1IsKill = false; + Reg0 = Reg1; } if (NewMI) { // Create a new instruction. - unsigned Reg0 = HasDef - ? (ChangeReg0 ? Reg2 : MI->getOperand(0).getReg()) : 0; bool Reg0IsDead = HasDef ? MI->getOperand(0).isDead() : false; MachineFunction &MF = *MI->getParent()->getParent(); if (HasDef) @@ -104,8 +106,8 @@ MachineInstr *TargetInstrInfoImpl::commuteInstruction(MachineInstr *MI, .addReg(Reg1, getKillRegState(Reg2IsKill)); } - if (ChangeReg0) - MI->getOperand(0).setReg(Reg2); + if (HasDef) + MI->getOperand(0).setReg(Reg0); MI->getOperand(Idx2).setReg(Reg1); MI->getOperand(Idx1).setReg(Reg2); MI->getOperand(Idx2).setIsKill(Reg1IsKill); @@ -160,6 +162,42 @@ bool TargetInstrInfoImpl::PredicateInstruction(MachineInstr *MI, return MadeChange; } +bool TargetInstrInfoImpl::hasLoadFromStackSlot(const MachineInstr *MI, + const MachineMemOperand *&MMO, + int &FrameIndex) const { + for (MachineInstr::mmo_iterator o = MI->memoperands_begin(), + oe = MI->memoperands_end(); + o != oe; + ++o) { + if ((*o)->isLoad() && (*o)->getValue()) + if (const FixedStackPseudoSourceValue *Value = + dyn_cast((*o)->getValue())) { + FrameIndex = Value->getFrameIndex(); + MMO = *o; + return true; + } + } + return false; +} + +bool TargetInstrInfoImpl::hasStoreToStackSlot(const MachineInstr *MI, + const MachineMemOperand *&MMO, + int &FrameIndex) const { + for (MachineInstr::mmo_iterator o = MI->memoperands_begin(), + oe = MI->memoperands_end(); + o != oe; + ++o) { + if ((*o)->isStore() && (*o)->getValue()) + if (const FixedStackPseudoSourceValue *Value = + dyn_cast((*o)->getValue())) { + FrameIndex = Value->getFrameIndex(); + MMO = *o; + return true; + } + } + return false; +} + void TargetInstrInfoImpl::reMaterialize(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, unsigned DestReg, @@ -324,6 +362,19 @@ isReallyTriviallyReMaterializableGeneric(const MachineInstr *MI, const TargetInstrInfo &TII = *TM.getInstrInfo(); const TargetRegisterInfo &TRI = *TM.getRegisterInfo(); + // Remat clients assume operand 0 is the defined register. + if (!MI->getNumOperands() || !MI->getOperand(0).isReg()) + return false; + unsigned DefReg = MI->getOperand(0).getReg(); + + // A sub-register definition can only be rematerialized if the instruction + // doesn't read the other parts of the register. Otherwise it is really a + // read-modify-write operation on the full virtual register which cannot be + // moved safely. + if (TargetRegisterInfo::isVirtualRegister(DefReg) && + MI->getOperand(0).getSubReg() && MI->readsVirtualRegister(DefReg)) + return false; + // A load from a fixed stack slot can be rematerialized. This may be // redundant with subsequent checks, but it's target-independent, // simple, and a common case. @@ -383,8 +434,9 @@ isReallyTriviallyReMaterializableGeneric(const MachineInstr *MI, continue; } - // Only allow one virtual-register def, and that in the first operand. - if (MO.isDef() != (i == 0)) + // Only allow one virtual-register def. There may be multiple defs of the + // same virtual register, though. + if (MO.isDef() && Reg != DefReg) return false; // Don't allow any virtual-register uses. Rematting an instruction with diff --git a/contrib/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/contrib/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp index a3c562013..fb8715423 100644 --- a/contrib/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp +++ b/contrib/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp @@ -43,153 +43,6 @@ using namespace dwarf; // ELF //===----------------------------------------------------------------------===// -TargetLoweringObjectFileELF::TargetLoweringObjectFileELF() - : TargetLoweringObjectFile(), - TLSDataSection(0), - TLSBSSSection(0), - DataRelSection(0), - DataRelLocalSection(0), - DataRelROSection(0), - DataRelROLocalSection(0), - MergeableConst4Section(0), - MergeableConst8Section(0), - MergeableConst16Section(0) { -} - -void TargetLoweringObjectFileELF::Initialize(MCContext &Ctx, - const TargetMachine &TM) { - TargetLoweringObjectFile::Initialize(Ctx, TM); - - BSSSection = - getContext().getELFSection(".bss", ELF::SHT_NOBITS, - ELF::SHF_WRITE |ELF::SHF_ALLOC, - SectionKind::getBSS()); - - TextSection = - getContext().getELFSection(".text", ELF::SHT_PROGBITS, - ELF::SHF_EXECINSTR | - ELF::SHF_ALLOC, - SectionKind::getText()); - - DataSection = - getContext().getELFSection(".data", ELF::SHT_PROGBITS, - ELF::SHF_WRITE |ELF::SHF_ALLOC, - SectionKind::getDataRel()); - - ReadOnlySection = - getContext().getELFSection(".rodata", ELF::SHT_PROGBITS, - ELF::SHF_ALLOC, - SectionKind::getReadOnly()); - - TLSDataSection = - getContext().getELFSection(".tdata", ELF::SHT_PROGBITS, - ELF::SHF_ALLOC | ELF::SHF_TLS | - ELF::SHF_WRITE, - SectionKind::getThreadData()); - - TLSBSSSection = - getContext().getELFSection(".tbss", ELF::SHT_NOBITS, - ELF::SHF_ALLOC | ELF::SHF_TLS | - ELF::SHF_WRITE, - SectionKind::getThreadBSS()); - - DataRelSection = - getContext().getELFSection(".data.rel", ELF::SHT_PROGBITS, - ELF::SHF_ALLOC |ELF::SHF_WRITE, - SectionKind::getDataRel()); - - DataRelLocalSection = - getContext().getELFSection(".data.rel.local", ELF::SHT_PROGBITS, - ELF::SHF_ALLOC |ELF::SHF_WRITE, - SectionKind::getDataRelLocal()); - - DataRelROSection = - getContext().getELFSection(".data.rel.ro", ELF::SHT_PROGBITS, - ELF::SHF_ALLOC |ELF::SHF_WRITE, - SectionKind::getReadOnlyWithRel()); - - DataRelROLocalSection = - getContext().getELFSection(".data.rel.ro.local", ELF::SHT_PROGBITS, - ELF::SHF_ALLOC |ELF::SHF_WRITE, - SectionKind::getReadOnlyWithRelLocal()); - - MergeableConst4Section = - getContext().getELFSection(".rodata.cst4", ELF::SHT_PROGBITS, - ELF::SHF_ALLOC |ELF::SHF_MERGE, - SectionKind::getMergeableConst4()); - - MergeableConst8Section = - getContext().getELFSection(".rodata.cst8", ELF::SHT_PROGBITS, - ELF::SHF_ALLOC |ELF::SHF_MERGE, - SectionKind::getMergeableConst8()); - - MergeableConst16Section = - getContext().getELFSection(".rodata.cst16", ELF::SHT_PROGBITS, - ELF::SHF_ALLOC |ELF::SHF_MERGE, - SectionKind::getMergeableConst16()); - - StaticCtorSection = - getContext().getELFSection(".ctors", ELF::SHT_PROGBITS, - ELF::SHF_ALLOC |ELF::SHF_WRITE, - SectionKind::getDataRel()); - - StaticDtorSection = - getContext().getELFSection(".dtors", ELF::SHT_PROGBITS, - ELF::SHF_ALLOC |ELF::SHF_WRITE, - SectionKind::getDataRel()); - - // Exception Handling Sections. - - // FIXME: We're emitting LSDA info into a readonly section on ELF, even though - // it contains relocatable pointers. In PIC mode, this is probably a big - // runtime hit for C++ apps. Either the contents of the LSDA need to be - // adjusted or this should be a data section. - LSDASection = - getContext().getELFSection(".gcc_except_table", ELF::SHT_PROGBITS, - ELF::SHF_ALLOC, - SectionKind::getReadOnly()); - // Debug Info Sections. - DwarfAbbrevSection = - getContext().getELFSection(".debug_abbrev", ELF::SHT_PROGBITS, 0, - SectionKind::getMetadata()); - DwarfInfoSection = - getContext().getELFSection(".debug_info", ELF::SHT_PROGBITS, 0, - SectionKind::getMetadata()); - DwarfLineSection = - getContext().getELFSection(".debug_line", ELF::SHT_PROGBITS, 0, - SectionKind::getMetadata()); - DwarfFrameSection = - getContext().getELFSection(".debug_frame", ELF::SHT_PROGBITS, 0, - SectionKind::getMetadata()); - DwarfPubNamesSection = - getContext().getELFSection(".debug_pubnames", ELF::SHT_PROGBITS, 0, - SectionKind::getMetadata()); - DwarfPubTypesSection = - getContext().getELFSection(".debug_pubtypes", ELF::SHT_PROGBITS, 0, - SectionKind::getMetadata()); - DwarfStrSection = - getContext().getELFSection(".debug_str", ELF::SHT_PROGBITS, 0, - SectionKind::getMetadata()); - DwarfLocSection = - getContext().getELFSection(".debug_loc", ELF::SHT_PROGBITS, 0, - SectionKind::getMetadata()); - DwarfARangesSection = - getContext().getELFSection(".debug_aranges", ELF::SHT_PROGBITS, 0, - SectionKind::getMetadata()); - DwarfRangesSection = - getContext().getELFSection(".debug_ranges", ELF::SHT_PROGBITS, 0, - SectionKind::getMetadata()); - DwarfMacroInfoSection = - getContext().getELFSection(".debug_macinfo", ELF::SHT_PROGBITS, 0, - SectionKind::getMetadata()); -} - -const MCSection *TargetLoweringObjectFileELF::getEHFrameSection() const { - return getContext().getELFSection(".eh_frame", ELF::SHT_PROGBITS, - ELF::SHF_ALLOC, - SectionKind::getDataRel()); -} - MCSymbol * TargetLoweringObjectFileELF::getCFIPersonalitySymbol(const GlobalValue *GV, Mangler *Mang, @@ -493,221 +346,6 @@ getExprForDwarfGlobalReference(const GlobalValue *GV, Mangler *Mang, // MachO //===----------------------------------------------------------------------===// -TargetLoweringObjectFileMachO::TargetLoweringObjectFileMachO() - : TargetLoweringObjectFile(), - TLSDataSection(0), - TLSBSSSection(0), - TLSTLVSection(0), - TLSThreadInitSection(0), - CStringSection(0), - UStringSection(0), - TextCoalSection(0), - ConstTextCoalSection(0), - ConstDataSection(0), - DataCoalSection(0), - DataCommonSection(0), - DataBSSSection(0), - FourByteConstantSection(0), - EightByteConstantSection(0), - SixteenByteConstantSection(0), - LazySymbolPointerSection(0), - NonLazySymbolPointerSection(0) { -} - -void TargetLoweringObjectFileMachO::Initialize(MCContext &Ctx, - const TargetMachine &TM) { - IsFunctionEHFrameSymbolPrivate = false; - SupportsWeakOmittedEHFrame = false; - - // .comm doesn't support alignment before Leopard. - Triple T(((LLVMTargetMachine&)TM).getTargetTriple()); - if (T.isMacOSX() && T.isMacOSXVersionLT(10, 5)) - CommDirectiveSupportsAlignment = false; - - TargetLoweringObjectFile::Initialize(Ctx, TM); - - TextSection // .text - = getContext().getMachOSection("__TEXT", "__text", - MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, - SectionKind::getText()); - DataSection // .data - = getContext().getMachOSection("__DATA", "__data", 0, - SectionKind::getDataRel()); - - TLSDataSection // .tdata - = getContext().getMachOSection("__DATA", "__thread_data", - MCSectionMachO::S_THREAD_LOCAL_REGULAR, - SectionKind::getDataRel()); - TLSBSSSection // .tbss - = getContext().getMachOSection("__DATA", "__thread_bss", - MCSectionMachO::S_THREAD_LOCAL_ZEROFILL, - SectionKind::getThreadBSS()); - - // TODO: Verify datarel below. - TLSTLVSection // .tlv - = getContext().getMachOSection("__DATA", "__thread_vars", - MCSectionMachO::S_THREAD_LOCAL_VARIABLES, - SectionKind::getDataRel()); - - TLSThreadInitSection - = getContext().getMachOSection("__DATA", "__thread_init", - MCSectionMachO::S_THREAD_LOCAL_INIT_FUNCTION_POINTERS, - SectionKind::getDataRel()); - - CStringSection // .cstring - = getContext().getMachOSection("__TEXT", "__cstring", - MCSectionMachO::S_CSTRING_LITERALS, - SectionKind::getMergeable1ByteCString()); - UStringSection - = getContext().getMachOSection("__TEXT","__ustring", 0, - SectionKind::getMergeable2ByteCString()); - FourByteConstantSection // .literal4 - = getContext().getMachOSection("__TEXT", "__literal4", - MCSectionMachO::S_4BYTE_LITERALS, - SectionKind::getMergeableConst4()); - EightByteConstantSection // .literal8 - = getContext().getMachOSection("__TEXT", "__literal8", - MCSectionMachO::S_8BYTE_LITERALS, - SectionKind::getMergeableConst8()); - - // ld_classic doesn't support .literal16 in 32-bit mode, and ld64 falls back - // to using it in -static mode. - SixteenByteConstantSection = 0; - if (TM.getRelocationModel() != Reloc::Static && - TM.getTargetData()->getPointerSize() == 32) - SixteenByteConstantSection = // .literal16 - getContext().getMachOSection("__TEXT", "__literal16", - MCSectionMachO::S_16BYTE_LITERALS, - SectionKind::getMergeableConst16()); - - ReadOnlySection // .const - = getContext().getMachOSection("__TEXT", "__const", 0, - SectionKind::getReadOnly()); - - TextCoalSection - = getContext().getMachOSection("__TEXT", "__textcoal_nt", - MCSectionMachO::S_COALESCED | - MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, - SectionKind::getText()); - ConstTextCoalSection - = getContext().getMachOSection("__TEXT", "__const_coal", - MCSectionMachO::S_COALESCED, - SectionKind::getReadOnly()); - ConstDataSection // .const_data - = getContext().getMachOSection("__DATA", "__const", 0, - SectionKind::getReadOnlyWithRel()); - DataCoalSection - = getContext().getMachOSection("__DATA","__datacoal_nt", - MCSectionMachO::S_COALESCED, - SectionKind::getDataRel()); - DataCommonSection - = getContext().getMachOSection("__DATA","__common", - MCSectionMachO::S_ZEROFILL, - SectionKind::getBSS()); - DataBSSSection - = getContext().getMachOSection("__DATA","__bss", MCSectionMachO::S_ZEROFILL, - SectionKind::getBSS()); - - - LazySymbolPointerSection - = getContext().getMachOSection("__DATA", "__la_symbol_ptr", - MCSectionMachO::S_LAZY_SYMBOL_POINTERS, - SectionKind::getMetadata()); - NonLazySymbolPointerSection - = getContext().getMachOSection("__DATA", "__nl_symbol_ptr", - MCSectionMachO::S_NON_LAZY_SYMBOL_POINTERS, - SectionKind::getMetadata()); - - if (TM.getRelocationModel() == Reloc::Static) { - StaticCtorSection - = getContext().getMachOSection("__TEXT", "__constructor", 0, - SectionKind::getDataRel()); - StaticDtorSection - = getContext().getMachOSection("__TEXT", "__destructor", 0, - SectionKind::getDataRel()); - } else { - StaticCtorSection - = getContext().getMachOSection("__DATA", "__mod_init_func", - MCSectionMachO::S_MOD_INIT_FUNC_POINTERS, - SectionKind::getDataRel()); - StaticDtorSection - = getContext().getMachOSection("__DATA", "__mod_term_func", - MCSectionMachO::S_MOD_TERM_FUNC_POINTERS, - SectionKind::getDataRel()); - } - - // Exception Handling. - LSDASection = getContext().getMachOSection("__TEXT", "__gcc_except_tab", 0, - SectionKind::getReadOnlyWithRel()); - - if (T.isMacOSX() && !T.isMacOSXVersionLT(10, 6)) - CompactUnwindSection = - getContext().getMachOSection("__LD", "__compact_unwind", - MCSectionMachO::S_ATTR_DEBUG, - SectionKind::getReadOnly()); - - // Debug Information. - DwarfAbbrevSection = - getContext().getMachOSection("__DWARF", "__debug_abbrev", - MCSectionMachO::S_ATTR_DEBUG, - SectionKind::getMetadata()); - DwarfInfoSection = - getContext().getMachOSection("__DWARF", "__debug_info", - MCSectionMachO::S_ATTR_DEBUG, - SectionKind::getMetadata()); - DwarfLineSection = - getContext().getMachOSection("__DWARF", "__debug_line", - MCSectionMachO::S_ATTR_DEBUG, - SectionKind::getMetadata()); - DwarfFrameSection = - getContext().getMachOSection("__DWARF", "__debug_frame", - MCSectionMachO::S_ATTR_DEBUG, - SectionKind::getMetadata()); - DwarfPubNamesSection = - getContext().getMachOSection("__DWARF", "__debug_pubnames", - MCSectionMachO::S_ATTR_DEBUG, - SectionKind::getMetadata()); - DwarfPubTypesSection = - getContext().getMachOSection("__DWARF", "__debug_pubtypes", - MCSectionMachO::S_ATTR_DEBUG, - SectionKind::getMetadata()); - DwarfStrSection = - getContext().getMachOSection("__DWARF", "__debug_str", - MCSectionMachO::S_ATTR_DEBUG, - SectionKind::getMetadata()); - DwarfLocSection = - getContext().getMachOSection("__DWARF", "__debug_loc", - MCSectionMachO::S_ATTR_DEBUG, - SectionKind::getMetadata()); - DwarfARangesSection = - getContext().getMachOSection("__DWARF", "__debug_aranges", - MCSectionMachO::S_ATTR_DEBUG, - SectionKind::getMetadata()); - DwarfRangesSection = - getContext().getMachOSection("__DWARF", "__debug_ranges", - MCSectionMachO::S_ATTR_DEBUG, - SectionKind::getMetadata()); - DwarfMacroInfoSection = - getContext().getMachOSection("__DWARF", "__debug_macinfo", - MCSectionMachO::S_ATTR_DEBUG, - SectionKind::getMetadata()); - DwarfDebugInlineSection = - getContext().getMachOSection("__DWARF", "__debug_inlined", - MCSectionMachO::S_ATTR_DEBUG, - SectionKind::getMetadata()); - - TLSExtraDataSection = TLSTLVSection; -} - -const MCSection *TargetLoweringObjectFileMachO::getEHFrameSection() const { - return getContext().getMachOSection("__TEXT", "__eh_frame", - MCSectionMachO::S_COALESCED | - MCSectionMachO::S_ATTR_NO_TOC | - MCSectionMachO::S_ATTR_STRIP_STATIC_SYMS | - MCSectionMachO::S_ATTR_LIVE_SUPPORT, - SectionKind::getReadOnly()); -} - const MCSection *TargetLoweringObjectFileMachO:: getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind, Mangler *Mang, const TargetMachine &TM) const { @@ -905,183 +543,10 @@ getCFIPersonalitySymbol(const GlobalValue *GV, Mangler *Mang, return SSym; } -unsigned TargetLoweringObjectFileMachO::getPersonalityEncoding() const { - return DW_EH_PE_indirect | DW_EH_PE_pcrel | DW_EH_PE_sdata4; -} - -unsigned TargetLoweringObjectFileMachO::getLSDAEncoding() const { - return DW_EH_PE_pcrel; -} - -unsigned TargetLoweringObjectFileMachO::getFDEEncoding(bool CFI) const { - return DW_EH_PE_pcrel; -} - -unsigned TargetLoweringObjectFileMachO::getTTypeEncoding() const { - return DW_EH_PE_indirect | DW_EH_PE_pcrel | DW_EH_PE_sdata4; -} - //===----------------------------------------------------------------------===// // COFF //===----------------------------------------------------------------------===// -TargetLoweringObjectFileCOFF::TargetLoweringObjectFileCOFF() - : TargetLoweringObjectFile(), - DrectveSection(0), - PDataSection(0), - XDataSection(0) { -} - -void TargetLoweringObjectFileCOFF::Initialize(MCContext &Ctx, - const TargetMachine &TM) { - TargetLoweringObjectFile::Initialize(Ctx, TM); - TextSection = - getContext().getCOFFSection(".text", - COFF::IMAGE_SCN_CNT_CODE | - COFF::IMAGE_SCN_MEM_EXECUTE | - COFF::IMAGE_SCN_MEM_READ, - SectionKind::getText()); - DataSection = - getContext().getCOFFSection(".data", - COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | - COFF::IMAGE_SCN_MEM_READ | - COFF::IMAGE_SCN_MEM_WRITE, - SectionKind::getDataRel()); - ReadOnlySection = - getContext().getCOFFSection(".rdata", - COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | - COFF::IMAGE_SCN_MEM_READ, - SectionKind::getReadOnly()); - StaticCtorSection = - getContext().getCOFFSection(".ctors", - COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | - COFF::IMAGE_SCN_MEM_READ | - COFF::IMAGE_SCN_MEM_WRITE, - SectionKind::getDataRel()); - StaticDtorSection = - getContext().getCOFFSection(".dtors", - COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | - COFF::IMAGE_SCN_MEM_READ | - COFF::IMAGE_SCN_MEM_WRITE, - SectionKind::getDataRel()); - - // FIXME: We're emitting LSDA info into a readonly section on COFF, even - // though it contains relocatable pointers. In PIC mode, this is probably a - // big runtime hit for C++ apps. Either the contents of the LSDA need to be - // adjusted or this should be a data section. - LSDASection = - getContext().getCOFFSection(".gcc_except_table", - COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | - COFF::IMAGE_SCN_MEM_READ, - SectionKind::getReadOnly()); - // Debug info. - DwarfAbbrevSection = - getContext().getCOFFSection(".debug_abbrev", - COFF::IMAGE_SCN_MEM_DISCARDABLE | - COFF::IMAGE_SCN_MEM_READ, - SectionKind::getMetadata()); - DwarfInfoSection = - getContext().getCOFFSection(".debug_info", - COFF::IMAGE_SCN_MEM_DISCARDABLE | - COFF::IMAGE_SCN_MEM_READ, - SectionKind::getMetadata()); - DwarfLineSection = - getContext().getCOFFSection(".debug_line", - COFF::IMAGE_SCN_MEM_DISCARDABLE | - COFF::IMAGE_SCN_MEM_READ, - SectionKind::getMetadata()); - DwarfFrameSection = - getContext().getCOFFSection(".debug_frame", - COFF::IMAGE_SCN_MEM_DISCARDABLE | - COFF::IMAGE_SCN_MEM_READ, - SectionKind::getMetadata()); - DwarfPubNamesSection = - getContext().getCOFFSection(".debug_pubnames", - COFF::IMAGE_SCN_MEM_DISCARDABLE | - COFF::IMAGE_SCN_MEM_READ, - SectionKind::getMetadata()); - DwarfPubTypesSection = - getContext().getCOFFSection(".debug_pubtypes", - COFF::IMAGE_SCN_MEM_DISCARDABLE | - COFF::IMAGE_SCN_MEM_READ, - SectionKind::getMetadata()); - DwarfStrSection = - getContext().getCOFFSection(".debug_str", - COFF::IMAGE_SCN_MEM_DISCARDABLE | - COFF::IMAGE_SCN_MEM_READ, - SectionKind::getMetadata()); - DwarfLocSection = - getContext().getCOFFSection(".debug_loc", - COFF::IMAGE_SCN_MEM_DISCARDABLE | - COFF::IMAGE_SCN_MEM_READ, - SectionKind::getMetadata()); - DwarfARangesSection = - getContext().getCOFFSection(".debug_aranges", - COFF::IMAGE_SCN_MEM_DISCARDABLE | - COFF::IMAGE_SCN_MEM_READ, - SectionKind::getMetadata()); - DwarfRangesSection = - getContext().getCOFFSection(".debug_ranges", - COFF::IMAGE_SCN_MEM_DISCARDABLE | - COFF::IMAGE_SCN_MEM_READ, - SectionKind::getMetadata()); - DwarfMacroInfoSection = - getContext().getCOFFSection(".debug_macinfo", - COFF::IMAGE_SCN_MEM_DISCARDABLE | - COFF::IMAGE_SCN_MEM_READ, - SectionKind::getMetadata()); - - DrectveSection = - getContext().getCOFFSection(".drectve", - COFF::IMAGE_SCN_LNK_INFO, - SectionKind::getMetadata()); - - PDataSection = - getContext().getCOFFSection(".pdata", - COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | - COFF::IMAGE_SCN_MEM_READ | - COFF::IMAGE_SCN_MEM_WRITE, - SectionKind::getDataRel()); - - XDataSection = - getContext().getCOFFSection(".xdata", - COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | - COFF::IMAGE_SCN_MEM_READ | - COFF::IMAGE_SCN_MEM_WRITE, - SectionKind::getDataRel()); -} - -const MCSection *TargetLoweringObjectFileCOFF::getEHFrameSection() const { - return getContext().getCOFFSection(".eh_frame", - COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | - COFF::IMAGE_SCN_MEM_READ | - COFF::IMAGE_SCN_MEM_WRITE, - SectionKind::getDataRel()); -} - -const MCSection *TargetLoweringObjectFileCOFF::getWin64EHFuncTableSection( - StringRef suffix) const { - if (suffix == "") - return PDataSection; - return getContext().getCOFFSection((".pdata"+suffix).str(), - COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | - COFF::IMAGE_SCN_MEM_READ | - COFF::IMAGE_SCN_MEM_WRITE, - SectionKind::getDataRel()); -} - -const MCSection *TargetLoweringObjectFileCOFF::getWin64EHTableSection( - StringRef suffix) const { - if (suffix == "") - return XDataSection; - return getContext().getCOFFSection((".xdata"+suffix).str(), - COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | - COFF::IMAGE_SCN_MEM_READ | - COFF::IMAGE_SCN_MEM_WRITE, - SectionKind::getDataRel()); -} - - static unsigned getCOFFSectionFlags(SectionKind K) { unsigned Flags = 0; diff --git a/contrib/llvm/lib/CodeGen/TwoAddressInstructionPass.cpp b/contrib/llvm/lib/CodeGen/TwoAddressInstructionPass.cpp index 6d6244e4f..d87937822 100644 --- a/contrib/llvm/lib/CodeGen/TwoAddressInstructionPass.cpp +++ b/contrib/llvm/lib/CodeGen/TwoAddressInstructionPass.cpp @@ -177,6 +177,10 @@ char &llvm::TwoAddressInstructionPassID = TwoAddressInstructionPass::ID; bool TwoAddressInstructionPass::Sink3AddrInstruction(MachineBasicBlock *MBB, MachineInstr *MI, unsigned SavedReg, MachineBasicBlock::iterator OldPos) { + // FIXME: Shouldn't we be trying to do this before we three-addressify the + // instruction? After this transformation is done, we no longer need + // the instruction to be in three-address form. + // Check if it's safe to move this instruction. bool SeenStore = true; // Be conservative. if (!MI->isSafeToMove(TII, AA, SeenStore)) @@ -217,7 +221,11 @@ bool TwoAddressInstructionPass::Sink3AddrInstruction(MachineBasicBlock *MBB, break; } - if (!KillMI || KillMI->getParent() != MBB || KillMI == MI) + // If we find the instruction that kills SavedReg, and it is in an + // appropriate location, we can try to sink the current instruction + // past it. + if (!KillMI || KillMI->getParent() != MBB || KillMI == MI || + KillMI->getDesc().isTerminator()) return false; // If any of the definitions are used by another instruction between the @@ -1041,6 +1049,9 @@ bool TwoAddressInstructionPass::runOnMachineFunction(MachineFunction &MF) { DEBUG(dbgs() << "********** Function: " << MF.getFunction()->getName() << '\n'); + // This pass takes the function out of SSA form. + MRI->leaveSSA(); + // ReMatRegs - Keep track of the registers whose def's are remat'ed. BitVector ReMatRegs(MRI->getNumVirtRegs()); diff --git a/contrib/llvm/lib/CodeGen/VirtRegMap.cpp b/contrib/llvm/lib/CodeGen/VirtRegMap.cpp index 7557979ec..8a1cdc01c 100644 --- a/contrib/llvm/lib/CodeGen/VirtRegMap.cpp +++ b/contrib/llvm/lib/CodeGen/VirtRegMap.cpp @@ -41,8 +41,8 @@ #include using namespace llvm; -STATISTIC(NumSpills , "Number of register spills"); -STATISTIC(NumIdCopies, "Number of identity moves eliminated after rewriting"); +STATISTIC(NumSpillSlots, "Number of spill slots allocated"); +STATISTIC(NumIdCopies, "Number of identity moves eliminated after rewriting"); //===----------------------------------------------------------------------===// // VirtRegMap implementation @@ -111,6 +111,7 @@ unsigned VirtRegMap::createSpillSlot(const TargetRegisterClass *RC) { unsigned Idx = SS-LowSpillSlot; while (Idx >= SpillSlotToUsesMap.size()) SpillSlotToUsesMap.resize(SpillSlotToUsesMap.size()*2); + ++NumSpillSlots; return SS; } @@ -130,7 +131,6 @@ int VirtRegMap::assignVirt2StackSlot(unsigned virtReg) { assert(Virt2StackSlotMap[virtReg] == NO_STACK_SLOT && "attempt to assign stack slot to already spilled register"); const TargetRegisterClass* RC = MF->getRegInfo().getRegClass(virtReg); - ++NumSpills; return Virt2StackSlotMap[virtReg] = createSpillSlot(RC); } @@ -285,14 +285,24 @@ void VirtRegMap::rewrite(SlotIndexes *Indexes) { // Preserve semantics of sub-register operands. if (MO.getSubReg()) { // A virtual register kill refers to the whole register, so we may - // have to add operands for the super-register. - if (MO.isUse()) { - if (MO.isKill() && !MO.isUndef()) - SuperKills.push_back(PhysReg); - } else if (MO.isDead()) - SuperDeads.push_back(PhysReg); - else - SuperDefs.push_back(PhysReg); + // have to add operands for the super-register. A + // partial redef always kills and redefines the super-register. + if (MO.readsReg() && (MO.isDef() || MO.isKill())) + SuperKills.push_back(PhysReg); + + if (MO.isDef()) { + // The flag only makes sense for sub-register defs, and + // we are substituting a full physreg. An operand + // from the SuperKills list will represent the partial read of the + // super-register. + MO.setIsUndef(false); + + // Also add implicit defs for the super-register. + if (MO.isDead()) + SuperDeads.push_back(PhysReg); + else + SuperDefs.push_back(PhysReg); + } // PhysReg operands cannot have subregister indexes. PhysReg = TRI->getSubReg(PhysReg, MO.getSubReg()); diff --git a/contrib/llvm/lib/CompilerDriver/Action.cpp b/contrib/llvm/lib/CompilerDriver/Action.cpp deleted file mode 100644 index a8d625c7a..000000000 --- a/contrib/llvm/lib/CompilerDriver/Action.cpp +++ /dev/null @@ -1,134 +0,0 @@ -//===--- Action.cpp - The LLVM Compiler Driver ------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open -// Source License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Action class - implementation and auxiliary functions. -// -//===----------------------------------------------------------------------===// - -#include "llvm/CompilerDriver/Action.h" -#include "llvm/CompilerDriver/BuiltinOptions.h" -#include "llvm/CompilerDriver/Error.h" -#include "llvm/CompilerDriver/Main.h" - -#include "llvm/Support/raw_ostream.h" -#include "llvm/Support/SystemUtils.h" -#include "llvm/Support/Program.h" -#include "llvm/Support/TimeValue.h" - -#include -#include - -using namespace llvm; -using namespace llvmc; - -namespace llvmc { - -extern const char* ProgramName; - -} - -namespace { - - void PrintString (const std::string& str) { - errs() << str << ' '; - } - - void PrintCommand (const std::string& Cmd, const StrVector& Args) { - errs() << Cmd << ' '; - std::for_each(Args.begin(), Args.end(), &PrintString); - errs() << '\n'; - } - - bool IsSegmentationFault (int returnCode) { -#ifdef LLVM_ON_WIN32 - return (returnCode >= 0xc0000000UL) -#else - return (returnCode < 0); -#endif - } - - int ExecuteProgram (const std::string& name, const StrVector& args) { - sys::Path prog(name); - - if (sys::path::is_relative(prog.str())) { - prog = PrependMainExecutablePath(name, ProgramName, - (void *)(intptr_t)&Main); - - if (!prog.canExecute()) { - prog = sys::Program::FindProgramByName(name); - if (prog.isEmpty()) { - PrintError("Can't find program '" + name + "'"); - return -1; - } - } - } - if (!prog.canExecute()) { - PrintError("Program '" + name + "' is not executable."); - return -1; - } - - // Build the command line vector and the redirects array. - const sys::Path* redirects[3] = {0,0,0}; - sys::Path stdout_redirect; - - std::vector argv; - argv.reserve((args.size()+2)); - argv.push_back(name.c_str()); - - for (StrVector::const_iterator B = args.begin(), E = args.end(); - B!=E; ++B) { - if (*B == ">") { - ++B; - stdout_redirect.set(*B); - redirects[1] = &stdout_redirect; - } - else { - argv.push_back((*B).c_str()); - } - } - argv.push_back(0); // null terminate list. - - // Invoke the program. - int ret = sys::Program::ExecuteAndWait(prog, &argv[0], 0, &redirects[0]); - - if (IsSegmentationFault(ret)) { - errs() << "Segmentation fault: "; - PrintCommand(name, args); - } - - return ret; - } -} - -namespace llvmc { - void AppendToGlobalTimeLog (const std::string& cmd, double time); -} - -int llvmc::Action::Execute () const { - if (DryRun || VerboseMode) - PrintCommand(Command_, Args_); - - if (!DryRun) { - if (Time) { - sys::TimeValue now = sys::TimeValue::now(); - int ret = ExecuteProgram(Command_, Args_); - sys::TimeValue now2 = sys::TimeValue::now(); - now2 -= now; - double elapsed = now2.seconds() + now2.microseconds() / 1000000.0; - AppendToGlobalTimeLog(Command_, elapsed); - - return ret; - } - else { - return ExecuteProgram(Command_, Args_); - } - } - - return 0; -} diff --git a/contrib/llvm/lib/CompilerDriver/BuiltinOptions.cpp b/contrib/llvm/lib/CompilerDriver/BuiltinOptions.cpp deleted file mode 100644 index 38442038d..000000000 --- a/contrib/llvm/lib/CompilerDriver/BuiltinOptions.cpp +++ /dev/null @@ -1,61 +0,0 @@ -//===--- BuiltinOptions.cpp - The LLVM Compiler Driver ----------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open -// Source License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Definitions of all global command-line option variables. -// -//===----------------------------------------------------------------------===// - -#include "llvm/CompilerDriver/BuiltinOptions.h" - -#ifdef ENABLE_LLVMC_DYNAMIC_PLUGINS -#include "llvm/Support/PluginLoader.h" -#endif - -namespace cl = llvm::cl; - -namespace llvmc { - -cl::list InputFilenames(cl::Positional, cl::desc(""), - cl::ZeroOrMore); -cl::opt OutputFilename("o", cl::desc("Output file name"), - cl::value_desc("file"), cl::Prefix); -cl::opt TempDirname("temp-dir", cl::desc("Temp dir name"), - cl::value_desc(""), cl::Prefix); -cl::list Languages("x", - cl::desc("Specify the language of the following input files"), - cl::ZeroOrMore); - -cl::opt DryRun("dry-run", - cl::desc("Only pretend to run commands")); -cl::opt Time("time", cl::desc("Time individual commands")); -cl::opt VerboseMode("v", - cl::desc("Enable verbose mode")); - -cl::opt CheckGraph("check-graph", - cl::desc("Check the compilation graph for errors"), - cl::Hidden); -cl::opt WriteGraph("write-graph", - cl::desc("Write compilation-graph.dot file"), - cl::Hidden); -cl::opt ViewGraph("view-graph", - cl::desc("Show compilation graph in GhostView"), - cl::Hidden); - -cl::opt SaveTemps -("save-temps", cl::desc("Keep temporary files"), - cl::init(SaveTempsEnum::Unset), - cl::values(clEnumValN(SaveTempsEnum::Obj, "obj", - "Save files in the directory specified with -o"), - clEnumValN(SaveTempsEnum::Cwd, "cwd", - "Use current working directory"), - clEnumValN(SaveTempsEnum::Obj, "", "Same as 'cwd'"), - clEnumValEnd), - cl::ValueOptional); - -} // End namespace llvmc. diff --git a/contrib/llvm/lib/CompilerDriver/CompilationGraph.cpp b/contrib/llvm/lib/CompilerDriver/CompilationGraph.cpp deleted file mode 100644 index 33c656649..000000000 --- a/contrib/llvm/lib/CompilerDriver/CompilationGraph.cpp +++ /dev/null @@ -1,655 +0,0 @@ -//===--- CompilationGraph.cpp - The LLVM Compiler Driver --------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open -// Source License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Compilation graph - implementation. -// -//===----------------------------------------------------------------------===// - -#include "llvm/CompilerDriver/BuiltinOptions.h" -#include "llvm/CompilerDriver/CompilationGraph.h" -#include "llvm/CompilerDriver/Error.h" - -#include "llvm/ADT/STLExtras.h" -#include "llvm/Support/DOTGraphTraits.h" -#include "llvm/Support/GraphWriter.h" -#include "llvm/Support/raw_ostream.h" - -#include -#include -#include -#include -#include - -using namespace llvm; -using namespace llvmc; - -namespace llvmc { - - const std::string* LanguageMap::GetLanguage(const sys::Path& File) const { - // Remove the '.'. - StringRef suf = sys::path::extension(File.str()).substr(1); - LanguageMap::const_iterator Lang = - this->find(suf.empty() ? "*empty*" : suf); - if (Lang == this->end()) { - PrintError("File '" + File.str() + "' has unknown suffix '" - + suf.str() + '\''); - return 0; - } - return &Lang->second; - } -} - -namespace { - - /// ChooseEdge - Return the edge with the maximum weight. Returns 0 on error. - template - const Edge* ChooseEdge(const C& EdgesContainer, - const InputLanguagesSet& InLangs, - const std::string& NodeName = "root") { - const Edge* MaxEdge = 0; - int MaxWeight = 0; - bool SingleMax = true; - - // TODO: fix calculation of SingleMax. - for (typename C::const_iterator B = EdgesContainer.begin(), - E = EdgesContainer.end(); B != E; ++B) { - const Edge* e = B->getPtr(); - int EW = e->Weight(InLangs); - if (EW < 0) { - // (error) invocation in TableGen -> we don't need to print an error - // message. - return 0; - } - if (EW > MaxWeight) { - MaxEdge = e; - MaxWeight = EW; - SingleMax = true; - } else if (EW == MaxWeight) { - SingleMax = false; - } - } - - if (!SingleMax) { - PrintError("Node " + NodeName + ": multiple maximal outward edges found!" - " Most probably a specification error."); - return 0; - } - if (!MaxEdge) { - PrintError("Node " + NodeName + ": no maximal outward edge found!" - " Most probably a specification error."); - return 0; - } - return MaxEdge; - } - -} - -void Node::AddEdge(Edge* Edg) { - // If there already was an edge between two nodes, modify it instead - // of adding a new edge. - const std::string& ToolName = Edg->ToolName(); - for (container_type::iterator B = OutEdges.begin(), E = OutEdges.end(); - B != E; ++B) { - if ((*B)->ToolName() == ToolName) { - llvm::IntrusiveRefCntPtr(Edg).swap(*B); - return; - } - } - OutEdges.push_back(llvm::IntrusiveRefCntPtr(Edg)); -} - -CompilationGraph::CompilationGraph() { - NodesMap["root"] = Node(this); -} - -Node* CompilationGraph::getNode(const std::string& ToolName) { - nodes_map_type::iterator I = NodesMap.find(ToolName); - if (I == NodesMap.end()) { - PrintError("Node " + ToolName + " is not in the graph"); - return 0; - } - return &I->second; -} - -const Node* CompilationGraph::getNode(const std::string& ToolName) const { - nodes_map_type::const_iterator I = NodesMap.find(ToolName); - if (I == NodesMap.end()) { - PrintError("Node " + ToolName + " is not in the graph!"); - return 0; - } - return &I->second; -} - -// Find the tools list corresponding to the given language name. -const CompilationGraph::tools_vector_type* -CompilationGraph::getToolsVector(const std::string& LangName) const -{ - tools_map_type::const_iterator I = ToolsMap.find(LangName); - if (I == ToolsMap.end()) { - PrintError("No tool corresponding to the language " + LangName + " found"); - return 0; - } - return &I->second; -} - -void CompilationGraph::insertNode(Tool* V) { - if (NodesMap.count(V->Name()) == 0) - NodesMap[V->Name()] = Node(this, V); -} - -int CompilationGraph::insertEdge(const std::string& A, Edge* Edg) { - Node* B = getNode(Edg->ToolName()); - if (B == 0) - return 1; - - if (A == "root") { - const char** InLangs = B->ToolPtr->InputLanguages(); - for (;*InLangs; ++InLangs) - ToolsMap[*InLangs].push_back(IntrusiveRefCntPtr(Edg)); - NodesMap["root"].AddEdge(Edg); - } - else { - Node* N = getNode(A); - if (N == 0) - return 1; - - N->AddEdge(Edg); - } - // Increase the inward edge counter. - B->IncrInEdges(); - - return 0; -} - -// Pass input file through the chain until we bump into a Join node or -// a node that says that it is the last. -int CompilationGraph::PassThroughGraph (const sys::Path& InFile, - const Node* StartNode, - const InputLanguagesSet& InLangs, - const sys::Path& TempDir, - const LanguageMap& LangMap) const { - sys::Path In = InFile; - const Node* CurNode = StartNode; - - while(true) { - Tool* CurTool = CurNode->ToolPtr.getPtr(); - - if (CurTool->IsJoin()) { - JoinTool& JT = static_cast(*CurTool); - JT.AddToJoinList(In); - break; - } - - Action CurAction; - if (int ret = CurTool->GenerateAction(CurAction, In, CurNode->HasChildren(), - TempDir, InLangs, LangMap)) { - return ret; - } - - if (int ret = CurAction.Execute()) - return ret; - - if (CurAction.StopCompilation()) - return 0; - - const Edge* Edg = ChooseEdge(CurNode->OutEdges, InLangs, CurNode->Name()); - if (Edg == 0) - return 1; - - CurNode = getNode(Edg->ToolName()); - if (CurNode == 0) - return 1; - - In = CurAction.OutFile(); - } - - return 0; -} - -// Find the head of the toolchain corresponding to the given file. -// Also, insert an input language into InLangs. -const Node* CompilationGraph:: -FindToolChain(const sys::Path& In, const std::string* ForceLanguage, - InputLanguagesSet& InLangs, const LanguageMap& LangMap) const { - - // Determine the input language. - const std::string* InLang = (ForceLanguage ? ForceLanguage - : LangMap.GetLanguage(In)); - if (InLang == 0) - return 0; - const std::string& InLanguage = *InLang; - - // Add the current input language to the input language set. - InLangs.insert(InLanguage); - - // Find the toolchain for the input language. - const tools_vector_type* pTV = getToolsVector(InLanguage); - if (pTV == 0) - return 0; - - const tools_vector_type& TV = *pTV; - if (TV.empty()) { - PrintError("No toolchain corresponding to language " - + InLanguage + " found"); - return 0; - } - - const Edge* Edg = ChooseEdge(TV, InLangs); - if (Edg == 0) - return 0; - - return getNode(Edg->ToolName()); -} - -// Helper function used by Build(). -// Traverses initial portions of the toolchains (up to the first Join node). -// This function is also responsible for handling the -x option. -int CompilationGraph::BuildInitial (InputLanguagesSet& InLangs, - const sys::Path& TempDir, - const LanguageMap& LangMap) { - // This is related to -x option handling. - cl::list::const_iterator xIter = Languages.begin(), - xBegin = xIter, xEnd = Languages.end(); - bool xEmpty = true; - const std::string* xLanguage = 0; - unsigned xPos = 0, xPosNext = 0, filePos = 0; - - if (xIter != xEnd) { - xEmpty = false; - xPos = Languages.getPosition(xIter - xBegin); - cl::list::const_iterator xNext = llvm::next(xIter); - xPosNext = (xNext == xEnd) ? std::numeric_limits::max() - : Languages.getPosition(xNext - xBegin); - xLanguage = (*xIter == "none") ? 0 : &(*xIter); - } - - // For each input file: - for (cl::list::const_iterator B = InputFilenames.begin(), - CB = B, E = InputFilenames.end(); B != E; ++B) { - sys::Path In = sys::Path(*B); - - // Code for handling the -x option. - // Output: std::string* xLanguage (can be NULL). - if (!xEmpty) { - filePos = InputFilenames.getPosition(B - CB); - - if (xPos < filePos) { - if (filePos < xPosNext) { - xLanguage = (*xIter == "none") ? 0 : &(*xIter); - } - else { // filePos >= xPosNext - // Skip xIters while filePos > xPosNext - while (filePos > xPosNext) { - ++xIter; - xPos = xPosNext; - - cl::list::const_iterator xNext = llvm::next(xIter); - if (xNext == xEnd) - xPosNext = std::numeric_limits::max(); - else - xPosNext = Languages.getPosition(xNext - xBegin); - xLanguage = (*xIter == "none") ? 0 : &(*xIter); - } - } - } - } - - // Find the toolchain corresponding to this file. - const Node* N = FindToolChain(In, xLanguage, InLangs, LangMap); - if (N == 0) - return 1; - // Pass file through the chain starting at head. - if (int ret = PassThroughGraph(In, N, InLangs, TempDir, LangMap)) - return ret; - } - - return 0; -} - -// Sort the nodes in topological order. -int CompilationGraph::TopologicalSort(std::vector& Out) { - std::queue Q; - - Node* Root = getNode("root"); - if (Root == 0) - return 1; - - Q.push(Root); - - while (!Q.empty()) { - const Node* A = Q.front(); - Q.pop(); - Out.push_back(A); - for (Node::const_iterator EB = A->EdgesBegin(), EE = A->EdgesEnd(); - EB != EE; ++EB) { - Node* B = getNode((*EB)->ToolName()); - if (B == 0) - return 1; - - B->DecrInEdges(); - if (B->HasNoInEdges()) - Q.push(B); - } - } - - return 0; -} - -namespace { - bool NotJoinNode(const Node* N) { - return N->ToolPtr ? !N->ToolPtr->IsJoin() : true; - } -} - -// Call TopologicalSort and filter the resulting list to include -// only Join nodes. -int CompilationGraph:: -TopologicalSortFilterJoinNodes(std::vector& Out) { - std::vector TopSorted; - if (int ret = TopologicalSort(TopSorted)) - return ret; - std::remove_copy_if(TopSorted.begin(), TopSorted.end(), - std::back_inserter(Out), NotJoinNode); - - return 0; -} - -int CompilationGraph::Build (const sys::Path& TempDir, - const LanguageMap& LangMap) { - InputLanguagesSet InLangs; - bool WasSomeActionGenerated = !InputFilenames.empty(); - - // Traverse initial parts of the toolchains and fill in InLangs. - if (int ret = BuildInitial(InLangs, TempDir, LangMap)) - return ret; - - std::vector JTV; - if (int ret = TopologicalSortFilterJoinNodes(JTV)) - return ret; - - // For all join nodes in topological order: - for (std::vector::iterator B = JTV.begin(), E = JTV.end(); - B != E; ++B) { - - const Node* CurNode = *B; - JoinTool* JT = &static_cast(*CurNode->ToolPtr.getPtr()); - - // Are there any files in the join list? - if (JT->JoinListEmpty() && !(JT->WorksOnEmpty() && InputFilenames.empty())) - continue; - - WasSomeActionGenerated = true; - Action CurAction; - if (int ret = JT->GenerateAction(CurAction, CurNode->HasChildren(), - TempDir, InLangs, LangMap)) { - return ret; - } - - if (int ret = CurAction.Execute()) - return ret; - - if (CurAction.StopCompilation()) - return 0; - - const Edge* Edg = ChooseEdge(CurNode->OutEdges, InLangs, CurNode->Name()); - if (Edg == 0) - return 1; - - const Node* NextNode = getNode(Edg->ToolName()); - if (NextNode == 0) - return 1; - - if (int ret = PassThroughGraph(sys::Path(CurAction.OutFile()), NextNode, - InLangs, TempDir, LangMap)) { - return ret; - } - } - - if (!WasSomeActionGenerated) { - PrintError("no input files"); - return 1; - } - - return 0; -} - -int CompilationGraph::CheckLanguageNames() const { - int ret = 0; - - // Check that names for output and input languages on all edges do match. - for (const_nodes_iterator B = this->NodesMap.begin(), - E = this->NodesMap.end(); B != E; ++B) { - - const Node & N1 = B->second; - if (N1.ToolPtr) { - for (Node::const_iterator EB = N1.EdgesBegin(), EE = N1.EdgesEnd(); - EB != EE; ++EB) { - const Node* N2 = this->getNode((*EB)->ToolName()); - if (N2 == 0) - return 1; - - if (!N2->ToolPtr) { - ++ret; - errs() << "Error: there is an edge from '" << N1.ToolPtr->Name() - << "' back to the root!\n\n"; - continue; - } - - const char** OutLangs = N1.ToolPtr->OutputLanguages(); - const char** InLangs = N2->ToolPtr->InputLanguages(); - bool eq = false; - const char* OutLang = 0; - for (;*OutLangs; ++OutLangs) { - OutLang = *OutLangs; - for (;*InLangs; ++InLangs) { - if (std::strcmp(OutLang, *InLangs) == 0) { - eq = true; - break; - } - } - } - - if (!eq) { - ++ret; - errs() << "Error: Output->input language mismatch in the edge '" - << N1.ToolPtr->Name() << "' -> '" << N2->ToolPtr->Name() - << "'!\n" - << "Expected one of { "; - - InLangs = N2->ToolPtr->InputLanguages(); - for (;*InLangs; ++InLangs) { - errs() << '\'' << *InLangs << (*(InLangs+1) ? "', " : "'"); - } - - errs() << " }, but got '" << OutLang << "'!\n\n"; - } - - } - } - } - - return ret; -} - -int CompilationGraph::CheckMultipleDefaultEdges() const { - int ret = 0; - InputLanguagesSet Dummy; - - // For all nodes, just iterate over the outgoing edges and check if there is - // more than one edge with maximum weight. - for (const_nodes_iterator B = this->NodesMap.begin(), - E = this->NodesMap.end(); B != E; ++B) { - const Node& N = B->second; - int MaxWeight = -1024; - - // Ignore the root node. - if (!N.ToolPtr) - continue; - - for (Node::const_iterator EB = N.EdgesBegin(), EE = N.EdgesEnd(); - EB != EE; ++EB) { - int EdgeWeight = (*EB)->Weight(Dummy); - if (EdgeWeight > MaxWeight) { - MaxWeight = EdgeWeight; - } - else if (EdgeWeight == MaxWeight) { - ++ret; - errs() << "Error: there are multiple maximal edges stemming from the '" - << N.ToolPtr->Name() << "' node!\n\n"; - break; - } - } - } - - return ret; -} - -int CompilationGraph::CheckCycles() { - unsigned deleted = 0; - std::queue Q; - - Node* Root = getNode("root"); - if (Root == 0) - return 1; - - Q.push(Root); - - // Try to delete all nodes that have no ingoing edges, starting from the - // root. If there are any nodes left after this operation, then we have a - // cycle. This relies on '--check-graph' not performing the topological sort. - while (!Q.empty()) { - Node* A = Q.front(); - Q.pop(); - ++deleted; - - for (Node::iterator EB = A->EdgesBegin(), EE = A->EdgesEnd(); - EB != EE; ++EB) { - Node* B = getNode((*EB)->ToolName()); - if (B == 0) - return 1; - - B->DecrInEdges(); - if (B->HasNoInEdges()) - Q.push(B); - } - } - - if (deleted != NodesMap.size()) { - errs() << "Error: there are cycles in the compilation graph!\n" - << "Try inspecting the diagram produced by " - << "'llvmc --view-graph'.\n\n"; - return 1; - } - - return 0; -} - -int CompilationGraph::Check () { - // We try to catch as many errors as we can in one go. - int errs = 0; - int ret = 0; - - // Check that output/input language names match. - ret = this->CheckLanguageNames(); - if (ret < 0) - return 1; - errs += ret; - - // Check for multiple default edges. - ret = this->CheckMultipleDefaultEdges(); - if (ret < 0) - return 1; - errs += ret; - - // Check for cycles. - ret = this->CheckCycles(); - if (ret < 0) - return 1; - errs += ret; - - return errs; -} - -// Code related to graph visualization. - -namespace { - -std::string SquashStrArray (const char** StrArr) { - std::string ret; - - for (; *StrArr; ++StrArr) { - if (*(StrArr + 1)) { - ret += *StrArr; - ret += ", "; - } - else { - ret += *StrArr; - } - } - - return ret; -} - -} // End anonymous namespace. - -namespace llvm { - template <> - struct DOTGraphTraits - : public DefaultDOTGraphTraits - { - DOTGraphTraits (bool isSimple=false) : DefaultDOTGraphTraits(isSimple) {} - - template - static std::string getNodeLabel(const Node* N, const GraphType&) - { - if (N->ToolPtr) - if (N->ToolPtr->IsJoin()) - return N->Name() + "\n (join" + - (N->HasChildren() ? ")" - : std::string(": ") + - SquashStrArray(N->ToolPtr->OutputLanguages()) + ')'); - else - return N->Name(); - else - return "root"; - } - - template - static std::string getEdgeSourceLabel(const Node* N, EdgeIter I) { - if (N->ToolPtr) { - return SquashStrArray(N->ToolPtr->OutputLanguages()); - } - else { - return SquashStrArray(I->ToolPtr->InputLanguages()); - } - } - }; - -} // End namespace llvm - -int CompilationGraph::writeGraph(const std::string& OutputFilename) { - std::string ErrorInfo; - raw_fd_ostream O(OutputFilename.c_str(), ErrorInfo); - - if (ErrorInfo.empty()) { - errs() << "Writing '"<< OutputFilename << "' file..."; - llvm::WriteGraph(O, this); - errs() << "done.\n"; - } - else { - PrintError("Error opening file '" + OutputFilename + "' for writing!"); - return 1; - } - - return 0; -} - -void CompilationGraph::viewGraph() { - llvm::ViewGraph(this, "compilation-graph"); -} diff --git a/contrib/llvm/lib/CompilerDriver/Main.cpp b/contrib/llvm/lib/CompilerDriver/Main.cpp deleted file mode 100644 index 7120027f7..000000000 --- a/contrib/llvm/lib/CompilerDriver/Main.cpp +++ /dev/null @@ -1,146 +0,0 @@ -//===--- Main.cpp - The LLVM Compiler Driver --------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open -// Source License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// llvmc::Main function - driver entry point. -// -//===----------------------------------------------------------------------===// - -#include "llvm/CompilerDriver/AutoGenerated.h" -#include "llvm/CompilerDriver/BuiltinOptions.h" -#include "llvm/CompilerDriver/CompilationGraph.h" -#include "llvm/CompilerDriver/Error.h" - -#include "llvm/Support/FileSystem.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/Support/Path.h" - -#include -#include - -namespace cl = llvm::cl; -namespace sys = llvm::sys; -using namespace llvmc; - -namespace { - - std::stringstream* GlobalTimeLog; - - /// GetTempDir - Get the temporary directory location. Returns non-zero value - /// on error. - int GetTempDir(sys::Path& tempDir) { - // The --temp-dir option. - if (!TempDirname.empty()) { - tempDir = TempDirname; - } - // GCC 4.5-style -save-temps handling. - else if (SaveTemps == SaveTempsEnum::Unset) { - tempDir = sys::Path::GetTemporaryDirectory(); - return 0; - } - else if (SaveTemps == SaveTempsEnum::Obj && !OutputFilename.empty()) { - tempDir = sys::path::parent_path(OutputFilename); - } - else { - // SaveTemps == Cwd --> use current dir (leave tempDir empty). - return 0; - } - - bool Exists; - if (llvm::sys::fs::exists(tempDir.str(), Exists) || !Exists) { - std::string ErrMsg; - if (tempDir.createDirectoryOnDisk(true, &ErrMsg)) { - PrintError(ErrMsg); - return 1; - } - } - - return 0; - } - - /// BuildTargets - A small wrapper for CompilationGraph::Build. Returns - /// non-zero value in case of error. - int BuildTargets(CompilationGraph& graph, const LanguageMap& langMap) { - int ret; - sys::Path tempDir; - bool toDelete = (SaveTemps == SaveTempsEnum::Unset); - - if (int ret = GetTempDir(tempDir)) - return ret; - - ret = graph.Build(tempDir, langMap); - - if (toDelete) - tempDir.eraseFromDisk(true); - - return ret; - } -} - -namespace llvmc { - -// Used to implement -time option. External linkage is intentional. -void AppendToGlobalTimeLog(const std::string& cmd, double time) { - *GlobalTimeLog << "# " << cmd << ' ' << time << '\n'; -} - -// Sometimes user code wants to access the argv[0] value. -const char* ProgramName; - -int Main(int argc, char** argv) { - int ret = 0; - LanguageMap langMap; - CompilationGraph graph; - - ProgramName = argv[0]; - - cl::ParseCommandLineOptions - (argc, argv, - /* Overview = */ "LLVM Compiler Driver (Work In Progress)", - /* ReadResponseFiles = */ false); - - if (int ret = autogenerated::RunInitialization(langMap, graph)) - return ret; - - if (CheckGraph) { - ret = graph.Check(); - if (!ret) - llvm::errs() << "check-graph: no errors found.\n"; - - return ret; - } - - if (ViewGraph) { - graph.viewGraph(); - if (!WriteGraph) - return 0; - } - - if (WriteGraph) { - const std::string& Out = (OutputFilename.empty() - ? std::string("compilation-graph.dot") - : OutputFilename); - return graph.writeGraph(Out); - } - - if (Time) { - GlobalTimeLog = new std::stringstream; - GlobalTimeLog->precision(2); - } - - ret = BuildTargets(graph, langMap); - - if (Time) { - llvm::errs() << GlobalTimeLog->str(); - delete GlobalTimeLog; - } - - return ret; -} - -} // end namespace llvmc diff --git a/contrib/llvm/lib/CompilerDriver/Tool.cpp b/contrib/llvm/lib/CompilerDriver/Tool.cpp deleted file mode 100644 index 876759aa7..000000000 --- a/contrib/llvm/lib/CompilerDriver/Tool.cpp +++ /dev/null @@ -1,95 +0,0 @@ -//===--- Tool.cpp - The LLVM Compiler Driver --------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open -// Source License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Tool base class - implementation details. -// -//===----------------------------------------------------------------------===// - -#include "llvm/CompilerDriver/BuiltinOptions.h" -#include "llvm/CompilerDriver/Tool.h" - -#include "llvm/ADT/StringExtras.h" -#include "llvm/Support/Path.h" - -#include - -using namespace llvm; -using namespace llvmc; - -namespace { - sys::Path MakeTempFile(const sys::Path& TempDir, const std::string& BaseName, - const std::string& Suffix) { - sys::Path Out; - - // Make sure we don't end up with path names like '/file.o' if the - // TempDir is empty. - if (TempDir.empty()) { - Out.set(BaseName); - } - else { - Out = TempDir; - Out.appendComponent(BaseName); - } - Out.appendSuffix(Suffix); - // NOTE: makeUnique always *creates* a unique temporary file, - // which is good, since there will be no races. However, some - // tools do not like it when the output file already exists, so - // they need to be placated with -f or something like that. - Out.makeUnique(true, NULL); - return Out; - } -} - -sys::Path Tool::OutFilename(const sys::Path& In, - const sys::Path& TempDir, - bool StopCompilation, - const char* OutputSuffix) const { - sys::Path Out; - - if (StopCompilation) { - if (!OutputFilename.empty()) { - Out.set(OutputFilename); - } - else if (IsJoin()) { - Out.set("a"); - Out.appendSuffix(OutputSuffix); - } - else { - Out.set(sys::path::stem(In.str())); - Out.appendSuffix(OutputSuffix); - } - } - else { - if (IsJoin()) - Out = MakeTempFile(TempDir, "tmp", OutputSuffix); - else - Out = MakeTempFile(TempDir, sys::path::stem(In.str()), OutputSuffix); - } - return Out; -} - -namespace { - template - bool CompareFirst (std::pair p1, std::pair p2) { - return std::less()(p1.first, p2.first); - } -} - -StrVector Tool::SortArgs(ArgsVector& Args) const { - StrVector Out; - - // HACK: this won't be needed when we'll migrate away from CommandLine. - std::stable_sort(Args.begin(), Args.end(), - &CompareFirst); - for (ArgsVector::iterator B = Args.begin(), E = Args.end(); B != E; ++B) { - Out.push_back(B->second); - } - - return Out; -} diff --git a/contrib/llvm/lib/DebugInfo/DIContext.cpp b/contrib/llvm/lib/DebugInfo/DIContext.cpp new file mode 100644 index 000000000..e2fd55fd6 --- /dev/null +++ b/contrib/llvm/lib/DebugInfo/DIContext.cpp @@ -0,0 +1,24 @@ +//===-- DIContext.cpp -----------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/DebugInfo/DIContext.h" +#include "DWARFContext.h" +using namespace llvm; + +DIContext::~DIContext() {} + +DIContext *DIContext::getDWARFContext(bool isLittleEndian, + StringRef infoSection, + StringRef abbrevSection, + StringRef aRangeSection, + StringRef lineSection, + StringRef stringSection) { + return new DWARFContextInMemory(isLittleEndian, infoSection, abbrevSection, + aRangeSection, lineSection, stringSection); +} diff --git a/contrib/llvm/lib/DebugInfo/DWARFAbbreviationDeclaration.cpp b/contrib/llvm/lib/DebugInfo/DWARFAbbreviationDeclaration.cpp new file mode 100644 index 000000000..0df692c3a --- /dev/null +++ b/contrib/llvm/lib/DebugInfo/DWARFAbbreviationDeclaration.cpp @@ -0,0 +1,83 @@ +//===-- DWARFAbbreviationDeclaration.cpp ----------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "DWARFAbbreviationDeclaration.h" +#include "llvm/Support/Dwarf.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; +using namespace dwarf; + +bool +DWARFAbbreviationDeclaration::extract(DataExtractor data, uint32_t* offset_ptr){ + return extract(data, offset_ptr, data.getULEB128(offset_ptr)); +} + +bool +DWARFAbbreviationDeclaration::extract(DataExtractor data, uint32_t* offset_ptr, + uint32_t code) { + Code = code; + Attributes.clear(); + if (Code) { + Tag = data.getULEB128(offset_ptr); + HasChildren = data.getU8(offset_ptr); + + while (data.isValidOffset(*offset_ptr)) { + uint16_t attr = data.getULEB128(offset_ptr); + uint16_t form = data.getULEB128(offset_ptr); + + if (attr && form) + Attributes.push_back(DWARFAttribute(attr, form)); + else + break; + } + + return Tag != 0; + } else { + Tag = 0; + HasChildren = false; + } + + return false; +} + +void DWARFAbbreviationDeclaration::dump(raw_ostream &OS) const { + const char *tagString = TagString(getTag()); + OS << '[' << getCode() << "] "; + if (tagString) + OS << tagString; + else + OS << format("DW_TAG_Unknown_%x", getTag()); + OS << "\tDW_CHILDREN_" << (hasChildren() ? "yes" : "no") << '\n'; + for (unsigned i = 0, e = Attributes.size(); i != e; ++i) { + OS << '\t'; + const char *attrString = AttributeString(Attributes[i].getAttribute()); + if (attrString) + OS << attrString; + else + OS << format("DW_AT_Unknown_%x", Attributes[i].getAttribute()); + OS << '\t'; + const char *formString = FormEncodingString(Attributes[i].getForm()); + if (formString) + OS << formString; + else + OS << format("DW_FORM_Unknown_%x", Attributes[i].getForm()); + OS << '\n'; + } + OS << '\n'; +} + +uint32_t +DWARFAbbreviationDeclaration::findAttributeIndex(uint16_t attr) const { + for (uint32_t i = 0, e = Attributes.size(); i != e; ++i) { + if (Attributes[i].getAttribute() == attr) + return i; + } + return -1U; +} diff --git a/contrib/llvm/lib/DebugInfo/DWARFAbbreviationDeclaration.h b/contrib/llvm/lib/DebugInfo/DWARFAbbreviationDeclaration.h new file mode 100644 index 000000000..2463a3cc0 --- /dev/null +++ b/contrib/llvm/lib/DebugInfo/DWARFAbbreviationDeclaration.h @@ -0,0 +1,54 @@ +//===-- DWARFAbbreviationDeclaration.h --------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_DWARFABBREVIATIONDECLARATION_H +#define LLVM_DEBUGINFO_DWARFABBREVIATIONDECLARATION_H + +#include "DWARFAttribute.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/DataExtractor.h" + +namespace llvm { + +class raw_ostream; + +class DWARFAbbreviationDeclaration { + uint32_t Code; + uint32_t Tag; + bool HasChildren; + SmallVector Attributes; +public: + enum { InvalidCode = 0 }; + DWARFAbbreviationDeclaration() + : Code(InvalidCode), Tag(0), HasChildren(0) {} + + uint32_t getCode() const { return Code; } + uint32_t getTag() const { return Tag; } + bool hasChildren() const { return HasChildren; } + uint32_t getNumAttributes() const { return Attributes.size(); } + uint16_t getAttrByIndex(uint32_t idx) const { + return Attributes.size() > idx ? Attributes[idx].getAttribute() : 0; + } + uint16_t getFormByIndex(uint32_t idx) const { + return Attributes.size() > idx ? Attributes[idx].getForm() : 0; + } + + uint32_t findAttributeIndex(uint16_t attr) const; + bool extract(DataExtractor data, uint32_t* offset_ptr); + bool extract(DataExtractor data, uint32_t* offset_ptr, uint32_t code); + bool isValid() const { return Code != 0 && Tag != 0; } + void dump(raw_ostream &OS) const; + const SmallVectorImpl &getAttributes() const { + return Attributes; + } +}; + +} + +#endif diff --git a/contrib/llvm/lib/DebugInfo/DWARFAttribute.h b/contrib/llvm/lib/DebugInfo/DWARFAttribute.h new file mode 100644 index 000000000..6f49b637c --- /dev/null +++ b/contrib/llvm/lib/DebugInfo/DWARFAttribute.h @@ -0,0 +1,30 @@ +//===-- DWARFAttribute.h ----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_DWARFATTRIBUTE_H +#define LLVM_DEBUGINFO_DWARFATTRIBUTE_H + +#include "llvm/Support/DataTypes.h" + +namespace llvm { + +class DWARFAttribute { + uint16_t Attribute; + uint16_t Form; + public: + DWARFAttribute(uint16_t attr, uint16_t form) + : Attribute(attr), Form(form) {} + + uint16_t getAttribute() const { return Attribute; } + uint16_t getForm() const { return Form; } +}; + +} + +#endif diff --git a/contrib/llvm/lib/DebugInfo/DWARFCompileUnit.cpp b/contrib/llvm/lib/DebugInfo/DWARFCompileUnit.cpp new file mode 100644 index 000000000..24bf97ff6 --- /dev/null +++ b/contrib/llvm/lib/DebugInfo/DWARFCompileUnit.cpp @@ -0,0 +1,238 @@ +//===-- DWARFCompileUnit.cpp ----------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "DWARFCompileUnit.h" +#include "DWARFContext.h" +#include "DWARFFormValue.h" +#include "llvm/Support/Dwarf.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; +using namespace dwarf; + +DataExtractor DWARFCompileUnit::getDebugInfoExtractor() const { + return DataExtractor(Context.getInfoSection(), + Context.isLittleEndian(), getAddressByteSize()); +} + +bool DWARFCompileUnit::extract(DataExtractor debug_info, uint32_t *offset_ptr) { + clear(); + + Offset = *offset_ptr; + + if (debug_info.isValidOffset(*offset_ptr)) { + uint64_t abbrOffset; + const DWARFDebugAbbrev *abbr = Context.getDebugAbbrev(); + Length = debug_info.getU32(offset_ptr); + Version = debug_info.getU16(offset_ptr); + abbrOffset = debug_info.getU32(offset_ptr); + AddrSize = debug_info.getU8(offset_ptr); + + bool lengthOK = debug_info.isValidOffset(getNextCompileUnitOffset()-1); + bool versionOK = DWARFContext::isSupportedVersion(Version); + bool abbrOffsetOK = Context.getAbbrevSection().size() > abbrOffset; + bool addrSizeOK = AddrSize == 4 || AddrSize == 8; + + if (lengthOK && versionOK && addrSizeOK && abbrOffsetOK && abbr != NULL) { + Abbrevs = abbr->getAbbreviationDeclarationSet(abbrOffset); + return true; + } + + // reset the offset to where we tried to parse from if anything went wrong + *offset_ptr = Offset; + } + + return false; +} + +uint32_t +DWARFCompileUnit::extract(uint32_t offset, DataExtractor debug_info_data, + const DWARFAbbreviationDeclarationSet *abbrevs) { + clear(); + + Offset = offset; + + if (debug_info_data.isValidOffset(offset)) { + Length = debug_info_data.getU32(&offset); + Version = debug_info_data.getU16(&offset); + bool abbrevsOK = debug_info_data.getU32(&offset) == abbrevs->getOffset(); + Abbrevs = abbrevs; + AddrSize = debug_info_data.getU8 (&offset); + + bool versionOK = DWARFContext::isSupportedVersion(Version); + bool addrSizeOK = AddrSize == 4 || AddrSize == 8; + + if (versionOK && addrSizeOK && abbrevsOK && + debug_info_data.isValidOffset(offset)) + return offset; + } + return 0; +} + +void DWARFCompileUnit::clear() { + Offset = 0; + Length = 0; + Version = 0; + Abbrevs = 0; + AddrSize = 0; + BaseAddr = 0; + DieArray.clear(); +} + +void DWARFCompileUnit::dump(raw_ostream &OS) { + OS << format("0x%08x", Offset) << ": Compile Unit:" + << " length = " << format("0x%08x", Length) + << " version = " << format("0x%04x", Version) + << " abbr_offset = " << format("0x%04x", Abbrevs->getOffset()) + << " addr_size = " << format("0x%02x", AddrSize) + << " (next CU at " << format("0x%08x", getNextCompileUnitOffset()) + << ")\n"; + + getCompileUnitDIE(false)->dump(OS, this, -1U); +} + +void DWARFCompileUnit::setDIERelations() { + if (DieArray.empty()) + return; + DWARFDebugInfoEntryMinimal *die_array_begin = &DieArray.front(); + DWARFDebugInfoEntryMinimal *die_array_end = &DieArray.back(); + DWARFDebugInfoEntryMinimal *curr_die; + // We purposely are skipping the last element in the array in the loop below + // so that we can always have a valid next item + for (curr_die = die_array_begin; curr_die < die_array_end; ++curr_die) { + // Since our loop doesn't include the last element, we can always + // safely access the next die in the array. + DWARFDebugInfoEntryMinimal *next_die = curr_die + 1; + + const DWARFAbbreviationDeclaration *curr_die_abbrev = + curr_die->getAbbreviationDeclarationPtr(); + + if (curr_die_abbrev) { + // Normal DIE + if (curr_die_abbrev->hasChildren()) + next_die->setParent(curr_die); + else + curr_die->setSibling(next_die); + } else { + // NULL DIE that terminates a sibling chain + DWARFDebugInfoEntryMinimal *parent = curr_die->getParent(); + if (parent) + parent->setSibling(next_die); + } + } + + // Since we skipped the last element, we need to fix it up! + if (die_array_begin < die_array_end) + curr_die->setParent(die_array_begin); +} + +size_t DWARFCompileUnit::extractDIEsIfNeeded(bool cu_die_only) { + const size_t initial_die_array_size = DieArray.size(); + if ((cu_die_only && initial_die_array_size > 0) || + initial_die_array_size > 1) + return 0; // Already parsed + + // Set the offset to that of the first DIE and calculate the start of the + // next compilation unit header. + uint32_t offset = getFirstDIEOffset(); + uint32_t next_cu_offset = getNextCompileUnitOffset(); + + DWARFDebugInfoEntryMinimal die; + // Keep a flat array of the DIE for binary lookup by DIE offset + uint32_t depth = 0; + // We are in our compile unit, parse starting at the offset + // we were told to parse + + const uint8_t *fixed_form_sizes = + DWARFFormValue::getFixedFormSizesForAddressSize(getAddressByteSize()); + + while (offset < next_cu_offset && + die.extractFast(this, fixed_form_sizes, &offset)) { + + if (depth == 0) { + uint64_t base_addr = + die.getAttributeValueAsUnsigned(this, DW_AT_low_pc, -1U); + if (base_addr == -1U) + base_addr = die.getAttributeValueAsUnsigned(this, DW_AT_entry_pc, 0); + setBaseAddress(base_addr); + } + + if (cu_die_only) { + addDIE(die); + return 1; + } + else if (depth == 0 && initial_die_array_size == 1) { + // Don't append the CU die as we already did that + } else { + addDIE (die); + } + + const DWARFAbbreviationDeclaration *abbrDecl = + die.getAbbreviationDeclarationPtr(); + if (abbrDecl) { + // Normal DIE + if (abbrDecl->hasChildren()) + ++depth; + } else { + // NULL DIE. + if (depth > 0) + --depth; + if (depth == 0) + break; // We are done with this compile unit! + } + + } + + // Give a little bit of info if we encounter corrupt DWARF (our offset + // should always terminate at or before the start of the next compilation + // unit header). + if (offset > next_cu_offset) { + fprintf (stderr, "warning: DWARF compile unit extends beyond its bounds cu 0x%8.8x at 0x%8.8x'\n", getOffset(), offset); + } + + setDIERelations(); + return DieArray.size(); +} + +void DWARFCompileUnit::clearDIEs(bool keep_compile_unit_die) { + if (DieArray.size() > 1) { + // std::vectors never get any smaller when resized to a smaller size, + // or when clear() or erase() are called, the size will report that it + // is smaller, but the memory allocated remains intact (call capacity() + // to see this). So we need to create a temporary vector and swap the + // contents which will cause just the internal pointers to be swapped + // so that when "tmp_array" goes out of scope, it will destroy the + // contents. + + // Save at least the compile unit DIE + std::vector tmpArray; + DieArray.swap(tmpArray); + if (keep_compile_unit_die) + DieArray.push_back(tmpArray.front()); + } +} + +void +DWARFCompileUnit::buildAddressRangeTable(DWARFDebugAranges *debug_aranges, + bool clear_dies_if_already_not_parsed){ + // This function is usually called if there in no .debug_aranges section + // in order to produce a compile unit level set of address ranges that + // is accurate. If the DIEs weren't parsed, then we don't want all dies for + // all compile units to stay loaded when they weren't needed. So we can end + // up parsing the DWARF and then throwing them all away to keep memory usage + // down. + const bool clear_dies = extractDIEsIfNeeded(false) > 1; + + DieArray[0].buildAddressRangeTable(this, debug_aranges); + + // Keep memory down by clearing DIEs if this generate function + // caused them to be parsed. + if (clear_dies) + clearDIEs(true); +} diff --git a/contrib/llvm/lib/DebugInfo/DWARFCompileUnit.h b/contrib/llvm/lib/DebugInfo/DWARFCompileUnit.h new file mode 100644 index 000000000..d9167292a --- /dev/null +++ b/contrib/llvm/lib/DebugInfo/DWARFCompileUnit.h @@ -0,0 +1,111 @@ +//===-- DWARFCompileUnit.h --------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_DWARFCOMPILEUNIT_H +#define LLVM_DEBUGINFO_DWARFCOMPILEUNIT_H + +#include "DWARFDebugAbbrev.h" +#include "DWARFDebugInfoEntry.h" +#include + +namespace llvm { + +class DWARFContext; +class raw_ostream; + +class DWARFCompileUnit { + DWARFContext &Context; + + uint32_t Offset; + uint32_t Length; + uint16_t Version; + const DWARFAbbreviationDeclarationSet *Abbrevs; + uint8_t AddrSize; + uint64_t BaseAddr; + // The compile unit debug information entry item. + std::vector DieArray; +public: + DWARFCompileUnit(DWARFContext &context) : Context(context) { + clear(); + } + + DWARFContext &getContext() const { return Context; } + DataExtractor getDebugInfoExtractor() const; + + bool extract(DataExtractor debug_info, uint32_t* offset_ptr); + uint32_t extract(uint32_t offset, DataExtractor debug_info_data, + const DWARFAbbreviationDeclarationSet *abbrevs); + + /// extractDIEsIfNeeded - Parses a compile unit and indexes its DIEs if it + /// hasn't already been done. + size_t extractDIEsIfNeeded(bool cu_die_only); + void clear(); + void dump(raw_ostream &OS); + uint32_t getOffset() const { return Offset; } + /// Size in bytes of the compile unit header. + uint32_t getSize() const { return 11; } + bool containsDIEOffset(uint32_t die_offset) const { + return die_offset >= getFirstDIEOffset() && + die_offset < getNextCompileUnitOffset(); + } + uint32_t getFirstDIEOffset() const { return Offset + getSize(); } + uint32_t getNextCompileUnitOffset() const { return Offset + Length + 4; } + /// Size in bytes of the .debug_info data associated with this compile unit. + size_t getDebugInfoSize() const { return Length + 4 - getSize(); } + uint32_t getLength() const { return Length; } + uint16_t getVersion() const { return Version; } + const DWARFAbbreviationDeclarationSet *getAbbreviations() const { + return Abbrevs; + } + uint8_t getAddressByteSize() const { return AddrSize; } + uint64_t getBaseAddress() const { return BaseAddr; } + + void setBaseAddress(uint64_t base_addr) { + BaseAddr = base_addr; + } + + const DWARFDebugInfoEntryMinimal * + getCompileUnitDIE(bool extract_cu_die_only = true) { + extractDIEsIfNeeded(extract_cu_die_only); + if (DieArray.empty()) + return NULL; + return &DieArray[0]; + } + + /// setDIERelations - We read in all of the DIE entries into our flat list + /// of DIE entries and now we need to go back through all of them and set the + /// parent, sibling and child pointers for quick DIE navigation. + void setDIERelations(); + + void addDIE(DWARFDebugInfoEntryMinimal &die) { + // The average bytes per DIE entry has been seen to be + // around 14-20 so lets pre-reserve the needed memory for + // our DIE entries accordingly. Search forward for "Compute + // average bytes per DIE" to see #if'ed out code that does + // that determination. + + // Only reserve the memory if we are adding children of + // the main compile unit DIE. The compile unit DIE is always + // the first entry, so if our size is 1, then we are adding + // the first compile unit child DIE and should reserve + // the memory. + if (DieArray.empty()) + DieArray.reserve(getDebugInfoSize() / 14); + DieArray.push_back(die); + } + + void clearDIEs(bool keep_compile_unit_die); + + void buildAddressRangeTable(DWARFDebugAranges *debug_aranges, + bool clear_dies_if_already_not_parsed); +}; + +} + +#endif diff --git a/contrib/llvm/lib/DebugInfo/DWARFContext.cpp b/contrib/llvm/lib/DebugInfo/DWARFContext.cpp new file mode 100644 index 000000000..e1ac398b1 --- /dev/null +++ b/contrib/llvm/lib/DebugInfo/DWARFContext.cpp @@ -0,0 +1,167 @@ +//===-- DWARFContext.cpp --------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "DWARFContext.h" +#include "llvm/Support/Dwarf.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/raw_ostream.h" +#include +using namespace llvm; +using namespace dwarf; + +void DWARFContext::dump(raw_ostream &OS) { + OS << ".debug_abbrev contents:\n"; + getDebugAbbrev()->dump(OS); + + OS << "\n.debug_info contents:\n"; + for (unsigned i = 0, e = getNumCompileUnits(); i != e; ++i) + getCompileUnitAtIndex(i)->dump(OS); + + OS << "\n.debug_aranges contents:\n"; + DataExtractor arangesData(getARangeSection(), isLittleEndian(), 0); + uint32_t offset = 0; + DWARFDebugArangeSet set; + while (set.extract(arangesData, &offset)) + set.dump(OS); + + OS << "\n.debug_lines contents:\n"; + for (unsigned i = 0, e = getNumCompileUnits(); i != e; ++i) { + DWARFCompileUnit *cu = getCompileUnitAtIndex(i); + unsigned stmtOffset = + cu->getCompileUnitDIE()->getAttributeValueAsUnsigned(cu, DW_AT_stmt_list, + -1U); + if (stmtOffset != -1U) { + DataExtractor lineData(getLineSection(), isLittleEndian(), + cu->getAddressByteSize()); + DWARFDebugLine::DumpingState state(OS); + DWARFDebugLine::parseStatementTable(lineData, &stmtOffset, state); + } + } + + OS << "\n.debug_str contents:\n"; + DataExtractor strData(getStringSection(), isLittleEndian(), 0); + offset = 0; + uint32_t lastOffset = 0; + while (const char *s = strData.getCStr(&offset)) { + OS << format("0x%8.8x: \"%s\"\n", lastOffset, s); + lastOffset = offset; + } +} + +const DWARFDebugAbbrev *DWARFContext::getDebugAbbrev() { + if (Abbrev) + return Abbrev.get(); + + DataExtractor abbrData(getAbbrevSection(), isLittleEndian(), 0); + + Abbrev.reset(new DWARFDebugAbbrev()); + Abbrev->parse(abbrData); + return Abbrev.get(); +} + +const DWARFDebugAranges *DWARFContext::getDebugAranges() { + if (Aranges) + return Aranges.get(); + + DataExtractor arangesData(getARangeSection(), isLittleEndian(), 0); + + Aranges.reset(new DWARFDebugAranges()); + Aranges->extract(arangesData); + if (Aranges->isEmpty()) // No aranges in file, generate them from the DIEs. + Aranges->generate(this); + return Aranges.get(); +} + +const DWARFDebugLine::LineTable * +DWARFContext::getLineTableForCompileUnit(DWARFCompileUnit *cu) { + if (!Line) + Line.reset(new DWARFDebugLine()); + + unsigned stmtOffset = + cu->getCompileUnitDIE()->getAttributeValueAsUnsigned(cu, DW_AT_stmt_list, + -1U); + if (stmtOffset == -1U) + return 0; // No line table for this compile unit. + + // See if the line table is cached. + if (const DWARFDebugLine::LineTable *lt = Line->getLineTable(stmtOffset)) + return lt; + + // We have to parse it first. + DataExtractor lineData(getLineSection(), isLittleEndian(), + cu->getAddressByteSize()); + return Line->getOrParseLineTable(lineData, stmtOffset); +} + +void DWARFContext::parseCompileUnits() { + uint32_t offset = 0; + const DataExtractor &debug_info_data = DataExtractor(getInfoSection(), + isLittleEndian(), 0); + while (debug_info_data.isValidOffset(offset)) { + CUs.push_back(DWARFCompileUnit(*this)); + if (!CUs.back().extract(debug_info_data, &offset)) { + CUs.pop_back(); + break; + } + + offset = CUs.back().getNextCompileUnitOffset(); + } +} + +namespace { + struct OffsetComparator { + bool operator()(const DWARFCompileUnit &LHS, + const DWARFCompileUnit &RHS) const { + return LHS.getOffset() < RHS.getOffset(); + } + bool operator()(const DWARFCompileUnit &LHS, uint32_t RHS) const { + return LHS.getOffset() < RHS; + } + bool operator()(uint32_t LHS, const DWARFCompileUnit &RHS) const { + return LHS < RHS.getOffset(); + } + }; +} + +DWARFCompileUnit *DWARFContext::getCompileUnitForOffset(uint32_t offset) { + if (CUs.empty()) + parseCompileUnits(); + + DWARFCompileUnit *i = std::lower_bound(CUs.begin(), CUs.end(), offset, + OffsetComparator()); + if (i != CUs.end()) + return &*i; + return 0; +} + +DILineInfo DWARFContext::getLineInfoForAddress(uint64_t address) { + // First, get the offset of the compile unit. + uint32_t cuOffset = getDebugAranges()->findAddress(address); + // Retrieve the compile unit. + DWARFCompileUnit *cu = getCompileUnitForOffset(cuOffset); + if (!cu) + return DILineInfo("", 0, 0); + // Get the line table for this compile unit. + const DWARFDebugLine::LineTable *lineTable = getLineTableForCompileUnit(cu); + if (!lineTable) + return DILineInfo("", 0, 0); + // Get the index of the row we're looking for in the line table. + uint64_t hiPC = + cu->getCompileUnitDIE()->getAttributeValueAsUnsigned(cu, DW_AT_high_pc, + -1ULL); + uint32_t rowIndex = lineTable->lookupAddress(address, hiPC); + if (rowIndex == -1U) + return DILineInfo("", 0, 0); + + // From here, contruct the DILineInfo. + const DWARFDebugLine::Row &row = lineTable->Rows[rowIndex]; + const std::string &fileName = lineTable->Prologue.FileNames[row.File-1].Name; + + return DILineInfo(fileName.c_str(), row.Line, row.Column); +} diff --git a/contrib/llvm/lib/DebugInfo/DWARFContext.h b/contrib/llvm/lib/DebugInfo/DWARFContext.h new file mode 100644 index 000000000..746a4639f --- /dev/null +++ b/contrib/llvm/lib/DebugInfo/DWARFContext.h @@ -0,0 +1,118 @@ +//===-- DWARFContext.h ------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===/ + +#ifndef LLVM_DEBUGINFO_DWARFCONTEXT_H +#define LLVM_DEBUGINFO_DWARFCONTEXT_H + +#include "DWARFCompileUnit.h" +#include "DWARFDebugAranges.h" +#include "DWARFDebugLine.h" +#include "llvm/DebugInfo/DIContext.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/SmallVector.h" + +namespace llvm { + +/// DWARFContext +/// This data structure is the top level entity that deals with dwarf debug +/// information parsing. The actual data is supplied through pure virtual +/// methods that a concrete implementation provides. +class DWARFContext : public DIContext { + bool IsLittleEndian; + + SmallVector CUs; + OwningPtr Abbrev; + OwningPtr Aranges; + OwningPtr Line; + + DWARFContext(DWARFContext &); // = delete + DWARFContext &operator=(DWARFContext &); // = delete + + /// Read compile units from the debug_info section and store them in CUs. + void parseCompileUnits(); +protected: + DWARFContext(bool isLittleEndian) : IsLittleEndian(isLittleEndian) {} +public: + virtual void dump(raw_ostream &OS); + /// Get the number of compile units in this context. + unsigned getNumCompileUnits() { + if (CUs.empty()) + parseCompileUnits(); + return CUs.size(); + } + /// Get the compile unit at the specified index for this compile unit. + DWARFCompileUnit *getCompileUnitAtIndex(unsigned index) { + if (CUs.empty()) + parseCompileUnits(); + return &CUs[index]; + } + + /// Return the compile unit that includes an offset (relative to .debug_info). + DWARFCompileUnit *getCompileUnitForOffset(uint32_t offset); + + /// Get a pointer to the parsed DebugAbbrev object. + const DWARFDebugAbbrev *getDebugAbbrev(); + + /// Get a pointer to the parsed DebugAranges object. + const DWARFDebugAranges *getDebugAranges(); + + /// Get a pointer to a parsed line table corresponding to a compile unit. + const DWARFDebugLine::LineTable * + getLineTableForCompileUnit(DWARFCompileUnit *cu); + + virtual DILineInfo getLineInfoForAddress(uint64_t address); + + bool isLittleEndian() const { return IsLittleEndian; } + + virtual StringRef getInfoSection() = 0; + virtual StringRef getAbbrevSection() = 0; + virtual StringRef getARangeSection() = 0; + virtual StringRef getLineSection() = 0; + virtual StringRef getStringSection() = 0; + + static bool isSupportedVersion(unsigned version) { + return version == 2 || version == 3; + } +}; + + +/// DWARFContextInMemory is the simplest possible implementation of a +/// DWARFContext. It assumes all content is available in memory and stores +/// pointers to it. +class DWARFContextInMemory : public DWARFContext { + StringRef InfoSection; + StringRef AbbrevSection; + StringRef ARangeSection; + StringRef LineSection; + StringRef StringSection; +public: + DWARFContextInMemory(bool isLittleEndian, + StringRef infoSection, + StringRef abbrevSection, + StringRef aRangeSection, + StringRef lineSection, + StringRef stringSection) + : DWARFContext(isLittleEndian), + InfoSection(infoSection), + AbbrevSection(abbrevSection), + ARangeSection(aRangeSection), + LineSection(lineSection), + StringSection(stringSection) + {} + + virtual StringRef getInfoSection() { return InfoSection; } + virtual StringRef getAbbrevSection() { return AbbrevSection; } + virtual StringRef getARangeSection() { return ARangeSection; } + virtual StringRef getLineSection() { return LineSection; } + virtual StringRef getStringSection() { return StringSection; } +}; + +} + +#endif diff --git a/contrib/llvm/lib/DebugInfo/DWARFDebugAbbrev.cpp b/contrib/llvm/lib/DebugInfo/DWARFDebugAbbrev.cpp new file mode 100644 index 000000000..a11ae3f29 --- /dev/null +++ b/contrib/llvm/lib/DebugInfo/DWARFDebugAbbrev.cpp @@ -0,0 +1,106 @@ +//===-- DWARFDebugAbbrev.cpp ----------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "DWARFDebugAbbrev.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +bool DWARFAbbreviationDeclarationSet::extract(DataExtractor data, + uint32_t* offset_ptr) { + const uint32_t beginOffset = *offset_ptr; + Offset = beginOffset; + clear(); + DWARFAbbreviationDeclaration abbrevDeclaration; + uint32_t prevAbbrAode = 0; + while (abbrevDeclaration.extract(data, offset_ptr)) { + Decls.push_back(abbrevDeclaration); + if (IdxOffset == 0) { + IdxOffset = abbrevDeclaration.getCode(); + } else { + if (prevAbbrAode + 1 != abbrevDeclaration.getCode()) + IdxOffset = UINT32_MAX;// Out of order indexes, we can't do O(1) lookups + } + prevAbbrAode = abbrevDeclaration.getCode(); + } + return beginOffset != *offset_ptr; +} + +void DWARFAbbreviationDeclarationSet::dump(raw_ostream &OS) const { + for (unsigned i = 0, e = Decls.size(); i != e; ++i) + Decls[i].dump(OS); +} + +const DWARFAbbreviationDeclaration* +DWARFAbbreviationDeclarationSet::getAbbreviationDeclaration(uint32_t abbrCode) + const { + if (IdxOffset == UINT32_MAX) { + DWARFAbbreviationDeclarationCollConstIter pos; + DWARFAbbreviationDeclarationCollConstIter end = Decls.end(); + for (pos = Decls.begin(); pos != end; ++pos) { + if (pos->getCode() == abbrCode) + return &(*pos); + } + } else { + uint32_t idx = abbrCode - IdxOffset; + if (idx < Decls.size()) + return &Decls[idx]; + } + return NULL; +} + +DWARFDebugAbbrev::DWARFDebugAbbrev() : + AbbrevCollMap(), + PrevAbbrOffsetPos(AbbrevCollMap.end()) {} + + +void DWARFDebugAbbrev::parse(DataExtractor data) { + uint32_t offset = 0; + + while (data.isValidOffset(offset)) { + uint32_t initial_cu_offset = offset; + DWARFAbbreviationDeclarationSet abbrevDeclSet; + + if (abbrevDeclSet.extract(data, &offset)) + AbbrevCollMap[initial_cu_offset] = abbrevDeclSet; + else + break; + } + PrevAbbrOffsetPos = AbbrevCollMap.end(); +} + +void DWARFDebugAbbrev::dump(raw_ostream &OS) const { + if (AbbrevCollMap.empty()) { + OS << "< EMPTY >\n"; + return; + } + + DWARFAbbreviationDeclarationCollMapConstIter pos; + for (pos = AbbrevCollMap.begin(); pos != AbbrevCollMap.end(); ++pos) { + OS << format("Abbrev table for offset: 0x%8.8x\n", pos->first); + pos->second.dump(OS); + } +} + +const DWARFAbbreviationDeclarationSet* +DWARFDebugAbbrev::getAbbreviationDeclarationSet(uint64_t cu_abbr_offset) const { + DWARFAbbreviationDeclarationCollMapConstIter end = AbbrevCollMap.end(); + DWARFAbbreviationDeclarationCollMapConstIter pos; + if (PrevAbbrOffsetPos != end && + PrevAbbrOffsetPos->first == cu_abbr_offset) { + return &(PrevAbbrOffsetPos->second); + } else { + pos = AbbrevCollMap.find(cu_abbr_offset); + PrevAbbrOffsetPos = pos; + } + + if (pos != AbbrevCollMap.end()) + return &(pos->second); + return NULL; +} diff --git a/contrib/llvm/lib/DebugInfo/DWARFDebugAbbrev.h b/contrib/llvm/lib/DebugInfo/DWARFDebugAbbrev.h new file mode 100644 index 000000000..03189b132 --- /dev/null +++ b/contrib/llvm/lib/DebugInfo/DWARFDebugAbbrev.h @@ -0,0 +1,73 @@ +//===-- DWARFDebugAbbrev.h --------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_DWARFDEBUGABBREV_H +#define LLVM_DEBUGINFO_DWARFDEBUGABBREV_H + +#include "DWARFAbbreviationDeclaration.h" +#include +#include +#include + +namespace llvm { + +typedef std::vector + DWARFAbbreviationDeclarationColl; +typedef DWARFAbbreviationDeclarationColl::iterator + DWARFAbbreviationDeclarationCollIter; +typedef DWARFAbbreviationDeclarationColl::const_iterator + DWARFAbbreviationDeclarationCollConstIter; + +class DWARFAbbreviationDeclarationSet { + uint64_t Offset; + uint32_t IdxOffset; + std::vector Decls; + public: + DWARFAbbreviationDeclarationSet() + : Offset(0), IdxOffset(0) {} + + DWARFAbbreviationDeclarationSet(uint64_t offset, uint32_t idxOffset) + : Offset(offset), IdxOffset(idxOffset) {} + + void clear() { + IdxOffset = 0; + Decls.clear(); + } + uint64_t getOffset() const { return Offset; } + void dump(raw_ostream &OS) const; + bool extract(DataExtractor data, uint32_t* offset_ptr); + + const DWARFAbbreviationDeclaration * + getAbbreviationDeclaration(uint32_t abbrCode) const; +}; + +class DWARFDebugAbbrev { +public: + typedef std::map + DWARFAbbreviationDeclarationCollMap; + typedef DWARFAbbreviationDeclarationCollMap::iterator + DWARFAbbreviationDeclarationCollMapIter; + typedef DWARFAbbreviationDeclarationCollMap::const_iterator + DWARFAbbreviationDeclarationCollMapConstIter; + +private: + DWARFAbbreviationDeclarationCollMap AbbrevCollMap; + mutable DWARFAbbreviationDeclarationCollMapConstIter PrevAbbrOffsetPos; + +public: + DWARFDebugAbbrev(); + const DWARFAbbreviationDeclarationSet * + getAbbreviationDeclarationSet(uint64_t cu_abbr_offset) const; + void dump(raw_ostream &OS) const; + void parse(DataExtractor data); +}; + +} + +#endif diff --git a/contrib/llvm/lib/DebugInfo/DWARFDebugArangeSet.cpp b/contrib/llvm/lib/DebugInfo/DWARFDebugArangeSet.cpp new file mode 100644 index 000000000..b0c035438 --- /dev/null +++ b/contrib/llvm/lib/DebugInfo/DWARFDebugArangeSet.cpp @@ -0,0 +1,150 @@ +//===-- DWARFDebugArangeSet.cpp -------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "DWARFDebugArangeSet.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/raw_ostream.h" +#include +#include +using namespace llvm; + +void DWARFDebugArangeSet::clear() { + Offset = -1U; + std::memset(&Header, 0, sizeof(Header)); + ArangeDescriptors.clear(); +} + +void DWARFDebugArangeSet::compact() { + if (ArangeDescriptors.empty()) + return; + + // Iterate through all arange descriptors and combine any ranges that + // overlap or have matching boundaries. The ArangeDescriptors are assumed + // to be in ascending order. + uint32_t i = 0; + while (i + 1 < ArangeDescriptors.size()) { + if (ArangeDescriptors[i].getEndAddress() >= ArangeDescriptors[i+1].Address){ + // The current range ends at or exceeds the start of the next address + // range. Compute the max end address between the two and use that to + // make the new length. + const uint64_t max_end_addr = + std::max(ArangeDescriptors[i].getEndAddress(), + ArangeDescriptors[i+1].getEndAddress()); + ArangeDescriptors[i].Length = max_end_addr - ArangeDescriptors[i].Address; + // Now remove the next entry as it was just combined with the previous one + ArangeDescriptors.erase(ArangeDescriptors.begin()+i+1); + } else { + // Discontiguous address range, just proceed to the next one. + ++i; + } + } +} + +bool +DWARFDebugArangeSet::extract(DataExtractor data, uint32_t *offset_ptr) { + if (data.isValidOffset(*offset_ptr)) { + ArangeDescriptors.clear(); + Offset = *offset_ptr; + + // 7.20 Address Range Table + // + // Each set of entries in the table of address ranges contained in + // the .debug_aranges section begins with a header consisting of: a + // 4-byte length containing the length of the set of entries for this + // compilation unit, not including the length field itself; a 2-byte + // version identifier containing the value 2 for DWARF Version 2; a + // 4-byte offset into the.debug_infosection; a 1-byte unsigned integer + // containing the size in bytes of an address (or the offset portion of + // an address for segmented addressing) on the target system; and a + // 1-byte unsigned integer containing the size in bytes of a segment + // descriptor on the target system. This header is followed by a series + // of tuples. Each tuple consists of an address and a length, each in + // the size appropriate for an address on the target architecture. + Header.Length = data.getU32(offset_ptr); + Header.Version = data.getU16(offset_ptr); + Header.CuOffset = data.getU32(offset_ptr); + Header.AddrSize = data.getU8(offset_ptr); + Header.SegSize = data.getU8(offset_ptr); + + // Perform basic validation of the header fields. + if (!data.isValidOffsetForDataOfSize(Offset, Header.Length) || + (Header.AddrSize != 4 && Header.AddrSize != 8)) { + clear(); + return false; + } + + // The first tuple following the header in each set begins at an offset + // that is a multiple of the size of a single tuple (that is, twice the + // size of an address). The header is padded, if necessary, to the + // appropriate boundary. + const uint32_t header_size = *offset_ptr - Offset; + const uint32_t tuple_size = Header.AddrSize * 2; + uint32_t first_tuple_offset = 0; + while (first_tuple_offset < header_size) + first_tuple_offset += tuple_size; + + *offset_ptr = Offset + first_tuple_offset; + + Descriptor arangeDescriptor; + + assert(sizeof(arangeDescriptor.Address) == sizeof(arangeDescriptor.Length)); + assert(sizeof(arangeDescriptor.Address) >= Header.AddrSize); + + while (data.isValidOffset(*offset_ptr)) { + arangeDescriptor.Address = data.getUnsigned(offset_ptr, Header.AddrSize); + arangeDescriptor.Length = data.getUnsigned(offset_ptr, Header.AddrSize); + + // Each set of tuples is terminated by a 0 for the address and 0 + // for the length. + if (arangeDescriptor.Address || arangeDescriptor.Length) + ArangeDescriptors.push_back(arangeDescriptor); + else + break; // We are done if we get a zero address and length + } + + return !ArangeDescriptors.empty(); + } + return false; +} + +void DWARFDebugArangeSet::dump(raw_ostream &OS) const { + OS << format("Address Range Header: length = 0x%8.8x, version = 0x%4.4x, ", + Header.Length, Header.Version) + << format("cu_offset = 0x%8.8x, addr_size = 0x%2.2x, seg_size = 0x%2.2x\n", + Header.CuOffset, Header.AddrSize, Header.SegSize); + + const uint32_t hex_width = Header.AddrSize * 2; + for (DescriptorConstIter pos = ArangeDescriptors.begin(), + end = ArangeDescriptors.end(); pos != end; ++pos) + OS << format("[0x%*.*llx -", hex_width, hex_width, pos->Address) + << format(" 0x%*.*llx)\n", hex_width, hex_width, pos->getEndAddress()); +} + + +namespace { + class DescriptorContainsAddress { + const uint64_t Address; + public: + DescriptorContainsAddress(uint64_t address) : Address(address) {} + bool operator()(const DWARFDebugArangeSet::Descriptor &desc) const { + return Address >= desc.Address && Address < (desc.Address + desc.Length); + } + }; +} + +uint32_t DWARFDebugArangeSet::findAddress(uint64_t address) const { + DescriptorConstIter end = ArangeDescriptors.end(); + DescriptorConstIter pos = + std::find_if(ArangeDescriptors.begin(), end, // Range + DescriptorContainsAddress(address)); // Predicate + if (pos != end) + return Header.CuOffset; + + return -1U; +} diff --git a/contrib/llvm/lib/DebugInfo/DWARFDebugArangeSet.h b/contrib/llvm/lib/DebugInfo/DWARFDebugArangeSet.h new file mode 100644 index 000000000..9a2a6d0f0 --- /dev/null +++ b/contrib/llvm/lib/DebugInfo/DWARFDebugArangeSet.h @@ -0,0 +1,75 @@ +//===-- DWARFDebugArangeSet.h -----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_DWARFDEBUGARANGESET_H +#define LLVM_DEBUGINFO_DWARFDEBUGARANGESET_H + +#include "llvm/Support/DataExtractor.h" +#include + +namespace llvm { + +class raw_ostream; + +class DWARFDebugArangeSet { +public: + struct Header { + // The total length of the entries for that set, not including the length + // field itself. + uint32_t Length; + // The offset from the beginning of the .debug_info section of the + // compilation unit entry referenced by the table. + uint32_t CuOffset; + // The DWARF version number. + uint16_t Version; + // The size in bytes of an address on the target architecture. For segmented + // addressing, this is the size of the offset portion of the address. + uint8_t AddrSize; + // The size in bytes of a segment descriptor on the target architecture. + // If the target system uses a flat address space, this value is 0. + uint8_t SegSize; + }; + + struct Descriptor { + uint64_t Address; + uint64_t Length; + uint64_t getEndAddress() const { return Address + Length; } + }; + +private: + typedef std::vector DescriptorColl; + typedef DescriptorColl::iterator DescriptorIter; + typedef DescriptorColl::const_iterator DescriptorConstIter; + + uint32_t Offset; + Header Header; + DescriptorColl ArangeDescriptors; + +public: + DWARFDebugArangeSet() { clear(); } + void clear(); + void compact(); + bool extract(DataExtractor data, uint32_t *offset_ptr); + void dump(raw_ostream &OS) const; + + uint32_t getCompileUnitDIEOffset() const { return Header.CuOffset; } + uint32_t getOffsetOfNextEntry() const { return Offset + Header.Length + 4; } + uint32_t findAddress(uint64_t address) const; + uint32_t getNumDescriptors() const { return ArangeDescriptors.size(); } + const struct Header &getHeader() const { return Header; } + const Descriptor *getDescriptor(uint32_t i) const { + if (i < ArangeDescriptors.size()) + return &ArangeDescriptors[i]; + return NULL; + } +}; + +} + +#endif diff --git a/contrib/llvm/lib/DebugInfo/DWARFDebugAranges.cpp b/contrib/llvm/lib/DebugInfo/DWARFDebugAranges.cpp new file mode 100644 index 000000000..576d37d78 --- /dev/null +++ b/contrib/llvm/lib/DebugInfo/DWARFDebugAranges.cpp @@ -0,0 +1,223 @@ +//===-- DWARFDebugAranges.cpp -----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "DWARFDebugAranges.h" +#include "DWARFCompileUnit.h" +#include "DWARFContext.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/raw_ostream.h" +#include +#include +using namespace llvm; + +// Compare function DWARFDebugAranges::Range structures +static bool RangeLessThan(const DWARFDebugAranges::Range &range1, + const DWARFDebugAranges::Range &range2) { + return range1.LoPC < range2.LoPC; +} + +namespace { + class CountArangeDescriptors { + public: + CountArangeDescriptors(uint32_t &count_ref) : Count(count_ref) {} + void operator()(const DWARFDebugArangeSet &set) { + Count += set.getNumDescriptors(); + } + uint32_t &Count; + }; + + class AddArangeDescriptors { + public: + AddArangeDescriptors(DWARFDebugAranges::RangeColl &ranges) + : RangeCollection(ranges) {} + void operator()(const DWARFDebugArangeSet& set) { + const DWARFDebugArangeSet::Descriptor* arange_desc_ptr; + DWARFDebugAranges::Range range; + range.Offset = set.getCompileUnitDIEOffset(); + + for (uint32_t i=0; (arange_desc_ptr = set.getDescriptor(i)) != NULL; ++i){ + range.LoPC = arange_desc_ptr->Address; + range.Length = arange_desc_ptr->Length; + + // Insert each item in increasing address order so binary searching + // can later be done! + DWARFDebugAranges::RangeColl::iterator insert_pos = + std::lower_bound(RangeCollection.begin(), RangeCollection.end(), + range, RangeLessThan); + RangeCollection.insert(insert_pos, range); + } + } + DWARFDebugAranges::RangeColl& RangeCollection; + }; +} + +bool DWARFDebugAranges::extract(DataExtractor debug_aranges_data) { + if (debug_aranges_data.isValidOffset(0)) { + uint32_t offset = 0; + + typedef std::vector SetCollection; + typedef SetCollection::const_iterator SetCollectionIter; + SetCollection sets; + + DWARFDebugArangeSet set; + Range range; + while (set.extract(debug_aranges_data, &offset)) + sets.push_back(set); + + uint32_t count = 0; + + std::for_each(sets.begin(), sets.end(), CountArangeDescriptors(count)); + + if (count > 0) { + Aranges.reserve(count); + AddArangeDescriptors range_adder(Aranges); + std::for_each(sets.begin(), sets.end(), range_adder); + } + } + return false; +} + +bool DWARFDebugAranges::generate(DWARFContext *ctx) { + clear(); + if (ctx) { + const uint32_t num_compile_units = ctx->getNumCompileUnits(); + for (uint32_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) { + DWARFCompileUnit *cu = ctx->getCompileUnitAtIndex(cu_idx); + if (cu) + cu->buildAddressRangeTable(this, true); + } + } + return !isEmpty(); +} + +void DWARFDebugAranges::dump(raw_ostream &OS) const { + const uint32_t num_ranges = getNumRanges(); + for (uint32_t i = 0; i < num_ranges; ++i) { + const Range &range = Aranges[i]; + OS << format("0x%8.8x: [0x%8.8llx - 0x%8.8llx)\n", range.Offset, + (uint64_t)range.LoPC, (uint64_t)range.HiPC()); + } +} + +void DWARFDebugAranges::Range::dump(raw_ostream &OS) const { + OS << format("{0x%8.8x}: [0x%8.8llx - 0x%8.8llx)\n", Offset, LoPC, HiPC()); +} + +void DWARFDebugAranges::appendRange(uint32_t offset, uint64_t low_pc, + uint64_t high_pc) { + if (!Aranges.empty()) { + if (Aranges.back().Offset == offset && Aranges.back().HiPC() == low_pc) { + Aranges.back().setHiPC(high_pc); + return; + } + } + Aranges.push_back(Range(low_pc, high_pc, offset)); +} + +void DWARFDebugAranges::sort(bool minimize, uint32_t n) { + const size_t orig_arange_size = Aranges.size(); + // Size of one? If so, no sorting is needed + if (orig_arange_size <= 1) + return; + // Sort our address range entries + std::stable_sort(Aranges.begin(), Aranges.end(), RangeLessThan); + + if (!minimize) + return; + + // Most address ranges are contiguous from function to function + // so our new ranges will likely be smaller. We calculate the size + // of the new ranges since although std::vector objects can be resized, + // the will never reduce their allocated block size and free any excesss + // memory, so we might as well start a brand new collection so it is as + // small as possible. + + // First calculate the size of the new minimal arange vector + // so we don't have to do a bunch of re-allocations as we + // copy the new minimal stuff over to the new collection. + size_t minimal_size = 1; + for (size_t i = 1; i < orig_arange_size; ++i) { + if (!Range::SortedOverlapCheck(Aranges[i-1], Aranges[i], n)) + ++minimal_size; + } + + // If the sizes are the same, then no consecutive aranges can be + // combined, we are done. + if (minimal_size == orig_arange_size) + return; + + // Else, make a new RangeColl that _only_ contains what we need. + RangeColl minimal_aranges; + minimal_aranges.resize(minimal_size); + uint32_t j = 0; + minimal_aranges[j] = Aranges[0]; + for (size_t i = 1; i < orig_arange_size; ++i) { + if(Range::SortedOverlapCheck (minimal_aranges[j], Aranges[i], n)) { + minimal_aranges[j].setHiPC (Aranges[i].HiPC()); + } else { + // Only increment j if we aren't merging + minimal_aranges[++j] = Aranges[i]; + } + } + assert (j+1 == minimal_size); + + // Now swap our new minimal aranges into place. The local + // minimal_aranges will then contian the old big collection + // which will get freed. + minimal_aranges.swap(Aranges); +} + +uint32_t DWARFDebugAranges::findAddress(uint64_t address) const { + if (!Aranges.empty()) { + Range range(address); + RangeCollIterator begin = Aranges.begin(); + RangeCollIterator end = Aranges.end(); + RangeCollIterator pos = lower_bound(begin, end, range, RangeLessThan); + + if (pos != end && pos->LoPC <= address && address < pos->HiPC()) { + return pos->Offset; + } else if (pos != begin) { + --pos; + if (pos->LoPC <= address && address < pos->HiPC()) + return (*pos).Offset; + } + } + return -1U; +} + +bool +DWARFDebugAranges::allRangesAreContiguous(uint64_t &LoPC, uint64_t &HiPC) const{ + if (Aranges.empty()) + return false; + + uint64_t next_addr = 0; + RangeCollIterator begin = Aranges.begin(); + for (RangeCollIterator pos = begin, end = Aranges.end(); pos != end; + ++pos) { + if (pos != begin && pos->LoPC != next_addr) + return false; + next_addr = pos->HiPC(); + } + // We checked for empty at the start of function so front() will be valid. + LoPC = Aranges.front().LoPC; + // We checked for empty at the start of function so back() will be valid. + HiPC = Aranges.back().HiPC(); + return true; +} + +bool DWARFDebugAranges::getMaxRange(uint64_t &LoPC, uint64_t &HiPC) const { + if (Aranges.empty()) + return false; + // We checked for empty at the start of function so front() will be valid. + LoPC = Aranges.front().LoPC; + // We checked for empty at the start of function so back() will be valid. + HiPC = Aranges.back().HiPC(); + return true; +} + diff --git a/contrib/llvm/lib/DebugInfo/DWARFDebugAranges.h b/contrib/llvm/lib/DebugInfo/DWARFDebugAranges.h new file mode 100644 index 000000000..12afb60be --- /dev/null +++ b/contrib/llvm/lib/DebugInfo/DWARFDebugAranges.h @@ -0,0 +1,98 @@ +//===-- DWARFDebugAranges.h -------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_DWARFDEBUGARANGES_H +#define LLVM_DEBUGINFO_DWARFDEBUGARANGES_H + +#include "DWARFDebugArangeSet.h" +#include + +namespace llvm { + +class DWARFContext; + +class DWARFDebugAranges { +public: + struct Range { + explicit Range(uint64_t lo = -1ULL, uint64_t hi = -1ULL, + uint32_t off = -1U) + : LoPC(lo), Length(hi-lo), Offset(off) {} + + void clear() { + LoPC = -1ULL; + Length = 0; + Offset = -1U; + } + + void setHiPC(uint64_t HiPC) { + if (HiPC == -1ULL || HiPC <= LoPC) + Length = 0; + else + Length = HiPC - LoPC; + } + uint64_t HiPC() const { + if (Length) + return LoPC + Length; + return -1ULL; + } + bool isValidRange() const { return Length > 0; } + + static bool SortedOverlapCheck(const Range &curr_range, + const Range &next_range, uint32_t n) { + if (curr_range.Offset != next_range.Offset) + return false; + return curr_range.HiPC() + n >= next_range.LoPC; + } + + bool contains(const Range &range) const { + return LoPC <= range.LoPC && range.HiPC() <= HiPC(); + } + + void dump(raw_ostream &OS) const; + uint64_t LoPC; // Start of address range + uint32_t Length; // End of address range (not including this address) + uint32_t Offset; // Offset of the compile unit or die + }; + + void clear() { Aranges.clear(); } + bool allRangesAreContiguous(uint64_t& LoPC, uint64_t& HiPC) const; + bool getMaxRange(uint64_t& LoPC, uint64_t& HiPC) const; + bool extract(DataExtractor debug_aranges_data); + bool generate(DWARFContext *ctx); + + // Use append range multiple times and then call sort + void appendRange(uint32_t cu_offset, uint64_t low_pc, uint64_t high_pc); + void sort(bool minimize, uint32_t n); + + const Range *rangeAtIndex(uint32_t idx) const { + if (idx < Aranges.size()) + return &Aranges[idx]; + return NULL; + } + void dump(raw_ostream &OS) const; + uint32_t findAddress(uint64_t address) const; + bool isEmpty() const { return Aranges.empty(); } + uint32_t getNumRanges() const { return Aranges.size(); } + + uint32_t offsetAtIndex(uint32_t idx) const { + if (idx < Aranges.size()) + return Aranges[idx].Offset; + return -1U; + } + + typedef std::vector RangeColl; + typedef RangeColl::const_iterator RangeCollIterator; + +private: + RangeColl Aranges; +}; + +} + +#endif diff --git a/contrib/llvm/lib/DebugInfo/DWARFDebugInfoEntry.cpp b/contrib/llvm/lib/DebugInfo/DWARFDebugInfoEntry.cpp new file mode 100644 index 000000000..1b089adbe --- /dev/null +++ b/contrib/llvm/lib/DebugInfo/DWARFDebugInfoEntry.cpp @@ -0,0 +1,444 @@ +//===-- DWARFDebugInfoEntry.cpp --------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "DWARFDebugInfoEntry.h" +#include "DWARFCompileUnit.h" +#include "DWARFContext.h" +#include "DWARFDebugAbbrev.h" +#include "DWARFFormValue.h" +#include "llvm/Support/Dwarf.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; +using namespace dwarf; + +void DWARFDebugInfoEntryMinimal::dump(raw_ostream &OS, + const DWARFCompileUnit *cu, + unsigned recurseDepth, + unsigned indent) const { + DataExtractor debug_info_data = cu->getDebugInfoExtractor(); + uint32_t offset = Offset; + + if (debug_info_data.isValidOffset(offset)) { + uint64_t abbrCode = debug_info_data.getULEB128(&offset); + + OS << format("\n0x%8.8x: ", Offset); + if (abbrCode) { + if (AbbrevDecl) { + const char *tagString = TagString(getTag()); + if (tagString) + OS.indent(indent) << tagString; + else + OS.indent(indent) << format("DW_TAG_Unknown_%x", getTag()); + OS << format(" [%u] %c\n", abbrCode, + AbbrevDecl->hasChildren() ? '*' : ' '); + + // Dump all data in the .debug_info for the attributes + const uint32_t numAttributes = AbbrevDecl->getNumAttributes(); + for (uint32_t i = 0; i != numAttributes; ++i) { + uint16_t attr = AbbrevDecl->getAttrByIndex(i); + uint16_t form = AbbrevDecl->getFormByIndex(i); + dumpAttribute(OS, cu, &offset, attr, form, indent); + } + + const DWARFDebugInfoEntryMinimal *child = getFirstChild(); + if (recurseDepth > 0 && child) { + while (child) { + child->dump(OS, cu, recurseDepth-1, indent+2); + child = child->getSibling(); + } + } + } else { + OS << "Abbreviation code not found in 'debug_abbrev' class for code: " + << abbrCode << '\n'; + } + } else { + OS.indent(indent) << "NULL\n"; + } + } +} + +void DWARFDebugInfoEntryMinimal::dumpAttribute(raw_ostream &OS, + const DWARFCompileUnit *cu, + uint32_t* offset_ptr, + uint16_t attr, + uint16_t form, + unsigned indent) const { + OS << format("0x%8.8x: ", *offset_ptr); + OS.indent(indent+2); + const char *attrString = AttributeString(attr); + if (attrString) + OS << attrString; + else + OS << format("DW_AT_Unknown_%x", attr); + const char *formString = FormEncodingString(form); + if (formString) + OS << " [" << formString << ']'; + else + OS << format(" [DW_FORM_Unknown_%x]", form); + + DWARFFormValue formValue(form); + + if (!formValue.extractValue(cu->getDebugInfoExtractor(), offset_ptr, cu)) + return; + + OS << "\t("; + formValue.dump(OS, cu); + OS << ")\n"; +} + +bool DWARFDebugInfoEntryMinimal::extractFast(const DWARFCompileUnit *cu, + const uint8_t *fixed_form_sizes, + uint32_t *offset_ptr) { + Offset = *offset_ptr; + + DataExtractor debug_info_data = cu->getDebugInfoExtractor(); + uint64_t abbrCode = debug_info_data.getULEB128(offset_ptr); + + assert (fixed_form_sizes); // For best performance this should be specified! + + if (abbrCode) { + uint32_t offset = *offset_ptr; + + AbbrevDecl = cu->getAbbreviations()->getAbbreviationDeclaration(abbrCode); + + // Skip all data in the .debug_info for the attributes + const uint32_t numAttributes = AbbrevDecl->getNumAttributes(); + uint32_t i; + uint16_t form; + for (i=0; igetFormByIndex(i); + + const uint8_t fixed_skip_size = fixed_form_sizes[form]; + if (fixed_skip_size) + offset += fixed_skip_size; + else { + bool form_is_indirect = false; + do { + form_is_indirect = false; + uint32_t form_size = 0; + switch (form) { + // Blocks if inlined data that have a length field and the data bytes + // inlined in the .debug_info. + case DW_FORM_block: + form_size = debug_info_data.getULEB128(&offset); + break; + case DW_FORM_block1: + form_size = debug_info_data.getU8(&offset); + break; + case DW_FORM_block2: + form_size = debug_info_data.getU16(&offset); + break; + case DW_FORM_block4: + form_size = debug_info_data.getU32(&offset); + break; + + // Inlined NULL terminated C-strings + case DW_FORM_string: + debug_info_data.getCStr(&offset); + break; + + // Compile unit address sized values + case DW_FORM_addr: + case DW_FORM_ref_addr: + form_size = cu->getAddressByteSize(); + break; + + // 1 byte values + case DW_FORM_data1: + case DW_FORM_flag: + case DW_FORM_ref1: + form_size = 1; + break; + + // 2 byte values + case DW_FORM_data2: + case DW_FORM_ref2: + form_size = 2; + break; + + // 4 byte values + case DW_FORM_strp: + case DW_FORM_data4: + case DW_FORM_ref4: + form_size = 4; + break; + + // 8 byte values + case DW_FORM_data8: + case DW_FORM_ref8: + form_size = 8; + break; + + // signed or unsigned LEB 128 values + case DW_FORM_sdata: + case DW_FORM_udata: + case DW_FORM_ref_udata: + debug_info_data.getULEB128(&offset); + break; + + case DW_FORM_indirect: + form_is_indirect = true; + form = debug_info_data.getULEB128(&offset); + break; + + default: + *offset_ptr = Offset; + return false; + } + offset += form_size; + + } while (form_is_indirect); + } + } + *offset_ptr = offset; + return true; + } else { + AbbrevDecl = NULL; + return true; // NULL debug tag entry + } + + return false; +} + +bool +DWARFDebugInfoEntryMinimal::extract(const DWARFCompileUnit *cu, + uint32_t *offset_ptr) { + DataExtractor debug_info_data = cu->getDebugInfoExtractor(); + const uint32_t cu_end_offset = cu->getNextCompileUnitOffset(); + const uint8_t cu_addr_size = cu->getAddressByteSize(); + uint32_t offset = *offset_ptr; + if ((offset < cu_end_offset) && debug_info_data.isValidOffset(offset)) { + Offset = offset; + + uint64_t abbrCode = debug_info_data.getULEB128(&offset); + + if (abbrCode) { + AbbrevDecl = cu->getAbbreviations()->getAbbreviationDeclaration(abbrCode); + + if (AbbrevDecl) { + uint16_t tag = AbbrevDecl->getTag(); + + bool isCompileUnitTag = tag == DW_TAG_compile_unit; + if(cu && isCompileUnitTag) + const_cast(cu)->setBaseAddress(0); + + // Skip all data in the .debug_info for the attributes + const uint32_t numAttributes = AbbrevDecl->getNumAttributes(); + for (uint32_t i = 0; i != numAttributes; ++i) { + uint16_t attr = AbbrevDecl->getAttrByIndex(i); + uint16_t form = AbbrevDecl->getFormByIndex(i); + + if (isCompileUnitTag && + ((attr == DW_AT_entry_pc) || (attr == DW_AT_low_pc))) { + DWARFFormValue form_value(form); + if (form_value.extractValue(debug_info_data, &offset, cu)) { + if (attr == DW_AT_low_pc || attr == DW_AT_entry_pc) + const_cast(cu) + ->setBaseAddress(form_value.getUnsigned()); + } + } else { + bool form_is_indirect = false; + do { + form_is_indirect = false; + register uint32_t form_size = 0; + switch (form) { + // Blocks if inlined data that have a length field and the data + // bytes // inlined in the .debug_info + case DW_FORM_block: + form_size = debug_info_data.getULEB128(&offset); + break; + case DW_FORM_block1: + form_size = debug_info_data.getU8(&offset); + break; + case DW_FORM_block2: + form_size = debug_info_data.getU16(&offset); + break; + case DW_FORM_block4: + form_size = debug_info_data.getU32(&offset); + break; + + // Inlined NULL terminated C-strings + case DW_FORM_string: + debug_info_data.getCStr(&offset); + break; + + // Compile unit address sized values + case DW_FORM_addr: + case DW_FORM_ref_addr: + form_size = cu_addr_size; + break; + + // 1 byte values + case DW_FORM_data1: + case DW_FORM_flag: + case DW_FORM_ref1: + form_size = 1; + break; + + // 2 byte values + case DW_FORM_data2: + case DW_FORM_ref2: + form_size = 2; + break; + + // 4 byte values + case DW_FORM_strp: + form_size = 4; + break; + + case DW_FORM_data4: + case DW_FORM_ref4: + form_size = 4; + break; + + // 8 byte values + case DW_FORM_data8: + case DW_FORM_ref8: + form_size = 8; + break; + + // signed or unsigned LEB 128 values + case DW_FORM_sdata: + case DW_FORM_udata: + case DW_FORM_ref_udata: + debug_info_data.getULEB128(&offset); + break; + + case DW_FORM_indirect: + form = debug_info_data.getULEB128(&offset); + form_is_indirect = true; + break; + + default: + *offset_ptr = offset; + return false; + } + + offset += form_size; + } while (form_is_indirect); + } + } + *offset_ptr = offset; + return true; + } + } else { + AbbrevDecl = NULL; + *offset_ptr = offset; + return true; // NULL debug tag entry + } + } + + return false; +} + +uint32_t +DWARFDebugInfoEntryMinimal::getAttributeValue(const DWARFCompileUnit *cu, + const uint16_t attr, + DWARFFormValue &form_value, + uint32_t *end_attr_offset_ptr) + const { + if (AbbrevDecl) { + uint32_t attr_idx = AbbrevDecl->findAttributeIndex(attr); + + if (attr_idx != -1U) { + uint32_t offset = getOffset(); + + DataExtractor debug_info_data = cu->getDebugInfoExtractor(); + + // Skip the abbreviation code so we are at the data for the attributes + debug_info_data.getULEB128(&offset); + + uint32_t idx = 0; + while (idx < attr_idx) + DWARFFormValue::skipValue(AbbrevDecl->getFormByIndex(idx++), + debug_info_data, &offset, cu); + + const uint32_t attr_offset = offset; + form_value = DWARFFormValue(AbbrevDecl->getFormByIndex(idx)); + if (form_value.extractValue(debug_info_data, &offset, cu)) { + if (end_attr_offset_ptr) + *end_attr_offset_ptr = offset; + return attr_offset; + } + } + } + + return 0; +} + +const char* +DWARFDebugInfoEntryMinimal::getAttributeValueAsString( + const DWARFCompileUnit* cu, + const uint16_t attr, + const char* fail_value) const { + DWARFFormValue form_value; + if (getAttributeValue(cu, attr, form_value)) { + DataExtractor stringExtractor(cu->getContext().getStringSection(), + false, 0); + return form_value.getAsCString(&stringExtractor); + } + return fail_value; +} + +uint64_t +DWARFDebugInfoEntryMinimal::getAttributeValueAsUnsigned( + const DWARFCompileUnit* cu, + const uint16_t attr, + uint64_t fail_value) const { + DWARFFormValue form_value; + if (getAttributeValue(cu, attr, form_value)) + return form_value.getUnsigned(); + return fail_value; +} + +int64_t +DWARFDebugInfoEntryMinimal::getAttributeValueAsSigned( + const DWARFCompileUnit* cu, + const uint16_t attr, + int64_t fail_value) const { + DWARFFormValue form_value; + if (getAttributeValue(cu, attr, form_value)) + return form_value.getSigned(); + return fail_value; +} + +uint64_t +DWARFDebugInfoEntryMinimal::getAttributeValueAsReference( + const DWARFCompileUnit* cu, + const uint16_t attr, + uint64_t fail_value) const { + DWARFFormValue form_value; + if (getAttributeValue(cu, attr, form_value)) + return form_value.getReference(cu); + return fail_value; +} + +void +DWARFDebugInfoEntryMinimal::buildAddressRangeTable(const DWARFCompileUnit *cu, + DWARFDebugAranges *debug_aranges) + const { + if (AbbrevDecl) { + uint16_t tag = AbbrevDecl->getTag(); + if (tag == DW_TAG_subprogram) { + uint64_t hi_pc = -1ULL; + uint64_t lo_pc = getAttributeValueAsUnsigned(cu, DW_AT_low_pc, -1ULL); + if (lo_pc != -1ULL) + hi_pc = getAttributeValueAsUnsigned(cu, DW_AT_high_pc, -1ULL); + if (hi_pc != -1ULL) + debug_aranges->appendRange(cu->getOffset(), lo_pc, hi_pc); + } + + const DWARFDebugInfoEntryMinimal *child = getFirstChild(); + while (child) { + child->buildAddressRangeTable(cu, debug_aranges); + child = child->getSibling(); + } + } +} diff --git a/contrib/llvm/lib/DebugInfo/DWARFDebugInfoEntry.h b/contrib/llvm/lib/DebugInfo/DWARFDebugInfoEntry.h new file mode 100644 index 000000000..aff2e8556 --- /dev/null +++ b/contrib/llvm/lib/DebugInfo/DWARFDebugInfoEntry.h @@ -0,0 +1,135 @@ +//===-- DWARFDebugInfoEntry.h -----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_DWARFDEBUGINFOENTRY_H +#define LLVM_DEBUGINFO_DWARFDEBUGINFOENTRY_H + +#include "DWARFAbbreviationDeclaration.h" +#include "llvm/Support/DataTypes.h" + +namespace llvm { + +class DWARFDebugAranges; +class DWARFCompileUnit; +class DWARFContext; +class DWARFFormValue; + +/// DWARFDebugInfoEntryMinimal - A DIE with only the minimum required data. +class DWARFDebugInfoEntryMinimal { + /// Offset within the .debug_info of the start of this entry. + uint64_t Offset; + + /// How many to subtract from "this" to get the parent. + /// If zero this die has no parent. + uint32_t ParentIdx; + + /// How many to add to "this" to get the sibling. + uint32_t SiblingIdx; + + const DWARFAbbreviationDeclaration *AbbrevDecl; +public: + DWARFDebugInfoEntryMinimal() + : Offset(0), ParentIdx(0), SiblingIdx(0), AbbrevDecl(0) {} + + void dump(raw_ostream &OS, const DWARFCompileUnit *cu, + unsigned recurseDepth, unsigned indent = 0) const; + void dumpAttribute(raw_ostream &OS, const DWARFCompileUnit *cu, + uint32_t *offset_ptr, uint16_t attr, uint16_t form, + unsigned indent = 0) const; + + bool extractFast(const DWARFCompileUnit *cu, const uint8_t *fixed_form_sizes, + uint32_t *offset_ptr); + + /// Extract a debug info entry for a given compile unit from the + /// .debug_info and .debug_abbrev data starting at the given offset. + bool extract(const DWARFCompileUnit *cu, uint32_t *offset_ptr); + + uint32_t getTag() const { return AbbrevDecl ? AbbrevDecl->getTag() : 0; } + bool isNULL() const { return AbbrevDecl == 0; } + uint64_t getOffset() const { return Offset; } + uint32_t getNumAttributes() const { + return !isNULL() ? AbbrevDecl->getNumAttributes() : 0; + } + bool hasChildren() const { return !isNULL() && AbbrevDecl->hasChildren(); } + + // We know we are kept in a vector of contiguous entries, so we know + // our parent will be some index behind "this". + DWARFDebugInfoEntryMinimal *getParent() { + return ParentIdx > 0 ? this - ParentIdx : 0; + } + const DWARFDebugInfoEntryMinimal *getParent() const { + return ParentIdx > 0 ? this - ParentIdx : 0; + } + // We know we are kept in a vector of contiguous entries, so we know + // our sibling will be some index after "this". + DWARFDebugInfoEntryMinimal *getSibling() { + return SiblingIdx > 0 ? this + SiblingIdx : 0; + } + const DWARFDebugInfoEntryMinimal *getSibling() const { + return SiblingIdx > 0 ? this + SiblingIdx : 0; + } + // We know we are kept in a vector of contiguous entries, so we know + // we don't need to store our child pointer, if we have a child it will + // be the next entry in the list... + DWARFDebugInfoEntryMinimal *getFirstChild() { + return hasChildren() ? this + 1 : 0; + } + const DWARFDebugInfoEntryMinimal *getFirstChild() const { + return hasChildren() ? this + 1 : 0; + } + + void setParent(DWARFDebugInfoEntryMinimal *parent) { + if (parent) { + // We know we are kept in a vector of contiguous entries, so we know + // our parent will be some index behind "this". + ParentIdx = this - parent; + } else + ParentIdx = 0; + } + void setSibling(DWARFDebugInfoEntryMinimal *sibling) { + if (sibling) { + // We know we are kept in a vector of contiguous entries, so we know + // our sibling will be some index after "this". + SiblingIdx = sibling - this; + sibling->setParent(getParent()); + } else + SiblingIdx = 0; + } + + const DWARFAbbreviationDeclaration *getAbbreviationDeclarationPtr() const { + return AbbrevDecl; + } + + uint32_t getAttributeValue(const DWARFCompileUnit *cu, + const uint16_t attr, DWARFFormValue &formValue, + uint32_t *end_attr_offset_ptr = 0) const; + + const char* getAttributeValueAsString(const DWARFCompileUnit* cu, + const uint16_t attr, + const char *fail_value) const; + + uint64_t getAttributeValueAsUnsigned(const DWARFCompileUnit *cu, + const uint16_t attr, + uint64_t fail_value) const; + + uint64_t getAttributeValueAsReference(const DWARFCompileUnit *cu, + const uint16_t attr, + uint64_t fail_value) const; + + int64_t getAttributeValueAsSigned(const DWARFCompileUnit* cu, + const uint16_t attr, + int64_t fail_value) const; + + void buildAddressRangeTable(const DWARFCompileUnit *cu, + DWARFDebugAranges *debug_aranges) const; +}; + +} + +#endif diff --git a/contrib/llvm/lib/DebugInfo/DWARFDebugLine.cpp b/contrib/llvm/lib/DebugInfo/DWARFDebugLine.cpp new file mode 100644 index 000000000..fe1ef78b0 --- /dev/null +++ b/contrib/llvm/lib/DebugInfo/DWARFDebugLine.cpp @@ -0,0 +1,475 @@ +//===-- DWARFDebugLine.cpp ------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "DWARFDebugLine.h" +#include "llvm/Support/Dwarf.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/raw_ostream.h" +#include +using namespace llvm; +using namespace dwarf; + +void DWARFDebugLine::Prologue::dump(raw_ostream &OS) const { + OS << "Line table prologue:\n" + << format(" total_length: 0x%8.8x\n", TotalLength) + << format(" version: %u\n", Version) + << format("prologue_length: 0x%8.8x\n", PrologueLength) + << format("min_inst_length: %u\n", MinInstLength) + << format("default_is_stmt: %u\n", DefaultIsStmt) + << format(" line_base: %i\n", LineBase) + << format(" line_range: %u\n", LineRange) + << format(" opcode_base: %u\n", OpcodeBase); + + for (uint32_t i = 0; i < StandardOpcodeLengths.size(); ++i) + OS << format("standard_opcode_lengths[%s] = %u\n", LNStandardString(i+1), + StandardOpcodeLengths[i]); + + if (!IncludeDirectories.empty()) + for (uint32_t i = 0; i < IncludeDirectories.size(); ++i) + OS << format("include_directories[%3u] = '", i+1) + << IncludeDirectories[i] << "'\n"; + + if (!FileNames.empty()) { + OS << " Dir Mod Time File Len File Name\n" + << " ---- ---------- ---------- -----------" + "----------------\n"; + for (uint32_t i = 0; i < FileNames.size(); ++i) { + const FileNameEntry& fileEntry = FileNames[i]; + OS << format("file_names[%3u] %4u ", i+1, fileEntry.DirIdx) + << format("0x%8.8x 0x%8.8x ", fileEntry.ModTime, fileEntry.Length) + << fileEntry.Name << '\n'; + } + } +} + +void DWARFDebugLine::Row::postAppend() { + BasicBlock = false; + PrologueEnd = false; + EpilogueBegin = false; +} + +void DWARFDebugLine::Row::reset(bool default_is_stmt) { + Address = 0; + Line = 1; + Column = 0; + File = 1; + Isa = 0; + IsStmt = default_is_stmt; + BasicBlock = false; + EndSequence = false; + PrologueEnd = false; + EpilogueBegin = false; +} + +void DWARFDebugLine::Row::dump(raw_ostream &OS) const { + OS << format("0x%16.16llx %6u %6u", Address, Line, Column) + << format(" %6u %3u ", File, Isa) + << (IsStmt ? " is_stmt" : "") + << (BasicBlock ? " basic_block" : "") + << (PrologueEnd ? " prologue_end" : "") + << (EpilogueBegin ? " epilogue_begin" : "") + << (EndSequence ? " end_sequence" : "") + << '\n'; +} + +void DWARFDebugLine::LineTable::dump(raw_ostream &OS) const { + Prologue.dump(OS); + OS << '\n'; + + if (!Rows.empty()) { + OS << "Address Line Column File ISA Flags\n" + << "------------------ ------ ------ ------ --- -------------\n"; + for (std::vector::const_iterator pos = Rows.begin(), + end = Rows.end(); pos != end; ++pos) + pos->dump(OS); + } +} + +DWARFDebugLine::State::~State() {} + +void DWARFDebugLine::State::appendRowToMatrix(uint32_t offset) { + ++row; // Increase the row number. + LineTable::appendRow(*this); + Row::postAppend(); +} + +DWARFDebugLine::DumpingState::~DumpingState() {} + +void DWARFDebugLine::DumpingState::finalize(uint32_t offset) { + LineTable::dump(OS); +} + +const DWARFDebugLine::LineTable * +DWARFDebugLine::getLineTable(uint32_t offset) const { + LineTableConstIter pos = LineTableMap.find(offset); + if (pos != LineTableMap.end()) + return &pos->second; + return 0; +} + +const DWARFDebugLine::LineTable * +DWARFDebugLine::getOrParseLineTable(DataExtractor debug_line_data, + uint32_t offset) { + std::pair pos = + LineTableMap.insert(LineTableMapTy::value_type(offset, LineTable())); + if (pos.second) { + // Parse and cache the line table for at this offset. + State state; + if (!parseStatementTable(debug_line_data, &offset, state)) + return 0; + pos.first->second = state; + } + return &pos.first->second; +} + +bool +DWARFDebugLine::parsePrologue(DataExtractor debug_line_data, + uint32_t *offset_ptr, Prologue *prologue) { + const uint32_t prologue_offset = *offset_ptr; + + prologue->clear(); + prologue->TotalLength = debug_line_data.getU32(offset_ptr); + prologue->Version = debug_line_data.getU16(offset_ptr); + if (prologue->Version != 2) + return false; + + prologue->PrologueLength = debug_line_data.getU32(offset_ptr); + const uint32_t end_prologue_offset = prologue->PrologueLength + *offset_ptr; + prologue->MinInstLength = debug_line_data.getU8(offset_ptr); + prologue->DefaultIsStmt = debug_line_data.getU8(offset_ptr); + prologue->LineBase = debug_line_data.getU8(offset_ptr); + prologue->LineRange = debug_line_data.getU8(offset_ptr); + prologue->OpcodeBase = debug_line_data.getU8(offset_ptr); + + prologue->StandardOpcodeLengths.reserve(prologue->OpcodeBase-1); + for (uint32_t i = 1; i < prologue->OpcodeBase; ++i) { + uint8_t op_len = debug_line_data.getU8(offset_ptr); + prologue->StandardOpcodeLengths.push_back(op_len); + } + + while (*offset_ptr < end_prologue_offset) { + const char *s = debug_line_data.getCStr(offset_ptr); + if (s && s[0]) + prologue->IncludeDirectories.push_back(s); + else + break; + } + + while (*offset_ptr < end_prologue_offset) { + const char *name = debug_line_data.getCStr(offset_ptr); + if (name && name[0]) { + FileNameEntry fileEntry; + fileEntry.Name = name; + fileEntry.DirIdx = debug_line_data.getULEB128(offset_ptr); + fileEntry.ModTime = debug_line_data.getULEB128(offset_ptr); + fileEntry.Length = debug_line_data.getULEB128(offset_ptr); + prologue->FileNames.push_back(fileEntry); + } else { + break; + } + } + + if (*offset_ptr != end_prologue_offset) { + fprintf(stderr, "warning: parsing line table prologue at 0x%8.8x should" + " have ended at 0x%8.8x but it ended ad 0x%8.8x\n", + prologue_offset, end_prologue_offset, *offset_ptr); + } + return end_prologue_offset; +} + +bool +DWARFDebugLine::parseStatementTable(DataExtractor debug_line_data, + uint32_t *offset_ptr, State &state) { + const uint32_t debug_line_offset = *offset_ptr; + + Prologue *prologue = &state.Prologue; + + if (!parsePrologue(debug_line_data, offset_ptr, prologue)) { + // Restore our offset and return false to indicate failure! + *offset_ptr = debug_line_offset; + return false; + } + + const uint32_t end_offset = debug_line_offset + prologue->TotalLength + + sizeof(prologue->TotalLength); + + state.reset(); + + while (*offset_ptr < end_offset) { + uint8_t opcode = debug_line_data.getU8(offset_ptr); + + if (opcode == 0) { + // Extended Opcodes always start with a zero opcode followed by + // a uleb128 length so you can skip ones you don't know about + uint32_t ext_offset = *offset_ptr; + uint64_t len = debug_line_data.getULEB128(offset_ptr); + uint32_t arg_size = len - (*offset_ptr - ext_offset); + + uint8_t sub_opcode = debug_line_data.getU8(offset_ptr); + switch (sub_opcode) { + case DW_LNE_end_sequence: + // Set the end_sequence register of the state machine to true and + // append a row to the matrix using the current values of the + // state-machine registers. Then reset the registers to the initial + // values specified above. Every statement program sequence must end + // with a DW_LNE_end_sequence instruction which creates a row whose + // address is that of the byte after the last target machine instruction + // of the sequence. + state.EndSequence = true; + state.appendRowToMatrix(*offset_ptr); + state.reset(); + break; + + case DW_LNE_set_address: + // Takes a single relocatable address as an operand. The size of the + // operand is the size appropriate to hold an address on the target + // machine. Set the address register to the value given by the + // relocatable address. All of the other statement program opcodes + // that affect the address register add a delta to it. This instruction + // stores a relocatable value into it instead. + state.Address = debug_line_data.getAddress(offset_ptr); + break; + + case DW_LNE_define_file: + // Takes 4 arguments. The first is a null terminated string containing + // a source file name. The second is an unsigned LEB128 number + // representing the directory index of the directory in which the file + // was found. The third is an unsigned LEB128 number representing the + // time of last modification of the file. The fourth is an unsigned + // LEB128 number representing the length in bytes of the file. The time + // and length fields may contain LEB128(0) if the information is not + // available. + // + // The directory index represents an entry in the include_directories + // section of the statement program prologue. The index is LEB128(0) + // if the file was found in the current directory of the compilation, + // LEB128(1) if it was found in the first directory in the + // include_directories section, and so on. The directory index is + // ignored for file names that represent full path names. + // + // The files are numbered, starting at 1, in the order in which they + // appear; the names in the prologue come before names defined by + // the DW_LNE_define_file instruction. These numbers are used in the + // the file register of the state machine. + { + FileNameEntry fileEntry; + fileEntry.Name = debug_line_data.getCStr(offset_ptr); + fileEntry.DirIdx = debug_line_data.getULEB128(offset_ptr); + fileEntry.ModTime = debug_line_data.getULEB128(offset_ptr); + fileEntry.Length = debug_line_data.getULEB128(offset_ptr); + prologue->FileNames.push_back(fileEntry); + } + break; + + default: + // Length doesn't include the zero opcode byte or the length itself, but + // it does include the sub_opcode, so we have to adjust for that below + (*offset_ptr) += arg_size; + break; + } + } else if (opcode < prologue->OpcodeBase) { + switch (opcode) { + // Standard Opcodes + case DW_LNS_copy: + // Takes no arguments. Append a row to the matrix using the + // current values of the state-machine registers. Then set + // the basic_block register to false. + state.appendRowToMatrix(*offset_ptr); + break; + + case DW_LNS_advance_pc: + // Takes a single unsigned LEB128 operand, multiplies it by the + // min_inst_length field of the prologue, and adds the + // result to the address register of the state machine. + state.Address += debug_line_data.getULEB128(offset_ptr) * + prologue->MinInstLength; + break; + + case DW_LNS_advance_line: + // Takes a single signed LEB128 operand and adds that value to + // the line register of the state machine. + state.Line += debug_line_data.getSLEB128(offset_ptr); + break; + + case DW_LNS_set_file: + // Takes a single unsigned LEB128 operand and stores it in the file + // register of the state machine. + state.File = debug_line_data.getULEB128(offset_ptr); + break; + + case DW_LNS_set_column: + // Takes a single unsigned LEB128 operand and stores it in the + // column register of the state machine. + state.Column = debug_line_data.getULEB128(offset_ptr); + break; + + case DW_LNS_negate_stmt: + // Takes no arguments. Set the is_stmt register of the state + // machine to the logical negation of its current value. + state.IsStmt = !state.IsStmt; + break; + + case DW_LNS_set_basic_block: + // Takes no arguments. Set the basic_block register of the + // state machine to true + state.BasicBlock = true; + break; + + case DW_LNS_const_add_pc: + // Takes no arguments. Add to the address register of the state + // machine the address increment value corresponding to special + // opcode 255. The motivation for DW_LNS_const_add_pc is this: + // when the statement program needs to advance the address by a + // small amount, it can use a single special opcode, which occupies + // a single byte. When it needs to advance the address by up to + // twice the range of the last special opcode, it can use + // DW_LNS_const_add_pc followed by a special opcode, for a total + // of two bytes. Only if it needs to advance the address by more + // than twice that range will it need to use both DW_LNS_advance_pc + // and a special opcode, requiring three or more bytes. + { + uint8_t adjust_opcode = 255 - prologue->OpcodeBase; + uint64_t addr_offset = (adjust_opcode / prologue->LineRange) * + prologue->MinInstLength; + state.Address += addr_offset; + } + break; + + case DW_LNS_fixed_advance_pc: + // Takes a single uhalf operand. Add to the address register of + // the state machine the value of the (unencoded) operand. This + // is the only extended opcode that takes an argument that is not + // a variable length number. The motivation for DW_LNS_fixed_advance_pc + // is this: existing assemblers cannot emit DW_LNS_advance_pc or + // special opcodes because they cannot encode LEB128 numbers or + // judge when the computation of a special opcode overflows and + // requires the use of DW_LNS_advance_pc. Such assemblers, however, + // can use DW_LNS_fixed_advance_pc instead, sacrificing compression. + state.Address += debug_line_data.getU16(offset_ptr); + break; + + case DW_LNS_set_prologue_end: + // Takes no arguments. Set the prologue_end register of the + // state machine to true + state.PrologueEnd = true; + break; + + case DW_LNS_set_epilogue_begin: + // Takes no arguments. Set the basic_block register of the + // state machine to true + state.EpilogueBegin = true; + break; + + case DW_LNS_set_isa: + // Takes a single unsigned LEB128 operand and stores it in the + // column register of the state machine. + state.Isa = debug_line_data.getULEB128(offset_ptr); + break; + + default: + // Handle any unknown standard opcodes here. We know the lengths + // of such opcodes because they are specified in the prologue + // as a multiple of LEB128 operands for each opcode. + { + assert(opcode - 1U < prologue->StandardOpcodeLengths.size()); + uint8_t opcode_length = prologue->StandardOpcodeLengths[opcode - 1]; + for (uint8_t i=0; iOpcodeBase; + uint64_t addr_offset = (adjust_opcode / prologue->LineRange) * + prologue->MinInstLength; + int32_t line_offset = prologue->LineBase + + (adjust_opcode % prologue->LineRange); + state.Line += line_offset; + state.Address += addr_offset; + state.appendRowToMatrix(*offset_ptr); + } + } + + state.finalize(*offset_ptr); + + return end_offset; +} + +static bool findMatchingAddress(const DWARFDebugLine::Row& row1, + const DWARFDebugLine::Row& row2) { + return row1.Address < row2.Address; +} + +uint32_t +DWARFDebugLine::LineTable::lookupAddress(uint64_t address, + uint64_t cu_high_pc) const { + uint32_t index = UINT32_MAX; + if (!Rows.empty()) { + // Use the lower_bound algorithm to perform a binary search since we know + // that our line table data is ordered by address. + DWARFDebugLine::Row row; + row.Address = address; + typedef std::vector::const_iterator iterator; + iterator begin_pos = Rows.begin(); + iterator end_pos = Rows.end(); + iterator pos = std::lower_bound(begin_pos, end_pos, row, + findMatchingAddress); + if (pos == end_pos) { + if (address < cu_high_pc) + return Rows.size()-1; + } else { + // Rely on fact that we are using a std::vector and we can do + // pointer arithmetic to find the row index (which will be one less + // that what we found since it will find the first position after + // the current address) since std::vector iterators are just + // pointers to the container type. + index = pos - begin_pos; + if (pos->Address > address) { + if (index > 0) + --index; + else + index = UINT32_MAX; + } + } + } + return index; // Failed to find address. +} diff --git a/contrib/llvm/lib/DebugInfo/DWARFDebugLine.h b/contrib/llvm/lib/DebugInfo/DWARFDebugLine.h new file mode 100644 index 000000000..bc6a70b11 --- /dev/null +++ b/contrib/llvm/lib/DebugInfo/DWARFDebugLine.h @@ -0,0 +1,190 @@ +//===-- DWARFDebugLine.h ----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_DWARFDEBUGLINE_H +#define LLVM_DEBUGINFO_DWARFDEBUGLINE_H + +#include "llvm/Support/DataExtractor.h" +#include +#include +#include + +namespace llvm { + +class raw_ostream; + +class DWARFDebugLine { +public: + struct FileNameEntry { + FileNameEntry() : DirIdx(0), ModTime(0), Length(0) {} + + std::string Name; + uint64_t DirIdx; + uint64_t ModTime; + uint64_t Length; + }; + + struct Prologue { + Prologue() + : TotalLength(0), Version(0), PrologueLength(0), MinInstLength(0), + DefaultIsStmt(0), LineBase(0), LineRange(0), OpcodeBase(0) {} + + // The size in bytes of the statement information for this compilation unit + // (not including the total_length field itself). + uint32_t TotalLength; + // Version identifier for the statement information format. + uint16_t Version; + // The number of bytes following the prologue_length field to the beginning + // of the first byte of the statement program itself. + uint32_t PrologueLength; + // The size in bytes of the smallest target machine instruction. Statement + // program opcodes that alter the address register first multiply their + // operands by this value. + uint8_t MinInstLength; + // The initial value of theis_stmtregister. + uint8_t DefaultIsStmt; + // This parameter affects the meaning of the special opcodes. See below. + int8_t LineBase; + // This parameter affects the meaning of the special opcodes. See below. + uint8_t LineRange; + // The number assigned to the first special opcode. + uint8_t OpcodeBase; + std::vector StandardOpcodeLengths; + std::vector IncludeDirectories; + std::vector FileNames; + + // Length of the prologue in bytes. + uint32_t getLength() const { + return PrologueLength + sizeof(TotalLength) + sizeof(Version) + + sizeof(PrologueLength); + } + // Length of the line table data in bytes (not including the prologue). + uint32_t getStatementTableLength() const { + return TotalLength + sizeof(TotalLength) - getLength(); + } + int32_t getMaxLineIncrementForSpecialOpcode() const { + return LineBase + (int8_t)LineRange - 1; + } + void dump(raw_ostream &OS) const; + void clear() { + TotalLength = Version = PrologueLength = 0; + MinInstLength = LineBase = LineRange = OpcodeBase = 0; + StandardOpcodeLengths.clear(); + IncludeDirectories.clear(); + FileNames.clear(); + } + }; + + // Standard .debug_line state machine structure. + struct Row { + Row(bool default_is_stmt = false) { reset(default_is_stmt); } + /// Called after a row is appended to the matrix. + void postAppend(); + void reset(bool default_is_stmt); + void dump(raw_ostream &OS) const; + + // The program-counter value corresponding to a machine instruction + // generated by the compiler. + uint64_t Address; + // An unsigned integer indicating a source line number. Lines are numbered + // beginning at 1. The compiler may emit the value 0 in cases where an + // instruction cannot be attributed to any source line. + uint32_t Line; + // An unsigned integer indicating a column number within a source line. + // Columns are numbered beginning at 1. The value 0 is reserved to indicate + // that a statement begins at the 'left edge' of the line. + uint16_t Column; + // An unsigned integer indicating the identity of the source file + // corresponding to a machine instruction. + uint16_t File; + // An unsigned integer whose value encodes the applicable instruction set + // architecture for the current instruction. + uint8_t Isa; + // A boolean indicating that the current instruction is the beginning of a + // statement. + uint8_t IsStmt:1, + // A boolean indicating that the current instruction is the + // beginning of a basic block. + BasicBlock:1, + // A boolean indicating that the current address is that of the + // first byte after the end of a sequence of target machine + // instructions. + EndSequence:1, + // A boolean indicating that the current address is one (of possibly + // many) where execution should be suspended for an entry breakpoint + // of a function. + PrologueEnd:1, + // A boolean indicating that the current address is one (of possibly + // many) where execution should be suspended for an exit breakpoint + // of a function. + EpilogueBegin:1; + }; + + struct LineTable { + void appendRow(const DWARFDebugLine::Row &state) { Rows.push_back(state); } + void clear() { + Prologue.clear(); + Rows.clear(); + } + + uint32_t lookupAddress(uint64_t address, uint64_t cu_high_pc) const; + void dump(raw_ostream &OS) const; + + struct Prologue Prologue; + std::vector Rows; + }; + + struct State : public Row, public LineTable { + // Special row codes. + enum { + StartParsingLineTable = 0, + DoneParsingLineTable = -1 + }; + + State() : row(StartParsingLineTable) {} + virtual ~State(); + + virtual void appendRowToMatrix(uint32_t offset); + virtual void finalize(uint32_t offset) { row = DoneParsingLineTable; } + virtual void reset() { Row::reset(Prologue.DefaultIsStmt); } + + // The row number that starts at zero for the prologue, and increases for + // each row added to the matrix. + unsigned row; + }; + + struct DumpingState : public State { + DumpingState(raw_ostream &OS) : OS(OS) {} + virtual ~DumpingState(); + virtual void finalize(uint32_t offset); + private: + raw_ostream &OS; + }; + + static bool parsePrologue(DataExtractor debug_line_data, uint32_t *offset_ptr, + Prologue *prologue); + /// Parse a single line table (prologue and all rows). + static bool parseStatementTable(DataExtractor debug_line_data, + uint32_t *offset_ptr, State &state); + + const LineTable *getLineTable(uint32_t offset) const; + const LineTable *getOrParseLineTable(DataExtractor debug_line_data, + uint32_t offset); + +private: + typedef std::map LineTableMapTy; + typedef LineTableMapTy::iterator LineTableIter; + typedef LineTableMapTy::const_iterator LineTableConstIter; + + LineTableMapTy LineTableMap; +}; + +} + +#endif diff --git a/contrib/llvm/lib/DebugInfo/DWARFFormValue.cpp b/contrib/llvm/lib/DebugInfo/DWARFFormValue.cpp new file mode 100644 index 000000000..705efe554 --- /dev/null +++ b/contrib/llvm/lib/DebugInfo/DWARFFormValue.cpp @@ -0,0 +1,427 @@ +//===-- DWARFFormValue.cpp ------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "DWARFFormValue.h" +#include "DWARFCompileUnit.h" +#include "DWARFContext.h" +#include "llvm/Support/Dwarf.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/raw_ostream.h" +#include +using namespace llvm; +using namespace dwarf; + +static const uint8_t form_sizes_addr4[] = { + 0, // 0x00 unused + 4, // 0x01 DW_FORM_addr + 0, // 0x02 unused + 0, // 0x03 DW_FORM_block2 + 0, // 0x04 DW_FORM_block4 + 2, // 0x05 DW_FORM_data2 + 4, // 0x06 DW_FORM_data4 + 8, // 0x07 DW_FORM_data8 + 0, // 0x08 DW_FORM_string + 0, // 0x09 DW_FORM_block + 0, // 0x0a DW_FORM_block1 + 1, // 0x0b DW_FORM_data1 + 1, // 0x0c DW_FORM_flag + 0, // 0x0d DW_FORM_sdata + 4, // 0x0e DW_FORM_strp + 0, // 0x0f DW_FORM_udata + 4, // 0x10 DW_FORM_ref_addr + 1, // 0x11 DW_FORM_ref1 + 2, // 0x12 DW_FORM_ref2 + 4, // 0x13 DW_FORM_ref4 + 8, // 0x14 DW_FORM_ref8 + 0, // 0x15 DW_FORM_ref_udata + 0, // 0x16 DW_FORM_indirect +}; + +static const uint8_t form_sizes_addr8[] = { + 0, // 0x00 unused + 8, // 0x01 DW_FORM_addr + 0, // 0x02 unused + 0, // 0x03 DW_FORM_block2 + 0, // 0x04 DW_FORM_block4 + 2, // 0x05 DW_FORM_data2 + 4, // 0x06 DW_FORM_data4 + 8, // 0x07 DW_FORM_data8 + 0, // 0x08 DW_FORM_string + 0, // 0x09 DW_FORM_block + 0, // 0x0a DW_FORM_block1 + 1, // 0x0b DW_FORM_data1 + 1, // 0x0c DW_FORM_flag + 0, // 0x0d DW_FORM_sdata + 4, // 0x0e DW_FORM_strp + 0, // 0x0f DW_FORM_udata + 8, // 0x10 DW_FORM_ref_addr + 1, // 0x11 DW_FORM_ref1 + 2, // 0x12 DW_FORM_ref2 + 4, // 0x13 DW_FORM_ref4 + 8, // 0x14 DW_FORM_ref8 + 0, // 0x15 DW_FORM_ref_udata + 0, // 0x16 DW_FORM_indirect +}; + +const uint8_t * +DWARFFormValue::getFixedFormSizesForAddressSize(uint8_t addr_size) { + switch (addr_size) { + case 4: return form_sizes_addr4; + case 8: return form_sizes_addr8; + } + return NULL; +} + +bool +DWARFFormValue::extractValue(DataExtractor data, uint32_t *offset_ptr, + const DWARFCompileUnit *cu) { + bool indirect = false; + bool is_block = false; + Value.data = NULL; + // Read the value for the form into value and follow and DW_FORM_indirect + // instances we run into + do { + indirect = false; + switch (Form) { + case DW_FORM_addr: + case DW_FORM_ref_addr: + Value.uval = data.getUnsigned(offset_ptr, cu->getAddressByteSize()); + break; + case DW_FORM_block: + Value.uval = data.getULEB128(offset_ptr); + is_block = true; + break; + case DW_FORM_block1: + Value.uval = data.getU8(offset_ptr); + is_block = true; + break; + case DW_FORM_block2: + Value.uval = data.getU16(offset_ptr); + is_block = true; + break; + case DW_FORM_block4: + Value.uval = data.getU32(offset_ptr); + is_block = true; + break; + case DW_FORM_data1: + case DW_FORM_ref1: + case DW_FORM_flag: + Value.uval = data.getU8(offset_ptr); + break; + case DW_FORM_data2: + case DW_FORM_ref2: + Value.uval = data.getU16(offset_ptr); + break; + case DW_FORM_data4: + case DW_FORM_ref4: + Value.uval = data.getU32(offset_ptr); + break; + case DW_FORM_data8: + case DW_FORM_ref8: + Value.uval = data.getU64(offset_ptr); + break; + case DW_FORM_sdata: + Value.sval = data.getSLEB128(offset_ptr); + break; + case DW_FORM_strp: + Value.uval = data.getU32(offset_ptr); + break; + case DW_FORM_udata: + case DW_FORM_ref_udata: + Value.uval = data.getULEB128(offset_ptr); + break; + case DW_FORM_string: + Value.cstr = data.getCStr(offset_ptr); + // Set the string value to also be the data for inlined cstr form + // values only so we can tell the differnence between DW_FORM_string + // and DW_FORM_strp form values + Value.data = (uint8_t*)Value.cstr; + break; + case DW_FORM_indirect: + Form = data.getULEB128(offset_ptr); + indirect = true; + break; + default: + return false; + } + } while (indirect); + + if (is_block) { + StringRef str = data.getData().substr(*offset_ptr, Value.uval); + Value.data = NULL; + if (!str.empty()) { + Value.data = reinterpret_cast(str.data()); + *offset_ptr += Value.uval; + } + } + + return true; +} + +bool +DWARFFormValue::skipValue(DataExtractor debug_info_data, uint32_t* offset_ptr, + const DWARFCompileUnit *cu) const { + return DWARFFormValue::skipValue(Form, debug_info_data, offset_ptr, cu); +} + +bool +DWARFFormValue::skipValue(uint16_t form, DataExtractor debug_info_data, + uint32_t *offset_ptr, const DWARFCompileUnit *cu) { + bool indirect = false; + do { + indirect = false; + switch (form) { + // Blocks if inlined data that have a length field and the data bytes + // inlined in the .debug_info + case DW_FORM_block: { + uint64_t size = debug_info_data.getULEB128(offset_ptr); + *offset_ptr += size; + return true; + } + case DW_FORM_block1: { + uint8_t size = debug_info_data.getU8(offset_ptr); + *offset_ptr += size; + return true; + } + case DW_FORM_block2: { + uint16_t size = debug_info_data.getU16(offset_ptr); + *offset_ptr += size; + return true; + } + case DW_FORM_block4: { + uint32_t size = debug_info_data.getU32(offset_ptr); + *offset_ptr += size; + return true; + } + + // Inlined NULL terminated C-strings + case DW_FORM_string: + debug_info_data.getCStr(offset_ptr); + return true; + + // Compile unit address sized values + case DW_FORM_addr: + case DW_FORM_ref_addr: + *offset_ptr += cu->getAddressByteSize(); + return true; + + // 1 byte values + case DW_FORM_data1: + case DW_FORM_flag: + case DW_FORM_ref1: + *offset_ptr += 1; + return true; + + // 2 byte values + case DW_FORM_data2: + case DW_FORM_ref2: + *offset_ptr += 2; + return true; + + // 4 byte values + case DW_FORM_strp: + case DW_FORM_data4: + case DW_FORM_ref4: + *offset_ptr += 4; + return true; + + // 8 byte values + case DW_FORM_data8: + case DW_FORM_ref8: + *offset_ptr += 8; + return true; + + // signed or unsigned LEB 128 values + // case DW_FORM_APPLE_db_str: + case DW_FORM_sdata: + case DW_FORM_udata: + case DW_FORM_ref_udata: + debug_info_data.getULEB128(offset_ptr); + return true; + + case DW_FORM_indirect: + indirect = true; + form = debug_info_data.getULEB128(offset_ptr); + break; + default: + return false; + } + } while (indirect); + return true; +} + +void +DWARFFormValue::dump(raw_ostream &OS, const DWARFCompileUnit *cu) const { + DataExtractor debug_str_data(cu->getContext().getStringSection(), true, 0); + uint64_t uvalue = getUnsigned(); + bool cu_relative_offset = false; + + switch (Form) { + case DW_FORM_addr: OS << format("0x%016x", uvalue); break; + case DW_FORM_flag: + case DW_FORM_data1: OS << format("0x%02x", uvalue); break; + case DW_FORM_data2: OS << format("0x%04x", uvalue); break; + case DW_FORM_data4: OS << format("0x%08x", uvalue); break; + case DW_FORM_data8: OS << format("0x%016x", uvalue); break; + case DW_FORM_string: + OS << '"'; + OS.write_escaped(getAsCString(NULL)); + OS << '"'; + break; + case DW_FORM_block: + case DW_FORM_block1: + case DW_FORM_block2: + case DW_FORM_block4: + if (uvalue > 0) { + switch (Form) { + case DW_FORM_block: OS << format("<0x%llx> ", uvalue); break; + case DW_FORM_block1: OS << format("<0x%2.2x> ", (uint8_t)uvalue); break; + case DW_FORM_block2: OS << format("<0x%4.4x> ", (uint16_t)uvalue); break; + case DW_FORM_block4: OS << format("<0x%8.8x> ", (uint32_t)uvalue); break; + default: break; + } + + const uint8_t* data_ptr = Value.data; + if (data_ptr) { + // uvalue contains size of block + const uint8_t* end_data_ptr = data_ptr + uvalue; + while (data_ptr < end_data_ptr) { + OS << format("%2.2x ", *data_ptr); + ++data_ptr; + } + } + else + OS << "NULL"; + } + break; + + case DW_FORM_sdata: OS << getSigned(); break; + case DW_FORM_udata: OS << getUnsigned(); break; + case DW_FORM_strp: { + OS << format(" .debug_str[0x%8.8x] = ", (uint32_t)uvalue); + const char* dbg_str = getAsCString(&debug_str_data); + if (dbg_str) { + OS << '"'; + OS.write_escaped(dbg_str); + OS << '"'; + } + break; + } + case DW_FORM_ref_addr: + OS << format("0x%016x", uvalue); + break; + case DW_FORM_ref1: + cu_relative_offset = true; + OS << format("cu + 0x%2.2x", (uint8_t)uvalue); + break; + case DW_FORM_ref2: + cu_relative_offset = true; + OS << format("cu + 0x%4.4x", (uint16_t)uvalue); + break; + case DW_FORM_ref4: + cu_relative_offset = true; + OS << format("cu + 0x%4.4x", (uint32_t)uvalue); + break; + case DW_FORM_ref8: + cu_relative_offset = true; + OS << format("cu + 0x%8.8llx", uvalue); + break; + case DW_FORM_ref_udata: + cu_relative_offset = true; + OS << format("cu + 0x%llx", uvalue); + break; + + // All DW_FORM_indirect attributes should be resolved prior to calling + // this function + case DW_FORM_indirect: + OS << "DW_FORM_indirect"; + break; + default: + OS << format("DW_FORM(0x%4.4x)", Form); + break; + } + + if (cu_relative_offset) + OS << format(" => {0x%8.8x}", (uvalue + (cu ? cu->getOffset() : 0))); +} + +const char* +DWARFFormValue::getAsCString(const DataExtractor *debug_str_data_ptr) const { + if (isInlinedCStr()) { + return Value.cstr; + } else if (debug_str_data_ptr) { + uint32_t offset = Value.uval; + return debug_str_data_ptr->getCStr(&offset); + } + return NULL; +} + +uint64_t DWARFFormValue::getReference(const DWARFCompileUnit *cu) const { + uint64_t die_offset = Value.uval; + switch (Form) { + case DW_FORM_ref1: + case DW_FORM_ref2: + case DW_FORM_ref4: + case DW_FORM_ref8: + case DW_FORM_ref_udata: + die_offset += (cu ? cu->getOffset() : 0); + break; + default: + break; + } + + return die_offset; +} + +bool +DWARFFormValue::resolveCompileUnitReferences(const DWARFCompileUnit *cu) { + switch (Form) { + case DW_FORM_ref1: + case DW_FORM_ref2: + case DW_FORM_ref4: + case DW_FORM_ref8: + case DW_FORM_ref_udata: + Value.uval += cu->getOffset(); + Form = DW_FORM_ref_addr; + return true; + default: + break; + } + return false; +} + +const uint8_t *DWARFFormValue::BlockData() const { + if (!isInlinedCStr()) + return Value.data; + return NULL; +} + +bool DWARFFormValue::isBlockForm(uint16_t form) { + switch (form) { + case DW_FORM_block: + case DW_FORM_block1: + case DW_FORM_block2: + case DW_FORM_block4: + return true; + } + return false; +} + +bool DWARFFormValue::isDataForm(uint16_t form) { + switch (form) { + case DW_FORM_sdata: + case DW_FORM_udata: + case DW_FORM_data1: + case DW_FORM_data2: + case DW_FORM_data4: + case DW_FORM_data8: + return true; + } + return false; +} diff --git a/contrib/llvm/lib/DebugInfo/DWARFFormValue.h b/contrib/llvm/lib/DebugInfo/DWARFFormValue.h new file mode 100644 index 000000000..22ac01166 --- /dev/null +++ b/contrib/llvm/lib/DebugInfo/DWARFFormValue.h @@ -0,0 +1,78 @@ +//===-- DWARFFormValue.h ----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_DWARFFORMVALUE_H +#define LLVM_DEBUGINFO_DWARFFORMVALUE_H + +#include "llvm/Support/DataExtractor.h" + +namespace llvm { + +class DWARFCompileUnit; +class raw_ostream; + +class DWARFFormValue { +public: + struct ValueType { + ValueType() : data(NULL) { + uval = 0; + } + + union { + uint64_t uval; + int64_t sval; + const char* cstr; + }; + 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) {} + uint16_t getForm() const { return Form; } + const ValueType& value() const { return Value; } + void dump(raw_ostream &OS, const DWARFCompileUnit* cu) const; + bool extractValue(DataExtractor data, uint32_t *offset_ptr, + const DWARFCompileUnit *cu); + bool isInlinedCStr() const { + return Value.data != NULL && Value.data == (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; + bool skipValue(DataExtractor debug_info_data, uint32_t *offset_ptr, + const DWARFCompileUnit *cu) 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 *getFixedFormSizesForAddressSize(uint8_t addr_size); +}; + +} + +#endif diff --git a/contrib/llvm/lib/ExecutionEngine/ExecutionEngine.cpp b/contrib/llvm/lib/ExecutionEngine/ExecutionEngine.cpp index 7652090af..525877b68 100644 --- a/contrib/llvm/lib/ExecutionEngine/ExecutionEngine.cpp +++ b/contrib/llvm/lib/ExecutionEngine/ExecutionEngine.cpp @@ -93,7 +93,7 @@ public: /// \brief Returns the address the GlobalVariable should be written into. The /// GVMemoryBlock object prefixes that. static char *Create(const GlobalVariable *GV, const TargetData& TD) { - const Type *ElTy = GV->getType()->getElementType(); + Type *ElTy = GV->getType()->getElementType(); size_t GVSize = (size_t)TD.getTypeAllocSize(ElTy); void *RawMemory = ::operator new( TargetData::RoundUpAlignment(sizeof(GVMemoryBlock), @@ -272,7 +272,7 @@ void *ArgvArray::reset(LLVMContext &C, ExecutionEngine *EE, Array = new char[(InputArgv.size()+1)*PtrSize]; DEBUG(dbgs() << "JIT: ARGV = " << (void*)Array << "\n"); - const Type *SBytePtr = Type::getInt8PtrTy(C); + Type *SBytePtr = Type::getInt8PtrTy(C); for (unsigned i = 0; i != InputArgv.size(); ++i) { unsigned Size = InputArgv[i].size()+1; @@ -361,8 +361,8 @@ int ExecutionEngine::runFunctionAsMain(Function *Fn, // Check main() type unsigned NumArgs = Fn->getFunctionType()->getNumParams(); - const FunctionType *FTy = Fn->getFunctionType(); - const Type* PPInt8Ty = Type::getInt8PtrTy(Fn->getContext())->getPointerTo(); + FunctionType *FTy = Fn->getFunctionType(); + Type* PPInt8Ty = Type::getInt8PtrTy(Fn->getContext())->getPointerTo(); // Check the argument types. if (NumArgs > 3) @@ -422,6 +422,7 @@ ExecutionEngine *ExecutionEngine::createJIT(Module *M, JITMemoryManager *JMM, CodeGenOpt::Level OptLevel, bool GVsWithCode, + Reloc::Model RM, CodeModel::Model CMM) { if (ExecutionEngine::JITCtor == 0) { if (ErrorStr) @@ -436,9 +437,8 @@ ExecutionEngine *ExecutionEngine::createJIT(Module *M, SmallVector MAttrs; TargetMachine *TM = - EngineBuilder::selectTarget(M, MArch, MCPU, MAttrs, ErrorStr); + EngineBuilder::selectTarget(M, MArch, MCPU, MAttrs, RM, CMM, ErrorStr); if (!TM || (ErrorStr && ErrorStr->length() > 0)) return 0; - TM->setCodeModel(CMM); return ExecutionEngine::JITCtor(M, ErrorStr, JMM, OptLevel, GVsWithCode, TM); } @@ -465,10 +465,9 @@ ExecutionEngine *EngineBuilder::create() { // Unless the interpreter was explicitly selected or the JIT is not linked, // try making a JIT. if (WhichEngine & EngineKind::JIT) { - if (TargetMachine *TM = - EngineBuilder::selectTarget(M, MArch, MCPU, MAttrs, ErrorStr)) { - TM->setCodeModel(CMModel); - + if (TargetMachine *TM = EngineBuilder::selectTarget(M, MArch, MCPU, MAttrs, + RelocModel, CMModel, + ErrorStr)) { if (UseMCJIT && ExecutionEngine::MCJITCtor) { ExecutionEngine *EE = ExecutionEngine::MCJITCtor(M, ErrorStr, JMM, OptLevel, @@ -548,8 +547,7 @@ GenericValue ExecutionEngine::getConstantValue(const Constant *C) { // Compute the index GenericValue Result = getConstantValue(Op0); SmallVector Indices(CE->op_begin()+1, CE->op_end()); - uint64_t Offset = - TD->getIndexedOffset(Op0->getType(), &Indices[0], Indices.size()); + uint64_t Offset = TD->getIndexedOffset(Op0->getType(), Indices); char* tmp = (char*) Result.PointerVal; Result = PTOGV(tmp + Offset); @@ -651,7 +649,7 @@ GenericValue ExecutionEngine::getConstantValue(const Constant *C) { } case Instruction::BitCast: { GenericValue GV = getConstantValue(Op0); - const Type* DestTy = CE->getType(); + Type* DestTy = CE->getType(); switch (Op0->getType()->getTypeID()) { default: llvm_unreachable("Invalid bitcast operand"); case Type::IntegerTyID: @@ -847,7 +845,7 @@ static void StoreIntToMemory(const APInt &IntVal, uint8_t *Dst, } void ExecutionEngine::StoreValueToMemory(const GenericValue &Val, - GenericValue *Ptr, const Type *Ty) { + GenericValue *Ptr, Type *Ty) { const unsigned StoreBytes = getTargetData()->getTypeStoreSize(Ty); switch (Ty->getTypeID()) { @@ -909,7 +907,7 @@ static void LoadIntFromMemory(APInt &IntVal, uint8_t *Src, unsigned LoadBytes) { /// void ExecutionEngine::LoadValueFromMemory(GenericValue &Result, GenericValue *Ptr, - const Type *Ty) { + Type *Ty) { const unsigned LoadBytes = getTargetData()->getTypeStoreSize(Ty); switch (Ty->getTypeID()) { @@ -932,7 +930,7 @@ void ExecutionEngine::LoadValueFromMemory(GenericValue &Result, // FIXME: Will not trap if loading a signaling NaN. uint64_t y[2]; memcpy(y, Ptr, 10); - Result.IntVal = APInt(80, 2, y); + Result.IntVal = APInt(80, y); break; } default: @@ -986,7 +984,7 @@ void ExecutionEngine::emitGlobals() { // Loop over all of the global variables in the program, allocating the memory // to hold them. If there is more than one module, do a prepass over globals // to figure out how the different modules should link together. - std::map, + std::map, const GlobalValue*> LinkedGlobalsMap; if (Modules.size() != 1) { @@ -1101,7 +1099,7 @@ void ExecutionEngine::EmitGlobalVariable(const GlobalVariable *GV) { if (!GV->isThreadLocal()) InitializeMemory(GV->getInitializer(), GA); - const Type *ElTy = GV->getType()->getElementType(); + Type *ElTy = GV->getType()->getElementType(); size_t GVSize = (size_t)getTargetData()->getTypeAllocSize(ElTy); NumInitBytes += (unsigned)GVSize; ++NumGlobals; diff --git a/contrib/llvm/lib/ExecutionEngine/Interpreter/Execution.cpp b/contrib/llvm/lib/ExecutionEngine/Interpreter/Execution.cpp index 498063bf6..27917da07 100644 --- a/contrib/llvm/lib/ExecutionEngine/Interpreter/Execution.cpp +++ b/contrib/llvm/lib/ExecutionEngine/Interpreter/Execution.cpp @@ -51,7 +51,7 @@ static void SetValue(Value *V, GenericValue Val, ExecutionContext &SF) { break static void executeFAddInst(GenericValue &Dest, GenericValue Src1, - GenericValue Src2, const Type *Ty) { + GenericValue Src2, Type *Ty) { switch (Ty->getTypeID()) { IMPLEMENT_BINARY_OPERATOR(+, Float); IMPLEMENT_BINARY_OPERATOR(+, Double); @@ -62,7 +62,7 @@ static void executeFAddInst(GenericValue &Dest, GenericValue Src1, } static void executeFSubInst(GenericValue &Dest, GenericValue Src1, - GenericValue Src2, const Type *Ty) { + GenericValue Src2, Type *Ty) { switch (Ty->getTypeID()) { IMPLEMENT_BINARY_OPERATOR(-, Float); IMPLEMENT_BINARY_OPERATOR(-, Double); @@ -73,7 +73,7 @@ static void executeFSubInst(GenericValue &Dest, GenericValue Src1, } static void executeFMulInst(GenericValue &Dest, GenericValue Src1, - GenericValue Src2, const Type *Ty) { + GenericValue Src2, Type *Ty) { switch (Ty->getTypeID()) { IMPLEMENT_BINARY_OPERATOR(*, Float); IMPLEMENT_BINARY_OPERATOR(*, Double); @@ -84,7 +84,7 @@ static void executeFMulInst(GenericValue &Dest, GenericValue Src1, } static void executeFDivInst(GenericValue &Dest, GenericValue Src1, - GenericValue Src2, const Type *Ty) { + GenericValue Src2, Type *Ty) { switch (Ty->getTypeID()) { IMPLEMENT_BINARY_OPERATOR(/, Float); IMPLEMENT_BINARY_OPERATOR(/, Double); @@ -95,7 +95,7 @@ static void executeFDivInst(GenericValue &Dest, GenericValue Src1, } static void executeFRemInst(GenericValue &Dest, GenericValue Src1, - GenericValue Src2, const Type *Ty) { + GenericValue Src2, Type *Ty) { switch (Ty->getTypeID()) { case Type::FloatTyID: Dest.FloatVal = fmod(Src1.FloatVal, Src2.FloatVal); @@ -125,7 +125,7 @@ static void executeFRemInst(GenericValue &Dest, GenericValue Src1, break; static GenericValue executeICMP_EQ(GenericValue Src1, GenericValue Src2, - const Type *Ty) { + Type *Ty) { GenericValue Dest; switch (Ty->getTypeID()) { IMPLEMENT_INTEGER_ICMP(eq,Ty); @@ -138,7 +138,7 @@ static GenericValue executeICMP_EQ(GenericValue Src1, GenericValue Src2, } static GenericValue executeICMP_NE(GenericValue Src1, GenericValue Src2, - const Type *Ty) { + Type *Ty) { GenericValue Dest; switch (Ty->getTypeID()) { IMPLEMENT_INTEGER_ICMP(ne,Ty); @@ -151,7 +151,7 @@ static GenericValue executeICMP_NE(GenericValue Src1, GenericValue Src2, } static GenericValue executeICMP_ULT(GenericValue Src1, GenericValue Src2, - const Type *Ty) { + Type *Ty) { GenericValue Dest; switch (Ty->getTypeID()) { IMPLEMENT_INTEGER_ICMP(ult,Ty); @@ -164,7 +164,7 @@ static GenericValue executeICMP_ULT(GenericValue Src1, GenericValue Src2, } static GenericValue executeICMP_SLT(GenericValue Src1, GenericValue Src2, - const Type *Ty) { + Type *Ty) { GenericValue Dest; switch (Ty->getTypeID()) { IMPLEMENT_INTEGER_ICMP(slt,Ty); @@ -177,7 +177,7 @@ static GenericValue executeICMP_SLT(GenericValue Src1, GenericValue Src2, } static GenericValue executeICMP_UGT(GenericValue Src1, GenericValue Src2, - const Type *Ty) { + Type *Ty) { GenericValue Dest; switch (Ty->getTypeID()) { IMPLEMENT_INTEGER_ICMP(ugt,Ty); @@ -190,7 +190,7 @@ static GenericValue executeICMP_UGT(GenericValue Src1, GenericValue Src2, } static GenericValue executeICMP_SGT(GenericValue Src1, GenericValue Src2, - const Type *Ty) { + Type *Ty) { GenericValue Dest; switch (Ty->getTypeID()) { IMPLEMENT_INTEGER_ICMP(sgt,Ty); @@ -203,7 +203,7 @@ static GenericValue executeICMP_SGT(GenericValue Src1, GenericValue Src2, } static GenericValue executeICMP_ULE(GenericValue Src1, GenericValue Src2, - const Type *Ty) { + Type *Ty) { GenericValue Dest; switch (Ty->getTypeID()) { IMPLEMENT_INTEGER_ICMP(ule,Ty); @@ -216,7 +216,7 @@ static GenericValue executeICMP_ULE(GenericValue Src1, GenericValue Src2, } static GenericValue executeICMP_SLE(GenericValue Src1, GenericValue Src2, - const Type *Ty) { + Type *Ty) { GenericValue Dest; switch (Ty->getTypeID()) { IMPLEMENT_INTEGER_ICMP(sle,Ty); @@ -229,7 +229,7 @@ static GenericValue executeICMP_SLE(GenericValue Src1, GenericValue Src2, } static GenericValue executeICMP_UGE(GenericValue Src1, GenericValue Src2, - const Type *Ty) { + Type *Ty) { GenericValue Dest; switch (Ty->getTypeID()) { IMPLEMENT_INTEGER_ICMP(uge,Ty); @@ -242,7 +242,7 @@ static GenericValue executeICMP_UGE(GenericValue Src1, GenericValue Src2, } static GenericValue executeICMP_SGE(GenericValue Src1, GenericValue Src2, - const Type *Ty) { + Type *Ty) { GenericValue Dest; switch (Ty->getTypeID()) { IMPLEMENT_INTEGER_ICMP(sge,Ty); @@ -256,7 +256,7 @@ static GenericValue executeICMP_SGE(GenericValue Src1, GenericValue Src2, void Interpreter::visitICmpInst(ICmpInst &I) { ExecutionContext &SF = ECStack.back(); - const Type *Ty = I.getOperand(0)->getType(); + Type *Ty = I.getOperand(0)->getType(); GenericValue Src1 = getOperandValue(I.getOperand(0), SF); GenericValue Src2 = getOperandValue(I.getOperand(1), SF); GenericValue R; // Result @@ -286,7 +286,7 @@ void Interpreter::visitICmpInst(ICmpInst &I) { break static GenericValue executeFCMP_OEQ(GenericValue Src1, GenericValue Src2, - const Type *Ty) { + Type *Ty) { GenericValue Dest; switch (Ty->getTypeID()) { IMPLEMENT_FCMP(==, Float); @@ -299,7 +299,7 @@ static GenericValue executeFCMP_OEQ(GenericValue Src1, GenericValue Src2, } static GenericValue executeFCMP_ONE(GenericValue Src1, GenericValue Src2, - const Type *Ty) { + Type *Ty) { GenericValue Dest; switch (Ty->getTypeID()) { IMPLEMENT_FCMP(!=, Float); @@ -313,7 +313,7 @@ static GenericValue executeFCMP_ONE(GenericValue Src1, GenericValue Src2, } static GenericValue executeFCMP_OLE(GenericValue Src1, GenericValue Src2, - const Type *Ty) { + Type *Ty) { GenericValue Dest; switch (Ty->getTypeID()) { IMPLEMENT_FCMP(<=, Float); @@ -326,7 +326,7 @@ static GenericValue executeFCMP_OLE(GenericValue Src1, GenericValue Src2, } static GenericValue executeFCMP_OGE(GenericValue Src1, GenericValue Src2, - const Type *Ty) { + Type *Ty) { GenericValue Dest; switch (Ty->getTypeID()) { IMPLEMENT_FCMP(>=, Float); @@ -339,7 +339,7 @@ static GenericValue executeFCMP_OGE(GenericValue Src1, GenericValue Src2, } static GenericValue executeFCMP_OLT(GenericValue Src1, GenericValue Src2, - const Type *Ty) { + Type *Ty) { GenericValue Dest; switch (Ty->getTypeID()) { IMPLEMENT_FCMP(<, Float); @@ -352,7 +352,7 @@ static GenericValue executeFCMP_OLT(GenericValue Src1, GenericValue Src2, } static GenericValue executeFCMP_OGT(GenericValue Src1, GenericValue Src2, - const Type *Ty) { + Type *Ty) { GenericValue Dest; switch (Ty->getTypeID()) { IMPLEMENT_FCMP(>, Float); @@ -377,49 +377,49 @@ static GenericValue executeFCMP_OGT(GenericValue Src1, GenericValue Src2, static GenericValue executeFCMP_UEQ(GenericValue Src1, GenericValue Src2, - const Type *Ty) { + Type *Ty) { GenericValue Dest; IMPLEMENT_UNORDERED(Ty, Src1, Src2) return executeFCMP_OEQ(Src1, Src2, Ty); } static GenericValue executeFCMP_UNE(GenericValue Src1, GenericValue Src2, - const Type *Ty) { + Type *Ty) { GenericValue Dest; IMPLEMENT_UNORDERED(Ty, Src1, Src2) return executeFCMP_ONE(Src1, Src2, Ty); } static GenericValue executeFCMP_ULE(GenericValue Src1, GenericValue Src2, - const Type *Ty) { + Type *Ty) { GenericValue Dest; IMPLEMENT_UNORDERED(Ty, Src1, Src2) return executeFCMP_OLE(Src1, Src2, Ty); } static GenericValue executeFCMP_UGE(GenericValue Src1, GenericValue Src2, - const Type *Ty) { + Type *Ty) { GenericValue Dest; IMPLEMENT_UNORDERED(Ty, Src1, Src2) return executeFCMP_OGE(Src1, Src2, Ty); } static GenericValue executeFCMP_ULT(GenericValue Src1, GenericValue Src2, - const Type *Ty) { + Type *Ty) { GenericValue Dest; IMPLEMENT_UNORDERED(Ty, Src1, Src2) return executeFCMP_OLT(Src1, Src2, Ty); } static GenericValue executeFCMP_UGT(GenericValue Src1, GenericValue Src2, - const Type *Ty) { + Type *Ty) { GenericValue Dest; IMPLEMENT_UNORDERED(Ty, Src1, Src2) return executeFCMP_OGT(Src1, Src2, Ty); } static GenericValue executeFCMP_ORD(GenericValue Src1, GenericValue Src2, - const Type *Ty) { + Type *Ty) { GenericValue Dest; if (Ty->isFloatTy()) Dest.IntVal = APInt(1,(Src1.FloatVal == Src1.FloatVal && @@ -431,7 +431,7 @@ static GenericValue executeFCMP_ORD(GenericValue Src1, GenericValue Src2, } static GenericValue executeFCMP_UNO(GenericValue Src1, GenericValue Src2, - const Type *Ty) { + Type *Ty) { GenericValue Dest; if (Ty->isFloatTy()) Dest.IntVal = APInt(1,(Src1.FloatVal != Src1.FloatVal || @@ -444,7 +444,7 @@ static GenericValue executeFCMP_UNO(GenericValue Src1, GenericValue Src2, void Interpreter::visitFCmpInst(FCmpInst &I) { ExecutionContext &SF = ECStack.back(); - const Type *Ty = I.getOperand(0)->getType(); + Type *Ty = I.getOperand(0)->getType(); GenericValue Src1 = getOperandValue(I.getOperand(0), SF); GenericValue Src2 = getOperandValue(I.getOperand(1), SF); GenericValue R; // Result @@ -475,7 +475,7 @@ void Interpreter::visitFCmpInst(FCmpInst &I) { } static GenericValue executeCmpInst(unsigned predicate, GenericValue Src1, - GenericValue Src2, const Type *Ty) { + GenericValue Src2, Type *Ty) { GenericValue Result; switch (predicate) { case ICmpInst::ICMP_EQ: return executeICMP_EQ(Src1, Src2, Ty); @@ -520,7 +520,7 @@ static GenericValue executeCmpInst(unsigned predicate, GenericValue Src1, void Interpreter::visitBinaryOperator(BinaryOperator &I) { ExecutionContext &SF = ECStack.back(); - const Type *Ty = I.getOperand(0)->getType(); + Type *Ty = I.getOperand(0)->getType(); GenericValue Src1 = getOperandValue(I.getOperand(0), SF); GenericValue Src2 = getOperandValue(I.getOperand(1), SF); GenericValue R; // Result @@ -585,7 +585,7 @@ void Interpreter::exitCalled(GenericValue GV) { /// care of switching to the normal destination BB, if we are returning /// from an invoke. /// -void Interpreter::popStackAndReturnValueToCaller(const Type *RetTy, +void Interpreter::popStackAndReturnValueToCaller(Type *RetTy, GenericValue Result) { // Pop the current stack frame. ECStack.pop_back(); @@ -613,7 +613,7 @@ void Interpreter::popStackAndReturnValueToCaller(const Type *RetTy, void Interpreter::visitReturnInst(ReturnInst &I) { ExecutionContext &SF = ECStack.back(); - const Type *RetTy = Type::getVoidTy(I.getContext()); + Type *RetTy = Type::getVoidTy(I.getContext()); GenericValue Result; // Save away the return value... (if we are not 'ret void') @@ -662,18 +662,21 @@ void Interpreter::visitBranchInst(BranchInst &I) { void Interpreter::visitSwitchInst(SwitchInst &I) { ExecutionContext &SF = ECStack.back(); - GenericValue CondVal = getOperandValue(I.getOperand(0), SF); - const Type *ElTy = I.getOperand(0)->getType(); + Value* Cond = I.getCondition(); + Type *ElTy = Cond->getType(); + GenericValue CondVal = getOperandValue(Cond, SF); // Check to see if any of the cases match... BasicBlock *Dest = 0; - for (unsigned i = 2, e = I.getNumOperands(); i != e; i += 2) - if (executeICMP_EQ(CondVal, getOperandValue(I.getOperand(i), SF), ElTy) - .IntVal != 0) { - Dest = cast(I.getOperand(i+1)); + unsigned NumCases = I.getNumCases(); + // Skip the first item since that's the default case. + for (unsigned i = 1; i < NumCases; ++i) { + GenericValue CaseVal = getOperandValue(I.getCaseValue(i), SF); + if (executeICMP_EQ(CondVal, CaseVal, ElTy).IntVal != 0) { + Dest = cast(I.getSuccessor(i)); break; } - + } if (!Dest) Dest = I.getDefaultDest(); // No cases matched: use default SwitchToNewBasicBlock(Dest, SF); } @@ -730,7 +733,7 @@ void Interpreter::SwitchToNewBasicBlock(BasicBlock *Dest, ExecutionContext &SF){ void Interpreter::visitAllocaInst(AllocaInst &I) { ExecutionContext &SF = ECStack.back(); - const Type *Ty = I.getType()->getElementType(); // Type to be allocated + Type *Ty = I.getType()->getElementType(); // Type to be allocated // Get the number of elements being allocated by the array... unsigned NumElements = @@ -767,7 +770,7 @@ GenericValue Interpreter::executeGEPOperation(Value *Ptr, gep_type_iterator I, uint64_t Total = 0; for (; I != E; ++I) { - if (const StructType *STy = dyn_cast(*I)) { + if (StructType *STy = dyn_cast(*I)) { const StructLayout *SLO = TD.getStructLayout(STy); const ConstantInt *CPU = cast(I.getOperand()); @@ -775,7 +778,7 @@ GenericValue Interpreter::executeGEPOperation(Value *Ptr, gep_type_iterator I, Total += SLO->getElementOffset(Index); } else { - const SequentialType *ST = cast(*I); + SequentialType *ST = cast(*I); // Get the index number for the array... which must be long type... GenericValue IdxGV = getOperandValue(I.getOperand(), SF); @@ -929,34 +932,34 @@ void Interpreter::visitAShr(BinaryOperator &I) { SetValue(&I, Dest, SF); } -GenericValue Interpreter::executeTruncInst(Value *SrcVal, const Type *DstTy, +GenericValue Interpreter::executeTruncInst(Value *SrcVal, Type *DstTy, ExecutionContext &SF) { GenericValue Dest, Src = getOperandValue(SrcVal, SF); - const IntegerType *DITy = cast(DstTy); + IntegerType *DITy = cast(DstTy); unsigned DBitWidth = DITy->getBitWidth(); Dest.IntVal = Src.IntVal.trunc(DBitWidth); return Dest; } -GenericValue Interpreter::executeSExtInst(Value *SrcVal, const Type *DstTy, +GenericValue Interpreter::executeSExtInst(Value *SrcVal, Type *DstTy, ExecutionContext &SF) { GenericValue Dest, Src = getOperandValue(SrcVal, SF); - const IntegerType *DITy = cast(DstTy); + IntegerType *DITy = cast(DstTy); unsigned DBitWidth = DITy->getBitWidth(); Dest.IntVal = Src.IntVal.sext(DBitWidth); return Dest; } -GenericValue Interpreter::executeZExtInst(Value *SrcVal, const Type *DstTy, +GenericValue Interpreter::executeZExtInst(Value *SrcVal, Type *DstTy, ExecutionContext &SF) { GenericValue Dest, Src = getOperandValue(SrcVal, SF); - const IntegerType *DITy = cast(DstTy); + IntegerType *DITy = cast(DstTy); unsigned DBitWidth = DITy->getBitWidth(); Dest.IntVal = Src.IntVal.zext(DBitWidth); return Dest; } -GenericValue Interpreter::executeFPTruncInst(Value *SrcVal, const Type *DstTy, +GenericValue Interpreter::executeFPTruncInst(Value *SrcVal, Type *DstTy, ExecutionContext &SF) { GenericValue Dest, Src = getOperandValue(SrcVal, SF); assert(SrcVal->getType()->isDoubleTy() && DstTy->isFloatTy() && @@ -965,7 +968,7 @@ GenericValue Interpreter::executeFPTruncInst(Value *SrcVal, const Type *DstTy, return Dest; } -GenericValue Interpreter::executeFPExtInst(Value *SrcVal, const Type *DstTy, +GenericValue Interpreter::executeFPExtInst(Value *SrcVal, Type *DstTy, ExecutionContext &SF) { GenericValue Dest, Src = getOperandValue(SrcVal, SF); assert(SrcVal->getType()->isFloatTy() && DstTy->isDoubleTy() && @@ -974,9 +977,9 @@ GenericValue Interpreter::executeFPExtInst(Value *SrcVal, const Type *DstTy, return Dest; } -GenericValue Interpreter::executeFPToUIInst(Value *SrcVal, const Type *DstTy, +GenericValue Interpreter::executeFPToUIInst(Value *SrcVal, Type *DstTy, ExecutionContext &SF) { - const Type *SrcTy = SrcVal->getType(); + Type *SrcTy = SrcVal->getType(); uint32_t DBitWidth = cast(DstTy)->getBitWidth(); GenericValue Dest, Src = getOperandValue(SrcVal, SF); assert(SrcTy->isFloatingPointTy() && "Invalid FPToUI instruction"); @@ -988,9 +991,9 @@ GenericValue Interpreter::executeFPToUIInst(Value *SrcVal, const Type *DstTy, return Dest; } -GenericValue Interpreter::executeFPToSIInst(Value *SrcVal, const Type *DstTy, +GenericValue Interpreter::executeFPToSIInst(Value *SrcVal, Type *DstTy, ExecutionContext &SF) { - const Type *SrcTy = SrcVal->getType(); + Type *SrcTy = SrcVal->getType(); uint32_t DBitWidth = cast(DstTy)->getBitWidth(); GenericValue Dest, Src = getOperandValue(SrcVal, SF); assert(SrcTy->isFloatingPointTy() && "Invalid FPToSI instruction"); @@ -1002,7 +1005,7 @@ GenericValue Interpreter::executeFPToSIInst(Value *SrcVal, const Type *DstTy, return Dest; } -GenericValue Interpreter::executeUIToFPInst(Value *SrcVal, const Type *DstTy, +GenericValue Interpreter::executeUIToFPInst(Value *SrcVal, Type *DstTy, ExecutionContext &SF) { GenericValue Dest, Src = getOperandValue(SrcVal, SF); assert(DstTy->isFloatingPointTy() && "Invalid UIToFP instruction"); @@ -1014,7 +1017,7 @@ GenericValue Interpreter::executeUIToFPInst(Value *SrcVal, const Type *DstTy, return Dest; } -GenericValue Interpreter::executeSIToFPInst(Value *SrcVal, const Type *DstTy, +GenericValue Interpreter::executeSIToFPInst(Value *SrcVal, Type *DstTy, ExecutionContext &SF) { GenericValue Dest, Src = getOperandValue(SrcVal, SF); assert(DstTy->isFloatingPointTy() && "Invalid SIToFP instruction"); @@ -1027,7 +1030,7 @@ GenericValue Interpreter::executeSIToFPInst(Value *SrcVal, const Type *DstTy, } -GenericValue Interpreter::executePtrToIntInst(Value *SrcVal, const Type *DstTy, +GenericValue Interpreter::executePtrToIntInst(Value *SrcVal, Type *DstTy, ExecutionContext &SF) { uint32_t DBitWidth = cast(DstTy)->getBitWidth(); GenericValue Dest, Src = getOperandValue(SrcVal, SF); @@ -1037,7 +1040,7 @@ GenericValue Interpreter::executePtrToIntInst(Value *SrcVal, const Type *DstTy, return Dest; } -GenericValue Interpreter::executeIntToPtrInst(Value *SrcVal, const Type *DstTy, +GenericValue Interpreter::executeIntToPtrInst(Value *SrcVal, Type *DstTy, ExecutionContext &SF) { GenericValue Dest, Src = getOperandValue(SrcVal, SF); assert(DstTy->isPointerTy() && "Invalid PtrToInt instruction"); @@ -1050,10 +1053,10 @@ GenericValue Interpreter::executeIntToPtrInst(Value *SrcVal, const Type *DstTy, return Dest; } -GenericValue Interpreter::executeBitCastInst(Value *SrcVal, const Type *DstTy, +GenericValue Interpreter::executeBitCastInst(Value *SrcVal, Type *DstTy, ExecutionContext &SF) { - const Type *SrcTy = SrcVal->getType(); + Type *SrcTy = SrcVal->getType(); GenericValue Dest, Src = getOperandValue(SrcVal, SF); if (DstTy->isPointerTy()) { assert(SrcTy->isPointerTy() && "Invalid BitCast"); @@ -1155,7 +1158,7 @@ void Interpreter::visitVAArgInst(VAArgInst &I) { GenericValue Dest; GenericValue Src = ECStack[VAList.UIntPairVal.first] .VarArgs[VAList.UIntPairVal.second]; - const Type *Ty = I.getType(); + Type *Ty = I.getType(); switch (Ty->getTypeID()) { case Type::IntegerTyID: Dest.IntVal = Src.IntVal; IMPLEMENT_VAARG(Pointer); @@ -1222,7 +1225,7 @@ GenericValue Interpreter::getConstantExprValue (ConstantExpr *CE, GenericValue Op0 = getOperandValue(CE->getOperand(0), SF); GenericValue Op1 = getOperandValue(CE->getOperand(1), SF); GenericValue Dest; - const Type * Ty = CE->getOperand(0)->getType(); + Type * Ty = CE->getOperand(0)->getType(); switch (CE->getOpcode()) { case Instruction::Add: Dest.IntVal = Op0.IntVal + Op1.IntVal; break; case Instruction::Sub: Dest.IntVal = Op0.IntVal - Op1.IntVal; break; diff --git a/contrib/llvm/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp b/contrib/llvm/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp index f7e2a4df9..055875c94 100644 --- a/contrib/llvm/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp +++ b/contrib/llvm/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp @@ -48,7 +48,7 @@ using namespace llvm; static ManagedStatic FunctionsLock; -typedef GenericValue (*ExFunc)(const FunctionType *, +typedef GenericValue (*ExFunc)(FunctionType *, const std::vector &); static ManagedStatic > ExportedFunctions; static std::map FuncNames; @@ -60,7 +60,7 @@ static ManagedStatic > RawFunctions; static Interpreter *TheInterpreter; -static char getTypeID(const Type *Ty) { +static char getTypeID(Type *Ty) { switch (Ty->getTypeID()) { case Type::VoidTyID: return 'V'; case Type::IntegerTyID: @@ -91,7 +91,7 @@ static ExFunc lookupFunction(const Function *F) { // Function not found, look it up... start by figuring out what the // composite function name should be. std::string ExtName = "lle_"; - const FunctionType *FT = F->getFunctionType(); + FunctionType *FT = F->getFunctionType(); for (unsigned i = 0, e = FT->getNumContainedTypes(); i != e; ++i) ExtName += getTypeID(FT->getContainedType(i)); ExtName + "_" + F->getNameStr(); @@ -109,7 +109,7 @@ static ExFunc lookupFunction(const Function *F) { } #ifdef USE_LIBFFI -static ffi_type *ffiTypeFor(const Type *Ty) { +static ffi_type *ffiTypeFor(Type *Ty) { switch (Ty->getTypeID()) { case Type::VoidTyID: return &ffi_type_void; case Type::IntegerTyID: @@ -129,7 +129,7 @@ static ffi_type *ffiTypeFor(const Type *Ty) { return NULL; } -static void *ffiValueFor(const Type *Ty, const GenericValue &AV, +static void *ffiValueFor(Type *Ty, const GenericValue &AV, void *ArgDataPtr) { switch (Ty->getTypeID()) { case Type::IntegerTyID: @@ -181,7 +181,7 @@ static bool ffiInvoke(RawFunc Fn, Function *F, const std::vector &ArgVals, const TargetData *TD, GenericValue &Result) { ffi_cif cif; - const FunctionType *FTy = F->getFunctionType(); + FunctionType *FTy = F->getFunctionType(); const unsigned NumArgs = F->arg_size(); // TODO: We don't have type information about the remaining arguments, because @@ -197,7 +197,7 @@ static bool ffiInvoke(RawFunc Fn, Function *F, for (Function::const_arg_iterator A = F->arg_begin(), E = F->arg_end(); A != E; ++A) { const unsigned ArgNo = A->getArgNo(); - const Type *ArgTy = FTy->getParamType(ArgNo); + Type *ArgTy = FTy->getParamType(ArgNo); args[ArgNo] = ffiTypeFor(ArgTy); ArgBytes += TD->getTypeStoreSize(ArgTy); } @@ -209,12 +209,12 @@ static bool ffiInvoke(RawFunc Fn, Function *F, for (Function::const_arg_iterator A = F->arg_begin(), E = F->arg_end(); A != E; ++A) { const unsigned ArgNo = A->getArgNo(); - const Type *ArgTy = FTy->getParamType(ArgNo); + Type *ArgTy = FTy->getParamType(ArgNo); values[ArgNo] = ffiValueFor(ArgTy, ArgVals[ArgNo], ArgDataPtr); ArgDataPtr += TD->getTypeStoreSize(ArgTy); } - const Type *RetTy = FTy->getReturnType(); + Type *RetTy = FTy->getReturnType(); ffi_type *rtype = ffiTypeFor(RetTy); if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, NumArgs, rtype, &args[0]) == FFI_OK) { @@ -304,7 +304,7 @@ GenericValue Interpreter::callExternalFunction(Function *F, extern "C" { // Don't add C++ manglings to llvm mangling :) // void atexit(Function*) -GenericValue lle_X_atexit(const FunctionType *FT, +GenericValue lle_X_atexit(FunctionType *FT, const std::vector &Args) { assert(Args.size() == 1); TheInterpreter->addAtExitHandler((Function*)GVTOP(Args[0])); @@ -314,14 +314,14 @@ GenericValue lle_X_atexit(const FunctionType *FT, } // void exit(int) -GenericValue lle_X_exit(const FunctionType *FT, +GenericValue lle_X_exit(FunctionType *FT, const std::vector &Args) { TheInterpreter->exitCalled(Args[0]); return GenericValue(); } // void abort(void) -GenericValue lle_X_abort(const FunctionType *FT, +GenericValue lle_X_abort(FunctionType *FT, const std::vector &Args) { //FIXME: should we report or raise here? //report_fatal_error("Interpreted program raised SIGABRT"); @@ -331,7 +331,7 @@ GenericValue lle_X_abort(const FunctionType *FT, // int sprintf(char *, const char *, ...) - a very rough implementation to make // output useful. -GenericValue lle_X_sprintf(const FunctionType *FT, +GenericValue lle_X_sprintf(FunctionType *FT, const std::vector &Args) { char *OutputBuffer = (char *)GVTOP(Args[0]); const char *FmtStr = (const char *)GVTOP(Args[1]); @@ -413,7 +413,7 @@ GenericValue lle_X_sprintf(const FunctionType *FT, // int printf(const char *, ...) - a very rough implementation to make output // useful. -GenericValue lle_X_printf(const FunctionType *FT, +GenericValue lle_X_printf(FunctionType *FT, const std::vector &Args) { char Buffer[10000]; std::vector NewArgs; @@ -425,7 +425,7 @@ GenericValue lle_X_printf(const FunctionType *FT, } // int sscanf(const char *format, ...); -GenericValue lle_X_sscanf(const FunctionType *FT, +GenericValue lle_X_sscanf(FunctionType *FT, const std::vector &args) { assert(args.size() < 10 && "Only handle up to 10 args to sscanf right now!"); @@ -440,7 +440,7 @@ GenericValue lle_X_sscanf(const FunctionType *FT, } // int scanf(const char *format, ...); -GenericValue lle_X_scanf(const FunctionType *FT, +GenericValue lle_X_scanf(FunctionType *FT, const std::vector &args) { assert(args.size() < 10 && "Only handle up to 10 args to scanf right now!"); @@ -456,7 +456,7 @@ GenericValue lle_X_scanf(const FunctionType *FT, // int fprintf(FILE *, const char *, ...) - a very rough implementation to make // output useful. -GenericValue lle_X_fprintf(const FunctionType *FT, +GenericValue lle_X_fprintf(FunctionType *FT, const std::vector &Args) { assert(Args.size() >= 2); char Buffer[10000]; diff --git a/contrib/llvm/lib/ExecutionEngine/Interpreter/Interpreter.h b/contrib/llvm/lib/ExecutionEngine/Interpreter/Interpreter.h index bfebe3deb..ee2b4596f 100644 --- a/contrib/llvm/lib/ExecutionEngine/Interpreter/Interpreter.h +++ b/contrib/llvm/lib/ExecutionEngine/Interpreter/Interpreter.h @@ -174,7 +174,7 @@ public: void visitVAArgInst(VAArgInst &I); void visitInstruction(Instruction &I) { - errs() << I; + errs() << I << "\n"; llvm_unreachable("Instruction not interpretable yet!"); } @@ -207,33 +207,33 @@ private: // Helper functions void initializeExternalFunctions(); GenericValue getConstantExprValue(ConstantExpr *CE, ExecutionContext &SF); GenericValue getOperandValue(Value *V, ExecutionContext &SF); - GenericValue executeTruncInst(Value *SrcVal, const Type *DstTy, + GenericValue executeTruncInst(Value *SrcVal, Type *DstTy, ExecutionContext &SF); - GenericValue executeSExtInst(Value *SrcVal, const Type *DstTy, + GenericValue executeSExtInst(Value *SrcVal, Type *DstTy, ExecutionContext &SF); - GenericValue executeZExtInst(Value *SrcVal, const Type *DstTy, + GenericValue executeZExtInst(Value *SrcVal, Type *DstTy, ExecutionContext &SF); - GenericValue executeFPTruncInst(Value *SrcVal, const Type *DstTy, + GenericValue executeFPTruncInst(Value *SrcVal, Type *DstTy, ExecutionContext &SF); - GenericValue executeFPExtInst(Value *SrcVal, const Type *DstTy, + GenericValue executeFPExtInst(Value *SrcVal, Type *DstTy, ExecutionContext &SF); - GenericValue executeFPToUIInst(Value *SrcVal, const Type *DstTy, + GenericValue executeFPToUIInst(Value *SrcVal, Type *DstTy, ExecutionContext &SF); - GenericValue executeFPToSIInst(Value *SrcVal, const Type *DstTy, + GenericValue executeFPToSIInst(Value *SrcVal, Type *DstTy, ExecutionContext &SF); - GenericValue executeUIToFPInst(Value *SrcVal, const Type *DstTy, + GenericValue executeUIToFPInst(Value *SrcVal, Type *DstTy, ExecutionContext &SF); - GenericValue executeSIToFPInst(Value *SrcVal, const Type *DstTy, + GenericValue executeSIToFPInst(Value *SrcVal, Type *DstTy, ExecutionContext &SF); - GenericValue executePtrToIntInst(Value *SrcVal, const Type *DstTy, + GenericValue executePtrToIntInst(Value *SrcVal, Type *DstTy, ExecutionContext &SF); - GenericValue executeIntToPtrInst(Value *SrcVal, const Type *DstTy, + GenericValue executeIntToPtrInst(Value *SrcVal, Type *DstTy, ExecutionContext &SF); - GenericValue executeBitCastInst(Value *SrcVal, const Type *DstTy, + GenericValue executeBitCastInst(Value *SrcVal, Type *DstTy, ExecutionContext &SF); GenericValue executeCastOperation(Instruction::CastOps opcode, Value *SrcVal, - const Type *Ty, ExecutionContext &SF); - void popStackAndReturnValueToCaller(const Type *RetTy, GenericValue Result); + Type *Ty, ExecutionContext &SF); + void popStackAndReturnValueToCaller(Type *RetTy, GenericValue Result); }; diff --git a/contrib/llvm/lib/ExecutionEngine/JIT/Intercept.cpp b/contrib/llvm/lib/ExecutionEngine/JIT/Intercept.cpp index fa8bee460..2251a8e6b 100644 --- a/contrib/llvm/lib/ExecutionEngine/JIT/Intercept.cpp +++ b/contrib/llvm/lib/ExecutionEngine/JIT/Intercept.cpp @@ -52,6 +52,7 @@ static void runAtExitHandlers() { #include #endif #include +#include /* stat functions are redirecting to __xstat with a version number. On x86-64 * linking with libc_nonshared.a and -Wl,--export-dynamic doesn't make 'stat' * available as an exported symbol, so we have to add it explicitly. diff --git a/contrib/llvm/lib/ExecutionEngine/JIT/JIT.cpp b/contrib/llvm/lib/ExecutionEngine/JIT/JIT.cpp index 445d2d067..d77300906 100644 --- a/contrib/llvm/lib/ExecutionEngine/JIT/JIT.cpp +++ b/contrib/llvm/lib/ExecutionEngine/JIT/JIT.cpp @@ -390,8 +390,8 @@ GenericValue JIT::runFunction(Function *F, void *FPtr = getPointerToFunction(F); assert(FPtr && "Pointer to fn's code was null after getPointerToFunction"); - const FunctionType *FTy = F->getFunctionType(); - const Type *RetTy = FTy->getReturnType(); + FunctionType *FTy = F->getFunctionType(); + Type *RetTy = FTy->getReturnType(); assert((FTy->getNumParams() == ArgValues.size() || (FTy->isVarArg() && FTy->getNumParams() <= ArgValues.size())) && @@ -500,7 +500,7 @@ GenericValue JIT::runFunction(Function *F, SmallVector Args; for (unsigned i = 0, e = ArgValues.size(); i != e; ++i) { Constant *C = 0; - const Type *ArgTy = FTy->getParamType(i); + Type *ArgTy = FTy->getParamType(i); const GenericValue &AV = ArgValues[i]; switch (ArgTy->getTypeID()) { default: llvm_unreachable("Unknown argument type for function call!"); @@ -788,7 +788,7 @@ char* JIT::getMemoryForGV(const GlobalVariable* GV) { // be allocated into the same buffer, but in general globals are allocated // through the memory manager which puts them near the code but not in the // same buffer. - const Type *GlobalType = GV->getType()->getElementType(); + Type *GlobalType = GV->getType()->getElementType(); size_t S = getTargetData()->getTypeAllocSize(GlobalType); size_t A = getTargetData()->getPreferredAlignment(GV); if (GV->isThreadLocal()) { diff --git a/contrib/llvm/lib/ExecutionEngine/JIT/JIT.h b/contrib/llvm/lib/ExecutionEngine/JIT/JIT.h index b879fc36e..92dcb0e99 100644 --- a/contrib/llvm/lib/ExecutionEngine/JIT/JIT.h +++ b/contrib/llvm/lib/ExecutionEngine/JIT/JIT.h @@ -100,9 +100,10 @@ public: CodeGenOpt::Level OptLevel = CodeGenOpt::Default, bool GVsWithCode = true, - CodeModel::Model CMM = CodeModel::Default) { + Reloc::Model RM = Reloc::Default, + CodeModel::Model CMM = CodeModel::JITDefault) { return ExecutionEngine::createJIT(M, Err, JMM, OptLevel, GVsWithCode, - CMM); + RM, CMM); } virtual void addModule(Module *M); diff --git a/contrib/llvm/lib/ExecutionEngine/JIT/JITDwarfEmitter.cpp b/contrib/llvm/lib/ExecutionEngine/JIT/JITDwarfEmitter.cpp index ddb0d5478..8f84ac7b4 100644 --- a/contrib/llvm/lib/ExecutionEngine/JIT/JITDwarfEmitter.cpp +++ b/contrib/llvm/lib/ExecutionEngine/JIT/JITDwarfEmitter.cpp @@ -18,12 +18,12 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/CodeGen/JITCodeEmitter.h" #include "llvm/CodeGen/MachineFunction.h" -#include "llvm/CodeGen/MachineLocation.h" #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/ExecutionEngine/JITMemoryManager.h" -#include "llvm/Support/ErrorHandling.h" +#include "llvm/MC/MachineLocation.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCSymbol.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetInstrInfo.h" #include "llvm/Target/TargetFrameLowering.h" @@ -45,7 +45,7 @@ unsigned char* JITDwarfEmitter::EmitDwarfTable(MachineFunction& F, TD = TM.getTargetData(); stackGrowthDirection = TM.getFrameLowering()->getStackGrowthDirection(); RI = TM.getRegisterInfo(); - TFI = TM.getFrameLowering(); + MAI = TM.getMCAsmInfo(); JCE = &jce; unsigned char* ExceptionTable = EmitExceptionTable(&F, StartFunction, @@ -523,9 +523,7 @@ JITDwarfEmitter::EmitCommonEHFrame(const Function* Personality) const { JCE->emitULEB128Bytes(dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4); } - std::vector Moves; - TFI->getInitialFrameState(Moves); - EmitFrameMoves(0, Moves); + EmitFrameMoves(0, MAI->getInitialFrameState()); JCE->emitAlignmentWithFill(PointerSize, dwarf::DW_CFA_nop); diff --git a/contrib/llvm/lib/ExecutionEngine/JIT/JITDwarfEmitter.h b/contrib/llvm/lib/ExecutionEngine/JIT/JITDwarfEmitter.h index e1d00454d..8dc99abc4 100644 --- a/contrib/llvm/lib/ExecutionEngine/JIT/JITDwarfEmitter.h +++ b/contrib/llvm/lib/ExecutionEngine/JIT/JITDwarfEmitter.h @@ -22,8 +22,8 @@ class JITCodeEmitter; class MachineFunction; class MachineModuleInfo; class MachineMove; +class MCAsmInfo; class TargetData; -class TargetFrameLowering; class TargetMachine; class TargetRegisterInfo; @@ -31,7 +31,7 @@ class JITDwarfEmitter { const TargetData* TD; JITCodeEmitter* JCE; const TargetRegisterInfo* RI; - const TargetFrameLowering *TFI; + const MCAsmInfo *MAI; MachineModuleInfo* MMI; JIT& Jit; bool stackGrowthDirection; diff --git a/contrib/llvm/lib/ExecutionEngine/JIT/JITEmitter.cpp b/contrib/llvm/lib/ExecutionEngine/JIT/JITEmitter.cpp index d046b8aea..24020ee6d 100644 --- a/contrib/llvm/lib/ExecutionEngine/JIT/JITEmitter.cpp +++ b/contrib/llvm/lib/ExecutionEngine/JIT/JITEmitter.cpp @@ -668,6 +668,7 @@ void *JITResolver::JITCompilerFn(void *Stub) { DEBUG(dbgs() << "JIT: Lazily resolving function '" << F->getName() << "' In stub ptr = " << Stub << " actual ptr = " << ActualPtr << "\n"); + (void)ActualPtr; Result = JR->TheJIT->getPointerToFunction(F); } @@ -770,7 +771,7 @@ static unsigned GetConstantPoolSizeInBytes(MachineConstantPool *MCP, MachineConstantPoolEntry CPE = Constants[i]; unsigned AlignMask = CPE.getAlignment() - 1; Size = (Size + AlignMask) & ~AlignMask; - const Type *Ty = CPE.getType(); + Type *Ty = CPE.getType(); Size += TD->getTypeAllocSize(Ty); } return Size; @@ -1098,7 +1099,7 @@ void JITEmitter::emitConstantPool(MachineConstantPool *MCP) { DEBUG(dbgs() << "JIT: CP" << i << " at [0x"; dbgs().write_hex(CAddr) << "]\n"); - const Type *Ty = CPE.Val.ConstVal->getType(); + Type *Ty = CPE.Val.ConstVal->getType(); Offset += TheJIT->getTargetData()->getTypeAllocSize(Ty); } } diff --git a/contrib/llvm/lib/ExecutionEngine/MCJIT/CMakeLists.txt b/contrib/llvm/lib/ExecutionEngine/MCJIT/CMakeLists.txt deleted file mode 100644 index f7ed176fe..000000000 --- a/contrib/llvm/lib/ExecutionEngine/MCJIT/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -add_llvm_library(LLVMMCJIT - MCJIT.cpp - TargetSelect.cpp - ) diff --git a/contrib/llvm/lib/ExecutionEngine/MCJIT/Intercept.cpp b/contrib/llvm/lib/ExecutionEngine/MCJIT/Intercept.cpp index e431c848d..f83f4282e 100644 --- a/contrib/llvm/lib/ExecutionEngine/MCJIT/Intercept.cpp +++ b/contrib/llvm/lib/ExecutionEngine/MCJIT/Intercept.cpp @@ -52,6 +52,7 @@ static void runAtExitHandlers() { #include #endif #include +#include /* stat functions are redirecting to __xstat with a version number. On x86-64 * linking with libc_nonshared.a and -Wl,--export-dynamic doesn't make 'stat' * available as an exported symbol, so we have to add it explicitly. diff --git a/contrib/llvm/lib/ExecutionEngine/MCJIT/MCJIT.cpp b/contrib/llvm/lib/ExecutionEngine/MCJIT/MCJIT.cpp index 4475f4d5c..7c8a740dc 100644 --- a/contrib/llvm/lib/ExecutionEngine/MCJIT/MCJIT.cpp +++ b/contrib/llvm/lib/ExecutionEngine/MCJIT/MCJIT.cpp @@ -59,6 +59,7 @@ MCJIT::MCJIT(Module *m, TargetMachine *tm, TargetJITInfo &tji, bool AllocateGVsWithCode) : ExecutionEngine(m), TM(tm), MemMgr(MM), M(m), OS(Buffer), Dyld(MM) { + setTargetData(TM->getTargetData()); PM.add(new TargetData(*TM->getTargetData())); // Turn the machine code intermediate representation into bytes in memory @@ -124,8 +125,8 @@ GenericValue MCJIT::runFunction(Function *F, void *FPtr = getPointerToFunction(F); assert(FPtr && "Pointer to fn's code was null after getPointerToFunction"); - const FunctionType *FTy = F->getFunctionType(); - const Type *RetTy = FTy->getReturnType(); + FunctionType *FTy = F->getFunctionType(); + Type *RetTy = FTy->getReturnType(); assert((FTy->getNumParams() == ArgValues.size() || (FTy->isVarArg() && FTy->getNumParams() <= ArgValues.size())) && @@ -216,6 +217,6 @@ GenericValue MCJIT::runFunction(Function *F, } } - assert("Full-featured argument passing not supported yet!"); + assert(0 && "Full-featured argument passing not supported yet!"); return GenericValue(); } diff --git a/contrib/llvm/lib/ExecutionEngine/MCJIT/Makefile b/contrib/llvm/lib/ExecutionEngine/MCJIT/Makefile deleted file mode 100644 index 967efbc0e..000000000 --- a/contrib/llvm/lib/ExecutionEngine/MCJIT/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -##===- lib/ExecutionEngine/MCJIT/Makefile ------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../.. -LIBRARYNAME = LLVMMCJIT - -include $(LEVEL)/Makefile.common diff --git a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/CMakeLists.txt b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/CMakeLists.txt deleted file mode 100644 index 9e53f8757..000000000 --- a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -add_llvm_library(LLVMRuntimeDyld - RuntimeDyld.cpp - ) diff --git a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/Makefile b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/Makefile deleted file mode 100644 index 5d6f26d95..000000000 --- a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -##===- lib/ExecutionEngine/MCJIT/Makefile ------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../.. -LIBRARYNAME = LLVMRuntimeDyld - -include $(LEVEL)/Makefile.common diff --git a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h index bcdfb0480..7190a3c36 100644 --- a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h +++ b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h @@ -143,7 +143,7 @@ public: bool isCompatibleFormat(const MemoryBuffer *InputBuffer) const { return isKnownFormat(InputBuffer); - }; + } }; } // end namespace llvm diff --git a/contrib/llvm/lib/ExecutionEngine/TargetSelect.cpp b/contrib/llvm/lib/ExecutionEngine/TargetSelect.cpp index f51aff360..004b8656b 100644 --- a/contrib/llvm/lib/ExecutionEngine/TargetSelect.cpp +++ b/contrib/llvm/lib/ExecutionEngine/TargetSelect.cpp @@ -17,11 +17,11 @@ #include "llvm/Module.h" #include "llvm/ADT/Triple.h" #include "llvm/MC/SubtargetFeature.h" +#include "llvm/Target/TargetMachine.h" #include "llvm/Support/CommandLine.h" -#include "llvm/Support/raw_ostream.h" #include "llvm/Support/Host.h" -#include "llvm/Target/TargetMachine.h" -#include "llvm/Target/TargetRegistry.h" +#include "llvm/Support/TargetRegistry.h" +#include "llvm/Support/raw_ostream.h" using namespace llvm; /// selectTarget - Pick a target either via -march or by guessing the native @@ -30,6 +30,8 @@ TargetMachine *EngineBuilder::selectTarget(Module *Mod, StringRef MArch, StringRef MCPU, const SmallVectorImpl& MAttrs, + Reloc::Model RM, + CodeModel::Model CM, std::string *ErrorStr) { Triple TheTriple(Mod->getTargetTriple()); if (TheTriple.getTriple().empty()) @@ -83,8 +85,9 @@ TargetMachine *EngineBuilder::selectTarget(Module *Mod, } // Allocate a target... - TargetMachine *Target = - TheTarget->createTargetMachine(TheTriple.getTriple(), MCPU, FeaturesStr); + TargetMachine *Target = TheTarget->createTargetMachine(TheTriple.getTriple(), + MCPU, FeaturesStr, + RM, CM); assert(Target && "Could not allocate target machine!"); return Target; } diff --git a/contrib/llvm/lib/Linker/LinkModules.cpp b/contrib/llvm/lib/Linker/LinkModules.cpp index 55aa9bf18..03a962e3b 100644 --- a/contrib/llvm/lib/Linker/LinkModules.cpp +++ b/contrib/llvm/lib/Linker/LinkModules.cpp @@ -14,9 +14,12 @@ #include "llvm/Linker.h" #include "llvm/Constants.h" #include "llvm/DerivedTypes.h" +#include "llvm/Instructions.h" #include "llvm/Module.h" +#include "llvm/ADT/SmallPtrSet.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Support/Path.h" +#include "llvm/Transforms/Utils/Cloning.h" #include "llvm/Transforms/Utils/ValueMapper.h" using namespace llvm; @@ -139,7 +142,7 @@ bool TypeMapTy::areTypesIsomorphic(Type *DstTy, Type *SrcTy) { return false; } else if (StructType *DSTy = dyn_cast(DstTy)) { StructType *SSTy = cast(SrcTy); - if (DSTy->isAnonymous() != SSTy->isAnonymous() || + if (DSTy->isLiteral() != SSTy->isLiteral() || DSTy->isPacked() != SSTy->isPacked()) return false; } else if (ArrayType *DATy = dyn_cast(DstTy)) { @@ -223,7 +226,7 @@ Type *TypeMapTy::getImpl(Type *Ty) { // If this is not a named struct type, then just map all of the elements and // then rebuild the type from inside out. - if (!isa(Ty) || cast(Ty)->isAnonymous()) { + if (!isa(Ty) || cast(Ty)->isLiteral()) { // If there are no element types to map, then the type is itself. This is // true for the anonymous {} struct, things like 'float', integers, etc. if (Ty->getNumContainedTypes() == 0) @@ -261,7 +264,7 @@ Type *TypeMapTy::getImpl(Type *Ty) { cast(Ty)->getAddressSpace()); case Type::FunctionTyID: return *Entry = FunctionType::get(ElementTypes[0], - ArrayRef(ElementTypes).slice(1), + makeArrayRef(ElementTypes).slice(1), cast(Ty)->isVarArg()); case Type::StructTyID: // Note that this is only reached for anonymous structs. @@ -302,7 +305,7 @@ Type *TypeMapTy::getImpl(Type *Ty) { // Otherwise we create a new type and resolve its body later. This will be // resolved by the top level of get(). DefinitionsToResolve.push_back(STy); - return *Entry = StructType::createNamed(STy->getContext(), ""); + return *Entry = StructType::create(STy->getContext()); } @@ -333,10 +336,16 @@ namespace { std::vector AppendingVars; + unsigned Mode; // Mode to treat source module. + + // Set of items not to link in from source. + SmallPtrSet DoNotLinkFromSource; + public: std::string ErrorMsg; - ModuleLinker(Module *dstM, Module *srcM) : DstM(dstM), SrcM(srcM) { } + ModuleLinker(Module *dstM, Module *srcM, unsigned mode) + : DstM(dstM), SrcM(srcM), Mode(mode) { } bool run(); @@ -596,9 +605,9 @@ bool ModuleLinker::linkAppendingVarProto(GlobalVariable *DstGV, DstGV->replaceAllUsesWith(ConstantExpr::getBitCast(NG, DstGV->getType())); DstGV->eraseFromParent(); - // Zap the initializer in the source variable so we don't try to link it. - SrcGV->setInitializer(0); - SrcGV->setLinkage(GlobalValue::ExternalLinkage); + // Track the source variable so we don't try to link it. + DoNotLinkFromSource.insert(SrcGV); + return false; } @@ -633,11 +642,10 @@ bool ModuleLinker::linkGlobalProto(GlobalVariable *SGV) { // Make sure to remember this mapping. ValueMap[SGV] = ConstantExpr::getBitCast(DGV,TypeMap.get(SGV->getType())); - // Destroy the source global's initializer (and convert it to a prototype) - // so that we don't attempt to copy it over when processing global - // initializers. - SGV->setInitializer(0); - SGV->setLinkage(GlobalValue::ExternalLinkage); + // Track the source global so that we don't attempt to copy it over when + // processing global initializers. + DoNotLinkFromSource.insert(SGV); + return false; } } @@ -682,8 +690,10 @@ bool ModuleLinker::linkFunctionProto(Function *SF) { // Make sure to remember this mapping. ValueMap[SF] = ConstantExpr::getBitCast(DGV, TypeMap.get(SF->getType())); - // Remove the body from the source module so we don't attempt to remap it. - SF->deleteBody(); + // Track the function from the source module so we don't attempt to remap + // it. + DoNotLinkFromSource.insert(SF); + return false; } } @@ -722,8 +732,9 @@ bool ModuleLinker::linkAliasProto(GlobalAlias *SGA) { // Make sure to remember this mapping. ValueMap[SGA] = ConstantExpr::getBitCast(DGV,TypeMap.get(SGA->getType())); - // Remove the body from the source module so we don't attempt to remap it. - SGA->setAliasee(0); + // Track the alias from the source module so we don't attempt to remap it. + DoNotLinkFromSource.insert(SGA); + return false; } } @@ -779,7 +790,9 @@ void ModuleLinker::linkGlobalInits() { // Loop over all of the globals in the src module, mapping them over as we go for (Module::const_global_iterator I = SrcM->global_begin(), E = SrcM->global_end(); I != E; ++I) { - if (!I->hasInitializer()) continue; // Only process initialized GV's. + + // Only process initialized GV's or ones not already in dest. + if (!I->hasInitializer() || DoNotLinkFromSource.count(I)) continue; // Grab destination global variable. GlobalVariable *DGV = cast(ValueMap[I]); @@ -805,31 +818,42 @@ void ModuleLinker::linkFunctionBody(Function *Dst, Function *Src) { ValueMap[I] = DI; } - // Splice the body of the source function into the dest function. - Dst->getBasicBlockList().splice(Dst->end(), Src->getBasicBlockList()); - - // At this point, all of the instructions and values of the function are now - // copied over. The only problem is that they are still referencing values in - // the Source function as operands. Loop through all of the operands of the - // functions and patch them up to point to the local versions. - for (Function::iterator BB = Dst->begin(), BE = Dst->end(); BB != BE; ++BB) - for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) - RemapInstruction(I, ValueMap, RF_IgnoreMissingEntries, &TypeMap); - + if (Mode == Linker::DestroySource) { + // Splice the body of the source function into the dest function. + Dst->getBasicBlockList().splice(Dst->end(), Src->getBasicBlockList()); + + // At this point, all of the instructions and values of the function are now + // copied over. The only problem is that they are still referencing values in + // the Source function as operands. Loop through all of the operands of the + // functions and patch them up to point to the local versions. + for (Function::iterator BB = Dst->begin(), BE = Dst->end(); BB != BE; ++BB) + for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) + RemapInstruction(I, ValueMap, RF_IgnoreMissingEntries, &TypeMap); + + } else { + // Clone the body of the function into the dest function. + SmallVector Returns; // Ignore returns. + CloneFunctionInto(Dst, Src, ValueMap, false, Returns); + } + // There is no need to map the arguments anymore. for (Function::arg_iterator I = Src->arg_begin(), E = Src->arg_end(); I != E; ++I) ValueMap.erase(I); + } void ModuleLinker::linkAliasBodies() { for (Module::alias_iterator I = SrcM->alias_begin(), E = SrcM->alias_end(); - I != E; ++I) + I != E; ++I) { + if (DoNotLinkFromSource.count(I)) + continue; if (Constant *Aliasee = I->getAliasee()) { GlobalAlias *DA = cast(ValueMap[I]); DA->setAliasee(MapValue(Aliasee, ValueMap, RF_None, &TypeMap)); } + } } /// linkNamedMDNodes - Insert all of the named mdnodes in Src into the Dest @@ -891,16 +915,10 @@ bool ModuleLinker::run() { StringRef ModuleId = SrcM->getModuleIdentifier(); if (!ModuleId.empty()) DstM->removeLibrary(sys::path::stem(ModuleId)); - // Loop over all of the linked values to compute type mappings. computeTypeMapping(); - // Remap all of the named mdnoes in Src into the DstM module. We do this - // after linking GlobalValues so that MDNodes that reference GlobalValues - // are properly remapped. - linkNamedMDNodes(); - // Insert all of the globals in src into the DstM module... without linking // initializers (which could refer to functions not yet mapped over). for (Module::global_iterator I = SrcM->global_begin(), @@ -933,7 +951,17 @@ bool ModuleLinker::run() { // Link in the function bodies that are defined in the source module into // DstM. for (Module::iterator SF = SrcM->begin(), E = SrcM->end(); SF != E; ++SF) { - if (SF->isDeclaration()) continue; // No body if function is external. + + // Skip if not linking from source. + if (DoNotLinkFromSource.count(SF)) continue; + + // Skip if no body (function is external) or materialize. + if (SF->isDeclaration()) { + if (!SF->isMaterializable()) + continue; + if (SF->Materialize(&ErrorMsg)) + return true; + } linkFunctionBody(cast(ValueMap[SF]), SF); } @@ -941,6 +969,11 @@ bool ModuleLinker::run() { // Resolve all uses of aliases with aliasees. linkAliasBodies(); + // Remap all of the named mdnoes in Src into the DstM module. We do this + // after linking GlobalValues so that MDNodes that reference GlobalValues + // are properly remapped. + linkNamedMDNodes(); + // Now that all of the types from the source are used, resolve any structs // copied over to the dest that didn't exist there. TypeMap.linkDefinedTypeBodies(); @@ -957,8 +990,9 @@ bool ModuleLinker::run() { // error occurs, true is returned and ErrorMsg (if not null) is set to indicate // the problem. Upon failure, the Dest module could be in a modified state, and // shouldn't be relied on to be consistent. -bool Linker::LinkModules(Module *Dest, Module *Src, std::string *ErrorMsg) { - ModuleLinker TheLinker(Dest, Src); +bool Linker::LinkModules(Module *Dest, Module *Src, unsigned Mode, + std::string *ErrorMsg) { + ModuleLinker TheLinker(Dest, Src, Mode); if (TheLinker.run()) { if (ErrorMsg) *ErrorMsg = TheLinker.ErrorMsg; return true; diff --git a/contrib/llvm/lib/Linker/Linker.cpp b/contrib/llvm/lib/Linker/Linker.cpp index fba91da5d..59fbceb6a 100644 --- a/contrib/llvm/lib/Linker/Linker.cpp +++ b/contrib/llvm/lib/Linker/Linker.cpp @@ -141,6 +141,14 @@ static inline sys::Path IsLibrary(StringRef Name, if (FullPath.isBitcodeFile()) // .so file containing bitcode? return FullPath; + // Try libX form, to make it possible to add dependency on the + // specific version of .so, like liblzma.so.1.0.0 + FullPath.eraseSuffix(); + if (FullPath.isDynamicLibrary()) // Native shared library? + return FullPath; + if (FullPath.isBitcodeFile()) // .so file containing bitcode? + return FullPath; + // Not found .. fall through // Indicate that the library was not found in the directory. diff --git a/contrib/llvm/lib/MC/ELFObjectWriter.cpp b/contrib/llvm/lib/MC/ELFObjectWriter.cpp index 59e1b8eb8..3d16de560 100644 --- a/contrib/llvm/lib/MC/ELFObjectWriter.cpp +++ b/contrib/llvm/lib/MC/ELFObjectWriter.cpp @@ -15,6 +15,7 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/Twine.h" +#include "llvm/MC/MCAsmBackend.h" #include "llvm/MC/MCAsmLayout.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" @@ -23,13 +24,13 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ELF.h" -#include "llvm/Target/TargetAsmBackend.h" -#include "llvm/ADT/StringSwitch.h" #include "llvm/Support/CommandLine.h" #include "llvm/ADT/Statistic.h" +#include "llvm/ADT/StringSwitch.h" -#include "../Target/X86/X86FixupKinds.h" -#include "../Target/ARM/ARMFixupKinds.h" +#include "../Target/X86/MCTargetDesc/X86FixupKinds.h" +#include "../Target/ARM/MCTargetDesc/ARMFixupKinds.h" +#include "../Target/PowerPC/MCTargetDesc/PPCFixupKinds.h" #include using namespace llvm; @@ -124,12 +125,12 @@ void ELFObjectWriter::WriteHeader(uint64_t SectionDataSize, // e_shnum = # of section header ents if (NumberOfSections >= ELF::SHN_LORESERVE) - Write16(0); + Write16(ELF::SHN_UNDEF); else Write16(NumberOfSections); // e_shstrndx = Section # of '.shstrtab' - if (NumberOfSections >= ELF::SHN_LORESERVE) + if (ShstrtabIndex >= ELF::SHN_LORESERVE) Write16(ELF::SHN_XINDEX); else Write16(ShstrtabIndex); @@ -301,7 +302,8 @@ void ELFObjectWriter::WriteSymbolTable(MCDataFragment *SymtabF, if (Section.getType() == ELF::SHT_RELA || Section.getType() == ELF::SHT_REL || Section.getType() == ELF::SHT_STRTAB || - Section.getType() == ELF::SHT_SYMTAB) + Section.getType() == ELF::SHT_SYMTAB || + Section.getType() == ELF::SHT_SYMTAB_SHNDX) continue; WriteSymbolEntry(SymtabF, ShndxF, 0, ELF::STT_SECTION, 0, 0, ELF::STV_DEFAULT, SectionIndexMap.lookup(&Section), false); @@ -447,8 +449,16 @@ void ELFObjectWriter::RecordRelocation(const MCAssembler &Asm, uint64_t RelocOffset = Layout.getFragmentOffset(Fragment) + Fixup.getOffset(); + adjustFixupOffset(Fixup, RelocOffset); + if (!hasRelocationAddend()) Addend = 0; + + if (is64Bit()) + assert(isInt<64>(Addend)); + else + assert(isInt<32>(Addend)); + ELFRelocationEntry ERE(RelocOffset, Index, Type, RelocSymbol, Addend); Relocations[Fragment->getParent()].push_back(ERE); } @@ -656,6 +666,9 @@ void ELFObjectWriter::ComputeSymbolTable(MCAssembler &Asm, ExternalSymbolData[i].SymbolData->setIndex(Index++); for (unsigned i = 0, e = UndefinedSymbolData.size(); i != e; ++i) UndefinedSymbolData[i].SymbolData->setIndex(Index++); + + if (NumRegularSections > ELF::SHN_LORESERVE) + NeedsSymtabShndx = true; } void ELFObjectWriter::CreateRelocationSections(MCAssembler &Asm, @@ -992,11 +1005,10 @@ void ELFObjectWriter::WriteSection(MCAssembler &Asm, // Nothing to do. break; - case ELF::SHT_GROUP: { + case ELF::SHT_GROUP: sh_link = SymbolTableIndex; sh_info = GroupSymbolIndex; break; - } default: assert(0 && "FIXME: sh_type value not supported!"); @@ -1224,7 +1236,7 @@ void ELFObjectWriter::WriteObject(MCAssembler &Asm, FileOff = OS.tell(); - // ... and then the remainting sections ... + // ... and then the remaining sections ... for (unsigned i = NumRegularSections + 1; i < NumSections; ++i) WriteDataSectionData(Asm, Layout, *Sections[i]); } @@ -1252,6 +1264,11 @@ MCObjectWriter *llvm::createELFObjectWriter(MCELFObjectTargetWriter *MOTW, return new ARMELFObjectWriter(MOTW, OS, IsLittleEndian); break; case ELF::EM_MBLAZE: return new MBlazeELFObjectWriter(MOTW, OS, IsLittleEndian); break; + case ELF::EM_PPC: + case ELF::EM_PPC64: + return new PPCELFObjectWriter(MOTW, OS, IsLittleEndian); break; + case ELF::EM_MIPS: + return new MipsELFObjectWriter(MOTW, OS, IsLittleEndian); break; default: llvm_unreachable("Unsupported architecture"); break; } } @@ -1503,6 +1520,76 @@ unsigned ARMELFObjectWriter::GetRelocTypeInner(const MCValue &Target, return Type; } +//===- PPCELFObjectWriter -------------------------------------------===// + +PPCELFObjectWriter::PPCELFObjectWriter(MCELFObjectTargetWriter *MOTW, + raw_ostream &_OS, + bool IsLittleEndian) + : ELFObjectWriter(MOTW, _OS, IsLittleEndian) { +} + +PPCELFObjectWriter::~PPCELFObjectWriter() { +} + +unsigned PPCELFObjectWriter::GetRelocType(const MCValue &Target, + const MCFixup &Fixup, + bool IsPCRel, + bool IsRelocWithSymbol, + int64_t Addend) { + // determine the type of the relocation + unsigned Type; + if (IsPCRel) { + switch ((unsigned)Fixup.getKind()) { + default: + llvm_unreachable("Unimplemented"); + case PPC::fixup_ppc_br24: + Type = ELF::R_PPC_REL24; + break; + case FK_PCRel_4: + Type = ELF::R_PPC_REL32; + break; + } + } else { + switch ((unsigned)Fixup.getKind()) { + default: llvm_unreachable("invalid fixup kind!"); + case PPC::fixup_ppc_br24: + Type = ELF::R_PPC_ADDR24; + break; + case PPC::fixup_ppc_brcond14: + Type = ELF::R_PPC_ADDR14_BRTAKEN; // XXX: or BRNTAKEN?_ + break; + case PPC::fixup_ppc_ha16: + Type = ELF::R_PPC_ADDR16_HA; + break; + case PPC::fixup_ppc_lo16: + Type = ELF::R_PPC_ADDR16_LO; + break; + case PPC::fixup_ppc_lo14: + Type = ELF::R_PPC_ADDR14; + break; + case FK_Data_4: + Type = ELF::R_PPC_ADDR32; + break; + case FK_Data_2: + Type = ELF::R_PPC_ADDR16; + break; + } + } + return Type; +} + +void +PPCELFObjectWriter::adjustFixupOffset(const MCFixup &Fixup, uint64_t &RelocOffset) { + switch ((unsigned)Fixup.getKind()) { + case PPC::fixup_ppc_ha16: + case PPC::fixup_ppc_lo16: + RelocOffset += 2; + break; + default: + break; + } +} + //===- MBlazeELFObjectWriter -------------------------------------------===// MBlazeELFObjectWriter::MBlazeELFObjectWriter(MCELFObjectTargetWriter *MOTW, @@ -1624,7 +1711,6 @@ unsigned X86ELFObjectWriter::GetRelocType(const MCValue &Target, default: llvm_unreachable("invalid fixup kind!"); case FK_Data_8: Type = ELF::R_X86_64_64; break; case X86::reloc_signed_4byte: - assert(isInt<32>(Target.getConstant())); switch (Modifier) { default: llvm_unreachable("Unimplemented"); @@ -1728,3 +1814,19 @@ unsigned X86ELFObjectWriter::GetRelocType(const MCValue &Target, return Type; } + +MipsELFObjectWriter::MipsELFObjectWriter(MCELFObjectTargetWriter *MOTW, + raw_ostream &_OS, + bool IsLittleEndian) + : ELFObjectWriter(MOTW, _OS, IsLittleEndian) {} + +MipsELFObjectWriter::~MipsELFObjectWriter() {} + +unsigned MipsELFObjectWriter::GetRelocType(const MCValue &Target, + const MCFixup &Fixup, + bool IsPCRel, + bool IsRelocWithSymbol, + int64_t Addend) { + // tbd + return 1; +} diff --git a/contrib/llvm/lib/MC/ELFObjectWriter.h b/contrib/llvm/lib/MC/ELFObjectWriter.h index 7593099fb..862b085c7 100644 --- a/contrib/llvm/lib/MC/ELFObjectWriter.h +++ b/contrib/llvm/lib/MC/ELFObjectWriter.h @@ -347,6 +347,7 @@ class ELFObjectWriter : public MCObjectWriter { virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, bool IsPCRel, bool IsRelocWithSymbol, int64_t Addend) = 0; + virtual void adjustFixupOffset(const MCFixup &Fixup, uint64_t &RelocOffset) { } }; //===- X86ELFObjectWriter -------------------------------------------===// @@ -395,6 +396,22 @@ class ELFObjectWriter : public MCObjectWriter { }; + //===- PPCELFObjectWriter -------------------------------------------===// + + class PPCELFObjectWriter : public ELFObjectWriter { + public: + PPCELFObjectWriter(MCELFObjectTargetWriter *MOTW, + raw_ostream &_OS, + bool IsLittleEndian); + + virtual ~PPCELFObjectWriter(); + protected: + virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, + bool IsPCRel, bool IsRelocWithSymbol, + int64_t Addend); + virtual void adjustFixupOffset(const MCFixup &Fixup, uint64_t &RelocOffset); + }; + //===- MBlazeELFObjectWriter -------------------------------------------===// class MBlazeELFObjectWriter : public ELFObjectWriter { @@ -409,6 +426,21 @@ class ELFObjectWriter : public MCObjectWriter { bool IsPCRel, bool IsRelocWithSymbol, int64_t Addend); }; + + //===- MipsELFObjectWriter -------------------------------------------===// + + class MipsELFObjectWriter : public ELFObjectWriter { + public: + MipsELFObjectWriter(MCELFObjectTargetWriter *MOTW, + raw_ostream &_OS, + bool IsLittleEndian); + + virtual ~MipsELFObjectWriter(); + protected: + virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, + bool IsPCRel, bool IsRelocWithSymbol, + int64_t Addend); + }; } #endif diff --git a/contrib/llvm/lib/MC/TargetAsmBackend.cpp b/contrib/llvm/lib/MC/MCAsmBackend.cpp similarity index 78% rename from contrib/llvm/lib/MC/TargetAsmBackend.cpp rename to contrib/llvm/lib/MC/MCAsmBackend.cpp index 192755742..2c150f456 100644 --- a/contrib/llvm/lib/MC/TargetAsmBackend.cpp +++ b/contrib/llvm/lib/MC/MCAsmBackend.cpp @@ -1,4 +1,4 @@ -//===-- TargetAsmBackend.cpp - Target Assembly Backend ---------------------==// +//===-- MCAsmBackend.cpp - Target MC Assembly Backend ----------------------==// // // The LLVM Compiler Infrastructure // @@ -7,19 +7,19 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Target/TargetAsmBackend.h" +#include "llvm/MC/MCAsmBackend.h" using namespace llvm; -TargetAsmBackend::TargetAsmBackend() +MCAsmBackend::MCAsmBackend() : HasReliableSymbolDifference(false) { } -TargetAsmBackend::~TargetAsmBackend() { +MCAsmBackend::~MCAsmBackend() { } const MCFixupKindInfo & -TargetAsmBackend::getFixupKindInfo(MCFixupKind Kind) const { +MCAsmBackend::getFixupKindInfo(MCFixupKind Kind) const { static const MCFixupKindInfo Builtins[] = { { "FK_Data_1", 0, 8, 0 }, { "FK_Data_2", 0, 16, 0 }, diff --git a/contrib/llvm/lib/MC/MCAsmInfo.cpp b/contrib/llvm/lib/MC/MCAsmInfo.cpp index 502b60b0e..95861bc61 100644 --- a/contrib/llvm/lib/MC/MCAsmInfo.cpp +++ b/contrib/llvm/lib/MC/MCAsmInfo.cpp @@ -29,6 +29,7 @@ MCAsmInfo::MCAsmInfo() { HasSubsectionsViaSymbols = false; HasMachoZeroFillDirective = false; HasMachoTBSSDirective = false; + StructorOutputOrder = Structors::ReversePriorityOrder; HasStaticCtorDtorReferenceInStaticMode = false; LinkerRequiresNonEmptyDwarfLines = false; MaxInstLength = 4; @@ -42,6 +43,9 @@ MCAsmInfo::MCAsmInfo() { LinkerPrivateGlobalPrefix = ""; InlineAsmStart = "APP"; InlineAsmEnd = "NO_APP"; + Code16Directive = ".code16"; + Code32Directive = ".code32"; + Code64Directive = ".code64"; AssemblerDialect = 0; AllowQuotesInName = false; AllowNameToStartWithDigit = false; @@ -53,6 +57,12 @@ MCAsmInfo::MCAsmInfo() { Data16bitsDirective = "\t.short\t"; Data32bitsDirective = "\t.long\t"; Data64bitsDirective = "\t.quad\t"; + DataBegin = "$d."; + CodeBegin = "$a."; + JT8Begin = "$d."; + JT16Begin = "$d."; + JT32Begin = "$d."; + SupportsDataRegions = false; SunStyleELFSectionSwitchSyntax = false; UsesELFSectionDirectiveForBSS = false; AlignDirective = "\t.align\t"; @@ -62,7 +72,7 @@ MCAsmInfo::MCAsmInfo() { GlobalDirective = "\t.globl\t"; HasSetDirective = true; HasAggressiveSymbolFolding = true; - HasLCOMMDirective = false; + LCOMMDirectiveType = LCOMM::None; COMMDirectiveAlignmentIsInBytes = true; HasDotTypeDotSizeDirective = true; HasSingleParameterDotFile = true; diff --git a/contrib/llvm/lib/MC/MCAsmInfoCOFF.cpp b/contrib/llvm/lib/MC/MCAsmInfoCOFF.cpp index 7fc7d7abb..434d9103a 100644 --- a/contrib/llvm/lib/MC/MCAsmInfoCOFF.cpp +++ b/contrib/llvm/lib/MC/MCAsmInfoCOFF.cpp @@ -19,7 +19,7 @@ using namespace llvm; MCAsmInfoCOFF::MCAsmInfoCOFF() { GlobalPrefix = "_"; COMMDirectiveAlignmentIsInBytes = false; - HasLCOMMDirective = true; + LCOMMDirectiveType = LCOMM::ByteAlignment; HasDotTypeDotSizeDirective = false; HasSingleParameterDotFile = false; PrivateGlobalPrefix = "L"; // Prefix for private global symbols @@ -27,11 +27,14 @@ MCAsmInfoCOFF::MCAsmInfoCOFF() { LinkOnceDirective = "\t.linkonce discard\n"; // Doesn't support visibility: - HiddenVisibilityAttr = ProtectedVisibilityAttr = MCSA_Invalid; + HiddenVisibilityAttr = HiddenDeclarationVisibilityAttr = MCSA_Invalid; + ProtectedVisibilityAttr = MCSA_Invalid; // Set up DWARF directives HasLEB128 = true; // Target asm supports leb128 directives (little-endian) SupportsDebugInformation = true; DwarfSectionOffsetDirective = "\t.secrel32\t"; HasMicrosoftFastStdCallMangling = true; + + SupportsDataRegions = false; } diff --git a/contrib/llvm/lib/MC/MCAsmInfoDarwin.cpp b/contrib/llvm/lib/MC/MCAsmInfoDarwin.cpp index 5851cb039..b20e338f7 100644 --- a/contrib/llvm/lib/MC/MCAsmInfoDarwin.cpp +++ b/contrib/llvm/lib/MC/MCAsmInfoDarwin.cpp @@ -39,8 +39,16 @@ MCAsmInfoDarwin::MCAsmInfoDarwin() { ZeroDirective = "\t.space\t"; // ".space N" emits N zeros. HasMachoZeroFillDirective = true; // Uses .zerofill HasMachoTBSSDirective = true; // Uses .tbss + StructorOutputOrder = Structors::PriorityOrder; HasStaticCtorDtorReferenceInStaticMode = true; + CodeBegin = "L$start$code$"; + DataBegin = "L$start$data$"; + JT8Begin = "L$start$jt8$"; + JT16Begin = "L$start$jt16$"; + JT32Begin = "L$start$jt32$"; + SupportsDataRegions = true; + // FIXME: Darwin 10 and newer don't need this. LinkerRequiresNonEmptyDwarfLines = true; diff --git a/contrib/llvm/lib/MC/MCAsmStreamer.cpp b/contrib/llvm/lib/MC/MCAsmStreamer.cpp index d5d08e8f6..3fcbb0590 100644 --- a/contrib/llvm/lib/MC/MCAsmStreamer.cpp +++ b/contrib/llvm/lib/MC/MCAsmStreamer.cpp @@ -15,8 +15,12 @@ #include "llvm/MC/MCFixupKindInfo.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCInstPrinter.h" +#include "llvm/MC/MCObjectFileInfo.h" +#include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCSectionCOFF.h" #include "llvm/MC/MCSectionMachO.h" #include "llvm/MC/MCSymbol.h" +#include "llvm/MC/MCAsmBackend.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" @@ -25,9 +29,6 @@ #include "llvm/Support/MathExtras.h" #include "llvm/Support/Format.h" #include "llvm/Support/FormattedStream.h" -#include "llvm/Target/TargetAsmBackend.h" -#include "llvm/Target/TargetAsmInfo.h" -#include "llvm/Target/TargetLoweringObjectFile.h" #include using namespace llvm; @@ -40,7 +41,7 @@ protected: private: OwningPtr InstPrinter; OwningPtr Emitter; - OwningPtr AsmBackend; + OwningPtr AsmBackend; SmallString<128> CommentToEmit; raw_svector_ostream CommentStream; @@ -63,7 +64,7 @@ public: MCAsmStreamer(MCContext &Context, formatted_raw_ostream &os, bool isVerboseAsm, bool useLoc, bool useCFI, MCInstPrinter *printer, MCCodeEmitter *emitter, - TargetAsmBackend *asmbackend, + MCAsmBackend *asmbackend, bool showInst) : MCStreamer(Context), OS(os), MAI(Context.getAsmInfo()), InstPrinter(printer), Emitter(emitter), AsmBackend(asmbackend), @@ -157,7 +158,9 @@ public: /// /// @param Symbol - The common symbol to emit. /// @param Size - The size of the common symbol. - virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size); + /// @param Size - The alignment of the common symbol in bytes. + virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment); virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = 0, unsigned Size = 0, unsigned ByteAlignment = 0); @@ -334,8 +337,9 @@ void MCAsmStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) { default: assert(0 && "Invalid flag!"); case MCAF_SyntaxUnified: OS << "\t.syntax unified"; break; case MCAF_SubsectionsViaSymbols: OS << ".subsections_via_symbols"; break; - case MCAF_Code16: OS << "\t.code\t16"; break; - case MCAF_Code32: OS << "\t.code\t32"; break; + case MCAF_Code16: OS << '\t'<< MAI.getCode16Directive(); break; + case MCAF_Code32: OS << '\t'<< MAI.getCode32Directive(); break; + case MCAF_Code64: OS << '\t'<< MAI.getCode64Directive(); break; } EmitEOL(); } @@ -482,9 +486,16 @@ void MCAsmStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, /// /// @param Symbol - The common symbol to emit. /// @param Size - The size of the common symbol. -void MCAsmStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size) { - assert(MAI.hasLCOMMDirective() && "Doesn't have .lcomm, can't emit it!"); +void MCAsmStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlign) { + assert(MAI.getLCOMMDirectiveType() != LCOMM::None && + "Doesn't have .lcomm, can't emit it!"); OS << "\t.lcomm\t" << *Symbol << ',' << Size; + if (ByteAlign > 1) { + assert(MAI.getLCOMMDirectiveType() == LCOMM::ByteAlignment && + "Alignment not supported on .lcomm!"); + OS << ',' << ByteAlign; + } EmitEOL(); } @@ -827,8 +838,8 @@ void MCAsmStreamer::EmitCFIEndProc() { void MCAsmStreamer::EmitRegisterName(int64_t Register) { if (InstPrinter && !MAI.useDwarfRegNumForCFI()) { - const TargetAsmInfo &TAI = getContext().getTargetAsmInfo(); - unsigned LLVMRegister = TAI.getLLVMRegNum(Register, true); + const MCRegisterInfo &MRI = getContext().getRegisterInfo(); + unsigned LLVMRegister = MRI.getLLVMRegNum(Register, true); InstPrinter->printRegName(OS, LLVMRegister); } else { OS << Register; @@ -994,6 +1005,19 @@ void MCAsmStreamer::EmitWin64EHHandler(const MCSymbol *Sym, bool Unwind, EmitEOL(); } +static const MCSection *getWin64EHTableSection(StringRef suffix, + MCContext &context) { + // FIXME: This doesn't belong in MCObjectFileInfo. However, + /// this duplicate code in MCWin64EH.cpp. + if (suffix == "") + return context.getObjectFileInfo()->getXDataSection(); + return context.getCOFFSection((".xdata"+suffix).str(), + COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | + COFF::IMAGE_SCN_MEM_READ | + COFF::IMAGE_SCN_MEM_WRITE, + SectionKind::getDataRel()); +} + void MCAsmStreamer::EmitWin64EHHandlerData() { MCStreamer::EmitWin64EHHandlerData(); @@ -1003,8 +1027,7 @@ void MCAsmStreamer::EmitWin64EHHandlerData() { // data block is visible. MCWin64EHUnwindInfo *CurFrame = getCurrentW64UnwindInfo(); StringRef suffix=MCWin64EHUnwindEmitter::GetSectionSuffix(CurFrame->Function); - const MCSection *xdataSect = - getContext().getTargetAsmInfo().getWin64EHTableSection(suffix); + const MCSection *xdataSect = getWin64EHTableSection(suffix, getContext()); if (xdataSect) SwitchSectionNoChange(xdataSect); @@ -1221,7 +1244,7 @@ void MCAsmStreamer::EmitInstruction(const MCInst &Inst) { // If we have an AsmPrinter, use that to print, otherwise print the MCInst. if (InstPrinter) - InstPrinter->printInst(&Inst, OS); + InstPrinter->printInst(&Inst, OS, ""); else Inst.print(OS, &MAI); EmitEOL(); @@ -1249,8 +1272,8 @@ MCStreamer *llvm::createAsmStreamer(MCContext &Context, formatted_raw_ostream &OS, bool isVerboseAsm, bool useLoc, bool useCFI, MCInstPrinter *IP, - MCCodeEmitter *CE, TargetAsmBackend *TAB, + MCCodeEmitter *CE, MCAsmBackend *MAB, bool ShowInst) { return new MCAsmStreamer(Context, OS, isVerboseAsm, useLoc, useCFI, - IP, CE, TAB, ShowInst); + IP, CE, MAB, ShowInst); } diff --git a/contrib/llvm/lib/MC/MCAssembler.cpp b/contrib/llvm/lib/MC/MCAssembler.cpp index 527a63caa..06c8aec91 100644 --- a/contrib/llvm/lib/MC/MCAssembler.cpp +++ b/contrib/llvm/lib/MC/MCAssembler.cpp @@ -18,6 +18,7 @@ #include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCValue.h" #include "llvm/MC/MCDwarf.h" +#include "llvm/MC/MCAsmBackend.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/Statistic.h" #include "llvm/ADT/StringExtras.h" @@ -25,8 +26,7 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/Target/TargetRegistry.h" -#include "llvm/Target/TargetAsmBackend.h" +#include "llvm/Support/TargetRegistry.h" using namespace llvm; @@ -194,7 +194,7 @@ MCSymbolData::MCSymbolData(const MCSymbol &_Symbol, MCFragment *_Fragment, /* *** */ -MCAssembler::MCAssembler(MCContext &Context_, TargetAsmBackend &Backend_, +MCAssembler::MCAssembler(MCContext &Context_, MCAsmBackend &Backend_, MCCodeEmitter &Emitter_, MCObjectWriter &Writer_, raw_ostream &OS_) : Context(Context_), Backend(Backend_), Emitter(Emitter_), Writer(Writer_), diff --git a/contrib/llvm/lib/MC/MCAtom.cpp b/contrib/llvm/lib/MC/MCAtom.cpp new file mode 100644 index 000000000..d71444324 --- /dev/null +++ b/contrib/llvm/lib/MC/MCAtom.cpp @@ -0,0 +1,97 @@ +//===- lib/MC/MCAtom.cpp - MCAtom implementation --------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCAtom.h" +#include "llvm/MC/MCModule.h" +#include "llvm/Support/ErrorHandling.h" + +using namespace llvm; + +void MCAtom::addInst(const MCInst &I, uint64_t Address, unsigned Size) { + assert(Type == TextAtom && "Trying to add MCInst to a non-text atom!"); + + assert(Address < End+Size && + "Instruction not contiguous with end of atom!"); + if (Address > End) + Parent->remap(this, Begin, End+Size); + + Text.push_back(std::make_pair(Address, I)); +} + +void MCAtom::addData(const MCData &D) { + assert(Type == DataAtom && "Trying to add MCData to a non-data atom!"); + Parent->remap(this, Begin, End+1); + + Data.push_back(D); +} + +MCAtom *MCAtom::split(uint64_t SplitPt) { + assert((SplitPt > Begin && SplitPt <= End) && + "Splitting at point not contained in atom!"); + + // Compute the new begin/end points. + uint64_t LeftBegin = Begin; + uint64_t LeftEnd = SplitPt - 1; + uint64_t RightBegin = SplitPt; + uint64_t RightEnd = End; + + // Remap this atom to become the lower of the two new ones. + Parent->remap(this, LeftBegin, LeftEnd); + + // Create a new atom for the higher atom. + MCAtom *RightAtom = Parent->createAtom(Type, RightBegin, RightEnd); + + // Split the contents of the original atom between it and the new one. The + // precise method depends on whether this is a data or a text atom. + if (isDataAtom()) { + std::vector::iterator I = Data.begin() + (RightBegin - LeftBegin); + + assert(I != Data.end() && "Split point not found in range!"); + + std::copy(I, Data.end(), RightAtom->Data.end()); + Data.erase(I, Data.end()); + } else if (isTextAtom()) { + std::vector >::iterator I = Text.begin(); + + while (I != Text.end() && I->first < SplitPt) ++I; + + assert(I != Text.end() && "Split point not found in disassembly!"); + assert(I->first == SplitPt && + "Split point does not fall on instruction boundary!"); + + std::copy(I, Text.end(), RightAtom->Text.end()); + Text.erase(I, Text.end()); + } else + llvm_unreachable("Unknown atom type!"); + + return RightAtom; +} + +void MCAtom::truncate(uint64_t TruncPt) { + assert((TruncPt >= Begin && TruncPt < End) && + "Truncation point not contained in atom!"); + + Parent->remap(this, Begin, TruncPt); + + if (isDataAtom()) { + Data.resize(TruncPt - Begin + 1); + } else if (isTextAtom()) { + std::vector >::iterator I = Text.begin(); + + while (I != Text.end() && I->first <= TruncPt) ++I; + + assert(I != Text.end() && "Truncation point not found in disassembly!"); + assert(I->first == TruncPt+1 && + "Truncation point does not fall on instruction boundary"); + + Text.erase(I, Text.end()); + } else + llvm_unreachable("Unknown atom type!"); +} + diff --git a/contrib/llvm/lib/MC/MCCodeGenInfo.cpp b/contrib/llvm/lib/MC/MCCodeGenInfo.cpp new file mode 100644 index 000000000..236e7de68 --- /dev/null +++ b/contrib/llvm/lib/MC/MCCodeGenInfo.cpp @@ -0,0 +1,21 @@ +//===-- MCCodeGenInfo.cpp - Target CodeGen Info -----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file tracks information about the target which can affect codegen, +// asm parsing, and asm printing. For example, relocation model. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCCodeGenInfo.h" +using namespace llvm; + +void MCCodeGenInfo::InitMCCodeGenInfo(Reloc::Model RM, CodeModel::Model CM) { + RelocationModel = RM; + CMModel = CM; +} diff --git a/contrib/llvm/lib/MC/MCContext.cpp b/contrib/llvm/lib/MC/MCContext.cpp index 8faa72ecb..82690ee3b 100644 --- a/contrib/llvm/lib/MC/MCContext.cpp +++ b/contrib/llvm/lib/MC/MCContext.cpp @@ -9,13 +9,14 @@ #include "llvm/MC/MCContext.h" #include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCObjectFileInfo.h" +#include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCSectionMachO.h" #include "llvm/MC/MCSectionELF.h" #include "llvm/MC/MCSectionCOFF.h" #include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCLabel.h" #include "llvm/MC/MCDwarf.h" -#include "llvm/Target/TargetAsmInfo.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/ELF.h" @@ -26,8 +27,9 @@ typedef StringMap ELFUniqueMapTy; typedef StringMap COFFUniqueMapTy; -MCContext::MCContext(const MCAsmInfo &mai, const TargetAsmInfo *tai) : - MAI(mai), TAI(tai), +MCContext::MCContext(const MCAsmInfo &mai, const MCRegisterInfo &mri, + const MCObjectFileInfo *mofi) : + MAI(mai), MRI(mri), MOFI(mofi), Allocator(), Symbols(Allocator), UsedNames(Allocator), NextUniqueID(0), CurrentDwarfLoc(0,0,0,DWARF2_FLAG_IS_STMT,0,0), @@ -54,8 +56,6 @@ MCContext::~MCContext() { // If the stream for the .secure_log_unique directive was created free it. delete (raw_ostream*)SecureLog; - - delete TAI; } //===----------------------------------------------------------------------===// @@ -279,7 +279,8 @@ unsigned MCContext::GetDwarfFile(StringRef FileName, unsigned FileNumber) { } else { StringRef Directory = Slash.first; Name = Slash.second; - for (DirIndex = 0; DirIndex < MCDwarfDirs.size(); DirIndex++) { + DirIndex = 0; + for (unsigned End = MCDwarfDirs.size(); DirIndex < End; DirIndex++) { if (Directory == MCDwarfDirs[DirIndex]) break; } diff --git a/contrib/llvm/lib/MC/MCDisassembler/Disassembler.cpp b/contrib/llvm/lib/MC/MCDisassembler/Disassembler.cpp index 5480b4b12..16e66dc98 100644 --- a/contrib/llvm/lib/MC/MCDisassembler/Disassembler.cpp +++ b/contrib/llvm/lib/MC/MCDisassembler/Disassembler.cpp @@ -1,4 +1,4 @@ -//===-- lib/MC/Disassembler.cpp - Disassembler Public C Interface -*- C -*-===// +//===-- lib/MC/Disassembler.cpp - Disassembler Public C Interface ---------===// // // The LLVM Compiler Infrastructure // @@ -11,15 +11,14 @@ #include "llvm-c/Disassembler.h" #include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h" #include "llvm/MC/MCDisassembler.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCInstPrinter.h" -#include "llvm/MC/MCContext.h" -#include "llvm/Target/TargetRegistry.h" -#include "llvm/Target/TargetAsmInfo.h" // FIXME. -#include "llvm/Target/TargetMachine.h" // FIXME. -#include "llvm/Target/TargetSelect.h" +#include "llvm/MC/MCRegisterInfo.h" #include "llvm/Support/MemoryObject.h" +#include "llvm/Support/TargetRegistry.h" +#include "llvm/Support/TargetSelect.h" namespace llvm { class Target; @@ -38,10 +37,7 @@ LLVMDisasmContextRef LLVMCreateDisasm(const char *TripleName, void *DisInfo, LLVMSymbolLookupCallback SymbolLookUp) { // Initialize targets and assembly printers/parsers. llvm::InitializeAllTargetInfos(); - // FIXME: We shouldn't need to initialize the Target(Machine)s. - llvm::InitializeAllTargets(); - llvm::InitializeAllMCAsmInfos(); - llvm::InitializeAllAsmPrinters(); + llvm::InitializeAllTargetMCs(); llvm::InitializeAllAsmParsers(); llvm::InitializeAllDisassemblers(); @@ -54,41 +50,38 @@ LLVMDisasmContextRef LLVMCreateDisasm(const char *TripleName, void *DisInfo, const MCAsmInfo *MAI = TheTarget->createMCAsmInfo(TripleName); assert(MAI && "Unable to create target asm info!"); + const MCRegisterInfo *MRI = TheTarget->createMCRegInfo(TripleName); + assert(MRI && "Unable to create target register info!"); + // Package up features to be passed to target/subtarget std::string FeaturesStr; std::string CPU; - // FIXME: We shouldn't need to do this (and link in codegen). - // When we split this out, we should do it in a way that makes - // it straightforward to switch subtargets on the fly. - TargetMachine *TM = TheTarget->createTargetMachine(TripleName, CPU, - FeaturesStr); - assert(TM && "Unable to create target machine!"); - - // Get the target assembler info needed to setup the context. - const TargetAsmInfo *tai = new TargetAsmInfo(*TM); - assert(tai && "Unable to create target assembler!"); + const MCSubtargetInfo *STI = TheTarget->createMCSubtargetInfo(TripleName, CPU, + FeaturesStr); + assert(STI && "Unable to create subtarget info!"); // Set up the MCContext for creating symbols and MCExpr's. - MCContext *Ctx = new MCContext(*MAI, tai); + MCContext *Ctx = new MCContext(*MAI, *MRI, 0); assert(Ctx && "Unable to create MCContext!"); // Set up disassembler. - MCDisassembler *DisAsm = TheTarget->createMCDisassembler(); + MCDisassembler *DisAsm = TheTarget->createMCDisassembler(*STI); assert(DisAsm && "Unable to create disassembler!"); - DisAsm->setupForSymbolicDisassembly(GetOpInfo, DisInfo, Ctx); + DisAsm->setupForSymbolicDisassembly(GetOpInfo, SymbolLookUp, DisInfo, Ctx); // Set up the instruction printer. int AsmPrinterVariant = MAI->getAssemblerDialect(); MCInstPrinter *IP = TheTarget->createMCInstPrinter(AsmPrinterVariant, - *MAI); + *MAI, *STI); assert(IP && "Unable to create instruction printer!"); LLVMDisasmContext *DC = new LLVMDisasmContext(TripleName, DisInfo, TagType, GetOpInfo, SymbolLookUp, - TheTarget, MAI, TM, tai, Ctx, - DisAsm, IP); + TheTarget, MAI, MRI, + Ctx, DisAsm, IP); assert(DC && "Allocation failure!"); + return DC; } @@ -147,18 +140,35 @@ size_t LLVMDisasmInstruction(LLVMDisasmContextRef DCR, uint8_t *Bytes, MCInst Inst; const MCDisassembler *DisAsm = DC->getDisAsm(); MCInstPrinter *IP = DC->getIP(); - if (!DisAsm->getInstruction(Inst, Size, MemoryObject, PC, /*REMOVE*/ nulls())) + MCDisassembler::DecodeStatus S; + S = DisAsm->getInstruction(Inst, Size, MemoryObject, PC, + /*REMOVE*/ nulls(), DC->CommentStream); + switch (S) { + case MCDisassembler::Fail: + case MCDisassembler::SoftFail: + // FIXME: Do something different for soft failure modes? return 0; - SmallVector InsnStr; - raw_svector_ostream OS(InsnStr); - IP->printInst(&Inst, OS); - OS.flush(); + case MCDisassembler::Success: { + DC->CommentStream.flush(); + StringRef Comments = DC->CommentsToEmit.str(); - assert(OutStringSize != 0 && "Output buffer cannot be zero size"); - size_t OutputSize = std::min(OutStringSize-1, InsnStr.size()); - std::memcpy(OutString, InsnStr.data(), OutputSize); - OutString[OutputSize] = '\0'; // Terminate string. + SmallVector InsnStr; + raw_svector_ostream OS(InsnStr); + IP->printInst(&Inst, OS, Comments); + OS.flush(); - return Size; + // Tell the comment stream that the vector changed underneath it. + DC->CommentsToEmit.clear(); + DC->CommentStream.resync(); + + assert(OutStringSize != 0 && "Output buffer cannot be zero size"); + size_t OutputSize = std::min(OutStringSize-1, InsnStr.size()); + std::memcpy(OutString, InsnStr.data(), OutputSize); + OutString[OutputSize] = '\0'; // Terminate string. + + return Size; + } + } + return 0; } diff --git a/contrib/llvm/lib/MC/MCDisassembler/Disassembler.h b/contrib/llvm/lib/MC/MCDisassembler/Disassembler.h index f0ec42a01..238ff7d50 100644 --- a/contrib/llvm/lib/MC/MCDisassembler/Disassembler.h +++ b/contrib/llvm/lib/MC/MCDisassembler/Disassembler.h @@ -20,15 +20,16 @@ #include "llvm-c/Disassembler.h" #include #include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/Support/raw_ostream.h" namespace llvm { -class TargetAsmInfo; class MCContext; class MCAsmInfo; class MCDisassembler; class MCInstPrinter; +class MCRegisterInfo; class Target; -class TargetMachine; // // This is the disassembler context returned by LLVMCreateDisasm(). @@ -58,12 +59,8 @@ private: const Target *TheTarget; // The assembly information for the target architecture. llvm::OwningPtr MAI; - // The target machine instance. - llvm::OwningPtr TM; - // The disassembler for the target architecture. - // FIXME: using llvm::OwningPtr causes a malloc - // error when this LLVMDisasmContext is deleted. - const TargetAsmInfo *Tai; + // The register information for the target architecture. + llvm::OwningPtr MRI; // The assembly context for creating symbols and MCExprs. llvm::OwningPtr Ctx; // The disassembler for the target architecture. @@ -72,22 +69,28 @@ private: llvm::OwningPtr IP; public: + // Comment stream and backing vector. + SmallString<128> CommentsToEmit; + raw_svector_ostream CommentStream; + LLVMDisasmContext(std::string tripleName, void *disInfo, int tagType, LLVMOpInfoCallback getOpInfo, LLVMSymbolLookupCallback symbolLookUp, const Target *theTarget, const MCAsmInfo *mAI, - llvm::TargetMachine *tM, const TargetAsmInfo *tai, + const MCRegisterInfo *mRI, llvm::MCContext *ctx, const MCDisassembler *disAsm, MCInstPrinter *iP) : TripleName(tripleName), DisInfo(disInfo), TagType(tagType), GetOpInfo(getOpInfo), - SymbolLookUp(symbolLookUp), TheTarget(theTarget), Tai(tai) { - TM.reset(tM); + SymbolLookUp(symbolLookUp), TheTarget(theTarget), + CommentStream(CommentsToEmit) { MAI.reset(mAI); + MRI.reset(mRI); Ctx.reset(ctx); DisAsm.reset(disAsm); IP.reset(iP); } const MCDisassembler *getDisAsm() const { return DisAsm.get(); } + const MCAsmInfo *getAsmInfo() const { return MAI.get(); } MCInstPrinter *getIP() { return IP.get(); } }; diff --git a/contrib/llvm/lib/MC/MCDisassembler/EDDisassembler.cpp b/contrib/llvm/lib/MC/MCDisassembler/EDDisassembler.cpp index bdd99afe1..83362a21f 100644 --- a/contrib/llvm/lib/MC/MCDisassembler/EDDisassembler.cpp +++ b/contrib/llvm/lib/MC/MCDisassembler/EDDisassembler.cpp @@ -22,20 +22,19 @@ #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCInstPrinter.h" +#include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/MC/MCParser/AsmLexer.h" #include "llvm/MC/MCParser/MCAsmParser.h" #include "llvm/MC/MCParser/MCParsedAsmOperand.h" +#include "llvm/MC/MCTargetAsmLexer.h" +#include "llvm/MC/MCTargetAsmParser.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/MemoryObject.h" #include "llvm/Support/SourceMgr.h" -#include "llvm/Target/TargetAsmLexer.h" -#include "llvm/Target/TargetAsmParser.h" -#include "llvm/Target/TargetRegistry.h" -#include "llvm/Target/TargetMachine.h" -#include "llvm/Target/TargetRegisterInfo.h" -#include "llvm/Target/TargetSelect.h" +#include "llvm/Support/TargetRegistry.h" +#include "llvm/Support/TargetSelect.h" using namespace llvm; bool EDDisassembler::sInitialized = false; @@ -106,9 +105,7 @@ void EDDisassembler::initialize() { sInitialized = true; InitializeAllTargetInfos(); - InitializeAllTargets(); - InitializeAllMCAsmInfos(); - InitializeAllAsmPrinters(); + InitializeAllTargetMCs(); InitializeAllAsmParsers(); InitializeAllDisassemblers(); } @@ -169,24 +166,24 @@ EDDisassembler::EDDisassembler(CPUKey &key) : if (!Tgt) return; - std::string CPU; - std::string featureString; - TargetMachine.reset(Tgt->createTargetMachine(tripleString, CPU, - featureString)); + MRI.reset(Tgt->createMCRegInfo(tripleString)); - const TargetRegisterInfo *registerInfo = TargetMachine->getRegisterInfo(); - - if (!registerInfo) + if (!MRI) return; - - initMaps(*registerInfo); + + initMaps(*MRI); AsmInfo.reset(Tgt->createMCAsmInfo(tripleString)); if (!AsmInfo) return; - Disassembler.reset(Tgt->createMCDisassembler()); + STI.reset(Tgt->createMCSubtargetInfo(tripleString, "", "")); + + if (!STI) + return; + + Disassembler.reset(Tgt->createMCDisassembler(*STI)); if (!Disassembler) return; @@ -195,16 +192,16 @@ EDDisassembler::EDDisassembler(CPUKey &key) : InstString.reset(new std::string); InstStream.reset(new raw_string_ostream(*InstString)); - InstPrinter.reset(Tgt->createMCInstPrinter(LLVMSyntaxVariant, *AsmInfo)); + InstPrinter.reset(Tgt->createMCInstPrinter(LLVMSyntaxVariant, *AsmInfo, *STI)); if (!InstPrinter) return; GenericAsmLexer.reset(new AsmLexer(*AsmInfo)); - SpecificAsmLexer.reset(Tgt->createAsmLexer(*AsmInfo)); + SpecificAsmLexer.reset(Tgt->createMCAsmLexer(*MRI, *AsmInfo)); SpecificAsmLexer->InstallLexer(*GenericAsmLexer); - initMaps(*TargetMachine->getRegisterInfo()); + initMaps(*MRI); Valid = true; } @@ -247,14 +244,17 @@ EDInst *EDDisassembler::createInst(EDByteReaderCallback byteReader, MCInst* inst = new MCInst; uint64_t byteSize; - if (!Disassembler->getInstruction(*inst, - byteSize, - memoryObject, - address, - ErrorStream)) { + MCDisassembler::DecodeStatus S; + S = Disassembler->getInstruction(*inst, byteSize, memoryObject, address, + ErrorStream, nulls()); + switch (S) { + case MCDisassembler::Fail: + case MCDisassembler::SoftFail: + // FIXME: Do something different on soft failure mode? delete inst; return NULL; - } else { + + case MCDisassembler::Success: { const llvm::EDInstInfo *thisInstInfo = NULL; if (InstInfos) { @@ -264,9 +264,11 @@ EDInst *EDDisassembler::createInst(EDByteReaderCallback byteReader, EDInst* sdInst = new EDInst(inst, byteSize, *this, thisInstInfo); return sdInst; } + } + return NULL; } -void EDDisassembler::initMaps(const TargetRegisterInfo ®isterInfo) { +void EDDisassembler::initMaps(const MCRegisterInfo ®isterInfo) { unsigned numRegisters = registerInfo.getNumRegs(); unsigned registerIndex; @@ -325,7 +327,7 @@ bool EDDisassembler::registerIsProgramCounter(unsigned registerID) { int EDDisassembler::printInst(std::string &str, MCInst &inst) { PrinterMutex.acquire(); - InstPrinter->printInst(&inst, *InstStream); + InstPrinter->printInst(&inst, *InstStream, ""); InstStream->flush(); str = *InstString; InstString->clear(); @@ -368,16 +370,16 @@ int EDDisassembler::parseInst(SmallVectorImpl &operands, SourceMgr sourceMgr; sourceMgr.setDiagHandler(diag_handler, static_cast(this)); sourceMgr.AddNewSourceBuffer(buf, SMLoc()); // ownership of buf handed over - MCContext context(*AsmInfo, NULL); + MCContext context(*AsmInfo, *MRI, NULL); OwningPtr streamer(createNullStreamer(context)); - OwningPtr genericParser(createMCAsmParser(*Tgt, sourceMgr, + OwningPtr genericParser(createMCAsmParser(sourceMgr, context, *streamer, *AsmInfo)); StringRef triple = tripleFromArch(Key.Arch); OwningPtr STI(Tgt->createMCSubtargetInfo(triple, "", "")); - OwningPtr TargetParser(Tgt->createAsmParser(*STI, - *genericParser)); + OwningPtr + TargetParser(Tgt->createMCAsmParser(*STI, *genericParser)); AsmToken OpcodeToken = genericParser->Lex(); AsmToken NextToken = genericParser->Lex(); // consume next token, because specificParser expects us to diff --git a/contrib/llvm/lib/MC/MCDisassembler/EDDisassembler.h b/contrib/llvm/lib/MC/MCDisassembler/EDDisassembler.h index 11d69c151..38c22038c 100644 --- a/contrib/llvm/lib/MC/MCDisassembler/EDDisassembler.h +++ b/contrib/llvm/lib/MC/MCDisassembler/EDDisassembler.h @@ -29,24 +29,23 @@ namespace llvm { class AsmLexer; +class AsmParser; class AsmToken; class MCContext; class MCAsmInfo; class MCAsmLexer; -class AsmParser; -class TargetAsmLexer; -class TargetAsmParser; class MCDisassembler; class MCInstPrinter; class MCInst; class MCParsedAsmOperand; +class MCRegisterInfo; class MCStreamer; class MCSubtargetInfo; +class MCTargetAsmLexer; +class MCTargetAsmParser; template class SmallVectorImpl; class SourceMgr; class Target; -class TargetMachine; -class TargetRegisterInfo; struct EDInstInfo; struct EDInst; @@ -136,10 +135,12 @@ struct EDDisassembler { CPUKey Key; /// The LLVM target corresponding to the disassembler const llvm::Target *Tgt; - /// The target machine instance. - llvm::OwningPtr TargetMachine; /// The assembly information for the target architecture llvm::OwningPtr AsmInfo; + /// The subtarget information for the target architecture + llvm::OwningPtr STI; + // The register information for the target architecture. + llvm::OwningPtr MRI; /// The disassembler for the target architecture llvm::OwningPtr Disassembler; /// The output string for the instruction printer; must be guarded with @@ -160,7 +161,7 @@ struct EDDisassembler { /// The target-specific lexer for use in tokenizing strings, in /// target-independent and target-specific portions llvm::OwningPtr GenericAsmLexer; - llvm::OwningPtr SpecificAsmLexer; + llvm::OwningPtr SpecificAsmLexer; /// The guard for the above llvm::sys::Mutex ParserMutex; /// The LLVM number used for the target disassembly syntax variant @@ -216,7 +217,7 @@ struct EDDisassembler { /// info /// /// @arg registerInfo - the register information to use as a source - void initMaps(const llvm::TargetRegisterInfo ®isterInfo); + void initMaps(const llvm::MCRegisterInfo ®isterInfo); /// nameWithRegisterID - Returns the name (owned by the EDDisassembler) of a /// register for a given register ID, or NULL on failure /// diff --git a/contrib/llvm/lib/MC/MCDisassembler/EDInst.h b/contrib/llvm/lib/MC/MCDisassembler/EDInst.h index ceb950502..6b78dc826 100644 --- a/contrib/llvm/lib/MC/MCDisassembler/EDInst.h +++ b/contrib/llvm/lib/MC/MCDisassembler/EDInst.h @@ -73,7 +73,7 @@ struct EDInst { std::string String; /// The order in which operands from the InstInfo's operand information appear /// in String - const char* OperandOrder; + const signed char* OperandOrder; /// The result of the parseOperands() function CachedResult ParseResult; diff --git a/contrib/llvm/lib/MC/MCDisassembler/EDToken.cpp b/contrib/llvm/lib/MC/MCDisassembler/EDToken.cpp index de770b41e..5f6c9df48 100644 --- a/contrib/llvm/lib/MC/MCDisassembler/EDToken.cpp +++ b/contrib/llvm/lib/MC/MCDisassembler/EDToken.cpp @@ -87,14 +87,18 @@ int EDToken::registerID(unsigned ®isterID) const { int EDToken::tokenize(std::vector &tokens, std::string &str, - const char *operandOrder, + const signed char *operandOrder, EDDisassembler &disassembler) { SmallVector parsedOperands; SmallVector asmTokens; if (disassembler.parseInst(parsedOperands, asmTokens, str)) + { + for (unsigned i = 0, e = parsedOperands.size(); i != e; ++i) + delete parsedOperands[i]; return -1; - + } + SmallVectorImpl::iterator operandIterator; unsigned int operandIndex; SmallVectorImpl::iterator tokenIterator; diff --git a/contrib/llvm/lib/MC/MCDisassembler/EDToken.h b/contrib/llvm/lib/MC/MCDisassembler/EDToken.h index ba4670786..384079b72 100644 --- a/contrib/llvm/lib/MC/MCDisassembler/EDToken.h +++ b/contrib/llvm/lib/MC/MCDisassembler/EDToken.h @@ -125,7 +125,7 @@ struct EDToken { // assembly syntax static int tokenize(std::vector &tokens, std::string &str, - const char *operandOrder, + const signed char *operandOrder, EDDisassembler &disassembler); /// getString - Directs a character pointer to the string, returning 0 on diff --git a/contrib/llvm/lib/MC/MCDwarf.cpp b/contrib/llvm/lib/MC/MCDwarf.cpp index ad86db13d..4658a3093 100644 --- a/contrib/llvm/lib/MC/MCDwarf.cpp +++ b/contrib/llvm/lib/MC/MCDwarf.cpp @@ -7,17 +7,18 @@ // //===----------------------------------------------------------------------===// -#include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCDwarf.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCObjectFileInfo.h" +#include "llvm/MC/MCObjectWriter.h" +#include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCExpr.h" -#include "llvm/MC/MCContext.h" -#include "llvm/MC/MCObjectWriter.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/Target/TargetAsmInfo.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" @@ -196,7 +197,7 @@ static inline void EmitDwarfLineTable(MCStreamer *MCOS, MCOS->EmitLabel(SectionEnd); // Switch back the the dwarf line section. - MCOS->SwitchSection(context.getTargetAsmInfo().getDwarfLineSection()); + MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfLineSection()); const MCAsmInfo &asmInfo = MCOS->getContext().getAsmInfo(); MCOS->EmitDwarfAdvanceLineAddr(INT64_MAX, LastLabel, SectionEnd, @@ -209,7 +210,7 @@ static inline void EmitDwarfLineTable(MCStreamer *MCOS, void MCDwarfFileTable::Emit(MCStreamer *MCOS) { MCContext &context = MCOS->getContext(); // Switch to the section where the table will be emitted into. - MCOS->SwitchSection(context.getTargetAsmInfo().getDwarfLineSection()); + MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfLineSection()); // Create a symbol at the beginning of this section. MCSymbol *LineStartSym = context.CreateTempSymbol(); @@ -485,11 +486,11 @@ static void EmitPersonality(MCStreamer &streamer, const MCSymbol &symbol, } static const MachineLocation TranslateMachineLocation( - const TargetAsmInfo &TAI, + const MCRegisterInfo &MRI, const MachineLocation &Loc) { unsigned Reg = Loc.getReg() == MachineLocation::VirtualFP ? MachineLocation::VirtualFP : - unsigned(TAI.getDwarfRegNum(Loc.getReg(), true)); + unsigned(MRI.getDwarfRegNum(Loc.getReg(), true)); const MachineLocation &NewLoc = Loc.isReg() ? MachineLocation(Reg) : MachineLocation(Reg, Loc.getOffset()); return NewLoc; @@ -503,10 +504,11 @@ namespace { bool IsEH; const MCSymbol *SectionStart; public: - FrameEmitterImpl(bool usingCFI, bool isEH, const MCSymbol *sectionStart) : - CFAOffset(0), CIENum(0), UsingCFI(usingCFI), IsEH(isEH), - SectionStart(sectionStart) { - } + FrameEmitterImpl(bool usingCFI, bool isEH) + : CFAOffset(0), CIENum(0), UsingCFI(usingCFI), IsEH(isEH), + SectionStart(0) {} + + void setSectionStart(const MCSymbol *Label) { SectionStart = Label; } /// EmitCompactUnwind - Emit the unwind information in a compact way. If /// we're successful, return 'true'. Otherwise, return 'false' and it will @@ -687,11 +689,8 @@ void FrameEmitterImpl::EmitCFIInstructions(MCStreamer &streamer, /// normal CIE and FDE. bool FrameEmitterImpl::EmitCompactUnwind(MCStreamer &Streamer, const MCDwarfFrameInfo &Frame) { -#if 1 - return false; -#else MCContext &Context = Streamer.getContext(); - const TargetAsmInfo &TAI = Context.getTargetAsmInfo(); + const MCObjectFileInfo *MOFI = Context.getObjectFileInfo(); bool VerboseAsm = Streamer.isVerboseAsm(); // range-start range-length compact-unwind-enc personality-func lsda @@ -716,19 +715,17 @@ bool FrameEmitterImpl::EmitCompactUnwind(MCStreamer &Streamer, // .quad __gxx_personality // .quad except_tab1 - uint32_t Encoding = - TAI.getCompactUnwindEncoding(Frame.Instructions, - getDataAlignmentFactor(Streamer), IsEH); + uint32_t Encoding = Frame.CompactUnwindEncoding; if (!Encoding) return false; // The encoding needs to know we have an LSDA. if (Frame.Lsda) Encoding |= 0x40000000; - Streamer.SwitchSection(TAI.getCompactUnwindSection()); + Streamer.SwitchSection(MOFI->getCompactUnwindSection()); // Range Start - unsigned FDEEncoding = TAI.getFDEEncoding(UsingCFI); + unsigned FDEEncoding = MOFI->getFDEEncoding(UsingCFI); unsigned Size = getSizeForEncoding(Streamer, FDEEncoding); if (VerboseAsm) Streamer.AddComment("Range Start"); Streamer.EmitSymbolValue(Frame.Function, Size); @@ -745,6 +742,7 @@ bool FrameEmitterImpl::EmitCompactUnwind(MCStreamer &Streamer, Twine(llvm::utohexstr(Encoding))); Streamer.EmitIntValue(Encoding, Size); + // Personality Function Size = getSizeForEncoding(Streamer, dwarf::DW_EH_PE_absptr); if (VerboseAsm) Streamer.AddComment("Personality Function"); @@ -762,7 +760,6 @@ bool FrameEmitterImpl::EmitCompactUnwind(MCStreamer &Streamer, Streamer.EmitIntValue(0, Size); // No LSDA return true; -#endif } const MCSymbol &FrameEmitterImpl::EmitCIE(MCStreamer &streamer, @@ -771,11 +768,12 @@ const MCSymbol &FrameEmitterImpl::EmitCIE(MCStreamer &streamer, const MCSymbol *lsda, unsigned lsdaEncoding) { MCContext &context = streamer.getContext(); - const TargetAsmInfo &TAI = context.getTargetAsmInfo(); + const MCRegisterInfo &MRI = context.getRegisterInfo(); + const MCObjectFileInfo *MOFI = context.getObjectFileInfo(); bool verboseAsm = streamer.isVerboseAsm(); MCSymbol *sectionStart; - if (TAI.isFunctionEHFrameSymbolPrivate() || !IsEH) + if (MOFI->isFunctionEHFrameSymbolPrivate() || !IsEH) sectionStart = context.CreateTempSymbol(); else sectionStart = context.GetOrCreateSymbol(Twine("EH_frame") + Twine(CIENum)); @@ -824,7 +822,7 @@ const MCSymbol &FrameEmitterImpl::EmitCIE(MCStreamer &streamer, // Return Address Register if (verboseAsm) streamer.AddComment("CIE Return Address Column"); - streamer.EmitULEB128IntValue(TAI.getDwarfRARegNum(true)); + streamer.EmitULEB128IntValue(MRI.getDwarfRegNum(MRI.getRARegister(), true)); // Augmentation Data Length (optional) @@ -858,21 +856,22 @@ const MCSymbol &FrameEmitterImpl::EmitCIE(MCStreamer &streamer, EmitEncodingByte(streamer, lsdaEncoding, "LSDA Encoding"); // Encoding of the FDE pointers - EmitEncodingByte(streamer, TAI.getFDEEncoding(UsingCFI), + EmitEncodingByte(streamer, MOFI->getFDEEncoding(UsingCFI), "FDE Encoding"); } // Initial Instructions - const std::vector &Moves = TAI.getInitialFrameState(); + const MCAsmInfo &MAI = context.getAsmInfo(); + const std::vector &Moves = MAI.getInitialFrameState(); std::vector Instructions; for (int i = 0, n = Moves.size(); i != n; ++i) { MCSymbol *Label = Moves[i].getLabel(); const MachineLocation &Dst = - TranslateMachineLocation(TAI, Moves[i].getDestination()); + TranslateMachineLocation(MRI, Moves[i].getDestination()); const MachineLocation &Src = - TranslateMachineLocation(TAI, Moves[i].getSource()); + TranslateMachineLocation(MRI, Moves[i].getSource()); MCCFIInstruction Inst(Label, Dst, Src); Instructions.push_back(Inst); } @@ -893,10 +892,10 @@ MCSymbol *FrameEmitterImpl::EmitFDE(MCStreamer &streamer, MCContext &context = streamer.getContext(); MCSymbol *fdeStart = context.CreateTempSymbol(); MCSymbol *fdeEnd = context.CreateTempSymbol(); - const TargetAsmInfo &TAI = context.getTargetAsmInfo(); + const MCObjectFileInfo *MOFI = context.getObjectFileInfo(); bool verboseAsm = streamer.isVerboseAsm(); - if (!TAI.isFunctionEHFrameSymbolPrivate() && IsEH) { + if (IsEH && frame.Function && !MOFI->isFunctionEHFrameSymbolPrivate()) { MCSymbol *EHSym = context.GetOrCreateSymbol(frame.Function->getName() + Twine(".eh")); streamer.EmitEHSymAttributes(frame.Function, EHSym); @@ -925,7 +924,7 @@ MCSymbol *FrameEmitterImpl::EmitFDE(MCStreamer &streamer, streamer.EmitSymbolValue(&cieStart, 4); } - unsigned fdeEncoding = TAI.getFDEEncoding(UsingCFI); + unsigned fdeEncoding = MOFI->getFDEEncoding(UsingCFI); unsigned size = getSizeForEncoding(streamer, fdeEncoding); // PC Begin @@ -1011,26 +1010,34 @@ void MCDwarfFrameEmitter::Emit(MCStreamer &Streamer, bool UsingCFI, bool IsEH) { MCContext &Context = Streamer.getContext(); - const TargetAsmInfo &TAI = Context.getTargetAsmInfo(); - const MCSection &Section = IsEH ? *TAI.getEHFrameSection() : - *TAI.getDwarfFrameSection(); + MCObjectFileInfo *MOFI = + const_cast(Context.getObjectFileInfo()); + FrameEmitterImpl Emitter(UsingCFI, IsEH); + ArrayRef FrameArray = Streamer.getFrameInfos(); + + // Emit the compact unwind info if available. + // FIXME: This emits both the compact unwind and the old CIE/FDE + // information. Only one of those is needed. + if (IsEH && MOFI->getCompactUnwindSection()) + for (unsigned i = 0, n = Streamer.getNumFrameInfos(); i < n; ++i) { + const MCDwarfFrameInfo &Frame = Streamer.getFrameInfo(i); + if (!Frame.CompactUnwindEncoding) + Emitter.EmitCompactUnwind(Streamer, Frame); + } + + const MCSection &Section = IsEH ? *MOFI->getEHFrameSection() : + *MOFI->getDwarfFrameSection(); Streamer.SwitchSection(&Section); MCSymbol *SectionStart = Context.CreateTempSymbol(); Streamer.EmitLabel(SectionStart); + Emitter.setSectionStart(SectionStart); MCSymbol *FDEEnd = NULL; DenseMap CIEStarts; - FrameEmitterImpl Emitter(UsingCFI, IsEH, SectionStart); const MCSymbol *DummyDebugKey = NULL; - for (unsigned i = 0, n = Streamer.getNumFrameInfos(); i < n; ++i) { - const MCDwarfFrameInfo &Frame = Streamer.getFrameInfo(i); - if (IsEH && TAI.getCompactUnwindSection() && - Emitter.EmitCompactUnwind(Streamer, Frame)) { - FDEEnd = NULL; - continue; - } - + for (unsigned i = 0, n = FrameArray.size(); i < n; ++i) { + const MCDwarfFrameInfo &Frame = FrameArray[i]; CIEKey Key(Frame.Personality, Frame.PersonalityEncoding, Frame.LsdaEncoding); const MCSymbol *&CIEStart = IsEH ? CIEStarts[Key] : DummyDebugKey; diff --git a/contrib/llvm/lib/MC/MCELF.cpp b/contrib/llvm/lib/MC/MCELF.cpp index 2c3f8e8f7..dad2e7ba9 100644 --- a/contrib/llvm/lib/MC/MCELF.cpp +++ b/contrib/llvm/lib/MC/MCELF.cpp @@ -16,7 +16,6 @@ #include "llvm/MC/MCELFSymbolFlags.h" #include "llvm/MC/MCFixupKindInfo.h" #include "llvm/Support/ELF.h" -#include "llvm/Target/TargetAsmBackend.h" namespace llvm { diff --git a/contrib/llvm/lib/MC/MCELFStreamer.cpp b/contrib/llvm/lib/MC/MCELFStreamer.cpp index 49340edbe..9ada08ea9 100644 --- a/contrib/llvm/lib/MC/MCELFStreamer.cpp +++ b/contrib/llvm/lib/MC/MCELFStreamer.cpp @@ -21,11 +21,11 @@ #include "llvm/MC/MCSection.h" #include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCValue.h" +#include "llvm/MC/MCAsmBackend.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ELF.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/Target/TargetAsmBackend.h" using namespace llvm; @@ -53,8 +53,9 @@ void MCELFStreamer::EmitLabel(MCSymbol *Symbol) { void MCELFStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) { switch (Flag) { case MCAF_SyntaxUnified: return; // no-op here. - case MCAF_Code16: return; // no-op here. - case MCAF_Code32: return; // no-op here. + case MCAF_Code16: return; // Change parsing mode; no-op here. + case MCAF_Code32: return; // Change parsing mode; no-op here. + case MCAF_Code64: return; // Change parsing mode; no-op here. case MCAF_SubsectionsViaSymbols: getAssembler().setSubsectionsViaSymbols(true); return; @@ -219,14 +220,14 @@ void MCELFStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, SD.setSize(MCConstantExpr::Create(Size, getContext())); } -void MCELFStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size) { +void MCELFStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment) { // FIXME: Should this be caught and done earlier? MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol); MCELF::SetBinding(SD, ELF::STB_LOCAL); SD.setExternal(false); BindingExplicitlySet.insert(Symbol); - // FIXME: ByteAlignment is not needed here, but is required. - EmitCommonSymbol(Symbol, Size, 1); + EmitCommonSymbol(Symbol, Size, ByteAlignment); } void MCELFStreamer::EmitBytes(StringRef Data, unsigned AddrSpace) { @@ -374,10 +375,10 @@ void MCELFStreamer::Finish() { this->MCObjectStreamer::Finish(); } -MCStreamer *llvm::createELFStreamer(MCContext &Context, TargetAsmBackend &TAB, +MCStreamer *llvm::createELFStreamer(MCContext &Context, MCAsmBackend &MAB, raw_ostream &OS, MCCodeEmitter *CE, bool RelaxAll, bool NoExecStack) { - MCELFStreamer *S = new MCELFStreamer(Context, TAB, OS, CE); + MCELFStreamer *S = new MCELFStreamer(Context, MAB, OS, CE); if (RelaxAll) S->getAssembler().setRelaxAll(true); if (NoExecStack) diff --git a/contrib/llvm/lib/MC/MCELFStreamer.h b/contrib/llvm/lib/MC/MCELFStreamer.h index 855e7e9ca..10bf77580 100644 --- a/contrib/llvm/lib/MC/MCELFStreamer.h +++ b/contrib/llvm/lib/MC/MCELFStreamer.h @@ -25,11 +25,11 @@ namespace llvm { class MCELFStreamer : public MCObjectStreamer { public: - MCELFStreamer(MCContext &Context, TargetAsmBackend &TAB, + MCELFStreamer(MCContext &Context, MCAsmBackend &TAB, raw_ostream &OS, MCCodeEmitter *Emitter) : MCObjectStreamer(Context, TAB, OS, Emitter) {} - MCELFStreamer(MCContext &Context, TargetAsmBackend &TAB, + MCELFStreamer(MCContext &Context, MCAsmBackend &TAB, raw_ostream &OS, MCCodeEmitter *Emitter, MCAssembler *Assembler) : MCObjectStreamer(Context, TAB, OS, Emitter, Assembler) {} @@ -74,7 +74,8 @@ public: SD.setSize(Value); } - virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size); + virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment); virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = 0, unsigned Size = 0, unsigned ByteAlignment = 0) { diff --git a/contrib/llvm/lib/MC/MCExpr.cpp b/contrib/llvm/lib/MC/MCExpr.cpp index fcf1aabb5..da297fb1d 100644 --- a/contrib/llvm/lib/MC/MCExpr.cpp +++ b/contrib/llvm/lib/MC/MCExpr.cpp @@ -18,7 +18,6 @@ #include "llvm/MC/MCValue.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/Target/TargetAsmBackend.h" using namespace llvm; namespace { diff --git a/contrib/llvm/lib/MC/MCInstPrinter.cpp b/contrib/llvm/lib/MC/MCInstPrinter.cpp index 81a939ffa..2317a2891 100644 --- a/contrib/llvm/lib/MC/MCInstPrinter.cpp +++ b/contrib/llvm/lib/MC/MCInstPrinter.cpp @@ -8,7 +8,9 @@ //===----------------------------------------------------------------------===// #include "llvm/MC/MCInstPrinter.h" +#include "llvm/MC/MCAsmInfo.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Support/raw_ostream.h" using namespace llvm; MCInstPrinter::~MCInstPrinter() { @@ -23,3 +25,12 @@ StringRef MCInstPrinter::getOpcodeName(unsigned Opcode) const { void MCInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const { assert(0 && "Target should implement this"); } + +void MCInstPrinter::printAnnotation(raw_ostream &OS, StringRef Annot) { + if (!Annot.empty()) { + if (CommentStream) + (*CommentStream) << Annot; + else + OS << " " << MAI.getCommentString() << " " << Annot; + } +} diff --git a/contrib/llvm/lib/MC/MCInstrAnalysis.cpp b/contrib/llvm/lib/MC/MCInstrAnalysis.cpp new file mode 100644 index 000000000..7736702f3 --- /dev/null +++ b/contrib/llvm/lib/MC/MCInstrAnalysis.cpp @@ -0,0 +1,21 @@ +//===-- MCInstrAnalysis.cpp - InstrDesc target hooks ------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCInstrAnalysis.h" +using namespace llvm; + +uint64_t MCInstrAnalysis::evaluateBranch(const MCInst &Inst, uint64_t Addr, + uint64_t Size) const { + if (Inst.getNumOperands() == 0 || + Info->get(Inst.getOpcode()).OpInfo[0].OperandType != MCOI::OPERAND_PCREL) + return -1ULL; + + int64_t Imm = Inst.getOperand(0).getImm(); + return Addr+Size+Imm; +} diff --git a/contrib/llvm/lib/MC/MCLoggingStreamer.cpp b/contrib/llvm/lib/MC/MCLoggingStreamer.cpp index 309752ec5..3fe8ac72c 100644 --- a/contrib/llvm/lib/MC/MCLoggingStreamer.cpp +++ b/contrib/llvm/lib/MC/MCLoggingStreamer.cpp @@ -133,9 +133,10 @@ public: return Child->EmitCommonSymbol(Symbol, Size, ByteAlignment); } - virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size) { + virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment) { LogCall("EmitLocalCommonSymbol"); - return Child->EmitLocalCommonSymbol(Symbol, Size); + return Child->EmitLocalCommonSymbol(Symbol, Size, ByteAlignment); } virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = 0, diff --git a/contrib/llvm/lib/MC/MCMachOStreamer.cpp b/contrib/llvm/lib/MC/MCMachOStreamer.cpp index 1b21249ca..aa35815dd 100644 --- a/contrib/llvm/lib/MC/MCMachOStreamer.cpp +++ b/contrib/llvm/lib/MC/MCMachOStreamer.cpp @@ -20,10 +20,10 @@ #include "llvm/MC/MCMachOSymbolFlags.h" #include "llvm/MC/MCSectionMachO.h" #include "llvm/MC/MCDwarf.h" +#include "llvm/MC/MCAsmBackend.h" #include "llvm/Support/Dwarf.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/Target/TargetAsmBackend.h" using namespace llvm; @@ -34,9 +34,9 @@ private: virtual void EmitInstToData(const MCInst &Inst); public: - MCMachOStreamer(MCContext &Context, TargetAsmBackend &TAB, + MCMachOStreamer(MCContext &Context, MCAsmBackend &MAB, raw_ostream &OS, MCCodeEmitter *Emitter) - : MCObjectStreamer(Context, TAB, OS, Emitter) {} + : MCObjectStreamer(Context, MAB, OS, Emitter) {} /// @name MCStreamer Interface /// @{ @@ -67,7 +67,8 @@ public: virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) { assert(0 && "macho doesn't support this directive"); } - virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size) { + virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment) { assert(0 && "macho doesn't support this directive"); } virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = 0, @@ -143,8 +144,9 @@ void MCMachOStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) { // Do any generic stuff we need to do. switch (Flag) { case MCAF_SyntaxUnified: return; // no-op here. - case MCAF_Code16: return; // no-op here. - case MCAF_Code32: return; // no-op here. + case MCAF_Code16: return; // Change parsing mode; no-op here. + case MCAF_Code32: return; // Change parsing mode; no-op here. + case MCAF_Code64: return; // Change parsing mode; no-op here. case MCAF_SubsectionsViaSymbols: getAssembler().setSubsectionsViaSymbols(true); return; @@ -207,8 +209,8 @@ void MCMachOStreamer::EmitSymbolAttribute(MCSymbol *Symbol, case MCSA_ELF_TypeCommon: case MCSA_ELF_TypeNoType: case MCSA_ELF_TypeGnuUniqueObject: - case MCSA_IndirectSymbol: case MCSA_Hidden: + case MCSA_IndirectSymbol: case MCSA_Internal: case MCSA_Protected: case MCSA_Weak: @@ -410,10 +412,10 @@ void MCMachOStreamer::Finish() { this->MCObjectStreamer::Finish(); } -MCStreamer *llvm::createMachOStreamer(MCContext &Context, TargetAsmBackend &TAB, +MCStreamer *llvm::createMachOStreamer(MCContext &Context, MCAsmBackend &MAB, raw_ostream &OS, MCCodeEmitter *CE, bool RelaxAll) { - MCMachOStreamer *S = new MCMachOStreamer(Context, TAB, OS, CE); + MCMachOStreamer *S = new MCMachOStreamer(Context, MAB, OS, CE); if (RelaxAll) S->getAssembler().setRelaxAll(true); return S; diff --git a/contrib/llvm/lib/MC/MCModule.cpp b/contrib/llvm/lib/MC/MCModule.cpp new file mode 100644 index 000000000..b1d09d945 --- /dev/null +++ b/contrib/llvm/lib/MC/MCModule.cpp @@ -0,0 +1,45 @@ +//===- lib/MC/MCModule.cpp - MCModule implementation --------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCAtom.h" +#include "llvm/MC/MCModule.h" + +using namespace llvm; + +MCAtom *MCModule::createAtom(MCAtom::AtomType Type, + uint64_t Begin, uint64_t End) { + assert(Begin < End && "Creating MCAtom with endpoints reversed?"); + + // Check for atoms already covering this range. + IntervalMap::iterator I = OffsetMap.find(Begin); + assert((!I.valid() || I.start() < End) && "Offset range already occupied!"); + + // Create the new atom and add it to our maps. + MCAtom *NewAtom = new MCAtom(Type, this, Begin, End); + AtomAllocationTracker.insert(NewAtom); + OffsetMap.insert(Begin, End, NewAtom); + return NewAtom; +} + +// remap - Update the interval mapping for an atom. +void MCModule::remap(MCAtom *Atom, uint64_t NewBegin, uint64_t NewEnd) { + // Find and erase the old mapping. + IntervalMap::iterator I = OffsetMap.find(Atom->Begin); + assert(I.valid() && "Atom offset not found in module!"); + assert(*I == Atom && "Previous atom mapping was invalid!"); + I.erase(); + + // Insert the new mapping. + OffsetMap.insert(NewBegin, NewEnd, Atom); + + // Update the atom internal bounds. + Atom->Begin = NewBegin; + Atom->End = NewEnd; +} + diff --git a/contrib/llvm/lib/MC/MCNullStreamer.cpp b/contrib/llvm/lib/MC/MCNullStreamer.cpp index 9577af010..a6c0adb67 100644 --- a/contrib/llvm/lib/MC/MCNullStreamer.cpp +++ b/contrib/llvm/lib/MC/MCNullStreamer.cpp @@ -59,8 +59,8 @@ namespace { virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) {} virtual void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment) {} - virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size) {} - + virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment) {} virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = 0, unsigned Size = 0, unsigned ByteAlignment = 0) {} virtual void EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol, diff --git a/contrib/llvm/lib/MC/MCObjectFileInfo.cpp b/contrib/llvm/lib/MC/MCObjectFileInfo.cpp new file mode 100644 index 000000000..df8b99d2b --- /dev/null +++ b/contrib/llvm/lib/MC/MCObjectFileInfo.cpp @@ -0,0 +1,554 @@ +//===-- MObjectFileInfo.cpp - Object File Information ---------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCObjectFileInfo.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCSection.h" +#include "llvm/MC/MCSectionCOFF.h" +#include "llvm/MC/MCSectionELF.h" +#include "llvm/MC/MCSectionMachO.h" +#include "llvm/ADT/Triple.h" +using namespace llvm; + +void MCObjectFileInfo::InitMachOMCObjectFileInfo(Triple T) { + // MachO + IsFunctionEHFrameSymbolPrivate = false; + SupportsWeakOmittedEHFrame = false; + + PersonalityEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel + | dwarf::DW_EH_PE_sdata4; + LSDAEncoding = FDEEncoding = FDECFIEncoding = dwarf::DW_EH_PE_pcrel; + TTypeEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | + dwarf::DW_EH_PE_sdata4; + + // .comm doesn't support alignment before Leopard. + if (T.isMacOSX() && T.isMacOSXVersionLT(10, 5)) + CommDirectiveSupportsAlignment = false; + + TextSection // .text + = Ctx->getMachOSection("__TEXT", "__text", + MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, + SectionKind::getText()); + DataSection // .data + = Ctx->getMachOSection("__DATA", "__data", 0, + SectionKind::getDataRel()); + + TLSDataSection // .tdata + = Ctx->getMachOSection("__DATA", "__thread_data", + MCSectionMachO::S_THREAD_LOCAL_REGULAR, + SectionKind::getDataRel()); + TLSBSSSection // .tbss + = Ctx->getMachOSection("__DATA", "__thread_bss", + MCSectionMachO::S_THREAD_LOCAL_ZEROFILL, + SectionKind::getThreadBSS()); + + // TODO: Verify datarel below. + TLSTLVSection // .tlv + = Ctx->getMachOSection("__DATA", "__thread_vars", + MCSectionMachO::S_THREAD_LOCAL_VARIABLES, + SectionKind::getDataRel()); + + TLSThreadInitSection + = Ctx->getMachOSection("__DATA", "__thread_init", + MCSectionMachO::S_THREAD_LOCAL_INIT_FUNCTION_POINTERS, + SectionKind::getDataRel()); + + CStringSection // .cstring + = Ctx->getMachOSection("__TEXT", "__cstring", + MCSectionMachO::S_CSTRING_LITERALS, + SectionKind::getMergeable1ByteCString()); + UStringSection + = Ctx->getMachOSection("__TEXT","__ustring", 0, + SectionKind::getMergeable2ByteCString()); + FourByteConstantSection // .literal4 + = Ctx->getMachOSection("__TEXT", "__literal4", + MCSectionMachO::S_4BYTE_LITERALS, + SectionKind::getMergeableConst4()); + EightByteConstantSection // .literal8 + = Ctx->getMachOSection("__TEXT", "__literal8", + MCSectionMachO::S_8BYTE_LITERALS, + SectionKind::getMergeableConst8()); + + // ld_classic doesn't support .literal16 in 32-bit mode, and ld64 falls back + // to using it in -static mode. + SixteenByteConstantSection = 0; + if (RelocM != Reloc::Static && + T.getArch() != Triple::x86_64 && T.getArch() != Triple::ppc64) + SixteenByteConstantSection = // .literal16 + Ctx->getMachOSection("__TEXT", "__literal16", + MCSectionMachO::S_16BYTE_LITERALS, + SectionKind::getMergeableConst16()); + + ReadOnlySection // .const + = Ctx->getMachOSection("__TEXT", "__const", 0, + SectionKind::getReadOnly()); + + TextCoalSection + = Ctx->getMachOSection("__TEXT", "__textcoal_nt", + MCSectionMachO::S_COALESCED | + MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, + SectionKind::getText()); + ConstTextCoalSection + = Ctx->getMachOSection("__TEXT", "__const_coal", + MCSectionMachO::S_COALESCED, + SectionKind::getReadOnly()); + ConstDataSection // .const_data + = Ctx->getMachOSection("__DATA", "__const", 0, + SectionKind::getReadOnlyWithRel()); + DataCoalSection + = Ctx->getMachOSection("__DATA","__datacoal_nt", + MCSectionMachO::S_COALESCED, + SectionKind::getDataRel()); + DataCommonSection + = Ctx->getMachOSection("__DATA","__common", + MCSectionMachO::S_ZEROFILL, + SectionKind::getBSS()); + DataBSSSection + = Ctx->getMachOSection("__DATA","__bss", MCSectionMachO::S_ZEROFILL, + SectionKind::getBSS()); + + + LazySymbolPointerSection + = Ctx->getMachOSection("__DATA", "__la_symbol_ptr", + MCSectionMachO::S_LAZY_SYMBOL_POINTERS, + SectionKind::getMetadata()); + NonLazySymbolPointerSection + = Ctx->getMachOSection("__DATA", "__nl_symbol_ptr", + MCSectionMachO::S_NON_LAZY_SYMBOL_POINTERS, + SectionKind::getMetadata()); + + if (RelocM == Reloc::Static) { + StaticCtorSection + = Ctx->getMachOSection("__TEXT", "__constructor", 0, + SectionKind::getDataRel()); + StaticDtorSection + = Ctx->getMachOSection("__TEXT", "__destructor", 0, + SectionKind::getDataRel()); + } else { + StaticCtorSection + = Ctx->getMachOSection("__DATA", "__mod_init_func", + MCSectionMachO::S_MOD_INIT_FUNC_POINTERS, + SectionKind::getDataRel()); + StaticDtorSection + = Ctx->getMachOSection("__DATA", "__mod_term_func", + MCSectionMachO::S_MOD_TERM_FUNC_POINTERS, + SectionKind::getDataRel()); + } + + // Exception Handling. + LSDASection = Ctx->getMachOSection("__TEXT", "__gcc_except_tab", 0, + SectionKind::getReadOnlyWithRel()); + + if (T.isMacOSX() && !T.isMacOSXVersionLT(10, 6)) + CompactUnwindSection = + Ctx->getMachOSection("__LD", "__compact_unwind", + MCSectionMachO::S_ATTR_DEBUG, + SectionKind::getReadOnly()); + + // Debug Information. + DwarfAbbrevSection = + Ctx->getMachOSection("__DWARF", "__debug_abbrev", + MCSectionMachO::S_ATTR_DEBUG, + SectionKind::getMetadata()); + DwarfInfoSection = + Ctx->getMachOSection("__DWARF", "__debug_info", + MCSectionMachO::S_ATTR_DEBUG, + SectionKind::getMetadata()); + DwarfLineSection = + Ctx->getMachOSection("__DWARF", "__debug_line", + MCSectionMachO::S_ATTR_DEBUG, + SectionKind::getMetadata()); + DwarfFrameSection = + Ctx->getMachOSection("__DWARF", "__debug_frame", + MCSectionMachO::S_ATTR_DEBUG, + SectionKind::getMetadata()); + DwarfPubNamesSection = + Ctx->getMachOSection("__DWARF", "__debug_pubnames", + MCSectionMachO::S_ATTR_DEBUG, + SectionKind::getMetadata()); + DwarfPubTypesSection = + Ctx->getMachOSection("__DWARF", "__debug_pubtypes", + MCSectionMachO::S_ATTR_DEBUG, + SectionKind::getMetadata()); + DwarfStrSection = + Ctx->getMachOSection("__DWARF", "__debug_str", + MCSectionMachO::S_ATTR_DEBUG, + SectionKind::getMetadata()); + DwarfLocSection = + Ctx->getMachOSection("__DWARF", "__debug_loc", + MCSectionMachO::S_ATTR_DEBUG, + SectionKind::getMetadata()); + DwarfARangesSection = + Ctx->getMachOSection("__DWARF", "__debug_aranges", + MCSectionMachO::S_ATTR_DEBUG, + SectionKind::getMetadata()); + DwarfRangesSection = + Ctx->getMachOSection("__DWARF", "__debug_ranges", + MCSectionMachO::S_ATTR_DEBUG, + SectionKind::getMetadata()); + DwarfMacroInfoSection = + Ctx->getMachOSection("__DWARF", "__debug_macinfo", + MCSectionMachO::S_ATTR_DEBUG, + SectionKind::getMetadata()); + DwarfDebugInlineSection = + Ctx->getMachOSection("__DWARF", "__debug_inlined", + MCSectionMachO::S_ATTR_DEBUG, + SectionKind::getMetadata()); + + TLSExtraDataSection = TLSTLVSection; +} + +void MCObjectFileInfo::InitELFMCObjectFileInfo(Triple T) { + if (T.getArch() == Triple::x86) { + PersonalityEncoding = (RelocM == Reloc::PIC_) + ? dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4 + : dwarf::DW_EH_PE_absptr; + LSDAEncoding = (RelocM == Reloc::PIC_) + ? dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4 + : dwarf::DW_EH_PE_absptr; + FDEEncoding = FDECFIEncoding = (RelocM == Reloc::PIC_) + ? dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4 + : dwarf::DW_EH_PE_absptr; + TTypeEncoding = (RelocM == Reloc::PIC_) + ? dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4 + : dwarf::DW_EH_PE_absptr; + } else if (T.getArch() == Triple::x86_64) { + FDECFIEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4; + + if (RelocM == Reloc::PIC_) { + PersonalityEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | + ((CMModel == CodeModel::Small || CMModel == CodeModel::Medium) + ? dwarf::DW_EH_PE_sdata4 : dwarf::DW_EH_PE_sdata8); + LSDAEncoding = dwarf::DW_EH_PE_pcrel | + (CMModel == CodeModel::Small + ? dwarf::DW_EH_PE_sdata4 : dwarf::DW_EH_PE_sdata8); + FDEEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4; + TTypeEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | + ((CMModel == CodeModel::Small || CMModel == CodeModel::Medium) + ? dwarf::DW_EH_PE_sdata4 : dwarf::DW_EH_PE_sdata8); + } else { + PersonalityEncoding = + (CMModel == CodeModel::Small || CMModel == CodeModel::Medium) + ? dwarf::DW_EH_PE_udata4 : dwarf::DW_EH_PE_absptr; + LSDAEncoding = (CMModel == CodeModel::Small) + ? dwarf::DW_EH_PE_udata4 : dwarf::DW_EH_PE_absptr; + FDEEncoding = dwarf::DW_EH_PE_udata4; + TTypeEncoding = (CMModel == CodeModel::Small) + ? dwarf::DW_EH_PE_udata4 : dwarf::DW_EH_PE_absptr; + } + } + + // ELF + BSSSection = + Ctx->getELFSection(".bss", ELF::SHT_NOBITS, + ELF::SHF_WRITE |ELF::SHF_ALLOC, + SectionKind::getBSS()); + + TextSection = + Ctx->getELFSection(".text", ELF::SHT_PROGBITS, + ELF::SHF_EXECINSTR | + ELF::SHF_ALLOC, + SectionKind::getText()); + + DataSection = + Ctx->getELFSection(".data", ELF::SHT_PROGBITS, + ELF::SHF_WRITE |ELF::SHF_ALLOC, + SectionKind::getDataRel()); + + ReadOnlySection = + Ctx->getELFSection(".rodata", ELF::SHT_PROGBITS, + ELF::SHF_ALLOC, + SectionKind::getReadOnly()); + + TLSDataSection = + Ctx->getELFSection(".tdata", ELF::SHT_PROGBITS, + ELF::SHF_ALLOC | ELF::SHF_TLS | + ELF::SHF_WRITE, + SectionKind::getThreadData()); + + TLSBSSSection = + Ctx->getELFSection(".tbss", ELF::SHT_NOBITS, + ELF::SHF_ALLOC | ELF::SHF_TLS | + ELF::SHF_WRITE, + SectionKind::getThreadBSS()); + + DataRelSection = + Ctx->getELFSection(".data.rel", ELF::SHT_PROGBITS, + ELF::SHF_ALLOC |ELF::SHF_WRITE, + SectionKind::getDataRel()); + + DataRelLocalSection = + Ctx->getELFSection(".data.rel.local", ELF::SHT_PROGBITS, + ELF::SHF_ALLOC |ELF::SHF_WRITE, + SectionKind::getDataRelLocal()); + + DataRelROSection = + Ctx->getELFSection(".data.rel.ro", ELF::SHT_PROGBITS, + ELF::SHF_ALLOC |ELF::SHF_WRITE, + SectionKind::getReadOnlyWithRel()); + + DataRelROLocalSection = + Ctx->getELFSection(".data.rel.ro.local", ELF::SHT_PROGBITS, + ELF::SHF_ALLOC |ELF::SHF_WRITE, + SectionKind::getReadOnlyWithRelLocal()); + + MergeableConst4Section = + Ctx->getELFSection(".rodata.cst4", ELF::SHT_PROGBITS, + ELF::SHF_ALLOC |ELF::SHF_MERGE, + SectionKind::getMergeableConst4()); + + MergeableConst8Section = + Ctx->getELFSection(".rodata.cst8", ELF::SHT_PROGBITS, + ELF::SHF_ALLOC |ELF::SHF_MERGE, + SectionKind::getMergeableConst8()); + + MergeableConst16Section = + Ctx->getELFSection(".rodata.cst16", ELF::SHT_PROGBITS, + ELF::SHF_ALLOC |ELF::SHF_MERGE, + SectionKind::getMergeableConst16()); + + StaticCtorSection = + Ctx->getELFSection(".ctors", ELF::SHT_PROGBITS, + ELF::SHF_ALLOC |ELF::SHF_WRITE, + SectionKind::getDataRel()); + + StaticDtorSection = + Ctx->getELFSection(".dtors", ELF::SHT_PROGBITS, + ELF::SHF_ALLOC |ELF::SHF_WRITE, + SectionKind::getDataRel()); + + // Exception Handling Sections. + + // FIXME: We're emitting LSDA info into a readonly section on ELF, even though + // it contains relocatable pointers. In PIC mode, this is probably a big + // runtime hit for C++ apps. Either the contents of the LSDA need to be + // adjusted or this should be a data section. + LSDASection = + Ctx->getELFSection(".gcc_except_table", ELF::SHT_PROGBITS, + ELF::SHF_ALLOC, + SectionKind::getReadOnly()); + + // Debug Info Sections. + DwarfAbbrevSection = + Ctx->getELFSection(".debug_abbrev", ELF::SHT_PROGBITS, 0, + SectionKind::getMetadata()); + DwarfInfoSection = + Ctx->getELFSection(".debug_info", ELF::SHT_PROGBITS, 0, + SectionKind::getMetadata()); + DwarfLineSection = + Ctx->getELFSection(".debug_line", ELF::SHT_PROGBITS, 0, + SectionKind::getMetadata()); + DwarfFrameSection = + Ctx->getELFSection(".debug_frame", ELF::SHT_PROGBITS, 0, + SectionKind::getMetadata()); + DwarfPubNamesSection = + Ctx->getELFSection(".debug_pubnames", ELF::SHT_PROGBITS, 0, + SectionKind::getMetadata()); + DwarfPubTypesSection = + Ctx->getELFSection(".debug_pubtypes", ELF::SHT_PROGBITS, 0, + SectionKind::getMetadata()); + DwarfStrSection = + Ctx->getELFSection(".debug_str", ELF::SHT_PROGBITS, 0, + SectionKind::getMetadata()); + DwarfLocSection = + Ctx->getELFSection(".debug_loc", ELF::SHT_PROGBITS, 0, + SectionKind::getMetadata()); + DwarfARangesSection = + Ctx->getELFSection(".debug_aranges", ELF::SHT_PROGBITS, 0, + SectionKind::getMetadata()); + DwarfRangesSection = + Ctx->getELFSection(".debug_ranges", ELF::SHT_PROGBITS, 0, + SectionKind::getMetadata()); + DwarfMacroInfoSection = + Ctx->getELFSection(".debug_macinfo", ELF::SHT_PROGBITS, 0, + SectionKind::getMetadata()); +} + + +void MCObjectFileInfo::InitCOFFMCObjectFileInfo(Triple T) { + // COFF + TextSection = + Ctx->getCOFFSection(".text", + COFF::IMAGE_SCN_CNT_CODE | + COFF::IMAGE_SCN_MEM_EXECUTE | + COFF::IMAGE_SCN_MEM_READ, + SectionKind::getText()); + DataSection = + Ctx->getCOFFSection(".data", + COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | + COFF::IMAGE_SCN_MEM_READ | + COFF::IMAGE_SCN_MEM_WRITE, + SectionKind::getDataRel()); + ReadOnlySection = + Ctx->getCOFFSection(".rdata", + COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | + COFF::IMAGE_SCN_MEM_READ, + SectionKind::getReadOnly()); + StaticCtorSection = + Ctx->getCOFFSection(".ctors", + COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | + COFF::IMAGE_SCN_MEM_READ | + COFF::IMAGE_SCN_MEM_WRITE, + SectionKind::getDataRel()); + StaticDtorSection = + Ctx->getCOFFSection(".dtors", + COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | + COFF::IMAGE_SCN_MEM_READ | + COFF::IMAGE_SCN_MEM_WRITE, + SectionKind::getDataRel()); + + // FIXME: We're emitting LSDA info into a readonly section on COFF, even + // though it contains relocatable pointers. In PIC mode, this is probably a + // big runtime hit for C++ apps. Either the contents of the LSDA need to be + // adjusted or this should be a data section. + LSDASection = + Ctx->getCOFFSection(".gcc_except_table", + COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | + COFF::IMAGE_SCN_MEM_READ, + SectionKind::getReadOnly()); + + // Debug info. + DwarfAbbrevSection = + Ctx->getCOFFSection(".debug_abbrev", + COFF::IMAGE_SCN_MEM_DISCARDABLE | + COFF::IMAGE_SCN_MEM_READ, + SectionKind::getMetadata()); + DwarfInfoSection = + Ctx->getCOFFSection(".debug_info", + COFF::IMAGE_SCN_MEM_DISCARDABLE | + COFF::IMAGE_SCN_MEM_READ, + SectionKind::getMetadata()); + DwarfLineSection = + Ctx->getCOFFSection(".debug_line", + COFF::IMAGE_SCN_MEM_DISCARDABLE | + COFF::IMAGE_SCN_MEM_READ, + SectionKind::getMetadata()); + DwarfFrameSection = + Ctx->getCOFFSection(".debug_frame", + COFF::IMAGE_SCN_MEM_DISCARDABLE | + COFF::IMAGE_SCN_MEM_READ, + SectionKind::getMetadata()); + DwarfPubNamesSection = + Ctx->getCOFFSection(".debug_pubnames", + COFF::IMAGE_SCN_MEM_DISCARDABLE | + COFF::IMAGE_SCN_MEM_READ, + SectionKind::getMetadata()); + DwarfPubTypesSection = + Ctx->getCOFFSection(".debug_pubtypes", + COFF::IMAGE_SCN_MEM_DISCARDABLE | + COFF::IMAGE_SCN_MEM_READ, + SectionKind::getMetadata()); + DwarfStrSection = + Ctx->getCOFFSection(".debug_str", + COFF::IMAGE_SCN_MEM_DISCARDABLE | + COFF::IMAGE_SCN_MEM_READ, + SectionKind::getMetadata()); + DwarfLocSection = + Ctx->getCOFFSection(".debug_loc", + COFF::IMAGE_SCN_MEM_DISCARDABLE | + COFF::IMAGE_SCN_MEM_READ, + SectionKind::getMetadata()); + DwarfARangesSection = + Ctx->getCOFFSection(".debug_aranges", + COFF::IMAGE_SCN_MEM_DISCARDABLE | + COFF::IMAGE_SCN_MEM_READ, + SectionKind::getMetadata()); + DwarfRangesSection = + Ctx->getCOFFSection(".debug_ranges", + COFF::IMAGE_SCN_MEM_DISCARDABLE | + COFF::IMAGE_SCN_MEM_READ, + SectionKind::getMetadata()); + DwarfMacroInfoSection = + Ctx->getCOFFSection(".debug_macinfo", + COFF::IMAGE_SCN_MEM_DISCARDABLE | + COFF::IMAGE_SCN_MEM_READ, + SectionKind::getMetadata()); + + DrectveSection = + Ctx->getCOFFSection(".drectve", + COFF::IMAGE_SCN_LNK_INFO, + SectionKind::getMetadata()); + + PDataSection = + Ctx->getCOFFSection(".pdata", + COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | + COFF::IMAGE_SCN_MEM_READ | + COFF::IMAGE_SCN_MEM_WRITE, + SectionKind::getDataRel()); + + XDataSection = + Ctx->getCOFFSection(".xdata", + COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | + COFF::IMAGE_SCN_MEM_READ | + COFF::IMAGE_SCN_MEM_WRITE, + SectionKind::getDataRel()); +} + +void MCObjectFileInfo::InitMCObjectFileInfo(StringRef TT, Reloc::Model relocm, + CodeModel::Model cm, + MCContext &ctx) { + RelocM = relocm; + CMModel = cm; + Ctx = &ctx; + + // Common. + CommDirectiveSupportsAlignment = true; + SupportsWeakOmittedEHFrame = true; + IsFunctionEHFrameSymbolPrivate = true; + + PersonalityEncoding = LSDAEncoding = FDEEncoding = FDECFIEncoding = + TTypeEncoding = dwarf::DW_EH_PE_absptr; + + EHFrameSection = 0; // Created on demand. + CompactUnwindSection = 0; // Used only by selected targets. + + Triple T(TT); + Triple::ArchType Arch = T.getArch(); + // FIXME: Checking for Arch here to filter out bogus triples such as + // cellspu-apple-darwin. Perhaps we should fix in Triple? + if ((Arch == Triple::x86 || Arch == Triple::x86_64 || + Arch == Triple::arm || Arch == Triple::thumb || + Arch == Triple::ppc || Arch == Triple::ppc64 || + Arch == Triple::UnknownArch) && + (T.isOSDarwin() || T.getEnvironment() == Triple::MachO)) { + Env = IsMachO; + InitMachOMCObjectFileInfo(T); + } else if ((Arch == Triple::x86 || Arch == Triple::x86_64) && + (T.getOS() == Triple::MinGW32 || T.getOS() == Triple::Cygwin || + T.getOS() == Triple::Win32)) { + Env = IsCOFF; + InitCOFFMCObjectFileInfo(T); + } else { + Env = IsELF; + InitELFMCObjectFileInfo(T); + } +} + +void MCObjectFileInfo::InitEHFrameSection() { + if (Env == IsMachO) + EHFrameSection = + Ctx->getMachOSection("__TEXT", "__eh_frame", + MCSectionMachO::S_COALESCED | + MCSectionMachO::S_ATTR_NO_TOC | + MCSectionMachO::S_ATTR_STRIP_STATIC_SYMS | + MCSectionMachO::S_ATTR_LIVE_SUPPORT, + SectionKind::getReadOnly()); + else if (Env == IsELF) + EHFrameSection = + Ctx->getELFSection(".eh_frame", ELF::SHT_PROGBITS, + ELF::SHF_ALLOC, + SectionKind::getDataRel()); + else + EHFrameSection = + Ctx->getCOFFSection(".eh_frame", + COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | + COFF::IMAGE_SCN_MEM_READ | + COFF::IMAGE_SCN_MEM_WRITE, + SectionKind::getDataRel()); +} diff --git a/contrib/llvm/lib/MC/MCObjectStreamer.cpp b/contrib/llvm/lib/MC/MCObjectStreamer.cpp index 8635aac00..a04ae0812 100644 --- a/contrib/llvm/lib/MC/MCObjectStreamer.cpp +++ b/contrib/llvm/lib/MC/MCObjectStreamer.cpp @@ -17,10 +17,10 @@ #include "llvm/MC/MCDwarf.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCSymbol.h" -#include "llvm/Target/TargetAsmBackend.h" +#include "llvm/MC/MCAsmBackend.h" using namespace llvm; -MCObjectStreamer::MCObjectStreamer(MCContext &Context, TargetAsmBackend &TAB, +MCObjectStreamer::MCObjectStreamer(MCContext &Context, MCAsmBackend &TAB, raw_ostream &OS, MCCodeEmitter *Emitter_) : MCStreamer(Context), Assembler(new MCAssembler(Context, TAB, @@ -30,7 +30,7 @@ MCObjectStreamer::MCObjectStreamer(MCContext &Context, TargetAsmBackend &TAB, { } -MCObjectStreamer::MCObjectStreamer(MCContext &Context, TargetAsmBackend &TAB, +MCObjectStreamer::MCObjectStreamer(MCContext &Context, MCAsmBackend &TAB, raw_ostream &OS, MCCodeEmitter *Emitter_, MCAssembler *_Assembler) : MCStreamer(Context), Assembler(_Assembler), CurSectionData(0) diff --git a/contrib/llvm/lib/MC/MCParser/AsmLexer.cpp b/contrib/llvm/lib/MC/MCParser/AsmLexer.cpp index 0c1f8f0df..c76052d66 100644 --- a/contrib/llvm/lib/MC/MCParser/AsmLexer.cpp +++ b/contrib/llvm/lib/MC/MCParser/AsmLexer.cpp @@ -24,6 +24,7 @@ using namespace llvm; AsmLexer::AsmLexer(const MCAsmInfo &_MAI) : MAI(_MAI) { CurBuf = NULL; CurPtr = NULL; + isAtStartOfLine = true; } AsmLexer::~AsmLexer() { @@ -146,7 +147,7 @@ AsmToken AsmLexer::LexLineComment() { // FIXME: This is broken if we happen to a comment at the end of a file, which // was .included, and which doesn't end with a newline. int CurChar = getNextChar(); - while (CurChar != '\n' && CurChar != '\n' && CurChar != EOF) + while (CurChar != '\n' && CurChar != '\r' && CurChar != EOF) CurChar = getNextChar(); if (CurChar == EOF) @@ -334,6 +335,17 @@ StringRef AsmLexer::LexUntilEndOfStatement() { return StringRef(TokStart, CurPtr-TokStart); } +StringRef AsmLexer::LexUntilEndOfLine() { + TokStart = CurPtr; + + while (*CurPtr != '\n' && + *CurPtr != '\r' && + (*CurPtr != 0 || CurPtr != CurBuf->getBufferEnd())) { + ++CurPtr; + } + return StringRef(TokStart, CurPtr-TokStart); +} + bool AsmLexer::isAtStartOfComment(char Char) { // FIXME: This won't work for multi-character comment indicators like "//". return Char == *MAI.getCommentString(); @@ -349,14 +361,29 @@ AsmToken AsmLexer::LexToken() { // This always consumes at least one character. int CurChar = getNextChar(); - if (isAtStartOfComment(CurChar)) + if (isAtStartOfComment(CurChar)) { + // If this comment starts with a '#', then return the Hash token and let + // the assembler parser see if it can be parsed as a cpp line filename + // comment. We do this only if we are at the start of a line. + if (CurChar == '#' && isAtStartOfLine) + return AsmToken(AsmToken::Hash, StringRef(TokStart, 1)); + isAtStartOfLine = true; return LexLineComment(); + } if (isAtStatementSeparator(TokStart)) { CurPtr += strlen(MAI.getSeparatorString()) - 1; return AsmToken(AsmToken::EndOfStatement, StringRef(TokStart, strlen(MAI.getSeparatorString()))); } + // If we're missing a newline at EOF, make sure we still get an + // EndOfStatement token before the Eof token. + if (CurChar == EOF && !isAtStartOfLine) { + isAtStartOfLine = true; + return AsmToken(AsmToken::EndOfStatement, StringRef(TokStart, 1)); + } + + isAtStartOfLine = false; switch (CurChar) { default: // Handle identifier: [a-zA-Z_.][a-zA-Z0-9_$.@]* @@ -373,6 +400,7 @@ AsmToken AsmLexer::LexToken() { return LexToken(); case '\n': // FALL THROUGH. case '\r': + isAtStartOfLine = true; return AsmToken(AsmToken::EndOfStatement, StringRef(TokStart, 1)); case ':': return AsmToken(AsmToken::Colon, StringRef(TokStart, 1)); case '+': return AsmToken(AsmToken::Plus, StringRef(TokStart, 1)); diff --git a/contrib/llvm/lib/MC/MCParser/AsmParser.cpp b/contrib/llvm/lib/MC/MCParser/AsmParser.cpp index 0c181f396..16487579a 100644 --- a/contrib/llvm/lib/MC/MCParser/AsmParser.cpp +++ b/contrib/llvm/lib/MC/MCParser/AsmParser.cpp @@ -18,22 +18,22 @@ #include "llvm/ADT/Twine.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" +#include "llvm/MC/MCDwarf.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCParser/AsmCond.h" #include "llvm/MC/MCParser/AsmLexer.h" #include "llvm/MC/MCParser/MCAsmParser.h" #include "llvm/MC/MCParser/MCParsedAsmOperand.h" +#include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCSectionMachO.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" -#include "llvm/MC/MCDwarf.h" +#include "llvm/MC/MCTargetAsmParser.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/SourceMgr.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/Target/TargetAsmInfo.h" -#include "llvm/Target/TargetAsmParser.h" #include #include using namespace llvm; @@ -87,6 +87,8 @@ private: MCStreamer &Out; const MCAsmInfo &MAI; SourceMgr &SrcMgr; + SourceMgr::DiagHandlerTy SavedDiagHandler; + void *SavedDiagContext; MCAsmParserExtension *GenericParser; MCAsmParserExtension *PlatformParser; @@ -115,8 +117,13 @@ private: /// Flag tracking whether any errors have been encountered. unsigned HadError : 1; + /// The values from the last parsed cpp hash file line comment if any. + StringRef CppHashFilename; + int64_t CppHashLineNumber; + SMLoc CppHashLoc; + public: - AsmParser(const Target &T, SourceMgr &SM, MCContext &Ctx, MCStreamer &Out, + AsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out, const MCAsmInfo &MAI); ~AsmParser(); @@ -153,6 +160,8 @@ private: void CheckForValidSection(); bool ParseStatement(); + void EatToEndOfLine(); + bool ParseCppHashLineFilenameComment(const SMLoc &L); bool HandleMacroEntry(StringRef Name, SMLoc NameLoc, const Macro *M); bool expandMacro(SmallString<256> &Buf, StringRef Body, @@ -166,6 +175,7 @@ private: bool ShowLine = true) const { SrcMgr.PrintMessage(Loc, Msg, Type, ShowLine); } + static void DiagHandler(const SMDiagnostic &Diag, void *Context); /// EnterIncludeFile - Enter the specified file. This returns true on failure. bool EnterIncludeFile(const std::string &Filename); @@ -338,11 +348,16 @@ extern MCAsmParserExtension *createCOFFAsmParser(); enum { DEFAULT_ADDRSPACE = 0 }; -AsmParser::AsmParser(const Target &T, SourceMgr &_SM, MCContext &_Ctx, +AsmParser::AsmParser(SourceMgr &_SM, MCContext &_Ctx, MCStreamer &_Out, const MCAsmInfo &_MAI) : Lexer(_MAI), Ctx(_Ctx), Out(_Out), MAI(_MAI), SrcMgr(_SM), GenericParser(new GenericAsmParser), PlatformParser(0), - CurBuffer(0), MacrosEnabled(true) { + CurBuffer(0), MacrosEnabled(true), CppHashLineNumber(0) { + // Save the old handler. + SavedDiagHandler = SrcMgr.getDiagHandler(); + SavedDiagContext = SrcMgr.getDiagContext(); + // Set our own handler which calls the saved handler. + SrcMgr.setDiagHandler(DiagHandler, this); Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)); // Initialize the generic parser. @@ -740,9 +755,12 @@ AsmParser::ApplyModifierToExpr(const MCExpr *E, /// ParseExpression - Parse an expression and return it. /// -/// expr ::= expr +,- expr -> lowest. -/// expr ::= expr |,^,&,! expr -> middle. -/// expr ::= expr *,/,%,<<,>> expr -> highest. +/// expr ::= expr &&,|| expr -> lowest. +/// expr ::= expr |,^,&,! expr +/// expr ::= expr ==,!=,<>,<,<=,>,>= expr +/// expr ::= expr <<,>> expr +/// expr ::= expr +,- expr +/// expr ::= expr *,/,% expr -> highest. /// expr ::= primaryexpr /// bool AsmParser::ParseExpression(const MCExpr *&Res, SMLoc &EndLoc) { @@ -809,7 +827,7 @@ static unsigned getBinOpPrecedence(AsmToken::TokenKind K, default: return 0; // not a binop. - // Lowest Precedence: &&, ||, @ + // Lowest Precedence: &&, || case AsmToken::AmpAmp: Kind = MCBinaryExpr::LAnd; return 1; @@ -852,30 +870,32 @@ static unsigned getBinOpPrecedence(AsmToken::TokenKind K, Kind = MCBinaryExpr::GTE; return 3; + // Intermediate Precedence: <<, >> + case AsmToken::LessLess: + Kind = MCBinaryExpr::Shl; + return 4; + case AsmToken::GreaterGreater: + Kind = MCBinaryExpr::Shr; + return 4; + // High Intermediate Precedence: +, - case AsmToken::Plus: Kind = MCBinaryExpr::Add; - return 4; + return 5; case AsmToken::Minus: Kind = MCBinaryExpr::Sub; - return 4; + return 5; - // Highest Precedence: *, /, %, <<, >> + // Highest Precedence: *, /, % case AsmToken::Star: Kind = MCBinaryExpr::Mul; - return 5; + return 6; case AsmToken::Slash: Kind = MCBinaryExpr::Div; - return 5; + return 6; case AsmToken::Percent: Kind = MCBinaryExpr::Mod; - return 5; - case AsmToken::LessLess: - Kind = MCBinaryExpr::Shl; - return 5; - case AsmToken::GreaterGreater: - Kind = MCBinaryExpr::Shr; - return 5; + return 6; } } @@ -932,10 +952,8 @@ bool AsmParser::ParseStatement() { StringRef IDVal; int64_t LocalLabelVal = -1; // A full line comment is a '#' as the first token. - if (Lexer.is(AsmToken::Hash)) { - EatToEndOfStatement(); - return false; - } + if (Lexer.is(AsmToken::Hash)) + return ParseCppHashLineFilenameComment(IDLoc); // Allow an integer followed by a ':' as a directional local label. if (Lexer.is(AsmToken::Integer)) { @@ -1117,15 +1135,8 @@ bool AsmParser::ParseStatement() { if (IDVal == ".globl" || IDVal == ".global") return ParseDirectiveSymbolAttribute(MCSA_Global); - // ELF only? Should it be here? - if (IDVal == ".local") - return ParseDirectiveSymbolAttribute(MCSA_Local); - if (IDVal == ".hidden") - return ParseDirectiveSymbolAttribute(MCSA_Hidden); if (IDVal == ".indirect_symbol") return ParseDirectiveSymbolAttribute(MCSA_IndirectSymbol); - if (IDVal == ".internal") - return ParseDirectiveSymbolAttribute(MCSA_Internal); if (IDVal == ".lazy_reference") return ParseDirectiveSymbolAttribute(MCSA_LazyReference); if (IDVal == ".no_dead_strip") @@ -1134,12 +1145,8 @@ bool AsmParser::ParseStatement() { return ParseDirectiveSymbolAttribute(MCSA_SymbolResolver); if (IDVal == ".private_extern") return ParseDirectiveSymbolAttribute(MCSA_PrivateExtern); - if (IDVal == ".protected") - return ParseDirectiveSymbolAttribute(MCSA_Protected); if (IDVal == ".reference") return ParseDirectiveSymbolAttribute(MCSA_Reference); - if (IDVal == ".weak") - return ParseDirectiveSymbolAttribute(MCSA_Weak); if (IDVal == ".weak_definition") return ParseDirectiveSymbolAttribute(MCSA_WeakDefinition); if (IDVal == ".weak_reference") @@ -1157,7 +1164,7 @@ bool AsmParser::ParseStatement() { if (IDVal == ".include") return ParseDirectiveInclude(); - if (IDVal == ".code16" || IDVal == ".code32" || IDVal == ".code64") + if (IDVal == ".code16") return TokError(Twine(IDVal) + " not supported yet"); // Look up the handler in the handler table. @@ -1215,6 +1222,108 @@ bool AsmParser::ParseStatement() { return false; } +/// EatToEndOfLine uses the Lexer to eat the characters to the end of the line +/// since they may not be able to be tokenized to get to the end of line token. +void AsmParser::EatToEndOfLine() { + if (!Lexer.is(AsmToken::EndOfStatement)) + Lexer.LexUntilEndOfLine(); + // Eat EOL. + Lex(); +} + +/// ParseCppHashLineFilenameComment as this: +/// ::= # number "filename" +/// or just as a full line comment if it doesn't have a number and a string. +bool AsmParser::ParseCppHashLineFilenameComment(const SMLoc &L) { + Lex(); // Eat the hash token. + + if (getLexer().isNot(AsmToken::Integer)) { + // Consume the line since in cases it is not a well-formed line directive, + // as if were simply a full line comment. + EatToEndOfLine(); + return false; + } + + int64_t LineNumber = getTok().getIntVal(); + Lex(); + + if (getLexer().isNot(AsmToken::String)) { + EatToEndOfLine(); + return false; + } + + StringRef Filename = getTok().getString(); + // Get rid of the enclosing quotes. + Filename = Filename.substr(1, Filename.size()-2); + + // Save the SMLoc, Filename and LineNumber for later use by diagnostics. + CppHashLoc = L; + CppHashFilename = Filename; + CppHashLineNumber = LineNumber; + + // Ignore any trailing characters, they're just comment. + EatToEndOfLine(); + return false; +} + +/// DiagHandler - will use the the last parsed cpp hash line filename comment +/// for the Filename and LineNo if any in the diagnostic. +void AsmParser::DiagHandler(const SMDiagnostic &Diag, void *Context) { + const AsmParser *Parser = static_cast(Context); + raw_ostream &OS = errs(); + + const SourceMgr &DiagSrcMgr = *Diag.getSourceMgr(); + const SMLoc &DiagLoc = Diag.getLoc(); + int DiagBuf = DiagSrcMgr.FindBufferContainingLoc(DiagLoc); + int CppHashBuf = Parser->SrcMgr.FindBufferContainingLoc(Parser->CppHashLoc); + + // Like SourceMgr::PrintMessage() we need to print the include stack if any + // before printing the message. + int DiagCurBuffer = DiagSrcMgr.FindBufferContainingLoc(DiagLoc); + if (!Parser->SavedDiagHandler && DiagCurBuffer > 0) { + SMLoc ParentIncludeLoc = DiagSrcMgr.getParentIncludeLoc(DiagCurBuffer); + DiagSrcMgr.PrintIncludeStack(ParentIncludeLoc, OS); + } + + // If we have not parsed a cpp hash line filename comment or the source + // manager changed or buffer changed (like in a nested include) then just + // print the normal diagnostic using its Filename and LineNo. + if (!Parser->CppHashLineNumber || + &DiagSrcMgr != &Parser->SrcMgr || + DiagBuf != CppHashBuf) { + if (Parser->SavedDiagHandler) + Parser->SavedDiagHandler(Diag, Parser->SavedDiagContext); + else + Diag.Print(0, OS); + return; + } + + // Use the CppHashFilename and calculate a line number based on the + // CppHashLoc and CppHashLineNumber relative to this Diag's SMLoc for + // the diagnostic. + const std::string Filename = Parser->CppHashFilename; + + int DiagLocLineNo = DiagSrcMgr.FindLineNumber(DiagLoc, DiagBuf); + int CppHashLocLineNo = + Parser->SrcMgr.FindLineNumber(Parser->CppHashLoc, CppHashBuf); + int LineNo = Parser->CppHashLineNumber - 1 + + (DiagLocLineNo - CppHashLocLineNo); + + SMDiagnostic NewDiag(*Diag.getSourceMgr(), + Diag.getLoc(), + Filename, + LineNo, + Diag.getColumnNo(), + Diag.getMessage(), + Diag.getLineContents(), + Diag.getShowLine()); + + if (Parser->SavedDiagHandler) + Parser->SavedDiagHandler(NewDiag, Parser->SavedDiagContext); + else + NewDiag.Print(0, OS); +} + bool AsmParser::expandMacro(SmallString<256> &Buf, StringRef Body, const std::vector &Parameters, const std::vector > &A, @@ -1923,12 +2032,17 @@ bool AsmParser::ParseDirectiveSymbolAttribute(MCSymbolAttr Attr) { if (getLexer().isNot(AsmToken::EndOfStatement)) { for (;;) { StringRef Name; + SMLoc Loc = getTok().getLoc(); if (ParseIdentifier(Name)) - return TokError("expected identifier in directive"); + return Error(Loc, "expected identifier in directive"); MCSymbol *Sym = getContext().GetOrCreateSymbol(Name); + // Assembler local symbols don't make any sense here. Complain loudly. + if (Sym->isTemporary()) + return Error(Loc, "non-local symbol required in directive"); + getStreamer().EmitSymbolAttribute(Sym, Attr); if (getLexer().is(AsmToken::EndOfStatement)) @@ -2416,7 +2530,7 @@ bool GenericAsmParser::ParseRegisterOrRegisterNumber(int64_t &Register, if (getParser().getTargetParser().ParseRegister(RegNo, DirectiveLoc, DirectiveLoc)) return true; - Register = getContext().getTargetAsmInfo().getDwarfRegNum(RegNo, true); + Register = getContext().getRegisterInfo().getDwarfRegNum(RegNo, true); } else return getParser().ParseAbsoluteExpression(Register); @@ -2724,8 +2838,8 @@ bool GenericAsmParser::ParseDirectiveLEB128(StringRef DirName, SMLoc) { /// \brief Create an MCAsmParser instance. -MCAsmParser *llvm::createMCAsmParser(const Target &T, SourceMgr &SM, +MCAsmParser *llvm::createMCAsmParser(SourceMgr &SM, MCContext &C, MCStreamer &Out, const MCAsmInfo &MAI) { - return new AsmParser(T, SM, C, Out, MAI); + return new AsmParser(SM, C, Out, MAI); } diff --git a/contrib/llvm/lib/MC/MCParser/COFFAsmParser.cpp b/contrib/llvm/lib/MC/MCParser/COFFAsmParser.cpp index 66ad384c7..185b5168b 100644 --- a/contrib/llvm/lib/MC/MCParser/COFFAsmParser.cpp +++ b/contrib/llvm/lib/MC/MCParser/COFFAsmParser.cpp @@ -8,15 +8,16 @@ //===----------------------------------------------------------------------===// #include "llvm/MC/MCParser/MCAsmParserExtension.h" +#include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Twine.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCParser/MCAsmLexer.h" +#include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCSectionCOFF.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCExpr.h" -#include "llvm/Target/TargetAsmInfo.h" -#include "llvm/Target/TargetAsmParser.h" +#include "llvm/MC/MCTargetAsmParser.h" #include "llvm/Support/COFF.h" using namespace llvm; @@ -72,6 +73,7 @@ class COFFAsmParser : public MCAsmParserExtension { ".seh_pushframe"); AddDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProlog>( ".seh_endprologue"); + AddDirectiveHandler<&COFFAsmParser::ParseDirectiveSymbolAttribute>(".weak"); } bool ParseSectionDirectiveText(StringRef, SMLoc) { @@ -118,12 +120,44 @@ class COFFAsmParser : public MCAsmParserExtension { bool ParseAtUnwindOrAtExcept(bool &unwind, bool &except); bool ParseSEHRegisterNumber(unsigned &RegNo); + bool ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc); public: COFFAsmParser() {} }; } // end annonomous namespace. +/// ParseDirectiveSymbolAttribute +/// ::= { ".weak", ... } [ identifier ( , identifier )* ] +bool COFFAsmParser::ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) { + MCSymbolAttr Attr = StringSwitch(Directive) + .Case(".weak", MCSA_Weak) + .Default(MCSA_Invalid); + assert(Attr != MCSA_Invalid && "unexpected symbol attribute directive!"); + if (getLexer().isNot(AsmToken::EndOfStatement)) { + for (;;) { + StringRef Name; + + if (getParser().ParseIdentifier(Name)) + return TokError("expected identifier in directive"); + + MCSymbol *Sym = getContext().GetOrCreateSymbol(Name); + + getStreamer().EmitSymbolAttribute(Sym, Attr); + + if (getLexer().is(AsmToken::EndOfStatement)) + break; + + if (getLexer().isNot(AsmToken::Comma)) + return TokError("unexpected token in directive"); + Lex(); + } + } + + Lex(); + return false; +} + bool COFFAsmParser::ParseSectionSwitch(StringRef Section, unsigned Characteristics, SectionKind Kind) { @@ -401,12 +435,16 @@ bool COFFAsmParser::ParseAtUnwindOrAtExcept(bool &unwind, bool &except) { bool COFFAsmParser::ParseSEHRegisterNumber(unsigned &RegNo) { SMLoc startLoc = getLexer().getLoc(); if (getLexer().is(AsmToken::Percent)) { - const TargetAsmInfo &TAI = getContext().getTargetAsmInfo(); + const MCRegisterInfo &MRI = getContext().getRegisterInfo(); SMLoc endLoc; unsigned LLVMRegNo; if (getParser().getTargetParser().ParseRegister(LLVMRegNo,startLoc,endLoc)) return true; +#if 0 + // FIXME: TargetAsmInfo::getCalleeSavedRegs() commits a serious layering + // violation so this validation code is disabled. + // Check that this is a non-volatile register. const unsigned *NVRegs = TAI.getCalleeSavedRegs(); unsigned i; @@ -415,8 +453,9 @@ bool COFFAsmParser::ParseSEHRegisterNumber(unsigned &RegNo) { break; if (NVRegs[i] == 0) return Error(startLoc, "expected non-volatile register"); +#endif - int SEHRegNo = TAI.getSEHRegNum(LLVMRegNo); + int SEHRegNo = MRI.getSEHRegNum(LLVMRegNo); if (SEHRegNo < 0) return Error(startLoc,"register can't be represented in SEH unwind info"); RegNo = SEHRegNo; diff --git a/contrib/llvm/lib/MC/MCParser/ELFAsmParser.cpp b/contrib/llvm/lib/MC/MCParser/ELFAsmParser.cpp index dcf689a6f..d89112645 100644 --- a/contrib/llvm/lib/MC/MCParser/ELFAsmParser.cpp +++ b/contrib/llvm/lib/MC/MCParser/ELFAsmParser.cpp @@ -47,12 +47,17 @@ public: AddDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveRoData>(".rodata"); AddDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveTData>(".tdata"); AddDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveTBSS>(".tbss"); - AddDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveDataRel>(".data.rel"); - AddDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveDataRelRo>(".data.rel.ro"); - AddDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveDataRelRoLocal>(".data.rel.ro.local"); - AddDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveEhFrame>(".eh_frame"); + AddDirectiveHandler< + &ELFAsmParser::ParseSectionDirectiveDataRel>(".data.rel"); + AddDirectiveHandler< + &ELFAsmParser::ParseSectionDirectiveDataRelRo>(".data.rel.ro"); + AddDirectiveHandler< + &ELFAsmParser::ParseSectionDirectiveDataRelRoLocal>(".data.rel.ro.local"); + AddDirectiveHandler< + &ELFAsmParser::ParseSectionDirectiveEhFrame>(".eh_frame"); AddDirectiveHandler<&ELFAsmParser::ParseDirectiveSection>(".section"); - AddDirectiveHandler<&ELFAsmParser::ParseDirectivePushSection>(".pushsection"); + AddDirectiveHandler< + &ELFAsmParser::ParseDirectivePushSection>(".pushsection"); AddDirectiveHandler<&ELFAsmParser::ParseDirectivePopSection>(".popsection"); AddDirectiveHandler<&ELFAsmParser::ParseDirectiveSize>(".size"); AddDirectiveHandler<&ELFAsmParser::ParseDirectivePrevious>(".previous"); @@ -60,6 +65,14 @@ public: AddDirectiveHandler<&ELFAsmParser::ParseDirectiveIdent>(".ident"); AddDirectiveHandler<&ELFAsmParser::ParseDirectiveSymver>(".symver"); AddDirectiveHandler<&ELFAsmParser::ParseDirectiveWeakref>(".weakref"); + AddDirectiveHandler<&ELFAsmParser::ParseDirectiveSymbolAttribute>(".weak"); + AddDirectiveHandler<&ELFAsmParser::ParseDirectiveSymbolAttribute>(".local"); + AddDirectiveHandler< + &ELFAsmParser::ParseDirectiveSymbolAttribute>(".protected"); + AddDirectiveHandler< + &ELFAsmParser::ParseDirectiveSymbolAttribute>(".internal"); + AddDirectiveHandler< + &ELFAsmParser::ParseDirectiveSymbolAttribute>(".hidden"); } // FIXME: Part of this logic is duplicated in the MCELFStreamer. What is @@ -129,6 +142,7 @@ public: bool ParseDirectiveIdent(StringRef, SMLoc); bool ParseDirectiveSymver(StringRef, SMLoc); bool ParseDirectiveWeakref(StringRef, SMLoc); + bool ParseDirectiveSymbolAttribute(StringRef, SMLoc); private: bool ParseSectionName(StringRef &SectionName); @@ -136,6 +150,41 @@ private: } +/// ParseDirectiveSymbolAttribute +/// ::= { ".local", ".weak", ... } [ identifier ( , identifier )* ] +bool ELFAsmParser::ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) { + MCSymbolAttr Attr = StringSwitch(Directive) + .Case(".weak", MCSA_Weak) + .Case(".local", MCSA_Local) + .Case(".hidden", MCSA_Hidden) + .Case(".internal", MCSA_Internal) + .Case(".protected", MCSA_Protected) + .Default(MCSA_Invalid); + assert(Attr != MCSA_Invalid && "unexpected symbol attribute directive!"); + if (getLexer().isNot(AsmToken::EndOfStatement)) { + for (;;) { + StringRef Name; + + if (getParser().ParseIdentifier(Name)) + return TokError("expected identifier in directive"); + + MCSymbol *Sym = getContext().GetOrCreateSymbol(Name); + + getStreamer().EmitSymbolAttribute(Sym, Attr); + + if (getLexer().is(AsmToken::EndOfStatement)) + break; + + if (getLexer().isNot(AsmToken::Comma)) + return TokError("unexpected token in directive"); + Lex(); + } + } + + Lex(); + return false; +} + bool ELFAsmParser::ParseSectionSwitch(StringRef Section, unsigned Type, unsigned Flags, SectionKind Kind) { if (getLexer().isNot(AsmToken::EndOfStatement)) diff --git a/contrib/llvm/lib/MC/MCParser/MCAsmParser.cpp b/contrib/llvm/lib/MC/MCParser/MCAsmParser.cpp index 4030e4103..5239ec753 100644 --- a/contrib/llvm/lib/MC/MCParser/MCAsmParser.cpp +++ b/contrib/llvm/lib/MC/MCParser/MCAsmParser.cpp @@ -8,13 +8,13 @@ //===----------------------------------------------------------------------===// #include "llvm/MC/MCParser/MCAsmParser.h" -#include "llvm/ADT/Twine.h" #include "llvm/MC/MCParser/MCAsmLexer.h" #include "llvm/MC/MCParser/MCParsedAsmOperand.h" +#include "llvm/MC/MCTargetAsmParser.h" #include "llvm/Support/SourceMgr.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Support/Debug.h" -#include "llvm/Target/TargetAsmParser.h" +#include "llvm/ADT/Twine.h" using namespace llvm; MCAsmParser::MCAsmParser() : TargetParser(0), ShowParsedOperands(0) { @@ -23,7 +23,7 @@ MCAsmParser::MCAsmParser() : TargetParser(0), ShowParsedOperands(0) { MCAsmParser::~MCAsmParser() { } -void MCAsmParser::setTargetParser(TargetAsmParser &P) { +void MCAsmParser::setTargetParser(MCTargetAsmParser &P) { assert(!TargetParser && "Target parser is already initialized!"); TargetParser = &P; TargetParser->Initialize(*this); diff --git a/contrib/llvm/lib/MC/MCParser/TargetAsmParser.cpp b/contrib/llvm/lib/MC/MCParser/MCTargetAsmParser.cpp similarity index 64% rename from contrib/llvm/lib/MC/MCParser/TargetAsmParser.cpp rename to contrib/llvm/lib/MC/MCParser/MCTargetAsmParser.cpp index 512f6b044..6fb1ba421 100644 --- a/contrib/llvm/lib/MC/MCParser/TargetAsmParser.cpp +++ b/contrib/llvm/lib/MC/MCParser/MCTargetAsmParser.cpp @@ -1,4 +1,4 @@ -//===-- TargetAsmParser.cpp - Target Assembly Parser -----------------------==// +//===-- MCTargetAsmParser.cpp - Target Assembly Parser ---------------------==// // // The LLVM Compiler Infrastructure // @@ -7,13 +7,13 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Target/TargetAsmParser.h" +#include "llvm/MC/MCTargetAsmParser.h" using namespace llvm; -TargetAsmParser::TargetAsmParser() +MCTargetAsmParser::MCTargetAsmParser() : AvailableFeatures(0) { } -TargetAsmParser::~TargetAsmParser() { +MCTargetAsmParser::~MCTargetAsmParser() { } diff --git a/contrib/llvm/lib/MC/MCPureStreamer.cpp b/contrib/llvm/lib/MC/MCPureStreamer.cpp index 6098e6b8f..086c9229b 100644 --- a/contrib/llvm/lib/MC/MCPureStreamer.cpp +++ b/contrib/llvm/lib/MC/MCPureStreamer.cpp @@ -28,7 +28,7 @@ private: virtual void EmitInstToData(const MCInst &Inst); public: - MCPureStreamer(MCContext &Context, TargetAsmBackend &TAB, + MCPureStreamer(MCContext &Context, MCAsmBackend &TAB, raw_ostream &OS, MCCodeEmitter *Emitter) : MCObjectStreamer(Context, TAB, OS, Emitter) {} @@ -86,7 +86,8 @@ public: virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) { report_fatal_error("unsupported directive in pure streamer"); } - virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size) { + virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment) { report_fatal_error("unsupported directive in pure streamer"); } virtual void EmitFileDirective(StringRef Filename) { @@ -228,7 +229,7 @@ void MCPureStreamer::Finish() { this->MCObjectStreamer::Finish(); } -MCStreamer *llvm::createPureStreamer(MCContext &Context, TargetAsmBackend &TAB, +MCStreamer *llvm::createPureStreamer(MCContext &Context, MCAsmBackend &MAB, raw_ostream &OS, MCCodeEmitter *CE) { - return new MCPureStreamer(Context, TAB, OS, CE); + return new MCPureStreamer(Context, MAB, OS, CE); } diff --git a/contrib/llvm/lib/MC/MCStreamer.cpp b/contrib/llvm/lib/MC/MCStreamer.cpp index 6e96b78e3..3afa22b0d 100644 --- a/contrib/llvm/lib/MC/MCStreamer.cpp +++ b/contrib/llvm/lib/MC/MCStreamer.cpp @@ -16,13 +16,17 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/Twine.h" #include using namespace llvm; MCStreamer::MCStreamer(MCContext &Ctx) : Context(Ctx), EmitEHFrame(true), EmitDebugFrame(false), - CurrentW64UnwindInfo(0) { + CurrentW64UnwindInfo(0), + LastSymbol(0), + UniqueCodeBeginSuffix(0), + UniqueDataBeginSuffix(0) { const MCSection *section = NULL; SectionStack.push_back(std::make_pair(section, section)); } @@ -171,10 +175,94 @@ void MCStreamer::EmitLabel(MCSymbol *Symbol) { assert(!Symbol->isVariable() && "Cannot emit a variable symbol!"); assert(getCurrentSection() && "Cannot emit before setting section!"); Symbol->setSection(*getCurrentSection()); + LastSymbol = Symbol; +} - StringRef Prefix = getContext().getAsmInfo().getPrivateGlobalPrefix(); - if (!Symbol->getName().startswith(Prefix)) - LastNonPrivate = Symbol; +void MCStreamer::EmitDataRegion() { + if (RegionIndicator == Data) return; + + MCContext &Context = getContext(); + const MCAsmInfo &MAI = Context.getAsmInfo(); + if (!MAI.getSupportsDataRegions()) return; + + // Generate a unique symbol name. + MCSymbol *NewSym = Context.GetOrCreateSymbol( + Twine(MAI.getDataBeginLabelName()) + + utostr(UniqueDataBeginSuffix++)); + EmitLabel(NewSym); + + RegionIndicator = Data; +} + +void MCStreamer::EmitCodeRegion() { + if (RegionIndicator == Code) return; + + MCContext &Context = getContext(); + const MCAsmInfo &MAI = Context.getAsmInfo(); + if (!MAI.getSupportsDataRegions()) return; + + // Generate a unique symbol name. + MCSymbol *NewSym = Context.GetOrCreateSymbol( + Twine(MAI.getCodeBeginLabelName()) + + utostr(UniqueCodeBeginSuffix++)); + EmitLabel(NewSym); + + RegionIndicator = Code; +} + +void MCStreamer::EmitJumpTable8Region() { + if (RegionIndicator == JumpTable8) return; + + MCContext &Context = getContext(); + const MCAsmInfo &MAI = Context.getAsmInfo(); + if (!MAI.getSupportsDataRegions()) return; + + // Generate a unique symbol name. + MCSymbol *NewSym = Context.GetOrCreateSymbol( + Twine(MAI.getJumpTable8BeginLabelName()) + + utostr(UniqueDataBeginSuffix++)); + EmitLabel(NewSym); + + RegionIndicator = JumpTable8; +} + +void MCStreamer::EmitJumpTable16Region() { + if (RegionIndicator == JumpTable16) return; + + MCContext &Context = getContext(); + const MCAsmInfo &MAI = Context.getAsmInfo(); + if (!MAI.getSupportsDataRegions()) return; + + // Generate a unique symbol name. + MCSymbol *NewSym = Context.GetOrCreateSymbol( + Twine(MAI.getJumpTable16BeginLabelName()) + + utostr(UniqueDataBeginSuffix++)); + EmitLabel(NewSym); + + RegionIndicator = JumpTable16; +} + + +void MCStreamer::EmitJumpTable32Region() { + if (RegionIndicator == JumpTable32) return; + + MCContext &Context = getContext(); + const MCAsmInfo &MAI = Context.getAsmInfo(); + if (!MAI.getSupportsDataRegions()) return; + + // Generate a unique symbol name. + MCSymbol *NewSym = Context.GetOrCreateSymbol( + Twine(MAI.getJumpTable32BeginLabelName()) + + utostr(UniqueDataBeginSuffix++)); + EmitLabel(NewSym); + + RegionIndicator = JumpTable32; +} + +void MCStreamer::EmitCompactUnwindEncoding(uint32_t CompactUnwindEncoding) { + EnsureValidFrame(); + MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); + CurFrame->CompactUnwindEncoding = CompactUnwindEncoding; } void MCStreamer::EmitCFISections(bool EH, bool Debug) { @@ -187,11 +275,22 @@ void MCStreamer::EmitCFIStartProc() { MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); if (CurFrame && !CurFrame->End) report_fatal_error("Starting a frame before finishing the previous one!"); + MCDwarfFrameInfo Frame; - Frame.Begin = getContext().CreateTempSymbol(); - Frame.Function = LastNonPrivate; - EmitLabel(Frame.Begin); + Frame.Function = LastSymbol; + + // If the function is externally visible, we need to create a local + // symbol to avoid relocations. + StringRef Prefix = getContext().getAsmInfo().getPrivateGlobalPrefix(); + if (LastSymbol && LastSymbol->getName().startswith(Prefix)) { + Frame.Begin = LastSymbol; + } else { + Frame.Begin = getContext().CreateTempSymbol(); + EmitLabel(Frame.Begin); + } + FrameInfos.push_back(Frame); + RegionIndicator = Code; } void MCStreamer::EmitCFIEndProc() { diff --git a/contrib/llvm/lib/Target/TargetAsmLexer.cpp b/contrib/llvm/lib/MC/MCTargetAsmLexer.cpp similarity index 56% rename from contrib/llvm/lib/Target/TargetAsmLexer.cpp rename to contrib/llvm/lib/MC/MCTargetAsmLexer.cpp index d4893ff25..c01c914ce 100644 --- a/contrib/llvm/lib/Target/TargetAsmLexer.cpp +++ b/contrib/llvm/lib/MC/MCTargetAsmLexer.cpp @@ -1,4 +1,4 @@ -//===-- llvm/Target/TargetAsmLexer.cpp - Target Assembly Lexer ------------===// +//===-- llvm/MC/MCTargetAsmLexer.cpp - Target Assembly Lexer --------------===// // // The LLVM Compiler Infrastructure // @@ -7,8 +7,10 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Target/TargetAsmLexer.h" +#include "llvm/MC/MCTargetAsmLexer.h" using namespace llvm; -TargetAsmLexer::TargetAsmLexer(const Target &T) : TheTarget(T), Lexer(NULL) {} -TargetAsmLexer::~TargetAsmLexer() {} +MCTargetAsmLexer::MCTargetAsmLexer(const Target &T) + : TheTarget(T), Lexer(NULL) { +} +MCTargetAsmLexer::~MCTargetAsmLexer() {} diff --git a/contrib/llvm/lib/MC/MCWin64EH.cpp b/contrib/llvm/lib/MC/MCWin64EH.cpp index e698384a4..79e66fcdf 100644 --- a/contrib/llvm/lib/MC/MCWin64EH.cpp +++ b/contrib/llvm/lib/MC/MCWin64EH.cpp @@ -10,10 +10,11 @@ #include "llvm/MC/MCWin64EH.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCContext.h" +#include "llvm/MC/MCObjectFileInfo.h" #include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCSectionCOFF.h" #include "llvm/MC/MCExpr.h" -#include "llvm/Target/TargetAsmInfo.h" +#include "llvm/ADT/Twine.h" namespace llvm { @@ -220,14 +221,36 @@ StringRef MCWin64EHUnwindEmitter::GetSectionSuffix(const MCSymbol *func) { return ""; } +static const MCSection *getWin64EHTableSection(StringRef suffix, + MCContext &context) { + if (suffix == "") + return context.getObjectFileInfo()->getXDataSection(); + + return context.getCOFFSection((".xdata"+suffix).str(), + COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | + COFF::IMAGE_SCN_MEM_READ | + COFF::IMAGE_SCN_MEM_WRITE, + SectionKind::getDataRel()); +} + +static const MCSection *getWin64EHFuncTableSection(StringRef suffix, + MCContext &context) { + if (suffix == "") + return context.getObjectFileInfo()->getPDataSection(); + return context.getCOFFSection((".pdata"+suffix).str(), + COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | + COFF::IMAGE_SCN_MEM_READ | + COFF::IMAGE_SCN_MEM_WRITE, + SectionKind::getDataRel()); +} + void MCWin64EHUnwindEmitter::EmitUnwindInfo(MCStreamer &streamer, MCWin64EHUnwindInfo *info) { // Switch sections (the static function above is meant to be called from // here and from Emit(). MCContext &context = streamer.getContext(); - const TargetAsmInfo &TAI = context.getTargetAsmInfo(); const MCSection *xdataSect = - TAI.getWin64EHTableSection(GetSectionSuffix(info->Function)); + getWin64EHTableSection(GetSectionSuffix(info->Function), context); streamer.SwitchSection(xdataSect); llvm::EmitUnwindInfo(streamer, info); @@ -236,11 +259,10 @@ void MCWin64EHUnwindEmitter::EmitUnwindInfo(MCStreamer &streamer, void MCWin64EHUnwindEmitter::Emit(MCStreamer &streamer) { MCContext &context = streamer.getContext(); // Emit the unwind info structs first. - const TargetAsmInfo &TAI = context.getTargetAsmInfo(); for (unsigned i = 0; i < streamer.getNumW64UnwindInfos(); ++i) { MCWin64EHUnwindInfo &info = streamer.getW64UnwindInfo(i); const MCSection *xdataSect = - TAI.getWin64EHTableSection(GetSectionSuffix(info.Function)); + getWin64EHTableSection(GetSectionSuffix(info.Function), context); streamer.SwitchSection(xdataSect); llvm::EmitUnwindInfo(streamer, &info); } @@ -248,7 +270,7 @@ void MCWin64EHUnwindEmitter::Emit(MCStreamer &streamer) { for (unsigned i = 0; i < streamer.getNumW64UnwindInfos(); ++i) { MCWin64EHUnwindInfo &info = streamer.getW64UnwindInfo(i); const MCSection *pdataSect = - TAI.getWin64EHFuncTableSection(GetSectionSuffix(info.Function)); + getWin64EHFuncTableSection(GetSectionSuffix(info.Function), context); streamer.SwitchSection(pdataSect); EmitRuntimeFunction(streamer, &info); } diff --git a/contrib/llvm/lib/MC/MachObjectWriter.cpp b/contrib/llvm/lib/MC/MachObjectWriter.cpp index 69efe231a..a9219ad29 100644 --- a/contrib/llvm/lib/MC/MachObjectWriter.cpp +++ b/contrib/llvm/lib/MC/MachObjectWriter.cpp @@ -12,6 +12,7 @@ #include "llvm/ADT/StringMap.h" #include "llvm/ADT/Twine.h" #include "llvm/MC/MCAssembler.h" +#include "llvm/MC/MCAsmBackend.h" #include "llvm/MC/MCAsmLayout.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCObjectWriter.h" @@ -21,7 +22,6 @@ #include "llvm/MC/MCValue.h" #include "llvm/Object/MachOFormat.h" #include "llvm/Support/ErrorHandling.h" -#include "llvm/Target/TargetAsmBackend.h" #include using namespace llvm; @@ -291,7 +291,7 @@ void MachObjectWriter::WriteNlist(MachSymbolData &MSD, const MCSymbol &Symbol = Data.getSymbol(); uint8_t Type = 0; uint16_t Flags = Data.getFlags(); - uint32_t Address = 0; + uint64_t Address = 0; // Set the N_TYPE bits. See . // @@ -590,14 +590,28 @@ IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, return false; return true; } + // For Darwin x86_64, there is one special case when the reference IsPCRel. + // If the fragment with the reference does not have a base symbol but meets + // the simple way of dealing with this, in that it is a temporary symbol in + // the same atom then it is assumed to be fully resolved. This is needed so + // a relocation entry is not created and so the static linker does not + // mess up the reference later. + else if(!FB.getAtom() && + SA.isTemporary() && SA.isInSection() && &SecA == &SecB){ + return true; + } } else { if (!TargetObjectWriter->useAggressiveSymbolFolding()) return false; } - const MCFragment &FA = *Asm.getSymbolData(SA).getFragment(); + const MCFragment *FA = Asm.getSymbolData(SA).getFragment(); + + // Bail if the symbol has no fragment. + if (!FA) + return false; - A_Base = FA.getAtom(); + A_Base = FA->getAtom(); if (!A_Base) return false; @@ -613,7 +627,8 @@ IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, return false; } -void MachObjectWriter::WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout) { +void MachObjectWriter::WriteObject(MCAssembler &Asm, + const MCAsmLayout &Layout) { unsigned NumSections = Asm.size(); // The section data starts after the header, the segment load command (and diff --git a/contrib/llvm/lib/MC/WinCOFFObjectWriter.cpp b/contrib/llvm/lib/MC/WinCOFFObjectWriter.cpp index 101237aab..b15e225fc 100644 --- a/contrib/llvm/lib/MC/WinCOFFObjectWriter.cpp +++ b/contrib/llvm/lib/MC/WinCOFFObjectWriter.cpp @@ -33,7 +33,7 @@ #include "llvm/Support/TimeValue.h" -#include "../Target/X86/X86FixupKinds.h" +#include "../Target/X86/MCTargetDesc/X86FixupKinds.h" #include diff --git a/contrib/llvm/lib/MC/WinCOFFStreamer.cpp b/contrib/llvm/lib/MC/WinCOFFStreamer.cpp index 6c36c1231..7409daf39 100644 --- a/contrib/llvm/lib/MC/WinCOFFStreamer.cpp +++ b/contrib/llvm/lib/MC/WinCOFFStreamer.cpp @@ -24,13 +24,13 @@ #include "llvm/MC/MCCodeEmitter.h" #include "llvm/MC/MCSectionCOFF.h" #include "llvm/MC/MCWin64EH.h" -#include "llvm/Target/TargetRegistry.h" -#include "llvm/Target/TargetAsmBackend.h" +#include "llvm/MC/MCAsmBackend.h" #include "llvm/ADT/StringMap.h" #include "llvm/Support/COFF.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/TargetRegistry.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; @@ -40,7 +40,7 @@ public: MCSymbol const *CurSymbol; WinCOFFStreamer(MCContext &Context, - TargetAsmBackend &TAB, + MCAsmBackend &MAB, MCCodeEmitter &CE, raw_ostream &OS); @@ -63,7 +63,8 @@ public: virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value); virtual void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment); - virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size); + virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment); virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol, unsigned Size,unsigned ByteAlignment); virtual void EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol, @@ -123,10 +124,10 @@ private: } // end anonymous namespace. WinCOFFStreamer::WinCOFFStreamer(MCContext &Context, - TargetAsmBackend &TAB, + MCAsmBackend &MAB, MCCodeEmitter &CE, raw_ostream &OS) - : MCObjectStreamer(Context, TAB, OS, &CE) + : MCObjectStreamer(Context, MAB, OS, &CE) , CurSymbol(NULL) { } @@ -304,11 +305,12 @@ void WinCOFFStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, AddCommonSymbol(Symbol, Size, ByteAlignment, true); } -void WinCOFFStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size) { +void WinCOFFStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment) { assert((Symbol->isInSection() ? Symbol->getSection().getVariant() == MCSection::SV_COFF : true) && "Got non COFF section in the COFF backend!"); - AddCommonSymbol(Symbol, Size, 1, false); + AddCommonSymbol(Symbol, Size, ByteAlignment, false); } void WinCOFFStreamer::EmitZerofill(const MCSection *Section, MCSymbol *Symbol, @@ -395,11 +397,11 @@ void WinCOFFStreamer::Finish() { namespace llvm { MCStreamer *createWinCOFFStreamer(MCContext &Context, - TargetAsmBackend &TAB, + MCAsmBackend &MAB, MCCodeEmitter &CE, raw_ostream &OS, bool RelaxAll) { - WinCOFFStreamer *S = new WinCOFFStreamer(Context, TAB, CE, OS); + WinCOFFStreamer *S = new WinCOFFStreamer(Context, MAB, CE, OS); S->getAssembler().setRelaxAll(RelaxAll); return S; } diff --git a/contrib/llvm/lib/Object/Archive.cpp b/contrib/llvm/lib/Object/Archive.cpp new file mode 100644 index 000000000..e2eaff53c --- /dev/null +++ b/contrib/llvm/lib/Object/Archive.cpp @@ -0,0 +1,172 @@ +//===- Archive.cpp - ar File Format 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 defines the ArchiveObjectFile class. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Object/Archive.h" +#include "llvm/ADT/APInt.h" +#include "llvm/Support/MemoryBuffer.h" + +using namespace llvm; +using namespace object; + +namespace { +const StringRef Magic = "!\n"; + +struct ArchiveMemberHeader { + char Name[16]; + char LastModified[12]; + char UID[6]; + char GID[6]; + char AccessMode[8]; + char Size[10]; //< Size of data, not including header or padding. + char Terminator[2]; + + ///! Get the name without looking up long names. + StringRef getName() const { + char EndCond = Name[0] == '/' ? ' ' : '/'; + StringRef::size_type end = StringRef(Name, sizeof(Name)).find(EndCond); + if (end == StringRef::npos) + end = sizeof(Name); + assert(end <= sizeof(Name) && end > 0); + // Don't include the EndCond if there is one. + return StringRef(Name, end); + } + + uint64_t getSize() const { + APInt ret; + StringRef(Size, sizeof(Size)).getAsInteger(10, ret); + return ret.getZExtValue(); + } +}; + +const ArchiveMemberHeader *ToHeader(const char *base) { + return reinterpret_cast(base); +} +} + +Archive::Child Archive::Child::getNext() const { + size_t SpaceToSkip = sizeof(ArchiveMemberHeader) + + ToHeader(Data.data())->getSize(); + // 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)); +} + +error_code Archive::Child::getName(StringRef &Result) const { + StringRef name = ToHeader(Data.data())->getName(); + // Check if it's a special name. + if (name[0] == '/') { + if (name.size() == 1) { // Linker member. + Result = name; + return object_error::success; + } + if (name.size() == 2 && name[1] == '/') { // String table. + Result = name; + return object_error::success; + } + // It's a long name. + // Get the offset. + APInt offset; + name.substr(1).getAsInteger(10, offset); + const char *addr = Parent->StringTable->Data.begin() + + sizeof(ArchiveMemberHeader) + + offset.getZExtValue(); + // Verify it. + if (Parent->StringTable == Parent->end_children() + || addr < (Parent->StringTable->Data.begin() + + sizeof(ArchiveMemberHeader)) + || addr > (Parent->StringTable->Data.begin() + + sizeof(ArchiveMemberHeader) + + Parent->StringTable->getSize())) + return object_error::parse_failed; + Result = addr; + return object_error::success; + } + // It's a simple name. + if (name[name.size() - 1] == '/') + Result = name.substr(0, name.size() - 1); + else + Result = name; + return object_error::success; +} + +uint64_t Archive::Child::getSize() const { + return ToHeader(Data.data())->getSize(); +} + +MemoryBuffer *Archive::Child::getBuffer() const { + StringRef name; + if (getName(name)) return NULL; + return MemoryBuffer::getMemBuffer(Data.substr(sizeof(ArchiveMemberHeader), + getSize()), + name, + false); +} + +error_code Archive::Child::getAsBinary(OwningPtr &Result) const { + OwningPtr ret; + if (error_code ec = + createBinary(getBuffer(), ret)) + return ec; + Result.swap(ret); + return object_error::success; +} + +Archive::Archive(MemoryBuffer *source, error_code &ec) + : Binary(Binary::isArchive, source) + , StringTable(Child(this, StringRef(0, 0))) { + // Check for sufficient magic. + if (!source || source->getBufferSize() + < (8 + sizeof(ArchiveMemberHeader) + 2) // Smallest archive. + || StringRef(source->getBufferStart(), 8) != Magic) { + ec = object_error::invalid_file_type; + return; + } + + // Get the string table. It's the 3rd member. + child_iterator StrTable = begin_children(); + child_iterator e = end_children(); + for (int i = 0; StrTable != e && i < 2; ++StrTable, ++i) {} + + // Check to see if there were 3 members, or the 3rd member wasn't named "//". + StringRef name; + if (StrTable != e && !StrTable->getName(name) && name == "//") + StringTable = StrTable; + + ec = object_error::success; +} + +Archive::child_iterator Archive::begin_children() const { + const char *Loc = Data->getBufferStart() + Magic.size(); + size_t Size = sizeof(ArchiveMemberHeader) + + ToHeader(Loc)->getSize(); + return Child(this, StringRef(Loc, Size)); +} + +Archive::child_iterator Archive::end_children() const { + return Child(this, StringRef(0, 0)); +} + +namespace llvm { + +} // end namespace llvm diff --git a/contrib/llvm/lib/Object/Binary.cpp b/contrib/llvm/lib/Object/Binary.cpp index 4b31c7557..4e528d8ea 100644 --- a/contrib/llvm/lib/Object/Binary.cpp +++ b/contrib/llvm/lib/Object/Binary.cpp @@ -17,8 +17,9 @@ #include "llvm/Support/Path.h" // Include headers for createBinary. -#include "llvm/Object/ObjectFile.h" +#include "llvm/Object/Archive.h" #include "llvm/Object/COFF.h" +#include "llvm/Object/ObjectFile.h" using namespace llvm; using namespace object; @@ -50,6 +51,12 @@ error_code object::createBinary(MemoryBuffer *Source, static_cast(Source->getBufferSize())); error_code ec; switch (type) { + case sys::Archive_FileType: { + OwningPtr ret(new Archive(scopedSource.take(), ec)); + if (ec) return ec; + Result.swap(ret); + return object_error::success; + } case sys::ELF_Relocatable_FileType: case sys::ELF_Executable_FileType: case sys::ELF_SharedObject_FileType: @@ -90,7 +97,7 @@ error_code object::createBinary(MemoryBuffer *Source, error_code object::createBinary(StringRef Path, OwningPtr &Result) { OwningPtr File; - if (error_code ec = MemoryBuffer::getFile(Path, File)) + if (error_code ec = MemoryBuffer::getFileOrSTDIN(Path, File)) return ec; return createBinary(File.take(), Result); } diff --git a/contrib/llvm/lib/Object/CMakeLists.txt b/contrib/llvm/lib/Object/CMakeLists.txt deleted file mode 100644 index 6a6814fd3..000000000 --- a/contrib/llvm/lib/Object/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -add_llvm_library(LLVMObject - MachOObject.cpp - ObjectFile.cpp - COFFObjectFile.cpp - ELFObjectFile.cpp - ) diff --git a/contrib/llvm/lib/Object/COFFObjectFile.cpp b/contrib/llvm/lib/Object/COFFObjectFile.cpp index 07de6bc99..750c34d12 100644 --- a/contrib/llvm/lib/Object/COFFObjectFile.cpp +++ b/contrib/llvm/lib/Object/COFFObjectFile.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "llvm/Object/COFF.h" +#include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Triple.h" @@ -114,7 +115,7 @@ error_code COFFObjectFile::getSymbolNext(DataRefImpl Symb, return object_error::success; } -error_code COFFObjectFile::getSymbolAddress(DataRefImpl Symb, +error_code COFFObjectFile::getSymbolOffset(DataRefImpl Symb, uint64_t &Result) const { const coff_symbol *symb = toSymb(Symb); const coff_section *Section = NULL; @@ -132,6 +133,55 @@ error_code COFFObjectFile::getSymbolAddress(DataRefImpl Symb, return object_error::success; } +error_code COFFObjectFile::getSymbolAddress(DataRefImpl Symb, + uint64_t &Result) const { + const coff_symbol *symb = toSymb(Symb); + const coff_section *Section = NULL; + if (error_code ec = getSection(symb->SectionNumber, Section)) + return ec; + char Type; + if (error_code ec = getSymbolNMTypeChar(Symb, Type)) + return ec; + if (Type == 'U' || Type == 'w') + Result = UnknownAddressOrSize; + else if (Section) + Result = reinterpret_cast(base() + + Section->PointerToRawData + + symb->Value); + else + Result = reinterpret_cast(base() + symb->Value); + return object_error::success; +} + +error_code COFFObjectFile::getSymbolType(DataRefImpl Symb, + SymbolRef::SymbolType &Result) const { + const coff_symbol *symb = toSymb(Symb); + Result = SymbolRef::ST_Other; + if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL && + symb->SectionNumber == COFF::IMAGE_SYM_UNDEFINED) { + Result = SymbolRef::ST_External; + } else { + if (symb->Type.ComplexType == COFF::IMAGE_SYM_DTYPE_FUNCTION) { + Result = SymbolRef::ST_Function; + } else { + char Type; + if (error_code ec = getSymbolNMTypeChar(Symb, Type)) + return ec; + if (Type == 'r' || Type == 'R') { + Result = SymbolRef::ST_Data; + } + } + } + return object_error::success; +} + +error_code COFFObjectFile::isSymbolGlobal(DataRefImpl Symb, + bool &Result) const { + const coff_symbol *symb = toSymb(Symb); + Result = (symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL); + return object_error::success; +} + error_code COFFObjectFile::getSymbolSize(DataRefImpl Symb, uint64_t &Result) const { // FIXME: Return the correct size. This requires looking at all the symbols @@ -286,6 +336,15 @@ error_code COFFObjectFile::getSectionContents(DataRefImpl Sec, return object_error::success; } +error_code COFFObjectFile::getSectionAlignment(DataRefImpl Sec, + uint64_t &Res) const { + const coff_section *sec = toSec(Sec); + if (!sec) + return object_error::parse_failed; + Res = uint64_t(1) << (((sec->Characteristics & 0x00F00000) >> 20) - 1); + return object_error::success; +} + error_code COFFObjectFile::isSectionText(DataRefImpl Sec, bool &Result) const { const coff_section *sec = toSec(Sec); @@ -293,14 +352,61 @@ error_code COFFObjectFile::isSectionText(DataRefImpl Sec, return object_error::success; } +error_code COFFObjectFile::isSectionData(DataRefImpl Sec, + bool &Result) const { + const coff_section *sec = toSec(Sec); + Result = sec->Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA; + return object_error::success; +} + +error_code COFFObjectFile::isSectionBSS(DataRefImpl Sec, + bool &Result) const { + const coff_section *sec = toSec(Sec); + Result = sec->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA; + return object_error::success; +} + error_code COFFObjectFile::sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, bool &Result) const { - // FIXME: Unimplemented. - Result = false; + const coff_section *sec = toSec(Sec); + const coff_symbol *symb = toSymb(Symb); + const coff_section *symb_sec; + if (error_code ec = getSection(symb->SectionNumber, symb_sec)) return ec; + if (symb_sec == sec) + Result = true; + else + Result = false; return object_error::success; } +relocation_iterator COFFObjectFile::getSectionRelBegin(DataRefImpl Sec) const { + const coff_section *sec = toSec(Sec); + DataRefImpl ret; + std::memset(&ret, 0, sizeof(ret)); + if (sec->NumberOfRelocations == 0) + ret.p = 0; + else + ret.p = reinterpret_cast(base() + sec->PointerToRelocations); + + return relocation_iterator(RelocationRef(ret, this)); +} + +relocation_iterator COFFObjectFile::getSectionRelEnd(DataRefImpl Sec) const { + const coff_section *sec = toSec(Sec); + DataRefImpl ret; + std::memset(&ret, 0, sizeof(ret)); + if (sec->NumberOfRelocations == 0) + ret.p = 0; + else + ret.p = reinterpret_cast( + reinterpret_cast( + base() + sec->PointerToRelocations) + + sec->NumberOfRelocations); + + return relocation_iterator(RelocationRef(ret, this)); +} + COFFObjectFile::COFFObjectFile(MemoryBuffer *Object, error_code &ec) : ObjectFile(Binary::isCOFF, Object, ec) { // Check that we at least have enough room for a header. @@ -327,7 +433,7 @@ COFFObjectFile::COFFObjectFile(MemoryBuffer *Object, error_code &ec) Header = reinterpret_cast(base() + HeaderStart); if (!checkAddr(Data, ec, uintptr_t(Header), sizeof(coff_file_header))) return; - + SectionTable = reinterpret_cast( base() + HeaderStart @@ -360,18 +466,18 @@ COFFObjectFile::COFFObjectFile(MemoryBuffer *Object, error_code &ec) ec = object_error::parse_failed; return; } - + ec = object_error::success; } -ObjectFile::symbol_iterator COFFObjectFile::begin_symbols() const { +symbol_iterator COFFObjectFile::begin_symbols() const { DataRefImpl ret; std::memset(&ret, 0, sizeof(DataRefImpl)); ret.p = reinterpret_cast(SymbolTable); return symbol_iterator(SymbolRef(ret, this)); } -ObjectFile::symbol_iterator COFFObjectFile::end_symbols() const { +symbol_iterator COFFObjectFile::end_symbols() const { // The symbol table ends where the string table begins. DataRefImpl ret; std::memset(&ret, 0, sizeof(DataRefImpl)); @@ -379,14 +485,14 @@ ObjectFile::symbol_iterator COFFObjectFile::end_symbols() const { return symbol_iterator(SymbolRef(ret, this)); } -ObjectFile::section_iterator COFFObjectFile::begin_sections() const { +section_iterator COFFObjectFile::begin_sections() const { DataRefImpl ret; std::memset(&ret, 0, sizeof(DataRefImpl)); ret.p = reinterpret_cast(SectionTable); return section_iterator(SectionRef(ret, this)); } -ObjectFile::section_iterator COFFObjectFile::end_sections() const { +section_iterator COFFObjectFile::end_sections() const { DataRefImpl ret; std::memset(&ret, 0, sizeof(DataRefImpl)); ret.p = reinterpret_cast(SectionTable + Header->NumberOfSections); @@ -445,6 +551,121 @@ error_code COFFObjectFile::getString(uint32_t offset, return object_error::success; } +error_code COFFObjectFile::getSymbol(uint32_t index, + const coff_symbol *&Result) const { + if (index > 0 && index < Header->NumberOfSymbols) + Result = SymbolTable + index; + else + return object_error::parse_failed; + return object_error::success; +} + +const coff_relocation *COFFObjectFile::toRel(DataRefImpl Rel) const { + return reinterpret_cast(Rel.p); +} +error_code COFFObjectFile::getRelocationNext(DataRefImpl Rel, + RelocationRef &Res) const { + Rel.p = reinterpret_cast( + reinterpret_cast(Rel.p) + 1); + Res = RelocationRef(Rel, this); + return object_error::success; +} +error_code COFFObjectFile::getRelocationAddress(DataRefImpl Rel, + uint64_t &Res) const { + Res = toRel(Rel)->VirtualAddress; + return object_error::success; +} +error_code COFFObjectFile::getRelocationSymbol(DataRefImpl Rel, + SymbolRef &Res) const { + const coff_relocation* R = toRel(Rel); + DataRefImpl Symb; + Symb.p = reinterpret_cast(SymbolTable + R->SymbolTableIndex); + Res = SymbolRef(Symb, this); + return object_error::success; +} +error_code COFFObjectFile::getRelocationType(DataRefImpl Rel, + uint32_t &Res) const { + const coff_relocation* R = toRel(Rel); + Res = R->Type; + return object_error::success; +} + +#define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(enum) \ + case COFF::enum: res = #enum; break; + +error_code COFFObjectFile::getRelocationTypeName(DataRefImpl Rel, + SmallVectorImpl &Result) const { + const coff_relocation *reloc = toRel(Rel); + StringRef res; + switch (Header->Machine) { + case COFF::IMAGE_FILE_MACHINE_AMD64: + switch (reloc->Type) { + LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ABSOLUTE); + LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR64); + LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32); + LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32NB); + LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32); + LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_1); + LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_2); + LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_3); + LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_4); + LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_5); + LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECTION); + LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL); + LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL7); + LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_TOKEN); + LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SREL32); + LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_PAIR); + LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SSPAN32); + default: + res = "Unknown"; + } + break; + case COFF::IMAGE_FILE_MACHINE_I386: + switch (reloc->Type) { + LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_ABSOLUTE); + LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR16); + LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL16); + LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32); + LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32NB); + LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SEG12); + LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECTION); + LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL); + LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_TOKEN); + LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL7); + LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL32); + default: + res = "Unknown"; + } + break; + default: + res = "Unknown"; + } + Result.append(res.begin(), res.end()); + return object_error::success; +} + +#undef LLVM_COFF_SWITCH_RELOC_TYPE_NAME + +error_code COFFObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel, + int64_t &Res) const { + Res = 0; + return object_error::success; +} +error_code COFFObjectFile::getRelocationValueString(DataRefImpl Rel, + SmallVectorImpl &Result) const { + const coff_relocation *reloc = toRel(Rel); + const coff_symbol *symb = 0; + if (error_code ec = getSymbol(reloc->SymbolTableIndex, symb)) return ec; + DataRefImpl sym; + ::memset(&sym, 0, sizeof(sym)); + sym.p = reinterpret_cast(symb); + StringRef symname; + if (error_code ec = getSymbolName(sym, symname)) return ec; + Result.append(symname.begin(), symname.end()); + return object_error::success; +} + namespace llvm { ObjectFile *ObjectFile::createCOFFObjectFile(MemoryBuffer *Object) { diff --git a/contrib/llvm/lib/Object/ELFObjectFile.cpp b/contrib/llvm/lib/Object/ELFObjectFile.cpp index e2ff4dfc0..257d08cad 100644 --- a/contrib/llvm/lib/Object/ELFObjectFile.cpp +++ b/contrib/llvm/lib/Object/ELFObjectFile.cpp @@ -14,11 +14,14 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Triple.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/Object/ObjectFile.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 @@ -175,6 +178,81 @@ struct Elf_Sym_Impl : Elf_Sym_Base { }; } +namespace { +template +struct Elf_Rel_Base; + +template +struct Elf_Rel_Base { + LLVM_ELF_IMPORT_TYPES(target_endianness, 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 +}; + +template +struct Elf_Rel_Base { + LLVM_ELF_IMPORT_TYPES(target_endianness, 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 +}; + +template +struct Elf_Rel_Base { + LLVM_ELF_IMPORT_TYPES(target_endianness, 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 +}; + +template +struct Elf_Rel_Base { + LLVM_ELF_IMPORT_TYPES(target_endianness, 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. +}; + +template +struct Elf_Rel_Impl; + +template +struct Elf_Rel_Impl + : Elf_Rel_Base { + using Elf_Rel_Base::r_info; + LLVM_ELF_IMPORT_TYPES(target_endianness, true) + + // These accessors and mutators correspond to the ELF64_R_SYM, ELF64_R_TYPE, + // and ELF64_R_INFO macros defined in the ELF specification: + uint64_t getSymbol() const { return (r_info >> 32); } + unsigned char getType() const { + return (unsigned char) (r_info & 0xffffffffL); + } + void setSymbol(uint64_t s) { setSymbolAndType(s, getType()); } + void setType(unsigned char t) { setSymbolAndType(getSymbol(), t); } + void setSymbolAndType(uint64_t s, unsigned char t) { + r_info = (s << 32) + (t&0xffffffffL); + } +}; + +template +struct Elf_Rel_Impl + : Elf_Rel_Base { + using Elf_Rel_Base::r_info; + LLVM_ELF_IMPORT_TYPES(target_endianness, 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() const { return (r_info >> 8); } + unsigned char getType() const { return (unsigned char) (r_info & 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) { + r_info = (s << 8) + t; + } +}; + +} + namespace { template class ELFObjectFile : public ObjectFile { @@ -182,6 +260,8 @@ class ELFObjectFile : public ObjectFile { typedef Elf_Shdr_Impl Elf_Shdr; typedef Elf_Sym_Impl Elf_Sym; + typedef Elf_Rel_Impl Elf_Rel; + typedef Elf_Rel_Impl Elf_Rela; struct Elf_Ehdr { unsigned char e_ident[ELF::EI_NIDENT]; // ELF Identification bytes @@ -206,37 +286,81 @@ class ELFObjectFile : public ObjectFile { unsigned char getDataEncoding() const { return e_ident[ELF::EI_DATA]; } }; - typedef SmallVector SymbolTableSections_t; + typedef SmallVector Sections_t; + typedef DenseMap IndexMap_t; + typedef DenseMap > RelocMap_t; 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. - SymbolTableSections_t SymbolTableSections; + Sections_t SymbolTableSections; + IndexMap_t SymbolTableSectionsIndexMap; + DenseMap ExtendedSymbolTable; + + /// @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); + } void validateSymbol(DataRefImpl Symb) const; + 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_Sym *getSymbol(DataRefImpl Symb) const; const Elf_Shdr *getSection(DataRefImpl index) const; - const Elf_Shdr *getSection(uint16_t index) const; - const char *getString(uint16_t section, uint32_t offset) const; + const Elf_Shdr *getSection(uint32_t index) const; + const Elf_Rel *getRel(DataRefImpl Rel) const; + const Elf_Rela *getRela(DataRefImpl Rela) const; + const char *getString(uint32_t section, uint32_t offset) const; const char *getString(const Elf_Shdr *section, uint32_t offset) const; + error_code getSymbolName(const Elf_Sym *Symb, StringRef &Res) const; protected: virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const; virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const; + virtual error_code getSymbolOffset(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 isSymbolInternal(DataRefImpl Symb, bool &Res) const; + virtual error_code isSymbolGlobal(DataRefImpl Symb, bool &Res) const; + virtual error_code getSymbolType(DataRefImpl Symb, SymbolRef::SymbolType &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 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 getRelocationSymbol(DataRefImpl Rel, + SymbolRef &Res) const; + virtual error_code getRelocationType(DataRefImpl Rel, + uint32_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; public: ELFObjectFile(MemoryBuffer *Object, error_code &ec); @@ -248,6 +372,11 @@ public: virtual uint8_t getBytesInAddress() const; virtual StringRef getFileFormatName() const; virtual unsigned getArch() const; + + uint64_t getNumSections() const; + uint64_t getStringTableIndex() const; + ELF::Elf64_Word getSymbolTableIndex(const Elf_Sym *symb) const; + const Elf_Shdr *getSection(const Elf_Sym *symb) const; }; } // end namespace @@ -299,29 +428,37 @@ error_code ELFObjectFile ::getSymbolName(DataRefImpl Symb, StringRef &Result) const { validateSymbol(Symb); - const Elf_Sym *symb = getSymbol(Symb); - if (symb->st_name == 0) { - const Elf_Shdr *section = getSection(symb->st_shndx); - if (!section) - Result = ""; - else - Result = getString(dot_shstrtab_sec, section->sh_name); - return object_error::success; - } + const Elf_Sym *symb = getSymbol(Symb); + return getSymbolName(symb, Result); +} - // Use the default symbol table name section. - Result = getString(dot_strtab_sec, symb->st_name); - return object_error::success; +template +ELF::Elf64_Word ELFObjectFile + ::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 { + if (symb->st_shndx == ELF::SHN_XINDEX) + return getSection(ExtendedSymbolTable.lookup(symb)); + if (symb->st_shndx >= ELF::SHN_LORESERVE) + return 0; + return getSection(symb->st_shndx); } template error_code ELFObjectFile - ::getSymbolAddress(DataRefImpl Symb, - uint64_t &Result) const { + ::getSymbolOffset(DataRefImpl Symb, + uint64_t &Result) const { validateSymbol(Symb); const Elf_Sym *symb = getSymbol(Symb); const Elf_Shdr *Section; - switch (symb->st_shndx) { + switch (getSymbolTableIndex(symb)) { case ELF::SHN_COMMON: // Undefined symbols have no address yet. case ELF::SHN_UNDEF: @@ -330,7 +467,7 @@ error_code ELFObjectFile case ELF::SHN_ABS: Result = symb->st_value; return object_error::success; - default: Section = getSection(symb->st_shndx); + default: Section = getSection(symb); } switch (symb->getType()) { @@ -348,6 +485,43 @@ error_code ELFObjectFile } } +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: // Fall through. + // Undefined symbols have no address yet. + case ELF::SHN_UNDEF: + Result = UnknownAddressOrSize; + return object_error::success; + case ELF::SHN_ABS: + Result = reinterpret_cast(base()+symb->st_value); + return object_error::success; + default: Section = getSection(symb); + } + const uint8_t* addr = base(); + if (Section) + addr += Section->sh_offset; + switch (symb->getType()) { + case ELF::STT_SECTION: + Result = reinterpret_cast(addr); + return object_error::success; + case ELF::STT_FUNC: // Fall through. + case ELF::STT_OBJECT: // Fall through. + case ELF::STT_NOTYPE: + addr += symb->st_value; + Result = reinterpret_cast(addr); + return object_error::success; + default: + Result = UnknownAddressOrSize; + return object_error::success; + } +} + template error_code ELFObjectFile ::getSymbolSize(DataRefImpl Symb, @@ -366,7 +540,7 @@ error_code ELFObjectFile char &Result) const { validateSymbol(Symb); const Elf_Sym *symb = getSymbol(Symb); - const Elf_Shdr *Section = getSection(symb->st_shndx); + const Elf_Shdr *Section = getSection(symb); char ret = '?'; @@ -389,7 +563,7 @@ error_code ELFObjectFile } } - switch (symb->st_shndx) { + switch (getSymbolTableIndex(symb)) { case ELF::SHN_UNDEF: if (ret == '?') ret = 'U'; @@ -401,7 +575,7 @@ error_code ELFObjectFile switch (symb->getBinding()) { case ELF::STB_GLOBAL: ret = ::toupper(ret); break; case ELF::STB_WEAK: - if (symb->st_shndx == ELF::SHN_UNDEF) + if (getSymbolTableIndex(symb) == ELF::SHN_UNDEF) ret = 'w'; else if (symb->getType() == ELF::STT_OBJECT) @@ -416,7 +590,8 @@ error_code ELFObjectFile return ec; Result = StringSwitch(name) .StartsWith(".debug", 'N') - .StartsWith(".note", 'n'); + .StartsWith(".note", 'n') + .Default('?'); return object_error::success; } @@ -424,6 +599,43 @@ error_code ELFObjectFile return object_error::success; } +template +error_code ELFObjectFile + ::getSymbolType(DataRefImpl Symb, + SymbolRef::SymbolType &Result) const { + validateSymbol(Symb); + const Elf_Sym *symb = getSymbol(Symb); + + if (getSymbolTableIndex(symb) == ELF::SHN_UNDEF) { + Result = SymbolRef::ST_External; + return object_error::success; + } + + switch (symb->getType()) { + case ELF::STT_FUNC: + Result = SymbolRef::ST_Function; + break; + case ELF::STT_OBJECT: + Result = SymbolRef::ST_Data; + break; + default: + Result = SymbolRef::ST_Other; + break; + } + return object_error::success; +} + +template +error_code ELFObjectFile + ::isSymbolGlobal(DataRefImpl Symb, + bool &Result) const { + validateSymbol(Symb); + const Elf_Sym *symb = getSymbol(Symb); + + Result = symb->getBinding() == ELF::STB_GLOBAL; + return object_error::success; +} + template error_code ELFObjectFile ::isSymbolInternal(DataRefImpl Symb, @@ -485,6 +697,15 @@ error_code ELFObjectFile 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, @@ -497,6 +718,32 @@ error_code ELFObjectFile 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 ::sectionContainsSymbol(DataRefImpl Sec, @@ -507,6 +754,330 @@ error_code ELFObjectFile return object_error::success; } +template +relocation_iterator ELFObjectFile + ::getSectionRelBegin(DataRefImpl Sec) const { + DataRefImpl RelData; + memset(&RelData, 0, sizeof(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; + memset(&RelData, 0, sizeof(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 +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(); + break; + } + case ELF::SHT_RELA : { + symbolIdx = getRela(Rel)->getSymbol(); + 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 { + uint64_t offset; + 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 : { + offset = getRel(Rel)->r_offset; + break; + } + case ELF::SHT_RELA : { + offset = getRela(Rel)->r_offset; + break; + } + } + + Result = offset; + return object_error::success; +} + +template +error_code ELFObjectFile + ::getRelocationType(DataRefImpl Rel, + uint32_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(); + break; + } + case ELF::SHT_RELA : { + Result = getRela(Rel)->getType(); + break; + } + } + return object_error::success; +} + +#define LLVM_ELF_SWITCH_RELOC_TYPE_NAME(enum) \ + case ELF::enum: res = #enum; break; + +template +error_code ELFObjectFile + ::getRelocationTypeName(DataRefImpl Rel, + SmallVectorImpl &Result) const { + const Elf_Shdr *sec = getSection(Rel.w.b); + uint8_t type; + StringRef res; + switch (sec->sh_type) { + default : + return object_error::parse_failed; + case ELF::SHT_REL : { + type = getRel(Rel)->getType(); + break; + } + case ELF::SHT_RELA : { + type = getRela(Rel)->getType(); + break; + } + } + 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_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); + default: + res = "Unknown"; + } + 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: + res = "Unknown"; + } + break; + default: + res = "Unknown"; + } + Result.append(res.begin(), res.end()); + return object_error::success; +} + +#undef LLVM_ELF_SWITCH_RELOC_TYPE_NAME + +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(); + symbol_index = getRel(Rel)->getSymbol(); + // TODO: Read implicit addend from section data. + break; + } + case ELF::SHT_RELA : { + type = getRela(Rel)->getType(); + symbol_index = getRela(Rel)->getSymbol(); + addend = getRela(Rel)->r_addend; + break; + } + } + const Elf_Sym *symb = getEntry(sec->sh_link, symbol_index); + StringRef symname; + if (error_code ec = getSymbolName(symb, symname)) + return ec; + switch (Header->e_machine) { + case ELF::EM_X86_64: + switch (type) { + case ELF::R_X86_64_32S: + res = symname; + break; + 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; + default: + res = "Unknown"; + } + break; + default: + res = "Unknown"; + } + if (Result.empty()) + Result.append(res.begin(), res.end()); + return object_error::success; +} + template ELFObjectFile::ELFObjectFile(MemoryBuffer *Object , error_code &ec) @@ -521,25 +1092,41 @@ ELFObjectFile::ELFObjectFile(MemoryBuffer *Object SectionHeaderTable = reinterpret_cast(base() + Header->e_shoff); - uint32_t SectionTableSize = Header->e_shnum * Header->e_shentsize; + uint64_t SectionTableSize = getNumSections() * Header->e_shentsize; if (!( (const uint8_t *)SectionHeaderTable + SectionTableSize <= base() + Data->getBufferSize())) // 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_STMTAB. - for (const char *i = reinterpret_cast(SectionHeaderTable), - *e = i + Header->e_shnum * Header->e_shentsize; - i != e; i += Header->e_shentsize) { - const Elf_Shdr *sh = reinterpret_cast(i); + // To find the symbol tables we walk the section table to find SHT_SYMTAB. + const Elf_Shdr* SymbolTableSectionHeaderIndex = 0; + const Elf_Shdr* sh = reinterpret_cast(SectionHeaderTable); + for (uint64_t i = 0, e = getNumSections(); i != e; ++i) { + if (sh->sh_type == ELF::SHT_SYMTAB_SHNDX) { + if (SymbolTableSectionHeaderIndex) + // FIXME: Proper error handling. + report_fatal_error("More than one .symtab_shndx!"); + SymbolTableSectionHeaderIndex = sh; + } if (sh->sh_type == ELF::SHT_SYMTAB) { + SymbolTableSectionsIndexMap[i] = SymbolTableSections.size(); SymbolTableSections.push_back(sh); } + if (sh->sh_type == ELF::SHT_REL || sh->sh_type == ELF::SHT_RELA) { + SectionRelocMap[getSection(sh->sh_info)].push_back(i); + } + ++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. - dot_shstrtab_sec = getSection(Header->e_shstrndx); + dot_shstrtab_sec = getSection(getStringTableIndex()); if (dot_shstrtab_sec) { // Verify that the last byte in the string table in a null. if (((const char*)base() + dot_shstrtab_sec->sh_offset) @@ -550,7 +1137,7 @@ ELFObjectFile::ELFObjectFile(MemoryBuffer *Object // Merge this into the above loop. for (const char *i = reinterpret_cast(SectionHeaderTable), - *e = i + Header->e_shnum * Header->e_shentsize; + *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) { @@ -567,11 +1154,26 @@ ELFObjectFile::ELFObjectFile(MemoryBuffer *Object } } } + + // 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!"); + if (*ShndxTable != ELF::SHN_UNDEF) + ExtendedSymbolTable[getSymbol(si->getRawDataRefImpl())] = *ShndxTable; + ++ShndxTable; + } + } } template -ObjectFile::symbol_iterator ELFObjectFile - ::begin_symbols() const { +symbol_iterator ELFObjectFile + ::begin_symbols() const { DataRefImpl SymbolData; memset(&SymbolData, 0, sizeof(SymbolData)); if (SymbolTableSections.size() == 0) { @@ -585,8 +1187,8 @@ ObjectFile::symbol_iterator ELFObjectFile } template -ObjectFile::symbol_iterator ELFObjectFile - ::end_symbols() const { +symbol_iterator ELFObjectFile + ::end_symbols() const { DataRefImpl SymbolData; memset(&SymbolData, 0, sizeof(SymbolData)); SymbolData.d.a = std::numeric_limits::max(); @@ -595,8 +1197,8 @@ ObjectFile::symbol_iterator ELFObjectFile } template -ObjectFile::section_iterator ELFObjectFile - ::begin_sections() const { +section_iterator ELFObjectFile + ::begin_sections() const { DataRefImpl ret; memset(&ret, 0, sizeof(DataRefImpl)); ret.p = reinterpret_cast(base() + Header->e_shoff); @@ -604,13 +1206,13 @@ ObjectFile::section_iterator ELFObjectFile } template -ObjectFile::section_iterator ELFObjectFile - ::end_sections() const { +section_iterator ELFObjectFile + ::end_sections() const { DataRefImpl ret; memset(&ret, 0, sizeof(DataRefImpl)); ret.p = reinterpret_cast(base() + Header->e_shoff - + (Header->e_shentsize * Header->e_shnum)); + + (Header->e_shentsize*getNumSections())); return section_iterator(SectionRef(ret, this)); } @@ -629,6 +1231,8 @@ StringRef ELFObjectFile return "ELF32-i386"; case ELF::EM_X86_64: return "ELF32-x86-64"; + case ELF::EM_ARM: + return "ELF32-arm"; default: return "ELF32-unknown"; } @@ -654,26 +1258,75 @@ unsigned ELFObjectFile::getArch() const { return Triple::x86; case ELF::EM_X86_64: return Triple::x86_64; + case ELF::EM_ARM: + return Triple::arm; default: return Triple::UnknownArch; } } +template +uint64_t ELFObjectFile::getNumSections() const { + if (Header->e_shnum == ELF::SHN_UNDEF) + 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 { + 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 { - const Elf_Shdr *sec = SymbolTableSections[Symb.d.b]; - return reinterpret_cast( - base() - + sec->sh_offset - + (Symb.d.a * sec->sh_entsize)); + 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) + 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; @@ -681,10 +1334,10 @@ ELFObjectFile::getSection(DataRefImpl Symb) const { template const typename ELFObjectFile::Elf_Shdr * -ELFObjectFile::getSection(uint16_t index) const { - if (index == 0 || index >= ELF::SHN_LORESERVE) +ELFObjectFile::getSection(uint32_t index) const { + if (index == 0) return 0; - if (!SectionHeaderTable || index >= Header->e_shnum) + if (!SectionHeaderTable || index >= getNumSections()) // FIXME: Proper error handling. report_fatal_error("Invalid section index!"); @@ -695,7 +1348,7 @@ ELFObjectFile::getSection(uint16_t index) const { template const char *ELFObjectFile - ::getString(uint16_t section, + ::getString(uint32_t section, ELF::Elf32_Word offset) const { return getString(getSection(section), offset); } @@ -711,6 +1364,24 @@ const char *ELFObjectFile return (const char *)base() + section->sh_offset + offset; } +template +error_code ELFObjectFile + ::getSymbolName(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; + } + + // Use the default symbol table name section. + Result = getString(dot_strtab_sec, symb->st_name); + return object_error::success; +} + // EI_CLASS, EI_DATA. static std::pair getElfArchType(MemoryBuffer *Object) { diff --git a/contrib/llvm/lib/Object/MachOObject.cpp b/contrib/llvm/lib/Object/MachOObject.cpp index 9890febfb..9cdac8681 100644 --- a/contrib/llvm/lib/Object/MachOObject.cpp +++ b/contrib/llvm/lib/Object/MachOObject.cpp @@ -9,6 +9,7 @@ #include "llvm/Object/MachOObject.h" #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Host.h" #include "llvm/Support/SwapByteOrder.h" @@ -243,6 +244,18 @@ void MachOObject::ReadDysymtabLoadCommand(const LoadCommandInfo &LCI, ReadInMemoryStruct(*this, Buffer->getBuffer(), LCI.Offset, Res); } +template<> +void SwapStruct(macho::LinkeditDataLoadCommand &Value) { + SwapValue(Value.Type); + SwapValue(Value.Size); + SwapValue(Value.DataOffset); + SwapValue(Value.DataSize); +} +void MachOObject::ReadLinkeditDataLoadCommand(const LoadCommandInfo &LCI, + InMemoryStruct &Res) const { + ReadInMemoryStruct(*this, Buffer->getBuffer(), LCI.Offset, Res); +} + template<> void SwapStruct(macho::IndirectSymbolTableEntry &Value) { SwapValue(Value.Index); @@ -343,6 +356,31 @@ void MachOObject::ReadSymbol64TableEntry(uint64_t SymbolTableOffset, ReadInMemoryStruct(*this, Buffer->getBuffer(), Offset, Res); } + +void MachOObject::ReadULEB128s(uint64_t Index, + SmallVectorImpl &Out) const { + const char *ptr = Buffer->getBufferStart() + Index; + uint64_t data = 0; + uint64_t delta = 0; + uint32_t shift = 0; + while (true) { + assert(ptr < Buffer->getBufferEnd() && "index out of bounds"); + assert(shift < 64 && "too big for uint64_t"); + + uint8_t byte = *ptr++; + delta |= ((byte & 0x7F) << shift); + shift += 7; + if (byte < 0x80) { + if (delta == 0) + break; + data += delta; + Out.push_back(data); + delta = 0; + shift = 0; + } + } +} + /* ** */ // Object Dumping Facilities void MachOObject::dump() const { print(dbgs()); dbgs() << '\n'; } diff --git a/contrib/llvm/lib/Object/MachOObjectFile.cpp b/contrib/llvm/lib/Object/MachOObjectFile.cpp index 26a6e136d..507df5865 100644 --- a/contrib/llvm/lib/Object/MachOObjectFile.cpp +++ b/contrib/llvm/lib/Object/MachOObjectFile.cpp @@ -13,11 +13,9 @@ //===----------------------------------------------------------------------===// #include "llvm/ADT/Triple.h" +#include "llvm/Object/MachO.h" #include "llvm/Object/MachOFormat.h" -#include "llvm/Object/MachOObject.h" -#include "llvm/Object/ObjectFile.h" #include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/MachO.h" #include #include @@ -27,56 +25,24 @@ using namespace llvm; using namespace object; namespace llvm { +namespace object { -typedef MachOObject::LoadCommandInfo LoadCommandInfo; - -class MachOObjectFile : public ObjectFile { -public: - MachOObjectFile(MemoryBuffer *Object, MachOObject *MOO, error_code &ec) +MachOObjectFile::MachOObjectFile(MemoryBuffer *Object, MachOObject *MOO, + error_code &ec) : ObjectFile(Binary::isMachO, Object, ec), MachOObj(MOO), - RegisteredStringTable(std::numeric_limits::max()) {} - - virtual symbol_iterator begin_symbols() const; - virtual symbol_iterator end_symbols() const; - virtual section_iterator begin_sections() const; - virtual section_iterator end_sections() const; - - virtual uint8_t getBytesInAddress() const; - virtual StringRef getFileFormatName() const; - virtual unsigned getArch() const; - -protected: - virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const; - virtual error_code getSymbolName(DataRefImpl Symb, StringRef &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 isSymbolInternal(DataRefImpl Symb, bool &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 isSectionText(DataRefImpl Sec, bool &Res) const; - virtual error_code sectionContainsSymbol(DataRefImpl DRI, DataRefImpl S, - bool &Result) const; - -private: - MachOObject *MachOObj; - mutable uint32_t RegisteredStringTable; - - void moveToNextSection(DataRefImpl &DRI) const; - void getSymbolTableEntry(DataRefImpl DRI, - InMemoryStruct &Res) const; - void getSymbol64TableEntry(DataRefImpl DRI, - InMemoryStruct &Res) const; - void moveToNextSymbol(DataRefImpl &DRI) const; - void getSection(DataRefImpl DRI, InMemoryStruct &Res) const; - void getSection64(DataRefImpl DRI, - InMemoryStruct &Res) const; -}; + RegisteredStringTable(std::numeric_limits::max()) { + DataRefImpl DRI; + DRI.d.a = DRI.d.b = 0; + moveToNextSection(DRI); + uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands; + while (DRI.d.a < LoadCommandCount) { + Sections.push_back(DRI); + DRI.d.b++; + moveToNextSection(DRI); + } +} + ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) { error_code ec; @@ -158,6 +124,27 @@ error_code MachOObjectFile::getSymbolName(DataRefImpl DRI, return object_error::success; } +error_code MachOObjectFile::getSymbolOffset(DataRefImpl DRI, + uint64_t &Result) const { + uint64_t SectionOffset; + uint8_t SectionIndex; + if (MachOObj->is64Bit()) { + InMemoryStruct Entry; + getSymbol64TableEntry(DRI, Entry); + Result = Entry->Value; + SectionIndex = Entry->SectionIndex; + } else { + InMemoryStruct Entry; + getSymbolTableEntry(DRI, Entry); + Result = Entry->Value; + SectionIndex = Entry->SectionIndex; + } + getSectionAddress(Sections[SectionIndex-1], SectionOffset); + Result -= SectionOffset; + + return object_error::success; +} + error_code MachOObjectFile::getSymbolAddress(DataRefImpl DRI, uint64_t &Result) const { if (MachOObj->is64Bit()) { @@ -227,7 +214,51 @@ error_code MachOObjectFile::isSymbolInternal(DataRefImpl DRI, return object_error::success; } -ObjectFile::symbol_iterator MachOObjectFile::begin_symbols() const { +error_code MachOObjectFile::isSymbolGlobal(DataRefImpl Symb, bool &Res) const { + + if (MachOObj->is64Bit()) { + InMemoryStruct Entry; + getSymbol64TableEntry(Symb, Entry); + Res = Entry->Type & MachO::NlistMaskExternal; + } else { + InMemoryStruct Entry; + getSymbolTableEntry(Symb, Entry); + Res = Entry->Type & MachO::NlistMaskExternal; + } + return object_error::success; +} + +error_code MachOObjectFile::getSymbolType(DataRefImpl Symb, + SymbolRef::SymbolType &Res) const { + uint8_t n_type; + if (MachOObj->is64Bit()) { + InMemoryStruct Entry; + getSymbol64TableEntry(Symb, Entry); + n_type = Entry->Type; + } else { + InMemoryStruct Entry; + getSymbolTableEntry(Symb, Entry); + n_type = Entry->Type; + } + Res = SymbolRef::ST_Other; + + // If this is a STAB debugging symbol, we can do nothing more. + if (n_type & MachO::NlistMaskStab) + return object_error::success; + + switch (n_type & MachO::NlistMaskType) { + case MachO::NListTypeUndefined : + Res = SymbolRef::ST_External; + break; + case MachO::NListTypeSection : + Res = SymbolRef::ST_Function; + break; + } + return object_error::success; +} + + +symbol_iterator MachOObjectFile::begin_symbols() const { // DRI.d.a = segment number; DRI.d.b = symbol index. DataRefImpl DRI; DRI.d.a = DRI.d.b = 0; @@ -235,7 +266,7 @@ ObjectFile::symbol_iterator MachOObjectFile::begin_symbols() const { return symbol_iterator(SymbolRef(DRI, this)); } -ObjectFile::symbol_iterator MachOObjectFile::end_symbols() const { +symbol_iterator MachOObjectFile::end_symbols() const { DataRefImpl DRI; DRI.d.a = MachOObj->getHeader().NumLoadCommands; DRI.d.b = 0; @@ -283,6 +314,13 @@ MachOObjectFile::getSection(DataRefImpl DRI, MachOObj->ReadSection(LCI, DRI.d.b, Res); } +std::size_t MachOObjectFile::getSectionIndex(DataRefImpl Sec) const { + SectionList::const_iterator loc = + std::find(Sections.begin(), Sections.end(), Sec); + assert(loc != Sections.end() && "Sec is not a valid section!"); + return std::distance(Sections.begin(), loc); +} + void MachOObjectFile::getSection64(DataRefImpl DRI, InMemoryStruct &Res) const { @@ -371,6 +409,20 @@ error_code MachOObjectFile::getSectionContents(DataRefImpl DRI, return object_error::success; } +error_code MachOObjectFile::getSectionAlignment(DataRefImpl DRI, + uint64_t &Result) const { + if (is64BitLoadCommand(MachOObj, DRI)) { + InMemoryStruct Sect; + getSection64(DRI, Sect); + Result = uint64_t(1) << Sect->Align; + } else { + InMemoryStruct Sect; + getSection(DRI, Sect); + Result = uint64_t(1) << Sect->Align; + } + return object_error::success; +} + error_code MachOObjectFile::isSectionText(DataRefImpl DRI, bool &Result) const { if (is64BitLoadCommand(MachOObj, DRI)) { @@ -385,35 +437,185 @@ error_code MachOObjectFile::isSectionText(DataRefImpl DRI, return object_error::success; } +error_code MachOObjectFile::isSectionData(DataRefImpl DRI, + bool &Result) const { + // FIXME: Unimplemented. + Result = false; + return object_error::success; +} + +error_code MachOObjectFile::isSectionBSS(DataRefImpl DRI, + bool &Result) const { + // FIXME: Unimplemented. + Result = false; + return object_error::success; +} + error_code MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, bool &Result) const { + SymbolRef::SymbolType ST; + getSymbolType(Symb, ST); + if (ST == SymbolRef::ST_External) { + Result = false; + return object_error::success; + } + + uint64_t SectBegin, SectEnd; + getSectionAddress(Sec, SectBegin); + getSectionSize(Sec, SectEnd); + SectEnd += SectBegin; + if (MachOObj->is64Bit()) { InMemoryStruct Entry; getSymbol64TableEntry(Symb, Entry); - Result = Entry->SectionIndex == 1 + Sec.d.a + Sec.d.b; + uint64_t SymAddr= Entry->Value; + Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd); } else { InMemoryStruct Entry; getSymbolTableEntry(Symb, Entry); - Result = Entry->SectionIndex == 1 + Sec.d.a + Sec.d.b; + uint64_t SymAddr= Entry->Value; + Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd); } + return object_error::success; } -ObjectFile::section_iterator MachOObjectFile::begin_sections() const { +relocation_iterator MachOObjectFile::getSectionRelBegin(DataRefImpl Sec) const { + DataRefImpl ret; + ret.d.a = 0; + ret.d.b = getSectionIndex(Sec); + return relocation_iterator(RelocationRef(ret, this)); +} +relocation_iterator MachOObjectFile::getSectionRelEnd(DataRefImpl Sec) const { + uint32_t last_reloc; + if (is64BitLoadCommand(MachOObj, Sec)) { + InMemoryStruct Sect; + getSection64(Sec, Sect); + last_reloc = Sect->NumRelocationTableEntries; + } else { + InMemoryStruct Sect; + getSection(Sec, Sect); + last_reloc = Sect->NumRelocationTableEntries; + } + DataRefImpl ret; + ret.d.a = last_reloc; + ret.d.b = getSectionIndex(Sec); + return relocation_iterator(RelocationRef(ret, this)); +} + +section_iterator MachOObjectFile::begin_sections() const { DataRefImpl DRI; DRI.d.a = DRI.d.b = 0; moveToNextSection(DRI); return section_iterator(SectionRef(DRI, this)); } -ObjectFile::section_iterator MachOObjectFile::end_sections() const { +section_iterator MachOObjectFile::end_sections() const { DataRefImpl DRI; DRI.d.a = MachOObj->getHeader().NumLoadCommands; DRI.d.b = 0; return section_iterator(SectionRef(DRI, this)); } +/*===-- Relocations -------------------------------------------------------===*/ + +void MachOObjectFile:: +getRelocation(DataRefImpl Rel, + InMemoryStruct &Res) const { + uint32_t relOffset; + if (MachOObj->is64Bit()) { + InMemoryStruct Sect; + getSection64(Sections[Rel.d.b], Sect); + relOffset = Sect->RelocationTableOffset; + } else { + InMemoryStruct Sect; + getSection(Sections[Rel.d.b], Sect); + relOffset = Sect->RelocationTableOffset; + } + MachOObj->ReadRelocationEntry(relOffset, Rel.d.a, Res); +} +error_code MachOObjectFile::getRelocationNext(DataRefImpl Rel, + RelocationRef &Res) const { + ++Rel.d.a; + Res = RelocationRef(Rel, this); + return object_error::success; +} +error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel, + uint64_t &Res) const { + const uint8_t* sectAddress = base(); + if (MachOObj->is64Bit()) { + InMemoryStruct Sect; + getSection64(Sections[Rel.d.b], Sect); + sectAddress += Sect->Offset; + } else { + InMemoryStruct Sect; + getSection(Sections[Rel.d.b], Sect); + sectAddress += Sect->Offset; + } + InMemoryStruct RE; + getRelocation(Rel, RE); + Res = reinterpret_cast(sectAddress + RE->Word0); + return object_error::success; +} +error_code MachOObjectFile::getRelocationSymbol(DataRefImpl Rel, + SymbolRef &Res) const { + InMemoryStruct RE; + getRelocation(Rel, RE); + uint32_t SymbolIdx = RE->Word1 & 0xffffff; + bool isExtern = (RE->Word1 >> 27) & 1; + + DataRefImpl Sym; + Sym.d.a = Sym.d.b = 0; + moveToNextSymbol(Sym); + if (isExtern) { + for (unsigned i = 0; i < SymbolIdx; i++) { + Sym.d.b++; + moveToNextSymbol(Sym); + assert(Sym.d.a < MachOObj->getHeader().NumLoadCommands && + "Relocation symbol index out of range!"); + } + } + Res = SymbolRef(Sym, this); + return object_error::success; +} +error_code MachOObjectFile::getRelocationType(DataRefImpl Rel, + uint32_t &Res) const { + InMemoryStruct RE; + getRelocation(Rel, RE); + Res = RE->Word1; + return object_error::success; +} +error_code MachOObjectFile::getRelocationTypeName(DataRefImpl Rel, + SmallVectorImpl &Result) const { + return object_error::success; +} +error_code MachOObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel, + int64_t &Res) const { + InMemoryStruct RE; + getRelocation(Rel, RE); + bool isExtern = (RE->Word1 >> 27) & 1; + Res = 0; + if (!isExtern) { + const uint8_t* sectAddress = base(); + if (MachOObj->is64Bit()) { + InMemoryStruct Sect; + getSection64(Sections[Rel.d.b], Sect); + sectAddress += Sect->Offset; + } else { + InMemoryStruct Sect; + getSection(Sections[Rel.d.b], Sect); + sectAddress += Sect->Offset; + } + Res = reinterpret_cast(sectAddress); + } + return object_error::success; +} +error_code MachOObjectFile::getRelocationValueString(DataRefImpl Rel, + SmallVectorImpl &Result) const { + return object_error::success; +} + /*===-- Miscellaneous -----------------------------------------------------===*/ uint8_t MachOObjectFile::getBytesInAddress() const { @@ -465,5 +667,5 @@ unsigned MachOObjectFile::getArch() const { } } +} // end namespace object } // end namespace llvm - diff --git a/contrib/llvm/lib/Object/Makefile b/contrib/llvm/lib/Object/Makefile deleted file mode 100644 index 79388dc97..000000000 --- a/contrib/llvm/lib/Object/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- lib/Object/Makefile ---------------------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../.. -LIBRARYNAME = LLVMObject -BUILD_ARCHIVE := 1 - -include $(LEVEL)/Makefile.common diff --git a/contrib/llvm/lib/Object/Object.cpp b/contrib/llvm/lib/Object/Object.cpp index 9a373ad21..2ea8db978 100644 --- a/contrib/llvm/lib/Object/Object.cpp +++ b/contrib/llvm/lib/Object/Object.cpp @@ -27,8 +27,8 @@ void LLVMDisposeObjectFile(LLVMObjectFileRef ObjectFile) { } LLVMSectionIteratorRef LLVMGetSections(LLVMObjectFileRef ObjectFile) { - ObjectFile::section_iterator SI = unwrap(ObjectFile)->begin_sections(); - return wrap(new ObjectFile::section_iterator(SI)); + section_iterator SI = unwrap(ObjectFile)->begin_sections(); + return wrap(new section_iterator(SI)); } void LLVMDisposeSectionIterator(LLVMSectionIteratorRef SI) { diff --git a/contrib/llvm/lib/Object/ObjectFile.cpp b/contrib/llvm/lib/Object/ObjectFile.cpp index a7798df33..69d8ed0e5 100644 --- a/contrib/llvm/lib/Object/ObjectFile.cpp +++ b/contrib/llvm/lib/Object/ObjectFile.cpp @@ -45,6 +45,7 @@ ObjectFile *ObjectFile::createObjectFile(MemoryBuffer *Object) { case sys::Mach_O_DynamicLinker_FileType: case sys::Mach_O_Bundle_FileType: case sys::Mach_O_DynamicallyLinkedSharedLibStub_FileType: + case sys::Mach_O_DSYMCompanion_FileType: return createMachOObjectFile(Object); case sys::COFF_FileType: return createCOFFObjectFile(Object); diff --git a/contrib/llvm/lib/Support/APFloat.cpp b/contrib/llvm/lib/Support/APFloat.cpp index c64da6e13..f23889449 100644 --- a/contrib/llvm/lib/Support/APFloat.cpp +++ b/contrib/llvm/lib/Support/APFloat.cpp @@ -832,6 +832,7 @@ APFloat::incrementSignificand() /* Our callers should never cause us to overflow. */ assert(carry == 0); + (void)carry; } /* Add the significand of the RHS. Returns the carry flag. */ @@ -926,6 +927,7 @@ APFloat::multiplySignificand(const APFloat &rhs, const APFloat *addend) APFloat extendedAddend(*addend); status = extendedAddend.convert(extendedSemantics, rmTowardZero, &ignored); assert(status == opOK); + (void)status; lost_fraction = addOrSubtractSignificand(extendedAddend, false); /* Restore our state. */ @@ -1190,7 +1192,7 @@ APFloat::normalize(roundingMode rounding_mode, if (omsb) { /* OMSB is numbered from 1. We want to place it in the integer - bit numbered PRECISON if possible, with a compensating change in + bit numbered PRECISION if possible, with a compensating change in the exponent. */ exponentChange = omsb - semantics->precision; @@ -1389,6 +1391,7 @@ APFloat::addOrSubtractSignificand(const APFloat &rhs, bool subtract) /* The code above is intended to ensure that no borrow is necessary. */ assert(!carry); + (void)carry; } else { if (bits > 0) { APFloat temp_rhs(rhs); @@ -1402,6 +1405,7 @@ APFloat::addOrSubtractSignificand(const APFloat &rhs, bool subtract) /* We have a guard bit; generating a carry cannot happen. */ assert(!carry); + (void)carry; } return lost_fraction; @@ -2098,7 +2102,7 @@ APFloat::convertToInteger(APSInt &result, opStatus status = convertToInteger( parts.data(), bitWidth, result.isSigned(), rounding_mode, isExact); // Keeps the original signed-ness. - result = APInt(bitWidth, (unsigned)parts.size(), parts.data()); + result = APInt(bitWidth, parts); return status; } @@ -2121,7 +2125,7 @@ APFloat::convertFromUnsignedParts(const integerPart *src, dstCount = partCount(); precision = semantics->precision; - /* We want the most significant PRECISON bits of SRC. There may not + /* We want the most significant PRECISION bits of SRC. There may not be that many; extract what we can. */ if (precision <= omsb) { exponent = omsb - 1; @@ -2192,7 +2196,7 @@ APFloat::convertFromZeroExtendedInteger(const integerPart *parts, roundingMode rounding_mode) { unsigned int partCount = partCountForBits(width); - APInt api = APInt(width, partCount, parts); + APInt api = APInt(width, makeArrayRef(parts, partCount)); sign = false; if (isSigned && APInt::tcExtractBit(parts, width - 1)) { @@ -2746,7 +2750,7 @@ APFloat::convertF80LongDoubleAPFloatToAPInt() const words[0] = mysignificand; words[1] = ((uint64_t)(sign & 1) << 15) | (myexponent & 0x7fffLL); - return APInt(80, 2, words); + return APInt(80, words); } APInt @@ -2791,7 +2795,7 @@ APFloat::convertPPCDoubleDoubleAPFloatToAPInt() const words[1] = ((uint64_t)(sign2 & 1) << 63) | ((myexponent2 & 0x7ff) << 52) | (mysignificand2 & 0xfffffffffffffLL); - return APInt(128, 2, words); + return APInt(128, words); } APInt @@ -2827,7 +2831,7 @@ APFloat::convertQuadrupleAPFloatToAPInt() const ((myexponent & 0x7fff) << 48) | (mysignificand2 & 0xffffffffffffLL); - return APInt(128, 2, words); + return APInt(128, words); } APInt @@ -3239,8 +3243,9 @@ APFloat APFloat::getLargest(const fltSemantics &Sem, bool Negative) { significand[i] = ~((integerPart) 0); // ...and then clear the top bits for internal consistency. - significand[N-1] &= - (((integerPart) 1) << ((Sem.precision % integerPartWidth) - 1)) - 1; + if (Sem.precision % integerPartWidth != 0) + significand[N-1] &= + (((integerPart) 1) << (Sem.precision % integerPartWidth)) - 1; return Val; } @@ -3270,7 +3275,7 @@ APFloat APFloat::getSmallestNormalized(const fltSemantics &Sem, bool Negative) { Val.exponent = Sem.minExponent; Val.zeroSignificand(); Val.significandParts()[partCountForBits(Sem.precision)-1] |= - (((integerPart) 1) << ((Sem.precision % integerPartWidth) - 1)); + (((integerPart) 1) << ((Sem.precision - 1) % integerPartWidth)); return Val; } @@ -3413,8 +3418,8 @@ void APFloat::toString(SmallVectorImpl &Str, // Decompose the number into an APInt and an exponent. int exp = exponent - ((int) semantics->precision - 1); APInt significand(semantics->precision, - partCountForBits(semantics->precision), - significandParts()); + makeArrayRef(significandParts(), + partCountForBits(semantics->precision))); // Set FormatPrecision if zero. We want to do this before we // truncate trailing zeros, as those are part of the precision. @@ -3451,7 +3456,7 @@ void APFloat::toString(SmallVectorImpl &Str, // <= semantics->precision + e * 137 / 59 // (log_2(5) ~ 2.321928 < 2.322034 ~ 137/59) - unsigned precision = semantics->precision + 137 * texp / 59; + unsigned precision = semantics->precision + (137 * texp + 136) / 59; // Multiply significand by 5^e. // N * 5^0101 == N * 5^(1*1) * 5^(0*2) * 5^(1*4) * 5^(0*8) diff --git a/contrib/llvm/lib/Support/APInt.cpp b/contrib/llvm/lib/Support/APInt.cpp index 76265d445..3774c5223 100644 --- a/contrib/llvm/lib/Support/APInt.cpp +++ b/contrib/llvm/lib/Support/APInt.cpp @@ -48,18 +48,20 @@ inline static uint64_t* getMemory(unsigned numWords) { inline static unsigned getDigit(char cdigit, uint8_t radix) { unsigned r; - if (radix == 16) { + if (radix == 16 || radix == 36) { r = cdigit - '0'; if (r <= 9) return r; r = cdigit - 'A'; - if (r <= 5) + if (r <= radix - 11U) return r + 10; r = cdigit - 'a'; - if (r <= 5) + if (r <= radix - 11U) return r + 10; + + radix = 10; } r = cdigit - '0'; @@ -83,25 +85,33 @@ void APInt::initSlowCase(const APInt& that) { memcpy(pVal, that.pVal, getNumWords() * APINT_WORD_SIZE); } - -APInt::APInt(unsigned numBits, unsigned numWords, const uint64_t bigVal[]) - : BitWidth(numBits), VAL(0) { +void APInt::initFromArray(ArrayRef bigVal) { assert(BitWidth && "Bitwidth too small"); - assert(bigVal && "Null pointer detected!"); + assert(bigVal.data() && "Null pointer detected!"); if (isSingleWord()) VAL = bigVal[0]; else { // Get memory, cleared to 0 pVal = getClearedMemory(getNumWords()); // Calculate the number of words to copy - unsigned words = std::min(numWords, getNumWords()); + unsigned words = std::min(bigVal.size(), getNumWords()); // Copy the words from bigVal to pVal - memcpy(pVal, bigVal, words * APINT_WORD_SIZE); + memcpy(pVal, bigVal.data(), words * APINT_WORD_SIZE); } // Make sure unused high bits are cleared clearUnusedBits(); } +APInt::APInt(unsigned numBits, ArrayRef bigVal) + : BitWidth(numBits), VAL(0) { + initFromArray(bigVal); +} + +APInt::APInt(unsigned numBits, unsigned numWords, const uint64_t bigVal[]) + : BitWidth(numBits), VAL(0) { + initFromArray(makeArrayRef(bigVal, numWords)); +} + APInt::APInt(unsigned numbits, StringRef Str, uint8_t radix) : BitWidth(numbits), VAL(0) { assert(BitWidth && "Bitwidth too small"); @@ -376,6 +386,7 @@ APInt& APInt::operator*=(const APInt& RHS) { clearAllBits(); unsigned wordsToCopy = destWords >= getNumWords() ? getNumWords() : destWords; memcpy(pVal, dest, wordsToCopy * APINT_WORD_SIZE); + clearUnusedBits(); // delete dest array and return delete[] dest; @@ -461,7 +472,7 @@ APInt APInt::operator*(const APInt& RHS) const { return APInt(BitWidth, VAL * RHS.VAL); APInt Result(*this); Result *= RHS; - return Result.clearUnusedBits(); + return Result; } APInt APInt::operator+(const APInt& RHS) const { @@ -613,8 +624,9 @@ void APInt::flipBit(unsigned bitPosition) { unsigned APInt::getBitsNeeded(StringRef str, uint8_t radix) { assert(!str.empty() && "Invalid string length"); - assert((radix == 10 || radix == 8 || radix == 16 || radix == 2) && - "Radix should be 2, 8, 10, or 16!"); + assert((radix == 10 || radix == 8 || radix == 16 || radix == 2 || + radix == 36) && + "Radix should be 2, 8, 10, 16, or 36!"); size_t slen = str.size(); @@ -636,6 +648,8 @@ unsigned APInt::getBitsNeeded(StringRef str, uint8_t radix) { if (radix == 16) return slen * 4 + isNegative; + // FIXME: base 36 + // This is grossly inefficient but accurate. We could probably do something // with a computation of roughly slen*64/20 and then adjust by the value of // the first few digits. But, I'm not sure how accurate that could be. @@ -644,7 +658,9 @@ unsigned APInt::getBitsNeeded(StringRef str, uint8_t radix) { // be too large. This avoids the assertion in the constructor. This // calculation doesn't work appropriately for the numbers 0-9, so just use 4 // bits in that case. - unsigned sufficient = slen == 1 ? 4 : slen * 64/18; + unsigned sufficient + = radix == 10? (slen == 1 ? 4 : slen * 64/18) + : (slen == 1 ? 7 : slen * 16/3); // Convert to the actual binary value. APInt tmp(sufficient, StringRef(p, slen), radix); @@ -2107,8 +2123,9 @@ APInt APInt::sshl_ov(unsigned ShAmt, bool &Overflow) const { void APInt::fromString(unsigned numbits, StringRef str, uint8_t radix) { // Check our assumptions here assert(!str.empty() && "Invalid string length"); - assert((radix == 10 || radix == 8 || radix == 16 || radix == 2) && - "Radix should be 2, 8, 10, or 16!"); + assert((radix == 10 || radix == 8 || radix == 16 || radix == 2 || + radix == 36) && + "Radix should be 2, 8, 10, 16, or 36!"); StringRef::iterator p = str.begin(); size_t slen = str.size(); @@ -2165,7 +2182,8 @@ void APInt::fromString(unsigned numbits, StringRef str, uint8_t radix) { void APInt::toString(SmallVectorImpl &Str, unsigned Radix, bool Signed, bool formatAsCLiteral) const { - assert((Radix == 10 || Radix == 8 || Radix == 16 || Radix == 2) && + assert((Radix == 10 || Radix == 8 || Radix == 16 || Radix == 2 || + Radix == 36) && "Radix should be 2, 8, 10, or 16!"); const char *Prefix = ""; @@ -2195,7 +2213,7 @@ void APInt::toString(SmallVectorImpl &Str, unsigned Radix, return; } - static const char Digits[] = "0123456789ABCDEF"; + static const char Digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; if (isSingleWord()) { char Buffer[65]; @@ -2249,7 +2267,7 @@ void APInt::toString(SmallVectorImpl &Str, unsigned Radix, // For the 2, 8 and 16 bit cases, we can just shift instead of divide // because the number of bits per digit (1, 3 and 4 respectively) divides // equaly. We just shift until the value is zero. - if (Radix != 10) { + if (Radix == 2 || Radix == 8 || Radix == 16) { // Just shift tmp right for each digit width until it becomes zero unsigned ShiftAmt = (Radix == 16 ? 4 : (Radix == 8 ? 3 : 1)); unsigned MaskAmt = Radix - 1; @@ -2260,7 +2278,7 @@ void APInt::toString(SmallVectorImpl &Str, unsigned Radix, Tmp = Tmp.lshr(ShiftAmt); } } else { - APInt divisor(4, 10); + APInt divisor(Radix == 10? 4 : 8, Radix); while (Tmp != 0) { APInt APdigit(1, 0); APInt tmp2(Tmp.getBitWidth(), 0); diff --git a/contrib/llvm/lib/Support/Atomic.cpp b/contrib/llvm/lib/Support/Atomic.cpp index 8214521f9..94760cc06 100644 --- a/contrib/llvm/lib/Support/Atomic.cpp +++ b/contrib/llvm/lib/Support/Atomic.cpp @@ -22,7 +22,7 @@ using namespace llvm; #endif void sys::MemoryFence() { -#if !defined(LLVM_MULTITHREADED) || LLVM_MULTITHREADED == 0 +#if LLVM_HAS_ATOMICS == 0 return; #else # if defined(__GNUC__) @@ -38,7 +38,7 @@ void sys::MemoryFence() { sys::cas_flag sys::CompareAndSwap(volatile sys::cas_flag* ptr, sys::cas_flag new_value, sys::cas_flag old_value) { -#if !defined(LLVM_MULTITHREADED) || LLVM_MULTITHREADED == 0 +#if LLVM_HAS_ATOMICS == 0 sys::cas_flag result = *ptr; if (result == old_value) *ptr = new_value; @@ -53,7 +53,7 @@ sys::cas_flag sys::CompareAndSwap(volatile sys::cas_flag* ptr, } sys::cas_flag sys::AtomicIncrement(volatile sys::cas_flag* ptr) { -#if !defined(LLVM_MULTITHREADED) || LLVM_MULTITHREADED == 0 +#if LLVM_HAS_ATOMICS == 0 ++(*ptr); return *ptr; #elif defined(__GNUC__) @@ -66,7 +66,7 @@ sys::cas_flag sys::AtomicIncrement(volatile sys::cas_flag* ptr) { } sys::cas_flag sys::AtomicDecrement(volatile sys::cas_flag* ptr) { -#if !defined(LLVM_MULTITHREADED) || LLVM_MULTITHREADED == 0 +#if LLVM_HAS_ATOMICS == 0 --(*ptr); return *ptr; #elif defined(__GNUC__) @@ -79,7 +79,7 @@ sys::cas_flag sys::AtomicDecrement(volatile sys::cas_flag* ptr) { } sys::cas_flag sys::AtomicAdd(volatile sys::cas_flag* ptr, sys::cas_flag val) { -#if !defined(LLVM_MULTITHREADED) || LLVM_MULTITHREADED == 0 +#if LLVM_HAS_ATOMICS == 0 *ptr += val; return *ptr; #elif defined(__GNUC__) diff --git a/contrib/llvm/lib/Support/BlockFrequency.cpp b/contrib/llvm/lib/Support/BlockFrequency.cpp new file mode 100644 index 000000000..a63bf83f2 --- /dev/null +++ b/contrib/llvm/lib/Support/BlockFrequency.cpp @@ -0,0 +1,126 @@ +//====--------------- lib/Support/BlockFrequency.cpp -----------*- 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 Block Frequency class. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/BranchProbability.h" +#include "llvm/Support/BlockFrequency.h" +#include "llvm/Support/raw_ostream.h" +#include + +using namespace llvm; + +namespace { + +/// mult96bit - Multiply FREQ by N and store result in W array. +void mult96bit(uint64_t freq, uint32_t N, uint64_t W[2]) { + uint64_t u0 = freq & UINT32_MAX; + uint64_t u1 = freq >> 32; + + // Represent 96-bit value as w[2]:w[1]:w[0]; + uint32_t w[3] = { 0, 0, 0 }; + + uint64_t t = u0 * N; + uint64_t k = t >> 32; + w[0] = t; + t = u1 * N + k; + w[1] = t; + w[2] = t >> 32; + + // W[1] - higher bits. + // W[0] - lower bits. + W[0] = w[0] + ((uint64_t) w[1] << 32); + W[1] = w[2]; +} + + +/// div96bit - Divide 96-bit value stored in W array by D. Return 64-bit frequency. +uint64_t div96bit(uint64_t W[2], uint32_t D) { + uint64_t y = W[0]; + uint64_t x = W[1]; + int i; + + for (i = 1; i <= 64 && x; ++i) { + uint32_t t = (int)x >> 31; + x = (x << 1) | (y >> 63); + y = y << 1; + if ((x | t) >= D) { + x -= D; + ++y; + } + } + + return y << (64 - i + 1); +} + +} + + +BlockFrequency &BlockFrequency::operator*=(const BranchProbability &Prob) { + uint32_t n = Prob.getNumerator(); + uint32_t d = Prob.getDenominator(); + + assert(n <= d && "Probability must be less or equal to 1."); + + // If we can overflow use 96-bit operations. + if (n > 0 && Frequency > UINT64_MAX / n) { + // 96-bit value represented as W[1]:W[0]. + uint64_t W[2]; + + // Probability is less or equal to 1 which means that results must fit + // 64-bit. + mult96bit(Frequency, n, W); + Frequency = div96bit(W, d); + return *this; + } + + Frequency *= n; + Frequency /= d; + return *this; +} + +const BlockFrequency +BlockFrequency::operator*(const BranchProbability &Prob) const { + BlockFrequency Freq(Frequency); + Freq *= Prob; + return Freq; +} + +BlockFrequency &BlockFrequency::operator+=(const BlockFrequency &Freq) { + uint64_t Before = Freq.Frequency; + Frequency += Freq.Frequency; + + // If overflow, set frequency to the maximum value. + if (Frequency < Before) + Frequency = UINT64_MAX; + + return *this; +} + +const BlockFrequency +BlockFrequency::operator+(const BlockFrequency &Prob) const { + BlockFrequency Freq(Frequency); + Freq += Prob; + return Freq; +} + +void BlockFrequency::print(raw_ostream &OS) const { + OS << Frequency; +} + +namespace llvm { + +raw_ostream &operator<<(raw_ostream &OS, const BlockFrequency &Freq) { + Freq.print(OS); + return OS; +} + +} diff --git a/contrib/llvm/lib/Support/BranchProbability.cpp b/contrib/llvm/lib/Support/BranchProbability.cpp index 97342da3f..49d04ed83 100644 --- a/contrib/llvm/lib/Support/BranchProbability.cpp +++ b/contrib/llvm/lib/Support/BranchProbability.cpp @@ -24,9 +24,8 @@ BranchProbability::BranchProbability(uint32_t n, uint32_t d) { D = d; } -raw_ostream &BranchProbability::print(raw_ostream &OS) const { +void BranchProbability::print(raw_ostream &OS) const { OS << N << " / " << D << " = " << ((double)N / D); - return OS; } void BranchProbability::dump() const { diff --git a/contrib/llvm/lib/Support/CommandLine.cpp b/contrib/llvm/lib/Support/CommandLine.cpp index 92c60a963..238adcce0 100644 --- a/contrib/llvm/lib/Support/CommandLine.cpp +++ b/contrib/llvm/lib/Support/CommandLine.cpp @@ -23,7 +23,6 @@ #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Support/system_error.h" -#include "llvm/Target/TargetRegistry.h" #include "llvm/Support/Host.h" #include "llvm/Support/Path.h" #include "llvm/ADT/OwningPtr.h" @@ -45,6 +44,7 @@ TEMPLATE_INSTANTIATION(class basic_parser); TEMPLATE_INSTANTIATION(class basic_parser); TEMPLATE_INSTANTIATION(class basic_parser); TEMPLATE_INSTANTIATION(class basic_parser); +TEMPLATE_INSTANTIATION(class basic_parser); TEMPLATE_INSTANTIATION(class basic_parser); TEMPLATE_INSTANTIATION(class basic_parser); TEMPLATE_INSTANTIATION(class basic_parser); @@ -63,6 +63,7 @@ void parser::anchor() {} void parser::anchor() {} void parser::anchor() {} void parser::anchor() {} +void parser::anchor() {} void parser::anchor() {} void parser::anchor() {} void parser::anchor() {} @@ -1006,6 +1007,16 @@ bool parser::parse(Option &O, StringRef ArgName, return false; } +// parser implementation +// +bool parser::parse(Option &O, StringRef ArgName, + StringRef Arg, unsigned long long &Value){ + + if (Arg.getAsInteger(0, Value)) + return O.error("'" + Arg + "' value invalid for uint argument!"); + return false; +} + // parser/parser implementation // static bool parseDouble(Option &O, StringRef Arg, double &Value) { @@ -1151,6 +1162,7 @@ PRINT_OPT_DIFF(bool) PRINT_OPT_DIFF(boolOrDefault) PRINT_OPT_DIFF(int) PRINT_OPT_DIFF(unsigned) +PRINT_OPT_DIFF(unsigned long long) PRINT_OPT_DIFF(double) PRINT_OPT_DIFF(float) PRINT_OPT_DIFF(char) @@ -1330,10 +1342,7 @@ void cl::PrintOptionValues() { static void (*OverrideVersionPrinter)() = 0; -static int TargetArraySortFn(const void *LHS, const void *RHS) { - typedef std::pair pair_ty; - return strcmp(((const pair_ty*)LHS)->first, ((const pair_ty*)RHS)->first); -} +static std::vector* ExtraVersionPrinters = 0; namespace { class VersionPrinter { @@ -1357,41 +1366,31 @@ public: std::string CPU = sys::getHostCPUName(); if (CPU == "generic") CPU = "(unknown)"; OS << ".\n" -#if defined(ENABLE_TIMESTAMPS) && ENABLE_TIMESTAMPS == 1 +#if (ENABLE_TIMESTAMPS == 1) << " Built " << __DATE__ << " (" << __TIME__ << ").\n" #endif << " Host: " << sys::getHostTriple() << '\n' - << " Host CPU: " << CPU << '\n' - << '\n' - << " Registered Targets:\n"; - - std::vector > Targets; - size_t Width = 0; - for (TargetRegistry::iterator it = TargetRegistry::begin(), - ie = TargetRegistry::end(); it != ie; ++it) { - Targets.push_back(std::make_pair(it->getName(), &*it)); - Width = std::max(Width, strlen(Targets.back().first)); - } - if (!Targets.empty()) - qsort(&Targets[0], Targets.size(), sizeof(Targets[0]), - TargetArraySortFn); - - for (unsigned i = 0, e = Targets.size(); i != e; ++i) { - OS << " " << Targets[i].first; - OS.indent(Width - strlen(Targets[i].first)) << " - " - << Targets[i].second->getShortDescription() << '\n'; - } - if (Targets.empty()) - OS << " (none)\n"; + << " Host CPU: " << CPU << '\n'; } void operator=(bool OptionWasSpecified) { if (!OptionWasSpecified) return; - if (OverrideVersionPrinter == 0) { - print(); + if (OverrideVersionPrinter != 0) { + (*OverrideVersionPrinter)(); exit(1); } - (*OverrideVersionPrinter)(); + print(); + + // Iterate over any registered extra printers and call them to add further + // information. + if (ExtraVersionPrinters != 0) { + outs() << '\n'; + for (std::vector::iterator I = ExtraVersionPrinters->begin(), + E = ExtraVersionPrinters->end(); + I != E; ++I) + (*I)(); + } + exit(1); } }; @@ -1424,3 +1423,10 @@ void cl::PrintVersionMessage() { void cl::SetVersionPrinter(void (*func)()) { OverrideVersionPrinter = func; } + +void cl::AddExtraVersionPrinter(void (*func)()) { + if (ExtraVersionPrinters == 0) + ExtraVersionPrinters = new std::vector; + + ExtraVersionPrinters->push_back(func); +} diff --git a/contrib/llvm/lib/Support/ConstantRange.cpp b/contrib/llvm/lib/Support/ConstantRange.cpp index 81382d08d..c29cb53fb 100644 --- a/contrib/llvm/lib/Support/ConstantRange.cpp +++ b/contrib/llvm/lib/Support/ConstantRange.cpp @@ -21,11 +21,10 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Constants.h" +#include "llvm/InstrTypes.h" #include "llvm/Support/ConstantRange.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/Instructions.h" using namespace llvm; /// Initialize a full (the default) or empty set for the specified type. @@ -56,56 +55,56 @@ ConstantRange ConstantRange::makeICmpRegion(unsigned Pred, uint32_t W = CR.getBitWidth(); switch (Pred) { - default: assert(!"Invalid ICmp predicate to makeICmpRegion()"); - case ICmpInst::ICMP_EQ: + default: assert(0 && "Invalid ICmp predicate to makeICmpRegion()"); + case CmpInst::ICMP_EQ: return CR; - case ICmpInst::ICMP_NE: + case CmpInst::ICMP_NE: if (CR.isSingleElement()) return ConstantRange(CR.getUpper(), CR.getLower()); return ConstantRange(W); - case ICmpInst::ICMP_ULT: { + case CmpInst::ICMP_ULT: { APInt UMax(CR.getUnsignedMax()); if (UMax.isMinValue()) return ConstantRange(W, /* empty */ false); return ConstantRange(APInt::getMinValue(W), UMax); } - case ICmpInst::ICMP_SLT: { + case CmpInst::ICMP_SLT: { APInt SMax(CR.getSignedMax()); if (SMax.isMinSignedValue()) return ConstantRange(W, /* empty */ false); return ConstantRange(APInt::getSignedMinValue(W), SMax); } - case ICmpInst::ICMP_ULE: { + case CmpInst::ICMP_ULE: { APInt UMax(CR.getUnsignedMax()); if (UMax.isMaxValue()) return ConstantRange(W); return ConstantRange(APInt::getMinValue(W), UMax + 1); } - case ICmpInst::ICMP_SLE: { + case CmpInst::ICMP_SLE: { APInt SMax(CR.getSignedMax()); if (SMax.isMaxSignedValue()) return ConstantRange(W); return ConstantRange(APInt::getSignedMinValue(W), SMax + 1); } - case ICmpInst::ICMP_UGT: { + case CmpInst::ICMP_UGT: { APInt UMin(CR.getUnsignedMin()); if (UMin.isMaxValue()) return ConstantRange(W, /* empty */ false); return ConstantRange(UMin + 1, APInt::getNullValue(W)); } - case ICmpInst::ICMP_SGT: { + case CmpInst::ICMP_SGT: { APInt SMin(CR.getSignedMin()); if (SMin.isMaxSignedValue()) return ConstantRange(W, /* empty */ false); return ConstantRange(SMin + 1, APInt::getSignedMinValue(W)); } - case ICmpInst::ICMP_UGE: { + case CmpInst::ICMP_UGE: { APInt UMin(CR.getUnsignedMin()); if (UMin.isMinValue()) return ConstantRange(W); return ConstantRange(UMin, APInt::getNullValue(W)); } - case ICmpInst::ICMP_SGE: { + case CmpInst::ICMP_SGE: { APInt SMin(CR.getSignedMin()); if (SMin.isMinSignedValue()) return ConstantRange(W); diff --git a/contrib/llvm/lib/Support/CrashRecoveryContext.cpp b/contrib/llvm/lib/Support/CrashRecoveryContext.cpp index 899c3890d..263114c06 100644 --- a/contrib/llvm/lib/Support/CrashRecoveryContext.cpp +++ b/contrib/llvm/lib/Support/CrashRecoveryContext.cpp @@ -12,6 +12,7 @@ #include "llvm/Config/config.h" #include "llvm/Support/Mutex.h" #include "llvm/Support/ThreadLocal.h" +#include "llvm/Support/ErrorHandling.h" #include #include using namespace llvm; @@ -123,7 +124,56 @@ CrashRecoveryContext::unregisterCleanup(CrashRecoveryContextCleanup *cleanup) { #ifdef LLVM_ON_WIN32 -// FIXME: No real Win32 implementation currently. +#include "Windows/Windows.h" + +// On Windows, we can make use of vectored exception handling to +// catch most crashing situations. Note that this does mean +// we will be alerted of exceptions *before* structured exception +// handling has the opportunity to catch it. But that isn't likely +// to cause problems because nowhere in the project is SEH being +// used. +// +// Vectored exception handling is built on top of SEH, and so it +// works on a per-thread basis. +// +// The vectored exception handler functionality was added in Windows +// XP, so if support for older versions of Windows is required, +// it will have to be added. +// +// If we want to support as far back as Win2k, we could use the +// SetUnhandledExceptionFilter API, but there's a risk of that +// being entirely overwritten (it's not a chain). + +static LONG CALLBACK ExceptionHandler(PEXCEPTION_POINTERS ExceptionInfo) +{ + // Lookup the current thread local recovery object. + const CrashRecoveryContextImpl *CRCI = CurrentContext.get(); + + if (!CRCI) { + // Something has gone horribly wrong, so let's just tell everyone + // to keep searching + CrashRecoveryContext::Disable(); + return EXCEPTION_CONTINUE_SEARCH; + } + + // TODO: We can capture the stack backtrace here and store it on the + // implementation if we so choose. + + // Handle the crash + const_cast(CRCI)->HandleCrash(); + + // Note that we don't actually get here because HandleCrash calls + // longjmp, which means the HandleCrash function never returns. + llvm_unreachable("Handled the crash, should have longjmp'ed out of here"); + return EXCEPTION_CONTINUE_SEARCH; +} + +// Because the Enable and Disable calls are static, it means that +// there may not actually be an Impl available, or even a current +// CrashRecoveryContext at all. So we make use of a thread-local +// exception table. The handles contained in here will either be +// non-NULL, valid VEH handles, or NULL. +static sys::ThreadLocal sCurrentExceptionHandle; void CrashRecoveryContext::Enable() { sys::ScopedLock L(gCrashRecoveryContexMutex); @@ -132,6 +182,13 @@ void CrashRecoveryContext::Enable() { return; gCrashRecoveryEnabled = true; + + // We can set up vectored exception handling now. We will install our + // handler as the front of the list, though there's no assurances that + // it will remain at the front (another call could install itself before + // our handler). This 1) isn't likely, and 2) shouldn't cause problems. + PVOID handle = ::AddVectoredExceptionHandler(1, ExceptionHandler); + sCurrentExceptionHandle.set(handle); } void CrashRecoveryContext::Disable() { @@ -141,6 +198,15 @@ void CrashRecoveryContext::Disable() { return; gCrashRecoveryEnabled = false; + + PVOID currentHandle = const_cast(sCurrentExceptionHandle.get()); + if (currentHandle) { + // Now we can remove the vectored exception handler from the chain + ::RemoveVectoredExceptionHandler(currentHandle); + + // Reset the handle in our thread-local set. + sCurrentExceptionHandle.set(NULL); + } } #else diff --git a/contrib/llvm/lib/Support/DataExtractor.cpp b/contrib/llvm/lib/Support/DataExtractor.cpp new file mode 100644 index 000000000..b946c1df8 --- /dev/null +++ b/contrib/llvm/lib/Support/DataExtractor.cpp @@ -0,0 +1,175 @@ +//===-- DataExtractor.cpp -------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/DataExtractor.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/Host.h" +#include "llvm/Support/SwapByteOrder.h" +using namespace llvm; + +template +static T getU(uint32_t *offset_ptr, const DataExtractor *de, + bool isLittleEndian, const char *Data) { + T val = 0; + uint32_t offset = *offset_ptr; + if (de->isValidOffsetForDataOfSize(offset, sizeof(val))) { + std::memcpy(&val, &Data[offset], sizeof(val)); + if (sys::isLittleEndianHost() != isLittleEndian) + val = sys::SwapByteOrder(val); + + // Advance the offset + *offset_ptr += sizeof(val); + } + return val; +} + +template +static T *getUs(uint32_t *offset_ptr, T *dst, uint32_t count, + const DataExtractor *de, bool isLittleEndian, const char *Data){ + uint32_t offset = *offset_ptr; + + if (count > 0 && de->isValidOffsetForDataOfSize(offset, sizeof(*dst)*count)) { + for (T *value_ptr = dst, *end = dst + count; value_ptr != end; + ++value_ptr, offset += sizeof(*dst)) + *value_ptr = getU(offset_ptr, de, isLittleEndian, Data); + // Advance the offset + *offset_ptr = offset; + // Return a non-NULL pointer to the converted data as an indicator of + // success + return dst; + } + return NULL; +} + +uint8_t DataExtractor::getU8(uint32_t *offset_ptr) const { + return getU(offset_ptr, this, IsLittleEndian, Data.data()); +} + +uint8_t * +DataExtractor::getU8(uint32_t *offset_ptr, uint8_t *dst, uint32_t count) const { + return getUs(offset_ptr, dst, count, this, IsLittleEndian, + Data.data()); +} + + +uint16_t DataExtractor::getU16(uint32_t *offset_ptr) const { + return getU(offset_ptr, this, IsLittleEndian, Data.data()); +} + +uint16_t *DataExtractor::getU16(uint32_t *offset_ptr, uint16_t *dst, + uint32_t count) const { + return getUs(offset_ptr, dst, count, this, IsLittleEndian, + Data.data()); +} + +uint32_t DataExtractor::getU32(uint32_t *offset_ptr) const { + return getU(offset_ptr, this, IsLittleEndian, Data.data()); +} + +uint32_t *DataExtractor::getU32(uint32_t *offset_ptr, uint32_t *dst, + uint32_t count) const { + return getUs(offset_ptr, dst, count, this, IsLittleEndian, + Data.data());; +} + +uint64_t DataExtractor::getU64(uint32_t *offset_ptr) const { + return getU(offset_ptr, this, IsLittleEndian, Data.data()); +} + +uint64_t *DataExtractor::getU64(uint32_t *offset_ptr, uint64_t *dst, + uint32_t count) const { + return getUs(offset_ptr, dst, count, this, IsLittleEndian, + Data.data()); +} + +uint64_t +DataExtractor::getUnsigned(uint32_t *offset_ptr, uint32_t byte_size) const { + switch (byte_size) { + case 1: + return getU8(offset_ptr); + case 2: + return getU16(offset_ptr); + case 4: + return getU32(offset_ptr); + case 8: + return getU64(offset_ptr); + } + llvm_unreachable("getUnsigned unhandled case!"); +} + +int64_t +DataExtractor::getSigned(uint32_t *offset_ptr, uint32_t byte_size) const { + switch (byte_size) { + case 1: + return (int8_t)getU8(offset_ptr); + case 2: + return (int16_t)getU16(offset_ptr); + case 4: + return (int32_t)getU32(offset_ptr); + case 8: + return (int64_t)getU64(offset_ptr); + } + llvm_unreachable("getSigned unhandled case!"); +} + +const char *DataExtractor::getCStr(uint32_t *offset_ptr) const { + uint32_t offset = *offset_ptr; + StringRef::size_type pos = Data.find('\0', offset); + if (pos != StringRef::npos) { + *offset_ptr = pos + 1; + return Data.data() + offset; + } + return NULL; +} + +uint64_t DataExtractor::getULEB128(uint32_t *offset_ptr) const { + uint64_t result = 0; + if (Data.empty()) + return 0; + + unsigned shift = 0; + uint32_t offset = *offset_ptr; + uint8_t byte = 0; + + while (isValidOffset(offset)) { + byte = Data[offset++]; + result |= (byte & 0x7f) << shift; + shift += 7; + if ((byte & 0x80) == 0) + break; + } + + *offset_ptr = offset; + return result; +} + +int64_t DataExtractor::getSLEB128(uint32_t *offset_ptr) const { + int64_t result = 0; + if (Data.empty()) + return 0; + + unsigned shift = 0; + uint32_t offset = *offset_ptr; + uint8_t byte = 0; + + while (isValidOffset(offset)) { + byte = Data[offset++]; + result |= (byte & 0x7f) << shift; + shift += 7; + if ((byte & 0x80) == 0) + break; + } + + // Sign bit of byte is 2nd high order bit (0x40) + if (shift < 64 && (byte & 0x40)) + result |= -(1 << shift); + + *offset_ptr = offset; + return result; +} diff --git a/contrib/llvm/lib/Support/Disassembler.cpp b/contrib/llvm/lib/Support/Disassembler.cpp index 6362aff43..c6d73bcad 100644 --- a/contrib/llvm/lib/Support/Disassembler.cpp +++ b/contrib/llvm/lib/Support/Disassembler.cpp @@ -1,4 +1,4 @@ -//===- lib/System/Disassembler.cpp ------------------------------*- C++ -*-===// +//===- lib/Support/Disassembler.cpp -----------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // diff --git a/contrib/llvm/lib/Support/Dwarf.cpp b/contrib/llvm/lib/Support/Dwarf.cpp index 0813321b6..95a9550f9 100644 --- a/contrib/llvm/lib/Support/Dwarf.cpp +++ b/contrib/llvm/lib/Support/Dwarf.cpp @@ -82,6 +82,19 @@ const char *llvm::dwarf::TagString(unsigned Tag) { case DW_TAG_arg_variable: return "DW_TAG_arg_variable"; case DW_TAG_return_variable: return "DW_TAG_return_variable"; case DW_TAG_vector_type: return "DW_TAG_vector_type"; + case DW_TAG_rvalue_reference_type: return "DW_TAG_rvalue_reference_type"; + case DW_TAG_template_alias: return "DW_TAG_template_alias"; + case DW_TAG_MIPS_loop: return "DW_TAG_MIPS_loop"; + case DW_TAG_type_unit: return "DW_TAG_type_unit"; + case DW_TAG_format_label: return "DW_TAG_format_label"; + case DW_TAG_function_template: return "DW_TAG_function_template"; + case DW_TAG_class_template: return "DW_TAG_class_template"; + case DW_TAG_GNU_template_template_param: + return "DW_TAG_GNU_template_template_param"; + case DW_TAG_GNU_template_parameter_pack: + return "DW_TAG_GNU_template_parameter_pack"; + case DW_TAG_GNU_formal_parameter_pack: + return "DW_TAG_GNU_formal_parameter_pack"; } return 0; } @@ -186,7 +199,30 @@ const char *llvm::dwarf::AttributeString(unsigned Attribute) { case DW_AT_elemental: return "DW_AT_elemental"; case DW_AT_pure: return "DW_AT_pure"; case DW_AT_recursive: return "DW_AT_recursive"; + case DW_AT_signature: return "DW_AT_signature"; + case DW_AT_main_subprogram: return "DW_AT_main_subprogram"; + case DW_AT_data_bit_offset: return "DW_AT_data_bit_offset"; + case DW_AT_const_expr: return "DW_AT_const_expr"; + case DW_AT_enum_class: return "DW_AT_enum_class"; + case DW_AT_linkage_name: return "DW_AT_linkage_name"; + case DW_AT_MIPS_loop_begin: return "DW_AT_MIPS_loop_begin"; + case DW_AT_MIPS_tail_loop_begin: return "DW_AT_MIPS_tail_loop_begin"; + case DW_AT_MIPS_epilog_begin: return "DW_AT_MIPS_epilog_begin"; + case DW_AT_MIPS_loop_unroll_factor: return "DW_AT_MIPS_loop_unroll_factor"; + case DW_AT_MIPS_software_pipeline_depth: + return "DW_AT_MIPS_software_pipeline_depth"; case DW_AT_MIPS_linkage_name: return "DW_AT_MIPS_linkage_name"; + case DW_AT_MIPS_stride: return "DW_AT_MIPS_stride"; + case DW_AT_MIPS_abstract_name: return "DW_AT_MIPS_abstract_name"; + case DW_AT_MIPS_clone_origin: return "DW_AT_MIPS_clone_origin"; + case DW_AT_MIPS_has_inlines: return "DW_AT_MIPS_has_inlines"; + case DW_AT_MIPS_stride_byte: return "DW_AT_MIPS_stride_byte"; + case DW_AT_MIPS_stride_elem: return "DW_AT_MIPS_stride_elem"; + case DW_AT_MIPS_ptr_dopetype: return "DW_AT_MIPS_ptr_dopetype"; + case DW_AT_MIPS_allocatable_dopetype: + return "DW_AT_MIPS_allocatable_dopetype"; + case DW_AT_MIPS_assumed_shape_dopetype: + return "DW_AT_MIPS_assumed_shape_dopetype"; case DW_AT_sf_names: return "DW_AT_sf_names"; case DW_AT_src_info: return "DW_AT_src_info"; case DW_AT_mac_info: return "DW_AT_mac_info"; @@ -194,6 +230,8 @@ const char *llvm::dwarf::AttributeString(unsigned Attribute) { case DW_AT_body_begin: return "DW_AT_body_begin"; case DW_AT_body_end: return "DW_AT_body_end"; case DW_AT_GNU_vector: return "DW_AT_GNU_vector"; + case DW_AT_GNU_template_name: return "DW_AT_GNU_template_name"; + case DW_AT_MIPS_assumed_size: return "DW_AT_MIPS_assumed_size"; case DW_AT_lo_user: return "DW_AT_lo_user"; case DW_AT_hi_user: return "DW_AT_hi_user"; case DW_AT_APPLE_optimized: return "DW_AT_APPLE_optimized"; @@ -237,6 +275,10 @@ const char *llvm::dwarf::FormEncodingString(unsigned Encoding) { case DW_FORM_ref8: return "DW_FORM_ref8"; case DW_FORM_ref_udata: return "DW_FORM_ref_udata"; case DW_FORM_indirect: return "DW_FORM_indirect"; + case DW_FORM_sec_offset: return "DW_FORM_sec_offset"; + case DW_FORM_exprloc: return "DW_FORM_exprloc"; + case DW_FORM_flag_present: return "DW_FORM_flag_present"; + case DW_FORM_ref_sig8: return "DW_FORM_ref_sig8"; } return 0; } @@ -397,6 +439,8 @@ const char *llvm::dwarf::OperationEncodingString(unsigned Encoding) { case DW_OP_form_tls_address: return "DW_OP_form_tls_address"; case DW_OP_call_frame_cfa: return "DW_OP_call_frame_cfa"; case DW_OP_bit_piece: return "DW_OP_bit_piece"; + case DW_OP_implicit_value: return "DW_OP_implicit_value"; + case DW_OP_stack_value: return "DW_OP_stack_value"; case DW_OP_lo_user: return "DW_OP_lo_user"; case DW_OP_hi_user: return "DW_OP_hi_user"; } @@ -416,6 +460,7 @@ const char *llvm::dwarf::AttributeEncodingString(unsigned Encoding) { case DW_ATE_unsigned: return "DW_ATE_unsigned"; case DW_ATE_unsigned_char: return "DW_ATE_unsigned_char"; case DW_ATE_imaginary_float: return "DW_ATE_imaginary_float"; + case DW_ATE_UTF: return "DW_ATE_UTF"; case DW_ATE_packed_decimal: return "DW_ATE_packed_decimal"; case DW_ATE_numeric_string: return "DW_ATE_numeric_string"; case DW_ATE_edited: return "DW_ATE_edited"; @@ -602,6 +647,7 @@ const char *llvm::dwarf::LNExtendedString(unsigned Encoding) { case DW_LNE_end_sequence: return "DW_LNE_end_sequence"; case DW_LNE_set_address: return "DW_LNE_set_address"; case DW_LNE_define_file: return "DW_LNE_define_file"; + case DW_LNE_set_discriminator: return "DW_LNE_set_discriminator"; case DW_LNE_lo_user: return "DW_LNE_lo_user"; case DW_LNE_hi_user: return "DW_LNE_hi_user"; } @@ -651,6 +697,9 @@ const char *llvm::dwarf::CallFrameString(unsigned Encoding) { case DW_CFA_val_offset: return "DW_CFA_val_offset"; case DW_CFA_val_offset_sf: return "DW_CFA_val_offset_sf"; case DW_CFA_val_expression: return "DW_CFA_val_expression"; + case DW_CFA_MIPS_advance_loc8: return "DW_CFA_MIPS_advance_loc8"; + case DW_CFA_GNU_window_save: return "DW_CFA_GNU_window_save"; + case DW_CFA_GNU_args_size: return "DW_CFA_GNU_args_size"; case DW_CFA_lo_user: return "DW_CFA_lo_user"; case DW_CFA_hi_user: return "DW_CFA_hi_user"; } diff --git a/contrib/llvm/lib/Support/DynamicLibrary.cpp b/contrib/llvm/lib/Support/DynamicLibrary.cpp index 455c3801c..fb02c07e4 100644 --- a/contrib/llvm/lib/Support/DynamicLibrary.cpp +++ b/contrib/llvm/lib/Support/DynamicLibrary.cpp @@ -9,28 +9,26 @@ // // This header file implements the operating system DynamicLibrary concept. // -// FIXME: This file leaks the ExplicitSymbols and OpenedHandles vector, and is -// not thread safe! +// FIXME: This file leaks ExplicitSymbols and OpenedHandles! // //===----------------------------------------------------------------------===// +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/DenseSet.h" #include "llvm/Support/DynamicLibrary.h" #include "llvm/Support/Mutex.h" #include "llvm/Config/config.h" #include #include -#include -#include // Collection of symbol name/value pairs to be searched prior to any libraries. -static std::map *ExplicitSymbols = 0; +static llvm::StringMap *ExplicitSymbols = 0; namespace { struct ExplicitSymbolsDeleter { ~ExplicitSymbolsDeleter() { - if (ExplicitSymbols) - delete ExplicitSymbols; + delete ExplicitSymbols; } }; @@ -38,13 +36,22 @@ struct ExplicitSymbolsDeleter { static ExplicitSymbolsDeleter Dummy; -void llvm::sys::DynamicLibrary::AddSymbol(const char* symbolName, + +static llvm::sys::SmartMutex& getMutex() { + static llvm::sys::SmartMutex HandlesMutex; + return HandlesMutex; +} + +void llvm::sys::DynamicLibrary::AddSymbol(StringRef symbolName, void *symbolValue) { + SmartScopedLock lock(getMutex()); if (ExplicitSymbols == 0) - ExplicitSymbols = new std::map(); + ExplicitSymbols = new llvm::StringMap(); (*ExplicitSymbols)[symbolName] = symbolValue; } +char llvm::sys::DynamicLibrary::Invalid = 0; + #ifdef LLVM_ON_WIN32 #include "Windows/DynamicLibrary.inc" @@ -61,66 +68,78 @@ using namespace llvm::sys; //=== independent code. //===----------------------------------------------------------------------===// -static std::vector *OpenedHandles = 0; - - -static SmartMutex& getMutex() { - static SmartMutex HandlesMutex; - return HandlesMutex; -} +static DenseSet *OpenedHandles = 0; +DynamicLibrary DynamicLibrary::getPermanentLibrary(const char *filename, + std::string *errMsg) { + SmartScopedLock lock(getMutex()); -bool DynamicLibrary::LoadLibraryPermanently(const char *Filename, - std::string *ErrMsg) { - void *H = dlopen(Filename, RTLD_LAZY|RTLD_GLOBAL); - if (H == 0) { - if (ErrMsg) *ErrMsg = dlerror(); - return true; + void *handle = dlopen(filename, RTLD_LAZY|RTLD_GLOBAL); + if (handle == 0) { + if (errMsg) *errMsg = dlerror(); + return DynamicLibrary(); } + #ifdef __CYGWIN__ // Cygwin searches symbols only in the main // with the handle of dlopen(NULL, RTLD_GLOBAL). - if (Filename == NULL) - H = RTLD_DEFAULT; + if (filename == NULL) + handle = RTLD_DEFAULT; #endif - SmartScopedLock Lock(getMutex()); + if (OpenedHandles == 0) - OpenedHandles = new std::vector(); - OpenedHandles->push_back(H); - return false; + OpenedHandles = new DenseSet(); + + // If we've already loaded this library, dlclose() the handle in order to + // keep the internal refcount at +1. + if (!OpenedHandles->insert(handle).second) + dlclose(handle); + + return DynamicLibrary(handle); +} + +void *DynamicLibrary::getAddressOfSymbol(const char *symbolName) { + if (!isValid()) + return NULL; + return dlsym(Data, symbolName); } + #else using namespace llvm; using namespace llvm::sys; -bool DynamicLibrary::LoadLibraryPermanently(const char *Filename, - std::string *ErrMsg) { - if (ErrMsg) *ErrMsg = "dlopen() not supported on this platform"; - return true; +DynamicLibrary DynamicLibrary::getPermanentLibrary(const char *filename, + std::string *errMsg) { + if (errMsg) *errMsg = "dlopen() not supported on this platform"; + return DynamicLibrary(); } + +void *DynamicLibrary::getAddressOfSymbol(const char *symbolName) { + return NULL; +} + #endif namespace llvm { void *SearchForAddressOfSpecialSymbol(const char* symbolName); } -void* DynamicLibrary::SearchForAddressOfSymbol(const char* symbolName) { +void* DynamicLibrary::SearchForAddressOfSymbol(const char *symbolName) { + SmartScopedLock Lock(getMutex()); + // First check symbols added via AddSymbol(). if (ExplicitSymbols) { - std::map::iterator I = - ExplicitSymbols->find(symbolName); - std::map::iterator E = ExplicitSymbols->end(); + StringMap::iterator i = ExplicitSymbols->find(symbolName); - if (I != E) - return I->second; + if (i != ExplicitSymbols->end()) + return i->second; } #if HAVE_DLFCN_H // Now search the libraries. - SmartScopedLock Lock(getMutex()); if (OpenedHandles) { - for (std::vector::iterator I = OpenedHandles->begin(), + for (DenseSet::iterator I = OpenedHandles->begin(), E = OpenedHandles->end(); I != E; ++I) { //lt_ptr ptr = lt_dlsym(*I, symbolName); void *ptr = dlsym(*I, symbolName); diff --git a/contrib/llvm/lib/Support/FoldingSet.cpp b/contrib/llvm/lib/Support/FoldingSet.cpp index 1568342e9..17b827132 100644 --- a/contrib/llvm/lib/Support/FoldingSet.cpp +++ b/contrib/llvm/lib/Support/FoldingSet.cpp @@ -64,10 +64,8 @@ void FoldingSetNodeID::AddPointer(const void *Ptr) { // depend on the host. It doesn't matter however, because hashing on // pointer values in inherently unstable. Nothing should depend on the // ordering of nodes in the folding set. - intptr_t PtrI = (intptr_t)Ptr; - Bits.push_back(unsigned(PtrI)); - if (sizeof(intptr_t) > sizeof(unsigned)) - Bits.push_back(unsigned(uint64_t(PtrI) >> 32)); + Bits.append(reinterpret_cast(&Ptr), + reinterpret_cast(&Ptr+1)); } void FoldingSetNodeID::AddInteger(signed I) { Bits.push_back(I); diff --git a/contrib/llvm/lib/Support/Host.cpp b/contrib/llvm/lib/Support/Host.cpp index c525a1228..a19e4b411 100644 --- a/contrib/llvm/lib/Support/Host.cpp +++ b/contrib/llvm/lib/Support/Host.cpp @@ -213,13 +213,13 @@ std::string sys::getHostCPUName() { case 30: // Intel(R) Core(TM) i7 CPU 870 @ 2.93GHz. // As found in a Summer 2010 model iMac. case 37: // Intel Core i7, laptop version. + case 44: // Intel Core i7 processor and Intel Xeon processor. All + // processors are manufactured using the 32 nm process. return "corei7"; // SandyBridge: case 42: // Intel Core i7 processor. All processors are manufactured // using the 32 nm process. - case 44: // Intel Core i7 processor and Intel Xeon processor. All - // processors are manufactured using the 32 nm process. case 45: return "corei7-avx"; diff --git a/contrib/llvm/lib/Support/IncludeFile.cpp b/contrib/llvm/lib/Support/IncludeFile.cpp index 5da88261c..e67acb3d1 100644 --- a/contrib/llvm/lib/Support/IncludeFile.cpp +++ b/contrib/llvm/lib/Support/IncludeFile.cpp @@ -1,4 +1,4 @@ -//===- lib/System/IncludeFile.cpp - Ensure Linking Of Implementation -----===// +//===- lib/Support/IncludeFile.cpp - Ensure Linking Of Implementation -----===// // // The LLVM Compiler Infrastructure // diff --git a/contrib/llvm/lib/Support/Memory.cpp b/contrib/llvm/lib/Support/Memory.cpp index ac7af0ae8..ceaaa99b3 100644 --- a/contrib/llvm/lib/Support/Memory.cpp +++ b/contrib/llvm/lib/Support/Memory.cpp @@ -16,6 +16,10 @@ #include "llvm/Support/Valgrind.h" #include "llvm/Config/config.h" +#if defined(__mips__) +#include +#endif + namespace llvm { using namespace sys; } @@ -66,6 +70,8 @@ void llvm::sys::Memory::InvalidateInstructionCache(const void *Addr, char *Start = (char*) Addr; char *End = Start + Len; __clear_cache(Start, End); +# elif defined(__mips__) + cacheflush((char*)Addr, Len, BCACHE); # endif #endif // end apple diff --git a/contrib/llvm/lib/Support/MemoryBuffer.cpp b/contrib/llvm/lib/Support/MemoryBuffer.cpp index d264be9ac..0771af5fe 100644 --- a/contrib/llvm/lib/Support/MemoryBuffer.cpp +++ b/contrib/llvm/lib/Support/MemoryBuffer.cpp @@ -275,16 +275,16 @@ static bool shouldUseMmap(int FD, error_code MemoryBuffer::getOpenFile(int FD, const char *Filename, OwningPtr &result, - size_t FileSize, size_t MapSize, - off_t Offset, + uint64_t FileSize, uint64_t MapSize, + int64_t Offset, bool RequiresNullTerminator) { static int PageSize = sys::Process::GetPageSize(); // Default is to map the full file. - if (MapSize == size_t(-1)) { + if (MapSize == uint64_t(-1)) { // If we don't know the file size, use fstat to find out. fstat on an open // file descriptor is cheaper than stat on a random path. - if (FileSize == size_t(-1)) { + if (FileSize == uint64_t(-1)) { struct stat FileInfo; // TODO: This should use fstat64 when available. if (fstat(FD, &FileInfo) == -1) { diff --git a/contrib/llvm/lib/Support/MemoryObject.cpp b/contrib/llvm/lib/Support/MemoryObject.cpp index 91e3ecd23..b20ab8923 100644 --- a/contrib/llvm/lib/Support/MemoryObject.cpp +++ b/contrib/llvm/lib/Support/MemoryObject.cpp @@ -19,8 +19,11 @@ int MemoryObject::readBytes(uint64_t address, uint64_t* copied) const { uint64_t current = address; uint64_t limit = getBase() + getExtent(); - - while (current - address < size && current < limit) { + + if (current + size > limit) + return -1; + + while (current - address < size) { if (readByte(current, &buf[(current - address)])) return -1; diff --git a/contrib/llvm/lib/Support/Mutex.cpp b/contrib/llvm/lib/Support/Mutex.cpp index b408973bb..8874e943f 100644 --- a/contrib/llvm/lib/Support/Mutex.cpp +++ b/contrib/llvm/lib/Support/Mutex.cpp @@ -152,6 +152,6 @@ MutexImpl::tryacquire() #elif defined( LLVM_ON_WIN32) #include "Windows/Mutex.inc" #else -#warning Neither LLVM_ON_UNIX nor LLVM_ON_WIN32 was set in System/Mutex.cpp +#warning Neither LLVM_ON_UNIX nor LLVM_ON_WIN32 was set in Support/Mutex.cpp #endif #endif diff --git a/contrib/llvm/lib/Support/Path.cpp b/contrib/llvm/lib/Support/Path.cpp index 8fbaf2d42..e5b7cd3bf 100644 --- a/contrib/llvm/lib/Support/Path.cpp +++ b/contrib/llvm/lib/Support/Path.cpp @@ -121,7 +121,7 @@ sys::IdentifyFileType(const char *magic, unsigned length) { case 7: return Mach_O_DynamicLinker_FileType; case 8: return Mach_O_Bundle_FileType; case 9: return Mach_O_DynamicallyLinkedSharedLibStub_FileType; - case 10: break; // FIXME: MH_DSYM companion file with only debug. + case 10: return Mach_O_DSYMCompanion_FileType; } break; } diff --git a/contrib/llvm/lib/Support/PathV2.cpp b/contrib/llvm/lib/Support/PathV2.cpp index 896c94c07..bebe442e2 100644 --- a/contrib/llvm/lib/Support/PathV2.cpp +++ b/contrib/llvm/lib/Support/PathV2.cpp @@ -490,6 +490,36 @@ bool is_separator(char value) { } } +void system_temp_directory(bool erasedOnReboot, SmallVectorImpl &result) { + result.clear(); + + // Check whether the temporary directory is specified by an environment + // variable. + const char *EnvironmentVariable; +#ifdef LLVM_ON_WIN32 + EnvironmentVariable = "TEMP"; +#else + EnvironmentVariable = "TMPDIR"; +#endif + if (char *RequestedDir = getenv(EnvironmentVariable)) { + result.append(RequestedDir, RequestedDir + strlen(RequestedDir)); + return; + } + + // Fall back to a system default. + const char *DefaultResult; +#ifdef LLVM_ON_WIN32 + (void)erasedOnReboot; + DefaultResult = "C:\\TEMP"; +#else + if (erasedOnReboot) + DefaultResult = "/tmp"; + else + DefaultResult = "/var/tmp"; +#endif + result.append(DefaultResult, DefaultResult + strlen(DefaultResult)); +} + bool has_root_name(const Twine &path) { SmallString<128> path_storage; StringRef p = path.toStringRef(path_storage); @@ -626,7 +656,7 @@ error_code create_directories(const Twine &path, bool &existed) { if (error_code ec = fs::exists(parent, parent_exists)) return ec; if (!parent_exists) - return create_directories(parent, existed); + if (error_code ec = create_directories(parent, existed)) return ec; return create_directory(p, existed); } @@ -682,14 +712,12 @@ bool is_other(file_status status) { !is_symlink(status); } -void directory_entry::replace_filename(const Twine &filename, file_status st, - file_status symlink_st) { +void directory_entry::replace_filename(const Twine &filename, file_status st) { SmallString<128> path(Path.begin(), Path.end()); path::remove_filename(path); path::append(path, filename); Path = path.str(); Status = st; - SymlinkStatus = symlink_st; } error_code has_magic(const Twine &path, const Twine &magic, bool &result) { diff --git a/contrib/llvm/lib/Support/PrettyStackTrace.cpp b/contrib/llvm/lib/Support/PrettyStackTrace.cpp index 082b7012e..ef3307317 100644 --- a/contrib/llvm/lib/Support/PrettyStackTrace.cpp +++ b/contrib/llvm/lib/Support/PrettyStackTrace.cpp @@ -62,7 +62,7 @@ extern "C" { CRASH_REPORTER_CLIENT_HIDDEN struct crashreporter_annotations_t gCRAnnotations __attribute__((section("__DATA," CRASHREPORTER_ANNOTATIONS_SECTION))) - = { CRASHREPORTER_ANNOTATIONS_VERSION, 0, 0, 0, 0 }; + = { CRASHREPORTER_ANNOTATIONS_VERSION, 0, 0, 0, 0, 0, 0 }; } #elif defined (__APPLE__) && HAVE_CRASHREPORTER_INFO static const char *__crashreporter_info__ = 0; diff --git a/contrib/llvm/lib/Support/RWMutex.cpp b/contrib/llvm/lib/Support/RWMutex.cpp index fc02f9cf7..d0b1e10b5 100644 --- a/contrib/llvm/lib/Support/RWMutex.cpp +++ b/contrib/llvm/lib/Support/RWMutex.cpp @@ -152,6 +152,6 @@ RWMutexImpl::writer_release() #elif defined( LLVM_ON_WIN32) #include "Windows/RWMutex.inc" #else -#warning Neither LLVM_ON_UNIX nor LLVM_ON_WIN32 was set in System/Mutex.cpp +#warning Neither LLVM_ON_UNIX nor LLVM_ON_WIN32 was set in Support/Mutex.cpp #endif #endif diff --git a/contrib/llvm/lib/Support/SearchForAddressOfSpecialSymbol.cpp b/contrib/llvm/lib/Support/SearchForAddressOfSpecialSymbol.cpp index d63830185..2d23902bb 100644 --- a/contrib/llvm/lib/Support/SearchForAddressOfSpecialSymbol.cpp +++ b/contrib/llvm/lib/Support/SearchForAddressOfSpecialSymbol.cpp @@ -28,21 +28,6 @@ static void *DoSearch(const char* symbolName) { #ifdef __APPLE__ { - EXPLICIT_SYMBOL(__ashldi3); - EXPLICIT_SYMBOL(__ashrdi3); - EXPLICIT_SYMBOL(__cmpdi2); - EXPLICIT_SYMBOL(__divdi3); - EXPLICIT_SYMBOL(__fixdfdi); - EXPLICIT_SYMBOL(__fixsfdi); - EXPLICIT_SYMBOL(__fixunsdfdi); - EXPLICIT_SYMBOL(__fixunssfdi); - EXPLICIT_SYMBOL(__floatdidf); - EXPLICIT_SYMBOL(__floatdisf); - EXPLICIT_SYMBOL(__lshrdi3); - EXPLICIT_SYMBOL(__moddi3); - EXPLICIT_SYMBOL(__udivdi3); - EXPLICIT_SYMBOL(__umoddi3); - // __eprintf is sometimes used for assert() handling on x86. // // FIXME: Currently disabled when using Clang, as we don't always have our diff --git a/contrib/llvm/lib/Support/StringExtras.cpp b/contrib/llvm/lib/Support/StringExtras.cpp index eb2fa0842..49c5ac425 100644 --- a/contrib/llvm/lib/Support/StringExtras.cpp +++ b/contrib/llvm/lib/Support/StringExtras.cpp @@ -51,11 +51,10 @@ std::pair llvm::getToken(StringRef Source, void llvm::SplitString(StringRef Source, SmallVectorImpl &OutFragments, StringRef Delimiters) { - StringRef S2, S; - tie(S2, S) = getToken(Source, Delimiters); - while (!S2.empty()) { - OutFragments.push_back(S2); - tie(S2, S) = getToken(S, Delimiters); + std::pair S = getToken(Source, Delimiters); + while (!S.first.empty()) { + OutFragments.push_back(S.first); + S = getToken(S.second, Delimiters); } } diff --git a/contrib/llvm/lib/Support/StringRef.cpp b/contrib/llvm/lib/Support/StringRef.cpp index 8c3fc094c..b5b4f9476 100644 --- a/contrib/llvm/lib/Support/StringRef.cpp +++ b/contrib/llvm/lib/Support/StringRef.cpp @@ -46,12 +46,12 @@ int StringRef::compare_lower(StringRef RHS) const { /// compare_numeric - Compare strings, handle embedded numbers. int StringRef::compare_numeric(StringRef RHS) const { for (size_t I = 0, E = min(Length, RHS.Length); I != E; ++I) { - if (Data[I] == RHS.Data[I]) - continue; + // Check for sequences of digits. if (ascii_isdigit(Data[I]) && ascii_isdigit(RHS.Data[I])) { - // The longer sequence of numbers is larger. This doesn't really handle - // prefixed zeros well. - for (size_t J = I+1; J != E+1; ++J) { + // The longer sequence of numbers is considered larger. + // This doesn't really handle prefixed zeros well. + size_t J; + for (J = I + 1; J != E + 1; ++J) { bool ld = J < Length && ascii_isdigit(Data[J]); bool rd = J < RHS.Length && ascii_isdigit(RHS.Data[J]); if (ld != rd) @@ -59,8 +59,15 @@ int StringRef::compare_numeric(StringRef RHS) const { if (!rd) break; } + // The two number sequences have the same length (J-I), just memcmp them. + if (int Res = compareMemory(Data + I, RHS.Data + I, J - I)) + return Res < 0 ? -1 : 1; + // Identical number sequences, continue search after the numbers. + I = J - 1; + continue; } - return (unsigned char)Data[I] < (unsigned char)RHS.Data[I] ? -1 : 1; + if (Data[I] != RHS.Data[I]) + return (unsigned char)Data[I] < (unsigned char)RHS.Data[I] ? -1 : 1; } if (Length == RHS.Length) return 0; diff --git a/contrib/llvm/lib/Support/TargetRegistry.cpp b/contrib/llvm/lib/Support/TargetRegistry.cpp index 293a5d7a0..7497bfe03 100644 --- a/contrib/llvm/lib/Support/TargetRegistry.cpp +++ b/contrib/llvm/lib/Support/TargetRegistry.cpp @@ -7,9 +7,13 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Target/TargetRegistry.h" +#include "llvm/Support/TargetRegistry.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringRef.h" #include "llvm/Support/Host.h" +#include "llvm/Support/raw_ostream.h" #include +#include using namespace llvm; // Clients are responsible for avoid race conditions in registration. @@ -90,3 +94,29 @@ const Target *TargetRegistry::getClosestTargetForJIT(std::string &Error) { return TheTarget; } +static int TargetArraySortFn(const void *LHS, const void *RHS) { + typedef std::pair pair_ty; + return ((const pair_ty*)LHS)->first.compare(((const pair_ty*)RHS)->first); +} + +void TargetRegistry::printRegisteredTargetsForVersion() { + std::vector > Targets; + size_t Width = 0; + for (TargetRegistry::iterator I = TargetRegistry::begin(), + E = TargetRegistry::end(); + I != E; ++I) { + Targets.push_back(std::make_pair(I->getName(), &*I)); + Width = std::max(Width, Targets.back().first.size()); + } + array_pod_sort(Targets.begin(), Targets.end(), TargetArraySortFn); + + raw_ostream &OS = outs(); + OS << " Registered Targets:\n"; + for (unsigned i = 0, e = Targets.size(); i != e; ++i) { + OS << " " << Targets[i].first; + OS.indent(Width - Targets[i].first.size()) << " - " + << Targets[i].second->getShortDescription() << '\n'; + } + if (Targets.empty()) + OS << " (none)\n"; +} diff --git a/contrib/llvm/lib/Support/ThreadLocal.cpp b/contrib/llvm/lib/Support/ThreadLocal.cpp index 6b43048da..fdb251c0a 100644 --- a/contrib/llvm/lib/Support/ThreadLocal.cpp +++ b/contrib/llvm/lib/Support/ThreadLocal.cpp @@ -79,6 +79,6 @@ void ThreadLocalImpl::removeInstance() { #elif defined( LLVM_ON_WIN32) #include "Windows/ThreadLocal.inc" #else -#warning Neither LLVM_ON_UNIX nor LLVM_ON_WIN32 was set in System/ThreadLocal.cpp +#warning Neither LLVM_ON_UNIX nor LLVM_ON_WIN32 set in Support/ThreadLocal.cpp #endif #endif diff --git a/contrib/llvm/lib/Support/Threading.cpp b/contrib/llvm/lib/Support/Threading.cpp index b62b1a94b..8f0bb93eb 100644 --- a/contrib/llvm/lib/Support/Threading.cpp +++ b/contrib/llvm/lib/Support/Threading.cpp @@ -24,7 +24,7 @@ static bool multithreaded_mode = false; static sys::Mutex* global_lock = 0; bool llvm::llvm_start_multithreaded() { -#if defined(LLVM_MULTITHREADED) && LLVM_MULTITHREADED == 1 +#if ENABLE_THREADS != 0 assert(!multithreaded_mode && "Already multithreaded!"); multithreaded_mode = true; global_lock = new sys::Mutex(true); @@ -39,7 +39,7 @@ bool llvm::llvm_start_multithreaded() { } void llvm::llvm_stop_multithreaded() { -#if defined(LLVM_MULTITHREADED) && LLVM_MULTITHREADED == 1 +#if ENABLE_THREADS != 0 assert(multithreaded_mode && "Not currently multithreaded!"); // We fence here to insure that all threaded operations are complete BEFORE we @@ -63,7 +63,7 @@ void llvm::llvm_release_global_lock() { if (multithreaded_mode) global_lock->release(); } -#if defined(LLVM_MULTITHREADED) && LLVM_MULTITHREADED == 1 && defined(HAVE_PTHREAD_H) +#if ENABLE_THREADS != 0 && defined(HAVE_PTHREAD_H) #include struct ThreadInfo { @@ -102,11 +102,42 @@ void llvm::llvm_execute_on_thread(void (*Fn)(void*), void *UserData, error: ::pthread_attr_destroy(&Attr); } +#elif ENABLE_THREADS!=0 && defined(LLVM_ON_WIN32) +#include "Windows/Windows.h" +#include -#else +struct ThreadInfo { + void (*func)(void*); + void *param; +}; -// No non-pthread implementation, currently. +static unsigned __stdcall ThreadCallback(void *param) { + struct ThreadInfo *info = reinterpret_cast(param); + info->func(info->param); + + return 0; +} +void llvm::llvm_execute_on_thread(void (*Fn)(void*), void *UserData, + unsigned RequestedStackSize) { + struct ThreadInfo param = { Fn, UserData }; + + HANDLE hThread = (HANDLE)::_beginthreadex(NULL, + RequestedStackSize, ThreadCallback, + ¶m, 0, NULL); + + if (hThread) { + // We actually don't care whether the wait succeeds or fails, in + // the same way we don't care whether the pthread_join call succeeds + // or fails. There's not much we could do if this were to fail. But + // on success, this call will wait until the thread finishes executing + // before returning. + (void)::WaitForSingleObject(hThread, INFINITE); + ::CloseHandle(hThread); + } +} +#else +// Support for non-Win32, non-pthread implementation. void llvm::llvm_execute_on_thread(void (*Fn)(void*), void *UserData, unsigned RequestedStackSize) { (void) RequestedStackSize; diff --git a/contrib/llvm/lib/Support/Triple.cpp b/contrib/llvm/lib/Support/Triple.cpp index 7e094ee78..c61af372d 100644 --- a/contrib/llvm/lib/Support/Triple.cpp +++ b/contrib/llvm/lib/Support/Triple.cpp @@ -8,16 +8,11 @@ //===----------------------------------------------------------------------===// #include "llvm/ADT/Triple.h" - #include "llvm/ADT/SmallString.h" #include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/Twine.h" -#include #include using namespace llvm; -// - const char *Triple::getArchTypeName(ArchType Kind) { switch (Kind) { case InvalidArch: return ""; @@ -29,6 +24,8 @@ const char *Triple::getArchTypeName(ArchType Kind) { case cellspu: return "cellspu"; case mips: return "mips"; case mipsel: return "mipsel"; + case mips64: return "mips64"; + case mips64el:return "mips64el"; case msp430: return "msp430"; case ppc64: return "powerpc64"; case ppc: return "powerpc"; @@ -43,6 +40,8 @@ const char *Triple::getArchTypeName(ArchType Kind) { case mblaze: return "mblaze"; case ptx32: return "ptx32"; case ptx64: return "ptx64"; + case le32: return "le32"; + case amdil: return "amdil"; } return ""; @@ -77,6 +76,8 @@ const char *Triple::getArchTypePrefix(ArchType Kind) { case ptx32: return "ptx"; case ptx64: return "ptx"; + case le32: return "le32"; + case amdil: return "amdil"; } } @@ -102,6 +103,7 @@ const char *Triple::getOSTypeName(OSType Kind) { case DragonFly: return "dragonfly"; case FreeBSD: return "freebsd"; case IOS: return "ios"; + case KFreeBSD: return "kfreebsd"; case Linux: return "linux"; case Lv2: return "lv2"; case MacOSX: return "macosx"; @@ -114,6 +116,7 @@ const char *Triple::getOSTypeName(OSType Kind) { case Haiku: return "haiku"; case Minix: return "minix"; case RTEMS: return "rtems"; + case NativeClient: return "nacl"; } return ""; @@ -144,10 +147,16 @@ Triple::ArchType Triple::getArchTypeForLLVMName(StringRef Name) { return mips; if (Name == "mipsel") return mipsel; + if (Name == "mips64") + return mips64; + if (Name == "mips64el") + return mips64el; if (Name == "msp430") return msp430; if (Name == "ppc64") return ppc64; + if (Name == "ppc32") + return ppc; if (Name == "ppc") return ppc; if (Name == "mblaze") @@ -172,6 +181,10 @@ Triple::ArchType Triple::getArchTypeForLLVMName(StringRef Name) { return ptx32; if (Name == "ptx64") return ptx64; + if (Name == "le32") + return le32; + if (Name == "amdil") + return amdil; return UnknownArch; } @@ -207,13 +220,16 @@ Triple::ArchType Triple::getArchTypeForDarwinArchName(StringRef Str) { // This is derived from the driver driver. if (Str == "arm" || Str == "armv4t" || Str == "armv5" || Str == "xscale" || - Str == "armv6" || Str == "armv7") + Str == "armv6" || Str == "armv7" || Str == "armv7f" || Str == "armv7k" || + Str == "armv7s") return Triple::arm; if (Str == "ptx32") return Triple::ptx32; if (Str == "ptx64") return Triple::ptx64; + if (Str == "amdil") + return Triple::amdil; return Triple::UnknownArch; } @@ -249,6 +265,10 @@ const char *Triple::getArchNameForAssembler() { return "ptx32"; if (Str == "ptx64") return "ptx64"; + if (Str == "le32") + return "le32"; + if (Str == "amdil") + return "amdil"; return NULL; } @@ -288,6 +308,10 @@ Triple::ArchType Triple::ParseArch(StringRef ArchName) { else if (ArchName == "mipsel" || ArchName == "mipsallegrexel" || ArchName == "psp") return mipsel; + else if (ArchName == "mips64" || ArchName == "mips64eb") + return mips64; + else if (ArchName == "mips64el") + return mips64el; else if (ArchName == "sparc") return sparc; else if (ArchName == "sparcv9") @@ -302,6 +326,10 @@ Triple::ArchType Triple::ParseArch(StringRef ArchName) { return ptx32; else if (ArchName == "ptx64") return ptx64; + else if (ArchName == "le32") + return le32; + else if (ArchName == "amdil") + return amdil; else return UnknownArch; } @@ -330,6 +358,8 @@ Triple::OSType Triple::ParseOS(StringRef OSName) { return FreeBSD; else if (OSName.startswith("ios")) return IOS; + else if (OSName.startswith("kfreebsd")) + return KFreeBSD; else if (OSName.startswith("linux")) return Linux; else if (OSName.startswith("lv2")) @@ -354,6 +384,8 @@ Triple::OSType Triple::ParseOS(StringRef OSName) { return Minix; else if (OSName.startswith("rtems")) return RTEMS; + else if (OSName.startswith("nacl")) + return NativeClient; else return UnknownOS; } diff --git a/contrib/llvm/lib/Support/Twine.cpp b/contrib/llvm/lib/Support/Twine.cpp index d62123cc9..3d04bc34f 100644 --- a/contrib/llvm/lib/Support/Twine.cpp +++ b/contrib/llvm/lib/Support/Twine.cpp @@ -16,7 +16,7 @@ using namespace llvm; std::string Twine::str() const { // If we're storing only a std::string, just return it. if (LHSKind == StdStringKind && RHSKind == EmptyKind) - return *static_cast(LHS); + return *LHS.stdString; // Otherwise, flatten and copy the contents first. SmallString<256> Vec; @@ -40,9 +40,9 @@ StringRef Twine::toNullTerminatedStringRef(SmallVectorImpl &Out) const { switch (getLHSKind()) { case CStringKind: // Already null terminated, yay! - return StringRef(static_cast(LHS)); + return StringRef(LHS.cString); case StdStringKind: { - const std::string *str = static_cast(LHS); + const std::string *str = LHS.stdString; return StringRef(str->c_str(), str->size()); } default: @@ -55,48 +55,51 @@ StringRef Twine::toNullTerminatedStringRef(SmallVectorImpl &Out) const { return StringRef(Out.data(), Out.size()); } -void Twine::printOneChild(raw_ostream &OS, const void *Ptr, +void Twine::printOneChild(raw_ostream &OS, Child Ptr, NodeKind Kind) const { switch (Kind) { case Twine::NullKind: break; case Twine::EmptyKind: break; case Twine::TwineKind: - static_cast(Ptr)->print(OS); + Ptr.twine->print(OS); break; case Twine::CStringKind: - OS << static_cast(Ptr); + OS << Ptr.cString; break; case Twine::StdStringKind: - OS << *static_cast(Ptr); + OS << *Ptr.stdString; break; case Twine::StringRefKind: - OS << *static_cast(Ptr); + OS << *Ptr.stringRef; + break; + case Twine::CharKind: + OS << Ptr.character; break; case Twine::DecUIKind: - OS << (unsigned)(uintptr_t)Ptr; + OS << Ptr.decUI; break; case Twine::DecIKind: - OS << (int)(intptr_t)Ptr; + OS << Ptr.decI; break; case Twine::DecULKind: - OS << *static_cast(Ptr); + OS << *Ptr.decUL; break; case Twine::DecLKind: - OS << *static_cast(Ptr); + OS << *Ptr.decL; break; case Twine::DecULLKind: - OS << *static_cast(Ptr); + OS << *Ptr.decULL; break; case Twine::DecLLKind: - OS << *static_cast(Ptr); + OS << *Ptr.decLL; break; case Twine::UHexKind: - OS.write_hex(*static_cast(Ptr)); + OS.write_hex(*Ptr.uHex); break; } } -void Twine::printOneChildRepr(raw_ostream &OS, const void *Ptr, +void Twine::printOneChildRepr(raw_ostream &OS, Child Ptr, NodeKind Kind) const { switch (Kind) { case Twine::NullKind: @@ -105,40 +108,43 @@ void Twine::printOneChildRepr(raw_ostream &OS, const void *Ptr, OS << "empty"; break; case Twine::TwineKind: OS << "rope:"; - static_cast(Ptr)->printRepr(OS); + Ptr.twine->printRepr(OS); break; case Twine::CStringKind: OS << "cstring:\"" - << static_cast(Ptr) << "\""; + << Ptr.cString << "\""; break; case Twine::StdStringKind: OS << "std::string:\"" - << static_cast(Ptr) << "\""; + << Ptr.stdString << "\""; break; case Twine::StringRefKind: OS << "stringref:\"" - << static_cast(Ptr) << "\""; + << Ptr.stringRef << "\""; + break; + case Twine::CharKind: + OS << "char:\"" << Ptr.character << "\""; break; case Twine::DecUIKind: - OS << "decUI:\"" << (unsigned)(uintptr_t)Ptr << "\""; + OS << "decUI:\"" << Ptr.decUI << "\""; break; case Twine::DecIKind: - OS << "decI:\"" << (int)(intptr_t)Ptr << "\""; + OS << "decI:\"" << Ptr.decI << "\""; break; case Twine::DecULKind: - OS << "decUL:\"" << *static_cast(Ptr) << "\""; + OS << "decUL:\"" << *Ptr.decUL << "\""; break; case Twine::DecLKind: - OS << "decL:\"" << *static_cast(Ptr) << "\""; + OS << "decL:\"" << *Ptr.decL << "\""; break; case Twine::DecULLKind: - OS << "decULL:\"" << *static_cast(Ptr) << "\""; + OS << "decULL:\"" << *Ptr.decULL << "\""; break; case Twine::DecLLKind: - OS << "decLL:\"" << *static_cast(Ptr) << "\""; + OS << "decLL:\"" << *Ptr.decLL << "\""; break; case Twine::UHexKind: - OS << "uhex:\"" << static_cast(Ptr) << "\""; + OS << "uhex:\"" << Ptr.uHex << "\""; break; } } diff --git a/contrib/llvm/lib/Support/Unix/Host.inc b/contrib/llvm/lib/Support/Unix/Host.inc index eacb08b3f..1e438e75f 100644 --- a/contrib/llvm/lib/Support/Unix/Host.inc +++ b/contrib/llvm/lib/Support/Unix/Host.inc @@ -22,6 +22,7 @@ #include #include #include +#include // ::getenv using namespace llvm; diff --git a/contrib/llvm/lib/Support/Unix/Path.inc b/contrib/llvm/lib/Support/Unix/Path.inc index f295b92e4..85c7c4022 100644 --- a/contrib/llvm/lib/Support/Unix/Path.inc +++ b/contrib/llvm/lib/Support/Unix/Path.inc @@ -252,8 +252,8 @@ Path::GetUserHomeDirectory() { Path Path::GetCurrentDirectory() { char pathname[MAXPATHLEN]; - if (!getcwd(pathname,MAXPATHLEN)) { - assert (false && "Could not query current working directory."); + if (!getcwd(pathname, MAXPATHLEN)) { + assert(false && "Could not query current working directory."); return Path(); } diff --git a/contrib/llvm/lib/Support/Unix/PathV2.inc b/contrib/llvm/lib/Support/Unix/PathV2.inc index 03ff28367..bbbc34466 100644 --- a/contrib/llvm/lib/Support/Unix/PathV2.inc +++ b/contrib/llvm/lib/Support/Unix/PathV2.inc @@ -42,6 +42,9 @@ #if HAVE_STDIO_H #include #endif +#if HAVE_LIMITS_H +#include +#endif using namespace llvm; @@ -342,19 +345,22 @@ error_code status(const Twine &path, file_status &result) { } error_code unique_file(const Twine &model, int &result_fd, - SmallVectorImpl &result_path) { + SmallVectorImpl &result_path, + bool makeAbsolute) { SmallString<128> Model; model.toVector(Model); // Null terminate. Model.c_str(); - // Make model absolute by prepending a temp directory if it's not already. - bool absolute = path::is_absolute(Twine(Model)); - if (!absolute) { - SmallString<128> TDir; - if (error_code ec = TempDir(TDir)) return ec; - path::append(TDir, Twine(Model)); - Model.swap(TDir); + if (makeAbsolute) { + // Make model absolute by prepending a temp directory if it's not already. + bool absolute = path::is_absolute(Twine(Model)); + if (!absolute) { + SmallString<128> TDir; + if (error_code ec = TempDir(TDir)) return ec; + path::append(TDir, Twine(Model)); + Model.swap(TDir); + } } // Replace '%' with random chars. From here on, DO NOT modify model. It may be diff --git a/contrib/llvm/lib/Support/Unix/Process.inc b/contrib/llvm/lib/Support/Unix/Process.inc index 5cdb11cce..da440fd48 100644 --- a/contrib/llvm/lib/Support/Unix/Process.inc +++ b/contrib/llvm/lib/Support/Unix/Process.inc @@ -293,3 +293,7 @@ const char *Process::OutputBold(bool bg) { const char *Process::ResetColor() { return "\033[0m"; } + +void Process::SetWorkingDirectory(std::string Path) { + ::chdir(Path.c_str()); +} diff --git a/contrib/llvm/lib/Support/Windows/DynamicLibrary.inc b/contrib/llvm/lib/Support/Windows/DynamicLibrary.inc index fc5f5809c..83da82a94 100644 --- a/contrib/llvm/lib/Support/Windows/DynamicLibrary.inc +++ b/contrib/llvm/lib/Support/Windows/DynamicLibrary.inc @@ -39,7 +39,7 @@ using namespace sys; //=== and must not be UNIX code. //===----------------------------------------------------------------------===// -static std::vector OpenedHandles; +static DenseSet *OpenedHandles; extern "C" { @@ -63,30 +63,43 @@ extern "C" { #endif stricmp(ModuleName, "msvcrt20") != 0 && stricmp(ModuleName, "msvcrt40") != 0) { - OpenedHandles.push_back((HMODULE)ModuleBase); + OpenedHandles->insert((HMODULE)ModuleBase); } return TRUE; } } -bool DynamicLibrary::LoadLibraryPermanently(const char *filename, - std::string *ErrMsg) { - if (filename) { - HMODULE a_handle = LoadLibrary(filename); +DynamicLibrary DynamicLibrary::getPermanentLibrary(const char *filename, + std::string *errMsg) { + SmartScopedLock lock(getMutex()); - if (a_handle == 0) - return MakeErrMsg(ErrMsg, std::string(filename) + ": Can't open : "); + if (!filename) { + // When no file is specified, enumerate all DLLs and EXEs in the process. + if (OpenedHandles == 0) + OpenedHandles = new DenseSet(); - OpenedHandles.push_back(a_handle); - } else { - // When no file is specified, enumerate all DLLs and EXEs in the - // process. EnumerateLoadedModules(GetCurrentProcess(), ELM_Callback, 0); + // Dummy library that represents "search all handles". + // This is mostly to ensure that the return value still shows up as "valid". + return DynamicLibrary(&OpenedHandles); } + + HMODULE a_handle = LoadLibrary(filename); - // Because we don't remember the handle, we will never free it; hence, - // it is loaded permanently. - return false; + if (a_handle == 0) { + MakeErrMsg(errMsg, std::string(filename) + ": Can't open : "); + return DynamicLibrary(); + } + + if (OpenedHandles == 0) + OpenedHandles = new DenseSet(); + + // If we've already loaded this library, FreeLibrary() the handle in order to + // keep the internal refcount at +1. + if (!OpenedHandles->insert(a_handle).second) + FreeLibrary(a_handle); + + return DynamicLibrary(a_handle); } // Stack probing routines are in the support library (e.g. libgcc), but we don't @@ -101,21 +114,24 @@ bool DynamicLibrary::LoadLibraryPermanently(const char *filename, #undef EXPLICIT_SYMBOL2 void* DynamicLibrary::SearchForAddressOfSymbol(const char* symbolName) { + SmartScopedLock Lock(getMutex()); + // First check symbols added via AddSymbol(). if (ExplicitSymbols) { - std::map::iterator I = - ExplicitSymbols->find(symbolName); - std::map::iterator E = ExplicitSymbols->end(); - if (I != E) - return I->second; + StringMap::iterator i = ExplicitSymbols->find(symbolName); + + if (i != ExplicitSymbols->end()) + return i->second; } // Now search the libraries. - for (std::vector::iterator I = OpenedHandles.begin(), - E = OpenedHandles.end(); I != E; ++I) { - FARPROC ptr = GetProcAddress((HMODULE)*I, symbolName); - if (ptr) { - return (void *)(intptr_t)ptr; + if (OpenedHandles) { + for (DenseSet::iterator I = OpenedHandles->begin(), + E = OpenedHandles->end(); I != E; ++I) { + FARPROC ptr = GetProcAddress((HMODULE)*I, symbolName); + if (ptr) { + return (void *)(intptr_t)ptr; + } } } @@ -134,4 +150,14 @@ void* DynamicLibrary::SearchForAddressOfSymbol(const char* symbolName) { return 0; } + +void *DynamicLibrary::getAddressOfSymbol(const char *symbolName) { + if (!isValid()) + return NULL; + if (Data == &OpenedHandles) + return SearchForAddressOfSymbol(symbolName); + return (void *)(intptr_t)GetProcAddress((HMODULE)Data, symbolName); +} + + } diff --git a/contrib/llvm/lib/Support/Windows/Memory.inc b/contrib/llvm/lib/Support/Windows/Memory.inc index 9f69e7367..fcc72837c 100644 --- a/contrib/llvm/lib/Support/Windows/Memory.inc +++ b/contrib/llvm/lib/Support/Windows/Memory.inc @@ -32,11 +32,16 @@ MemoryBlock Memory::AllocateRWX(size_t NumBytes, static const size_t pageSize = Process::GetPageSize(); size_t NumPages = (NumBytes+pageSize-1)/pageSize; - //FIXME: support NearBlock if ever needed on Win64. + PVOID start = NearBlock ? static_cast(NearBlock->base()) + + NearBlock->size() : NULL; - void *pa = VirtualAlloc(NULL, NumPages*pageSize, MEM_COMMIT, + void *pa = VirtualAlloc(start, NumPages*pageSize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE); if (pa == NULL) { + if (NearBlock) { + // Try again without the NearBlock hint + return AllocateRWX(NumBytes, NULL, ErrMsg); + } MakeErrMsg(ErrMsg, "Can't allocate RWX Memory: "); return MemoryBlock(); } @@ -54,20 +59,62 @@ bool Memory::ReleaseRWX(MemoryBlock &M, std::string *ErrMsg) { return false; } +static DWORD getProtection(const void *addr) { + MEMORY_BASIC_INFORMATION info; + if (sizeof(info) == ::VirtualQuery(addr, &info, sizeof(info))) { + return info.Protect; + } + return 0; +} + bool Memory::setWritable(MemoryBlock &M, std::string *ErrMsg) { + if (!setRangeWritable(M.Address, M.Size)) { + return MakeErrMsg(ErrMsg, "Cannot set memory to writeable: "); + } return true; } bool Memory::setExecutable(MemoryBlock &M, std::string *ErrMsg) { - return false; + if (!setRangeExecutable(M.Address, M.Size)) { + return MakeErrMsg(ErrMsg, "Cannot set memory to executable: "); + } + return true; } bool Memory::setRangeWritable(const void *Addr, size_t Size) { - return true; + DWORD prot = getProtection(Addr); + if (!prot) + return false; + + if (prot == PAGE_EXECUTE || prot == PAGE_EXECUTE_READ) { + prot = PAGE_EXECUTE_READWRITE; + } else if (prot == PAGE_NOACCESS || prot == PAGE_READONLY) { + prot = PAGE_READWRITE; + } + + DWORD oldProt; + sys::Memory::InvalidateInstructionCache(Addr, Size); + return ::VirtualProtect(const_cast(Addr), Size, prot, &oldProt) + == TRUE; } bool Memory::setRangeExecutable(const void *Addr, size_t Size) { - return false; + DWORD prot = getProtection(Addr); + if (!prot) + return false; + + if (prot == PAGE_NOACCESS) { + prot = PAGE_EXECUTE; + } else if (prot == PAGE_READONLY) { + prot = PAGE_EXECUTE_READ; + } else if (prot == PAGE_READWRITE) { + prot = PAGE_EXECUTE_READWRITE; + } + + DWORD oldProt; + sys::Memory::InvalidateInstructionCache(Addr, Size); + return ::VirtualProtect(const_cast(Addr), Size, prot, &oldProt) + == TRUE; } } diff --git a/contrib/llvm/lib/Support/Windows/PathV2.inc b/contrib/llvm/lib/Support/Windows/PathV2.inc index af71b73cd..bc597b2dc 100644 --- a/contrib/llvm/lib/Support/Windows/PathV2.inc +++ b/contrib/llvm/lib/Support/Windows/PathV2.inc @@ -445,13 +445,35 @@ error_code file_size(const Twine &path, uint64_t &result) { return success; } +static bool isReservedName(StringRef path) { + // This list of reserved names comes from MSDN, at: + // http://msdn.microsoft.com/en-us/library/aa365247%28v=vs.85%29.aspx + static const char *sReservedNames[] = { "nul", "con", "prn", "aux", + "com1", "com2", "com3", "com4", "com5", "com6", + "com7", "com8", "com9", "lpt1", "lpt2", "lpt3", + "lpt4", "lpt5", "lpt6", "lpt7", "lpt8", "lpt9" }; + + // First, check to see if this is a device namespace, which always + // starts with \\.\, since device namespaces are not legal file paths. + if (path.startswith("\\\\.\\")) + return true; + + // Then compare against the list of ancient reserved names + for (size_t i = 0; i < sizeof(sReservedNames) / sizeof(const char *); ++i) { + if (path.equals_lower(sReservedNames[i])) + return true; + } + + // The path isn't what we consider reserved. + return false; +} + error_code status(const Twine &path, file_status &result) { SmallString<128> path_storage; SmallVector path_utf16; StringRef path8 = path.toStringRef(path_storage); - // FIXME: We should detect as many "special file name" as possible. - if (path8.compare_lower("nul") == 0) { + if (isReservedName(path8)) { result = file_status(file_type::character_file); return success; } @@ -501,7 +523,8 @@ handle_status_error: } error_code unique_file(const Twine &model, int &result_fd, - SmallVectorImpl &result_path) { + SmallVectorImpl &result_path, + bool makeAbsolute) { // Use result_path as temp storage. result_path.set_size(0); StringRef m = model.toStringRef(result_path); @@ -509,17 +532,19 @@ error_code unique_file(const Twine &model, int &result_fd, SmallVector model_utf16; if (error_code ec = UTF8ToUTF16(m, model_utf16)) return ec; - // Make model absolute by prepending a temp directory if it's not already. - bool absolute = path::is_absolute(m); - - if (!absolute) { - SmallVector temp_dir; - if (error_code ec = TempDir(temp_dir)) return ec; - // Handle c: by removing it. - if (model_utf16.size() > 2 && model_utf16[1] == L':') { - model_utf16.erase(model_utf16.begin(), model_utf16.begin() + 2); + if (makeAbsolute) { + // Make model absolute by prepending a temp directory if it's not already. + bool absolute = path::is_absolute(m); + + if (!absolute) { + SmallVector temp_dir; + if (error_code ec = TempDir(temp_dir)) return ec; + // Handle c: by removing it. + if (model_utf16.size() > 2 && model_utf16[1] == L':') { + model_utf16.erase(model_utf16.begin(), model_utf16.begin() + 2); + } + model_utf16.insert(model_utf16.begin(), temp_dir.begin(), temp_dir.end()); } - model_utf16.insert(model_utf16.begin(), temp_dir.begin(), temp_dir.end()); } // Replace '%' with random chars. From here on, DO NOT modify model. It may be diff --git a/contrib/llvm/lib/Support/Windows/Process.inc b/contrib/llvm/lib/Support/Windows/Process.inc index 06a7f0054..fe54eb1a7 100644 --- a/contrib/llvm/lib/Support/Windows/Process.inc +++ b/contrib/llvm/lib/Support/Windows/Process.inc @@ -15,6 +15,7 @@ #include #include #include +#include #ifdef __MINGW32__ #if (HAVE_LIBPSAPI != 1) @@ -219,4 +220,8 @@ const char *Process::ResetColor() { return 0; } +void Process::SetWorkingDirectory(std::string Path) { + ::_chdir(Path.c_str()); +} + } diff --git a/contrib/llvm/lib/Support/Windows/RWMutex.inc b/contrib/llvm/lib/Support/Windows/RWMutex.inc index 471f8fa29..26b9bba90 100644 --- a/contrib/llvm/lib/Support/Windows/RWMutex.inc +++ b/contrib/llvm/lib/Support/Windows/RWMutex.inc @@ -18,39 +18,115 @@ #include "Windows.h" -// FIXME: Windows does not have reader-writer locks pre-Vista. If you want -// real reader-writer locks, you a threads implementation for Windows. - namespace llvm { using namespace sys; +// Windows has slim read-writer lock support on Vista and higher, so we +// will attempt to load the APIs. If they exist, we will use them, and +// if not, we will fall back on critical sections. When we drop support +// for XP, we can stop lazy-loading these APIs and just use them directly. +#if defined(__MINGW32__) + // Taken from WinNT.h + typedef struct _RTL_SRWLOCK { + PVOID Ptr; + } RTL_SRWLOCK, *PRTL_SRWLOCK; + + // Taken from WinBase.h + typedef RTL_SRWLOCK SRWLOCK, *PSRWLOCK; +#endif + +static VOID (WINAPI *fpInitializeSRWLock)(PSRWLOCK lock) = NULL; +static VOID (WINAPI *fpAcquireSRWLockExclusive)(PSRWLOCK lock) = NULL; +static VOID (WINAPI *fpAcquireSRWLockShared)(PSRWLOCK lock) = NULL; +static VOID (WINAPI *fpReleaseSRWLockExclusive)(PSRWLOCK lock) = NULL; +static VOID (WINAPI *fpReleaseSRWLockShared)(PSRWLOCK lock) = NULL; + +static bool sHasSRW = false; + +static bool loadSRW() { + static bool sChecked = false; + if (!sChecked) { + sChecked = true; + + HMODULE hLib = ::LoadLibrary(TEXT("Kernel32")); + if (hLib) { + fpInitializeSRWLock = + (VOID (WINAPI *)(PSRWLOCK))::GetProcAddress(hLib, + "InitializeSRWLock"); + fpAcquireSRWLockExclusive = + (VOID (WINAPI *)(PSRWLOCK))::GetProcAddress(hLib, + "AcquireSRWLockExclusive"); + fpAcquireSRWLockShared = + (VOID (WINAPI *)(PSRWLOCK))::GetProcAddress(hLib, + "AcquireSRWLockShared"); + fpReleaseSRWLockExclusive = + (VOID (WINAPI *)(PSRWLOCK))::GetProcAddress(hLib, + "ReleaseSRWLockExclusive"); + fpReleaseSRWLockShared = + (VOID (WINAPI *)(PSRWLOCK))::GetProcAddress(hLib, + "ReleaseSRWLockShared"); + ::FreeLibrary(hLib); + + if (fpInitializeSRWLock != NULL) { + sHasSRW = true; + } + } + } + return sHasSRW; +} + RWMutexImpl::RWMutexImpl() { - data_ = calloc(1, sizeof(CRITICAL_SECTION)); - InitializeCriticalSection(static_cast(data_)); + if (loadSRW()) { + data_ = calloc(1, sizeof(SRWLOCK)); + fpInitializeSRWLock(static_cast(data_)); + } else { + data_ = calloc(1, sizeof(CRITICAL_SECTION)); + InitializeCriticalSection(static_cast(data_)); + } } RWMutexImpl::~RWMutexImpl() { - DeleteCriticalSection(static_cast(data_)); - free(data_); + if (sHasSRW) { + // Nothing to do in the case of slim reader/writers + } else { + DeleteCriticalSection(static_cast(data_)); + free(data_); + } } bool RWMutexImpl::reader_acquire() { - EnterCriticalSection(static_cast(data_)); + if (sHasSRW) { + fpAcquireSRWLockShared(static_cast(data_)); + } else { + EnterCriticalSection(static_cast(data_)); + } return true; } bool RWMutexImpl::reader_release() { - LeaveCriticalSection(static_cast(data_)); + if (sHasSRW) { + fpReleaseSRWLockShared(static_cast(data_)); + } else { + LeaveCriticalSection(static_cast(data_)); + } return true; } bool RWMutexImpl::writer_acquire() { - EnterCriticalSection(static_cast(data_)); + if (sHasSRW) { + fpAcquireSRWLockExclusive(static_cast(data_)); + } else { + EnterCriticalSection(static_cast(data_)); + } return true; } bool RWMutexImpl::writer_release() { - LeaveCriticalSection(static_cast(data_)); + if (sHasSRW) { + fpReleaseSRWLockExclusive(static_cast(data_)); + } else { + LeaveCriticalSection(static_cast(data_)); + } return true; } diff --git a/contrib/llvm/lib/Support/Windows/Signals.inc b/contrib/llvm/lib/Support/Windows/Signals.inc index 14f3f21f0..0d4b8a26b 100644 --- a/contrib/llvm/lib/Support/Windows/Signals.inc +++ b/contrib/llvm/lib/Support/Windows/Signals.inc @@ -23,14 +23,133 @@ #endif #include -#ifdef __MINGW32__ +#ifdef _MSC_VER + #pragma comment(lib, "psapi.lib") + #pragma comment(lib, "dbghelp.lib") +#elif __MINGW32__ #if ((HAVE_LIBIMAGEHLP != 1) || (HAVE_LIBPSAPI != 1)) #error "libimagehlp.a & libpsapi.a should be present" #endif -#else - #pragma comment(lib, "psapi.lib") - #pragma comment(lib, "dbghelp.lib") -#endif + // The version of g++ that comes with MinGW does *not* properly understand + // the ll format specifier for printf. However, MinGW passes the format + // specifiers on to the MSVCRT entirely, and the CRT understands the ll + // specifier. So these warnings are spurious in this case. Since we compile + // with -Wall, this will generate these warnings which should be ignored. So + // we will turn off the warnings for this just file. However, MinGW also does + // not support push and pop for diagnostics, so we have to manually turn it + // back on at the end of the file. + #pragma GCC diagnostic ignored "-Wformat" + #pragma GCC diagnostic ignored "-Wformat-extra-args" + + #if !defined(__MINGW64_VERSION_MAJOR) + // MinGW.org does not have updated support for the 64-bit versions of the + // DebugHlp APIs. So we will have to load them manually. The structures and + // method signatures were pulled from DbgHelp.h in the Windows Platform SDK, + // and adjusted for brevity. + typedef struct _IMAGEHLP_LINE64 { + DWORD SizeOfStruct; + PVOID Key; + DWORD LineNumber; + PCHAR FileName; + DWORD64 Address; + } IMAGEHLP_LINE64, *PIMAGEHLP_LINE64; + + typedef struct _IMAGEHLP_SYMBOL64 { + DWORD SizeOfStruct; + DWORD64 Address; + DWORD Size; + DWORD Flags; + DWORD MaxNameLength; + CHAR Name[1]; + } IMAGEHLP_SYMBOL64, *PIMAGEHLP_SYMBOL64; + + typedef struct _tagADDRESS64 { + DWORD64 Offset; + WORD Segment; + ADDRESS_MODE Mode; + } ADDRESS64, *LPADDRESS64; + + typedef struct _KDHELP64 { + DWORD64 Thread; + DWORD ThCallbackStack; + DWORD ThCallbackBStore; + DWORD NextCallback; + DWORD FramePointer; + DWORD64 KiCallUserMode; + DWORD64 KeUserCallbackDispatcher; + DWORD64 SystemRangeStart; + DWORD64 KiUserExceptionDispatcher; + DWORD64 StackBase; + DWORD64 StackLimit; + DWORD64 Reserved[5]; + } KDHELP64, *PKDHELP64; + + typedef struct _tagSTACKFRAME64 { + ADDRESS64 AddrPC; + ADDRESS64 AddrReturn; + ADDRESS64 AddrFrame; + ADDRESS64 AddrStack; + ADDRESS64 AddrBStore; + PVOID FuncTableEntry; + DWORD64 Params[4]; + BOOL Far; + BOOL Virtual; + DWORD64 Reserved[3]; + KDHELP64 KdHelp; + } STACKFRAME64, *LPSTACKFRAME64; + +typedef BOOL (__stdcall *PREAD_PROCESS_MEMORY_ROUTINE64)(HANDLE hProcess, + DWORD64 qwBaseAddress, PVOID lpBuffer, DWORD nSize, + LPDWORD lpNumberOfBytesRead); + +typedef PVOID (__stdcall *PFUNCTION_TABLE_ACCESS_ROUTINE64)( HANDLE ahProcess, + DWORD64 AddrBase); + +typedef DWORD64 (__stdcall *PGET_MODULE_BASE_ROUTINE64)(HANDLE hProcess, + DWORD64 Address); + +typedef DWORD64 (__stdcall *PTRANSLATE_ADDRESS_ROUTINE64)(HANDLE hProcess, + HANDLE hThread, LPADDRESS64 lpaddr); + +typedef BOOL (WINAPI *fpStackWalk64)(DWORD, HANDLE, HANDLE, LPSTACKFRAME64, + PVOID, PREAD_PROCESS_MEMORY_ROUTINE64, + PFUNCTION_TABLE_ACCESS_ROUTINE64, + PGET_MODULE_BASE_ROUTINE64, + PTRANSLATE_ADDRESS_ROUTINE64); +static fpStackWalk64 StackWalk64; + +typedef DWORD64 (WINAPI *fpSymGetModuleBase64)(HANDLE, DWORD64); +static fpSymGetModuleBase64 SymGetModuleBase64; + +typedef BOOL (WINAPI *fpSymGetSymFromAddr64)(HANDLE, DWORD64, + PDWORD64, PIMAGEHLP_SYMBOL64); +static fpSymGetSymFromAddr64 SymGetSymFromAddr64; + +typedef BOOL (WINAPI *fpSymGetLineFromAddr64)(HANDLE, DWORD64, + PDWORD, PIMAGEHLP_LINE64); +static fpSymGetLineFromAddr64 SymGetLineFromAddr64; + +typedef PVOID (WINAPI *fpSymFunctionTableAccess64)(HANDLE, DWORD64); +static fpSymFunctionTableAccess64 SymFunctionTableAccess64; + +static bool load64BitDebugHelp(void) { + HMODULE hLib = ::LoadLibrary("Dbghelp.dll"); + if (hLib) { + StackWalk64 = (fpStackWalk64) + ::GetProcAddress(hLib, "StackWalk64"); + SymGetModuleBase64 = (fpSymGetModuleBase64) + ::GetProcAddress(hLib, "SymGetModuleBase64"); + SymGetSymFromAddr64 = (fpSymGetSymFromAddr64) + ::GetProcAddress(hLib, "SymGetSymFromAddr64"); + SymGetLineFromAddr64 = (fpSymGetLineFromAddr64) + ::GetProcAddress(hLib, "SymGetLineFromAddr64"); + SymFunctionTableAccess64 = (fpSymFunctionTableAccess64) + ::GetProcAddress(hLib, "SymFunctionTableAccess64"); + } + return StackWalk64 != NULL; +} + #endif // !defined(__MINGW64_VERSION_MAJOR) +#endif // __MINGW32__ // Forward declare. static LONG WINAPI LLVMUnhandledExceptionFilter(LPEXCEPTION_POINTERS ep); @@ -90,6 +209,18 @@ static int CRTReportHook(int ReportType, char *Message, int *Return) { #endif static void RegisterHandler() { +#if __MINGW32__ && !defined(__MINGW64_VERSION_MAJOR) + // On MinGW.org, we need to load up the symbols explicitly, because the + // Win32 framework they include does not have support for the 64-bit + // versions of the APIs we need. If we cannot load up the APIs (which + // would be unexpected as they should exist on every version of Windows + // we support), we will bail out since there would be nothing to report. + if (!load64BitDebugHelp()) { + assert(false && "These APIs should always be available"); + return; + } +#endif + if (RegisteredUnhandledExceptionFilter) { EnterCriticalSection(&CriticalSection); return; @@ -213,20 +344,28 @@ void llvm::sys::RunInterruptHandlers() { static LONG WINAPI LLVMUnhandledExceptionFilter(LPEXCEPTION_POINTERS ep) { Cleanup(); -#ifdef _WIN64 - // TODO: provide a x64 friendly version of the following -#else - // Initialize the STACKFRAME structure. - STACKFRAME StackFrame; + STACKFRAME64 StackFrame; memset(&StackFrame, 0, sizeof(StackFrame)); + DWORD machineType; +#if defined(_M_X64) + machineType = IMAGE_FILE_MACHINE_AMD64; + StackFrame.AddrPC.Offset = ep->ContextRecord->Rip; + StackFrame.AddrPC.Mode = AddrModeFlat; + StackFrame.AddrStack.Offset = ep->ContextRecord->Rsp; + StackFrame.AddrStack.Mode = AddrModeFlat; + StackFrame.AddrFrame.Offset = ep->ContextRecord->Rbp; + StackFrame.AddrFrame.Mode = AddrModeFlat; +#elif defined(_M_IX86) + machineType = IMAGE_FILE_MACHINE_I386; StackFrame.AddrPC.Offset = ep->ContextRecord->Eip; StackFrame.AddrPC.Mode = AddrModeFlat; StackFrame.AddrStack.Offset = ep->ContextRecord->Esp; StackFrame.AddrStack.Mode = AddrModeFlat; StackFrame.AddrFrame.Offset = ep->ContextRecord->Ebp; StackFrame.AddrFrame.Mode = AddrModeFlat; +#endif HANDLE hProcess = GetCurrentProcess(); HANDLE hThread = GetCurrentThread(); @@ -236,9 +375,9 @@ static LONG WINAPI LLVMUnhandledExceptionFilter(LPEXCEPTION_POINTERS ep) { SymInitialize(hProcess, NULL, TRUE); while (true) { - if (!StackWalk(IMAGE_FILE_MACHINE_I386, hProcess, hThread, &StackFrame, - ep->ContextRecord, NULL, SymFunctionTableAccess, - SymGetModuleBase, NULL)) { + if (!StackWalk64(machineType, hProcess, hThread, &StackFrame, + ep->ContextRecord, NULL, SymFunctionTableAccess64, + SymGetModuleBase64, NULL)) { break; } @@ -246,54 +385,66 @@ static LONG WINAPI LLVMUnhandledExceptionFilter(LPEXCEPTION_POINTERS ep) { break; // Print the PC in hexadecimal. - DWORD PC = StackFrame.AddrPC.Offset; - fprintf(stderr, "%08lX", PC); + DWORD64 PC = StackFrame.AddrPC.Offset; +#if defined(_M_X64) + fprintf(stderr, "0x%016llX", PC); +#elif defined(_M_IX86) + fprintf(stderr, "0x%08lX", static_cast(PC)); +#endif // Print the parameters. Assume there are four. +#if defined(_M_X64) + fprintf(stderr, " (0x%016llX 0x%016llX 0x%016llX 0x%016llX)", + StackFrame.Params[0], + StackFrame.Params[1], + StackFrame.Params[2], + StackFrame.Params[3]); +#elif defined(_M_IX86) fprintf(stderr, " (0x%08lX 0x%08lX 0x%08lX 0x%08lX)", - StackFrame.Params[0], - StackFrame.Params[1], StackFrame.Params[2], StackFrame.Params[3]); - + static_cast(StackFrame.Params[0]), + static_cast(StackFrame.Params[1]), + static_cast(StackFrame.Params[2]), + static_cast(StackFrame.Params[3])); +#endif // Verify the PC belongs to a module in this process. - if (!SymGetModuleBase(hProcess, PC)) { + if (!SymGetModuleBase64(hProcess, PC)) { fputs(" \n", stderr); continue; } // Print the symbol name. char buffer[512]; - IMAGEHLP_SYMBOL *symbol = reinterpret_cast(buffer); - memset(symbol, 0, sizeof(IMAGEHLP_SYMBOL)); - symbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL); - symbol->MaxNameLength = 512 - sizeof(IMAGEHLP_SYMBOL); + IMAGEHLP_SYMBOL64 *symbol = reinterpret_cast(buffer); + memset(symbol, 0, sizeof(IMAGEHLP_SYMBOL64)); + symbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64); + symbol->MaxNameLength = 512 - sizeof(IMAGEHLP_SYMBOL64); - DWORD dwDisp; - if (!SymGetSymFromAddr(hProcess, PC, &dwDisp, symbol)) { + DWORD64 dwDisp; + if (!SymGetSymFromAddr64(hProcess, PC, &dwDisp, symbol)) { fputc('\n', stderr); continue; } buffer[511] = 0; if (dwDisp > 0) - fprintf(stderr, ", %s()+%04lu bytes(s)", symbol->Name, dwDisp); + fprintf(stderr, ", %s() + 0x%llX bytes(s)", symbol->Name, dwDisp); else fprintf(stderr, ", %s", symbol->Name); // Print the source file and line number information. - IMAGEHLP_LINE line; + IMAGEHLP_LINE64 line; + DWORD dwLineDisp; memset(&line, 0, sizeof(line)); line.SizeOfStruct = sizeof(line); - if (SymGetLineFromAddr(hProcess, PC, &dwDisp, &line)) { + if (SymGetLineFromAddr64(hProcess, PC, &dwLineDisp, &line)) { fprintf(stderr, ", %s, line %lu", line.FileName, line.LineNumber); - if (dwDisp > 0) - fprintf(stderr, "+%04lu byte(s)", dwDisp); + if (dwLineDisp > 0) + fprintf(stderr, " + 0x%lX byte(s)", dwLineDisp); } fputc('\n', stderr); } -#endif - if (ExitOnUnhandledExceptions) _exit(-3); @@ -326,3 +477,12 @@ static BOOL WINAPI LLVMConsoleCtrlHandler(DWORD dwCtrlType) { LeaveCriticalSection(&CriticalSection); return FALSE; } + +#if __MINGW32__ + // We turned these warnings off for this file so that MinGW-g++ doesn't + // complain about the ll format specifiers used. Now we are turning the + // warnings back on. If MinGW starts to support diagnostic stacks, we can + // replace this with a pop. + #pragma GCC diagnostic warning "-Wformat" + #pragma GCC diagnostic warning "-Wformat-extra-args" +#endif diff --git a/contrib/llvm/lib/Support/Windows/Windows.h b/contrib/llvm/lib/Support/Windows/Windows.h index 4a1553b59..67b6f0151 100644 --- a/contrib/llvm/lib/Support/Windows/Windows.h +++ b/contrib/llvm/lib/Support/Windows/Windows.h @@ -19,9 +19,9 @@ // mingw-w64 tends to define it as 0x0502 in its headers. #undef _WIN32_WINNT -// Require at least Windows 2000 API. -#define _WIN32_WINNT 0x0500 -#define _WIN32_IE 0x0500 // MinGW at it again. +// Require at least Windows XP(5.1) API. +#define _WIN32_WINNT 0x0501 +#define _WIN32_IE 0x0600 // MinGW at it again. #define WIN32_LEAN_AND_MEAN #include "llvm/Config/config.h" // Get build system configuration settings diff --git a/contrib/llvm/lib/Support/raw_ostream.cpp b/contrib/llvm/lib/Support/raw_ostream.cpp index 5a71fa3d8..4927e9a7b 100644 --- a/contrib/llvm/lib/Support/raw_ostream.cpp +++ b/contrib/llvm/lib/Support/raw_ostream.cpp @@ -84,7 +84,7 @@ void raw_ostream::SetBuffered() { } void raw_ostream::SetBufferAndMode(char *BufferStart, size_t Size, - BufferKind Mode) { + BufferKind Mode) { assert(((Mode == Unbuffered && BufferStart == 0 && Size == 0) || (Mode != Unbuffered && BufferStart && Size)) && "stream must be unbuffered or have at least one byte"); @@ -121,7 +121,8 @@ raw_ostream &raw_ostream::operator<<(unsigned long N) { raw_ostream &raw_ostream::operator<<(long N) { if (N < 0) { *this << '-'; - N = -N; + // Avoid undefined behavior on LONG_MIN with a cast. + N = -(unsigned long)N; } return this->operator<<(static_cast(N)); @@ -284,7 +285,7 @@ raw_ostream &raw_ostream::write(unsigned char C) { raw_ostream &raw_ostream::write(const char *Ptr, size_t Size) { // Group exceptional cases into a single branch. - if (BUILTIN_EXPECT(OutBufCur+Size > OutBufEnd, false)) { + if (BUILTIN_EXPECT(size_t(OutBufEnd - OutBufCur) < Size, false)) { if (BUILTIN_EXPECT(!OutBufStart, false)) { if (BufferMode == Unbuffered) { write_impl(Ptr, Size); diff --git a/contrib/llvm/utils/TableGen/Error.cpp b/contrib/llvm/lib/TableGen/Error.cpp similarity index 96% rename from contrib/llvm/utils/TableGen/Error.cpp rename to contrib/llvm/lib/TableGen/Error.cpp index 3f6cda897..5b2cbbfec 100644 --- a/contrib/llvm/utils/TableGen/Error.cpp +++ b/contrib/llvm/lib/TableGen/Error.cpp @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// -#include "Error.h" +#include "llvm/TableGen/Error.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/raw_ostream.h" diff --git a/contrib/llvm/lib/TableGen/Main.cpp b/contrib/llvm/lib/TableGen/Main.cpp new file mode 100644 index 000000000..01bc55e98 --- /dev/null +++ b/contrib/llvm/lib/TableGen/Main.cpp @@ -0,0 +1,124 @@ +//===- Main.cpp - Top-Level TableGen implementation -----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// TableGen is a tool which can be used to build up a description of something, +// then invoke one or more "tablegen backends" to emit information about the +// description in some predefined format. In practice, this is used by the LLVM +// code generators to automate generation of a code generator through a +// high-level description of the target. +// +//===----------------------------------------------------------------------===// + +#include "TGParser.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/ToolOutputFile.h" +#include "llvm/Support/system_error.h" +#include "llvm/TableGen/Error.h" +#include "llvm/TableGen/Record.h" +#include "llvm/TableGen/TableGenAction.h" +#include +#include +using namespace llvm; + +namespace { + cl::opt + OutputFilename("o", cl::desc("Output filename"), cl::value_desc("filename"), + cl::init("-")); + + cl::opt + DependFilename("d", cl::desc("Dependency filename"), cl::value_desc("filename"), + cl::init("")); + + cl::opt + InputFilename(cl::Positional, cl::desc(""), cl::init("-")); + + cl::list + IncludeDirs("I", cl::desc("Directory of include files"), + cl::value_desc("directory"), cl::Prefix); +} + +namespace llvm { + +int TableGenMain(char *argv0, TableGenAction &Action) { + RecordKeeper Records; + + try { + // Parse the input file. + OwningPtr File; + if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputFilename.c_str(), File)) { + errs() << "Could not open input file '" << InputFilename << "': " + << ec.message() <<"\n"; + return 1; + } + MemoryBuffer *F = File.take(); + + // Tell SrcMgr about this buffer, which is what TGParser will pick up. + SrcMgr.AddNewSourceBuffer(F, SMLoc()); + + // Record the location of the include directory so that the lexer can find + // it later. + SrcMgr.setIncludeDirs(IncludeDirs); + + TGParser Parser(SrcMgr, Records); + + if (Parser.ParseFile()) + return 1; + + std::string Error; + tool_output_file Out(OutputFilename.c_str(), Error); + if (!Error.empty()) { + errs() << argv0 << ": error opening " << OutputFilename + << ":" << Error << "\n"; + return 1; + } + if (!DependFilename.empty()) { + if (OutputFilename == "-") { + errs() << argv0 << ": the option -d must be used together with -o\n"; + return 1; + } + tool_output_file DepOut(DependFilename.c_str(), Error); + if (!Error.empty()) { + errs() << argv0 << ": error opening " << DependFilename + << ":" << Error << "\n"; + return 1; + } + DepOut.os() << OutputFilename << ":"; + const std::vector &Dependencies = Parser.getDependencies(); + for (std::vector::const_iterator I = Dependencies.begin(), + E = Dependencies.end(); + I != E; ++I) { + DepOut.os() << " " << (*I); + } + DepOut.os() << "\n"; + DepOut.keep(); + } + + if (Action(Out.os(), Records)) + return 1; + + // Declare success. + Out.keep(); + return 0; + + } catch (const TGError &Error) { + PrintError(Error); + } catch (const std::string &Error) { + PrintError(Error); + } catch (const char *Error) { + PrintError(Error); + } catch (...) { + errs() << argv0 << ": Unknown unexpected exception occurred.\n"; + } + + return 1; +} + +} diff --git a/contrib/llvm/utils/TableGen/Record.cpp b/contrib/llvm/lib/TableGen/Record.cpp similarity index 68% rename from contrib/llvm/utils/TableGen/Record.cpp rename to contrib/llvm/lib/TableGen/Record.cpp index 730eca1b3..b7c51cae9 100644 --- a/contrib/llvm/utils/TableGen/Record.cpp +++ b/contrib/llvm/lib/TableGen/Record.cpp @@ -11,20 +11,84 @@ // //===----------------------------------------------------------------------===// -#include "Record.h" -#include "Error.h" +#include "llvm/TableGen/Record.h" +#include "llvm/TableGen/Error.h" #include "llvm/Support/DataTypes.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Format.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringMap.h" using namespace llvm; +//===----------------------------------------------------------------------===// +// std::string wrapper for DenseMap purposes +//===----------------------------------------------------------------------===// + +/// TableGenStringKey - This is a wrapper for std::string suitable for +/// using as a key to a DenseMap. Because there isn't a particularly +/// good way to indicate tombstone or empty keys for strings, we want +/// to wrap std::string to indicate that this is a "special" string +/// not expected to take on certain values (those of the tombstone and +/// empty keys). This makes things a little safer as it clarifies +/// that DenseMap is really not appropriate for general strings. + +class TableGenStringKey { +public: + TableGenStringKey(const std::string &str) : data(str) {} + TableGenStringKey(const char *str) : data(str) {} + + const std::string &str() const { return data; } + +private: + std::string data; +}; + +/// Specialize DenseMapInfo for TableGenStringKey. +namespace llvm { + +template<> struct DenseMapInfo { + static inline TableGenStringKey getEmptyKey() { + TableGenStringKey Empty("<<>>"); + return Empty; + } + static inline TableGenStringKey getTombstoneKey() { + TableGenStringKey Tombstone("<<>>"); + return Tombstone; + } + static unsigned getHashValue(const TableGenStringKey& Val) { + return HashString(Val.str()); + } + static bool isEqual(const TableGenStringKey& LHS, + const TableGenStringKey& RHS) { + return LHS.str() == RHS.str(); + } +}; + +} + //===----------------------------------------------------------------------===// // Type implementations //===----------------------------------------------------------------------===// +BitRecTy BitRecTy::Shared; +IntRecTy IntRecTy::Shared; +StringRecTy StringRecTy::Shared; +CodeRecTy CodeRecTy::Shared; +DagRecTy DagRecTy::Shared; + void RecTy::dump() const { print(errs()); } +ListRecTy *RecTy::getListTy() { + if (!ListTy) + ListTy = new ListRecTy(this); + return ListTy; +} + Init *BitRecTy::convertValue(BitsInit *BI) { if (BI->getNumBits() != 1) return 0; // Only accept if just one bit! return BI->getBit(0); @@ -38,7 +102,7 @@ Init *BitRecTy::convertValue(IntInit *II) { int64_t Val = II->getValue(); if (Val != 0 && Val != 1) return 0; // Only accept 0 or 1 for a bit! - return new BitInit(Val != 0); + return BitInit::get(Val != 0); } Init *BitRecTy::convertValue(TypedInit *VI) { @@ -47,23 +111,32 @@ Init *BitRecTy::convertValue(TypedInit *VI) { return 0; } +BitsRecTy *BitsRecTy::get(unsigned Sz) { + static std::vector Shared; + if (Sz >= Shared.size()) + Shared.resize(Sz + 1); + BitsRecTy *&Ty = Shared[Sz]; + if (!Ty) + Ty = new BitsRecTy(Sz); + return Ty; +} + std::string BitsRecTy::getAsString() const { return "bits<" + utostr(Size) + ">"; } Init *BitsRecTy::convertValue(UnsetInit *UI) { - BitsInit *Ret = new BitsInit(Size); + SmallVector NewBits(Size); for (unsigned i = 0; i != Size; ++i) - Ret->setBit(i, new UnsetInit()); - return Ret; + NewBits[i] = UnsetInit::get(); + + return BitsInit::get(NewBits); } Init *BitsRecTy::convertValue(BitInit *UI) { if (Size != 1) return 0; // Can only convert single bit. - BitsInit *Ret = new BitsInit(1); - Ret->setBit(0, UI); - return Ret; + return BitsInit::get(UI); } /// canFitInBitfield - Return true if the number of bits is large enough to hold @@ -83,11 +156,12 @@ Init *BitsRecTy::convertValue(IntInit *II) { if (!canFitInBitfield(Value, Size)) return 0; - BitsInit *Ret = new BitsInit(Size); + SmallVector NewBits(Size); + for (unsigned i = 0; i != Size; ++i) - Ret->setBit(i, new BitInit(Value & (1LL << i))); + NewBits[i] = BitInit::get(Value & (1LL << i)); - return Ret; + return BitsInit::get(NewBits); } Init *BitsRecTy::convertValue(BitsInit *BI) { @@ -100,17 +174,15 @@ Init *BitsRecTy::convertValue(BitsInit *BI) { Init *BitsRecTy::convertValue(TypedInit *VI) { if (BitsRecTy *BRT = dynamic_cast(VI->getType())) if (BRT->Size == Size) { - BitsInit *Ret = new BitsInit(Size); + SmallVector NewBits(Size); + for (unsigned i = 0; i != Size; ++i) - Ret->setBit(i, new VarBitInit(VI, i)); - return Ret; + NewBits[i] = VarBitInit::get(VI, i); + return BitsInit::get(NewBits); } - if (Size == 1 && dynamic_cast(VI->getType())) { - BitsInit *Ret = new BitsInit(1); - Ret->setBit(0, VI); - return Ret; - } + if (Size == 1 && dynamic_cast(VI->getType())) + return BitsInit::get(VI); if (TernOpInit *Tern = dynamic_cast(VI)) { if (Tern->getOpcode() == TernOpInit::IF) { @@ -126,30 +198,31 @@ Init *BitsRecTy::convertValue(TypedInit *VI) { int64_t RHSVal = RHSi->getValue(); if (canFitInBitfield(MHSVal, Size) && canFitInBitfield(RHSVal, Size)) { - BitsInit *Ret = new BitsInit(Size); + SmallVector NewBits(Size); for (unsigned i = 0; i != Size; ++i) - Ret->setBit(i, new TernOpInit(TernOpInit::IF, LHS, - new IntInit((MHSVal & (1LL << i)) ? 1 : 0), - new IntInit((RHSVal & (1LL << i)) ? 1 : 0), - VI->getType())); + NewBits[i] = + TernOpInit::get(TernOpInit::IF, LHS, + IntInit::get((MHSVal & (1LL << i)) ? 1 : 0), + IntInit::get((RHSVal & (1LL << i)) ? 1 : 0), + VI->getType()); - return Ret; + return BitsInit::get(NewBits); } } else { BitsInit *MHSbs = dynamic_cast(MHS); BitsInit *RHSbs = dynamic_cast(RHS); if (MHSbs && RHSbs) { - BitsInit *Ret = new BitsInit(Size); + SmallVector NewBits(Size); for (unsigned i = 0; i != Size; ++i) - Ret->setBit(i, new TernOpInit(TernOpInit::IF, LHS, - MHSbs->getBit(i), - RHSbs->getBit(i), - VI->getType())); + NewBits[i] = TernOpInit::get(TernOpInit::IF, LHS, + MHSbs->getBit(i), + RHSbs->getBit(i), + VI->getType()); - return Ret; + return BitsInit::get(NewBits); } } } @@ -159,7 +232,7 @@ Init *BitsRecTy::convertValue(TypedInit *VI) { } Init *IntRecTy::convertValue(BitInit *BI) { - return new IntInit(BI->getValue()); + return IntInit::get(BI->getValue()); } Init *IntRecTy::convertValue(BitsInit *BI) { @@ -170,7 +243,7 @@ Init *IntRecTy::convertValue(BitsInit *BI) { } else { return 0; } - return new IntInit(Result); + return IntInit::get(Result); } Init *IntRecTy::convertValue(TypedInit *TI) { @@ -184,7 +257,7 @@ Init *StringRecTy::convertValue(UnOpInit *BO) { Init *L = BO->getOperand()->convertInitializerTo(this); if (L == 0) return 0; if (L != BO->getOperand()) - return new UnOpInit(UnOpInit::CAST, L, new StringRecTy); + return UnOpInit::get(UnOpInit::CAST, L, new StringRecTy); return BO; } @@ -197,7 +270,7 @@ Init *StringRecTy::convertValue(BinOpInit *BO) { Init *R = BO->getRHS()->convertInitializerTo(this); if (L == 0 || R == 0) return 0; if (L != BO->getLHS() || R != BO->getRHS()) - return new BinOpInit(BinOpInit::STRCONCAT, L, R, new StringRecTy); + return BinOpInit::get(BinOpInit::STRCONCAT, L, R, new StringRecTy); return BO; } @@ -231,7 +304,7 @@ Init *ListRecTy::convertValue(ListInit *LI) { return 0; } - return new ListInit(Elements, new ListRecTy(Ty)); + return ListInit::get(Elements, this); } Init *ListRecTy::convertValue(TypedInit *TI) { @@ -259,7 +332,7 @@ Init *DagRecTy::convertValue(UnOpInit *BO) { Init *L = BO->getOperand()->convertInitializerTo(this); if (L == 0) return 0; if (L != BO->getOperand()) - return new UnOpInit(UnOpInit::CAST, L, new DagRecTy); + return UnOpInit::get(UnOpInit::CAST, L, new DagRecTy); return BO; } return 0; @@ -271,12 +344,16 @@ Init *DagRecTy::convertValue(BinOpInit *BO) { Init *R = BO->getRHS()->convertInitializerTo(this); if (L == 0 || R == 0) return 0; if (L != BO->getLHS() || R != BO->getRHS()) - return new BinOpInit(BinOpInit::CONCAT, L, R, new DagRecTy); + return BinOpInit::get(BinOpInit::CONCAT, L, R, new DagRecTy); return BO; } return 0; } +RecordRecTy *RecordRecTy::get(Record *R) { + return &dynamic_cast(*R->getDefInit()->getType()); +} + std::string RecordRecTy::getAsString() const { return Rec->getName(); } @@ -326,7 +403,7 @@ RecTy *llvm::resolveTypes(RecTy *T1, RecTy *T2) { iend = T1SuperClasses.end(); i != iend; ++i) { - RecordRecTy *SuperRecTy1 = new RecordRecTy(*i); + RecordRecTy *SuperRecTy1 = RecordRecTy::get(*i); RecTy *NewType1 = resolveTypes(SuperRecTy1, T2); if (NewType1 != 0) { if (NewType1 != SuperRecTy1) { @@ -345,7 +422,7 @@ RecTy *llvm::resolveTypes(RecTy *T1, RecTy *T2) { iend = T2SuperClasses.end(); i != iend; ++i) { - RecordRecTy *SuperRecTy2 = new RecordRecTy(*i); + RecordRecTy *SuperRecTy2 = RecordRecTy::get(*i); RecTy *NewType2 = resolveTypes(T1, SuperRecTy2); if (NewType2 != 0) { if (NewType2 != SuperRecTy2) { @@ -369,16 +446,60 @@ RecTy *llvm::resolveTypes(RecTy *T1, RecTy *T2) { void Init::dump() const { return print(errs()); } -Init *BitsInit::convertInitializerBitRange(const std::vector &Bits) { - BitsInit *BI = new BitsInit(Bits.size()); +UnsetInit *UnsetInit::get() { + static UnsetInit TheInit; + return &TheInit; +} + +BitInit *BitInit::get(bool V) { + static BitInit True(true); + static BitInit False(false); + + return V ? &True : &False; +} + +static void +ProfileBitsInit(FoldingSetNodeID &ID, ArrayRef Range) { + ID.AddInteger(Range.size()); + + for (ArrayRef::iterator i = Range.begin(), + iend = Range.end(); + i != iend; + ++i) + ID.AddPointer(*i); +} + +BitsInit *BitsInit::get(ArrayRef Range) { + typedef FoldingSet Pool; + static Pool ThePool; + + FoldingSetNodeID ID; + ProfileBitsInit(ID, Range); + + void *IP = 0; + if (BitsInit *I = ThePool.FindNodeOrInsertPos(ID, IP)) + return I; + + BitsInit *I = new BitsInit(Range); + ThePool.InsertNode(I, IP); + + return I; +} + +void BitsInit::Profile(FoldingSetNodeID &ID) const { + ProfileBitsInit(ID, Bits); +} + +Init * +BitsInit::convertInitializerBitRange(const std::vector &Bits) const { + SmallVector NewBits(Bits.size()); + for (unsigned i = 0, e = Bits.size(); i != e; ++i) { - if (Bits[i] >= getNumBits()) { - delete BI; + if (Bits[i] >= getNumBits()) return 0; - } - BI->setBit(i, getBit(Bits[i])); + NewBits[i] = getBit(Bits[i]); } - return BI; + return BitsInit::get(NewBits); } std::string BitsInit::getAsString() const { @@ -396,9 +517,9 @@ std::string BitsInit::getAsString() const { // resolveReferences - If there are any field references that refer to fields // that have been filled in, we can propagate the values now. // -Init *BitsInit::resolveReferences(Record &R, const RecordVal *RV) { +Init *BitsInit::resolveReferences(Record &R, const RecordVal *RV) const { bool Changed = false; - BitsInit *New = new BitsInit(getNumBits()); + SmallVector NewBits(getNumBits()); for (unsigned i = 0, e = Bits.size(); i != e; ++i) { Init *B; @@ -409,40 +530,107 @@ Init *BitsInit::resolveReferences(Record &R, const RecordVal *RV) { CurBit = CurBit->resolveReferences(R, RV); Changed |= B != CurBit; } while (B != CurBit); - New->setBit(i, CurBit); + NewBits[i] = CurBit; } if (Changed) - return New; - delete New; - return this; + return BitsInit::get(NewBits); + + return const_cast(this); +} + +IntInit *IntInit::get(int64_t V) { + typedef DenseMap Pool; + static Pool ThePool; + + IntInit *&I = ThePool[V]; + if (!I) I = new IntInit(V); + return I; } std::string IntInit::getAsString() const { return itostr(Value); } -Init *IntInit::convertInitializerBitRange(const std::vector &Bits) { - BitsInit *BI = new BitsInit(Bits.size()); +Init * +IntInit::convertInitializerBitRange(const std::vector &Bits) const { + SmallVector NewBits(Bits.size()); for (unsigned i = 0, e = Bits.size(); i != e; ++i) { - if (Bits[i] >= 64) { - delete BI; + if (Bits[i] >= 64) return 0; - } - BI->setBit(i, new BitInit(Value & (INT64_C(1) << Bits[i]))); + + NewBits[i] = BitInit::get(Value & (INT64_C(1) << Bits[i])); } - return BI; + return BitsInit::get(NewBits); +} + +StringInit *StringInit::get(const std::string &V) { + typedef StringMap Pool; + static Pool ThePool; + + StringInit *&I = ThePool[V]; + if (!I) I = new StringInit(V); + return I; +} + +CodeInit *CodeInit::get(const std::string &V) { + typedef StringMap Pool; + static Pool ThePool; + + CodeInit *&I = ThePool[V]; + if (!I) I = new CodeInit(V); + return I; +} + +static void ProfileListInit(FoldingSetNodeID &ID, + ArrayRef Range, + RecTy *EltTy) { + ID.AddInteger(Range.size()); + ID.AddPointer(EltTy); + + for (ArrayRef::iterator i = Range.begin(), + iend = Range.end(); + i != iend; + ++i) + ID.AddPointer(*i); +} + +ListInit *ListInit::get(ArrayRef Range, RecTy *EltTy) { + typedef FoldingSet Pool; + static Pool ThePool; + + // Just use the FoldingSetNodeID to compute a hash. Use a DenseMap + // for actual storage. + FoldingSetNodeID ID; + ProfileListInit(ID, Range, EltTy); + + void *IP = 0; + if (ListInit *I = ThePool.FindNodeOrInsertPos(ID, IP)) + return I; + + ListInit *I = new ListInit(Range, EltTy); + ThePool.InsertNode(I, IP); + return I; } -Init *ListInit::convertInitListSlice(const std::vector &Elements) { +void ListInit::Profile(FoldingSetNodeID &ID) const { + ListRecTy *ListType = dynamic_cast(getType()); + assert(ListType && "Bad type for ListInit!"); + RecTy *EltTy = ListType->getElementType(); + + ProfileListInit(ID, Values, EltTy); +} + +Init * +ListInit::convertInitListSlice(const std::vector &Elements) const { std::vector Vals; for (unsigned i = 0, e = Elements.size(); i != e; ++i) { if (Elements[i] >= getSize()) return 0; Vals.push_back(getElement(Elements[i])); } - return new ListInit(Vals, getType()); + return ListInit::get(Vals, getType()); } Record *ListInit::getElementAsRecord(unsigned i) const { @@ -452,7 +640,7 @@ Record *ListInit::getElementAsRecord(unsigned i) const { return DI->getDef(); } -Init *ListInit::resolveReferences(Record &R, const RecordVal *RV) { +Init *ListInit::resolveReferences(Record &R, const RecordVal *RV) const { std::vector Resolved; Resolved.reserve(getSize()); bool Changed = false; @@ -470,12 +658,12 @@ Init *ListInit::resolveReferences(Record &R, const RecordVal *RV) { } if (Changed) - return new ListInit(Resolved, getType()); - return this; + return ListInit::get(Resolved, getType()); + return const_cast(this); } Init *ListInit::resolveListElementReference(Record &R, const RecordVal *IRV, - unsigned Elt) { + unsigned Elt) const { if (Elt >= getSize()) return 0; // Out of range reference. Init *E = getElement(Elt); @@ -497,7 +685,7 @@ std::string ListInit::getAsString() const { } Init *OpInit::resolveBitReference(Record &R, const RecordVal *IRV, - unsigned Bit) { + unsigned Bit) const { Init *Folded = Fold(&R, 0); if (Folded != this) { @@ -511,20 +699,41 @@ Init *OpInit::resolveBitReference(Record &R, const RecordVal *IRV, } Init *OpInit::resolveListElementReference(Record &R, const RecordVal *IRV, - unsigned Elt) { - Init *Folded = Fold(&R, 0); + unsigned Elt) const { + Init *Resolved = resolveReferences(R, IRV); + OpInit *OResolved = dynamic_cast(Resolved); + if (OResolved) { + Resolved = OResolved->Fold(&R, 0); + } - if (Folded != this) { - TypedInit *Typed = dynamic_cast(Folded); + if (Resolved != this) { + TypedInit *Typed = dynamic_cast(Resolved); + assert(Typed && "Expected typed init for list reference"); if (Typed) { - return Typed->resolveListElementReference(R, IRV, Elt); + Init *New = Typed->resolveListElementReference(R, IRV, Elt); + if (New) + return New; + return VarListElementInit::get(Typed, Elt); } } return 0; } -Init *UnOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) { +UnOpInit *UnOpInit::get(UnaryOp opc, Init *lhs, RecTy *Type) { + typedef std::pair, RecTy *> Key; + + typedef DenseMap Pool; + static Pool ThePool; + + Key TheKey(std::make_pair(std::make_pair(opc, lhs), Type)); + + UnOpInit *&I = ThePool[TheKey]; + if (!I) I = new UnOpInit(opc, lhs, Type); + return I; +} + +Init *UnOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) const { switch (getOpcode()) { default: assert(0 && "Unknown unop"); case CAST: { @@ -536,7 +745,7 @@ Init *UnOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) { DefInit *LHSd = dynamic_cast(LHS); if (LHSd) { - return new StringInit(LHSd->getDef()->getName()); + return StringInit::get(LHSd->getDef()->getName()); } } else { StringInit *LHSs = dynamic_cast(LHS); @@ -548,7 +757,7 @@ Init *UnOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) { if (const RecordVal *RV = CurRec->getValue(Name)) { if (RV->getType() != getType()) throw "type mismatch in cast"; - return new VarInit(Name, RV->getType()); + return VarInit::get(Name, RV->getType()); } std::string TemplateArgName = CurRec->getName()+":"+Name; @@ -559,7 +768,7 @@ Init *UnOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) { if (RV->getType() != getType()) throw "type mismatch in cast"; - return new VarInit(TemplateArgName, RV->getType()); + return VarInit::get(TemplateArgName, RV->getType()); } } @@ -572,12 +781,12 @@ Init *UnOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) { if (RV->getType() != getType()) throw "type mismatch in cast"; - return new VarInit(MCName, RV->getType()); + return VarInit::get(MCName, RV->getType()); } } if (Record *D = (CurRec->getRecords()).getDef(Name)) - return new DefInit(D); + return DefInit::get(D); throw TGError(CurRec->getLoc(), "Undefined reference:'" + Name + "'\n"); } @@ -602,8 +811,13 @@ Init *UnOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) { assert(0 && "Empty list in cdr"); return 0; } - ListInit *Result = new ListInit(LHSl->begin()+1, LHSl->end(), - LHSl->getType()); + // Note the +1. We can't just pass the result of getValues() + // directly. + ArrayRef::iterator begin = LHSl->getValues().begin()+1; + ArrayRef::iterator end = LHSl->getValues().end(); + ListInit *Result = + ListInit::get(ArrayRef(begin, end - begin), + LHSl->getType()); return Result; } break; @@ -612,31 +826,31 @@ Init *UnOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) { ListInit *LHSl = dynamic_cast(LHS); if (LHSl) { if (LHSl->getSize() == 0) { - return new IntInit(1); + return IntInit::get(1); } else { - return new IntInit(0); + return IntInit::get(0); } } StringInit *LHSs = dynamic_cast(LHS); if (LHSs) { if (LHSs->getValue().empty()) { - return new IntInit(1); + return IntInit::get(1); } else { - return new IntInit(0); + return IntInit::get(0); } } break; } } - return this; + return const_cast(this); } -Init *UnOpInit::resolveReferences(Record &R, const RecordVal *RV) { +Init *UnOpInit::resolveReferences(Record &R, const RecordVal *RV) const { Init *lhs = LHS->resolveReferences(R, RV); if (LHS != lhs) - return (new UnOpInit(getOpcode(), lhs, getType()))->Fold(&R, 0); + return (UnOpInit::get(getOpcode(), lhs, getType()))->Fold(&R, 0); return Fold(&R, 0); } @@ -651,7 +865,25 @@ std::string UnOpInit::getAsString() const { return Result + "(" + LHS->getAsString() + ")"; } -Init *BinOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) { +BinOpInit *BinOpInit::get(BinaryOp opc, Init *lhs, + Init *rhs, RecTy *Type) { + typedef std::pair< + std::pair, Init *>, + RecTy * + > Key; + + typedef DenseMap Pool; + static Pool ThePool; + + Key TheKey(std::make_pair(std::make_pair(std::make_pair(opc, lhs), rhs), + Type)); + + BinOpInit *&I = ThePool[TheKey]; + if (!I) I = new BinOpInit(opc, lhs, rhs, Type); + return I; +} + +Init *BinOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) const { switch (getOpcode()) { default: assert(0 && "Unknown binop"); case CONCAT: { @@ -672,7 +904,7 @@ Init *BinOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) { Args.push_back(RHSs->getArg(i)); ArgNames.push_back(RHSs->getArgName(i)); } - return new DagInit(LHSs->getOperator(), "", Args, ArgNames); + return DagInit::get(LHSs->getOperator(), "", Args, ArgNames); } break; } @@ -680,26 +912,26 @@ Init *BinOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) { StringInit *LHSs = dynamic_cast(LHS); StringInit *RHSs = dynamic_cast(RHS); if (LHSs && RHSs) - return new StringInit(LHSs->getValue() + RHSs->getValue()); + return StringInit::get(LHSs->getValue() + RHSs->getValue()); break; } case EQ: { // try to fold eq comparison for 'bit' and 'int', otherwise fallback // to string objects. IntInit* L = - dynamic_cast(LHS->convertInitializerTo(new IntRecTy())); + dynamic_cast(LHS->convertInitializerTo(IntRecTy::get())); IntInit* R = - dynamic_cast(RHS->convertInitializerTo(new IntRecTy())); + dynamic_cast(RHS->convertInitializerTo(IntRecTy::get())); if (L && R) - return new IntInit(L->getValue() == R->getValue()); + return IntInit::get(L->getValue() == R->getValue()); StringInit *LHSs = dynamic_cast(LHS); StringInit *RHSs = dynamic_cast(RHS); // Make sure we've resolved if (LHSs && RHSs) - return new IntInit(LHSs->getValue() == RHSs->getValue()); + return IntInit::get(LHSs->getValue() == RHSs->getValue()); break; } @@ -717,20 +949,20 @@ Init *BinOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) { case SRA: Result = LHSv >> RHSv; break; case SRL: Result = (uint64_t)LHSv >> (uint64_t)RHSv; break; } - return new IntInit(Result); + return IntInit::get(Result); } break; } } - return this; + return const_cast(this); } -Init *BinOpInit::resolveReferences(Record &R, const RecordVal *RV) { +Init *BinOpInit::resolveReferences(Record &R, const RecordVal *RV) const { Init *lhs = LHS->resolveReferences(R, RV); Init *rhs = RHS->resolveReferences(R, RV); if (LHS != lhs || RHS != rhs) - return (new BinOpInit(getOpcode(), lhs, rhs, getType()))->Fold(&R, 0); + return (BinOpInit::get(getOpcode(), lhs, rhs, getType()))->Fold(&R, 0); return Fold(&R, 0); } @@ -747,6 +979,31 @@ std::string BinOpInit::getAsString() const { return Result + "(" + LHS->getAsString() + ", " + RHS->getAsString() + ")"; } +TernOpInit *TernOpInit::get(TernaryOp opc, Init *lhs, + Init *mhs, Init *rhs, + RecTy *Type) { + typedef std::pair< + std::pair< + std::pair, Init *>, + Init * + >, + Init * + > Key; + + typedef DenseMap Pool; + static Pool ThePool; + + Key TheKey(std::make_pair(std::make_pair(std::make_pair(std::make_pair(opc, + Type), + lhs), + mhs), + rhs)); + + TernOpInit *&I = ThePool[TheKey]; + if (!I) I = new TernOpInit(opc, lhs, mhs, rhs, Type); + return I; +} + static Init *ForeachHelper(Init *LHS, Init *MHS, Init *RHS, RecTy *Type, Record *CurRec, MultiClass *CurMultiClass); @@ -787,12 +1044,11 @@ static Init *EvaluateOperation(OpInit *RHSo, Init *LHS, Init *Arg, } // Now run the operator and use its result as the new leaf - OpInit *NewOp = RHSo->clone(NewOperands); + const OpInit *NewOp = RHSo->clone(NewOperands); Init *NewVal = NewOp->Fold(CurRec, CurMultiClass); - if (NewVal != NewOp) { - delete NewOp; + if (NewVal != NewOp) return NewVal; - } + return 0; } @@ -843,13 +1099,13 @@ static Init *ForeachHelper(Init *LHS, Init *MHS, Init *RHS, RecTy *Type, args.push_back(std::make_pair(Arg, ArgName)); } - return new DagInit(Val, "", args); + return DagInit::get(Val, "", args); } if (MHSl) { std::vector NewOperands; std::vector NewList(MHSl->begin(), MHSl->end()); - for (ListInit::iterator li = NewList.begin(), + for (std::vector::iterator li = NewList.begin(), liend = NewList.end(); li != liend; ++li) { @@ -865,20 +1121,18 @@ static Init *ForeachHelper(Init *LHS, Init *MHS, Init *RHS, RecTy *Type, } // Now run the operator and use its result as the new list item - OpInit *NewOp = RHSo->clone(NewOperands); + const OpInit *NewOp = RHSo->clone(NewOperands); Init *NewItem = NewOp->Fold(CurRec, CurMultiClass); - if (NewItem != NewOp) { + if (NewItem != NewOp) *li = NewItem; - delete NewOp; - } } - return new ListInit(NewList, MHSl->getType()); + return ListInit::get(NewList, MHSl->getType()); } } return 0; } -Init *TernOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) { +Init *TernOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) const { switch (getOpcode()) { default: assert(0 && "Unknown binop"); case SUBST: { @@ -902,14 +1156,14 @@ Init *TernOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) { if (LHSd->getAsString() == RHSd->getAsString()) { Val = MHSd->getDef(); } - return new DefInit(Val); + return DefInit::get(Val); } if (RHSv) { std::string Val = RHSv->getName(); if (LHSv->getAsString() == RHSv->getAsString()) { Val = MHSv->getName(); } - return new VarInit(Val, getType()); + return VarInit::get(Val, getType()); } if (RHSs) { std::string Val = RHSs->getValue(); @@ -924,7 +1178,7 @@ Init *TernOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) { idx = found + MHSs->getValue().size(); } while (found != std::string::npos); - return new StringInit(Val); + return StringInit::get(Val); } } break; @@ -941,7 +1195,7 @@ Init *TernOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) { case IF: { IntInit *LHSi = dynamic_cast(LHS); - if (Init *I = LHS->convertInitializerTo(new IntRecTy())) + if (Init *I = LHS->convertInitializerTo(IntRecTy::get())) LHSi = dynamic_cast(I); if (LHSi) { if (LHSi->getValue()) { @@ -954,26 +1208,27 @@ Init *TernOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) { } } - return this; + return const_cast(this); } -Init *TernOpInit::resolveReferences(Record &R, const RecordVal *RV) { +Init *TernOpInit::resolveReferences(Record &R, + const RecordVal *RV) const { Init *lhs = LHS->resolveReferences(R, RV); if (Opc == IF && lhs != LHS) { IntInit *Value = dynamic_cast(lhs); - if (Init *I = lhs->convertInitializerTo(new IntRecTy())) + if (Init *I = lhs->convertInitializerTo(IntRecTy::get())) Value = dynamic_cast(I); if (Value != 0) { // Short-circuit if (Value->getValue()) { Init *mhs = MHS->resolveReferences(R, RV); - return (new TernOpInit(getOpcode(), lhs, mhs, - RHS, getType()))->Fold(&R, 0); + return (TernOpInit::get(getOpcode(), lhs, mhs, + RHS, getType()))->Fold(&R, 0); } else { Init *rhs = RHS->resolveReferences(R, RV); - return (new TernOpInit(getOpcode(), lhs, MHS, - rhs, getType()))->Fold(&R, 0); + return (TernOpInit::get(getOpcode(), lhs, MHS, + rhs, getType()))->Fold(&R, 0); } } } @@ -982,7 +1237,8 @@ Init *TernOpInit::resolveReferences(Record &R, const RecordVal *RV) { Init *rhs = RHS->resolveReferences(R, RV); if (LHS != lhs || MHS != mhs || RHS != rhs) - return (new TernOpInit(getOpcode(), lhs, mhs, rhs, getType()))->Fold(&R, 0); + return (TernOpInit::get(getOpcode(), lhs, mhs, rhs, + getType()))->Fold(&R, 0); return Fold(&R, 0); } @@ -1008,39 +1264,53 @@ RecTy *TypedInit::getFieldType(const std::string &FieldName) const { return 0; } -Init *TypedInit::convertInitializerBitRange(const std::vector &Bits) { +Init * +TypedInit::convertInitializerBitRange(const std::vector &Bits) const { BitsRecTy *T = dynamic_cast(getType()); if (T == 0) return 0; // Cannot subscript a non-bits variable. unsigned NumBits = T->getNumBits(); - BitsInit *BI = new BitsInit(Bits.size()); + SmallVector NewBits(Bits.size()); for (unsigned i = 0, e = Bits.size(); i != e; ++i) { - if (Bits[i] >= NumBits) { - delete BI; + if (Bits[i] >= NumBits) return 0; - } - BI->setBit(i, new VarBitInit(this, Bits[i])); + + NewBits[i] = VarBitInit::get(const_cast(this), Bits[i]); } - return BI; + return BitsInit::get(NewBits); } -Init *TypedInit::convertInitListSlice(const std::vector &Elements) { +Init * +TypedInit::convertInitListSlice(const std::vector &Elements) const { ListRecTy *T = dynamic_cast(getType()); if (T == 0) return 0; // Cannot subscript a non-list variable. if (Elements.size() == 1) - return new VarListElementInit(this, Elements[0]); + return VarListElementInit::get(const_cast(this), Elements[0]); std::vector ListInits; ListInits.reserve(Elements.size()); for (unsigned i = 0, e = Elements.size(); i != e; ++i) - ListInits.push_back(new VarListElementInit(this, Elements[i])); - return new ListInit(ListInits, T); + ListInits.push_back(VarListElementInit::get(const_cast(this), + Elements[i])); + return ListInit::get(ListInits, T); } +VarInit *VarInit::get(const std::string &VN, RecTy *T) { + typedef std::pair Key; + typedef DenseMap Pool; + static Pool ThePool; + + Key TheKey(std::make_pair(T, VN)); + + VarInit *&I = ThePool[TheKey]; + if (!I) I = new VarInit(VN, T); + return I; +} + Init *VarInit::resolveBitReference(Record &R, const RecordVal *IRV, - unsigned Bit) { + unsigned Bit) const { if (R.isTemplateArg(getName())) return 0; if (IRV && IRV->getName() != getName()) return 0; @@ -1060,8 +1330,9 @@ Init *VarInit::resolveBitReference(Record &R, const RecordVal *IRV, return 0; } -Init *VarInit::resolveListElementReference(Record &R, const RecordVal *IRV, - unsigned Elt) { +Init *VarInit::resolveListElementReference(Record &R, + const RecordVal *IRV, + unsigned Elt) const { if (R.isTemplateArg(getName())) return 0; if (IRV && IRV->getName() != getName()) return 0; @@ -1069,9 +1340,9 @@ Init *VarInit::resolveListElementReference(Record &R, const RecordVal *IRV, assert(RV && "Reference to a non-existent variable?"); ListInit *LI = dynamic_cast(RV->getValue()); if (!LI) { - VarInit *VI = dynamic_cast(RV->getValue()); + TypedInit *VI = dynamic_cast(RV->getValue()); assert(VI && "Invalid list element!"); - return new VarListElementInit(VI, Elt); + return VarListElementInit::get(VI, Elt); } if (Elt >= LI->getSize()) @@ -1114,48 +1385,91 @@ Init *VarInit::getFieldInit(Record &R, const RecordVal *RV, /// If a value is set for the variable later, this method will be called on /// users of the value to allow the value to propagate out. /// -Init *VarInit::resolveReferences(Record &R, const RecordVal *RV) { +Init *VarInit::resolveReferences(Record &R, const RecordVal *RV) const { if (RecordVal *Val = R.getValue(VarName)) if (RV == Val || (RV == 0 && !dynamic_cast(Val->getValue()))) return Val->getValue(); - return this; + return const_cast(this); +} + +VarBitInit *VarBitInit::get(TypedInit *T, unsigned B) { + typedef std::pair Key; + typedef DenseMap Pool; + + static Pool ThePool; + + Key TheKey(std::make_pair(T, B)); + + VarBitInit *&I = ThePool[TheKey]; + if (!I) I = new VarBitInit(T, B); + return I; } std::string VarBitInit::getAsString() const { return TI->getAsString() + "{" + utostr(Bit) + "}"; } -Init *VarBitInit::resolveReferences(Record &R, const RecordVal *RV) { +Init *VarBitInit::resolveReferences(Record &R, const RecordVal *RV) const { if (Init *I = getVariable()->resolveBitReference(R, RV, getBitNum())) return I; - return this; + return const_cast(this); +} + +VarListElementInit *VarListElementInit::get(TypedInit *T, + unsigned E) { + typedef std::pair Key; + typedef DenseMap Pool; + + static Pool ThePool; + + Key TheKey(std::make_pair(T, E)); + + VarListElementInit *&I = ThePool[TheKey]; + if (!I) I = new VarListElementInit(T, E); + return I; } std::string VarListElementInit::getAsString() const { return TI->getAsString() + "[" + utostr(Element) + "]"; } -Init *VarListElementInit::resolveReferences(Record &R, const RecordVal *RV) { +Init * +VarListElementInit::resolveReferences(Record &R, const RecordVal *RV) const { if (Init *I = getVariable()->resolveListElementReference(R, RV, getElementNum())) return I; - return this; + return const_cast(this); } Init *VarListElementInit::resolveBitReference(Record &R, const RecordVal *RV, - unsigned Bit) { + unsigned Bit) const { // FIXME: This should be implemented, to support references like: // bit B = AA[0]{1}; return 0; } -Init *VarListElementInit:: -resolveListElementReference(Record &R, const RecordVal *RV, unsigned Elt) { - // FIXME: This should be implemented, to support references like: - // int B = AA[0][1]; +Init *VarListElementInit:: resolveListElementReference(Record &R, + const RecordVal *RV, + unsigned Elt) const { + Init *Result = TI->resolveListElementReference(R, RV, Element); + + if (Result) { + TypedInit *TInit = dynamic_cast(Result); + if (TInit) { + Init *Result2 = TInit->resolveListElementReference(R, RV, Elt); + if (Result2) return Result2; + return new VarListElementInit(TInit, Elt); + } + return Result; + } + return 0; } +DefInit *DefInit::get(Record *R) { + return R->getDefInit(); +} + RecTy *DefInit::getFieldType(const std::string &FieldName) const { if (const RecordVal *RV = Def->getValue(FieldName)) return RV->getType(); @@ -1172,8 +1486,20 @@ std::string DefInit::getAsString() const { return Def->getName(); } +FieldInit *FieldInit::get(Init *R, const std::string &FN) { + typedef std::pair Key; + typedef DenseMap Pool; + static Pool ThePool; + + Key TheKey(std::make_pair(R, FN)); + + FieldInit *&I = ThePool[TheKey]; + if (!I) I = new FieldInit(R, FN); + return I; +} + Init *FieldInit::resolveBitReference(Record &R, const RecordVal *RV, - unsigned Bit) { + unsigned Bit) const { if (Init *BitsVal = Rec->getFieldInit(R, RV, FieldName)) if (BitsInit *BI = dynamic_cast(BitsVal)) { assert(Bit < BI->getNumBits() && "Bit reference out of range!"); @@ -1186,7 +1512,7 @@ Init *FieldInit::resolveBitReference(Record &R, const RecordVal *RV, } Init *FieldInit::resolveListElementReference(Record &R, const RecordVal *RV, - unsigned Elt) { + unsigned Elt) const { if (Init *ListVal = Rec->getFieldInit(R, RV, FieldName)) if (ListInit *LI = dynamic_cast(ListVal)) { if (Elt >= LI->getSize()) return 0; @@ -1201,22 +1527,83 @@ Init *FieldInit::resolveListElementReference(Record &R, const RecordVal *RV, return 0; } -Init *FieldInit::resolveReferences(Record &R, const RecordVal *RV) { +Init *FieldInit::resolveReferences(Record &R, const RecordVal *RV) const { Init *NewRec = RV ? Rec->resolveReferences(R, RV) : Rec; Init *BitsVal = NewRec->getFieldInit(R, RV, FieldName); if (BitsVal) { Init *BVR = BitsVal->resolveReferences(R, RV); - return BVR->isComplete() ? BVR : this; + return BVR->isComplete() ? BVR : const_cast(this); } if (NewRec != Rec) { - return new FieldInit(NewRec, FieldName); + return FieldInit::get(NewRec, FieldName); + } + return const_cast(this); +} + +void ProfileDagInit(FoldingSetNodeID &ID, + Init *V, + const std::string &VN, + ArrayRef ArgRange, + ArrayRef NameRange) { + ID.AddPointer(V); + ID.AddString(VN); + + ArrayRef::iterator Arg = ArgRange.begin(); + ArrayRef::iterator Name = NameRange.begin(); + while (Arg != ArgRange.end()) { + assert(Name != NameRange.end() && "Arg name underflow!"); + ID.AddPointer(*Arg++); + ID.AddString(*Name++); + } + assert(Name == NameRange.end() && "Arg name overflow!"); +} + +DagInit * +DagInit::get(Init *V, const std::string &VN, + ArrayRef ArgRange, + ArrayRef NameRange) { + typedef FoldingSet Pool; + static Pool ThePool; + + FoldingSetNodeID ID; + ProfileDagInit(ID, V, VN, ArgRange, NameRange); + + void *IP = 0; + if (DagInit *I = ThePool.FindNodeOrInsertPos(ID, IP)) + return I; + + DagInit *I = new DagInit(V, VN, ArgRange, NameRange); + ThePool.InsertNode(I, IP); + + return I; +} + +DagInit * +DagInit::get(Init *V, const std::string &VN, + const std::vector > &args) { + typedef std::pair PairType; + + std::vector Args; + std::vector Names; + + for (std::vector::const_iterator i = args.begin(), + iend = args.end(); + i != iend; + ++i) { + Args.push_back(i->first); + Names.push_back(i->second); } - return this; + + return DagInit::get(V, VN, Args, Names); +} + +void DagInit::Profile(FoldingSetNodeID &ID) const { + ProfileDagInit(ID, Val, ValName, Args, ArgNames); } -Init *DagInit::resolveReferences(Record &R, const RecordVal *RV) { +Init *DagInit::resolveReferences(Record &R, const RecordVal *RV) const { std::vector NewArgs; for (unsigned i = 0, e = Args.size(); i != e; ++i) NewArgs.push_back(Args[i]->resolveReferences(R, RV)); @@ -1224,9 +1611,9 @@ Init *DagInit::resolveReferences(Record &R, const RecordVal *RV) { Init *Op = Val->resolveReferences(R, RV); if (Args != NewArgs || Op != Val) - return new DagInit(Op, ValName, NewArgs, ArgNames); + return DagInit::get(Op, ValName, NewArgs, ArgNames); - return this; + return const_cast(this); } @@ -1250,12 +1637,24 @@ std::string DagInit::getAsString() const { // Other implementations //===----------------------------------------------------------------------===// -RecordVal::RecordVal(const std::string &N, RecTy *T, unsigned P) +RecordVal::RecordVal(Init *N, RecTy *T, unsigned P) : Name(N), Ty(T), Prefix(P) { - Value = Ty->convertValue(new UnsetInit()); + Value = Ty->convertValue(UnsetInit::get()); assert(Value && "Cannot create unset value for current type!"); } +RecordVal::RecordVal(const std::string &N, RecTy *T, unsigned P) + : Name(StringInit::get(N)), Ty(T), Prefix(P) { + Value = Ty->convertValue(UnsetInit::get()); + assert(Value && "Cannot create unset value for current type!"); +} + +const std::string &RecordVal::getName() const { + StringInit *NameString = dynamic_cast(Name); + assert(NameString && "RecordVal name is not a string!"); + return NameString->getValue(); +} + void RecordVal::dump() const { errs() << *this; } void RecordVal::print(raw_ostream &OS, bool PrintSem) const { @@ -1270,16 +1669,61 @@ void RecordVal::print(raw_ostream &OS, bool PrintSem) const { unsigned Record::LastID = 0; -void Record::setName(const std::string &Name) { - if (TrackedRecords.getDef(getName()) == this) { - TrackedRecords.removeDef(getName()); - this->Name = Name; +void Record::checkName() { + // Ensure the record name has string type. + const TypedInit *TypedName = dynamic_cast(Name); + assert(TypedName && "Record name is not typed!"); + RecTy *Type = TypedName->getType(); + if (dynamic_cast(Type) == 0) { + llvm_unreachable("Record name is not a string!"); + } +} + +DefInit *Record::getDefInit() { + if (!TheInit) + TheInit = new DefInit(this, new RecordRecTy(this)); + return TheInit; +} + +const std::string &Record::getName() const { + const StringInit *NameString = + dynamic_cast(Name); + assert(NameString && "Record name is not a string!"); + return NameString->getValue(); +} + +void Record::setName(Init *NewName) { + if (TrackedRecords.getDef(Name->getAsUnquotedString()) == this) { + TrackedRecords.removeDef(Name->getAsUnquotedString()); + Name = NewName; TrackedRecords.addDef(this); } else { - TrackedRecords.removeClass(getName()); - this->Name = Name; + TrackedRecords.removeClass(Name->getAsUnquotedString()); + Name = NewName; TrackedRecords.addClass(this); } + checkName(); + // Since the Init for the name was changed, see if we can resolve + // any of it using members of the Record. + Init *ComputedName = Name->resolveReferences(*this, 0); + if (ComputedName != Name) { + setName(ComputedName); + } + // DO NOT resolve record values to the name at this point because + // there might be default values for arguments of this def. Those + // arguments might not have been resolved yet so we don't want to + // prematurely assume values for those arguments were not passed to + // this def. + // + // Nonetheless, it may be that some of this Record's values + // reference the record name. Indeed, the reason for having the + // record name be an Init is to provide this flexibility. The extra + // resolve steps after completely instantiating defs takes care of + // this. See TGParser::ParseDef and TGParser::ParseDefm. +} + +void Record::setName(const std::string &Name) { + setName(StringInit::get(Name)); } /// resolveReferencesTo - If anything in this record refers to RV, replace the @@ -1351,7 +1795,7 @@ std::string Record::getValueAsString(StringRef FieldName) const { throw "Record `" + getName() + "' does not have a field named `" + FieldName.str() + "'!\n"; - if (const StringInit *SI = dynamic_cast(R->getValue())) + if (StringInit *SI = dynamic_cast(R->getValue())) return SI->getValue(); throw "Record `" + getName() + "', field `" + FieldName.str() + "' does not have a string initializer!"; @@ -1516,7 +1960,7 @@ std::string Record::getValueAsCode(StringRef FieldName) const { throw "Record `" + getName() + "' does not have a field named `" + FieldName.str() + "'!\n"; - if (const CodeInit *CI = dynamic_cast(R->getValue())) + if (CodeInit *CI = dynamic_cast(R->getValue())) return CI->getValue(); throw "Record `" + getName() + "', field `" + FieldName.str() + "' does not have a code initializer!"; diff --git a/contrib/llvm/utils/TableGen/TGLexer.cpp b/contrib/llvm/lib/TableGen/TGLexer.cpp similarity index 90% rename from contrib/llvm/utils/TableGen/TGLexer.cpp rename to contrib/llvm/lib/TableGen/TGLexer.cpp index b4b90ff64..8c1b42905 100644 --- a/contrib/llvm/utils/TableGen/TGLexer.cpp +++ b/contrib/llvm/lib/TableGen/TGLexer.cpp @@ -12,7 +12,7 @@ //===----------------------------------------------------------------------===// #include "TGLexer.h" -#include "Error.h" +#include "llvm/TableGen/Error.h" #include "llvm/Support/SourceMgr.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Config/config.h" @@ -208,40 +208,40 @@ tgtok::TokKind TGLexer::LexVarName() { tgtok::TokKind TGLexer::LexIdentifier() { // The first letter is [a-zA-Z_#]. const char *IdentStart = TokStart; - + // Match the rest of the identifier regex: [0-9a-zA-Z_#]* while (isalpha(*CurPtr) || isdigit(*CurPtr) || *CurPtr == '_' || *CurPtr == '#') ++CurPtr; - - + // Check to see if this identifier is a keyword. - unsigned Len = CurPtr-IdentStart; - - if (Len == 3 && !memcmp(IdentStart, "int", 3)) return tgtok::Int; - if (Len == 3 && !memcmp(IdentStart, "bit", 3)) return tgtok::Bit; - if (Len == 4 && !memcmp(IdentStart, "bits", 4)) return tgtok::Bits; - if (Len == 6 && !memcmp(IdentStart, "string", 6)) return tgtok::String; - if (Len == 4 && !memcmp(IdentStart, "list", 4)) return tgtok::List; - if (Len == 4 && !memcmp(IdentStart, "code", 4)) return tgtok::Code; - if (Len == 3 && !memcmp(IdentStart, "dag", 3)) return tgtok::Dag; - - if (Len == 5 && !memcmp(IdentStart, "class", 5)) return tgtok::Class; - if (Len == 3 && !memcmp(IdentStart, "def", 3)) return tgtok::Def; - if (Len == 4 && !memcmp(IdentStart, "defm", 4)) return tgtok::Defm; - if (Len == 10 && !memcmp(IdentStart, "multiclass", 10)) - return tgtok::MultiClass; - if (Len == 5 && !memcmp(IdentStart, "field", 5)) return tgtok::Field; - if (Len == 3 && !memcmp(IdentStart, "let", 3)) return tgtok::Let; - if (Len == 2 && !memcmp(IdentStart, "in", 2)) return tgtok::In; - - if (Len == 7 && !memcmp(IdentStart, "include", 7)) { + StringRef Str(IdentStart, CurPtr-IdentStart); + + if (Str == "include") { if (LexInclude()) return tgtok::Error; return Lex(); } - - CurStrVal.assign(IdentStart, CurPtr); - return tgtok::Id; + + tgtok::TokKind Kind = StringSwitch(Str) + .Case("int", tgtok::Int) + .Case("bit", tgtok::Bit) + .Case("bits", tgtok::Bits) + .Case("string", tgtok::String) + .Case("list", tgtok::List) + .Case("code", tgtok::Code) + .Case("dag", tgtok::Dag) + .Case("class", tgtok::Class) + .Case("def", tgtok::Def) + .Case("defm", tgtok::Defm) + .Case("multiclass", tgtok::MultiClass) + .Case("field", tgtok::Field) + .Case("let", tgtok::Let) + .Case("in", tgtok::In) + .Default(tgtok::Id); + + if (Kind == tgtok::Id) + CurStrVal.assign(Str.begin(), Str.end()); + return Kind; } /// LexInclude - We just read the "include" token. Get the string token that diff --git a/contrib/llvm/utils/TableGen/TGLexer.h b/contrib/llvm/lib/TableGen/TGLexer.h similarity index 100% rename from contrib/llvm/utils/TableGen/TGLexer.h rename to contrib/llvm/lib/TableGen/TGLexer.h diff --git a/contrib/llvm/utils/TableGen/TGParser.cpp b/contrib/llvm/lib/TableGen/TGParser.cpp similarity index 88% rename from contrib/llvm/utils/TableGen/TGParser.cpp rename to contrib/llvm/lib/TableGen/TGParser.cpp index 59097f986..e7f00baf4 100644 --- a/contrib/llvm/utils/TableGen/TGParser.cpp +++ b/contrib/llvm/lib/TableGen/TGParser.cpp @@ -12,7 +12,7 @@ //===----------------------------------------------------------------------===// #include "TGParser.h" -#include "Record.h" +#include "llvm/TableGen/Record.h" #include "llvm/ADT/StringExtras.h" #include #include @@ -106,9 +106,9 @@ bool TGParser::SetValue(Record *CurRec, SMLoc Loc, const std::string &ValName, return Error(Loc, "Value '" + ValName + "' is not a bits type"); // Convert the incoming value to a bits type of the appropriate size... - Init *BI = V->convertInitializerTo(new BitsRecTy(BitList.size())); + Init *BI = V->convertInitializerTo(BitsRecTy::get(BitList.size())); if (BI == 0) { - V->convertInitializerTo(new BitsRecTy(BitList.size())); + V->convertInitializerTo(BitsRecTy::get(BitList.size())); return Error(Loc, "Initializer is not compatible with bit range"); } @@ -116,22 +116,22 @@ bool TGParser::SetValue(Record *CurRec, SMLoc Loc, const std::string &ValName, BitsInit *BInit = dynamic_cast(BI); assert(BInit != 0); - BitsInit *NewVal = new BitsInit(CurVal->getNumBits()); + SmallVector NewBits(CurVal->getNumBits()); // Loop over bits, assigning values as appropriate. for (unsigned i = 0, e = BitList.size(); i != e; ++i) { unsigned Bit = BitList[i]; - if (NewVal->getBit(Bit)) + if (NewBits[Bit]) return Error(Loc, "Cannot set bit #" + utostr(Bit) + " of value '" + ValName + "' more than once"); - NewVal->setBit(Bit, BInit->getBit(i)); + NewBits[Bit] = BInit->getBit(i); } for (unsigned i = 0, e = CurVal->getNumBits(); i != e; ++i) - if (NewVal->getBit(i) == 0) - NewVal->setBit(i, CurVal->getBit(i)); + if (NewBits[i] == 0) + NewBits[i] = CurVal->getBit(i); - V = NewVal; + V = BitsInit::get(NewBits); } if (RV->setValue(V)) @@ -581,13 +581,13 @@ bool TGParser::ParseOptionalBitList(std::vector &Ranges) { RecTy *TGParser::ParseType() { switch (Lex.getCode()) { default: TokError("Unknown token when expecting a type"); return 0; - case tgtok::String: Lex.Lex(); return new StringRecTy(); - case tgtok::Bit: Lex.Lex(); return new BitRecTy(); - case tgtok::Int: Lex.Lex(); return new IntRecTy(); - case tgtok::Code: Lex.Lex(); return new CodeRecTy(); - case tgtok::Dag: Lex.Lex(); return new DagRecTy(); + case tgtok::String: Lex.Lex(); return StringRecTy::get(); + case tgtok::Bit: Lex.Lex(); return BitRecTy::get(); + case tgtok::Int: Lex.Lex(); return IntRecTy::get(); + case tgtok::Code: Lex.Lex(); return CodeRecTy::get(); + case tgtok::Dag: Lex.Lex(); return DagRecTy::get(); case tgtok::Id: - if (Record *R = ParseClassID()) return new RecordRecTy(R); + if (Record *R = ParseClassID()) return RecordRecTy::get(R); return 0; case tgtok::Bits: { if (Lex.Lex() != tgtok::less) { // Eat 'bits' @@ -604,7 +604,7 @@ RecTy *TGParser::ParseType() { return 0; } Lex.Lex(); // Eat '>' - return new BitsRecTy(Val); + return BitsRecTy::get(Val); } case tgtok::List: { if (Lex.Lex() != tgtok::less) { // Eat 'bits' @@ -620,7 +620,7 @@ RecTy *TGParser::ParseType() { return 0; } Lex.Lex(); // Eat '>' - return new ListRecTy(SubType); + return ListRecTy::get(SubType); } } } @@ -647,13 +647,16 @@ Init *TGParser::ParseIDValue(Record *CurRec, const std::string &Name, SMLoc NameLoc) { if (CurRec) { if (const RecordVal *RV = CurRec->getValue(Name)) - return new VarInit(Name, RV->getType()); + return VarInit::get(Name, RV->getType()); std::string TemplateArgName = CurRec->getName()+":"+Name; + if (CurMultiClass) + TemplateArgName = CurMultiClass->Rec.getName()+"::"+TemplateArgName; + if (CurRec->isTemplateArg(TemplateArgName)) { const RecordVal *RV = CurRec->getValue(TemplateArgName); assert(RV && "Template arg doesn't exist??"); - return new VarInit(TemplateArgName, RV->getType()); + return VarInit::get(TemplateArgName, RV->getType()); } } @@ -662,12 +665,12 @@ Init *TGParser::ParseIDValue(Record *CurRec, if (CurMultiClass->Rec.isTemplateArg(MCName)) { const RecordVal *RV = CurMultiClass->Rec.getValue(MCName); assert(RV && "Template arg doesn't exist??"); - return new VarInit(MCName, RV->getType()); + return VarInit::get(MCName, RV->getType()); } } if (Record *D = Records.getDef(Name)) - return new DefInit(D); + return DefInit::get(D); Error(NameLoc, "Variable not defined: '" + Name + "'"); return 0; @@ -715,7 +718,7 @@ Init *TGParser::ParseOperation(Record *CurRec) { case tgtok::XEmpty: Lex.Lex(); // eat the operation Code = UnOpInit::EMPTY; - Type = new IntRecTy; + Type = IntRecTy::get(); break; } if (Lex.getCode() != tgtok::l_paren) { @@ -767,7 +770,7 @@ Init *TGParser::ParseOperation(Record *CurRec) { if (Code == UnOpInit::HEAD) { Type = Itemt->getType(); } else { - Type = new ListRecTy(Itemt->getType()); + Type = ListRecTy::get(Itemt->getType()); } } else { assert(LHSt && "expected list type argument in unary operator"); @@ -790,7 +793,7 @@ Init *TGParser::ParseOperation(Record *CurRec) { return 0; } Lex.Lex(); // eat the ')' - return (new UnOpInit(Code, LHS, Type))->Fold(CurRec, CurMultiClass); + return (UnOpInit::get(Code, LHS, Type))->Fold(CurRec, CurMultiClass); } case tgtok::XConcat: @@ -808,14 +811,14 @@ Init *TGParser::ParseOperation(Record *CurRec) { switch (OpTok) { default: assert(0 && "Unhandled code!"); - case tgtok::XConcat: Code = BinOpInit::CONCAT; Type = new DagRecTy(); break; - case tgtok::XSRA: Code = BinOpInit::SRA; Type = new IntRecTy(); break; - case tgtok::XSRL: Code = BinOpInit::SRL; Type = new IntRecTy(); break; - case tgtok::XSHL: Code = BinOpInit::SHL; Type = new IntRecTy(); break; - case tgtok::XEq: Code = BinOpInit::EQ; Type = new BitRecTy(); break; + case tgtok::XConcat: Code = BinOpInit::CONCAT;Type = DagRecTy::get(); break; + case tgtok::XSRA: Code = BinOpInit::SRA; Type = IntRecTy::get(); break; + case tgtok::XSRL: Code = BinOpInit::SRL; Type = IntRecTy::get(); break; + case tgtok::XSHL: Code = BinOpInit::SHL; Type = IntRecTy::get(); break; + case tgtok::XEq: Code = BinOpInit::EQ; Type = BitRecTy::get(); break; case tgtok::XStrConcat: Code = BinOpInit::STRCONCAT; - Type = new StringRecTy(); + Type = StringRecTy::get(); break; } @@ -848,14 +851,14 @@ Init *TGParser::ParseOperation(Record *CurRec) { if (Code == BinOpInit::STRCONCAT) { while (InitList.size() > 2) { Init *RHS = InitList.pop_back_val(); - RHS = (new BinOpInit(Code, InitList.back(), RHS, Type)) - ->Fold(CurRec, CurMultiClass); + RHS = (BinOpInit::get(Code, InitList.back(), RHS, Type)) + ->Fold(CurRec, CurMultiClass); InitList.back() = RHS; } } if (InitList.size() == 2) - return (new BinOpInit(Code, InitList[0], InitList[1], Type)) + return (BinOpInit::get(Code, InitList[0], InitList[1], Type)) ->Fold(CurRec, CurMultiClass); Error(OpLoc, "expected two operands to operator"); @@ -932,14 +935,14 @@ Init *TGParser::ParseOperation(Record *CurRec) { if (MHSbits && RHSbits && MHSbits->getNumBits() == RHSbits->getNumBits()) { - Type = new BitRecTy(); + Type = BitRecTy::get(); break; } else { BitInit *MHSbit = dynamic_cast(MHS); BitInit *RHSbit = dynamic_cast(RHS); if (MHSbit && RHSbit) { - Type = new BitRecTy(); + Type = BitRecTy::get(); break; } } @@ -982,7 +985,7 @@ Init *TGParser::ParseOperation(Record *CurRec) { break; } } - return (new TernOpInit(Code, LHS, MHS, RHS, Type))->Fold(CurRec, + return (TernOpInit::get(Code, LHS, MHS, RHS, Type))->Fold(CurRec, CurMultiClass); } } @@ -1042,7 +1045,7 @@ Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType) { Init *R = 0; switch (Lex.getCode()) { default: TokError("Unknown token when parsing a value"); break; - case tgtok::IntVal: R = new IntInit(Lex.getCurIntVal()); Lex.Lex(); break; + case tgtok::IntVal: R = IntInit::get(Lex.getCurIntVal()); Lex.Lex(); break; case tgtok::StrVal: { std::string Val = Lex.getCurStrVal(); Lex.Lex(); @@ -1053,15 +1056,15 @@ Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType) { Lex.Lex(); } - R = new StringInit(Val); + R = StringInit::get(Val); break; } case tgtok::CodeFragment: - R = new CodeInit(Lex.getCurStrVal()); + R = CodeInit::get(Lex.getCurStrVal()); Lex.Lex(); break; case tgtok::question: - R = new UnsetInit(); + R = UnsetInit::get(); Lex.Lex(); break; case tgtok::Id: { @@ -1110,7 +1113,7 @@ Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType) { Records.addDef(NewRec); // The result of the expression is a reference to the new record. - return new DefInit(NewRec); + return DefInit::get(NewRec); } case tgtok::l_brace: { // Value ::= '{' ValueList '}' SMLoc BraceLoc = Lex.getLoc(); @@ -1127,17 +1130,18 @@ Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType) { } Lex.Lex(); // eat the '}' - BitsInit *Result = new BitsInit(Vals.size()); + SmallVector NewBits(Vals.size()); + for (unsigned i = 0, e = Vals.size(); i != e; ++i) { - Init *Bit = Vals[i]->convertInitializerTo(new BitRecTy()); + Init *Bit = Vals[i]->convertInitializerTo(BitRecTy::get()); if (Bit == 0) { Error(BraceLoc, "Element #" + utostr(i) + " (" + Vals[i]->getAsString()+ ") is not convertable to a bit"); return 0; } - Result->setBit(Vals.size()-i-1, Bit); + NewBits[Vals.size()-i-1] = Bit; } - return Result; + return BitsInit::get(NewBits); } case tgtok::l_square: { // Value ::= '[' ValueList ']' Lex.Lex(); // eat the '[' @@ -1236,7 +1240,7 @@ Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType) { DeducedEltTy = EltTy; } - return new ListInit(Vals, DeducedEltTy); + return ListInit::get(Vals, DeducedEltTy); } case tgtok::l_paren: { // Value ::= '(' IDValue DagArgList ')' Lex.Lex(); // eat the '(' @@ -1271,7 +1275,7 @@ Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType) { } Lex.Lex(); // eat the ')' - return new DagInit(Operator, OperatorName, DagArgs); + return DagInit::get(Operator, OperatorName, DagArgs); } case tgtok::XHead: @@ -1361,7 +1365,7 @@ Init *TGParser::ParseValue(Record *CurRec, RecTy *ItemType) { Result->getAsString() + "'"); return 0; } - Result = new FieldInit(Result, Lex.getCurStrVal()); + Result = FieldInit::get(Result, Lex.getCurStrVal()); Lex.Lex(); // eat field name break; } @@ -1415,6 +1419,10 @@ std::vector TGParser::ParseValueList(Record *CurRec, Record *ArgsRec, if (ArgsRec != 0 && EltTy == 0) { const std::vector &TArgs = ArgsRec->getTemplateArgs(); const RecordVal *RV = ArgsRec->getValue(TArgs[ArgN]); + if (!RV) { + errs() << "Cannot find template arg " << ArgN << " (" << TArgs[ArgN] + << ")\n"; + } assert(RV && "Template argument record not found??"); ItemType = RV->getType(); ++ArgN; @@ -1689,6 +1697,9 @@ bool TGParser::ParseDef(MultiClass *CurMultiClass) { return true; if (CurMultiClass == 0) // Def's in multiclasses aren't really defs. + // See Record::setName(). This resolve step will see any new name + // for the def that might have been created when resolving + // inheritance, values and arguments above. CurRec->resolveReferences(); // If ObjectBody has template arguments, it's an error. @@ -1709,7 +1720,6 @@ bool TGParser::ParseDef(MultiClass *CurMultiClass) { return false; } - /// ParseClass - Parse a tblgen class definition. /// /// ClassInst ::= CLASS ID TemplateArgList? ObjectBody @@ -1911,6 +1921,115 @@ bool TGParser::ParseMultiClass() { return false; } +Record *TGParser:: +InstantiateMulticlassDef(MultiClass &MC, + Record *DefProto, + const std::string &DefmPrefix, + SMLoc DefmPrefixLoc) { + // Add in the defm name. If the defm prefix is empty, give each + // instantiated def a unique name. Otherwise, if "#NAME#" exists in the + // name, substitute the prefix for #NAME#. Otherwise, use the defm name + // as a prefix. + std::string DefName = DefProto->getName(); + if (DefmPrefix.empty()) { + DefName = GetNewAnonymousName(); + } else { + std::string::size_type idx = DefName.find("#NAME#"); + if (idx != std::string::npos) { + DefName.replace(idx, 6, DefmPrefix); + } else { + // Add the suffix to the defm name to get the new name. + DefName = DefmPrefix + DefName; + } + } + + Record *CurRec = new Record(DefName, DefmPrefixLoc, Records); + + SubClassReference Ref; + Ref.RefLoc = DefmPrefixLoc; + Ref.Rec = DefProto; + AddSubClass(CurRec, Ref); + + return CurRec; +} + +bool TGParser::ResolveMulticlassDefArgs(MultiClass &MC, + Record *CurRec, + SMLoc DefmPrefixLoc, + SMLoc SubClassLoc, + const std::vector &TArgs, + std::vector &TemplateVals, + bool DeleteArgs) { + // Loop over all of the template arguments, setting them to the specified + // value or leaving them as the default if necessary. + for (unsigned i = 0, e = TArgs.size(); i != e; ++i) { + // Check if a value is specified for this temp-arg. + if (i < TemplateVals.size()) { + // Set it now. + if (SetValue(CurRec, DefmPrefixLoc, TArgs[i], std::vector(), + TemplateVals[i])) + return true; + + // Resolve it next. + CurRec->resolveReferencesTo(CurRec->getValue(TArgs[i])); + + if (DeleteArgs) + // Now remove it. + CurRec->removeValue(TArgs[i]); + + } else if (!CurRec->getValue(TArgs[i])->getValue()->isComplete()) { + return Error(SubClassLoc, "value not specified for template argument #"+ + utostr(i) + " (" + TArgs[i] + ") of multiclassclass '" + + MC.Rec.getName() + "'"); + } + } + return false; +} + +bool TGParser::ResolveMulticlassDef(MultiClass &MC, + Record *CurRec, + Record *DefProto, + SMLoc DefmPrefixLoc) { + // If the mdef is inside a 'let' expression, add to each def. + for (unsigned i = 0, e = LetStack.size(); i != e; ++i) + for (unsigned j = 0, e = LetStack[i].size(); j != e; ++j) + if (SetValue(CurRec, LetStack[i][j].Loc, LetStack[i][j].Name, + LetStack[i][j].Bits, LetStack[i][j].Value)) + return Error(DefmPrefixLoc, "when instantiating this defm"); + + // Ensure redefinition doesn't happen. + if (Records.getDef(CurRec->getName())) + return Error(DefmPrefixLoc, "def '" + CurRec->getName() + + "' already defined, instantiating defm with subdef '" + + DefProto->getName() + "'"); + + // Don't create a top level definition for defm inside multiclasses, + // instead, only update the prototypes and bind the template args + // with the new created definition. + if (CurMultiClass) { + for (unsigned i = 0, e = CurMultiClass->DefPrototypes.size(); + i != e; ++i) + if (CurMultiClass->DefPrototypes[i]->getName() == CurRec->getName()) + return Error(DefmPrefixLoc, "defm '" + CurRec->getName() + + "' already defined in this multiclass!"); + CurMultiClass->DefPrototypes.push_back(CurRec); + + // Copy the template arguments for the multiclass into the new def. + const std::vector &TA = + CurMultiClass->Rec.getTemplateArgs(); + + for (unsigned i = 0, e = TA.size(); i != e; ++i) { + const RecordVal *RV = CurMultiClass->Rec.getValue(TA[i]); + assert(RV && "Template arg doesn't exist?"); + CurRec->addValue(*RV); + } + } else { + Records.addDef(CurRec); + } + + return false; +} + /// ParseDefm - Parse the instantiation of a multiclass. /// /// DefMInst ::= DEFM ID ':' DefmSubClassRef ';' @@ -1960,99 +2079,19 @@ bool TGParser::ParseDefm(MultiClass *CurMultiClass) { for (unsigned i = 0, e = MC->DefPrototypes.size(); i != e; ++i) { Record *DefProto = MC->DefPrototypes[i]; - // Add in the defm name. If the defm prefix is empty, give each - // instantiated def a unique name. Otherwise, if "#NAME#" exists in the - // name, substitute the prefix for #NAME#. Otherwise, use the defm name - // as a prefix. - std::string DefName = DefProto->getName(); - if (DefmPrefix.empty()) { - DefName = GetNewAnonymousName(); - } else { - std::string::size_type idx = DefName.find("#NAME#"); - if (idx != std::string::npos) { - DefName.replace(idx, 6, DefmPrefix); - } else { - // Add the suffix to the defm name to get the new name. - DefName = DefmPrefix + DefName; - } - } + Record *CurRec = InstantiateMulticlassDef(*MC, DefProto, DefmPrefix, DefmPrefixLoc); - Record *CurRec = new Record(DefName, DefmPrefixLoc, Records); - - SubClassReference Ref; - Ref.RefLoc = DefmPrefixLoc; - Ref.Rec = DefProto; - AddSubClass(CurRec, Ref); - - // Loop over all of the template arguments, setting them to the specified - // value or leaving them as the default if necessary. - for (unsigned i = 0, e = TArgs.size(); i != e; ++i) { - // Check if a value is specified for this temp-arg. - if (i < TemplateVals.size()) { - // Set it now. - if (SetValue(CurRec, DefmPrefixLoc, TArgs[i], std::vector(), - TemplateVals[i])) - return true; + if (ResolveMulticlassDefArgs(*MC, CurRec, DefmPrefixLoc, SubClassLoc, + TArgs, TemplateVals, true/*Delete args*/)) + return Error(SubClassLoc, "could not instantiate def"); - // Resolve it next. - CurRec->resolveReferencesTo(CurRec->getValue(TArgs[i])); - - // Now remove it. - CurRec->removeValue(TArgs[i]); - - } else if (!CurRec->getValue(TArgs[i])->getValue()->isComplete()) { - return Error(SubClassLoc, - "value not specified for template argument #"+ - utostr(i) + " (" + TArgs[i] + ") of multiclassclass '" + - MC->Rec.getName() + "'"); - } - } - - // If the mdef is inside a 'let' expression, add to each def. - for (unsigned i = 0, e = LetStack.size(); i != e; ++i) - for (unsigned j = 0, e = LetStack[i].size(); j != e; ++j) - if (SetValue(CurRec, LetStack[i][j].Loc, LetStack[i][j].Name, - LetStack[i][j].Bits, LetStack[i][j].Value)) { - Error(DefmPrefixLoc, "when instantiating this defm"); - return true; - } - - // Ensure redefinition doesn't happen. - if (Records.getDef(CurRec->getName())) - return Error(DefmPrefixLoc, "def '" + CurRec->getName() + - "' already defined, instantiating defm with subdef '" + - DefProto->getName() + "'"); - - // Don't create a top level definition for defm inside multiclasses, - // instead, only update the prototypes and bind the template args - // with the new created definition. - if (CurMultiClass) { - for (unsigned i = 0, e = CurMultiClass->DefPrototypes.size(); - i != e; ++i) { - if (CurMultiClass->DefPrototypes[i]->getName() == CurRec->getName()) { - Error(DefmPrefixLoc, "defm '" + CurRec->getName() + - "' already defined in this multiclass!"); - return 0; - } - } - CurMultiClass->DefPrototypes.push_back(CurRec); - - // Copy the template arguments for the multiclass into the new def. - const std::vector &TA = - CurMultiClass->Rec.getTemplateArgs(); - - for (unsigned i = 0, e = TA.size(); i != e; ++i) { - const RecordVal *RV = CurMultiClass->Rec.getValue(TA[i]); - assert(RV && "Template arg doesn't exist?"); - CurRec->addValue(*RV); - } - } else { - Records.addDef(CurRec); - } + if (ResolveMulticlassDef(*MC, CurRec, DefProto, DefmPrefixLoc)) + return Error(SubClassLoc, "could not instantiate def"); NewRecDefs.push_back(CurRec); } + if (Lex.getCode() != tgtok::comma) break; Lex.Lex(); // eat ','. @@ -2101,6 +2140,9 @@ bool TGParser::ParseDefm(MultiClass *CurMultiClass) { if (!CurMultiClass) for (unsigned i = 0, e = NewRecDefs.size(); i != e; ++i) + // See Record::setName(). This resolve step will see any new + // name for the def that might have been created when resolving + // inheritance, values and arguments above. NewRecDefs[i]->resolveReferences(); if (Lex.getCode() != tgtok::semi) diff --git a/contrib/llvm/utils/TableGen/TGParser.h b/contrib/llvm/lib/TableGen/TGParser.h similarity index 82% rename from contrib/llvm/utils/TableGen/TGParser.h rename to contrib/llvm/lib/TableGen/TGParser.h index dce7e1dec..db8a62029 100644 --- a/contrib/llvm/utils/TableGen/TGParser.h +++ b/contrib/llvm/lib/TableGen/TGParser.h @@ -15,7 +15,7 @@ #define TGPARSER_H #include "TGLexer.h" -#include "Error.h" +#include "llvm/TableGen/Error.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/SourceMgr.h" #include @@ -24,7 +24,7 @@ namespace llvm { class Record; class RecordVal; class RecordKeeper; - struct RecTy; + class RecTy; class Init; struct MultiClass; struct SubClassReference; @@ -83,6 +83,21 @@ private: // Parser methods. bool ParseObject(MultiClass *MC); bool ParseClass(); bool ParseMultiClass(); + Record *InstantiateMulticlassDef(MultiClass &MC, + Record *DefProto, + const std::string &DefmPrefix, + SMLoc DefmPrefixLoc); + bool ResolveMulticlassDefArgs(MultiClass &MC, + Record *DefProto, + SMLoc DefmPrefixLoc, + SMLoc SubClassLoc, + const std::vector &TArgs, + std::vector &TemplateVals, + bool DeleteArgs); + bool ResolveMulticlassDef(MultiClass &MC, + Record *CurRec, + Record *DefProto, + SMLoc DefmPrefixLoc); bool ParseDefm(MultiClass *CurMultiClass); bool ParseDef(MultiClass *CurMultiClass); bool ParseTopLevelLet(MultiClass *CurMultiClass); diff --git a/contrib/llvm/utils/TableGen/TableGenBackend.cpp b/contrib/llvm/lib/TableGen/TableGenBackend.cpp similarity index 92% rename from contrib/llvm/utils/TableGen/TableGenBackend.cpp rename to contrib/llvm/lib/TableGen/TableGenBackend.cpp index b3e33b5f9..29588db32 100644 --- a/contrib/llvm/utils/TableGen/TableGenBackend.cpp +++ b/contrib/llvm/lib/TableGen/TableGenBackend.cpp @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#include "TableGenBackend.h" -#include "Record.h" +#include "llvm/TableGen/TableGenBackend.h" +#include "llvm/TableGen/Record.h" using namespace llvm; void TableGenBackend::EmitSourceFileHeader(const std::string &Desc, diff --git a/contrib/llvm/lib/Target/ARM/ARM.h b/contrib/llvm/lib/Target/ARM/ARM.h index 08dc340f8..16d0da3b8 100644 --- a/contrib/llvm/lib/Target/ARM/ARM.h +++ b/contrib/llvm/lib/Target/ARM/ARM.h @@ -15,7 +15,7 @@ #ifndef TARGET_ARM_H #define TARGET_ARM_H -#include "ARMBaseInfo.h" +#include "MCTargetDesc/ARMBaseInfo.h" #include "MCTargetDesc/ARMMCTargetDesc.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/ErrorHandling.h" @@ -29,19 +29,7 @@ class ARMBaseTargetMachine; class FunctionPass; class JITCodeEmitter; class MachineInstr; -class MCCodeEmitter; class MCInst; -class MCInstrInfo; -class MCObjectWriter; -class MCSubtargetInfo; -class TargetAsmBackend; -class formatted_raw_ostream; - -MCCodeEmitter *createARMMCCodeEmitter(const MCInstrInfo &MCII, - const MCSubtargetInfo &STI, - MCContext &Ctx); - -TargetAsmBackend *createARMAsmBackend(const Target &, const std::string &); FunctionPass *createARMISelDag(ARMBaseTargetMachine &TM, CodeGenOpt::Level OptLevel); @@ -53,7 +41,6 @@ FunctionPass *createARMLoadStoreOptimizationPass(bool PreAlloc = false); FunctionPass *createARMExpandPseudoPass(); FunctionPass *createARMGlobalMergePass(const TargetLowering* tli); FunctionPass *createARMConstantIslandPass(); -FunctionPass *createNEONMoveFixPass(); FunctionPass *createMLxExpansionPass(); FunctionPass *createThumb2ITBlockPass(); FunctionPass *createThumb2SizeReductionPass(); @@ -61,12 +48,6 @@ FunctionPass *createThumb2SizeReductionPass(); void LowerARMMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI, ARMAsmPrinter &AP); -/// createARMMachObjectWriter - Construct an ARM Mach-O object writer. -MCObjectWriter *createARMMachObjectWriter(raw_ostream &OS, - bool Is64Bit, - uint32_t CPUType, - uint32_t CPUSubtype); - } // end namespace llvm; #endif diff --git a/contrib/llvm/lib/Target/ARM/ARM.td b/contrib/llvm/lib/Target/ARM/ARM.td index cf333ccd4..5c727ad6e 100644 --- a/contrib/llvm/lib/Target/ARM/ARM.td +++ b/contrib/llvm/lib/Target/ARM/ARM.td @@ -23,6 +23,9 @@ include "llvm/Target/Target.td" def ModeThumb : SubtargetFeature<"thumb-mode", "InThumbMode", "true", "Thumb mode">; +def ModeNaCl : SubtargetFeature<"nacl-mode", "InNaClMode", "true", + "Native client mode">; + //===----------------------------------------------------------------------===// // ARM Subtarget features. // @@ -85,12 +88,16 @@ def FeatureAvoidPartialCPSR : SubtargetFeature<"avoid-partial-cpsr", /// Some M architectures don't have the DSP extension (v7E-M vs. v7M) def FeatureDSPThumb2 : SubtargetFeature<"t2dsp", "Thumb2DSP", "true", - "Supports v7 DSP instructions in Thumb2.">; + "Supports v7 DSP instructions in Thumb2">; // Multiprocessing extension. def FeatureMP : SubtargetFeature<"mp", "HasMPExtension", "true", "Supports Multiprocessing extension">; +// M-series ISA? +def FeatureMClass : SubtargetFeature<"mclass", "IsMClass", "true", + "Is microcontroller profile ('M' series)">; + // ARM ISAs. def HasV4TOps : SubtargetFeature<"v4t", "HasV4TOps", "true", "Support ARM v4T instructions">; @@ -105,7 +112,7 @@ def HasV6Ops : SubtargetFeature<"v6", "HasV6Ops", "true", [HasV5TEOps]>; def HasV6T2Ops : SubtargetFeature<"v6t2", "HasV6T2Ops", "true", "Support ARM v6t2 instructions", - [HasV6Ops, FeatureThumb2, FeatureDSPThumb2]>; + [HasV6Ops, FeatureThumb2]>; def HasV7Ops : SubtargetFeature<"v7", "HasV7Ops", "true", "Support ARM v7 instructions", [HasV6T2Ops]>; @@ -182,12 +189,14 @@ def : Processor<"mpcore", ARMV6Itineraries, [HasV6Ops, FeatureVFP2, // V6M Processors. def : Processor<"cortex-m0", ARMV6Itineraries, [HasV6Ops, FeatureNoARM, - FeatureDB]>; + FeatureDB, FeatureMClass]>; // V6T2 Processors. -def : Processor<"arm1156t2-s", ARMV6Itineraries, [HasV6T2Ops]>; +def : Processor<"arm1156t2-s", ARMV6Itineraries, [HasV6T2Ops, + FeatureDSPThumb2]>; def : Processor<"arm1156t2f-s", ARMV6Itineraries, [HasV6T2Ops, FeatureVFP2, - FeatureHasSlowFPVMLx]>; + FeatureHasSlowFPVMLx, + FeatureDSPThumb2]>; // V7a Processors. def : Processor<"cortex-a8", CortexA8Itineraries, @@ -203,14 +212,14 @@ def : Processor<"cortex-a9-mp", CortexA9Itineraries, // V7M Processors. def : ProcNoItin<"cortex-m3", [HasV7Ops, FeatureThumb2, FeatureNoARM, FeatureDB, - FeatureHWDiv]>; + FeatureHWDiv, FeatureMClass]>; // V7EM Processors. def : ProcNoItin<"cortex-m4", [HasV7Ops, FeatureThumb2, FeatureNoARM, FeatureDB, FeatureHWDiv, FeatureDSPThumb2, FeatureT2XtPk, FeatureVFP2, - FeatureVFPOnlySP]>; + FeatureVFPOnlySP, FeatureMClass]>; //===----------------------------------------------------------------------===// // Register File Description diff --git a/contrib/llvm/lib/Target/ARM/ARMAsmPrinter.cpp b/contrib/llvm/lib/Target/ARM/ARMAsmPrinter.cpp index dbc3ee41f..ea3319fb0 100644 --- a/contrib/llvm/lib/Target/ARM/ARMAsmPrinter.cpp +++ b/contrib/llvm/lib/Target/ARM/ARMAsmPrinter.cpp @@ -15,15 +15,15 @@ #define DEBUG_TYPE "asm-printer" #include "ARM.h" #include "ARMAsmPrinter.h" -#include "ARMAddressingModes.h" #include "ARMBuildAttrs.h" #include "ARMBaseRegisterInfo.h" #include "ARMConstantPoolValue.h" #include "ARMMachineFunctionInfo.h" -#include "ARMMCExpr.h" #include "ARMTargetMachine.h" #include "ARMTargetObjectFile.h" #include "InstPrinter/ARMInstPrinter.h" +#include "MCTargetDesc/ARMAddressingModes.h" +#include "MCTargetDesc/ARMMCExpr.h" #include "llvm/Analysis/DebugInfo.h" #include "llvm/Constants.h" #include "llvm/Module.h" @@ -45,13 +45,13 @@ #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" -#include "llvm/Target/TargetRegistry.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/TargetRegistry.h" #include "llvm/Support/raw_ostream.h" #include using namespace llvm; @@ -92,7 +92,7 @@ namespace { case ARMBuildAttrs::Advanced_SIMD_arch: case ARMBuildAttrs::VFP_arch: Streamer.EmitRawText(StringRef("\t.fpu ") + LowercaseString(String)); - break; + break; default: assert(0 && "Unsupported Text attribute in ASM Mode"); break; } } @@ -100,13 +100,41 @@ namespace { }; class ObjectAttributeEmitter : public AttributeEmitter { + // This structure holds all attributes, accounting for + // their string/numeric value, so we can later emmit them + // in declaration order, keeping all in the same vector + struct AttributeItemType { + enum { + HiddenAttribute = 0, + NumericAttribute, + TextAttribute + } Type; + unsigned Tag; + unsigned IntValue; + StringRef StringValue; + } AttributeItem; + MCObjectStreamer &Streamer; StringRef CurrentVendor; - SmallString<64> Contents; + SmallVector Contents; + + // Account for the ULEB/String size of each item, + // not just the number of items + size_t ContentsSize; + // FIXME: this should be in a more generic place, but + // getULEBSize() is in MCAsmInfo and will be moved to MCDwarf + size_t getULEBSize(int Value) { + size_t Size = 0; + do { + Value >>= 7; + Size += sizeof(int8_t); // Is this really necessary? + } while (Value); + return Size; + } public: ObjectAttributeEmitter(MCObjectStreamer &Streamer_) : - Streamer(Streamer_), CurrentVendor("") { } + Streamer(Streamer_), CurrentVendor(""), ContentsSize(0) { } void MaybeSwitchVendor(StringRef Vendor) { assert(!Vendor.empty() && "Vendor cannot be empty."); @@ -124,20 +152,32 @@ namespace { } void EmitAttribute(unsigned Attribute, unsigned Value) { - // FIXME: should be ULEB - Contents += Attribute; - Contents += Value; + AttributeItemType attr = { + AttributeItemType::NumericAttribute, + Attribute, + Value, + StringRef("") + }; + ContentsSize += getULEBSize(Attribute); + ContentsSize += getULEBSize(Value); + Contents.push_back(attr); } void EmitTextAttribute(unsigned Attribute, StringRef String) { - Contents += Attribute; - Contents += UppercaseString(String); - Contents += 0; + AttributeItemType attr = { + AttributeItemType::TextAttribute, + Attribute, + 0, + String + }; + ContentsSize += getULEBSize(Attribute); + // String + \0 + ContentsSize += String.size()+1; + + Contents.push_back(attr); } void Finish() { - const size_t ContentsSize = Contents.size(); - // Vendor size + Vendor name + '\0' const size_t VendorHeaderSize = 4 + CurrentVendor.size() + 1; @@ -151,7 +191,23 @@ namespace { Streamer.EmitIntValue(ARMBuildAttrs::File, 1); Streamer.EmitIntValue(TagHeaderSize + ContentsSize, 4); - Streamer.EmitBytes(Contents, 0); + // Size should have been accounted for already, now + // emit each field as its type (ULEB or String) + for (unsigned int i=0; i>1)) DW_OP_bit_piece(32, 0) // S[2x+1] = DW_OP_regx(256 + (x>>1)) DW_OP_bit_piece(32, 32) - + unsigned SReg = Reg - ARM::S0; bool odd = SReg & 0x1; unsigned Rx = 256 + (SReg >> 1); @@ -209,12 +265,13 @@ void ARMAsmPrinter::EmitDwarfRegOp(const MachineLocation &MLoc) const { } else if (Reg >= ARM::Q0 && Reg <= ARM::Q15) { assert(ARM::Q0 + 15 == ARM::Q15 && "Unexpected ARM Q register numbering"); // Q registers Q0-Q15 are described by composing two D registers together. - // Qx = DW_OP_regx(256+2x) DW_OP_piece(8) DW_OP_regx(256+2x+1) DW_OP_piece(8) + // Qx = DW_OP_regx(256+2x) DW_OP_piece(8) DW_OP_regx(256+2x+1) + // DW_OP_piece(8) unsigned QReg = Reg - ARM::Q0; unsigned D1 = 256 + 2 * QReg; unsigned D2 = D1 + 1; - + OutStreamer.AddComment("DW_OP_regx for Q register: D1"); EmitInt8(dwarf::DW_OP_regx); EmitULEB128(D1); @@ -233,6 +290,8 @@ void ARMAsmPrinter::EmitDwarfRegOp(const MachineLocation &MLoc) const { } void ARMAsmPrinter::EmitFunctionEntryLabel() { + OutStreamer.ForceCodeRegion(); + if (AFI->isThumbFunction()) { OutStreamer.EmitAssemblerFlag(MCAF_Code16); OutStreamer.EmitThumbFunc(CurrentFnSym); @@ -395,16 +454,16 @@ bool ARMAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum, // This takes advantage of the 2 operand-ness of ldm/stm and that we've // already got the operands in registers that are operands to the // inline asm statement. - + O << "{" << ARMInstPrinter::getRegisterName(RegBegin); - + // FIXME: The register allocator not only may not have given us the // registers in sequence, but may not be in ascending registers. This // will require changes in the register allocator that'll need to be // propagated down here if the operands change. unsigned RegOps = OpNum + 1; while (MI->getOperand(RegOps).isReg()) { - O << ", " + O << ", " << ARMInstPrinter::getRegisterName(MI->getOperand(RegOps).getReg()); RegOps++; } @@ -413,14 +472,34 @@ bool ARMAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum, return false; } + case 'R': // The most significant register of a pair. + case 'Q': { // The least significant register of a pair. + if (OpNum == 0) + return true; + const MachineOperand &FlagsOP = MI->getOperand(OpNum - 1); + if (!FlagsOP.isImm()) + return true; + unsigned Flags = FlagsOP.getImm(); + unsigned NumVals = InlineAsm::getNumOperandRegisters(Flags); + if (NumVals != 2) + return true; + unsigned RegOp = ExtraCode[0] == 'Q' ? OpNum : OpNum + 1; + if (RegOp >= MI->getNumOperands()) + return true; + const MachineOperand &MO = MI->getOperand(RegOp); + if (!MO.isReg()) + return true; + unsigned Reg = MO.getReg(); + O << ARMInstPrinter::getRegisterName(Reg); + return false; + } + // These modifiers are not yet supported. case 'p': // The high single-precision register of a VFP double-precision // register. case 'e': // The low doubleword register of a NEON quad register. case 'f': // The high doubleword register of a NEON quad register. case 'h': // A range of VFP/NEON registers suitable for VLD1/VST1. - case 'Q': // The least significant register of a pair. - case 'R': // The most significant register of a pair. case 'H': // The highest-numbered register of a pair. return true; } @@ -437,7 +516,7 @@ bool ARMAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, // Does this asm operand have a single letter operand modifier? if (ExtraCode && ExtraCode[0]) { if (ExtraCode[1] != 0) return true; // Unknown modifier. - + switch (ExtraCode[0]) { case 'A': // A memory operand for a VLD1/VST1 instruction. default: return true; // Unknown modifier. @@ -448,7 +527,7 @@ bool ARMAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, return false; } } - + const MachineOperand &MO = MI->getOperand(OpNum); assert(MO.isReg() && "unexpected inline asm memory operand"); O << "[" << ARMInstPrinter::getRegisterName(MO.getReg()) << "]"; @@ -772,13 +851,19 @@ EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) { OS << MAI->getPrivateGlobalPrefix() << "_LSDA_" << getFunctionNumber(); MCSym = OutContext.GetOrCreateSymbol(OS.str()); } else if (ACPV->isBlockAddress()) { - MCSym = GetBlockAddressSymbol(ACPV->getBlockAddress()); + const BlockAddress *BA = + cast(ACPV)->getBlockAddress(); + MCSym = GetBlockAddressSymbol(BA); } else if (ACPV->isGlobalValue()) { - const GlobalValue *GV = ACPV->getGV(); + const GlobalValue *GV = cast(ACPV)->getGV(); MCSym = GetARMGVSymbol(GV); + } else if (ACPV->isMachineBasicBlock()) { + const MachineBasicBlock *MBB = cast(ACPV)->getMBB(); + MCSym = MBB->getSymbol(); } else { assert(ACPV->isExtSymbol() && "unrecognized constant pool value"); - MCSym = GetExternalSymbolSymbol(ACPV->getSymbol()); + const char *Sym = cast(ACPV)->getSymbol(); + MCSym = GetExternalSymbolSymbol(Sym); } // Create an MCSymbol for the reference. @@ -822,6 +907,9 @@ void ARMAsmPrinter::EmitJumpTable(const MachineInstr *MI) { const MachineOperand &MO2 = MI->getOperand(OpNum+1); // Unique Id unsigned JTI = MO1.getIndex(); + // Tag the jump table appropriately for precise disassembly. + OutStreamer.EmitJumpTable32Region(); + // Emit a label for the jump table. MCSymbol *JTISymbol = GetARMJTIPICJumpTableLabel2(JTI, MO2.getImm()); OutStreamer.EmitLabel(JTISymbol); @@ -847,6 +935,11 @@ void ARMAsmPrinter::EmitJumpTable(const MachineInstr *MI) { Expr = MCBinaryExpr::CreateSub(Expr, MCSymbolRefExpr::Create(JTISymbol, OutContext), OutContext); + // If we're generating a table of Thumb addresses in static relocation + // model, we need to add one to keep interworking correctly. + else if (AFI->isThumbFunction()) + Expr = MCBinaryExpr::CreateAdd(Expr, MCConstantExpr::Create(1,OutContext), + OutContext); OutStreamer.EmitValue(Expr, 4); } } @@ -859,6 +952,14 @@ void ARMAsmPrinter::EmitJump2Table(const MachineInstr *MI) { unsigned JTI = MO1.getIndex(); // Emit a label for the jump table. + if (MI->getOpcode() == ARM::t2TBB_JT) { + OutStreamer.EmitJumpTable8Region(); + } else if (MI->getOpcode() == ARM::t2TBH_JT) { + OutStreamer.EmitJumpTable16Region(); + } else { + OutStreamer.EmitJumpTable32Region(); + } + MCSymbol *JTISymbol = GetARMJTIPICJumpTableLabel2(JTI, MO2.getImm()); OutStreamer.EmitLabel(JTISymbol); @@ -881,6 +982,8 @@ void ARMAsmPrinter::EmitJump2Table(const MachineInstr *MI) { MCInst BrInst; BrInst.setOpcode(ARM::t2B); BrInst.addOperand(MCOperand::CreateExpr(MBBSymbolExpr)); + BrInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); + BrInst.addOperand(MCOperand::CreateReg(0)); OutStreamer.EmitInstruction(BrInst); continue; } @@ -994,7 +1097,8 @@ void ARMAsmPrinter::EmitUnwindingInstruction(const MachineInstr *MI) { i != NumOps; ++i) RegList.push_back(MI->getOperand(i).getReg()); break; - case ARM::STR_PRE: + case ARM::STR_PRE_IMM: + case ARM::STR_PRE_REG: assert(MI->getOperand(2).getReg() == ARM::SP && "Only stack pointer as a source reg is supported"); RegList.push_back(SrcReg); @@ -1074,10 +1178,20 @@ extern cl::opt EnableARMEHABI; #include "ARMGenMCPseudoLowering.inc" void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) { + if (MI->getOpcode() != ARM::CONSTPOOL_ENTRY) + OutStreamer.EmitCodeRegion(); + + // Emit unwinding stuff for frame-related instructions + if (EnableARMEHABI && MI->getFlag(MachineInstr::FrameSetup)) + EmitUnwindingInstruction(MI); + // Do any auto-generated pseudo lowerings. if (emitPseudoExpansionLowering(OutStreamer, MI)) return; + assert(!convertAddSubFlagsOpcode(MI->getOpcode()) && + "Pseudo flag setting opcode should be expanded early"); + // Check for manual lowerings. unsigned Opc = MI->getOpcode(); switch (Opc) { @@ -1372,6 +1486,10 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) { unsigned CPIdx = (unsigned)MI->getOperand(1).getIndex(); EmitAlignment(2); + + // Mark the constant pool entry as data if we're not already in a data + // region. + OutStreamer.EmitDataRegion(); OutStreamer.EmitLabel(GetCPISymbol(LabelId)); const MachineConstantPoolEntry &MCPE = MCP->getConstants()[CPIdx]; @@ -1379,7 +1497,6 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) { EmitMachineConstantPoolValue(MCPE.Val.MachineCPVal); else EmitGlobalConstant(MCPE.Val.ConstVal); - return; } case ARM::t2BR_JT: { @@ -1590,6 +1707,8 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) { MCInst TmpInst; TmpInst.setOpcode(ARM::tB); TmpInst.addOperand(MCOperand::CreateExpr(SymbolExpr)); + TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); + TmpInst.addOperand(MCOperand::CreateReg(0)); OutStreamer.EmitInstruction(TmpInst); } { @@ -1804,10 +1923,6 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) { MCInst TmpInst; LowerARMMachineInstrToMCInst(MI, TmpInst, *this); - // Emit unwinding stuff for frame-related instructions - if (EnableARMEHABI && MI->getFlag(MachineInstr::FrameSetup)) - EmitUnwindingInstruction(MI); - OutStreamer.EmitInstruction(TmpInst); } @@ -1815,20 +1930,9 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) { // Target Registry Stuff //===----------------------------------------------------------------------===// -static MCInstPrinter *createARMMCInstPrinter(const Target &T, - unsigned SyntaxVariant, - const MCAsmInfo &MAI) { - if (SyntaxVariant == 0) - return new ARMInstPrinter(MAI); - return 0; -} - // Force static initialization. extern "C" void LLVMInitializeARMAsmPrinter() { RegisterAsmPrinter X(TheARMTarget); RegisterAsmPrinter Y(TheThumbTarget); - - TargetRegistry::RegisterMCInstPrinter(TheARMTarget, createARMMCInstPrinter); - TargetRegistry::RegisterMCInstPrinter(TheThumbTarget, createARMMCInstPrinter); } diff --git a/contrib/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp b/contrib/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp index 649bd7d5c..408edfc20 100644 --- a/contrib/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp +++ b/contrib/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp @@ -13,11 +13,11 @@ #include "ARMBaseInstrInfo.h" #include "ARM.h" -#include "ARMAddressingModes.h" #include "ARMConstantPoolValue.h" #include "ARMHazardRecognizer.h" #include "ARMMachineFunctionInfo.h" #include "ARMRegisterInfo.h" +#include "MCTargetDesc/ARMAddressingModes.h" #include "llvm/Constants.h" #include "llvm/Function.h" #include "llvm/GlobalValue.h" @@ -29,6 +29,7 @@ #include "llvm/CodeGen/MachineMemOperand.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/PseudoSourceValue.h" +#include "llvm/CodeGen/SelectionDAGNodes.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/Support/BranchProbability.h" #include "llvm/Support/CommandLine.h" @@ -45,6 +46,10 @@ static cl::opt EnableARM3Addr("enable-arm-3-addr-conv", cl::Hidden, cl::desc("Enable ARM 2-addr to 3-addr conv")); +static cl::opt +WidenVMOVS("widen-vmovs", cl::Hidden, + cl::desc("Widen ARM vmovs to vmovd when possible")); + /// ARM_MLxEntry - Record information about MLA / MLS instructions. struct ARM_MLxEntry { unsigned MLxOpc; // MLA / MLS opcode @@ -171,7 +176,7 @@ ARMBaseInstrInfo::convertToThreeAddress(MachineFunction::iterator &MFI, ARM_AM::ShiftOpc ShOpc = ARM_AM::getAM2ShiftOpc(OffImm); unsigned SOOpc = ARM_AM::getSORegOpc(ShOpc, Amt); UpdateMI = BuildMI(MF, MI->getDebugLoc(), - get(isSub ? ARM::SUBrs : ARM::ADDrs), WBReg) + get(isSub ? ARM::SUBrsi : ARM::ADDrsi), WBReg) .addReg(BaseReg).addReg(OffReg).addReg(0).addImm(SOOpc) .addImm(Pred).addReg(0).addReg(0); } else @@ -399,6 +404,7 @@ ARMBaseInstrInfo::InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, ? ARM::B : (AFI->isThumb2Function() ? ARM::t2B : ARM::tB); int BccOpc = !AFI->isThumbFunction() ? ARM::Bcc : (AFI->isThumb2Function() ? ARM::t2Bcc : ARM::tBcc); + bool isThumb = AFI->isThumbFunction() || AFI->isThumb2Function(); // Shouldn't be a fall through. assert(TBB && "InsertBranch must not be told to insert a fallthrough"); @@ -406,9 +412,12 @@ ARMBaseInstrInfo::InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, "ARM branch conditions have two components!"); if (FBB == 0) { - if (Cond.empty()) // Unconditional branch? - BuildMI(&MBB, DL, get(BOpc)).addMBB(TBB); - else + if (Cond.empty()) { // Unconditional branch? + if (isThumb) + BuildMI(&MBB, DL, get(BOpc)).addMBB(TBB).addImm(ARMCC::AL).addReg(0); + else + BuildMI(&MBB, DL, get(BOpc)).addMBB(TBB); + } else BuildMI(&MBB, DL, get(BccOpc)).addMBB(TBB) .addImm(Cond[0].getImm()).addReg(Cond[1].getReg()); return 1; @@ -417,7 +426,10 @@ ARMBaseInstrInfo::InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, // Two-way conditional branch. BuildMI(&MBB, DL, get(BccOpc)).addMBB(TBB) .addImm(Cond[0].getImm()).addReg(Cond[1].getReg()); - BuildMI(&MBB, DL, get(BOpc)).addMBB(FBB); + if (isThumb) + BuildMI(&MBB, DL, get(BOpc)).addMBB(FBB).addImm(ARMCC::AL).addReg(0); + else + BuildMI(&MBB, DL, get(BOpc)).addMBB(FBB); return 2; } @@ -627,7 +639,7 @@ void ARMBaseInstrInfo::copyPhysReg(MachineBasicBlock &MBB, bool SPRDest = ARM::SPRRegClass.contains(DestReg); bool SPRSrc = ARM::SPRRegClass.contains(SrcReg); - unsigned Opc; + unsigned Opc = 0; if (SPRDest && SPRSrc) Opc = ARM::VMOVS; else if (GPRDest && SPRSrc) @@ -638,19 +650,40 @@ void ARMBaseInstrInfo::copyPhysReg(MachineBasicBlock &MBB, Opc = ARM::VMOVD; else if (ARM::QPRRegClass.contains(DestReg, SrcReg)) Opc = ARM::VORRq; - else if (ARM::QQPRRegClass.contains(DestReg, SrcReg)) - Opc = ARM::VMOVQQ; - else if (ARM::QQQQPRRegClass.contains(DestReg, SrcReg)) - Opc = ARM::VMOVQQQQ; - else - llvm_unreachable("Impossible reg-to-reg copy"); - MachineInstrBuilder MIB = BuildMI(MBB, I, DL, get(Opc), DestReg); - MIB.addReg(SrcReg, getKillRegState(KillSrc)); - if (Opc == ARM::VORRq) + if (Opc) { + MachineInstrBuilder MIB = BuildMI(MBB, I, DL, get(Opc), DestReg); MIB.addReg(SrcReg, getKillRegState(KillSrc)); - if (Opc != ARM::VMOVQQ && Opc != ARM::VMOVQQQQ) + if (Opc == ARM::VORRq) + MIB.addReg(SrcReg, getKillRegState(KillSrc)); AddDefaultPred(MIB); + return; + } + + // Generate instructions for VMOVQQ and VMOVQQQQ pseudos in place. + if (ARM::QQPRRegClass.contains(DestReg, SrcReg) || + ARM::QQQQPRRegClass.contains(DestReg, SrcReg)) { + const TargetRegisterInfo *TRI = &getRegisterInfo(); + assert(ARM::qsub_0 + 3 == ARM::qsub_3 && "Expected contiguous enum."); + unsigned EndSubReg = ARM::QQPRRegClass.contains(DestReg, SrcReg) ? + ARM::qsub_1 : ARM::qsub_3; + for (unsigned i = ARM::qsub_0, e = EndSubReg + 1; i != e; ++i) { + unsigned Dst = TRI->getSubReg(DestReg, i); + unsigned Src = TRI->getSubReg(SrcReg, i); + MachineInstrBuilder Mov = + AddDefaultPred(BuildMI(MBB, I, I->getDebugLoc(), get(ARM::VORRq)) + .addReg(Dst, RegState::Define) + .addReg(Src, getKillRegState(KillSrc)) + .addReg(Src, getKillRegState(KillSrc))); + if (i == EndSubReg) { + Mov->addRegisterDefined(DestReg, TRI); + if (KillSrc) + Mov->addRegisterKilled(SrcReg, TRI); + } + } + return; + } + llvm_unreachable("Impossible reg-to-reg copy"); } static const @@ -683,82 +716,84 @@ storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, MFI.getObjectSize(FI), Align); - // tGPR is used sometimes in ARM instructions that need to avoid using - // certain registers. Just treat it as GPR here. Likewise, rGPR. - if (RC == ARM::tGPRRegisterClass || RC == ARM::tcGPRRegisterClass - || RC == ARM::rGPRRegisterClass) - RC = ARM::GPRRegisterClass; - - switch (RC->getID()) { - case ARM::GPRRegClassID: - AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::STRi12)) + switch (RC->getSize()) { + case 4: + if (ARM::GPRRegClass.hasSubClassEq(RC)) { + AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::STRi12)) .addReg(SrcReg, getKillRegState(isKill)) .addFrameIndex(FI).addImm(0).addMemOperand(MMO)); - break; - case ARM::SPRRegClassID: - AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VSTRS)) + } else if (ARM::SPRRegClass.hasSubClassEq(RC)) { + AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VSTRS)) .addReg(SrcReg, getKillRegState(isKill)) .addFrameIndex(FI).addImm(0).addMemOperand(MMO)); - break; - case ARM::DPRRegClassID: - case ARM::DPR_VFP2RegClassID: - case ARM::DPR_8RegClassID: - AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VSTRD)) + } else + llvm_unreachable("Unknown reg class!"); + break; + case 8: + if (ARM::DPRRegClass.hasSubClassEq(RC)) { + AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VSTRD)) .addReg(SrcReg, getKillRegState(isKill)) .addFrameIndex(FI).addImm(0).addMemOperand(MMO)); - break; - case ARM::QPRRegClassID: - case ARM::QPR_VFP2RegClassID: - case ARM::QPR_8RegClassID: - if (Align >= 16 && getRegisterInfo().needsStackRealignment(MF)) { - AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VST1q64Pseudo)) + } else + llvm_unreachable("Unknown reg class!"); + break; + case 16: + if (ARM::QPRRegClass.hasSubClassEq(RC)) { + if (Align >= 16 && getRegisterInfo().needsStackRealignment(MF)) { + AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VST1q64Pseudo)) .addFrameIndex(FI).addImm(16) .addReg(SrcReg, getKillRegState(isKill)) .addMemOperand(MMO)); - } else { - AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VSTMQIA)) + } else { + AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VSTMQIA)) .addReg(SrcReg, getKillRegState(isKill)) .addFrameIndex(FI) .addMemOperand(MMO)); - } - break; - case ARM::QQPRRegClassID: - case ARM::QQPR_VFP2RegClassID: - if (Align >= 16 && getRegisterInfo().canRealignStack(MF)) { - // FIXME: It's possible to only store part of the QQ register if the - // spilled def has a sub-register index. - AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VST1d64QPseudo)) + } + } else + llvm_unreachable("Unknown reg class!"); + break; + case 32: + if (ARM::QQPRRegClass.hasSubClassEq(RC)) { + if (Align >= 16 && getRegisterInfo().canRealignStack(MF)) { + // FIXME: It's possible to only store part of the QQ register if the + // spilled def has a sub-register index. + AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VST1d64QPseudo)) .addFrameIndex(FI).addImm(16) .addReg(SrcReg, getKillRegState(isKill)) .addMemOperand(MMO)); - } else { - MachineInstrBuilder MIB = - AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VSTMDIA)) + } else { + MachineInstrBuilder MIB = + AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VSTMDIA)) .addFrameIndex(FI)) - .addMemOperand(MMO); - MIB = AddDReg(MIB, SrcReg, ARM::dsub_0, getKillRegState(isKill), TRI); - MIB = AddDReg(MIB, SrcReg, ARM::dsub_1, 0, TRI); - MIB = AddDReg(MIB, SrcReg, ARM::dsub_2, 0, TRI); - AddDReg(MIB, SrcReg, ARM::dsub_3, 0, TRI); - } - break; - case ARM::QQQQPRRegClassID: { - MachineInstrBuilder MIB = - AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VSTMDIA)) - .addFrameIndex(FI)) - .addMemOperand(MMO); - MIB = AddDReg(MIB, SrcReg, ARM::dsub_0, getKillRegState(isKill), TRI); - MIB = AddDReg(MIB, SrcReg, ARM::dsub_1, 0, TRI); - MIB = AddDReg(MIB, SrcReg, ARM::dsub_2, 0, TRI); - MIB = AddDReg(MIB, SrcReg, ARM::dsub_3, 0, TRI); - MIB = AddDReg(MIB, SrcReg, ARM::dsub_4, 0, TRI); - MIB = AddDReg(MIB, SrcReg, ARM::dsub_5, 0, TRI); - MIB = AddDReg(MIB, SrcReg, ARM::dsub_6, 0, TRI); - AddDReg(MIB, SrcReg, ARM::dsub_7, 0, TRI); - break; - } - default: - llvm_unreachable("Unknown regclass!"); + .addMemOperand(MMO); + MIB = AddDReg(MIB, SrcReg, ARM::dsub_0, getKillRegState(isKill), TRI); + MIB = AddDReg(MIB, SrcReg, ARM::dsub_1, 0, TRI); + MIB = AddDReg(MIB, SrcReg, ARM::dsub_2, 0, TRI); + AddDReg(MIB, SrcReg, ARM::dsub_3, 0, TRI); + } + } else + llvm_unreachable("Unknown reg class!"); + break; + case 64: + if (ARM::QQQQPRRegClass.hasSubClassEq(RC)) { + MachineInstrBuilder MIB = + AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VSTMDIA)) + .addFrameIndex(FI)) + .addMemOperand(MMO); + MIB = AddDReg(MIB, SrcReg, ARM::dsub_0, getKillRegState(isKill), TRI); + MIB = AddDReg(MIB, SrcReg, ARM::dsub_1, 0, TRI); + MIB = AddDReg(MIB, SrcReg, ARM::dsub_2, 0, TRI); + MIB = AddDReg(MIB, SrcReg, ARM::dsub_3, 0, TRI); + MIB = AddDReg(MIB, SrcReg, ARM::dsub_4, 0, TRI); + MIB = AddDReg(MIB, SrcReg, ARM::dsub_5, 0, TRI); + MIB = AddDReg(MIB, SrcReg, ARM::dsub_6, 0, TRI); + AddDReg(MIB, SrcReg, ARM::dsub_7, 0, TRI); + } else + llvm_unreachable("Unknown reg class!"); + break; + default: + llvm_unreachable("Unknown reg class!"); } } @@ -809,6 +844,12 @@ ARMBaseInstrInfo::isStoreToStackSlot(const MachineInstr *MI, return 0; } +unsigned ARMBaseInstrInfo::isStoreToStackSlotPostFE(const MachineInstr *MI, + int &FrameIndex) const { + const MachineMemOperand *Dummy; + return MI->getDesc().mayStore() && hasStoreToStackSlot(MI, Dummy, FrameIndex); +} + void ARMBaseInstrInfo:: loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, unsigned DestReg, int FI, @@ -826,72 +867,77 @@ loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, MFI.getObjectSize(FI), Align); - // tGPR is used sometimes in ARM instructions that need to avoid using - // certain registers. Just treat it as GPR here. - if (RC == ARM::tGPRRegisterClass || RC == ARM::tcGPRRegisterClass - || RC == ARM::rGPRRegisterClass) - RC = ARM::GPRRegisterClass; - - switch (RC->getID()) { - case ARM::GPRRegClassID: - AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::LDRi12), DestReg) + switch (RC->getSize()) { + case 4: + if (ARM::GPRRegClass.hasSubClassEq(RC)) { + AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::LDRi12), DestReg) .addFrameIndex(FI).addImm(0).addMemOperand(MMO)); - break; - case ARM::SPRRegClassID: - AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VLDRS), DestReg) + + } else if (ARM::SPRRegClass.hasSubClassEq(RC)) { + AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VLDRS), DestReg) .addFrameIndex(FI).addImm(0).addMemOperand(MMO)); + } else + llvm_unreachable("Unknown reg class!"); break; - case ARM::DPRRegClassID: - case ARM::DPR_VFP2RegClassID: - case ARM::DPR_8RegClassID: - AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VLDRD), DestReg) + case 8: + if (ARM::DPRRegClass.hasSubClassEq(RC)) { + AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VLDRD), DestReg) .addFrameIndex(FI).addImm(0).addMemOperand(MMO)); + } else + llvm_unreachable("Unknown reg class!"); break; - case ARM::QPRRegClassID: - case ARM::QPR_VFP2RegClassID: - case ARM::QPR_8RegClassID: - if (Align >= 16 && getRegisterInfo().needsStackRealignment(MF)) { - AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VLD1q64Pseudo), DestReg) + case 16: + if (ARM::QPRRegClass.hasSubClassEq(RC)) { + if (Align >= 16 && getRegisterInfo().needsStackRealignment(MF)) { + AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VLD1q64Pseudo), DestReg) .addFrameIndex(FI).addImm(16) .addMemOperand(MMO)); - } else { - AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VLDMQIA), DestReg) - .addFrameIndex(FI) - .addMemOperand(MMO)); - } + } else { + AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VLDMQIA), DestReg) + .addFrameIndex(FI) + .addMemOperand(MMO)); + } + } else + llvm_unreachable("Unknown reg class!"); break; - case ARM::QQPRRegClassID: - case ARM::QQPR_VFP2RegClassID: - if (Align >= 16 && getRegisterInfo().canRealignStack(MF)) { - AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VLD1d64QPseudo), DestReg) + case 32: + if (ARM::QQPRRegClass.hasSubClassEq(RC)) { + if (Align >= 16 && getRegisterInfo().canRealignStack(MF)) { + AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VLD1d64QPseudo), DestReg) .addFrameIndex(FI).addImm(16) .addMemOperand(MMO)); - } else { - MachineInstrBuilder MIB = + } else { + MachineInstrBuilder MIB = AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VLDMDIA)) .addFrameIndex(FI)) - .addMemOperand(MMO); - MIB = AddDReg(MIB, DestReg, ARM::dsub_0, RegState::Define, TRI); - MIB = AddDReg(MIB, DestReg, ARM::dsub_1, RegState::Define, TRI); - MIB = AddDReg(MIB, DestReg, ARM::dsub_2, RegState::Define, TRI); - AddDReg(MIB, DestReg, ARM::dsub_3, RegState::Define, TRI); - } + .addMemOperand(MMO); + MIB = AddDReg(MIB, DestReg, ARM::dsub_0, RegState::Define, TRI); + MIB = AddDReg(MIB, DestReg, ARM::dsub_1, RegState::Define, TRI); + MIB = AddDReg(MIB, DestReg, ARM::dsub_2, RegState::Define, TRI); + MIB = AddDReg(MIB, DestReg, ARM::dsub_3, RegState::Define, TRI); + MIB.addReg(DestReg, RegState::Define | RegState::Implicit); + } + } else + llvm_unreachable("Unknown reg class!"); break; - case ARM::QQQQPRRegClassID: { - MachineInstrBuilder MIB = + case 64: + if (ARM::QQQQPRRegClass.hasSubClassEq(RC)) { + MachineInstrBuilder MIB = AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VLDMDIA)) .addFrameIndex(FI)) - .addMemOperand(MMO); - MIB = AddDReg(MIB, DestReg, ARM::dsub_0, RegState::Define, TRI); - MIB = AddDReg(MIB, DestReg, ARM::dsub_1, RegState::Define, TRI); - MIB = AddDReg(MIB, DestReg, ARM::dsub_2, RegState::Define, TRI); - MIB = AddDReg(MIB, DestReg, ARM::dsub_3, RegState::Define, TRI); - MIB = AddDReg(MIB, DestReg, ARM::dsub_4, RegState::Define, TRI); - MIB = AddDReg(MIB, DestReg, ARM::dsub_5, RegState::Define, TRI); - MIB = AddDReg(MIB, DestReg, ARM::dsub_6, RegState::Define, TRI); - AddDReg(MIB, DestReg, ARM::dsub_7, RegState::Define, TRI); + .addMemOperand(MMO); + MIB = AddDReg(MIB, DestReg, ARM::dsub_0, RegState::Define, TRI); + MIB = AddDReg(MIB, DestReg, ARM::dsub_1, RegState::Define, TRI); + MIB = AddDReg(MIB, DestReg, ARM::dsub_2, RegState::Define, TRI); + MIB = AddDReg(MIB, DestReg, ARM::dsub_3, RegState::Define, TRI); + MIB = AddDReg(MIB, DestReg, ARM::dsub_4, RegState::Define, TRI); + MIB = AddDReg(MIB, DestReg, ARM::dsub_5, RegState::Define, TRI); + MIB = AddDReg(MIB, DestReg, ARM::dsub_6, RegState::Define, TRI); + MIB = AddDReg(MIB, DestReg, ARM::dsub_7, RegState::Define, TRI); + MIB.addReg(DestReg, RegState::Define | RegState::Implicit); + } else + llvm_unreachable("Unknown reg class!"); break; - } default: llvm_unreachable("Unknown regclass!"); } @@ -944,6 +990,78 @@ ARMBaseInstrInfo::isLoadFromStackSlot(const MachineInstr *MI, return 0; } +unsigned ARMBaseInstrInfo::isLoadFromStackSlotPostFE(const MachineInstr *MI, + int &FrameIndex) const { + const MachineMemOperand *Dummy; + return MI->getDesc().mayLoad() && hasLoadFromStackSlot(MI, Dummy, FrameIndex); +} + +bool ARMBaseInstrInfo::expandPostRAPseudo(MachineBasicBlock::iterator MI) const{ + // This hook gets to expand COPY instructions before they become + // copyPhysReg() calls. Look for VMOVS instructions that can legally be + // widened to VMOVD. We prefer the VMOVD when possible because it may be + // changed into a VORR that can go down the NEON pipeline. + if (!WidenVMOVS || !MI->isCopy()) + return false; + + // Look for a copy between even S-registers. That is where we keep floats + // when using NEON v2f32 instructions for f32 arithmetic. + unsigned DstRegS = MI->getOperand(0).getReg(); + unsigned SrcRegS = MI->getOperand(1).getReg(); + if (!ARM::SPRRegClass.contains(DstRegS, SrcRegS)) + return false; + + const TargetRegisterInfo *TRI = &getRegisterInfo(); + unsigned DstRegD = TRI->getMatchingSuperReg(DstRegS, ARM::ssub_0, + &ARM::DPRRegClass); + unsigned SrcRegD = TRI->getMatchingSuperReg(SrcRegS, ARM::ssub_0, + &ARM::DPRRegClass); + if (!DstRegD || !SrcRegD) + return false; + + // We want to widen this into a DstRegD = VMOVD SrcRegD copy. This is only + // legal if the COPY already defines the full DstRegD, and it isn't a + // sub-register insertion. + if (!MI->definesRegister(DstRegD, TRI) || MI->readsRegister(DstRegD, TRI)) + return false; + + // A dead copy shouldn't show up here, but reject it just in case. + if (MI->getOperand(0).isDead()) + return false; + + // All clear, widen the COPY. + DEBUG(dbgs() << "widening: " << *MI); + + // Get rid of the old of DstRegD. Leave it if it defines a Q-reg + // or some other super-register. + int ImpDefIdx = MI->findRegisterDefOperandIdx(DstRegD); + if (ImpDefIdx != -1) + MI->RemoveOperand(ImpDefIdx); + + // Change the opcode and operands. + MI->setDesc(get(ARM::VMOVD)); + MI->getOperand(0).setReg(DstRegD); + MI->getOperand(1).setReg(SrcRegD); + AddDefaultPred(MachineInstrBuilder(MI)); + + // We are now reading SrcRegD instead of SrcRegS. This may upset the + // register scavenger and machine verifier, so we need to indicate that we + // are reading an undefined value from SrcRegD, but a proper value from + // SrcRegS. + MI->getOperand(1).setIsUndef(); + MachineInstrBuilder(MI).addReg(SrcRegS, RegState::Implicit); + + // SrcRegD may actually contain an unrelated value in the ssub_1 + // sub-register. Don't kill it. Only kill the ssub_0 sub-register. + if (MI->getOperand(1).isKill()) { + MI->getOperand(1).setIsKill(false); + MI->addRegisterKilled(SrcRegS, TRI, true); + } + + DEBUG(dbgs() << "replaced by: " << *MI); + return true; +} + MachineInstr* ARMBaseInstrInfo::emitFrameIndexDebugValue(MachineFunction &MF, int FrameIx, uint64_t Offset, @@ -974,17 +1092,24 @@ static unsigned duplicateCPV(MachineFunction &MF, unsigned &CPI) { // instructions, so that's probably OK, but is PIC always correct when // we get here? if (ACPV->isGlobalValue()) - NewCPV = new ARMConstantPoolValue(ACPV->getGV(), PCLabelId, - ARMCP::CPValue, 4); + NewCPV = ARMConstantPoolConstant:: + Create(cast(ACPV)->getGV(), PCLabelId, + ARMCP::CPValue, 4); else if (ACPV->isExtSymbol()) - NewCPV = new ARMConstantPoolValue(MF.getFunction()->getContext(), - ACPV->getSymbol(), PCLabelId, 4); + NewCPV = ARMConstantPoolSymbol:: + Create(MF.getFunction()->getContext(), + cast(ACPV)->getSymbol(), PCLabelId, 4); else if (ACPV->isBlockAddress()) - NewCPV = new ARMConstantPoolValue(ACPV->getBlockAddress(), PCLabelId, - ARMCP::CPBlockAddress, 4); + NewCPV = ARMConstantPoolConstant:: + Create(cast(ACPV)->getBlockAddress(), PCLabelId, + ARMCP::CPBlockAddress, 4); else if (ACPV->isLSDA()) - NewCPV = new ARMConstantPoolValue(MF.getFunction(), PCLabelId, - ARMCP::CPLSDA, 4); + NewCPV = ARMConstantPoolConstant::Create(MF.getFunction(), PCLabelId, + ARMCP::CPLSDA, 4); + else if (ACPV->isMachineBasicBlock()) + NewCPV = ARMConstantPoolMBB:: + Create(MF.getFunction()->getContext(), + cast(ACPV)->getMBB(), PCLabelId, 4); else llvm_unreachable("Unexpected ARM constantpool value type!!"); CPI = MCP->getConstantPoolIndex(NewCPV, MCPE.getAlignment()); @@ -1289,7 +1414,7 @@ isProfitableToIfCvt(MachineBasicBlock &TMBB, // Attempt to estimate the relative costs of predication versus branching. unsigned TUnpredCost = Probability.getNumerator() * TCycles; TUnpredCost /= Probability.getDenominator(); - + uint32_t Comp = Probability.getDenominator() - Probability.getNumerator(); unsigned FUnpredCost = Comp * FCycles; FUnpredCost /= Probability.getDenominator(); @@ -1330,6 +1455,57 @@ int llvm::getMatchingCondBranchOpcode(int Opc) { } +/// Map pseudo instructions that imply an 'S' bit onto real opcodes. Whether the +/// instruction is encoded with an 'S' bit is determined by the optional CPSR +/// def operand. +/// +/// This will go away once we can teach tblgen how to set the optional CPSR def +/// operand itself. +struct AddSubFlagsOpcodePair { + unsigned PseudoOpc; + unsigned MachineOpc; +}; + +static AddSubFlagsOpcodePair AddSubFlagsOpcodeMap[] = { + {ARM::ADDSri, ARM::ADDri}, + {ARM::ADDSrr, ARM::ADDrr}, + {ARM::ADDSrsi, ARM::ADDrsi}, + {ARM::ADDSrsr, ARM::ADDrsr}, + + {ARM::SUBSri, ARM::SUBri}, + {ARM::SUBSrr, ARM::SUBrr}, + {ARM::SUBSrsi, ARM::SUBrsi}, + {ARM::SUBSrsr, ARM::SUBrsr}, + + {ARM::RSBSri, ARM::RSBri}, + {ARM::RSBSrr, ARM::RSBrr}, + {ARM::RSBSrsi, ARM::RSBrsi}, + {ARM::RSBSrsr, ARM::RSBrsr}, + + {ARM::t2ADDSri, ARM::t2ADDri}, + {ARM::t2ADDSrr, ARM::t2ADDrr}, + {ARM::t2ADDSrs, ARM::t2ADDrs}, + + {ARM::t2SUBSri, ARM::t2SUBri}, + {ARM::t2SUBSrr, ARM::t2SUBrr}, + {ARM::t2SUBSrs, ARM::t2SUBrs}, + + {ARM::t2RSBSri, ARM::t2RSBri}, + {ARM::t2RSBSrs, ARM::t2RSBrs}, +}; + +unsigned llvm::convertAddSubFlagsOpcode(unsigned OldOpc) { + static const int NPairs = + sizeof(AddSubFlagsOpcodeMap) / sizeof(AddSubFlagsOpcodePair); + for (AddSubFlagsOpcodePair *OpcPair = &AddSubFlagsOpcodeMap[0], + *End = &AddSubFlagsOpcodeMap[NPairs]; OpcPair != End; ++OpcPair) { + if (OldOpc == OpcPair->PseudoOpc) { + return OpcPair->MachineOpc; + } + } + return 0; +} + void llvm::emitARMRegPlusImmediate(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, DebugLoc dl, unsigned DestReg, unsigned BaseReg, int NumBytes, @@ -1862,7 +2038,6 @@ ARMBaseInstrInfo::getNumMicroOps(const InstrItineraryData *ItinData, case ARM::STMIB_UPD: case ARM::tLDMIA: case ARM::tLDMIA_UPD: - case ARM::tSTMIA: case ARM::tSTMIA_UPD: case ARM::tPOP_RET: case ARM::tPOP: @@ -2128,7 +2303,6 @@ ARMBaseInstrInfo::getOperandLatency(const InstrItineraryData *ItinData, case ARM::STMDA_UPD: case ARM::STMDB_UPD: case ARM::STMIB_UPD: - case ARM::tSTMIA: case ARM::tSTMIA_UPD: case ARM::tPOP_RET: case ARM::tPOP: @@ -2567,6 +2741,15 @@ hasLowDefLatency(const InstrItineraryData *ItinData, return false; } +bool ARMBaseInstrInfo::verifyInstruction(const MachineInstr *MI, + StringRef &ErrInfo) const { + if (convertAddSubFlagsOpcode(MI->getOpcode())) { + ErrInfo = "Pseudo flag setting opcodes only exist in Selection DAG"; + return false; + } + return true; +} + bool ARMBaseInstrInfo::isFpMLxInstruction(unsigned Opcode, unsigned &MulOpc, unsigned &AddSubOpc, @@ -2582,3 +2765,66 @@ ARMBaseInstrInfo::isFpMLxInstruction(unsigned Opcode, unsigned &MulOpc, HasLane = Entry.HasLane; return true; } + +//===----------------------------------------------------------------------===// +// Execution domains. +//===----------------------------------------------------------------------===// +// +// Some instructions go down the NEON pipeline, some go down the VFP pipeline, +// and some can go down both. The vmov instructions go down the VFP pipeline, +// but they can be changed to vorr equivalents that are executed by the NEON +// pipeline. +// +// We use the following execution domain numbering: +// +enum ARMExeDomain { + ExeGeneric = 0, + ExeVFP = 1, + ExeNEON = 2 +}; +// +// Also see ARMInstrFormats.td and Domain* enums in ARMBaseInfo.h +// +std::pair +ARMBaseInstrInfo::getExecutionDomain(const MachineInstr *MI) const { + // VMOVD is a VFP instruction, but can be changed to NEON if it isn't + // predicated. + if (MI->getOpcode() == ARM::VMOVD && !isPredicated(MI)) + return std::make_pair(ExeVFP, (1<getDesc().TSFlags & ARMII::DomainMask; + + if (Domain & ARMII::DomainNEON) + return std::make_pair(ExeNEON, 0); + + // Certain instructions can go either way on Cortex-A8. + // Treat them as NEON instructions. + if ((Domain & ARMII::DomainNEONA8) && Subtarget.isCortexA8()) + return std::make_pair(ExeNEON, 0); + + if (Domain & ARMII::DomainVFP) + return std::make_pair(ExeVFP, 0); + + return std::make_pair(ExeGeneric, 0); +} + +void +ARMBaseInstrInfo::setExecutionDomain(MachineInstr *MI, unsigned Domain) const { + // We only know how to change VMOVD into VORR. + assert(MI->getOpcode() == ARM::VMOVD && "Can only swizzle VMOVD"); + if (Domain != ExeNEON) + return; + + // Zap the predicate operands. + assert(!isPredicated(MI) && "Cannot predicate a VORRd"); + MI->RemoveOperand(3); + MI->RemoveOperand(2); + + // Change to a VORRd which requires two identical use operands. + MI->setDesc(get(ARM::VORRd)); + + // Add the extra source operand and new predicates. + // This will go before any implicit ops. + AddDefaultPred(MachineInstrBuilder(MI).addOperand(MI->getOperand(1))); +} diff --git a/contrib/llvm/lib/Target/ARM/ARMBaseInstrInfo.h b/contrib/llvm/lib/Target/ARM/ARMBaseInstrInfo.h index 507e8974b..0f9f32179 100644 --- a/contrib/llvm/lib/Target/ARM/ARMBaseInstrInfo.h +++ b/contrib/llvm/lib/Target/ARM/ARMBaseInstrInfo.h @@ -27,146 +27,6 @@ namespace llvm { class ARMSubtarget; class ARMBaseRegisterInfo; -/// ARMII - This namespace holds all of the target specific flags that -/// instruction info tracks. -/// -namespace ARMII { - enum { - //===------------------------------------------------------------------===// - // Instruction Flags. - - //===------------------------------------------------------------------===// - // This four-bit field describes the addressing mode used. - AddrModeMask = 0x1f, // The AddrMode enums are declared in ARMBaseInfo.h - - // IndexMode - Unindex, pre-indexed, or post-indexed are valid for load - // and store ops only. Generic "updating" flag is used for ld/st multiple. - // The index mode enums are declared in ARMBaseInfo.h - IndexModeShift = 5, - IndexModeMask = 3 << IndexModeShift, - - //===------------------------------------------------------------------===// - // Instruction encoding formats. - // - FormShift = 7, - FormMask = 0x3f << FormShift, - - // Pseudo instructions - Pseudo = 0 << FormShift, - - // Multiply instructions - MulFrm = 1 << FormShift, - - // Branch instructions - BrFrm = 2 << FormShift, - BrMiscFrm = 3 << FormShift, - - // Data Processing instructions - DPFrm = 4 << FormShift, - DPSoRegFrm = 5 << FormShift, - - // Load and Store - LdFrm = 6 << FormShift, - StFrm = 7 << FormShift, - LdMiscFrm = 8 << FormShift, - StMiscFrm = 9 << FormShift, - LdStMulFrm = 10 << FormShift, - - LdStExFrm = 11 << FormShift, - - // Miscellaneous arithmetic instructions - ArithMiscFrm = 12 << FormShift, - SatFrm = 13 << FormShift, - - // Extend instructions - ExtFrm = 14 << FormShift, - - // VFP formats - VFPUnaryFrm = 15 << FormShift, - VFPBinaryFrm = 16 << FormShift, - VFPConv1Frm = 17 << FormShift, - VFPConv2Frm = 18 << FormShift, - VFPConv3Frm = 19 << FormShift, - VFPConv4Frm = 20 << FormShift, - VFPConv5Frm = 21 << FormShift, - VFPLdStFrm = 22 << FormShift, - VFPLdStMulFrm = 23 << FormShift, - VFPMiscFrm = 24 << FormShift, - - // Thumb format - ThumbFrm = 25 << FormShift, - - // Miscelleaneous format - MiscFrm = 26 << FormShift, - - // NEON formats - NGetLnFrm = 27 << FormShift, - NSetLnFrm = 28 << FormShift, - NDupFrm = 29 << FormShift, - NLdStFrm = 30 << FormShift, - N1RegModImmFrm= 31 << FormShift, - N2RegFrm = 32 << FormShift, - NVCVTFrm = 33 << FormShift, - NVDupLnFrm = 34 << FormShift, - N2RegVShLFrm = 35 << FormShift, - N2RegVShRFrm = 36 << FormShift, - N3RegFrm = 37 << FormShift, - N3RegVShFrm = 38 << FormShift, - NVExtFrm = 39 << FormShift, - NVMulSLFrm = 40 << FormShift, - NVTBLFrm = 41 << FormShift, - - //===------------------------------------------------------------------===// - // Misc flags. - - // UnaryDP - Indicates this is a unary data processing instruction, i.e. - // it doesn't have a Rn operand. - UnaryDP = 1 << 13, - - // Xform16Bit - Indicates this Thumb2 instruction may be transformed into - // a 16-bit Thumb instruction if certain conditions are met. - Xform16Bit = 1 << 14, - - //===------------------------------------------------------------------===// - // Code domain. - DomainShift = 15, - DomainMask = 7 << DomainShift, - DomainGeneral = 0 << DomainShift, - DomainVFP = 1 << DomainShift, - DomainNEON = 2 << DomainShift, - DomainNEONA8 = 4 << DomainShift, - - //===------------------------------------------------------------------===// - // Field shifts - such shifts are used to set field while generating - // machine instructions. - // - // FIXME: This list will need adjusting/fixing as the MC code emitter - // takes shape and the ARMCodeEmitter.cpp bits go away. - ShiftTypeShift = 4, - - M_BitShift = 5, - ShiftImmShift = 5, - ShiftShift = 7, - N_BitShift = 7, - ImmHiShift = 8, - SoRotImmShift = 8, - RegRsShift = 8, - ExtRotImmShift = 10, - RegRdLoShift = 12, - RegRdShift = 12, - RegRdHiShift = 16, - RegRnShift = 16, - S_BitShift = 20, - W_BitShift = 21, - AM3_I_BitShift = 22, - D_BitShift = 22, - U_BitShift = 23, - P_BitShift = 24, - I_BitShift = 25, - CondShift = 28 - }; -} - class ARMBaseInstrInfo : public ARMGenInstrInfo { const ARMSubtarget &Subtarget; @@ -241,6 +101,10 @@ public: int &FrameIndex) const; virtual unsigned isStoreToStackSlot(const MachineInstr *MI, int &FrameIndex) const; + virtual unsigned isLoadFromStackSlotPostFE(const MachineInstr *MI, + int &FrameIndex) const; + virtual unsigned isStoreToStackSlotPostFE(const MachineInstr *MI, + int &FrameIndex) const; virtual void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, DebugLoc DL, @@ -259,6 +123,8 @@ public: const TargetRegisterClass *RC, const TargetRegisterInfo *TRI) const; + virtual bool expandPostRAPseudo(MachineBasicBlock::iterator MI) const; + virtual MachineInstr *emitFrameIndexDebugValue(MachineFunction &MF, int FrameIx, uint64_t Offset, @@ -346,6 +212,12 @@ public: int getOperandLatency(const InstrItineraryData *ItinData, SDNode *DefNode, unsigned DefIdx, SDNode *UseNode, unsigned UseIdx) const; + + /// VFP/NEON execution domains. + std::pair + getExecutionDomain(const MachineInstr *MI) const; + void setExecutionDomain(MachineInstr *MI, unsigned Domain) const; + private: int getVLDMDefCycle(const InstrItineraryData *ItinData, const MCInstrDesc &DefMCID, @@ -382,6 +254,9 @@ private: bool hasLowDefLatency(const InstrItineraryData *ItinData, const MachineInstr *DefMI, unsigned DefIdx) const; + /// verifyInstruction - Perform target specific instruction verification. + bool verifyInstruction(const MachineInstr *MI, StringRef &ErrInfo) const; + private: /// Modeling special VFP / NEON fp MLA / MLS hazards. @@ -464,6 +339,12 @@ ARMCC::CondCodes getInstrPredicate(const MachineInstr *MI, unsigned &PredReg); int getMatchingCondBranchOpcode(int Opc); + +/// Map pseudo instructions that imply an 'S' bit onto real opcodes. Whether +/// the instruction is encoded with an 'S' bit is determined by the optional +/// CPSR def operand. +unsigned convertAddSubFlagsOpcode(unsigned OldOpc); + /// emitARMRegPlusImmediate / emitT2RegPlusImmediate - Emits a series of /// instructions to materializea destreg = basereg + immediate in ARM / Thumb2 /// code. diff --git a/contrib/llvm/lib/Target/ARM/ARMBaseRegisterInfo.cpp b/contrib/llvm/lib/Target/ARM/ARMBaseRegisterInfo.cpp index ba422952a..7c4234222 100644 --- a/contrib/llvm/lib/Target/ARM/ARMBaseRegisterInfo.cpp +++ b/contrib/llvm/lib/Target/ARM/ARMBaseRegisterInfo.cpp @@ -12,13 +12,13 @@ //===----------------------------------------------------------------------===// #include "ARM.h" -#include "ARMAddressingModes.h" #include "ARMBaseInstrInfo.h" #include "ARMBaseRegisterInfo.h" #include "ARMFrameLowering.h" #include "ARMInstrInfo.h" #include "ARMMachineFunctionInfo.h" #include "ARMSubtarget.h" +#include "MCTargetDesc/ARMAddressingModes.h" #include "llvm/Constants.h" #include "llvm/DerivedTypes.h" #include "llvm/Function.h" @@ -27,7 +27,6 @@ #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineInstrBuilder.h" -#include "llvm/CodeGen/MachineLocation.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/RegisterScavenging.h" #include "llvm/Support/Debug.h" @@ -57,7 +56,7 @@ EnableBasePointer("arm-use-base-pointer", cl::Hidden, cl::init(true), ARMBaseRegisterInfo::ARMBaseRegisterInfo(const ARMBaseInstrInfo &tii, const ARMSubtarget &sti) - : ARMGenRegisterInfo(), TII(tii), STI(sti), + : ARMGenRegisterInfo(ARM::LR), TII(tii), STI(sti), FramePtr((STI.isTargetDarwin() || STI.isThumb()) ? ARM::R7 : ARM::R11), BasePtr(ARM::R6) { } @@ -354,7 +353,7 @@ const TargetRegisterClass* ARMBaseRegisterInfo::getLargestLegalSuperClass(const TargetRegisterClass *RC) const { const TargetRegisterClass *Super = RC; - TargetRegisterClass::sc_iterator I = RC->superclasses_begin(); + TargetRegisterClass::sc_iterator I = RC->getSuperClasses(); do { switch (Super->getID()) { case ARM::GPRRegClassID: @@ -375,6 +374,13 @@ ARMBaseRegisterInfo::getPointerRegClass(unsigned Kind) const { return ARM::GPRRegisterClass; } +const TargetRegisterClass * +ARMBaseRegisterInfo::getCrossCopyRegClass(const TargetRegisterClass *RC) const { + if (RC == &ARM::CCRRegClass) + return 0; // Can't copy CCR registers. + return RC; +} + unsigned ARMBaseRegisterInfo::getRegPressureLimit(const TargetRegisterClass *RC, MachineFunction &MF) const { @@ -487,19 +493,19 @@ ARMBaseRegisterInfo::getRawAllocationOrder(const TargetRegisterClass *RC, if (!TFI->hasFP(MF)) { if (!STI.isR9Reserved()) - return ArrayRef(GPREven1); + return makeArrayRef(GPREven1); else - return ArrayRef(GPREven4); + return makeArrayRef(GPREven4); } else if (FramePtr == ARM::R7) { if (!STI.isR9Reserved()) - return ArrayRef(GPREven2); + return makeArrayRef(GPREven2); else - return ArrayRef(GPREven5); + return makeArrayRef(GPREven5); } else { // FramePtr == ARM::R11 if (!STI.isR9Reserved()) - return ArrayRef(GPREven3); + return makeArrayRef(GPREven3); else - return ArrayRef(GPREven6); + return makeArrayRef(GPREven6); } } else if (HintType == ARMRI::RegPairOdd) { if (isPhysicalRegister(HintReg) && getRegisterPairOdd(HintReg, MF) == 0) @@ -509,19 +515,19 @@ ARMBaseRegisterInfo::getRawAllocationOrder(const TargetRegisterClass *RC, if (!TFI->hasFP(MF)) { if (!STI.isR9Reserved()) - return ArrayRef(GPROdd1); + return makeArrayRef(GPROdd1); else - return ArrayRef(GPROdd4); + return makeArrayRef(GPROdd4); } else if (FramePtr == ARM::R7) { if (!STI.isR9Reserved()) - return ArrayRef(GPROdd2); + return makeArrayRef(GPROdd2); else - return ArrayRef(GPROdd5); + return makeArrayRef(GPROdd5); } else { // FramePtr == ARM::R11 if (!STI.isR9Reserved()) - return ArrayRef(GPROdd3); + return makeArrayRef(GPROdd3); else - return ArrayRef(GPROdd6); + return makeArrayRef(GPROdd6); } } return RC->getRawAllocationOrder(MF); @@ -649,10 +655,6 @@ cannotEliminateFrame(const MachineFunction &MF) const { || needsStackRealignment(MF); } -unsigned ARMBaseRegisterInfo::getRARegister() const { - return ARM::LR; -} - unsigned ARMBaseRegisterInfo::getFrameRegister(const MachineFunction &MF) const { const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering(); @@ -672,99 +674,54 @@ unsigned ARMBaseRegisterInfo::getEHHandlerRegister() const { return 0; } -int ARMBaseRegisterInfo::getDwarfRegNum(unsigned RegNum, bool isEH) const { - return ARMGenRegisterInfo::getDwarfRegNumFull(RegNum, 0); -} - -int ARMBaseRegisterInfo::getLLVMRegNum(unsigned DwarfRegNo, bool isEH) const { - return ARMGenRegisterInfo::getLLVMRegNumFull(DwarfRegNo,0); -} - unsigned ARMBaseRegisterInfo::getRegisterPairEven(unsigned Reg, const MachineFunction &MF) const { switch (Reg) { default: break; // Return 0 if either register of the pair is a special register. // So no R12, etc. - case ARM::R1: - return ARM::R0; - case ARM::R3: - return ARM::R2; - case ARM::R5: - return ARM::R4; + case ARM::R1: return ARM::R0; + case ARM::R3: return ARM::R2; + case ARM::R5: return ARM::R4; case ARM::R7: return (isReservedReg(MF, ARM::R7) || isReservedReg(MF, ARM::R6)) ? 0 : ARM::R6; - case ARM::R9: - return isReservedReg(MF, ARM::R9) ? 0 :ARM::R8; - case ARM::R11: - return isReservedReg(MF, ARM::R11) ? 0 : ARM::R10; - - case ARM::S1: - return ARM::S0; - case ARM::S3: - return ARM::S2; - case ARM::S5: - return ARM::S4; - case ARM::S7: - return ARM::S6; - case ARM::S9: - return ARM::S8; - case ARM::S11: - return ARM::S10; - case ARM::S13: - return ARM::S12; - case ARM::S15: - return ARM::S14; - case ARM::S17: - return ARM::S16; - case ARM::S19: - return ARM::S18; - case ARM::S21: - return ARM::S20; - case ARM::S23: - return ARM::S22; - case ARM::S25: - return ARM::S24; - case ARM::S27: - return ARM::S26; - case ARM::S29: - return ARM::S28; - case ARM::S31: - return ARM::S30; - - case ARM::D1: - return ARM::D0; - case ARM::D3: - return ARM::D2; - case ARM::D5: - return ARM::D4; - case ARM::D7: - return ARM::D6; - case ARM::D9: - return ARM::D8; - case ARM::D11: - return ARM::D10; - case ARM::D13: - return ARM::D12; - case ARM::D15: - return ARM::D14; - case ARM::D17: - return ARM::D16; - case ARM::D19: - return ARM::D18; - case ARM::D21: - return ARM::D20; - case ARM::D23: - return ARM::D22; - case ARM::D25: - return ARM::D24; - case ARM::D27: - return ARM::D26; - case ARM::D29: - return ARM::D28; - case ARM::D31: - return ARM::D30; + case ARM::R9: return isReservedReg(MF, ARM::R9) ? 0 :ARM::R8; + case ARM::R11: return isReservedReg(MF, ARM::R11) ? 0 : ARM::R10; + + case ARM::S1: return ARM::S0; + case ARM::S3: return ARM::S2; + case ARM::S5: return ARM::S4; + case ARM::S7: return ARM::S6; + case ARM::S9: return ARM::S8; + case ARM::S11: return ARM::S10; + case ARM::S13: return ARM::S12; + case ARM::S15: return ARM::S14; + case ARM::S17: return ARM::S16; + case ARM::S19: return ARM::S18; + case ARM::S21: return ARM::S20; + case ARM::S23: return ARM::S22; + case ARM::S25: return ARM::S24; + case ARM::S27: return ARM::S26; + case ARM::S29: return ARM::S28; + case ARM::S31: return ARM::S30; + + case ARM::D1: return ARM::D0; + case ARM::D3: return ARM::D2; + case ARM::D5: return ARM::D4; + case ARM::D7: return ARM::D6; + case ARM::D9: return ARM::D8; + case ARM::D11: return ARM::D10; + case ARM::D13: return ARM::D12; + case ARM::D15: return ARM::D14; + case ARM::D17: return ARM::D16; + case ARM::D19: return ARM::D18; + case ARM::D21: return ARM::D20; + case ARM::D23: return ARM::D22; + case ARM::D25: return ARM::D24; + case ARM::D27: return ARM::D26; + case ARM::D29: return ARM::D28; + case ARM::D31: return ARM::D30; } return 0; @@ -776,85 +733,48 @@ unsigned ARMBaseRegisterInfo::getRegisterPairOdd(unsigned Reg, default: break; // Return 0 if either register of the pair is a special register. // So no R12, etc. - case ARM::R0: - return ARM::R1; - case ARM::R2: - return ARM::R3; - case ARM::R4: - return ARM::R5; + case ARM::R0: return ARM::R1; + case ARM::R2: return ARM::R3; + case ARM::R4: return ARM::R5; case ARM::R6: return (isReservedReg(MF, ARM::R7) || isReservedReg(MF, ARM::R6)) ? 0 : ARM::R7; - case ARM::R8: - return isReservedReg(MF, ARM::R9) ? 0 :ARM::R9; - case ARM::R10: - return isReservedReg(MF, ARM::R11) ? 0 : ARM::R11; - - case ARM::S0: - return ARM::S1; - case ARM::S2: - return ARM::S3; - case ARM::S4: - return ARM::S5; - case ARM::S6: - return ARM::S7; - case ARM::S8: - return ARM::S9; - case ARM::S10: - return ARM::S11; - case ARM::S12: - return ARM::S13; - case ARM::S14: - return ARM::S15; - case ARM::S16: - return ARM::S17; - case ARM::S18: - return ARM::S19; - case ARM::S20: - return ARM::S21; - case ARM::S22: - return ARM::S23; - case ARM::S24: - return ARM::S25; - case ARM::S26: - return ARM::S27; - case ARM::S28: - return ARM::S29; - case ARM::S30: - return ARM::S31; - - case ARM::D0: - return ARM::D1; - case ARM::D2: - return ARM::D3; - case ARM::D4: - return ARM::D5; - case ARM::D6: - return ARM::D7; - case ARM::D8: - return ARM::D9; - case ARM::D10: - return ARM::D11; - case ARM::D12: - return ARM::D13; - case ARM::D14: - return ARM::D15; - case ARM::D16: - return ARM::D17; - case ARM::D18: - return ARM::D19; - case ARM::D20: - return ARM::D21; - case ARM::D22: - return ARM::D23; - case ARM::D24: - return ARM::D25; - case ARM::D26: - return ARM::D27; - case ARM::D28: - return ARM::D29; - case ARM::D30: - return ARM::D31; + case ARM::R8: return isReservedReg(MF, ARM::R9) ? 0 :ARM::R9; + case ARM::R10: return isReservedReg(MF, ARM::R11) ? 0 : ARM::R11; + + case ARM::S0: return ARM::S1; + case ARM::S2: return ARM::S3; + case ARM::S4: return ARM::S5; + case ARM::S6: return ARM::S7; + case ARM::S8: return ARM::S9; + case ARM::S10: return ARM::S11; + case ARM::S12: return ARM::S13; + case ARM::S14: return ARM::S15; + case ARM::S16: return ARM::S17; + case ARM::S18: return ARM::S19; + case ARM::S20: return ARM::S21; + case ARM::S22: return ARM::S23; + case ARM::S24: return ARM::S25; + case ARM::S26: return ARM::S27; + case ARM::S28: return ARM::S29; + case ARM::S30: return ARM::S31; + + case ARM::D0: return ARM::D1; + case ARM::D2: return ARM::D3; + case ARM::D4: return ARM::D5; + case ARM::D6: return ARM::D7; + case ARM::D8: return ARM::D9; + case ARM::D10: return ARM::D11; + case ARM::D12: return ARM::D13; + case ARM::D14: return ARM::D15; + case ARM::D16: return ARM::D17; + case ARM::D18: return ARM::D19; + case ARM::D20: return ARM::D21; + case ARM::D22: return ARM::D23; + case ARM::D24: return ARM::D25; + case ARM::D26: return ARM::D27; + case ARM::D28: return ARM::D29; + case ARM::D30: return ARM::D31; } return 0; @@ -1111,11 +1031,11 @@ materializeFrameBaseRegister(MachineBasicBlock *MBB, MachineRegisterInfo &MRI = MBB->getParent()->getRegInfo(); MRI.constrainRegClass(BaseReg, TII.getRegClass(MCID, 0, this)); - MachineInstrBuilder MIB = BuildMI(*MBB, Ins, DL, MCID, BaseReg) - .addFrameIndex(FrameIdx).addImm(Offset); + MachineInstrBuilder MIB = AddDefaultPred(BuildMI(*MBB, Ins, DL, MCID, BaseReg) + .addFrameIndex(FrameIdx).addImm(Offset)); if (!AFI->isThumb1OnlyFunction()) - AddDefaultCC(AddDefaultPred(MIB)); + AddDefaultCC(MIB); } void @@ -1143,6 +1063,7 @@ ARMBaseRegisterInfo::resolveFrameIndex(MachineBasicBlock::iterator I, Done = rewriteT2FrameIndex(MI, i, BaseReg, Off, TII); } assert (Done && "Unable to resolve frame index!"); + (void)Done; } bool ARMBaseRegisterInfo::isFrameOffsetLegal(const MachineInstr *MI, diff --git a/contrib/llvm/lib/Target/ARM/ARMBaseRegisterInfo.h b/contrib/llvm/lib/Target/ARM/ARMBaseRegisterInfo.h index b4b4059e7..fee17ff3c 100644 --- a/contrib/llvm/lib/Target/ARM/ARMBaseRegisterInfo.h +++ b/contrib/llvm/lib/Target/ARM/ARMBaseRegisterInfo.h @@ -33,19 +33,6 @@ namespace ARMRI { }; } -/// isARMLowRegister - Returns true if the register is low register r0-r7. -/// -static inline bool isARMLowRegister(unsigned Reg) { - using namespace ARM; - switch (Reg) { - case R0: case R1: case R2: case R3: - case R4: case R5: case R6: case R7: - return true; - default: - return false; - } -} - /// isARMArea1Register - Returns true if the register is a low register (r0-r7) /// or a stack/pc register that we should push/pop. static inline bool isARMArea1Register(unsigned Reg, bool isDarwin) { @@ -129,6 +116,8 @@ public: unsigned &NewSubIdx) const; const TargetRegisterClass *getPointerRegClass(unsigned Kind = 0) const; + const TargetRegisterClass* + getCrossCopyRegClass(const TargetRegisterClass *RC) const; const TargetRegisterClass* getLargestLegalSuperClass(const TargetRegisterClass *RC) const; @@ -164,7 +153,6 @@ public: bool cannotEliminateFrame(const MachineFunction &MF) const; // Debug information queries. - unsigned getRARegister() const; unsigned getFrameRegister(const MachineFunction &MF) const; unsigned getBaseRegister() const { return BasePtr; } @@ -172,9 +160,6 @@ public: unsigned getEHExceptionRegister() const; unsigned getEHHandlerRegister() const; - int getDwarfRegNum(unsigned RegNum, bool isEH) const; - int getLLVMRegNum(unsigned RegNum, bool isEH) const; - bool isLowRegister(unsigned Reg) const; diff --git a/contrib/llvm/lib/Target/ARM/ARMCodeEmitter.cpp b/contrib/llvm/lib/Target/ARM/ARMCodeEmitter.cpp index d6fca6277..4148d4ab1 100644 --- a/contrib/llvm/lib/Target/ARM/ARMCodeEmitter.cpp +++ b/contrib/llvm/lib/Target/ARM/ARMCodeEmitter.cpp @@ -14,12 +14,12 @@ #define DEBUG_TYPE "jit" #include "ARM.h" -#include "ARMAddressingModes.h" #include "ARMConstantPoolValue.h" #include "ARMInstrInfo.h" #include "ARMRelocations.h" #include "ARMSubtarget.h" #include "ARMTargetMachine.h" +#include "MCTargetDesc/ARMAddressingModes.h" #include "llvm/Constants.h" #include "llvm/DerivedTypes.h" #include "llvm/Function.h" @@ -161,11 +161,11 @@ namespace { // are already handled elsewhere. They are placeholders to allow this // encoder to continue to function until the MC encoder is sufficiently // far along that this one can be eliminated entirely. - unsigned NEONThumb2DataIPostEncoder(const MachineInstr &MI, unsigned Val) + unsigned NEONThumb2DataIPostEncoder(const MachineInstr &MI, unsigned Val) const { return 0; } - unsigned NEONThumb2LoadStorePostEncoder(const MachineInstr &MI,unsigned Val) + unsigned NEONThumb2LoadStorePostEncoder(const MachineInstr &MI,unsigned Val) const { return 0; } - unsigned NEONThumb2DupPostEncoder(const MachineInstr &MI,unsigned Val) + unsigned NEONThumb2DupPostEncoder(const MachineInstr &MI,unsigned Val) const { return 0; } unsigned VFPThumb2PostEncoder(const MachineInstr&MI, unsigned Val) const { return 0; } @@ -189,13 +189,17 @@ namespace { unsigned Op) const { return 0; } unsigned getARMBranchTargetOpValue(const MachineInstr &MI, unsigned Op) const { return 0; } + unsigned getARMBLXTargetOpValue(const MachineInstr &MI, unsigned Op) + const { return 0; } unsigned getCCOutOpValue(const MachineInstr &MI, unsigned Op) const { return 0; } unsigned getSOImmOpValue(const MachineInstr &MI, unsigned Op) const { return 0; } unsigned getT2SOImmOpValue(const MachineInstr &MI, unsigned Op) const { return 0; } - unsigned getSORegOpValue(const MachineInstr &MI, unsigned Op) + unsigned getSORegRegOpValue(const MachineInstr &MI, unsigned Op) + const { return 0; } + unsigned getSORegImmOpValue(const MachineInstr &MI, unsigned Op) const { return 0; } unsigned getThumbAddrModeRegRegOpValue(const MachineInstr &MI, unsigned Op) const { return 0; } @@ -203,8 +207,12 @@ namespace { const { return 0; } unsigned getT2AddrModeImm8OpValue(const MachineInstr &MI, unsigned Op) const { return 0; } + unsigned getT2Imm8s4OpValue(const MachineInstr &MI, unsigned Op) + const { return 0; } unsigned getT2AddrModeImm8s4OpValue(const MachineInstr &MI, unsigned Op) const { return 0; } + unsigned getT2AddrModeImm0_1020s4OpValue(const MachineInstr &MI,unsigned Op) + const { return 0; } unsigned getT2AddrModeImm8OffsetOpValue(const MachineInstr &MI, unsigned Op) const { return 0; } unsigned getT2AddrModeImm12OffsetOpValue(const MachineInstr &MI,unsigned Op) @@ -213,10 +221,6 @@ namespace { const { return 0; } unsigned getT2SORegOpValue(const MachineInstr &MI, unsigned Op) const { return 0; } - unsigned getRotImmOpValue(const MachineInstr &MI, unsigned Op) - const { return 0; } - unsigned getImmMinusOneOpValue(const MachineInstr &MI, unsigned Op) - const { return 0; } unsigned getT2AdrLabelOpValue(const MachineInstr &MI, unsigned Op) const { return 0; } unsigned getAddrMode6AddressOpValue(const MachineInstr &MI, unsigned Op) @@ -230,8 +234,6 @@ namespace { const { return 0; } unsigned getBitfieldInvertedMaskOpValue(const MachineInstr &MI, unsigned Op) const { return 0; } - unsigned getMsbOpValue(const MachineInstr &MI, - unsigned Op) const { return 0; } unsigned getSsatBitPosValue(const MachineInstr &MI, unsigned Op) const { return 0; } uint32_t getLdStmModeOpValue(const MachineInstr &MI, unsigned OpIdx) @@ -268,6 +270,8 @@ namespace { const { return 0;} uint32_t getAddrMode2OffsetOpValue(const MachineInstr &MI, unsigned OpIdx) const { return 0;} + uint32_t getPostIdxRegOpValue(const MachineInstr &MI, unsigned OpIdx) + const { return 0;} uint32_t getAddrMode3OffsetOpValue(const MachineInstr &MI, unsigned OpIdx) const { return 0;} uint32_t getAddrMode3OpValue(const MachineInstr &MI, unsigned Op) @@ -632,15 +636,16 @@ void ARMCodeEmitter::emitConstPoolInstruction(const MachineInstr &MI) { << (void*)MCE.getCurrentPCValue() << " " << *ACPV << '\n'); assert(ACPV->isGlobalValue() && "unsupported constant pool value"); - const GlobalValue *GV = ACPV->getGV(); + const GlobalValue *GV = cast(ACPV)->getGV(); if (GV) { Reloc::Model RelocM = TM.getRelocationModel(); emitGlobalAddress(GV, ARM::reloc_arm_machine_cp_entry, isa(GV), Subtarget->GVIsIndirectSymbol(GV, RelocM), (intptr_t)ACPV); - } else { - emitExternalSymbolAddress(ACPV->getSymbol(), ARM::reloc_arm_absolute); + } else { + const char *Sym = cast(ACPV)->getSymbol(); + emitExternalSymbolAddress(Sym, ARM::reloc_arm_absolute); } emitWordLE(0); } else { @@ -983,7 +988,7 @@ unsigned ARMCodeEmitter::getMachineSoImmOpValue(unsigned SoImm) { unsigned ARMCodeEmitter::getAddrModeSBit(const MachineInstr &MI, const MCInstrDesc &MCID) const { - for (unsigned i = MI.getNumOperands(), e = MCID.getNumOperands(); i >= e; --i){ + for (unsigned i = MI.getNumOperands(), e = MCID.getNumOperands(); i >= e;--i){ const MachineOperand &MO = MI.getOperand(i-1); if (MO.isReg() && MO.isDef() && MO.getReg() == ARM::CPSR) return 1 << ARMII::S_BitShift; diff --git a/contrib/llvm/lib/Target/ARM/ARMConstantIslandPass.cpp b/contrib/llvm/lib/Target/ARM/ARMConstantIslandPass.cpp index f45ebdc53..3e3a4134c 100644 --- a/contrib/llvm/lib/Target/ARM/ARMConstantIslandPass.cpp +++ b/contrib/llvm/lib/Target/ARM/ARMConstantIslandPass.cpp @@ -15,10 +15,10 @@ #define DEBUG_TYPE "arm-cp-islands" #include "ARM.h" -#include "ARMAddressingModes.h" #include "ARMMachineFunctionInfo.h" #include "ARMInstrInfo.h" #include "Thumb2InstrInfo.h" +#include "MCTargetDesc/ARMAddressingModes.h" #include "llvm/CodeGen/MachineConstantPool.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineJumpTableInfo.h" @@ -739,7 +739,11 @@ MachineBasicBlock *ARMConstantIslands::SplitBlockBeforeInstr(MachineInstr *MI) { // There doesn't seem to be meaningful DebugInfo available; this doesn't // correspond to anything in the source. unsigned Opc = isThumb ? (isThumb2 ? ARM::t2B : ARM::tB) : ARM::B; - BuildMI(OrigBB, DebugLoc(), TII->get(Opc)).addMBB(NewBB); + if (!isThumb) + BuildMI(OrigBB, DebugLoc(), TII->get(Opc)).addMBB(NewBB); + else + BuildMI(OrigBB, DebugLoc(), TII->get(Opc)).addMBB(NewBB) + .addImm(ARMCC::AL).addReg(0); ++NumSplit; // Update the CFG. All succs of OrigBB are now succs of NewBB. @@ -1151,7 +1155,11 @@ void ARMConstantIslands::CreateNewWater(unsigned CPUserIndex, // targets will be exchanged, and the altered branch may be out of // range, so the machinery has to know about it. int UncondBr = isThumb ? ((isThumb2) ? ARM::t2B : ARM::tB) : ARM::B; - BuildMI(UserMBB, DebugLoc(), TII->get(UncondBr)).addMBB(NewMBB); + if (!isThumb) + BuildMI(UserMBB, DebugLoc(), TII->get(UncondBr)).addMBB(NewMBB); + else + BuildMI(UserMBB, DebugLoc(), TII->get(UncondBr)).addMBB(NewMBB) + .addImm(ARMCC::AL).addReg(0); unsigned MaxDisp = getUnconditionalBrDisp(UncondBr); ImmBranches.push_back(ImmBranch(&UserMBB->back(), MaxDisp, false, UncondBr)); @@ -1512,7 +1520,11 @@ ARMConstantIslands::FixUpConditionalBr(MachineFunction &MF, ImmBranch &Br) { .addMBB(NextBB).addImm(CC).addReg(CCReg); Br.MI = &MBB->back(); BBSizes[MBB->getNumber()] += TII->GetInstSizeInBytes(&MBB->back()); - BuildMI(MBB, DebugLoc(), TII->get(Br.UncondBr)).addMBB(DestBB); + if (isThumb) + BuildMI(MBB, DebugLoc(), TII->get(Br.UncondBr)).addMBB(DestBB) + .addImm(ARMCC::AL).addReg(0); + else + BuildMI(MBB, DebugLoc(), TII->get(Br.UncondBr)).addMBB(DestBB); BBSizes[MBB->getNumber()] += TII->GetInstSizeInBytes(&MBB->back()); unsigned MaxDisp = getUnconditionalBrDisp(Br.UncondBr); ImmBranches.push_back(ImmBranch(&MBB->back(), MaxDisp, false, Br.UncondBr)); @@ -1891,7 +1903,8 @@ AdjustJTTargetBlockForward(MachineBasicBlock *BB, MachineBasicBlock *JTBB) // There doesn't seem to be meaningful DebugInfo available; this doesn't // correspond directly to anything in the source. assert (isThumb2 && "Adjusting for TB[BH] but not in Thumb2?"); - BuildMI(NewBB, DebugLoc(), TII->get(ARM::t2B)).addMBB(BB); + BuildMI(NewBB, DebugLoc(), TII->get(ARM::t2B)).addMBB(BB) + .addImm(ARMCC::AL).addReg(0); // Update internal data structures to account for the newly inserted MBB. MF.RenumberBlocks(NewBB); diff --git a/contrib/llvm/lib/Target/ARM/ARMConstantPoolValue.cpp b/contrib/llvm/lib/Target/ARM/ARMConstantPoolValue.cpp index 165a1d849..aadfd4779 100644 --- a/contrib/llvm/lib/Target/ARM/ARMConstantPoolValue.cpp +++ b/contrib/llvm/lib/Target/ARM/ARMConstantPoolValue.cpp @@ -17,79 +17,57 @@ #include "llvm/Constants.h" #include "llvm/GlobalValue.h" #include "llvm/Type.h" +#include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/Support/raw_ostream.h" #include using namespace llvm; -ARMConstantPoolValue::ARMConstantPoolValue(const Constant *cval, unsigned id, - ARMCP::ARMCPKind K, +//===----------------------------------------------------------------------===// +// ARMConstantPoolValue +//===----------------------------------------------------------------------===// + +ARMConstantPoolValue::ARMConstantPoolValue(Type *Ty, unsigned id, + ARMCP::ARMCPKind kind, unsigned char PCAdj, - ARMCP::ARMCPModifier Modif, - bool AddCA) - : MachineConstantPoolValue((const Type*)cval->getType()), - CVal(cval), S(NULL), LabelId(id), Kind(K), PCAdjust(PCAdj), - Modifier(Modif), AddCurrentAddress(AddCA) {} - -ARMConstantPoolValue::ARMConstantPoolValue(LLVMContext &C, - const char *s, unsigned id, + ARMCP::ARMCPModifier modifier, + bool addCurrentAddress) + : MachineConstantPoolValue(Ty), LabelId(id), Kind(kind), + PCAdjust(PCAdj), Modifier(modifier), + AddCurrentAddress(addCurrentAddress) {} + +ARMConstantPoolValue::ARMConstantPoolValue(LLVMContext &C, unsigned id, + ARMCP::ARMCPKind kind, unsigned char PCAdj, - ARMCP::ARMCPModifier Modif, - bool AddCA) - : MachineConstantPoolValue((const Type*)Type::getInt32Ty(C)), - CVal(NULL), S(strdup(s)), LabelId(id), Kind(ARMCP::CPExtSymbol), - PCAdjust(PCAdj), Modifier(Modif), AddCurrentAddress(AddCA) {} - -ARMConstantPoolValue::ARMConstantPoolValue(const GlobalValue *gv, - ARMCP::ARMCPModifier Modif) - : MachineConstantPoolValue((const Type*)Type::getInt32Ty(gv->getContext())), - CVal(gv), S(NULL), LabelId(0), Kind(ARMCP::CPValue), PCAdjust(0), - Modifier(Modif), AddCurrentAddress(false) {} - -const GlobalValue *ARMConstantPoolValue::getGV() const { - return dyn_cast_or_null(CVal); -} + ARMCP::ARMCPModifier modifier, + bool addCurrentAddress) + : MachineConstantPoolValue((Type*)Type::getInt32Ty(C)), + LabelId(id), Kind(kind), PCAdjust(PCAdj), Modifier(modifier), + AddCurrentAddress(addCurrentAddress) {} -const BlockAddress *ARMConstantPoolValue::getBlockAddress() const { - return dyn_cast_or_null(CVal); -} +ARMConstantPoolValue::~ARMConstantPoolValue() {} -static bool CPV_streq(const char *S1, const char *S2) { - if (S1 == S2) - return true; - if (S1 && S2 && strcmp(S1, S2) == 0) - return true; - return false; +const char *ARMConstantPoolValue::getModifierText() const { + switch (Modifier) { + default: llvm_unreachable("Unknown modifier!"); + // FIXME: Are these case sensitive? It'd be nice to lower-case all the + // strings if that's legal. + case ARMCP::no_modifier: return "none"; + case ARMCP::TLSGD: return "tlsgd"; + case ARMCP::GOT: return "GOT"; + case ARMCP::GOTOFF: return "GOTOFF"; + case ARMCP::GOTTPOFF: return "gottpoff"; + case ARMCP::TPOFF: return "tpoff"; + } } int ARMConstantPoolValue::getExistingMachineCPValue(MachineConstantPool *CP, unsigned Alignment) { - unsigned AlignMask = Alignment - 1; - const std::vector Constants = CP->getConstants(); - for (unsigned i = 0, e = Constants.size(); i != e; ++i) { - if (Constants[i].isMachineConstantPoolEntry() && - (Constants[i].getAlignment() & AlignMask) == 0) { - ARMConstantPoolValue *CPV = - (ARMConstantPoolValue *)Constants[i].Val.MachineCPVal; - if (CPV->CVal == CVal && - CPV->LabelId == LabelId && - CPV->PCAdjust == PCAdjust && - CPV_streq(CPV->S, S) && - CPV->Modifier == Modifier) - return i; - } - } - + assert(false && "Shouldn't be calling this directly!"); return -1; } -ARMConstantPoolValue::~ARMConstantPoolValue() { - free((void*)S); -} - void -ARMConstantPoolValue::AddSelectionDAGCSEId(FoldingSetNodeID &ID) { - ID.AddPointer(CVal); - ID.AddPointer(S); +ARMConstantPoolValue::addSelectionDAGCSEId(FoldingSetNodeID &ID) { ID.AddInteger(LabelId); ID.AddInteger(PCAdjust); } @@ -97,9 +75,7 @@ ARMConstantPoolValue::AddSelectionDAGCSEId(FoldingSetNodeID &ID) { bool ARMConstantPoolValue::hasSameValue(ARMConstantPoolValue *ACPV) { if (ACPV->Kind == Kind && - ACPV->CVal == CVal && ACPV->PCAdjust == PCAdjust && - CPV_streq(ACPV->S, S) && ACPV->Modifier == Modifier) { if (ACPV->LabelId == LabelId) return true; @@ -115,12 +91,7 @@ void ARMConstantPoolValue::dump() const { errs() << " " << *this; } - void ARMConstantPoolValue::print(raw_ostream &O) const { - if (CVal) - O << CVal->getName(); - else - O << S; if (Modifier) O << "(" << getModifierText() << ")"; if (PCAdjust != 0) { O << "-(LPC" << LabelId << "+" << (unsigned)PCAdjust; @@ -128,3 +99,221 @@ void ARMConstantPoolValue::print(raw_ostream &O) const { O << ")"; } } + +//===----------------------------------------------------------------------===// +// ARMConstantPoolConstant +//===----------------------------------------------------------------------===// + +ARMConstantPoolConstant::ARMConstantPoolConstant(Type *Ty, + const Constant *C, + unsigned ID, + ARMCP::ARMCPKind Kind, + unsigned char PCAdj, + ARMCP::ARMCPModifier Modifier, + bool AddCurrentAddress) + : ARMConstantPoolValue(Ty, ID, Kind, PCAdj, Modifier, AddCurrentAddress), + CVal(C) {} + +ARMConstantPoolConstant::ARMConstantPoolConstant(const Constant *C, + unsigned ID, + ARMCP::ARMCPKind Kind, + unsigned char PCAdj, + ARMCP::ARMCPModifier Modifier, + bool AddCurrentAddress) + : ARMConstantPoolValue((Type*)C->getType(), ID, Kind, PCAdj, Modifier, + AddCurrentAddress), + CVal(C) {} + +ARMConstantPoolConstant * +ARMConstantPoolConstant::Create(const Constant *C, unsigned ID) { + return new ARMConstantPoolConstant(C, ID, ARMCP::CPValue, 0, + ARMCP::no_modifier, false); +} + +ARMConstantPoolConstant * +ARMConstantPoolConstant::Create(const GlobalValue *GV, + ARMCP::ARMCPModifier Modifier) { + return new ARMConstantPoolConstant((Type*)Type::getInt32Ty(GV->getContext()), + GV, 0, ARMCP::CPValue, 0, + Modifier, false); +} + +ARMConstantPoolConstant * +ARMConstantPoolConstant::Create(const Constant *C, unsigned ID, + ARMCP::ARMCPKind Kind, unsigned char PCAdj) { + return new ARMConstantPoolConstant(C, ID, Kind, PCAdj, + ARMCP::no_modifier, false); +} + +ARMConstantPoolConstant * +ARMConstantPoolConstant::Create(const Constant *C, unsigned ID, + ARMCP::ARMCPKind Kind, unsigned char PCAdj, + ARMCP::ARMCPModifier Modifier, + bool AddCurrentAddress) { + return new ARMConstantPoolConstant(C, ID, Kind, PCAdj, Modifier, + AddCurrentAddress); +} + +const GlobalValue *ARMConstantPoolConstant::getGV() const { + return dyn_cast_or_null(CVal); +} + +const BlockAddress *ARMConstantPoolConstant::getBlockAddress() const { + return dyn_cast_or_null(CVal); +} + +int ARMConstantPoolConstant::getExistingMachineCPValue(MachineConstantPool *CP, + unsigned Alignment) { + unsigned AlignMask = Alignment - 1; + const std::vector Constants = CP->getConstants(); + for (unsigned i = 0, e = Constants.size(); i != e; ++i) { + if (Constants[i].isMachineConstantPoolEntry() && + (Constants[i].getAlignment() & AlignMask) == 0) { + ARMConstantPoolValue *CPV = + (ARMConstantPoolValue *)Constants[i].Val.MachineCPVal; + ARMConstantPoolConstant *APC = dyn_cast(CPV); + if (!APC) continue; + if (APC->CVal == CVal && equals(APC)) + return i; + } + } + + return -1; +} + +bool ARMConstantPoolConstant::hasSameValue(ARMConstantPoolValue *ACPV) { + const ARMConstantPoolConstant *ACPC = dyn_cast(ACPV); + return ACPC && ACPC->CVal == CVal && ARMConstantPoolValue::hasSameValue(ACPV); +} + +void ARMConstantPoolConstant::addSelectionDAGCSEId(FoldingSetNodeID &ID) { + ID.AddPointer(CVal); + ARMConstantPoolValue::addSelectionDAGCSEId(ID); +} + +void ARMConstantPoolConstant::print(raw_ostream &O) const { + O << CVal->getName(); + ARMConstantPoolValue::print(O); +} + +//===----------------------------------------------------------------------===// +// ARMConstantPoolSymbol +//===----------------------------------------------------------------------===// + +ARMConstantPoolSymbol::ARMConstantPoolSymbol(LLVMContext &C, const char *s, + unsigned id, + unsigned char PCAdj, + ARMCP::ARMCPModifier Modifier, + bool AddCurrentAddress) + : ARMConstantPoolValue(C, id, ARMCP::CPExtSymbol, PCAdj, Modifier, + AddCurrentAddress), + S(strdup(s)) {} + +ARMConstantPoolSymbol::~ARMConstantPoolSymbol() { + free((void*)S); +} + +ARMConstantPoolSymbol * +ARMConstantPoolSymbol::Create(LLVMContext &C, const char *s, + unsigned ID, unsigned char PCAdj) { + return new ARMConstantPoolSymbol(C, s, ID, PCAdj, ARMCP::no_modifier, false); +} + +static bool CPV_streq(const char *S1, const char *S2) { + if (S1 == S2) + return true; + if (S1 && S2 && strcmp(S1, S2) == 0) + return true; + return false; +} + +int ARMConstantPoolSymbol::getExistingMachineCPValue(MachineConstantPool *CP, + unsigned Alignment) { + unsigned AlignMask = Alignment - 1; + const std::vector Constants = CP->getConstants(); + for (unsigned i = 0, e = Constants.size(); i != e; ++i) { + if (Constants[i].isMachineConstantPoolEntry() && + (Constants[i].getAlignment() & AlignMask) == 0) { + ARMConstantPoolValue *CPV = + (ARMConstantPoolValue *)Constants[i].Val.MachineCPVal; + ARMConstantPoolSymbol *APS = dyn_cast(CPV); + if (!APS) continue; + + if (CPV_streq(APS->S, S) && equals(APS)) + return i; + } + } + + return -1; +} + +bool ARMConstantPoolSymbol::hasSameValue(ARMConstantPoolValue *ACPV) { + const ARMConstantPoolSymbol *ACPS = dyn_cast(ACPV); + return ACPS && CPV_streq(ACPS->S, S) && + ARMConstantPoolValue::hasSameValue(ACPV); +} + +void ARMConstantPoolSymbol::addSelectionDAGCSEId(FoldingSetNodeID &ID) { + ID.AddPointer(S); + ARMConstantPoolValue::addSelectionDAGCSEId(ID); +} + +void ARMConstantPoolSymbol::print(raw_ostream &O) const { + O << S; + ARMConstantPoolValue::print(O); +} + +//===----------------------------------------------------------------------===// +// ARMConstantPoolMBB +//===----------------------------------------------------------------------===// + +ARMConstantPoolMBB::ARMConstantPoolMBB(LLVMContext &C, + const MachineBasicBlock *mbb, + unsigned id, unsigned char PCAdj, + ARMCP::ARMCPModifier Modifier, + bool AddCurrentAddress) + : ARMConstantPoolValue(C, id, ARMCP::CPMachineBasicBlock, PCAdj, + Modifier, AddCurrentAddress), + MBB(mbb) {} + +ARMConstantPoolMBB *ARMConstantPoolMBB::Create(LLVMContext &C, + const MachineBasicBlock *mbb, + unsigned ID, + unsigned char PCAdj) { + return new ARMConstantPoolMBB(C, mbb, ID, PCAdj, ARMCP::no_modifier, false); +} + +int ARMConstantPoolMBB::getExistingMachineCPValue(MachineConstantPool *CP, + unsigned Alignment) { + unsigned AlignMask = Alignment - 1; + const std::vector Constants = CP->getConstants(); + for (unsigned i = 0, e = Constants.size(); i != e; ++i) { + if (Constants[i].isMachineConstantPoolEntry() && + (Constants[i].getAlignment() & AlignMask) == 0) { + ARMConstantPoolValue *CPV = + (ARMConstantPoolValue *)Constants[i].Val.MachineCPVal; + ARMConstantPoolMBB *APMBB = dyn_cast(CPV); + if (!APMBB) continue; + + if (APMBB->MBB == MBB && equals(APMBB)) + return i; + } + } + + return -1; +} + +bool ARMConstantPoolMBB::hasSameValue(ARMConstantPoolValue *ACPV) { + const ARMConstantPoolMBB *ACPMBB = dyn_cast(ACPV); + return ACPMBB && ACPMBB->MBB == MBB && + ARMConstantPoolValue::hasSameValue(ACPV); +} + +void ARMConstantPoolMBB::addSelectionDAGCSEId(FoldingSetNodeID &ID) { + ID.AddPointer(MBB); + ARMConstantPoolValue::addSelectionDAGCSEId(ID); +} + +void ARMConstantPoolMBB::print(raw_ostream &O) const { + ARMConstantPoolValue::print(O); +} diff --git a/contrib/llvm/lib/Target/ARM/ARMConstantPoolValue.h b/contrib/llvm/lib/Target/ARM/ARMConstantPoolValue.h index d008811c4..0d0def32b 100644 --- a/contrib/llvm/lib/Target/ARM/ARMConstantPoolValue.h +++ b/contrib/llvm/lib/Target/ARM/ARMConstantPoolValue.h @@ -20,17 +20,19 @@ namespace llvm { -class Constant; class BlockAddress; +class Constant; class GlobalValue; class LLVMContext; +class MachineBasicBlock; namespace ARMCP { enum ARMCPKind { CPValue, CPExtSymbol, CPBlockAddress, - CPLSDA + CPLSDA, + CPMachineBasicBlock }; enum ARMCPModifier { @@ -47,8 +49,6 @@ namespace ARMCP { /// represent PC-relative displacement between the address of the load /// instruction and the constant being loaded, i.e. (&GV-(LPIC+8)). class ARMConstantPoolValue : public MachineConstantPoolValue { - const Constant *CVal; // Constant being loaded. - const char *S; // ExtSymbol being loaded. unsigned LabelId; // Label id of the load. ARMCP::ARMCPKind Kind; // Kind of constant. unsigned char PCAdjust; // Extra adjustment if constantpool is pc-relative. @@ -56,60 +56,54 @@ class ARMConstantPoolValue : public MachineConstantPoolValue { ARMCP::ARMCPModifier Modifier; // GV modifier i.e. (&GV(modifier)-(LPIC+8)) bool AddCurrentAddress; +protected: + ARMConstantPoolValue(Type *Ty, unsigned id, ARMCP::ARMCPKind Kind, + unsigned char PCAdj, ARMCP::ARMCPModifier Modifier, + bool AddCurrentAddress); + + ARMConstantPoolValue(LLVMContext &C, unsigned id, ARMCP::ARMCPKind Kind, + unsigned char PCAdj, ARMCP::ARMCPModifier Modifier, + bool AddCurrentAddress); public: - ARMConstantPoolValue(const Constant *cval, unsigned id, - ARMCP::ARMCPKind Kind = ARMCP::CPValue, - unsigned char PCAdj = 0, - ARMCP::ARMCPModifier Modifier = ARMCP::no_modifier, - bool AddCurrentAddress = false); - ARMConstantPoolValue(LLVMContext &C, const char *s, unsigned id, - unsigned char PCAdj = 0, - ARMCP::ARMCPModifier Modifier = ARMCP::no_modifier, - bool AddCurrentAddress = false); - ARMConstantPoolValue(const GlobalValue *GV, ARMCP::ARMCPModifier Modifier); - ARMConstantPoolValue(); - ~ARMConstantPoolValue(); + virtual ~ARMConstantPoolValue(); - const GlobalValue *getGV() const; - const char *getSymbol() const { return S; } - const BlockAddress *getBlockAddress() const; ARMCP::ARMCPModifier getModifier() const { return Modifier; } - const char *getModifierText() const { - switch (Modifier) { - default: llvm_unreachable("Unknown modifier!"); - // FIXME: Are these case sensitive? It'd be nice to lower-case all the - // strings if that's legal. - case ARMCP::no_modifier: return "none"; - case ARMCP::TLSGD: return "tlsgd"; - case ARMCP::GOT: return "GOT"; - case ARMCP::GOTOFF: return "GOTOFF"; - case ARMCP::GOTTPOFF: return "gottpoff"; - case ARMCP::TPOFF: return "tpoff"; - } - } + const char *getModifierText() const; bool hasModifier() const { return Modifier != ARMCP::no_modifier; } + bool mustAddCurrentAddress() const { return AddCurrentAddress; } + unsigned getLabelId() const { return LabelId; } unsigned char getPCAdjustment() const { return PCAdjust; } + bool isGlobalValue() const { return Kind == ARMCP::CPValue; } bool isExtSymbol() const { return Kind == ARMCP::CPExtSymbol; } - bool isBlockAddress() { return Kind == ARMCP::CPBlockAddress; } - bool isLSDA() { return Kind == ARMCP::CPLSDA; } + bool isBlockAddress() const { return Kind == ARMCP::CPBlockAddress; } + bool isLSDA() const { return Kind == ARMCP::CPLSDA; } + bool isMachineBasicBlock() const{ return Kind == ARMCP::CPMachineBasicBlock; } virtual unsigned getRelocationInfo() const { return 2; } virtual int getExistingMachineCPValue(MachineConstantPool *CP, unsigned Alignment); - virtual void AddSelectionDAGCSEId(FoldingSetNodeID &ID); + virtual void addSelectionDAGCSEId(FoldingSetNodeID &ID); - /// hasSameValue - Return true if this ARM constpool value - /// can share the same constantpool entry as another ARM constpool value. - bool hasSameValue(ARMConstantPoolValue *ACPV); + /// hasSameValue - Return true if this ARM constpool value can share the same + /// constantpool entry as another ARM constpool value. + virtual bool hasSameValue(ARMConstantPoolValue *ACPV); + + bool equals(const ARMConstantPoolValue *A) const { + return this->LabelId == A->LabelId && + this->PCAdjust == A->PCAdjust && + this->Modifier == A->Modifier; + } + virtual void print(raw_ostream &O) const; void print(raw_ostream *O) const { if (O) print(*O); } - void print(raw_ostream &O) const; void dump() const; + + static bool classof(const ARMConstantPoolValue *) { return true; } }; inline raw_ostream &operator<<(raw_ostream &O, const ARMConstantPoolValue &V) { @@ -117,6 +111,123 @@ inline raw_ostream &operator<<(raw_ostream &O, const ARMConstantPoolValue &V) { return O; } +/// ARMConstantPoolConstant - ARM-specific constant pool values for Constants, +/// Functions, and BlockAddresses. +class ARMConstantPoolConstant : public ARMConstantPoolValue { + const Constant *CVal; // Constant being loaded. + + ARMConstantPoolConstant(const Constant *C, + unsigned ID, + ARMCP::ARMCPKind Kind, + unsigned char PCAdj, + ARMCP::ARMCPModifier Modifier, + bool AddCurrentAddress); + ARMConstantPoolConstant(Type *Ty, const Constant *C, + unsigned ID, + ARMCP::ARMCPKind Kind, + unsigned char PCAdj, + ARMCP::ARMCPModifier Modifier, + bool AddCurrentAddress); + +public: + static ARMConstantPoolConstant *Create(const Constant *C, unsigned ID); + static ARMConstantPoolConstant *Create(const GlobalValue *GV, + ARMCP::ARMCPModifier Modifier); + static ARMConstantPoolConstant *Create(const Constant *C, unsigned ID, + ARMCP::ARMCPKind Kind, + unsigned char PCAdj); + static ARMConstantPoolConstant *Create(const Constant *C, unsigned ID, + ARMCP::ARMCPKind Kind, + unsigned char PCAdj, + ARMCP::ARMCPModifier Modifier, + bool AddCurrentAddress); + + const GlobalValue *getGV() const; + const BlockAddress *getBlockAddress() const; + + virtual int getExistingMachineCPValue(MachineConstantPool *CP, + unsigned Alignment); + + /// hasSameValue - Return true if this ARM constpool value can share the same + /// constantpool entry as another ARM constpool value. + virtual bool hasSameValue(ARMConstantPoolValue *ACPV); + + virtual void addSelectionDAGCSEId(FoldingSetNodeID &ID); + + virtual void print(raw_ostream &O) const; + static bool classof(const ARMConstantPoolValue *APV) { + return APV->isGlobalValue() || APV->isBlockAddress() || APV->isLSDA(); + } + static bool classof(const ARMConstantPoolConstant *) { return true; } +}; + +/// ARMConstantPoolSymbol - ARM-specific constantpool values for external +/// symbols. +class ARMConstantPoolSymbol : public ARMConstantPoolValue { + const char *S; // ExtSymbol being loaded. + + ARMConstantPoolSymbol(LLVMContext &C, const char *s, unsigned id, + unsigned char PCAdj, ARMCP::ARMCPModifier Modifier, + bool AddCurrentAddress); + +public: + ~ARMConstantPoolSymbol(); + + static ARMConstantPoolSymbol *Create(LLVMContext &C, const char *s, + unsigned ID, unsigned char PCAdj); + + const char *getSymbol() const { return S; } + + virtual int getExistingMachineCPValue(MachineConstantPool *CP, + unsigned Alignment); + + virtual void addSelectionDAGCSEId(FoldingSetNodeID &ID); + + /// hasSameValue - Return true if this ARM constpool value can share the same + /// constantpool entry as another ARM constpool value. + virtual bool hasSameValue(ARMConstantPoolValue *ACPV); + + virtual void print(raw_ostream &O) const; + + static bool classof(const ARMConstantPoolValue *ACPV) { + return ACPV->isExtSymbol(); + } + static bool classof(const ARMConstantPoolSymbol *) { return true; } +}; + +/// ARMConstantPoolMBB - ARM-specific constantpool value of a machine basic +/// block. +class ARMConstantPoolMBB : public ARMConstantPoolValue { + const MachineBasicBlock *MBB; // Machine basic block. + + ARMConstantPoolMBB(LLVMContext &C, const MachineBasicBlock *mbb, unsigned id, + unsigned char PCAdj, ARMCP::ARMCPModifier Modifier, + bool AddCurrentAddress); + +public: + static ARMConstantPoolMBB *Create(LLVMContext &C, + const MachineBasicBlock *mbb, + unsigned ID, unsigned char PCAdj); + + const MachineBasicBlock *getMBB() const { return MBB; } + + virtual int getExistingMachineCPValue(MachineConstantPool *CP, + unsigned Alignment); + + virtual void addSelectionDAGCSEId(FoldingSetNodeID &ID); + + /// hasSameValue - Return true if this ARM constpool value can share the same + /// constantpool entry as another ARM constpool value. + virtual bool hasSameValue(ARMConstantPoolValue *ACPV); + + virtual void print(raw_ostream &O) const; + + static bool classof(const ARMConstantPoolValue *ACPV) { + return ACPV->isMachineBasicBlock(); + } + static bool classof(const ARMConstantPoolMBB *) { return true; } +}; + } // End llvm namespace #endif diff --git a/contrib/llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp b/contrib/llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp index 94b72fdb9..7872cb90f 100644 --- a/contrib/llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp +++ b/contrib/llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp @@ -16,19 +16,24 @@ #define DEBUG_TYPE "arm-pseudo" #include "ARM.h" -#include "ARMAddressingModes.h" #include "ARMBaseInstrInfo.h" #include "ARMBaseRegisterInfo.h" #include "ARMMachineFunctionInfo.h" #include "ARMRegisterInfo.h" +#include "MCTargetDesc/ARMAddressingModes.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/Target/TargetFrameLowering.h" #include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Support/CommandLine.h" #include "llvm/Support/raw_ostream.h" // FIXME: for debug only. remove! using namespace llvm; +static cl::opt +VerifyARMPseudo("verify-arm-pseudo-expand", cl::Hidden, + cl::desc("Verify machine code after expanding ARM pseudos")); + namespace { class ARMExpandPseudo : public MachineFunctionPass { public: @@ -741,8 +746,22 @@ bool ARMExpandPseudo::ExpandMI(MachineBasicBlock &MBB, MI.eraseFromParent(); return true; } - case ARM::MOVCCs: { - BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::MOVs), + case ARM::MOVCCsi: { + BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::MOVsi), + (MI.getOperand(1).getReg())) + .addReg(MI.getOperand(2).getReg(), + getKillRegState(MI.getOperand(2).isKill())) + .addImm(MI.getOperand(3).getImm()) + .addImm(MI.getOperand(4).getImm()) // 'pred' + .addReg(MI.getOperand(5).getReg()) + .addReg(0); // 's' bit + + MI.eraseFromParent(); + return true; + } + + case ARM::MOVCCsr: { + BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::MOVsr), (MI.getOperand(1).getReg())) .addReg(MI.getOperand(2).getReg(), getKillRegState(MI.getOperand(2).isKill())) @@ -837,10 +856,9 @@ bool ARMExpandPseudo::ExpandMI(MachineBasicBlock &MBB, case ARM::MOVsrl_flag: case ARM::MOVsra_flag: { // These are just fancy MOVs insructions. - AddDefaultPred(BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::MOVs), + AddDefaultPred(BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::MOVsi), MI.getOperand(0).getReg()) .addOperand(MI.getOperand(1)) - .addReg(0) .addImm(ARM_AM::getSORegOpc((Opcode == ARM::MOVsrl_flag ? ARM_AM::lsr : ARM_AM::asr), 1))) @@ -851,10 +869,9 @@ bool ARMExpandPseudo::ExpandMI(MachineBasicBlock &MBB, case ARM::RRX: { // This encodes as "MOVs Rd, Rm, rrx MachineInstrBuilder MIB = - AddDefaultPred(BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::MOVs), + AddDefaultPred(BuildMI(MBB, MBBI, MI.getDebugLoc(),TII->get(ARM::MOVsi), MI.getOperand(0).getReg()) .addOperand(MI.getOperand(1)) - .addOperand(MI.getOperand(1)) .addImm(ARM_AM::getSORegOpc(ARM_AM::rrx, 0))) .addReg(0); TransferImpOps(MI, MIB, MIB); @@ -953,34 +970,6 @@ bool ARMExpandPseudo::ExpandMI(MachineBasicBlock &MBB, ExpandMOV32BitImm(MBB, MBBI); return true; - case ARM::VMOVQQ: { - unsigned DstReg = MI.getOperand(0).getReg(); - bool DstIsDead = MI.getOperand(0).isDead(); - unsigned EvenDst = TRI->getSubReg(DstReg, ARM::qsub_0); - unsigned OddDst = TRI->getSubReg(DstReg, ARM::qsub_1); - unsigned SrcReg = MI.getOperand(1).getReg(); - bool SrcIsKill = MI.getOperand(1).isKill(); - unsigned EvenSrc = TRI->getSubReg(SrcReg, ARM::qsub_0); - unsigned OddSrc = TRI->getSubReg(SrcReg, ARM::qsub_1); - MachineInstrBuilder Even = - AddDefaultPred(BuildMI(MBB, MBBI, MI.getDebugLoc(), - TII->get(ARM::VORRq)) - .addReg(EvenDst, - RegState::Define | getDeadRegState(DstIsDead)) - .addReg(EvenSrc, getKillRegState(SrcIsKill)) - .addReg(EvenSrc, getKillRegState(SrcIsKill))); - MachineInstrBuilder Odd = - AddDefaultPred(BuildMI(MBB, MBBI, MI.getDebugLoc(), - TII->get(ARM::VORRq)) - .addReg(OddDst, - RegState::Define | getDeadRegState(DstIsDead)) - .addReg(OddSrc, getKillRegState(SrcIsKill)) - .addReg(OddSrc, getKillRegState(SrcIsKill))); - TransferImpOps(MI, Even, Odd); - MI.eraseFromParent(); - return true; - } - case ARM::VLDMQIA: { unsigned NewOpc = ARM::VLDMDIA; MachineInstrBuilder MIB = @@ -1316,6 +1305,8 @@ bool ARMExpandPseudo::runOnMachineFunction(MachineFunction &MF) { for (MachineFunction::iterator MFI = MF.begin(), E = MF.end(); MFI != E; ++MFI) Modified |= ExpandMBB(*MFI); + if (VerifyARMPseudo) + MF.verify(this, "After expanding ARM pseudo instructions."); return Modified; } diff --git a/contrib/llvm/lib/Target/ARM/ARMFastISel.cpp b/contrib/llvm/lib/Target/ARM/ARMFastISel.cpp index f469d7efe..9bc7ef21d 100644 --- a/contrib/llvm/lib/Target/ARM/ARMFastISel.cpp +++ b/contrib/llvm/lib/Target/ARM/ARMFastISel.cpp @@ -14,13 +14,13 @@ //===----------------------------------------------------------------------===// #include "ARM.h" -#include "ARMAddressingModes.h" #include "ARMBaseInstrInfo.h" #include "ARMCallingConv.h" #include "ARMRegisterInfo.h" #include "ARMTargetMachine.h" #include "ARMSubtarget.h" #include "ARMConstantPoolValue.h" +#include "MCTargetDesc/ARMAddressingModes.h" #include "llvm/CallingConv.h" #include "llvm/DerivedTypes.h" #include "llvm/GlobalVariable.h" @@ -171,8 +171,8 @@ class ARMFastISel : public FastISel { // Utility routines. private: - bool isTypeLegal(const Type *Ty, MVT &VT); - bool isLoadTypeLegal(const Type *Ty, MVT &VT); + bool isTypeLegal(Type *Ty, MVT &VT); + bool isLoadTypeLegal(Type *Ty, MVT &VT); bool ARMEmitLoad(EVT VT, unsigned &ResultReg, Address &Addr); bool ARMEmitStore(EVT VT, unsigned SrcReg, Address &Addr); bool ARMComputeAddress(const Value *Obj, Address &Addr); @@ -502,11 +502,19 @@ unsigned ARMFastISel::ARMMaterializeFP(const ConstantFP *CFP, EVT VT) { // This checks to see if we can use VFP3 instructions to materialize // a constant, otherwise we have to go through the constant pool. if (TLI.isFPImmLegal(Val, VT)) { - unsigned Opc = is64bit ? ARM::FCONSTD : ARM::FCONSTS; + int Imm; + unsigned Opc; + if (is64bit) { + Imm = ARM_AM::getFP64Imm(Val); + Opc = ARM::FCONSTD; + } else { + Imm = ARM_AM::getFP32Imm(Val); + Opc = ARM::FCONSTS; + } unsigned DestReg = createResultReg(TLI.getRegClassFor(VT)); AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(Opc), DestReg) - .addFPImm(CFP)); + .addImm(Imm)); return DestReg; } @@ -590,8 +598,9 @@ unsigned ARMFastISel::ARMMaterializeGV(const GlobalValue *GV, EVT VT) { // Grab index. unsigned PCAdj = (RelocM != Reloc::PIC_) ? 0 : (Subtarget->isThumb() ? 4 : 8); unsigned Id = AFI->createPICLabelUId(); - ARMConstantPoolValue *CPV = new ARMConstantPoolValue(GV, Id, - ARMCP::CPValue, PCAdj); + ARMConstantPoolValue *CPV = ARMConstantPoolConstant::Create(GV, Id, + ARMCP::CPValue, + PCAdj); unsigned Idx = MCP.getConstantPoolIndex(CPV, Align); // Load value. @@ -615,8 +624,8 @@ unsigned ARMFastISel::ARMMaterializeGV(const GlobalValue *GV, EVT VT) { if (Subtarget->GVIsIndirectSymbol(GV, RelocM)) { unsigned NewDestReg = createResultReg(TLI.getRegClassFor(VT)); if (isThumb) - MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(ARM::t2LDRi12), - NewDestReg) + MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, + TII.get(ARM::t2LDRi12), NewDestReg) .addReg(DestReg) .addImm(0); else @@ -673,7 +682,7 @@ unsigned ARMFastISel::TargetMaterializeAlloca(const AllocaInst *AI) { return 0; } -bool ARMFastISel::isTypeLegal(const Type *Ty, MVT &VT) { +bool ARMFastISel::isTypeLegal(Type *Ty, MVT &VT) { EVT evt = TLI.getValueType(Ty, true); // Only handle simple types. @@ -685,7 +694,7 @@ bool ARMFastISel::isTypeLegal(const Type *Ty, MVT &VT) { return TLI.isTypeLegal(VT); } -bool ARMFastISel::isLoadTypeLegal(const Type *Ty, MVT &VT) { +bool ARMFastISel::isLoadTypeLegal(Type *Ty, MVT &VT) { if (isTypeLegal(Ty, VT)) return true; // If this is a type than can be sign or zero-extended to a basic operation @@ -714,7 +723,7 @@ bool ARMFastISel::ARMComputeAddress(const Value *Obj, Address &Addr) { U = C; } - if (const PointerType *Ty = dyn_cast(Obj->getType())) + if (PointerType *Ty = dyn_cast(Obj->getType())) if (Ty->getAddressSpace() > 255) // Fast instruction selection doesn't support the special // address spaces. @@ -749,7 +758,7 @@ bool ARMFastISel::ARMComputeAddress(const Value *Obj, Address &Addr) { for (User::const_op_iterator i = U->op_begin() + 1, e = U->op_end(); i != e; ++i, ++GTI) { const Value *Op = *i; - if (const StructType *STy = dyn_cast(*GTI)) { + if (StructType *STy = dyn_cast(*GTI)) { const StructLayout *SL = TD.getStructLayout(STy); unsigned Idx = cast(Op)->getZExtValue(); TmpOffset += SL->getElementOffset(Idx); @@ -946,6 +955,10 @@ bool ARMFastISel::ARMEmitLoad(EVT VT, unsigned &ResultReg, Address &Addr) { } bool ARMFastISel::SelectLoad(const Instruction *I) { + // Atomic loads need special handling. + if (cast(I)->isAtomic()) + return false; + // Verify we have a legal type before going any further. MVT VT; if (!isLoadTypeLegal(I->getType(), VT)) @@ -1008,6 +1021,10 @@ bool ARMFastISel::SelectStore(const Instruction *I) { Value *Op0 = I->getOperand(0); unsigned SrcReg = 0; + // Atomic stores need special handling. + if (cast(I)->isAtomic()) + return false; + // Verify we have a legal type before going any further. MVT VT; if (!isLoadTypeLegal(I->getOperand(0)->getType(), VT)) @@ -1085,7 +1102,7 @@ bool ARMFastISel::SelectBranch(const Instruction *I) { // TODO: Factor this out. if (const CmpInst *CI = dyn_cast(BI->getCondition())) { MVT SourceVT; - const Type *Ty = CI->getOperand(0)->getType(); + Type *Ty = CI->getOperand(0)->getType(); if (CI->hasOneUse() && (CI->getParent() == I->getParent()) && isTypeLegal(Ty, SourceVT)) { bool isFloat = (Ty->isDoubleTy() || Ty->isFloatTy()); @@ -1201,7 +1218,7 @@ bool ARMFastISel::SelectCmp(const Instruction *I) { const CmpInst *CI = cast(I); MVT VT; - const Type *Ty = CI->getOperand(0)->getType(); + Type *Ty = CI->getOperand(0)->getType(); if (!isTypeLegal(Ty, VT)) return false; @@ -1309,7 +1326,7 @@ bool ARMFastISel::SelectSIToFP(const Instruction *I) { if (!Subtarget->hasVFP2()) return false; MVT DstVT; - const Type *Ty = I->getType(); + Type *Ty = I->getType(); if (!isTypeLegal(Ty, DstVT)) return false; @@ -1328,7 +1345,7 @@ bool ARMFastISel::SelectSIToFP(const Instruction *I) { unsigned Opc; if (Ty->isFloatTy()) Opc = ARM::VSITOS; else if (Ty->isDoubleTy()) Opc = ARM::VSITOD; - else return 0; + else return false; unsigned ResultReg = createResultReg(TLI.getRegClassFor(DstVT)); AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(Opc), @@ -1343,7 +1360,7 @@ bool ARMFastISel::SelectFPToSI(const Instruction *I) { if (!Subtarget->hasVFP2()) return false; MVT DstVT; - const Type *RetTy = I->getType(); + Type *RetTy = I->getType(); if (!isTypeLegal(RetTy, DstVT)) return false; @@ -1351,10 +1368,10 @@ bool ARMFastISel::SelectFPToSI(const Instruction *I) { if (Op == 0) return false; unsigned Opc; - const Type *OpTy = I->getOperand(0)->getType(); + Type *OpTy = I->getOperand(0)->getType(); if (OpTy->isFloatTy()) Opc = ARM::VTOSIZS; else if (OpTy->isDoubleTy()) Opc = ARM::VTOSIZD; - else return 0; + else return false; // f64->s32 or f32->s32 both need an intermediate f32 reg. unsigned ResultReg = createResultReg(TLI.getRegClassFor(MVT::f32)); @@ -1401,7 +1418,7 @@ bool ARMFastISel::SelectSelect(const Instruction *I) { bool ARMFastISel::SelectSDiv(const Instruction *I) { MVT VT; - const Type *Ty = I->getType(); + Type *Ty = I->getType(); if (!isTypeLegal(Ty, VT)) return false; @@ -1429,7 +1446,7 @@ bool ARMFastISel::SelectSDiv(const Instruction *I) { bool ARMFastISel::SelectSRem(const Instruction *I) { MVT VT; - const Type *Ty = I->getType(); + Type *Ty = I->getType(); if (!isTypeLegal(Ty, VT)) return false; @@ -1456,7 +1473,7 @@ bool ARMFastISel::SelectBinaryOp(const Instruction *I, unsigned ISDOpcode) { // operations, but can't figure out how to. Just use the vfp instructions // if we have them. // FIXME: It'd be nice to use NEON instructions. - const Type *Ty = I->getType(); + Type *Ty = I->getType(); bool isFloat = (Ty->isDoubleTy() || Ty->isFloatTy()); if (isFloat && !Subtarget->hasVFP2()) return false; @@ -1711,7 +1728,7 @@ bool ARMFastISel::SelectRet(const Instruction *I) { // Analyze operands of the call, assigning locations to each operand. SmallVector ValLocs; - CCState CCInfo(CC, F.isVarArg(), *FuncInfo.MF, TM, ValLocs, I->getContext()); + CCState CCInfo(CC, F.isVarArg(), *FuncInfo.MF, TM, ValLocs,I->getContext()); CCInfo.AnalyzeReturn(Outs, CCAssignFnForCall(CC, true /* is Ret */)); const Value *RV = Ret->getOperand(0); @@ -1778,7 +1795,7 @@ bool ARMFastISel::ARMEmitLibcall(const Instruction *I, RTLIB::Libcall Call) { CallingConv::ID CC = TLI.getLibcallCallingConv(Call); // Handle *simple* calls for now. - const Type *RetTy = I->getType(); + Type *RetTy = I->getType(); MVT RetVT; if (RetTy->isVoidTy()) RetVT = MVT::isVoid; @@ -1802,7 +1819,7 @@ bool ARMFastISel::ARMEmitLibcall(const Instruction *I, RTLIB::Libcall Call) { unsigned Arg = getRegForValue(Op); if (Arg == 0) return false; - const Type *ArgTy = Op->getType(); + Type *ArgTy = Op->getType(); MVT ArgVT; if (!isTypeLegal(ArgTy, ArgVT)) return false; @@ -1870,13 +1887,13 @@ bool ARMFastISel::SelectCall(const Instruction *I) { // TODO: Avoid some calling conventions? // Let SDISel handle vararg functions. - const PointerType *PT = cast(CS.getCalledValue()->getType()); - const FunctionType *FTy = cast(PT->getElementType()); + PointerType *PT = cast(CS.getCalledValue()->getType()); + FunctionType *FTy = cast(PT->getElementType()); if (FTy->isVarArg()) return false; // Handle *simple* calls for now. - const Type *RetTy = I->getType(); + Type *RetTy = I->getType(); MVT RetVT; if (RetTy->isVoidTy()) RetVT = MVT::isVoid; @@ -1915,7 +1932,7 @@ bool ARMFastISel::SelectCall(const Instruction *I) { CS.paramHasAttr(AttrInd, Attribute::ByVal)) return false; - const Type *ArgTy = (*i)->getType(); + Type *ArgTy = (*i)->getType(); MVT ArgVT; if (!isTypeLegal(ArgTy, ArgVT)) return false; @@ -1969,9 +1986,9 @@ bool ARMFastISel::SelectIntCast(const Instruction *I) { // On ARM, in general, integer casts don't involve legal types; this code // handles promotable integers. The high bits for a type smaller than // the register size are assumed to be undefined. - const Type *DestTy = I->getType(); + Type *DestTy = I->getType(); Value *Op = I->getOperand(0); - const Type *SrcTy = Op->getType(); + Type *SrcTy = Op->getType(); EVT SrcVT, DestVT; SrcVT = TLI.getValueType(SrcTy, true); @@ -2002,16 +2019,18 @@ bool ARMFastISel::SelectIntCast(const Instruction *I) { switch (SrcVT.getSimpleVT().SimpleTy) { default: return false; case MVT::i16: + if (!Subtarget->hasV6Ops()) return false; if (isZext) - Opc = isThumb ? ARM::t2UXTHr : ARM::UXTHr; + Opc = isThumb ? ARM::t2UXTH : ARM::UXTH; else - Opc = isThumb ? ARM::t2SXTHr : ARM::SXTHr; + Opc = isThumb ? ARM::t2SXTH : ARM::SXTH; break; case MVT::i8: + if (!Subtarget->hasV6Ops()) return false; if (isZext) - Opc = isThumb ? ARM::t2UXTBr : ARM::UXTBr; + Opc = isThumb ? ARM::t2UXTB : ARM::UXTB; else - Opc = isThumb ? ARM::t2SXTBr : ARM::SXTBr; + Opc = isThumb ? ARM::t2SXTB : ARM::SXTB; break; case MVT::i1: if (isZext) { @@ -2033,6 +2052,8 @@ bool ARMFastISel::SelectIntCast(const Instruction *I) { .addReg(SrcReg); if (isBoolZext) MIB.addImm(1); + else + MIB.addImm(0); AddOptionalDefs(MIB); UpdateValueMap(I, DestReg); return true; diff --git a/contrib/llvm/lib/Target/ARM/ARMFrameLowering.cpp b/contrib/llvm/lib/Target/ARM/ARMFrameLowering.cpp index 381b40451..2d1de6fe8 100644 --- a/contrib/llvm/lib/Target/ARM/ARMFrameLowering.cpp +++ b/contrib/llvm/lib/Target/ARM/ARMFrameLowering.cpp @@ -12,10 +12,10 @@ //===----------------------------------------------------------------------===// #include "ARMFrameLowering.h" -#include "ARMAddressingModes.h" #include "ARMBaseInstrInfo.h" #include "ARMBaseRegisterInfo.h" #include "ARMMachineFunctionInfo.h" +#include "MCTargetDesc/ARMAddressingModes.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineInstrBuilder.h" @@ -93,7 +93,8 @@ static bool isCSRestore(MachineInstr *MI, return false; return true; } - if ((MI->getOpcode() == ARM::LDR_POST || + if ((MI->getOpcode() == ARM::LDR_POST_IMM || + MI->getOpcode() == ARM::LDR_POST_REG || MI->getOpcode() == ARM::t2LDR_POST) && isCalleeSavedRegister(MI->getOperand(0).getReg(), CSRegs) && MI->getOperand(1).getReg() == ARM::SP) @@ -413,6 +414,9 @@ void ARMFrameLowering::emitEpilogue(MachineFunction &MF, MIB.addExternalSymbol(JumpTarget.getSymbolName(), JumpTarget.getTargetFlags()); } + + // Add the default predicate in Thumb mode. + if (STI.isThumb()) MIB.addImm(ARMCC::AL).addReg(0); } else if (RetOpcode == ARM::TCRETURNri) { BuildMI(MBB, MBBI, dl, TII.get(STI.isThumb() ? ARM::tTAILJMPr : ARM::TAILJMPr)). @@ -502,7 +506,7 @@ ARMFrameLowering::ResolveFrameIndexReference(const MachineFunction &MF, } } } else if (AFI->isThumb2Function()) { - // Use add , sp, # + // Use add , sp, # // ldr , [sp, #] // if at all possible to save space. if (Offset >= 0 && (Offset & 3) == 0 && Offset <= 1020) @@ -587,14 +591,8 @@ void ARMFrameLowering::emitPushInst(MachineBasicBlock &MBB, MachineInstrBuilder MIB = BuildMI(MBB, MI, DL, TII.get(StrOpc), ARM::SP) .addReg(Regs[0].first, getKillRegState(Regs[0].second)) - .addReg(ARM::SP).setMIFlags(MIFlags); - // ARM mode needs an extra reg0 here due to addrmode2. Will go away once - // that refactoring is complete (eventually). - if (StrOpc == ARM::STR_PRE) { - MIB.addReg(0); - MIB.addImm(ARM_AM::getAM2Opc(ARM_AM::sub, 4, ARM_AM::no_shift)); - } else - MIB.addImm(-4); + .addReg(ARM::SP).setMIFlags(MIFlags) + .addImm(-4); AddDefaultPred(MIB); } Regs.clear(); @@ -651,8 +649,10 @@ void ARMFrameLowering::emitPopInst(MachineBasicBlock &MBB, .addReg(ARM::SP)); for (unsigned i = 0, e = Regs.size(); i < e; ++i) MIB.addReg(Regs[i], getDefRegState(true)); - if (DeleteRet) + if (DeleteRet) { + MIB->copyImplicitOps(&*MI); MI->eraseFromParent(); + } MI = MIB; } else if (Regs.size() == 1) { // If we adjusted the reg to PC from LR above, switch it back here. We @@ -665,7 +665,7 @@ void ARMFrameLowering::emitPopInst(MachineBasicBlock &MBB, .addReg(ARM::SP); // ARM mode needs an extra reg0 here due to addrmode2. Will go away once // that refactoring is complete (eventually). - if (LdrOpc == ARM::LDR_POST) { + if (LdrOpc == ARM::LDR_POST_REG || LdrOpc == ARM::LDR_POST_IMM) { MIB.addReg(0); MIB.addImm(ARM_AM::getAM2Opc(ARM_AM::add, 4, ARM_AM::no_shift)); } else @@ -687,7 +687,8 @@ bool ARMFrameLowering::spillCalleeSavedRegisters(MachineBasicBlock &MBB, ARMFunctionInfo *AFI = MF.getInfo(); unsigned PushOpc = AFI->isThumbFunction() ? ARM::t2STMDB_UPD : ARM::STMDB_UPD; - unsigned PushOneOpc = AFI->isThumbFunction() ? ARM::t2STR_PRE : ARM::STR_PRE; + unsigned PushOneOpc = AFI->isThumbFunction() ? + ARM::t2STR_PRE : ARM::STR_PRE_IMM; unsigned FltOpc = ARM::VSTMDDB_UPD; emitPushInst(MBB, MI, CSI, PushOpc, PushOneOpc, false, &isARMArea1Register, MachineInstr::FrameSetup); @@ -711,7 +712,7 @@ bool ARMFrameLowering::restoreCalleeSavedRegisters(MachineBasicBlock &MBB, bool isVarArg = AFI->getVarArgsRegSaveSize() > 0; unsigned PopOpc = AFI->isThumbFunction() ? ARM::t2LDMIA_UPD : ARM::LDMIA_UPD; - unsigned LdrOpc = AFI->isThumbFunction() ? ARM::t2LDR_POST : ARM::LDR_POST; + unsigned LdrOpc = AFI->isThumbFunction() ? ARM::t2LDR_POST :ARM::LDR_POST_IMM; unsigned FltOpc = ARM::VLDMDIA_UPD; emitPopInst(MBB, MI, CSI, FltOpc, 0, isVarArg, true, &isARMArea3Register); emitPopInst(MBB, MI, CSI, PopOpc, LdrOpc, isVarArg, false, diff --git a/contrib/llvm/lib/Target/ARM/ARMGlobalMerge.cpp b/contrib/llvm/lib/Target/ARM/ARMGlobalMerge.cpp index 8d77b2d83..5f863ea24 100644 --- a/contrib/llvm/lib/Target/ARM/ARMGlobalMerge.cpp +++ b/contrib/llvm/lib/Target/ARM/ARMGlobalMerge.cpp @@ -100,8 +100,8 @@ namespace { GlobalCmp(const TargetData *td) : TD(td) { } bool operator()(const GlobalVariable *GV1, const GlobalVariable *GV2) { - const Type *Ty1 = cast(GV1->getType())->getElementType(); - const Type *Ty2 = cast(GV2->getType())->getElementType(); + Type *Ty1 = cast(GV1->getType())->getElementType(); + Type *Ty2 = cast(GV2->getType())->getElementType(); return (TD->getTypeAllocSize(Ty1) < TD->getTypeAllocSize(Ty2)); } @@ -123,7 +123,7 @@ bool ARMGlobalMerge::doMerge(SmallVectorImpl &Globals, // FIXME: Find better heuristics std::stable_sort(Globals.begin(), Globals.end(), GlobalCmp(TD)); - const Type *Int32Ty = Type::getInt32Ty(M.getContext()); + Type *Int32Ty = Type::getInt32Ty(M.getContext()); for (size_t i = 0, e = Globals.size(); i != e; ) { size_t j = 0; @@ -150,7 +150,7 @@ bool ARMGlobalMerge::doMerge(SmallVectorImpl &Globals, ConstantInt::get(Int32Ty, 0), ConstantInt::get(Int32Ty, k-i) }; - Constant *GEP = ConstantExpr::getInBoundsGetElementPtr(MergedGV, Idx, 2); + Constant *GEP = ConstantExpr::getInBoundsGetElementPtr(MergedGV, Idx); Globals[k]->replaceAllUsesWith(GEP); Globals[k]->eraseFromParent(); } @@ -176,7 +176,7 @@ bool ARMGlobalMerge::doInitialization(Module &M) { // Ignore fancy-aligned globals for now. unsigned Alignment = I->getAlignment(); - const Type *Ty = I->getType()->getElementType(); + Type *Ty = I->getType()->getElementType(); if (Alignment > TD->getABITypeAlignment(Ty)) continue; diff --git a/contrib/llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp b/contrib/llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp index 2c9481b86..5ee009c04 100644 --- a/contrib/llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp +++ b/contrib/llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp @@ -14,8 +14,8 @@ #define DEBUG_TYPE "arm-isel" #include "ARM.h" #include "ARMBaseInstrInfo.h" -#include "ARMAddressingModes.h" #include "ARMTargetMachine.h" +#include "MCTargetDesc/ARMAddressingModes.h" #include "llvm/CallingConv.h" #include "llvm/Constants.h" #include "llvm/DerivedTypes.h" @@ -47,6 +47,11 @@ CheckVMLxHazard("check-vmlx-hazard", cl::Hidden, cl::desc("Check fp vmla / vmls hazard at isel time"), cl::init(true)); +static cl::opt +DisableARMIntABS("disable-arm-int-abs", cl::Hidden, + cl::desc("Enable / disable ARM integer abs transform"), + cl::init(false)); + //===--------------------------------------------------------------------===// /// ARMDAGToDAGISel - ARM specific code to select ARM machine /// instructions for SelectionDAG operations. @@ -90,13 +95,20 @@ public: bool hasNoVMLxHazardUse(SDNode *N) const; bool isShifterOpProfitable(const SDValue &Shift, ARM_AM::ShiftOpc ShOpcVal, unsigned ShAmt); - bool SelectShifterOperandReg(SDValue N, SDValue &A, + bool SelectRegShifterOperand(SDValue N, SDValue &A, SDValue &B, SDValue &C, bool CheckProfitability = true); - bool SelectShiftShifterOperandReg(SDValue N, SDValue &A, + bool SelectImmShifterOperand(SDValue N, SDValue &A, + SDValue &B, bool CheckProfitability = true); + bool SelectShiftRegShifterOperand(SDValue N, SDValue &A, SDValue &B, SDValue &C) { // Don't apply the profitability check - return SelectShifterOperandReg(N, A, B, C, false); + return SelectRegShifterOperand(N, A, B, C, false); + } + bool SelectShiftImmShifterOperand(SDValue N, SDValue &A, + SDValue &B) { + // Don't apply the profitability check + return SelectImmShifterOperand(N, A, B, false); } bool SelectAddrModeImm12(SDValue N, SDValue &Base, SDValue &OffImm); @@ -122,8 +134,13 @@ public: return true; } - bool SelectAddrMode2Offset(SDNode *Op, SDValue N, + bool SelectAddrMode2OffsetReg(SDNode *Op, SDValue N, SDValue &Offset, SDValue &Opc); + bool SelectAddrMode2OffsetImm(SDNode *Op, SDValue N, + SDValue &Offset, SDValue &Opc); + bool SelectAddrMode2OffsetImmPre(SDNode *Op, SDValue N, + SDValue &Offset, SDValue &Opc); + bool SelectAddrOffsetNone(SDValue N, SDValue &Base); bool SelectAddrMode3(SDValue N, SDValue &Base, SDValue &Offset, SDValue &Opc); bool SelectAddrMode3Offset(SDNode *Op, SDValue N, @@ -240,8 +257,13 @@ private: ARMCC::CondCodes CCVal, SDValue CCR, SDValue InFlag); + // Select special operations if node forms integer ABS pattern + SDNode *SelectABSOp(SDNode *N); + SDNode *SelectConcatVector(SDNode *N); + SDNode *SelectAtomic64(SDNode *Node, unsigned Opc); + /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for /// inline asm expressions. virtual bool SelectInlineAsmMemoryOperand(const SDValue &Op, @@ -291,10 +313,10 @@ static bool isOpcWithIntImmediate(SDNode *N, unsigned Opc, unsigned& Imm) { /// (N * Scale) where (N in [\arg RangeMin, \arg RangeMax). /// /// \param ScaledConstant [out] - On success, the pre-scaled constant value. -static bool isScaledConstantInRange(SDValue Node, unsigned Scale, +static bool isScaledConstantInRange(SDValue Node, int Scale, int RangeMin, int RangeMax, int &ScaledConstant) { - assert(Scale && "Invalid scale!"); + assert(Scale > 0 && "Invalid scale!"); // Check that this is a constant. const ConstantSDNode *C = dyn_cast(Node); @@ -365,7 +387,30 @@ bool ARMDAGToDAGISel::isShifterOpProfitable(const SDValue &Shift, return ShOpcVal == ARM_AM::lsl && ShAmt == 2; } -bool ARMDAGToDAGISel::SelectShifterOperandReg(SDValue N, +bool ARMDAGToDAGISel::SelectImmShifterOperand(SDValue N, + SDValue &BaseReg, + SDValue &Opc, + bool CheckProfitability) { + if (DisableShifterOp) + return false; + + ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode()); + + // Don't match base register only case. That is matched to a separate + // lower complexity pattern with explicit register operand. + if (ShOpcVal == ARM_AM::no_shift) return false; + + BaseReg = N.getOperand(0); + unsigned ShImmVal = 0; + ConstantSDNode *RHS = dyn_cast(N.getOperand(1)); + if (!RHS) return false; + ShImmVal = RHS->getZExtValue() & 31; + Opc = CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal), + MVT::i32); + return true; +} + +bool ARMDAGToDAGISel::SelectRegShifterOperand(SDValue N, SDValue &BaseReg, SDValue &ShReg, SDValue &Opc, @@ -373,7 +418,7 @@ bool ARMDAGToDAGISel::SelectShifterOperandReg(SDValue N, if (DisableShifterOp) return false; - ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N); + ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode()); // Don't match base register only case. That is matched to a separate // lower complexity pattern with explicit register operand. @@ -381,19 +426,18 @@ bool ARMDAGToDAGISel::SelectShifterOperandReg(SDValue N, BaseReg = N.getOperand(0); unsigned ShImmVal = 0; - if (ConstantSDNode *RHS = dyn_cast(N.getOperand(1))) { - ShReg = CurDAG->getRegister(0, MVT::i32); - ShImmVal = RHS->getZExtValue() & 31; - } else { - ShReg = N.getOperand(1); - if (CheckProfitability && !isShifterOpProfitable(N, ShOpcVal, ShImmVal)) - return false; - } + ConstantSDNode *RHS = dyn_cast(N.getOperand(1)); + if (RHS) return false; + + ShReg = N.getOperand(1); + if (CheckProfitability && !isShifterOpProfitable(N, ShOpcVal, ShImmVal)) + return false; Opc = CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal), MVT::i32); return true; } + bool ARMDAGToDAGISel::SelectAddrModeImm12(SDValue N, SDValue &Base, SDValue &OffImm) { @@ -483,13 +527,10 @@ bool ARMDAGToDAGISel::SelectLdStSOReg(SDValue N, SDValue &Base, SDValue &Offset, return false; } - if (Subtarget->isCortexA9() && !N.hasOneUse()) - // Compute R +/- (R << N) and reuse it. - return false; - // Otherwise this is R +/- [possibly shifted] R. ARM_AM::AddrOpc AddSub = N.getOpcode() == ISD::SUB ? ARM_AM::sub:ARM_AM::add; - ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(1)); + ARM_AM::ShiftOpc ShOpcVal = + ARM_AM::getShiftOpcForNode(N.getOperand(1).getOpcode()); unsigned ShAmt = 0; Base = N.getOperand(0); @@ -515,16 +556,14 @@ bool ARMDAGToDAGISel::SelectLdStSOReg(SDValue N, SDValue &Base, SDValue &Offset, // Try matching (R shl C) + (R). if (N.getOpcode() != ISD::SUB && ShOpcVal == ARM_AM::no_shift && !(Subtarget->isCortexA9() || N.getOperand(0).hasOneUse())) { - ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(0)); + ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(0).getOpcode()); if (ShOpcVal != ARM_AM::no_shift) { // Check to see if the RHS of the shift is a constant, if not, we can't // fold it. if (ConstantSDNode *Sh = dyn_cast(N.getOperand(0).getOperand(1))) { ShAmt = Sh->getZExtValue(); - if (!Subtarget->isCortexA9() || - (N.hasOneUse() && - isShifterOpProfitable(N.getOperand(0), ShOpcVal, ShAmt))) { + if (isShifterOpProfitable(N.getOperand(0), ShOpcVal, ShAmt)) { Offset = N.getOperand(0).getOperand(0); Base = N.getOperand(1); } else { @@ -630,7 +669,8 @@ AddrMode2Type ARMDAGToDAGISel::SelectAddrMode2Worker(SDValue N, // Otherwise this is R +/- [possibly shifted] R. ARM_AM::AddrOpc AddSub = N.getOpcode() != ISD::SUB ? ARM_AM::add:ARM_AM::sub; - ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(1)); + ARM_AM::ShiftOpc ShOpcVal = + ARM_AM::getShiftOpcForNode(N.getOperand(1).getOpcode()); unsigned ShAmt = 0; Base = N.getOperand(0); @@ -656,16 +696,14 @@ AddrMode2Type ARMDAGToDAGISel::SelectAddrMode2Worker(SDValue N, // Try matching (R shl C) + (R). if (N.getOpcode() != ISD::SUB && ShOpcVal == ARM_AM::no_shift && !(Subtarget->isCortexA9() || N.getOperand(0).hasOneUse())) { - ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(0)); + ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(0).getOpcode()); if (ShOpcVal != ARM_AM::no_shift) { // Check to see if the RHS of the shift is a constant, if not, we can't // fold it. if (ConstantSDNode *Sh = dyn_cast(N.getOperand(0).getOperand(1))) { ShAmt = Sh->getZExtValue(); - if (!Subtarget->isCortexA9() || - (N.hasOneUse() && - isShifterOpProfitable(N.getOperand(0), ShOpcVal, ShAmt))) { + if (isShifterOpProfitable(N.getOperand(0), ShOpcVal, ShAmt)) { Offset = N.getOperand(0).getOperand(0); Base = N.getOperand(1); } else { @@ -683,7 +721,7 @@ AddrMode2Type ARMDAGToDAGISel::SelectAddrMode2Worker(SDValue N, return AM2_SHOP; } -bool ARMDAGToDAGISel::SelectAddrMode2Offset(SDNode *Op, SDValue N, +bool ARMDAGToDAGISel::SelectAddrMode2OffsetReg(SDNode *Op, SDValue N, SDValue &Offset, SDValue &Opc) { unsigned Opcode = Op->getOpcode(); ISD::MemIndexedMode AM = (Opcode == ISD::LOAD) @@ -692,16 +730,11 @@ bool ARMDAGToDAGISel::SelectAddrMode2Offset(SDNode *Op, SDValue N, ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC) ? ARM_AM::add : ARM_AM::sub; int Val; - if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x1000, Val)) { // 12 bits. - Offset = CurDAG->getRegister(0, MVT::i32); - Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, Val, - ARM_AM::no_shift), - MVT::i32); - return true; - } + if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x1000, Val)) + return false; Offset = N; - ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N); + ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode()); unsigned ShAmt = 0; if (ShOpcVal != ARM_AM::no_shift) { // Check to see if the RHS of the shift is a constant, if not, we can't fold @@ -724,6 +757,50 @@ bool ARMDAGToDAGISel::SelectAddrMode2Offset(SDNode *Op, SDValue N, return true; } +bool ARMDAGToDAGISel::SelectAddrMode2OffsetImmPre(SDNode *Op, SDValue N, + SDValue &Offset, SDValue &Opc) { + unsigned Opcode = Op->getOpcode(); + ISD::MemIndexedMode AM = (Opcode == ISD::LOAD) + ? cast(Op)->getAddressingMode() + : cast(Op)->getAddressingMode(); + ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC) + ? ARM_AM::add : ARM_AM::sub; + int Val; + if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x1000, Val)) { // 12 bits. + if (AddSub == ARM_AM::sub) Val *= -1; + Offset = CurDAG->getRegister(0, MVT::i32); + Opc = CurDAG->getTargetConstant(Val, MVT::i32); + return true; + } + + return false; +} + + +bool ARMDAGToDAGISel::SelectAddrMode2OffsetImm(SDNode *Op, SDValue N, + SDValue &Offset, SDValue &Opc) { + unsigned Opcode = Op->getOpcode(); + ISD::MemIndexedMode AM = (Opcode == ISD::LOAD) + ? cast(Op)->getAddressingMode() + : cast(Op)->getAddressingMode(); + ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC) + ? ARM_AM::add : ARM_AM::sub; + int Val; + if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x1000, Val)) { // 12 bits. + Offset = CurDAG->getRegister(0, MVT::i32); + Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, Val, + ARM_AM::no_shift), + MVT::i32); + return true; + } + + return false; +} + +bool ARMDAGToDAGISel::SelectAddrOffsetNone(SDValue N, SDValue &Base) { + Base = N; + return true; +} bool ARMDAGToDAGISel::SelectAddrMode3(SDValue N, SDValue &Base, SDValue &Offset, @@ -1079,7 +1156,7 @@ bool ARMDAGToDAGISel::SelectT2ShifterOperandReg(SDValue N, SDValue &BaseReg, if (DisableShifterOp) return false; - ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N); + ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOpcode()); // Don't match base register only case. That is matched to a separate // lower complexity pattern with explicit register operand. @@ -1208,21 +1285,15 @@ bool ARMDAGToDAGISel::SelectT2AddrModeSoReg(SDValue N, return false; } - if (Subtarget->isCortexA9() && !N.hasOneUse()) { - // Compute R + (R << [1,2,3]) and reuse it. - Base = N; - return false; - } - // Look for (R + R) or (R + (R << [1,2,3])). unsigned ShAmt = 0; Base = N.getOperand(0); OffReg = N.getOperand(1); // Swap if it is ((R << c) + R). - ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(OffReg); + ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(OffReg.getOpcode()); if (ShOpcVal != ARM_AM::lsl) { - ShOpcVal = ARM_AM::getShiftOpcForNode(Base); + ShOpcVal = ARM_AM::getShiftOpcForNode(Base.getOpcode()); if (ShOpcVal == ARM_AM::lsl) std::swap(Base, OffReg); } @@ -1266,10 +1337,19 @@ SDNode *ARMDAGToDAGISel::SelectARMIndexedLoad(SDNode *N) { bool isPre = (AM == ISD::PRE_INC) || (AM == ISD::PRE_DEC); unsigned Opcode = 0; bool Match = false; - if (LoadedVT == MVT::i32 && - SelectAddrMode2Offset(N, LD->getOffset(), Offset, AMOpc)) { - Opcode = isPre ? ARM::LDR_PRE : ARM::LDR_POST; + if (LoadedVT == MVT::i32 && isPre && + SelectAddrMode2OffsetImmPre(N, LD->getOffset(), Offset, AMOpc)) { + Opcode = ARM::LDR_PRE_IMM; + Match = true; + } else if (LoadedVT == MVT::i32 && !isPre && + SelectAddrMode2OffsetImm(N, LD->getOffset(), Offset, AMOpc)) { + Opcode = ARM::LDR_POST_IMM; Match = true; + } else if (LoadedVT == MVT::i32 && + SelectAddrMode2OffsetReg(N, LD->getOffset(), Offset, AMOpc)) { + Opcode = isPre ? ARM::LDR_PRE_REG : ARM::LDR_POST_REG; + Match = true; + } else if (LoadedVT == MVT::i16 && SelectAddrMode3Offset(N, LD->getOffset(), Offset, AMOpc)) { Match = true; @@ -1283,20 +1363,37 @@ SDNode *ARMDAGToDAGISel::SelectARMIndexedLoad(SDNode *N) { Opcode = isPre ? ARM::LDRSB_PRE : ARM::LDRSB_POST; } } else { - if (SelectAddrMode2Offset(N, LD->getOffset(), Offset, AMOpc)) { + if (isPre && + SelectAddrMode2OffsetImmPre(N, LD->getOffset(), Offset, AMOpc)) { + Match = true; + Opcode = ARM::LDRB_PRE_IMM; + } else if (!isPre && + SelectAddrMode2OffsetImm(N, LD->getOffset(), Offset, AMOpc)) { + Match = true; + Opcode = ARM::LDRB_POST_IMM; + } else if (SelectAddrMode2OffsetReg(N, LD->getOffset(), Offset, AMOpc)) { Match = true; - Opcode = isPre ? ARM::LDRB_PRE : ARM::LDRB_POST; + Opcode = isPre ? ARM::LDRB_PRE_REG : ARM::LDRB_POST_REG; } } } if (Match) { - SDValue Chain = LD->getChain(); - SDValue Base = LD->getBasePtr(); - SDValue Ops[]= { Base, Offset, AMOpc, getAL(CurDAG), - CurDAG->getRegister(0, MVT::i32), Chain }; - return CurDAG->getMachineNode(Opcode, N->getDebugLoc(), MVT::i32, MVT::i32, - MVT::Other, Ops, 6); + if (Opcode == ARM::LDR_PRE_IMM || Opcode == ARM::LDRB_PRE_IMM) { + SDValue Chain = LD->getChain(); + SDValue Base = LD->getBasePtr(); + SDValue Ops[]= { Base, AMOpc, getAL(CurDAG), + CurDAG->getRegister(0, MVT::i32), Chain }; + return CurDAG->getMachineNode(Opcode, N->getDebugLoc(), MVT::i32, + MVT::i32, MVT::Other, Ops, 5); + } else { + SDValue Chain = LD->getChain(); + SDValue Base = LD->getBasePtr(); + SDValue Ops[]= { Base, Offset, AMOpc, getAL(CurDAG), + CurDAG->getRegister(0, MVT::i32), Chain }; + return CurDAG->getMachineNode(Opcode, N->getDebugLoc(), MVT::i32, + MVT::i32, MVT::Other, Ops, 6); + } } return NULL; @@ -1966,7 +2063,8 @@ SDNode *ARMDAGToDAGISel::SelectV6T2BitfieldExtractOp(SDNode *N, Srl_imm)) { assert(Srl_imm > 0 && Srl_imm < 32 && "bad amount in shift node!"); - unsigned Width = CountTrailingOnes_32(And_imm); + // Note: The width operand is encoded as width-1. + unsigned Width = CountTrailingOnes_32(And_imm) - 1; unsigned LSB = Srl_imm; SDValue Reg0 = CurDAG->getRegister(0, MVT::i32); SDValue Ops[] = { N->getOperand(0).getOperand(0), @@ -1986,7 +2084,8 @@ SDNode *ARMDAGToDAGISel::SelectV6T2BitfieldExtractOp(SDNode *N, unsigned Srl_imm = 0; if (isInt32Immediate(N->getOperand(1), Srl_imm)) { assert(Srl_imm > 0 && Srl_imm < 32 && "bad amount in shift node!"); - unsigned Width = 32 - Srl_imm; + // Note: The width operand is encoded as width-1. + unsigned Width = 32 - Srl_imm - 1; int LSB = Srl_imm - Shl_imm; if (LSB < 0) return NULL; @@ -2034,10 +2133,16 @@ SelectARMCMOVShiftOp(SDNode *N, SDValue FalseVal, SDValue TrueVal, SDValue CPTmp0; SDValue CPTmp1; SDValue CPTmp2; - if (SelectShifterOperandReg(TrueVal, CPTmp0, CPTmp1, CPTmp2)) { + if (SelectImmShifterOperand(TrueVal, CPTmp0, CPTmp2)) { + SDValue CC = CurDAG->getTargetConstant(CCVal, MVT::i32); + SDValue Ops[] = { FalseVal, CPTmp0, CPTmp2, CC, CCR, InFlag }; + return CurDAG->SelectNodeTo(N, ARM::MOVCCsi, MVT::i32, Ops, 6); + } + + if (SelectRegShifterOperand(TrueVal, CPTmp0, CPTmp1, CPTmp2)) { SDValue CC = CurDAG->getTargetConstant(CCVal, MVT::i32); SDValue Ops[] = { FalseVal, CPTmp0, CPTmp1, CPTmp2, CC, CCR, InFlag }; - return CurDAG->SelectNodeTo(N, ARM::MOVCCs, MVT::i32, Ops, 7); + return CurDAG->SelectNodeTo(N, ARM::MOVCCsr, MVT::i32, Ops, 7); } return 0; } @@ -2198,6 +2303,56 @@ SDNode *ARMDAGToDAGISel::SelectCMOVOp(SDNode *N) { return CurDAG->SelectNodeTo(N, Opc, VT, Ops, 5); } +/// Target-specific DAG combining for ISD::XOR. +/// Target-independent combining lowers SELECT_CC nodes of the form +/// select_cc setg[ge] X, 0, X, -X +/// select_cc setgt X, -1, X, -X +/// select_cc setl[te] X, 0, -X, X +/// select_cc setlt X, 1, -X, X +/// which represent Integer ABS into: +/// Y = sra (X, size(X)-1); xor (add (X, Y), Y) +/// ARM instruction selection detects the latter and matches it to +/// ARM::ABS or ARM::t2ABS machine node. +SDNode *ARMDAGToDAGISel::SelectABSOp(SDNode *N){ + SDValue XORSrc0 = N->getOperand(0); + SDValue XORSrc1 = N->getOperand(1); + DebugLoc DL = N->getDebugLoc(); + EVT VT = N->getValueType(0); + + if (DisableARMIntABS) + return NULL; + + if (Subtarget->isThumb1Only()) + return NULL; + + if (XORSrc0.getOpcode() != ISD::ADD || + XORSrc1.getOpcode() != ISD::SRA) + return NULL; + + SDValue ADDSrc0 = XORSrc0.getOperand(0); + SDValue ADDSrc1 = XORSrc0.getOperand(1); + SDValue SRASrc0 = XORSrc1.getOperand(0); + SDValue SRASrc1 = XORSrc1.getOperand(1); + ConstantSDNode *SRAConstant = dyn_cast(SRASrc1); + EVT XType = SRASrc0.getValueType(); + unsigned Size = XType.getSizeInBits() - 1; + + if (ADDSrc1 == XORSrc1 && + ADDSrc0 == SRASrc0 && + XType.isInteger() && + SRAConstant != NULL && + Size == SRAConstant->getZExtValue()) { + + unsigned Opcode = ARM::ABS; + if (Subtarget->isThumb2()) + Opcode = ARM::t2ABS; + + return CurDAG->SelectNodeTo(N, Opcode, VT, ADDSrc0); + } + + return NULL; +} + SDNode *ARMDAGToDAGISel::SelectConcatVector(SDNode *N) { // The only time a CONCAT_VECTORS operation can have legal types is when // two 64-bit vectors are concatenated to a 128-bit vector. @@ -2207,6 +2362,25 @@ SDNode *ARMDAGToDAGISel::SelectConcatVector(SDNode *N) { return PairDRegs(VT, N->getOperand(0), N->getOperand(1)); } +SDNode *ARMDAGToDAGISel::SelectAtomic64(SDNode *Node, unsigned Opc) { + SmallVector Ops; + Ops.push_back(Node->getOperand(1)); // Ptr + Ops.push_back(Node->getOperand(2)); // Low part of Val1 + Ops.push_back(Node->getOperand(3)); // High part of Val1 + if (Opc == ARM::ATOMCMPXCHG6432) { + Ops.push_back(Node->getOperand(4)); // Low part of Val2 + Ops.push_back(Node->getOperand(5)); // High part of Val2 + } + Ops.push_back(Node->getOperand(0)); // Chain + MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); + MemOp[0] = cast(Node)->getMemOperand(); + SDNode *ResNode = CurDAG->getMachineNode(Opc, Node->getDebugLoc(), + MVT::i32, MVT::i32, MVT::Other, + Ops.data() ,Ops.size()); + cast(ResNode)->setMemRefs(MemOp, MemOp + 1); + return ResNode; +} + SDNode *ARMDAGToDAGISel::Select(SDNode *N) { DebugLoc dl = N->getDebugLoc(); @@ -2215,6 +2389,14 @@ SDNode *ARMDAGToDAGISel::Select(SDNode *N) { switch (N->getOpcode()) { default: break; + case ISD::XOR: { + // Select special operations if XOR node forms integer ABS pattern + SDNode *ResNode = SelectABSOp(N); + if (ResNode) + return ResNode; + // Other cases are autogenerated. + break; + } case ISD::Constant: { unsigned Val = cast(N)->getZExtValue(); bool UseCP = true; @@ -2269,8 +2451,9 @@ SDNode *ARMDAGToDAGISel::Select(SDNode *N) { int FI = cast(N)->getIndex(); SDValue TFI = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); if (Subtarget->isThumb1Only()) { - return CurDAG->SelectNodeTo(N, ARM::tADDrSPi, MVT::i32, TFI, - CurDAG->getTargetConstant(0, MVT::i32)); + SDValue Ops[] = { TFI, CurDAG->getTargetConstant(0, MVT::i32), + getAL(CurDAG), CurDAG->getRegister(0, MVT::i32) }; + return CurDAG->SelectNodeTo(N, ARM::tADDrSPi, MVT::i32, Ops, 4); } else { unsigned Opc = ((Subtarget->isThumb() && Subtarget->hasThumb2()) ? ARM::t2ADDri : ARM::ADDri); @@ -2307,7 +2490,7 @@ SDNode *ARMDAGToDAGISel::Select(SDNode *N) { return CurDAG->SelectNodeTo(N, ARM::t2ADDrs, MVT::i32, Ops, 6); } else { SDValue Ops[] = { V, V, Reg0, ShImmOp, getAL(CurDAG), Reg0, Reg0 }; - return CurDAG->SelectNodeTo(N, ARM::ADDrs, MVT::i32, Ops, 7); + return CurDAG->SelectNodeTo(N, ARM::ADDrsi, MVT::i32, Ops, 7); } } if (isPowerOf2_32(RHSV+1)) { // 2^n-1? @@ -2323,7 +2506,7 @@ SDNode *ARMDAGToDAGISel::Select(SDNode *N) { return CurDAG->SelectNodeTo(N, ARM::t2RSBrs, MVT::i32, Ops, 6); } else { SDValue Ops[] = { V, V, Reg0, ShImmOp, getAL(CurDAG), Reg0, Reg0 }; - return CurDAG->SelectNodeTo(N, ARM::RSBrs, MVT::i32, Ops, 7); + return CurDAG->SelectNodeTo(N, ARM::RSBrsi, MVT::i32, Ops, 7); } } } @@ -2986,6 +3169,23 @@ SDNode *ARMDAGToDAGISel::Select(SDNode *N) { case ISD::CONCAT_VECTORS: return SelectConcatVector(N); + + case ARMISD::ATOMOR64_DAG: + return SelectAtomic64(N, ARM::ATOMOR6432); + case ARMISD::ATOMXOR64_DAG: + return SelectAtomic64(N, ARM::ATOMXOR6432); + case ARMISD::ATOMADD64_DAG: + return SelectAtomic64(N, ARM::ATOMADD6432); + case ARMISD::ATOMSUB64_DAG: + return SelectAtomic64(N, ARM::ATOMSUB6432); + case ARMISD::ATOMNAND64_DAG: + return SelectAtomic64(N, ARM::ATOMNAND6432); + case ARMISD::ATOMAND64_DAG: + return SelectAtomic64(N, ARM::ATOMAND6432); + case ARMISD::ATOMSWAP64_DAG: + return SelectAtomic64(N, ARM::ATOMSWAP6432); + case ARMISD::ATOMCMPXCHG64_DAG: + return SelectAtomic64(N, ARM::ATOMCMPXCHG6432); } return SelectCode(N); diff --git a/contrib/llvm/lib/Target/ARM/ARMISelLowering.cpp b/contrib/llvm/lib/Target/ARM/ARMISelLowering.cpp index cf8c5baa8..e44e35673 100644 --- a/contrib/llvm/lib/Target/ARM/ARMISelLowering.cpp +++ b/contrib/llvm/lib/Target/ARM/ARMISelLowering.cpp @@ -14,7 +14,6 @@ #define DEBUG_TYPE "arm-isel" #include "ARM.h" -#include "ARMAddressingModes.h" #include "ARMCallingConv.h" #include "ARMConstantPoolValue.h" #include "ARMISelLowering.h" @@ -24,6 +23,7 @@ #include "ARMSubtarget.h" #include "ARMTargetMachine.h" #include "ARMTargetObjectFile.h" +#include "MCTargetDesc/ARMAddressingModes.h" #include "llvm/CallingConv.h" #include "llvm/Constants.h" #include "llvm/Function.h" @@ -38,6 +38,7 @@ #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/PseudoSourceValue.h" #include "llvm/CodeGen/SelectionDAG.h" @@ -106,7 +107,7 @@ void ARMTargetLowering::addTypeForNEON(EVT VT, EVT PromotedLdStVT, EVT ElemTy = VT.getVectorElementType(); if (ElemTy != MVT::i64 && ElemTy != MVT::f64) - setOperationAction(ISD::VSETCC, VT.getSimpleVT(), Custom); + setOperationAction(ISD::SETCC, VT.getSimpleVT(), Custom); setOperationAction(ISD::EXTRACT_VECTOR_ELT, VT.getSimpleVT(), Custom); if (ElemTy != MVT::i32) { setOperationAction(ISD::SINT_TO_FP, VT.getSimpleVT(), Expand); @@ -178,6 +179,8 @@ ARMTargetLowering::ARMTargetLowering(TargetMachine &TM) RegInfo = TM.getRegisterInfo(); Itins = TM.getInstrItineraryData(); + setBooleanVectorContents(ZeroOrNegativeOneBooleanContent); + if (Subtarget->isTargetDarwin()) { // Uses VFP for Thumb libfuncs if available. if (Subtarget->isThumb() && Subtarget->hasVFP2()) { @@ -419,6 +422,13 @@ ARMTargetLowering::ARMTargetLowering(TargetMachine &TM) setLibcallName(RTLIB::MEMSET, "__aeabi_memset"); } + // Use divmod compiler-rt calls for iOS 5.0 and later. + if (Subtarget->getTargetTriple().getOS() == Triple::IOS && + !Subtarget->getTargetTriple().isOSVersionLT(5, 0)) { + setLibcallName(RTLIB::SDIVREM_I32, "__divmodsi4"); + setLibcallName(RTLIB::UDIVREM_I32, "__udivmodsi4"); + } + if (Subtarget->isThumb1Only()) addRegisterClass(MVT::i32, ARM::tGPRRegisterClass); else @@ -453,7 +463,7 @@ ARMTargetLowering::ARMTargetLowering(TargetMachine &TM) setOperationAction(ISD::FDIV, MVT::v2f64, Expand); setOperationAction(ISD::FREM, MVT::v2f64, Expand); setOperationAction(ISD::FCOPYSIGN, MVT::v2f64, Expand); - setOperationAction(ISD::VSETCC, MVT::v2f64, Expand); + setOperationAction(ISD::SETCC, MVT::v2f64, Expand); setOperationAction(ISD::FNEG, MVT::v2f64, Expand); setOperationAction(ISD::FABS, MVT::v2f64, Expand); setOperationAction(ISD::FSQRT, MVT::v2f64, Expand); @@ -485,8 +495,8 @@ ARMTargetLowering::ARMTargetLowering(TargetMachine &TM) setOperationAction(ISD::SDIV, MVT::v8i8, Custom); setOperationAction(ISD::UDIV, MVT::v4i16, Custom); setOperationAction(ISD::UDIV, MVT::v8i8, Custom); - setOperationAction(ISD::VSETCC, MVT::v1i64, Expand); - setOperationAction(ISD::VSETCC, MVT::v2i64, Expand); + setOperationAction(ISD::SETCC, MVT::v1i64, Expand); + setOperationAction(ISD::SETCC, MVT::v2i64, Expand); // Neon does not have single instruction SINT_TO_FP and UINT_TO_FP with // a destination type that is wider than the source. setOperationAction(ISD::SINT_TO_FP, MVT::v4i16, Custom); @@ -551,6 +561,14 @@ ARMTargetLowering::ARMTargetLowering(TargetMachine &TM) setOperationAction(ISD::SRL, MVT::i64, Custom); setOperationAction(ISD::SRA, MVT::i64, Custom); + if (!Subtarget->isThumb1Only()) { + // FIXME: We should do this for Thumb1 as well. + setOperationAction(ISD::ADDC, MVT::i32, Custom); + setOperationAction(ISD::ADDE, MVT::i32, Custom); + setOperationAction(ISD::SUBC, MVT::i32, Custom); + setOperationAction(ISD::SUBE, MVT::i32, Custom); + } + // ARM does not have ROTL. setOperationAction(ISD::ROTL, MVT::i32, Expand); setOperationAction(ISD::CTTZ, MVT::i32, Custom); @@ -596,62 +614,46 @@ ARMTargetLowering::ARMTargetLowering(TargetMachine &TM) setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32, Expand); // ARMv6 Thumb1 (except for CPUs that support dmb / dsb) and earlier use // the default expansion. + // FIXME: This should be checking for v6k, not just v6. if (Subtarget->hasDataBarrier() || (Subtarget->hasV6Ops() && !Subtarget->isThumb())) { // membarrier needs custom lowering; the rest are legal and handled // normally. setOperationAction(ISD::MEMBARRIER, MVT::Other, Custom); + setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Custom); + // Custom lowering for 64-bit ops + setOperationAction(ISD::ATOMIC_LOAD_ADD, MVT::i64, Custom); + setOperationAction(ISD::ATOMIC_LOAD_SUB, MVT::i64, Custom); + setOperationAction(ISD::ATOMIC_LOAD_AND, MVT::i64, Custom); + setOperationAction(ISD::ATOMIC_LOAD_OR, MVT::i64, Custom); + setOperationAction(ISD::ATOMIC_LOAD_XOR, MVT::i64, Custom); + setOperationAction(ISD::ATOMIC_SWAP, MVT::i64, Custom); + setOperationAction(ISD::ATOMIC_CMP_SWAP, MVT::i64, Custom); + // Automatically insert fences (dmb ist) around ATOMIC_SWAP etc. + setInsertFencesForAtomic(true); } else { // Set them all for expansion, which will force libcalls. setOperationAction(ISD::MEMBARRIER, MVT::Other, Expand); - setOperationAction(ISD::ATOMIC_CMP_SWAP, MVT::i8, Expand); - setOperationAction(ISD::ATOMIC_CMP_SWAP, MVT::i16, Expand); + setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Expand); setOperationAction(ISD::ATOMIC_CMP_SWAP, MVT::i32, Expand); - setOperationAction(ISD::ATOMIC_SWAP, MVT::i8, Expand); - setOperationAction(ISD::ATOMIC_SWAP, MVT::i16, Expand); setOperationAction(ISD::ATOMIC_SWAP, MVT::i32, Expand); - setOperationAction(ISD::ATOMIC_LOAD_ADD, MVT::i8, Expand); - setOperationAction(ISD::ATOMIC_LOAD_ADD, MVT::i16, Expand); setOperationAction(ISD::ATOMIC_LOAD_ADD, MVT::i32, Expand); - setOperationAction(ISD::ATOMIC_LOAD_SUB, MVT::i8, Expand); - setOperationAction(ISD::ATOMIC_LOAD_SUB, MVT::i16, Expand); setOperationAction(ISD::ATOMIC_LOAD_SUB, MVT::i32, Expand); - setOperationAction(ISD::ATOMIC_LOAD_AND, MVT::i8, Expand); - setOperationAction(ISD::ATOMIC_LOAD_AND, MVT::i16, Expand); setOperationAction(ISD::ATOMIC_LOAD_AND, MVT::i32, Expand); - setOperationAction(ISD::ATOMIC_LOAD_OR, MVT::i8, Expand); - setOperationAction(ISD::ATOMIC_LOAD_OR, MVT::i16, Expand); setOperationAction(ISD::ATOMIC_LOAD_OR, MVT::i32, Expand); - setOperationAction(ISD::ATOMIC_LOAD_XOR, MVT::i8, Expand); - setOperationAction(ISD::ATOMIC_LOAD_XOR, MVT::i16, Expand); setOperationAction(ISD::ATOMIC_LOAD_XOR, MVT::i32, Expand); - setOperationAction(ISD::ATOMIC_LOAD_NAND, MVT::i8, Expand); - setOperationAction(ISD::ATOMIC_LOAD_NAND, MVT::i16, Expand); setOperationAction(ISD::ATOMIC_LOAD_NAND, MVT::i32, Expand); - setOperationAction(ISD::ATOMIC_LOAD_MIN, MVT::i8, Expand); - setOperationAction(ISD::ATOMIC_LOAD_MIN, MVT::i16, Expand); setOperationAction(ISD::ATOMIC_LOAD_MIN, MVT::i32, Expand); - setOperationAction(ISD::ATOMIC_LOAD_MAX, MVT::i8, Expand); - setOperationAction(ISD::ATOMIC_LOAD_MAX, MVT::i16, Expand); setOperationAction(ISD::ATOMIC_LOAD_MAX, MVT::i32, Expand); - setOperationAction(ISD::ATOMIC_LOAD_UMIN, MVT::i8, Expand); - setOperationAction(ISD::ATOMIC_LOAD_UMIN, MVT::i16, Expand); setOperationAction(ISD::ATOMIC_LOAD_UMIN, MVT::i32, Expand); - setOperationAction(ISD::ATOMIC_LOAD_UMAX, MVT::i8, Expand); - setOperationAction(ISD::ATOMIC_LOAD_UMAX, MVT::i16, Expand); setOperationAction(ISD::ATOMIC_LOAD_UMAX, MVT::i32, Expand); + // Mark ATOMIC_LOAD and ATOMIC_STORE custom so we can handle the + // Unordered/Monotonic case. + setOperationAction(ISD::ATOMIC_LOAD, MVT::i32, Custom); + setOperationAction(ISD::ATOMIC_STORE, MVT::i32, Custom); // Since the libcalls include locking, fold in the fences setShouldFoldAtomicFences(true); } - // 64-bit versions are always libcalls (for now) - setOperationAction(ISD::ATOMIC_CMP_SWAP, MVT::i64, Expand); - setOperationAction(ISD::ATOMIC_SWAP, MVT::i64, Expand); - setOperationAction(ISD::ATOMIC_LOAD_ADD, MVT::i64, Expand); - setOperationAction(ISD::ATOMIC_LOAD_SUB, MVT::i64, Expand); - setOperationAction(ISD::ATOMIC_LOAD_AND, MVT::i64, Expand); - setOperationAction(ISD::ATOMIC_LOAD_OR, MVT::i64, Expand); - setOperationAction(ISD::ATOMIC_LOAD_XOR, MVT::i64, Expand); - setOperationAction(ISD::ATOMIC_LOAD_NAND, MVT::i64, Expand); setOperationAction(ISD::PREFETCH, MVT::Other, Custom); @@ -839,6 +841,11 @@ const char *ARMTargetLowering::getTargetNodeName(unsigned Opcode) const { case ARMISD::SRA_FLAG: return "ARMISD::SRA_FLAG"; case ARMISD::RRX: return "ARMISD::RRX"; + case ARMISD::ADDC: return "ARMISD::ADDC"; + case ARMISD::ADDE: return "ARMISD::ADDE"; + case ARMISD::SUBC: return "ARMISD::SUBC"; + case ARMISD::SUBE: return "ARMISD::SUBE"; + case ARMISD::VMOVRRD: return "ARMISD::VMOVRRD"; case ARMISD::VMOVDRR: return "ARMISD::VMOVDRR"; @@ -935,6 +942,11 @@ const char *ARMTargetLowering::getTargetNodeName(unsigned Opcode) const { } } +EVT ARMTargetLowering::getSetCCResultType(EVT VT) const { + if (!VT.isVector()) return getPointerTy(); + return VT.changeVectorElementTypeToInteger(); +} + /// getRegClassFor - Return the register class that should be used for the /// specified value type. TargetRegisterClass *ARMTargetLowering::getRegClassFor(EVT VT) const { @@ -1210,8 +1222,8 @@ ARMTargetLowering::LowerCall(SDValue Chain, SDValue Callee, MachineFunction &MF = DAG.getMachineFunction(); bool IsStructRet = (Outs.empty()) ? false : Outs[0].Flags.isSRet(); bool IsSibCall = false; - // Temporarily disable tail calls so things don't break. - if (!EnableARMTailCalls) + // Disable tail calls if they're not supported. + if (!EnableARMTailCalls && !Subtarget->supportsTailCall()) isTailCall = false; if (isTailCall) { // Check if it's really possible to do a tail call. @@ -1336,10 +1348,12 @@ ARMTargetLowering::LowerCall(SDValue Chain, SDValue Callee, SDValue Src = DAG.getNode(ISD::ADD, dl, getPointerTy(), Arg, SrcOffset); SDValue SizeNode = DAG.getConstant(Flags.getByValSize() - 4*offset, MVT::i32); + // TODO: Disable AlwaysInline when it becomes possible + // to emit a nested call sequence. MemOpChains.push_back(DAG.getMemcpy(Chain, dl, Dst, Src, SizeNode, Flags.getByValAlign(), /*isVolatile=*/false, - /*AlwaysInline=*/false, + /*AlwaysInline=*/true, MachinePointerInfo(0), MachinePointerInfo(0))); @@ -1404,9 +1418,9 @@ ARMTargetLowering::LowerCall(SDValue Chain, SDValue Callee, const GlobalValue *GV = G->getGlobal(); // Create a constant pool entry for the callee address unsigned ARMPCLabelIndex = AFI->createPICLabelUId(); - ARMConstantPoolValue *CPV = new ARMConstantPoolValue(GV, - ARMPCLabelIndex, - ARMCP::CPValue, 0); + ARMConstantPoolValue *CPV = + ARMConstantPoolConstant::Create(GV, ARMPCLabelIndex, ARMCP::CPValue, 0); + // Get the address of the callee into a register SDValue CPAddr = DAG.getTargetConstantPool(CPV, getPointerTy(), 4); CPAddr = DAG.getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr); @@ -1419,8 +1433,9 @@ ARMTargetLowering::LowerCall(SDValue Chain, SDValue Callee, // Create a constant pool entry for the callee address unsigned ARMPCLabelIndex = AFI->createPICLabelUId(); - ARMConstantPoolValue *CPV = new ARMConstantPoolValue(*DAG.getContext(), - Sym, ARMPCLabelIndex, 0); + ARMConstantPoolValue *CPV = + ARMConstantPoolSymbol::Create(*DAG.getContext(), Sym, + ARMPCLabelIndex, 0); // Get the address of the callee into a register SDValue CPAddr = DAG.getTargetConstantPool(CPV, getPointerTy(), 4); CPAddr = DAG.getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr); @@ -1441,9 +1456,8 @@ ARMTargetLowering::LowerCall(SDValue Chain, SDValue Callee, // tBX takes a register source operand. if (isARMFunc && Subtarget->isThumb1Only() && !Subtarget->hasV5TOps()) { unsigned ARMPCLabelIndex = AFI->createPICLabelUId(); - ARMConstantPoolValue *CPV = new ARMConstantPoolValue(GV, - ARMPCLabelIndex, - ARMCP::CPValue, 4); + ARMConstantPoolValue *CPV = + ARMConstantPoolConstant::Create(GV, ARMPCLabelIndex, ARMCP::CPValue, 4); SDValue CPAddr = DAG.getTargetConstantPool(CPV, getPointerTy(), 4); CPAddr = DAG.getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr); Callee = DAG.getLoad(getPointerTy(), dl, @@ -1470,8 +1484,9 @@ ARMTargetLowering::LowerCall(SDValue Chain, SDValue Callee, const char *Sym = S->getSymbol(); if (isARMFunc && Subtarget->isThumb1Only() && !Subtarget->hasV5TOps()) { unsigned ARMPCLabelIndex = AFI->createPICLabelUId(); - ARMConstantPoolValue *CPV = new ARMConstantPoolValue(*DAG.getContext(), - Sym, ARMPCLabelIndex, 4); + ARMConstantPoolValue *CPV = + ARMConstantPoolSymbol::Create(*DAG.getContext(), Sym, + ARMPCLabelIndex, 4); SDValue CPAddr = DAG.getTargetConstantPool(CPV, getPointerTy(), 4); CPAddr = DAG.getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr); Callee = DAG.getLoad(getPointerTy(), dl, @@ -1940,9 +1955,9 @@ SDValue ARMTargetLowering::LowerBlockAddress(SDValue Op, } else { unsigned PCAdj = Subtarget->isThumb() ? 4 : 8; ARMPCLabelIndex = AFI->createPICLabelUId(); - ARMConstantPoolValue *CPV = new ARMConstantPoolValue(BA, ARMPCLabelIndex, - ARMCP::CPBlockAddress, - PCAdj); + ARMConstantPoolValue *CPV = + ARMConstantPoolConstant::Create(BA, ARMPCLabelIndex, + ARMCP::CPBlockAddress, PCAdj); CPAddr = DAG.getTargetConstantPool(CPV, PtrVT, 4); } CPAddr = DAG.getNode(ARMISD::Wrapper, DL, PtrVT, CPAddr); @@ -1966,8 +1981,8 @@ ARMTargetLowering::LowerToTLSGeneralDynamicModel(GlobalAddressSDNode *GA, ARMFunctionInfo *AFI = MF.getInfo(); unsigned ARMPCLabelIndex = AFI->createPICLabelUId(); ARMConstantPoolValue *CPV = - new ARMConstantPoolValue(GA->getGlobal(), ARMPCLabelIndex, - ARMCP::CPValue, PCAdj, ARMCP::TLSGD, true); + ARMConstantPoolConstant::Create(GA->getGlobal(), ARMPCLabelIndex, + ARMCP::CPValue, PCAdj, ARMCP::TLSGD, true); SDValue Argument = DAG.getTargetConstantPool(CPV, PtrVT, 4); Argument = DAG.getNode(ARMISD::Wrapper, dl, MVT::i32, Argument); Argument = DAG.getLoad(PtrVT, dl, DAG.getEntryNode(), Argument, @@ -1982,11 +1997,11 @@ ARMTargetLowering::LowerToTLSGeneralDynamicModel(GlobalAddressSDNode *GA, ArgListTy Args; ArgListEntry Entry; Entry.Node = Argument; - Entry.Ty = (const Type *) Type::getInt32Ty(*DAG.getContext()); + Entry.Ty = (Type *) Type::getInt32Ty(*DAG.getContext()); Args.push_back(Entry); // FIXME: is there useful debug info available here? std::pair CallResult = - LowerCallTo(Chain, (const Type *) Type::getInt32Ty(*DAG.getContext()), + LowerCallTo(Chain, (Type *) Type::getInt32Ty(*DAG.getContext()), false, false, false, false, 0, CallingConv::C, false, /*isReturnValueUsed=*/true, DAG.getExternalSymbol("__tls_get_addr", PtrVT), Args, DAG, dl); @@ -2013,8 +2028,9 @@ ARMTargetLowering::LowerToTLSExecModels(GlobalAddressSDNode *GA, // Initial exec model. unsigned char PCAdj = Subtarget->isThumb() ? 4 : 8; ARMConstantPoolValue *CPV = - new ARMConstantPoolValue(GA->getGlobal(), ARMPCLabelIndex, - ARMCP::CPValue, PCAdj, ARMCP::GOTTPOFF, true); + ARMConstantPoolConstant::Create(GA->getGlobal(), ARMPCLabelIndex, + ARMCP::CPValue, PCAdj, ARMCP::GOTTPOFF, + true); Offset = DAG.getTargetConstantPool(CPV, PtrVT, 4); Offset = DAG.getNode(ARMISD::Wrapper, dl, MVT::i32, Offset); Offset = DAG.getLoad(PtrVT, dl, Chain, Offset, @@ -2030,7 +2046,8 @@ ARMTargetLowering::LowerToTLSExecModels(GlobalAddressSDNode *GA, false, false, 0); } else { // local exec model - ARMConstantPoolValue *CPV = new ARMConstantPoolValue(GV, ARMCP::TPOFF); + ARMConstantPoolValue *CPV = + ARMConstantPoolConstant::Create(GV, ARMCP::TPOFF); Offset = DAG.getTargetConstantPool(CPV, PtrVT, 4); Offset = DAG.getNode(ARMISD::Wrapper, dl, MVT::i32, Offset); Offset = DAG.getLoad(PtrVT, dl, Chain, Offset, @@ -2066,7 +2083,8 @@ SDValue ARMTargetLowering::LowerGlobalAddressELF(SDValue Op, if (RelocM == Reloc::PIC_) { bool UseGOTOFF = GV->hasLocalLinkage() || GV->hasHiddenVisibility(); ARMConstantPoolValue *CPV = - new ARMConstantPoolValue(GV, UseGOTOFF ? ARMCP::GOTOFF : ARMCP::GOT); + ARMConstantPoolConstant::Create(GV, + UseGOTOFF ? ARMCP::GOTOFF : ARMCP::GOT); SDValue CPAddr = DAG.getTargetConstantPool(CPV, PtrVT, 4); CPAddr = DAG.getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr); SDValue Result = DAG.getLoad(PtrVT, dl, DAG.getEntryNode(), @@ -2135,7 +2153,8 @@ SDValue ARMTargetLowering::LowerGlobalAddressDarwin(SDValue Op, ARMPCLabelIndex = AFI->createPICLabelUId(); unsigned PCAdj = (RelocM != Reloc::PIC_) ? 0 : (Subtarget->isThumb()?4:8); ARMConstantPoolValue *CPV = - new ARMConstantPoolValue(GV, ARMPCLabelIndex, ARMCP::CPValue, PCAdj); + ARMConstantPoolConstant::Create(GV, ARMPCLabelIndex, ARMCP::CPValue, + PCAdj); CPAddr = DAG.getTargetConstantPool(CPV, PtrVT, 4); } CPAddr = DAG.getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr); @@ -2167,9 +2186,9 @@ SDValue ARMTargetLowering::LowerGLOBAL_OFFSET_TABLE(SDValue Op, EVT PtrVT = getPointerTy(); DebugLoc dl = Op.getDebugLoc(); unsigned PCAdj = Subtarget->isThumb() ? 4 : 8; - ARMConstantPoolValue *CPV = new ARMConstantPoolValue(*DAG.getContext(), - "_GLOBAL_OFFSET_TABLE_", - ARMPCLabelIndex, PCAdj); + ARMConstantPoolValue *CPV = + ARMConstantPoolSymbol::Create(*DAG.getContext(), "_GLOBAL_OFFSET_TABLE_", + ARMPCLabelIndex, PCAdj); SDValue CPAddr = DAG.getTargetConstantPool(CPV, PtrVT, 4); CPAddr = DAG.getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr); SDValue Result = DAG.getLoad(PtrVT, dl, DAG.getEntryNode(), CPAddr, @@ -2191,7 +2210,8 @@ SDValue ARMTargetLowering::LowerEH_SJLJ_SETJMP(SDValue Op, SelectionDAG &DAG) const { DebugLoc dl = Op.getDebugLoc(); SDValue Val = DAG.getConstant(0, MVT::i32); - return DAG.getNode(ARMISD::EH_SJLJ_SETJMP, dl, MVT::i32, Op.getOperand(0), + return DAG.getNode(ARMISD::EH_SJLJ_SETJMP, dl, + DAG.getVTList(MVT::i32, MVT::Other), Op.getOperand(0), Op.getOperand(1), Val); } @@ -2224,8 +2244,8 @@ ARMTargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG, unsigned PCAdj = (RelocM != Reloc::PIC_) ? 0 : (Subtarget->isThumb() ? 4 : 8); ARMConstantPoolValue *CPV = - new ARMConstantPoolValue(MF.getFunction(), ARMPCLabelIndex, - ARMCP::CPLSDA, PCAdj); + ARMConstantPoolConstant::Create(MF.getFunction(), ARMPCLabelIndex, + ARMCP::CPLSDA, PCAdj); CPAddr = DAG.getTargetConstantPool(CPV, PtrVT, 4); CPAddr = DAG.getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr); SDValue Result = @@ -2277,6 +2297,25 @@ static SDValue LowerMEMBARRIER(SDValue Op, SelectionDAG &DAG, DAG.getConstant(DMBOpt, MVT::i32)); } + +static SDValue LowerATOMIC_FENCE(SDValue Op, SelectionDAG &DAG, + const ARMSubtarget *Subtarget) { + // FIXME: handle "fence singlethread" more efficiently. + DebugLoc dl = Op.getDebugLoc(); + if (!Subtarget->hasDataBarrier()) { + // Some ARMv6 cpus can support data barriers with an mcr instruction. + // Thumb1 and pre-v6 ARM mode use a libcall instead and should never get + // here. + assert(Subtarget->hasV6Ops() && !Subtarget->isThumb() && + "Unexpected ISD::MEMBARRIER encountered. Should be libcall!"); + return DAG.getNode(ARMISD::MEMBARRIER_MCR, dl, MVT::Other, Op.getOperand(0), + DAG.getConstant(0, MVT::i32)); + } + + return DAG.getNode(ARMISD::MEMBARRIER, dl, MVT::Other, Op.getOperand(0), + DAG.getConstant(ARM_MB::ISH, MVT::i32)); +} + static SDValue LowerPREFETCH(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *Subtarget) { // ARM pre v5TE and Thumb1 does not have preload instructions. @@ -2754,7 +2793,7 @@ SDValue ARMTargetLowering::LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const { SDValue ARMcc; SDValue CCR = DAG.getRegister(ARM::CPSR, MVT::i32); SDValue Cmp = getARMCmp(LHS, RHS, CC, ARMcc, DAG, dl); - return DAG.getNode(ARMISD::CMOV, dl, VT, FalseVal, TrueVal, ARMcc, CCR, Cmp); + return DAG.getNode(ARMISD::CMOV, dl, VT, FalseVal, TrueVal, ARMcc, CCR,Cmp); } ARMCC::CondCodes CondCode, CondCode2; @@ -2993,8 +3032,8 @@ static SDValue LowerVectorINT_TO_FP(SDValue Op, SelectionDAG &DAG) { EVT VT = Op.getValueType(); DebugLoc dl = Op.getDebugLoc(); - EVT OperandVT = Op.getOperand(0).getValueType(); - assert(OperandVT == MVT::v4i16 && "Invalid type for custom lowering!"); + assert(Op.getOperand(0).getValueType() == MVT::v4i16 && + "Invalid type for custom lowering!"); if (VT != MVT::v4f32) return DAG.UnrollVectorOp(Op.getNode()); @@ -3905,8 +3944,7 @@ SDValue ARMTargetLowering::LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG, } // Try an immediate VMVN. - uint64_t NegatedImm = (SplatBits.getZExtValue() ^ - ((1LL << SplatBitSize) - 1)); + uint64_t NegatedImm = (~SplatBits).getZExtValue(); Val = isNEONModifiedImm(NegatedImm, SplatUndef.getZExtValue(), SplatBitSize, DAG, VmovVT, VT.is128BitVector(), @@ -4019,6 +4057,14 @@ SDValue ARMTargetLowering::ReconstructShuffle(SDValue Op, // A shuffle can only come from building a vector from various // elements of other vectors. return SDValue(); + } else if (V.getOperand(0).getValueType().getVectorElementType() != + VT.getVectorElementType()) { + // This code doesn't know how to handle shuffles where the vector + // element types do not match (this happens because type legalization + // promotes the return type of EXTRACT_VECTOR_ELT). + // FIXME: It might be appropriate to extend this code to handle + // mismatched types. + return SDValue(); } // Record this extraction against the appropriate vector if possible... @@ -4819,6 +4865,71 @@ static SDValue LowerUDIV(SDValue Op, SelectionDAG &DAG) { return N0; } +static SDValue LowerADDC_ADDE_SUBC_SUBE(SDValue Op, SelectionDAG &DAG) { + EVT VT = Op.getNode()->getValueType(0); + SDVTList VTs = DAG.getVTList(VT, MVT::i32); + + unsigned Opc; + bool ExtraOp = false; + switch (Op.getOpcode()) { + default: assert(0 && "Invalid code"); + case ISD::ADDC: Opc = ARMISD::ADDC; break; + case ISD::ADDE: Opc = ARMISD::ADDE; ExtraOp = true; break; + case ISD::SUBC: Opc = ARMISD::SUBC; break; + case ISD::SUBE: Opc = ARMISD::SUBE; ExtraOp = true; break; + } + + if (!ExtraOp) + return DAG.getNode(Opc, Op->getDebugLoc(), VTs, Op.getOperand(0), + Op.getOperand(1)); + return DAG.getNode(Opc, Op->getDebugLoc(), VTs, Op.getOperand(0), + Op.getOperand(1), Op.getOperand(2)); +} + +static SDValue LowerAtomicLoadStore(SDValue Op, SelectionDAG &DAG) { + // Monotonic load/store is legal for all targets + if (cast(Op)->getOrdering() <= Monotonic) + return Op; + + // Aquire/Release load/store is not legal for targets without a + // dmb or equivalent available. + return SDValue(); +} + + +static void +ReplaceATOMIC_OP_64(SDNode *Node, SmallVectorImpl& Results, + SelectionDAG &DAG, unsigned NewOp) { + DebugLoc dl = Node->getDebugLoc(); + assert (Node->getValueType(0) == MVT::i64 && + "Only know how to expand i64 atomics"); + + SmallVector Ops; + Ops.push_back(Node->getOperand(0)); // Chain + Ops.push_back(Node->getOperand(1)); // Ptr + // Low part of Val1 + Ops.push_back(DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, + Node->getOperand(2), DAG.getIntPtrConstant(0))); + // High part of Val1 + Ops.push_back(DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, + Node->getOperand(2), DAG.getIntPtrConstant(1))); + if (NewOp == ARMISD::ATOMCMPXCHG64_DAG) { + // High part of Val1 + Ops.push_back(DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, + Node->getOperand(3), DAG.getIntPtrConstant(0))); + // High part of Val2 + Ops.push_back(DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, + Node->getOperand(3), DAG.getIntPtrConstant(1))); + } + SDVTList Tys = DAG.getVTList(MVT::i32, MVT::i32, MVT::Other); + SDValue Result = + DAG.getMemIntrinsicNode(NewOp, dl, Tys, Ops.data(), Ops.size(), MVT::i64, + cast(Node)->getMemOperand()); + SDValue OpsF[] = { Result.getValue(0), Result.getValue(1) }; + Results.push_back(DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, OpsF, 2)); + Results.push_back(Result.getValue(2)); +} + SDValue ARMTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const { switch (Op.getOpcode()) { default: llvm_unreachable("Don't know how to custom lower this!"); @@ -4834,6 +4945,7 @@ SDValue ARMTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const { case ISD::BR_JT: return LowerBR_JT(Op, DAG); case ISD::VASTART: return LowerVASTART(Op, DAG); case ISD::MEMBARRIER: return LowerMEMBARRIER(Op, DAG, Subtarget); + case ISD::ATOMIC_FENCE: return LowerATOMIC_FENCE(Op, DAG, Subtarget); case ISD::PREFETCH: return LowerPREFETCH(Op, DAG, Subtarget); case ISD::SINT_TO_FP: case ISD::UINT_TO_FP: return LowerINT_TO_FP(Op, DAG); @@ -4856,7 +4968,7 @@ SDValue ARMTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const { case ISD::SRL_PARTS: case ISD::SRA_PARTS: return LowerShiftRightParts(Op, DAG); case ISD::CTTZ: return LowerCTTZ(Op.getNode(), DAG, Subtarget); - case ISD::VSETCC: return LowerVSETCC(Op, DAG); + case ISD::SETCC: return LowerVSETCC(Op, DAG); case ISD::BUILD_VECTOR: return LowerBUILD_VECTOR(Op, DAG, Subtarget); case ISD::VECTOR_SHUFFLE: return LowerVECTOR_SHUFFLE(Op, DAG); case ISD::EXTRACT_VECTOR_ELT: return LowerEXTRACT_VECTOR_ELT(Op, DAG); @@ -4865,6 +4977,12 @@ SDValue ARMTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const { case ISD::MUL: return LowerMUL(Op, DAG); case ISD::SDIV: return LowerSDIV(Op, DAG); case ISD::UDIV: return LowerUDIV(Op, DAG); + case ISD::ADDC: + case ISD::ADDE: + case ISD::SUBC: + case ISD::SUBE: return LowerADDC_ADDE_SUBC_SUBE(Op, DAG); + case ISD::ATOMIC_LOAD: + case ISD::ATOMIC_STORE: return LowerAtomicLoadStore(Op, DAG); } return SDValue(); } @@ -4886,6 +5004,30 @@ void ARMTargetLowering::ReplaceNodeResults(SDNode *N, case ISD::SRA: Res = Expand64BitShift(N, DAG, Subtarget); break; + case ISD::ATOMIC_LOAD_ADD: + ReplaceATOMIC_OP_64(N, Results, DAG, ARMISD::ATOMADD64_DAG); + return; + case ISD::ATOMIC_LOAD_AND: + ReplaceATOMIC_OP_64(N, Results, DAG, ARMISD::ATOMAND64_DAG); + return; + case ISD::ATOMIC_LOAD_NAND: + ReplaceATOMIC_OP_64(N, Results, DAG, ARMISD::ATOMNAND64_DAG); + return; + case ISD::ATOMIC_LOAD_OR: + ReplaceATOMIC_OP_64(N, Results, DAG, ARMISD::ATOMOR64_DAG); + return; + case ISD::ATOMIC_LOAD_SUB: + ReplaceATOMIC_OP_64(N, Results, DAG, ARMISD::ATOMSUB64_DAG); + return; + case ISD::ATOMIC_LOAD_XOR: + ReplaceATOMIC_OP_64(N, Results, DAG, ARMISD::ATOMXOR64_DAG); + return; + case ISD::ATOMIC_SWAP: + ReplaceATOMIC_OP_64(N, Results, DAG, ARMISD::ATOMSWAP64_DAG); + return; + case ISD::ATOMIC_CMP_SWAP: + ReplaceATOMIC_OP_64(N, Results, DAG, ARMISD::ATOMCMPXCHG64_DAG); + return; } if (Res.getNode()) Results.push_back(Res); @@ -4963,7 +5105,10 @@ ARMTargetLowering::EmitAtomicCmpSwap(MachineInstr *MI, // cmp dest, oldval // bne exitMBB BB = loop1MBB; - AddDefaultPred(BuildMI(BB, dl, TII->get(ldrOpc), dest).addReg(ptr)); + MachineInstrBuilder MIB = BuildMI(BB, dl, TII->get(ldrOpc), dest).addReg(ptr); + if (ldrOpc == ARM::t2LDREX) + MIB.addImm(0); + AddDefaultPred(MIB); AddDefaultPred(BuildMI(BB, dl, TII->get(isThumb2 ? ARM::t2CMPrr : ARM::CMPrr)) .addReg(dest).addReg(oldval)); BuildMI(BB, dl, TII->get(isThumb2 ? ARM::t2Bcc : ARM::Bcc)) @@ -4976,8 +5121,10 @@ ARMTargetLowering::EmitAtomicCmpSwap(MachineInstr *MI, // cmp scratch, #0 // bne loop1MBB BB = loop2MBB; - AddDefaultPred(BuildMI(BB, dl, TII->get(strOpc), scratch).addReg(newval) - .addReg(ptr)); + MIB = BuildMI(BB, dl, TII->get(strOpc), scratch).addReg(newval).addReg(ptr); + if (strOpc == ARM::t2STREX) + MIB.addImm(0); + AddDefaultPred(MIB); AddDefaultPred(BuildMI(BB, dl, TII->get(isThumb2 ? ARM::t2CMPri : ARM::CMPri)) .addReg(scratch).addImm(0)); BuildMI(BB, dl, TII->get(isThumb2 ? ARM::t2Bcc : ARM::Bcc)) @@ -5063,7 +5210,10 @@ ARMTargetLowering::EmitAtomicBinary(MachineInstr *MI, MachineBasicBlock *BB, // bne- loopMBB // fallthrough --> exitMBB BB = loopMBB; - AddDefaultPred(BuildMI(BB, dl, TII->get(ldrOpc), dest).addReg(ptr)); + MachineInstrBuilder MIB = BuildMI(BB, dl, TII->get(ldrOpc), dest).addReg(ptr); + if (ldrOpc == ARM::t2LDREX) + MIB.addImm(0); + AddDefaultPred(MIB); if (BinOpcode) { // operand order needs to go the other way for NAND if (BinOpcode == ARM::BICrr || BinOpcode == ARM::t2BICrr) @@ -5074,8 +5224,10 @@ ARMTargetLowering::EmitAtomicBinary(MachineInstr *MI, MachineBasicBlock *BB, addReg(dest).addReg(incr)).addReg(0); } - AddDefaultPred(BuildMI(BB, dl, TII->get(strOpc), scratch).addReg(scratch2) - .addReg(ptr)); + MIB = BuildMI(BB, dl, TII->get(strOpc), scratch).addReg(scratch2).addReg(ptr); + if (strOpc == ARM::t2STREX) + MIB.addImm(0); + AddDefaultPred(MIB); AddDefaultPred(BuildMI(BB, dl, TII->get(isThumb2 ? ARM::t2CMPri : ARM::CMPri)) .addReg(scratch).addImm(0)); BuildMI(BB, dl, TII->get(isThumb2 ? ARM::t2Bcc : ARM::Bcc)) @@ -5125,12 +5277,12 @@ ARMTargetLowering::EmitAtomicBinaryMinMax(MachineInstr *MI, case 1: ldrOpc = isThumb2 ? ARM::t2LDREXB : ARM::LDREXB; strOpc = isThumb2 ? ARM::t2STREXB : ARM::STREXB; - extendOpc = isThumb2 ? ARM::t2SXTBr : ARM::SXTBr; + extendOpc = isThumb2 ? ARM::t2SXTB : ARM::SXTB; break; case 2: ldrOpc = isThumb2 ? ARM::t2LDREXH : ARM::LDREXH; strOpc = isThumb2 ? ARM::t2STREXH : ARM::STREXH; - extendOpc = isThumb2 ? ARM::t2SXTHr : ARM::SXTHr; + extendOpc = isThumb2 ? ARM::t2SXTH : ARM::SXTH; break; case 4: ldrOpc = isThumb2 ? ARM::t2LDREX : ARM::LDREX; @@ -5170,12 +5322,17 @@ ARMTargetLowering::EmitAtomicBinaryMinMax(MachineInstr *MI, // bne- loopMBB // fallthrough --> exitMBB BB = loopMBB; - AddDefaultPred(BuildMI(BB, dl, TII->get(ldrOpc), dest).addReg(ptr)); + MachineInstrBuilder MIB = BuildMI(BB, dl, TII->get(ldrOpc), dest).addReg(ptr); + if (ldrOpc == ARM::t2LDREX) + MIB.addImm(0); + AddDefaultPred(MIB); // Sign extend the value, if necessary. if (signExtend && extendOpc) { oldval = MRI.createVirtualRegister(ARM::GPRRegisterClass); - AddDefaultPred(BuildMI(BB, dl, TII->get(extendOpc), oldval).addReg(dest)); + AddDefaultPred(BuildMI(BB, dl, TII->get(extendOpc), oldval) + .addReg(dest) + .addImm(0)); } // Build compare and cmov instructions. @@ -5184,8 +5341,10 @@ ARMTargetLowering::EmitAtomicBinaryMinMax(MachineInstr *MI, BuildMI(BB, dl, TII->get(isThumb2 ? ARM::t2MOVCCr : ARM::MOVCCr), scratch2) .addReg(oldval).addReg(incr).addImm(Cond).addReg(ARM::CPSR); - AddDefaultPred(BuildMI(BB, dl, TII->get(strOpc), scratch).addReg(scratch2) - .addReg(ptr)); + MIB = BuildMI(BB, dl, TII->get(strOpc), scratch).addReg(scratch2).addReg(ptr); + if (strOpc == ARM::t2STREX) + MIB.addImm(0); + AddDefaultPred(MIB); AddDefaultPred(BuildMI(BB, dl, TII->get(isThumb2 ? ARM::t2CMPri : ARM::CMPri)) .addReg(scratch).addImm(0)); BuildMI(BB, dl, TII->get(isThumb2 ? ARM::t2Bcc : ARM::Bcc)) @@ -5203,79 +5362,596 @@ ARMTargetLowering::EmitAtomicBinaryMinMax(MachineInstr *MI, return BB; } -static -MachineBasicBlock *OtherSucc(MachineBasicBlock *MBB, MachineBasicBlock *Succ) { - for (MachineBasicBlock::succ_iterator I = MBB->succ_begin(), - E = MBB->succ_end(); I != E; ++I) - if (*I != Succ) - return *I; - llvm_unreachable("Expecting a BB with two successors!"); -} +MachineBasicBlock * +ARMTargetLowering::EmitAtomicBinary64(MachineInstr *MI, MachineBasicBlock *BB, + unsigned Op1, unsigned Op2, + bool NeedsCarry, bool IsCmpxchg) const { + // This also handles ATOMIC_SWAP, indicated by Op1==0. + const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); -// FIXME: This opcode table should obviously be expressed in the target -// description. We probably just need a "machine opcode" value in the pseudo -// instruction. But the ideal solution maybe to simply remove the "S" version -// of the opcode altogether. -struct AddSubFlagsOpcodePair { - unsigned PseudoOpc; - unsigned MachineOpc; -}; + const BasicBlock *LLVM_BB = BB->getBasicBlock(); + MachineFunction *MF = BB->getParent(); + MachineFunction::iterator It = BB; + ++It; -static AddSubFlagsOpcodePair AddSubFlagsOpcodeMap[] = { - {ARM::ADCSri, ARM::ADCri}, - {ARM::ADCSrr, ARM::ADCrr}, - {ARM::ADCSrs, ARM::ADCrs}, - {ARM::SBCSri, ARM::SBCri}, - {ARM::SBCSrr, ARM::SBCrr}, - {ARM::SBCSrs, ARM::SBCrs}, - {ARM::RSBSri, ARM::RSBri}, - {ARM::RSBSrr, ARM::RSBrr}, - {ARM::RSBSrs, ARM::RSBrs}, - {ARM::RSCSri, ARM::RSCri}, - {ARM::RSCSrs, ARM::RSCrs}, - {ARM::t2ADCSri, ARM::t2ADCri}, - {ARM::t2ADCSrr, ARM::t2ADCrr}, - {ARM::t2ADCSrs, ARM::t2ADCrs}, - {ARM::t2SBCSri, ARM::t2SBCri}, - {ARM::t2SBCSrr, ARM::t2SBCrr}, - {ARM::t2SBCSrs, ARM::t2SBCrs}, - {ARM::t2RSBSri, ARM::t2RSBri}, - {ARM::t2RSBSrs, ARM::t2RSBrs}, -}; + unsigned destlo = MI->getOperand(0).getReg(); + unsigned desthi = MI->getOperand(1).getReg(); + unsigned ptr = MI->getOperand(2).getReg(); + unsigned vallo = MI->getOperand(3).getReg(); + unsigned valhi = MI->getOperand(4).getReg(); + DebugLoc dl = MI->getDebugLoc(); + bool isThumb2 = Subtarget->isThumb2(); -// Convert and Add or Subtract with Carry and Flags to a generic opcode with -// CPSR operand. e.g. ADCS (...) -> ADC (... CPSR). -// -// FIXME: Somewhere we should assert that CPSR is in the correct -// position to be recognized by the target descrition as the 'S' bit. -bool ARMTargetLowering::RemapAddSubWithFlags(MachineInstr *MI, - MachineBasicBlock *BB) const { - unsigned OldOpc = MI->getOpcode(); - unsigned NewOpc = 0; + MachineRegisterInfo &MRI = BB->getParent()->getRegInfo(); + if (isThumb2) { + MRI.constrainRegClass(destlo, ARM::rGPRRegisterClass); + MRI.constrainRegClass(desthi, ARM::rGPRRegisterClass); + MRI.constrainRegClass(ptr, ARM::rGPRRegisterClass); + } - // This is only called for instructions that need remapping, so iterating over - // the tiny opcode table is not costly. - static const int NPairs = - sizeof(AddSubFlagsOpcodeMap) / sizeof(AddSubFlagsOpcodePair); - for (AddSubFlagsOpcodePair *Pair = &AddSubFlagsOpcodeMap[0], - *End = &AddSubFlagsOpcodeMap[NPairs]; Pair != End; ++Pair) { - if (OldOpc == Pair->PseudoOpc) { - NewOpc = Pair->MachineOpc; - break; + unsigned ldrOpc = isThumb2 ? ARM::t2LDREXD : ARM::LDREXD; + unsigned strOpc = isThumb2 ? ARM::t2STREXD : ARM::STREXD; + + MachineBasicBlock *loopMBB = MF->CreateMachineBasicBlock(LLVM_BB); + MachineBasicBlock *contBB = 0, *cont2BB = 0; + if (IsCmpxchg) { + contBB = MF->CreateMachineBasicBlock(LLVM_BB); + cont2BB = MF->CreateMachineBasicBlock(LLVM_BB); + } + MachineBasicBlock *exitMBB = MF->CreateMachineBasicBlock(LLVM_BB); + MF->insert(It, loopMBB); + if (IsCmpxchg) { + MF->insert(It, contBB); + MF->insert(It, cont2BB); + } + MF->insert(It, exitMBB); + + // Transfer the remainder of BB and its successor edges to exitMBB. + exitMBB->splice(exitMBB->begin(), BB, + llvm::next(MachineBasicBlock::iterator(MI)), + BB->end()); + exitMBB->transferSuccessorsAndUpdatePHIs(BB); + + TargetRegisterClass *TRC = + isThumb2 ? ARM::tGPRRegisterClass : ARM::GPRRegisterClass; + unsigned storesuccess = MRI.createVirtualRegister(TRC); + + // thisMBB: + // ... + // fallthrough --> loopMBB + BB->addSuccessor(loopMBB); + + // loopMBB: + // ldrexd r2, r3, ptr + // r0, r2, incr + // r1, r3, incr + // strexd storesuccess, r0, r1, ptr + // cmp storesuccess, #0 + // bne- loopMBB + // fallthrough --> exitMBB + // + // Note that the registers are explicitly specified because there is not any + // way to force the register allocator to allocate a register pair. + // + // FIXME: The hardcoded registers are not necessary for Thumb2, but we + // need to properly enforce the restriction that the two output registers + // for ldrexd must be different. + BB = loopMBB; + // Load + AddDefaultPred(BuildMI(BB, dl, TII->get(ldrOpc)) + .addReg(ARM::R2, RegState::Define) + .addReg(ARM::R3, RegState::Define).addReg(ptr)); + // Copy r2/r3 into dest. (This copy will normally be coalesced.) + BuildMI(BB, dl, TII->get(TargetOpcode::COPY), destlo).addReg(ARM::R2); + BuildMI(BB, dl, TII->get(TargetOpcode::COPY), desthi).addReg(ARM::R3); + + if (IsCmpxchg) { + // Add early exit + for (unsigned i = 0; i < 2; i++) { + AddDefaultPred(BuildMI(BB, dl, TII->get(isThumb2 ? ARM::t2CMPrr : + ARM::CMPrr)) + .addReg(i == 0 ? destlo : desthi) + .addReg(i == 0 ? vallo : valhi)); + BuildMI(BB, dl, TII->get(isThumb2 ? ARM::t2Bcc : ARM::Bcc)) + .addMBB(exitMBB).addImm(ARMCC::NE).addReg(ARM::CPSR); + BB->addSuccessor(exitMBB); + BB->addSuccessor(i == 0 ? contBB : cont2BB); + BB = (i == 0 ? contBB : cont2BB); } + + // Copy to physregs for strexd + unsigned setlo = MI->getOperand(5).getReg(); + unsigned sethi = MI->getOperand(6).getReg(); + BuildMI(BB, dl, TII->get(TargetOpcode::COPY), ARM::R0).addReg(setlo); + BuildMI(BB, dl, TII->get(TargetOpcode::COPY), ARM::R1).addReg(sethi); + } else if (Op1) { + // Perform binary operation + AddDefaultPred(BuildMI(BB, dl, TII->get(Op1), ARM::R0) + .addReg(destlo).addReg(vallo)) + .addReg(NeedsCarry ? ARM::CPSR : 0, getDefRegState(NeedsCarry)); + AddDefaultPred(BuildMI(BB, dl, TII->get(Op2), ARM::R1) + .addReg(desthi).addReg(valhi)).addReg(0); + } else { + // Copy to physregs for strexd + BuildMI(BB, dl, TII->get(TargetOpcode::COPY), ARM::R0).addReg(vallo); + BuildMI(BB, dl, TII->get(TargetOpcode::COPY), ARM::R1).addReg(valhi); } - if (!NewOpc) - return false; + // Store + AddDefaultPred(BuildMI(BB, dl, TII->get(strOpc), storesuccess) + .addReg(ARM::R0).addReg(ARM::R1).addReg(ptr)); + // Cmp+jump + AddDefaultPred(BuildMI(BB, dl, TII->get(isThumb2 ? ARM::t2CMPri : ARM::CMPri)) + .addReg(storesuccess).addImm(0)); + BuildMI(BB, dl, TII->get(isThumb2 ? ARM::t2Bcc : ARM::Bcc)) + .addMBB(loopMBB).addImm(ARMCC::NE).addReg(ARM::CPSR); + + BB->addSuccessor(loopMBB); + BB->addSuccessor(exitMBB); + + // exitMBB: + // ... + BB = exitMBB; + + MI->eraseFromParent(); // The instruction is gone now. + + return BB; +} + +/// EmitBasePointerRecalculation - For functions using a base pointer, we +/// rematerialize it (via the frame pointer). +void ARMTargetLowering:: +EmitBasePointerRecalculation(MachineInstr *MI, MachineBasicBlock *MBB, + MachineBasicBlock *DispatchBB) const { + const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); + const ARMBaseInstrInfo *AII = static_cast(TII); + MachineFunction &MF = *MI->getParent()->getParent(); + ARMFunctionInfo *AFI = MF.getInfo(); + const ARMBaseRegisterInfo &RI = AII->getRegisterInfo(); + + if (!RI.hasBasePointer(MF)) return; + + MachineBasicBlock::iterator MBBI = MI; + + int32_t NumBytes = AFI->getFramePtrSpillOffset(); + unsigned FramePtr = RI.getFrameRegister(MF); + assert(MF.getTarget().getFrameLowering()->hasFP(MF) && + "Base pointer without frame pointer?"); + + if (AFI->isThumb2Function()) + llvm::emitT2RegPlusImmediate(*MBB, MBBI, MI->getDebugLoc(), ARM::R6, + FramePtr, -NumBytes, ARMCC::AL, 0, *AII); + else if (AFI->isThumbFunction()) + llvm::emitThumbRegPlusImmediate(*MBB, MBBI, MI->getDebugLoc(), ARM::R6, + FramePtr, -NumBytes, *AII, RI); + else + llvm::emitARMRegPlusImmediate(*MBB, MBBI, MI->getDebugLoc(), ARM::R6, + FramePtr, -NumBytes, ARMCC::AL, 0, *AII); + + if (!RI.needsStackRealignment(MF)) return; + + // If there's dynamic realignment, adjust for it. + MachineFrameInfo *MFI = MF.getFrameInfo(); + unsigned MaxAlign = MFI->getMaxAlignment(); + assert(!AFI->isThumb1OnlyFunction()); + + // Emit bic r6, r6, MaxAlign + unsigned bicOpc = AFI->isThumbFunction() ? ARM::t2BICri : ARM::BICri; + AddDefaultCC( + AddDefaultPred( + BuildMI(*MBB, MBBI, MI->getDebugLoc(), TII->get(bicOpc), ARM::R6) + .addReg(ARM::R6, RegState::Kill) + .addImm(MaxAlign - 1))); +} + +/// SetupEntryBlockForSjLj - Insert code into the entry block that creates and +/// registers the function context. +void ARMTargetLowering:: +SetupEntryBlockForSjLj(MachineInstr *MI, MachineBasicBlock *MBB, + MachineBasicBlock *DispatchBB, int FI) const { const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); DebugLoc dl = MI->getDebugLoc(); - MachineInstrBuilder MIB = BuildMI(*BB, MI, dl, TII->get(NewOpc)); - for (unsigned i = 0; i < MI->getNumOperands(); ++i) - MIB.addOperand(MI->getOperand(i)); - AddDefaultPred(MIB); - MIB.addReg(ARM::CPSR, RegState::Define); // S bit + MachineFunction *MF = MBB->getParent(); + MachineRegisterInfo *MRI = &MF->getRegInfo(); + MachineConstantPool *MCP = MF->getConstantPool(); + ARMFunctionInfo *AFI = MF->getInfo(); + const Function *F = MF->getFunction(); + + bool isThumb = Subtarget->isThumb(); + bool isThumb2 = Subtarget->isThumb2(); + + unsigned PCLabelId = AFI->createPICLabelUId(); + unsigned PCAdj = (isThumb || isThumb2) ? 4 : 8; + ARMConstantPoolValue *CPV = + ARMConstantPoolMBB::Create(F->getContext(), DispatchBB, PCLabelId, PCAdj); + unsigned CPI = MCP->getConstantPoolIndex(CPV, 4); + + const TargetRegisterClass *TRC = + isThumb ? ARM::tGPRRegisterClass : ARM::GPRRegisterClass; + + // Grab constant pool and fixed stack memory operands. + MachineMemOperand *CPMMO = + MF->getMachineMemOperand(MachinePointerInfo::getConstantPool(), + MachineMemOperand::MOLoad, 4, 4); + + MachineMemOperand *FIMMOSt = + MF->getMachineMemOperand(MachinePointerInfo::getFixedStack(FI), + MachineMemOperand::MOStore, 4, 4); + + EmitBasePointerRecalculation(MI, MBB, DispatchBB); + + // Load the address of the dispatch MBB into the jump buffer. + if (isThumb2) { + // Incoming value: jbuf + // ldr.n r5, LCPI1_1 + // orr r5, r5, #1 + // add r5, pc + // str r5, [$jbuf, #+4] ; &jbuf[1] + unsigned NewVReg1 = MRI->createVirtualRegister(TRC); + AddDefaultPred(BuildMI(*MBB, MI, dl, TII->get(ARM::t2LDRpci), NewVReg1) + .addConstantPoolIndex(CPI) + .addMemOperand(CPMMO)); + // Set the low bit because of thumb mode. + unsigned NewVReg2 = MRI->createVirtualRegister(TRC); + AddDefaultCC( + AddDefaultPred(BuildMI(*MBB, MI, dl, TII->get(ARM::t2ORRri), NewVReg2) + .addReg(NewVReg1, RegState::Kill) + .addImm(0x01))); + unsigned NewVReg3 = MRI->createVirtualRegister(TRC); + BuildMI(*MBB, MI, dl, TII->get(ARM::tPICADD), NewVReg3) + .addReg(NewVReg2, RegState::Kill) + .addImm(PCLabelId); + AddDefaultPred(BuildMI(*MBB, MI, dl, TII->get(ARM::t2STRi12)) + .addReg(NewVReg3, RegState::Kill) + .addFrameIndex(FI) + .addImm(36) // &jbuf[1] :: pc + .addMemOperand(FIMMOSt)); + } else if (isThumb) { + // Incoming value: jbuf + // ldr.n r1, LCPI1_4 + // add r1, pc + // mov r2, #1 + // orrs r1, r2 + // add r2, $jbuf, #+4 ; &jbuf[1] + // str r1, [r2] + unsigned NewVReg1 = MRI->createVirtualRegister(TRC); + AddDefaultPred(BuildMI(*MBB, MI, dl, TII->get(ARM::tLDRpci), NewVReg1) + .addConstantPoolIndex(CPI) + .addMemOperand(CPMMO)); + unsigned NewVReg2 = MRI->createVirtualRegister(TRC); + BuildMI(*MBB, MI, dl, TII->get(ARM::tPICADD), NewVReg2) + .addReg(NewVReg1, RegState::Kill) + .addImm(PCLabelId); + // Set the low bit because of thumb mode. + unsigned NewVReg3 = MRI->createVirtualRegister(TRC); + AddDefaultPred(BuildMI(*MBB, MI, dl, TII->get(ARM::tMOVi8), NewVReg3) + .addReg(ARM::CPSR, RegState::Define) + .addImm(1)); + unsigned NewVReg4 = MRI->createVirtualRegister(TRC); + AddDefaultPred(BuildMI(*MBB, MI, dl, TII->get(ARM::tORR), NewVReg4) + .addReg(ARM::CPSR, RegState::Define) + .addReg(NewVReg2, RegState::Kill) + .addReg(NewVReg3, RegState::Kill)); + unsigned NewVReg5 = MRI->createVirtualRegister(TRC); + AddDefaultPred(BuildMI(*MBB, MI, dl, TII->get(ARM::tADDrSPi), NewVReg5) + .addFrameIndex(FI) + .addImm(36)); // &jbuf[1] :: pc + AddDefaultPred(BuildMI(*MBB, MI, dl, TII->get(ARM::tSTRi)) + .addReg(NewVReg4, RegState::Kill) + .addReg(NewVReg5, RegState::Kill) + .addImm(0) + .addMemOperand(FIMMOSt)); + } else { + // Incoming value: jbuf + // ldr r1, LCPI1_1 + // add r1, pc, r1 + // str r1, [$jbuf, #+4] ; &jbuf[1] + unsigned NewVReg1 = MRI->createVirtualRegister(TRC); + AddDefaultPred(BuildMI(*MBB, MI, dl, TII->get(ARM::LDRi12), NewVReg1) + .addConstantPoolIndex(CPI) + .addImm(0) + .addMemOperand(CPMMO)); + unsigned NewVReg2 = MRI->createVirtualRegister(TRC); + AddDefaultPred(BuildMI(*MBB, MI, dl, TII->get(ARM::PICADD), NewVReg2) + .addReg(NewVReg1, RegState::Kill) + .addImm(PCLabelId)); + AddDefaultPred(BuildMI(*MBB, MI, dl, TII->get(ARM::STRi12)) + .addReg(NewVReg2, RegState::Kill) + .addFrameIndex(FI) + .addImm(36) // &jbuf[1] :: pc + .addMemOperand(FIMMOSt)); + } +} + +MachineBasicBlock *ARMTargetLowering:: +EmitSjLjDispatchBlock(MachineInstr *MI, MachineBasicBlock *MBB) const { + const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); + DebugLoc dl = MI->getDebugLoc(); + MachineFunction *MF = MBB->getParent(); + MachineRegisterInfo *MRI = &MF->getRegInfo(); + ARMFunctionInfo *AFI = MF->getInfo(); + MachineFrameInfo *MFI = MF->getFrameInfo(); + int FI = MFI->getFunctionContextIndex(); + + const TargetRegisterClass *TRC = + Subtarget->isThumb() ? ARM::tGPRRegisterClass : ARM::GPRRegisterClass; + + // Get a mapping of the call site numbers to all of the landing pads they're + // associated with. + DenseMap > CallSiteNumToLPad; + unsigned MaxCSNum = 0; + MachineModuleInfo &MMI = MF->getMMI(); + for (MachineFunction::iterator BB = MF->begin(), E = MF->end(); BB != E; ++BB) { + if (!BB->isLandingPad()) continue; + + // FIXME: We should assert that the EH_LABEL is the first MI in the landing + // pad. + for (MachineBasicBlock::iterator + II = BB->begin(), IE = BB->end(); II != IE; ++II) { + if (!II->isEHLabel()) continue; + + MCSymbol *Sym = II->getOperand(0).getMCSymbol(); + if (!MMI.hasCallSiteLandingPad(Sym)) continue; + + SmallVectorImpl &CallSiteIdxs = MMI.getCallSiteLandingPad(Sym); + for (SmallVectorImpl::iterator + CSI = CallSiteIdxs.begin(), CSE = CallSiteIdxs.end(); + CSI != CSE; ++CSI) { + CallSiteNumToLPad[*CSI].push_back(BB); + MaxCSNum = std::max(MaxCSNum, *CSI); + } + break; + } + } + + // Get an ordered list of the machine basic blocks for the jump table. + std::vector LPadList; + SmallPtrSet InvokeBBs; + LPadList.reserve(CallSiteNumToLPad.size()); + for (unsigned I = 1; I <= MaxCSNum; ++I) { + SmallVectorImpl &MBBList = CallSiteNumToLPad[I]; + for (SmallVectorImpl::iterator + II = MBBList.begin(), IE = MBBList.end(); II != IE; ++II) { + LPadList.push_back(*II); + InvokeBBs.insert((*II)->pred_begin(), (*II)->pred_end()); + } + } + + assert(!LPadList.empty() && + "No landing pad destinations for the dispatch jump table!"); + + // Create the jump table and associated information. + MachineJumpTableInfo *JTI = + MF->getOrCreateJumpTableInfo(MachineJumpTableInfo::EK_Inline); + unsigned MJTI = JTI->createJumpTableIndex(LPadList); + unsigned UId = AFI->createJumpTableUId(); + + // Create the MBBs for the dispatch code. + + // Shove the dispatch's address into the return slot in the function context. + MachineBasicBlock *DispatchBB = MF->CreateMachineBasicBlock(); + DispatchBB->setIsLandingPad(); + + MachineBasicBlock *TrapBB = MF->CreateMachineBasicBlock(); + BuildMI(TrapBB, dl, TII->get(Subtarget->isThumb() ? ARM::tTRAP : ARM::TRAP)); + DispatchBB->addSuccessor(TrapBB); + + MachineBasicBlock *DispContBB = MF->CreateMachineBasicBlock(); + DispatchBB->addSuccessor(DispContBB); + + // Insert and renumber MBBs. + MachineBasicBlock *Last = &MF->back(); + MF->insert(MF->end(), DispatchBB); + MF->insert(MF->end(), DispContBB); + MF->insert(MF->end(), TrapBB); + MF->RenumberBlocks(Last); + + // Insert code into the entry block that creates and registers the function + // context. + SetupEntryBlockForSjLj(MI, MBB, DispatchBB, FI); + + MachineMemOperand *FIMMOLd = + MF->getMachineMemOperand(MachinePointerInfo::getFixedStack(FI), + MachineMemOperand::MOLoad | + MachineMemOperand::MOVolatile, 4, 4); + + if (Subtarget->isThumb2()) { + unsigned NewVReg1 = MRI->createVirtualRegister(TRC); + AddDefaultPred(BuildMI(DispatchBB, dl, TII->get(ARM::t2LDRi12), NewVReg1) + .addFrameIndex(FI) + .addImm(4) + .addMemOperand(FIMMOLd)); + AddDefaultPred(BuildMI(DispatchBB, dl, TII->get(ARM::t2CMPri)) + .addReg(NewVReg1) + .addImm(LPadList.size())); + BuildMI(DispatchBB, dl, TII->get(ARM::t2Bcc)) + .addMBB(TrapBB) + .addImm(ARMCC::HI) + .addReg(ARM::CPSR); + + unsigned NewVReg2 = MRI->createVirtualRegister(TRC); + AddDefaultPred(BuildMI(DispContBB, dl, TII->get(ARM::t2LEApcrelJT),NewVReg2) + .addJumpTableIndex(MJTI) + .addImm(UId)); + + unsigned NewVReg3 = MRI->createVirtualRegister(TRC); + AddDefaultCC( + AddDefaultPred( + BuildMI(DispContBB, dl, TII->get(ARM::t2ADDrs), NewVReg3) + .addReg(NewVReg2, RegState::Kill) + .addReg(NewVReg1) + .addImm(ARM_AM::getSORegOpc(ARM_AM::lsl, 2)))); + + BuildMI(DispContBB, dl, TII->get(ARM::t2BR_JT)) + .addReg(NewVReg3, RegState::Kill) + .addReg(NewVReg1) + .addJumpTableIndex(MJTI) + .addImm(UId); + } else if (Subtarget->isThumb()) { + unsigned NewVReg1 = MRI->createVirtualRegister(TRC); + AddDefaultPred(BuildMI(DispatchBB, dl, TII->get(ARM::tLDRspi), NewVReg1) + .addFrameIndex(FI) + .addImm(1) + .addMemOperand(FIMMOLd)); + + AddDefaultPred(BuildMI(DispatchBB, dl, TII->get(ARM::tCMPi8)) + .addReg(NewVReg1) + .addImm(LPadList.size())); + BuildMI(DispatchBB, dl, TII->get(ARM::tBcc)) + .addMBB(TrapBB) + .addImm(ARMCC::HI) + .addReg(ARM::CPSR); + + unsigned NewVReg2 = MRI->createVirtualRegister(TRC); + AddDefaultPred(BuildMI(DispContBB, dl, TII->get(ARM::tLSLri), NewVReg2) + .addReg(ARM::CPSR, RegState::Define) + .addReg(NewVReg1) + .addImm(2)); + + unsigned NewVReg3 = MRI->createVirtualRegister(TRC); + AddDefaultPred(BuildMI(DispContBB, dl, TII->get(ARM::tLEApcrelJT), NewVReg3) + .addJumpTableIndex(MJTI) + .addImm(UId)); + + unsigned NewVReg4 = MRI->createVirtualRegister(TRC); + AddDefaultPred(BuildMI(DispContBB, dl, TII->get(ARM::tADDrr), NewVReg4) + .addReg(ARM::CPSR, RegState::Define) + .addReg(NewVReg2, RegState::Kill) + .addReg(NewVReg3)); + + MachineMemOperand *JTMMOLd = + MF->getMachineMemOperand(MachinePointerInfo::getJumpTable(), + MachineMemOperand::MOLoad, 4, 4); + + unsigned NewVReg5 = MRI->createVirtualRegister(TRC); + AddDefaultPred(BuildMI(DispContBB, dl, TII->get(ARM::tLDRi), NewVReg5) + .addReg(NewVReg4, RegState::Kill) + .addImm(0) + .addMemOperand(JTMMOLd)); + + unsigned NewVReg6 = MRI->createVirtualRegister(TRC); + AddDefaultPred(BuildMI(DispContBB, dl, TII->get(ARM::tADDrr), NewVReg6) + .addReg(ARM::CPSR, RegState::Define) + .addReg(NewVReg5, RegState::Kill) + .addReg(NewVReg3)); + + BuildMI(DispContBB, dl, TII->get(ARM::tBR_JTr)) + .addReg(NewVReg6, RegState::Kill) + .addJumpTableIndex(MJTI) + .addImm(UId); + } else { + unsigned NewVReg1 = MRI->createVirtualRegister(TRC); + AddDefaultPred(BuildMI(DispatchBB, dl, TII->get(ARM::LDRi12), NewVReg1) + .addFrameIndex(FI) + .addImm(4) + .addMemOperand(FIMMOLd)); + AddDefaultPred(BuildMI(DispatchBB, dl, TII->get(ARM::CMPri)) + .addReg(NewVReg1) + .addImm(LPadList.size())); + BuildMI(DispatchBB, dl, TII->get(ARM::Bcc)) + .addMBB(TrapBB) + .addImm(ARMCC::HI) + .addReg(ARM::CPSR); + + unsigned NewVReg2 = MRI->createVirtualRegister(TRC); + AddDefaultCC( + AddDefaultPred(BuildMI(DispContBB, dl, TII->get(ARM::MOVsi), NewVReg2) + .addReg(NewVReg1) + .addImm(ARM_AM::getSORegOpc(ARM_AM::lsl, 2)))); + unsigned NewVReg3 = MRI->createVirtualRegister(TRC); + AddDefaultPred(BuildMI(DispContBB, dl, TII->get(ARM::LEApcrelJT), NewVReg3) + .addJumpTableIndex(MJTI) + .addImm(UId)); + + MachineMemOperand *JTMMOLd = + MF->getMachineMemOperand(MachinePointerInfo::getJumpTable(), + MachineMemOperand::MOLoad, 4, 4); + unsigned NewVReg4 = MRI->createVirtualRegister(TRC); + AddDefaultPred( + BuildMI(DispContBB, dl, TII->get(ARM::LDRrs), NewVReg4) + .addReg(NewVReg2, RegState::Kill) + .addReg(NewVReg3) + .addImm(0) + .addMemOperand(JTMMOLd)); + + BuildMI(DispContBB, dl, TII->get(ARM::BR_JTadd)) + .addReg(NewVReg4, RegState::Kill) + .addReg(NewVReg3) + .addJumpTableIndex(MJTI) + .addImm(UId); + } + + // Add the jump table entries as successors to the MBB. + MachineBasicBlock *PrevMBB = 0; + for (std::vector::iterator + I = LPadList.begin(), E = LPadList.end(); I != E; ++I) { + MachineBasicBlock *CurMBB = *I; + if (PrevMBB != CurMBB) + DispContBB->addSuccessor(CurMBB); + PrevMBB = CurMBB; + } + + const ARMBaseInstrInfo *AII = static_cast(TII); + const ARMBaseRegisterInfo &RI = AII->getRegisterInfo(); + const unsigned *SavedRegs = RI.getCalleeSavedRegs(MF); + for (SmallPtrSet::iterator + I = InvokeBBs.begin(), E = InvokeBBs.end(); I != E; ++I) { + MachineBasicBlock *BB = *I; + + // Remove the landing pad successor from the invoke block and replace it + // with the new dispatch block. + for (MachineBasicBlock::succ_iterator + SI = BB->succ_begin(), SE = BB->succ_end(); SI != SE; ++SI) { + MachineBasicBlock *SMBB = *SI; + if (SMBB->isLandingPad()) { + BB->removeSuccessor(SMBB); + SMBB->setIsLandingPad(false); + } + } + + BB->addSuccessor(DispatchBB); + + // Find the invoke call and mark all of the callee-saved registers as + // 'implicit defined' so that they're spilled. This prevents code from + // moving instructions to before the EH block, where they will never be + // executed. + for (MachineBasicBlock::reverse_iterator + II = BB->rbegin(), IE = BB->rend(); II != IE; ++II) { + if (!II->getDesc().isCall()) continue; + + DenseMap DefRegs; + for (MachineInstr::mop_iterator + OI = II->operands_begin(), OE = II->operands_end(); + OI != OE; ++OI) { + if (!OI->isReg()) continue; + DefRegs[OI->getReg()] = true; + } + + MachineInstrBuilder MIB(&*II); + + for (unsigned i = 0; SavedRegs[i] != 0; ++i) { + if (!TRC->contains(SavedRegs[i])) continue; + if (!DefRegs[SavedRegs[i]]) + MIB.addReg(SavedRegs[i], RegState::ImplicitDefine | RegState::Dead); + } + + break; + } + } + + // The instruction is gone now. MI->eraseFromParent(); - return true; + + return MBB; +} + +static +MachineBasicBlock *OtherSucc(MachineBasicBlock *MBB, MachineBasicBlock *Succ) { + for (MachineBasicBlock::succ_iterator I = MBB->succ_begin(), + E = MBB->succ_end(); I != E; ++I) + if (*I != Succ) + return *I; + llvm_unreachable("Expecting a BB with two successors!"); } MachineBasicBlock * @@ -5286,12 +5962,61 @@ ARMTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, bool isThumb2 = Subtarget->isThumb2(); switch (MI->getOpcode()) { default: { - if (RemapAddSubWithFlags(MI, BB)) - return BB; - MI->dump(); llvm_unreachable("Unexpected instr type to insert"); } + // The Thumb2 pre-indexed stores have the same MI operands, they just + // define them differently in the .td files from the isel patterns, so + // they need pseudos. + case ARM::t2STR_preidx: + MI->setDesc(TII->get(ARM::t2STR_PRE)); + return BB; + case ARM::t2STRB_preidx: + MI->setDesc(TII->get(ARM::t2STRB_PRE)); + return BB; + case ARM::t2STRH_preidx: + MI->setDesc(TII->get(ARM::t2STRH_PRE)); + return BB; + + case ARM::STRi_preidx: + case ARM::STRBi_preidx: { + unsigned NewOpc = MI->getOpcode() == ARM::STRi_preidx ? + ARM::STR_PRE_IMM : ARM::STRB_PRE_IMM; + // Decode the offset. + unsigned Offset = MI->getOperand(4).getImm(); + bool isSub = ARM_AM::getAM2Op(Offset) == ARM_AM::sub; + Offset = ARM_AM::getAM2Offset(Offset); + if (isSub) + Offset = -Offset; + + MachineMemOperand *MMO = *MI->memoperands_begin(); + BuildMI(*BB, MI, dl, TII->get(NewOpc)) + .addOperand(MI->getOperand(0)) // Rn_wb + .addOperand(MI->getOperand(1)) // Rt + .addOperand(MI->getOperand(2)) // Rn + .addImm(Offset) // offset (skip GPR==zero_reg) + .addOperand(MI->getOperand(5)) // pred + .addOperand(MI->getOperand(6)) + .addMemOperand(MMO); + MI->eraseFromParent(); + return BB; + } + case ARM::STRr_preidx: + case ARM::STRBr_preidx: + case ARM::STRH_preidx: { + unsigned NewOpc; + switch (MI->getOpcode()) { + default: llvm_unreachable("unexpected opcode!"); + case ARM::STRr_preidx: NewOpc = ARM::STR_PRE_REG; break; + case ARM::STRBr_preidx: NewOpc = ARM::STRB_PRE_REG; break; + case ARM::STRH_preidx: NewOpc = ARM::STRH_PRE; break; + } + MachineInstrBuilder MIB = BuildMI(*BB, MI, dl, TII->get(NewOpc)); + for (unsigned i = 0; i < MI->getNumOperands(); ++i) + MIB.addOperand(MI->getOperand(i)); + MI->eraseFromParent(); + return BB; + } case ARM::ATOMIC_LOAD_ADD_I8: return EmitAtomicBinary(MI, BB, 1, isThumb2 ? ARM::t2ADDrr : ARM::ADDrr); case ARM::ATOMIC_LOAD_ADD_I16: @@ -5370,6 +6095,31 @@ ARMTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, case ARM::ATOMIC_CMP_SWAP_I16: return EmitAtomicCmpSwap(MI, BB, 2); case ARM::ATOMIC_CMP_SWAP_I32: return EmitAtomicCmpSwap(MI, BB, 4); + + case ARM::ATOMADD6432: + return EmitAtomicBinary64(MI, BB, isThumb2 ? ARM::t2ADDrr : ARM::ADDrr, + isThumb2 ? ARM::t2ADCrr : ARM::ADCrr, + /*NeedsCarry*/ true); + case ARM::ATOMSUB6432: + return EmitAtomicBinary64(MI, BB, isThumb2 ? ARM::t2SUBrr : ARM::SUBrr, + isThumb2 ? ARM::t2SBCrr : ARM::SBCrr, + /*NeedsCarry*/ true); + case ARM::ATOMOR6432: + return EmitAtomicBinary64(MI, BB, isThumb2 ? ARM::t2ORRrr : ARM::ORRrr, + isThumb2 ? ARM::t2ORRrr : ARM::ORRrr); + case ARM::ATOMXOR6432: + return EmitAtomicBinary64(MI, BB, isThumb2 ? ARM::t2EORrr : ARM::EORrr, + isThumb2 ? ARM::t2EORrr : ARM::EORrr); + case ARM::ATOMAND6432: + return EmitAtomicBinary64(MI, BB, isThumb2 ? ARM::t2ANDrr : ARM::ANDrr, + isThumb2 ? ARM::t2ANDrr : ARM::ANDrr); + case ARM::ATOMSWAP6432: + return EmitAtomicBinary64(MI, BB, 0, 0, false); + case ARM::ATOMCMPXCHG6432: + return EmitAtomicBinary64(MI, BB, isThumb2 ? ARM::t2SUBrr : ARM::SUBrr, + isThumb2 ? ARM::t2SBCrr : ARM::SBCrr, + /*NeedsCarry*/ false, /*IsCmpxchg*/true); + case ARM::tMOVCCr_pseudo: { // To "insert" a SELECT_CC instruction, we actually have to insert the // diamond control-flow pattern. The incoming instruction knows the @@ -5461,13 +6211,159 @@ ARMTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, BuildMI(BB, dl, TII->get(isThumb2 ? ARM::t2Bcc : ARM::Bcc)) .addMBB(destMBB).addImm(ARMCC::EQ).addReg(ARM::CPSR); - BuildMI(BB, dl, TII->get(isThumb2 ? ARM::t2B : ARM::B)) - .addMBB(exitMBB); + if (isThumb2) + AddDefaultPred(BuildMI(BB, dl, TII->get(ARM::t2B)).addMBB(exitMBB)); + else + BuildMI(BB, dl, TII->get(ARM::B)) .addMBB(exitMBB); MI->eraseFromParent(); // The pseudo instruction is gone now. return BB; } + + case ARM::ABS: + case ARM::t2ABS: { + // To insert an ABS instruction, we have to insert the + // diamond control-flow pattern. The incoming instruction knows the + // source vreg to test against 0, the destination vreg to set, + // the condition code register to branch on, the + // true/false values to select between, and a branch opcode to use. + // It transforms + // V1 = ABS V0 + // into + // V2 = MOVS V0 + // BCC (branch to SinkBB if V0 >= 0) + // RSBBB: V3 = RSBri V2, 0 (compute ABS if V2 < 0) + // SinkBB: V1 = PHI(V2, V3) + const BasicBlock *LLVM_BB = BB->getBasicBlock(); + MachineFunction::iterator BBI = BB; + ++BBI; + MachineFunction *Fn = BB->getParent(); + MachineBasicBlock *RSBBB = Fn->CreateMachineBasicBlock(LLVM_BB); + MachineBasicBlock *SinkBB = Fn->CreateMachineBasicBlock(LLVM_BB); + Fn->insert(BBI, RSBBB); + Fn->insert(BBI, SinkBB); + + unsigned int ABSSrcReg = MI->getOperand(1).getReg(); + unsigned int ABSDstReg = MI->getOperand(0).getReg(); + bool isThumb2 = Subtarget->isThumb2(); + MachineRegisterInfo &MRI = Fn->getRegInfo(); + // In Thumb mode S must not be specified if source register is the SP or + // PC and if destination register is the SP, so restrict register class + unsigned NewMovDstReg = MRI.createVirtualRegister( + isThumb2 ? ARM::rGPRRegisterClass : ARM::GPRRegisterClass); + unsigned NewRsbDstReg = MRI.createVirtualRegister( + isThumb2 ? ARM::rGPRRegisterClass : ARM::GPRRegisterClass); + + // Transfer the remainder of BB and its successor edges to sinkMBB. + SinkBB->splice(SinkBB->begin(), BB, + llvm::next(MachineBasicBlock::iterator(MI)), + BB->end()); + SinkBB->transferSuccessorsAndUpdatePHIs(BB); + + BB->addSuccessor(RSBBB); + BB->addSuccessor(SinkBB); + + // fall through to SinkMBB + RSBBB->addSuccessor(SinkBB); + + // insert a movs at the end of BB + BuildMI(BB, dl, TII->get(isThumb2 ? ARM::t2MOVr : ARM::MOVr), + NewMovDstReg) + .addReg(ABSSrcReg, RegState::Kill) + .addImm((unsigned)ARMCC::AL).addReg(0) + .addReg(ARM::CPSR, RegState::Define); + + // insert a bcc with opposite CC to ARMCC::MI at the end of BB + BuildMI(BB, dl, + TII->get(isThumb2 ? ARM::t2Bcc : ARM::Bcc)).addMBB(SinkBB) + .addImm(ARMCC::getOppositeCondition(ARMCC::MI)).addReg(ARM::CPSR); + + // insert rsbri in RSBBB + // Note: BCC and rsbri will be converted into predicated rsbmi + // by if-conversion pass + BuildMI(*RSBBB, RSBBB->begin(), dl, + TII->get(isThumb2 ? ARM::t2RSBri : ARM::RSBri), NewRsbDstReg) + .addReg(NewMovDstReg, RegState::Kill) + .addImm(0).addImm((unsigned)ARMCC::AL).addReg(0).addReg(0); + + // insert PHI in SinkBB, + // reuse ABSDstReg to not change uses of ABS instruction + BuildMI(*SinkBB, SinkBB->begin(), dl, + TII->get(ARM::PHI), ABSDstReg) + .addReg(NewRsbDstReg).addMBB(RSBBB) + .addReg(NewMovDstReg).addMBB(BB); + + // remove ABS instruction + MI->eraseFromParent(); + + // return last added BB + return SinkBB; + } + } +} + +void ARMTargetLowering::AdjustInstrPostInstrSelection(MachineInstr *MI, + SDNode *Node) const { + const MCInstrDesc &MCID = MI->getDesc(); + if (!MCID.hasPostISelHook()) { + assert(!convertAddSubFlagsOpcode(MI->getOpcode()) && + "Pseudo flag-setting opcodes must be marked with 'hasPostISelHook'"); + return; + } + + // Adjust potentially 's' setting instructions after isel, i.e. ADC, SBC, RSB, + // RSC. Coming out of isel, they have an implicit CPSR def, but the optional + // operand is still set to noreg. If needed, set the optional operand's + // register to CPSR, and remove the redundant implicit def. + // + // e.g. ADCS (...opt:%noreg, CPSR) -> ADC (... opt:CPSR). + + // Rename pseudo opcodes. + unsigned NewOpc = convertAddSubFlagsOpcode(MI->getOpcode()); + if (NewOpc) { + const ARMBaseInstrInfo *TII = + static_cast(getTargetMachine().getInstrInfo()); + MI->setDesc(TII->get(NewOpc)); + } + unsigned ccOutIdx = MCID.getNumOperands() - 1; + + // Any ARM instruction that sets the 's' bit should specify an optional + // "cc_out" operand in the last operand position. + if (!MCID.hasOptionalDef() || !MCID.OpInfo[ccOutIdx].isOptionalDef()) { + assert(!NewOpc && "Optional cc_out operand required"); + return; + } + // Look for an implicit def of CPSR added by MachineInstr ctor. Remove it + // since we already have an optional CPSR def. + bool definesCPSR = false; + bool deadCPSR = false; + for (unsigned i = MCID.getNumOperands(), e = MI->getNumOperands(); + i != e; ++i) { + const MachineOperand &MO = MI->getOperand(i); + if (MO.isReg() && MO.isDef() && MO.getReg() == ARM::CPSR) { + definesCPSR = true; + if (MO.isDead()) + deadCPSR = true; + MI->RemoveOperand(i); + break; + } + } + if (!definesCPSR) { + assert(!NewOpc && "Optional cc_out operand required"); + return; + } + assert(deadCPSR == !Node->hasAnyUseOfValue(1) && "inconsistent dead flag"); + if (deadCPSR) { + assert(!MI->getOperand(ccOutIdx).getReg() && + "expect uninitialized optional cc_out operand"); + return; } + + // If this instruction was defined with an optional CPSR def and its dag node + // had a live implicit CPSR def, then activate the optional CPSR def. + MachineOperand &MO = MI->getOperand(ccOutIdx); + MO.setReg(ARM::CPSR); + MO.setIsDef(true); } //===----------------------------------------------------------------------===// @@ -6975,7 +7871,8 @@ ARMTargetLowering::PerformCMOVCombine(SDNode *N, SelectionDAG &DAG) const { SDValue FalseVal = N->getOperand(0); SDValue TrueVal = N->getOperand(1); SDValue ARMcc = N->getOperand(2); - ARMCC::CondCodes CC = (ARMCC::CondCodes)cast(ARMcc)->getZExtValue(); + ARMCC::CondCodes CC = + (ARMCC::CondCodes)cast(ARMcc)->getZExtValue(); // Simplify // mov r1, r0 @@ -6995,7 +7892,7 @@ ARMTargetLowering::PerformCMOVCombine(SDNode *N, SelectionDAG &DAG) const { // movne r0, y /// FIXME: Turn this into a target neutral optimization? SDValue Res; - if (CC == ARMCC::NE && FalseVal == RHS) { + if (CC == ARMCC::NE && FalseVal == RHS && FalseVal != LHS) { Res = DAG.getNode(ARMISD::CMOV, dl, VT, LHS, TrueVal, ARMcc, N->getOperand(3), Cmp); } else if (CC == ARMCC::EQ && TrueVal == RHS) { @@ -7235,7 +8132,7 @@ bool ARMTargetLowering::isLegalT2ScaledAddressingMode(const AddrMode &AM, /// isLegalAddressingMode - Return true if the addressing mode represented /// by AM is legal for this target, for a load/store of the specified type. bool ARMTargetLowering::isLegalAddressingMode(const AddrMode &AM, - const Type *Ty) const { + Type *Ty) const { EVT VT = getValueType(Ty, true); if (!isLegalAddressImmediate(AM.BaseOffs, VT, Subtarget)) return false; @@ -7351,7 +8248,8 @@ static bool getARMIndexedAddressParts(SDNode *Ptr, EVT VT, if (Ptr->getOpcode() == ISD::ADD) { isInc = true; - ARM_AM::ShiftOpc ShOpcVal= ARM_AM::getShiftOpcForNode(Ptr->getOperand(0)); + ARM_AM::ShiftOpc ShOpcVal= + ARM_AM::getShiftOpcForNode(Ptr->getOperand(0).getOpcode()); if (ShOpcVal != ARM_AM::no_shift) { Base = Ptr->getOperand(1); Offset = Ptr->getOperand(0); @@ -7536,7 +8434,7 @@ bool ARMTargetLowering::ExpandInlineAsm(CallInst *CI) const { if (AsmPieces.size() == 3 && AsmPieces[0] == "rev" && AsmPieces[1] == "$0" && AsmPieces[2] == "$1" && IA->getConstraintString().compare(0, 4, "=l,l") == 0) { - const IntegerType *Ty = dyn_cast(CI->getType()); + IntegerType *Ty = dyn_cast(CI->getType()); if (Ty && Ty->getBitWidth() == 32) return IntrinsicLowering::LowerToByteSwap(CI); } @@ -7559,6 +8457,9 @@ ARMTargetLowering::getConstraintType(const std::string &Constraint) const { case 'x': return C_RegisterClass; case 't': return C_RegisterClass; case 'j': return C_Other; // Constant for movw. + // An address with a single base register. Due to the way we + // currently handle addresses it is the same as an 'r' memory constraint. + case 'Q': return C_Memory; } } else if (Constraint.size() == 2) { switch (Constraint[0]) { @@ -7582,7 +8483,7 @@ ARMTargetLowering::getSingleConstraintMatchWeight( // but allow it at the lowest weight. if (CallOperandVal == NULL) return CW_Default; - const Type *type = CallOperandVal->getType(); + Type *type = CallOperandVal->getType(); // Look at the constraint type. switch (*constraint) { default: @@ -7618,7 +8519,7 @@ ARMTargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint, return RCPair(0U, ARM::GPRRegisterClass); case 'h': // High regs or no regs. if (Subtarget->isThumb()) - return RCPair(0U, ARM::hGPRRegisterClass); + return RCPair(0U, ARM::hGPRRegisterClass); break; case 'r': return RCPair(0U, ARM::GPRRegisterClass); @@ -7632,15 +8533,15 @@ ARMTargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint, break; case 'x': if (VT == MVT::f32) - return RCPair(0U, ARM::SPR_8RegisterClass); + return RCPair(0U, ARM::SPR_8RegisterClass); if (VT.getSizeInBits() == 64) - return RCPair(0U, ARM::DPR_8RegisterClass); + return RCPair(0U, ARM::DPR_8RegisterClass); if (VT.getSizeInBits() == 128) - return RCPair(0U, ARM::QPR_8RegisterClass); + return RCPair(0U, ARM::QPR_8RegisterClass); break; case 't': if (VT == MVT::f32) - return RCPair(0U, ARM::SPRRegisterClass); + return RCPair(0U, ARM::SPRRegisterClass); break; } } @@ -7680,12 +8581,12 @@ void ARMTargetLowering::LowerAsmOperandForConstraint(SDValue Op, switch (ConstraintLetter) { case 'j': - // Constant suitable for movw, must be between 0 and - // 65535. - if (Subtarget->hasV6T2Ops()) - if (CVal >= 0 && CVal <= 65535) - break; - return; + // Constant suitable for movw, must be between 0 and + // 65535. + if (Subtarget->hasV6T2Ops()) + if (CVal >= 0 && CVal <= 65535) + break; + return; case 'I': if (Subtarget->isThumb1Only()) { // This must be a constant between 0 and 255, for ADD @@ -7823,50 +8724,6 @@ ARMTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const { return false; } -int ARM::getVFPf32Imm(const APFloat &FPImm) { - APInt Imm = FPImm.bitcastToAPInt(); - uint32_t Sign = Imm.lshr(31).getZExtValue() & 1; - int32_t Exp = (Imm.lshr(23).getSExtValue() & 0xff) - 127; // -126 to 127 - int64_t Mantissa = Imm.getZExtValue() & 0x7fffff; // 23 bits - - // We can handle 4 bits of mantissa. - // mantissa = (16+UInt(e:f:g:h))/16. - if (Mantissa & 0x7ffff) - return -1; - Mantissa >>= 19; - if ((Mantissa & 0xf) != Mantissa) - return -1; - - // We can handle 3 bits of exponent: exp == UInt(NOT(b):c:d)-3 - if (Exp < -3 || Exp > 4) - return -1; - Exp = ((Exp+3) & 0x7) ^ 4; - - return ((int)Sign << 7) | (Exp << 4) | Mantissa; -} - -int ARM::getVFPf64Imm(const APFloat &FPImm) { - APInt Imm = FPImm.bitcastToAPInt(); - uint64_t Sign = Imm.lshr(63).getZExtValue() & 1; - int64_t Exp = (Imm.lshr(52).getSExtValue() & 0x7ff) - 1023; // -1022 to 1023 - uint64_t Mantissa = Imm.getZExtValue() & 0xfffffffffffffLL; - - // We can handle 4 bits of mantissa. - // mantissa = (16+UInt(e:f:g:h))/16. - if (Mantissa & 0xffffffffffffLL) - return -1; - Mantissa >>= 48; - if ((Mantissa & 0xf) != Mantissa) - return -1; - - // We can handle 3 bits of exponent: exp == UInt(NOT(b):c:d)-3 - if (Exp < -3 || Exp > 4) - return -1; - Exp = ((Exp+3) & 0x7) ^ 4; - - return ((int)Sign << 7) | (Exp << 4) | Mantissa; -} - bool ARM::isBitFieldInvertedMask(unsigned v) { if (v == 0xffffffff) return 0; @@ -7889,9 +8746,9 @@ bool ARMTargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT) const { if (!Subtarget->hasVFP3()) return false; if (VT == MVT::f32) - return ARM::getVFPf32Imm(Imm) != -1; + return ARM_AM::getFP32Imm(Imm) != -1; if (VT == MVT::f64) - return ARM::getVFPf64Imm(Imm) != -1; + return ARM_AM::getFP64Imm(Imm) != -1; return false; } @@ -7933,7 +8790,7 @@ bool ARMTargetLowering::getTgtMemIntrinsic(IntrinsicInfo &Info, // Conservatively set memVT to the entire set of vectors stored. unsigned NumElts = 0; for (unsigned ArgI = 1, ArgE = I.getNumArgOperands(); ArgI < ArgE; ++ArgI) { - const Type *ArgTy = I.getArgOperand(ArgI)->getType(); + Type *ArgTy = I.getArgOperand(ArgI)->getType(); if (!ArgTy->isVectorTy()) break; NumElts += getTargetData()->getTypeAllocSize(ArgTy) / 8; diff --git a/contrib/llvm/lib/Target/ARM/ARMISelLowering.h b/contrib/llvm/lib/Target/ARM/ARMISelLowering.h index 980fb4048..5da9b27fc 100644 --- a/contrib/llvm/lib/Target/ARM/ARMISelLowering.h +++ b/contrib/llvm/lib/Target/ARM/ARMISelLowering.h @@ -71,6 +71,11 @@ namespace llvm { SRA_FLAG, // V,Flag = sra_flag X -> sra X, 1 + save carry out. RRX, // V = RRX X, Flag -> srl X, 1 + shift in carry flag. + ADDC, // Add with carry + ADDE, // Add using carry + SUBC, // Sub with carry + SUBE, // Sub using carry + VMOVRRD, // double to two gprs. VMOVDRR, // Two gprs to double. @@ -206,18 +211,22 @@ namespace llvm { VST4_UPD, VST2LN_UPD, VST3LN_UPD, - VST4LN_UPD + VST4LN_UPD, + + // 64-bit atomic ops (value split into two registers) + ATOMADD64_DAG, + ATOMSUB64_DAG, + ATOMOR64_DAG, + ATOMXOR64_DAG, + ATOMAND64_DAG, + ATOMNAND64_DAG, + ATOMSWAP64_DAG, + ATOMCMPXCHG64_DAG }; } /// Define some predicates that are used for node matching. namespace ARM { - /// getVFPf32Imm / getVFPf64Imm - If the given fp immediate can be - /// materialized with a VMOV.f32 / VMOV.f64 (i.e. fconsts / fconstd) - /// instruction, returns its 8-bit integer representation. Otherwise, - /// returns -1. - int getVFPf32Imm(const APFloat &FPImm); - int getVFPf64Imm(const APFloat &FPImm); bool isBitFieldInvertedMask(unsigned v); } @@ -240,10 +249,16 @@ namespace llvm { virtual const char *getTargetNodeName(unsigned Opcode) const; + /// getSetCCResultType - Return the value type to use for ISD::SETCC. + virtual EVT getSetCCResultType(EVT VT) const; + virtual MachineBasicBlock * EmitInstrWithCustomInserter(MachineInstr *MI, MachineBasicBlock *MBB) const; + virtual void + AdjustInstrPostInstrSelection(MachineInstr *MI, SDNode *Node) const; + SDValue PerformCMOVCombine(SDNode *N, SelectionDAG &DAG) const; virtual SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const; @@ -256,7 +271,7 @@ namespace llvm { /// isLegalAddressingMode - Return true if the addressing mode represented /// by AM is legal for this target, for a load/store of the specified type. - virtual bool isLegalAddressingMode(const AddrMode &AM, const Type *Ty)const; + virtual bool isLegalAddressingMode(const AddrMode &AM, Type *Ty)const; bool isLegalT2ScaledAddressingMode(const AddrMode &AM, EVT VT) const; /// isLegalICmpImmediate - Return true if the specified immediate is legal @@ -485,12 +500,28 @@ namespace llvm { MachineBasicBlock *BB, unsigned Size, unsigned BinOpcode) const; + MachineBasicBlock *EmitAtomicBinary64(MachineInstr *MI, + MachineBasicBlock *BB, + unsigned Op1, + unsigned Op2, + bool NeedsCarry = false, + bool IsCmpxchg = false) const; MachineBasicBlock * EmitAtomicBinaryMinMax(MachineInstr *MI, MachineBasicBlock *BB, unsigned Size, bool signExtend, ARMCC::CondCodes Cond) const; + void EmitBasePointerRecalculation(MachineInstr *MI, MachineBasicBlock *MBB, + MachineBasicBlock *DispatchBB) const; + + void SetupEntryBlockForSjLj(MachineInstr *MI, + MachineBasicBlock *MBB, + MachineBasicBlock *DispatchBB, int FI) const; + + MachineBasicBlock *EmitSjLjDispatchBlock(MachineInstr *MI, + MachineBasicBlock *MBB) const; + bool RemapAddSubWithFlags(MachineInstr *MI, MachineBasicBlock *BB) const; }; diff --git a/contrib/llvm/lib/Target/ARM/ARMInstrFormats.td b/contrib/llvm/lib/Target/ARM/ARMInstrFormats.td index 3ccf22f80..7cbc9111d 100644 --- a/contrib/llvm/lib/Target/ARM/ARMInstrFormats.td +++ b/contrib/llvm/lib/Target/ARM/ARMInstrFormats.td @@ -25,7 +25,7 @@ def BrFrm : Format<2>; def BrMiscFrm : Format<3>; def DPFrm : Format<4>; -def DPSoRegFrm : Format<5>; +def DPSoRegRegFrm : Format<5>; def LdFrm : Format<6>; def StFrm : Format<7>; @@ -68,6 +68,7 @@ def N3RegVShFrm : Format<38>; def NVExtFrm : Format<39>; def NVMulSLFrm : Format<40>; def NVTBLFrm : Format<41>; +def DPSoRegImmFrm : Format<42>; // Misc flags. @@ -130,39 +131,15 @@ def VFPNeonA8Domain : Domain<5>; // Instructions in VFP & Neon under A8 // ARM special operands. // -def CondCodeOperand : AsmOperandClass { - let Name = "CondCode"; - let SuperClasses = []; -} - -def CCOutOperand : AsmOperandClass { - let Name = "CCOut"; - let SuperClasses = []; -} - -def MemBarrierOptOperand : AsmOperandClass { - let Name = "MemBarrierOpt"; - let SuperClasses = []; - let ParserMethod = "tryParseMemBarrierOptOperand"; -} - -def ProcIFlagsOperand : AsmOperandClass { - let Name = "ProcIFlags"; - let SuperClasses = []; - let ParserMethod = "tryParseProcIFlagsOperand"; -} - -def MSRMaskOperand : AsmOperandClass { - let Name = "MSRMask"; - let SuperClasses = []; - let ParserMethod = "tryParseMSRMaskOperand"; -} - // ARM imod and iflag operands, used only by the CPS instruction. def imod_op : Operand { let PrintMethod = "printCPSIMod"; } +def ProcIFlagsOperand : AsmOperandClass { + let Name = "ProcIFlags"; + let ParserMethod = "parseProcIFlagsOperand"; +} def iflags_op : Operand { let PrintMethod = "printCPSIFlag"; let ParserMatchClass = ProcIFlagsOperand; @@ -170,17 +147,21 @@ def iflags_op : Operand { // ARM Predicate operand. Default to 14 = always (AL). Second part is CC // register whose default is 0 (no register). -def pred : PredicateOperand { let PrintMethod = "printPredicateOperand"; let ParserMatchClass = CondCodeOperand; + let DecoderMethod = "DecodePredicateOperand"; } // Conditional code result for instructions whose 's' bit is set, e.g. subs. +def CCOutOperand : AsmOperandClass { let Name = "CCOut"; } def cc_out : OptionalDefOperand { let EncoderMethod = "getCCOutOpValue"; let PrintMethod = "printSBitModifierOperand"; let ParserMatchClass = CCOutOperand; + let DecoderMethod = "DecodeCCOutOperand"; } // Same as cc_out except it defaults to setting CPSR. @@ -188,16 +169,27 @@ def s_cc_out : OptionalDefOperand { let EncoderMethod = "getCCOutOpValue"; let PrintMethod = "printSBitModifierOperand"; let ParserMatchClass = CCOutOperand; + let DecoderMethod = "DecodeCCOutOperand"; } // ARM special operands for disassembly only. // +def SetEndAsmOperand : AsmOperandClass { + let Name = "SetEndImm"; + let ParserMethod = "parseSetEndImm"; +} def setend_op : Operand { let PrintMethod = "printSetendOperand"; + let ParserMatchClass = SetEndAsmOperand; } +def MSRMaskOperand : AsmOperandClass { + let Name = "MSRMask"; + let ParserMethod = "parseMSRMaskOperand"; +} def msr_mask : Operand { let PrintMethod = "printMSRMaskOperand"; + let DecoderMethod = "DecodeMSRMask"; let ParserMatchClass = MSRMaskOperand; } @@ -211,21 +203,40 @@ def msr_mask : Operand { // 64 64 - is encoded in imm6<5:0> def shr_imm8 : Operand { let EncoderMethod = "getShiftRight8Imm"; + let DecoderMethod = "DecodeShiftRight8Imm"; } def shr_imm16 : Operand { let EncoderMethod = "getShiftRight16Imm"; + let DecoderMethod = "DecodeShiftRight16Imm"; } def shr_imm32 : Operand { let EncoderMethod = "getShiftRight32Imm"; + let DecoderMethod = "DecodeShiftRight32Imm"; } def shr_imm64 : Operand { let EncoderMethod = "getShiftRight64Imm"; + let DecoderMethod = "DecodeShiftRight64Imm"; } +//===----------------------------------------------------------------------===// +// ARM Assembler alias templates. +// +class ARMInstAlias + : InstAlias, Requires<[IsARM]>; +class tInstAlias + : InstAlias, Requires<[IsThumb]>; +class t2InstAlias + : InstAlias, Requires<[IsThumb2]>; +class VFP2InstAlias + : InstAlias, Requires<[HasVFP2]>; +class VFP3InstAlias + : InstAlias, Requires<[HasVFP3]>; + //===----------------------------------------------------------------------===// // ARM Instruction templates. // + class InstTemplate : Instruction { @@ -240,17 +251,22 @@ class InstTemplate(f), "Pseudo"); - // The layout of TSFlags should be kept in sync with ARMBaseInstrInfo.h. + // The layout of TSFlags should be kept in sync with ARMBaseInfo.h. let TSFlags{4-0} = AM.Value; let TSFlags{6-5} = IndexModeBits; let TSFlags{12-7} = Form; let TSFlags{13} = isUnaryDataProc; let TSFlags{14} = canXformTo16Bit; let TSFlags{17-15} = D.Value; + let TSFlags{18} = thumbArithFlagSetting; let Constraints = cstr; let Itinerary = itin; @@ -262,13 +278,17 @@ class Encoding { class InstARM - : InstTemplate, Encoding; + : InstTemplate, Encoding { + let DecoderNamespace = "ARM"; +} // This Encoding-less class is used by Thumb1 to specify the encoding bits later // on by adding flavors to specific instructions. class InstThumb - : InstTemplate; + : InstTemplate { + let DecoderNamespace = "Thumb"; +} class PseudoInst pattern> : InstTemplate opcod, dag oops, dag iops, InstrItinClass itin, : I { bits<4> Rt; - bits<4> Rn; + bits<4> addr; let Inst{27-23} = 0b00011; let Inst{22-21} = opcod; let Inst{20} = 1; - let Inst{19-16} = Rn; + let Inst{19-16} = addr; let Inst{15-12} = Rt; let Inst{11-0} = 0b111110011111; } @@ -450,14 +470,14 @@ class AIstrex opcod, dag oops, dag iops, InstrItinClass itin, let Inst{3-0} = Rt; } class AIswp pattern> - : AI { + : AI { bits<4> Rt; bits<4> Rt2; - bits<4> Rn; + bits<4> addr; let Inst{27-23} = 0b00010; let Inst{22} = b; let Inst{21-20} = 0b00; - let Inst{19-16} = Rn; + let Inst{19-16} = addr; let Inst{15-12} = Rt; let Inst{11-4} = 0b00001001; let Inst{3-0} = Rt2; @@ -515,22 +535,41 @@ class AI2ldstidx pattern> + : AI2ldstidx<0, isByte, isPre, oops, iops, im, f, itin, opc, asm, cstr, + pattern> { + // AM2 store w/ two operands: (GPR, am2offset) + // {12} isAdd + // {11-0} imm12/Rm + bits<14> offset; + bits<4> Rn; + let Inst{25} = 1; + let Inst{23} = offset{12}; + let Inst{19-16} = Rn; + let Inst{11-5} = offset{11-5}; + let Inst{4} = 0; + let Inst{3-0} = offset{3-0}; +} + +class AI2stridx_imm pattern> : AI2ldstidx<0, isByte, isPre, oops, iops, im, f, itin, opc, asm, cstr, pattern> { // AM2 store w/ two operands: (GPR, am2offset) - // {13} 1 == Rm, 0 == imm12 // {12} isAdd // {11-0} imm12/Rm bits<14> offset; bits<4> Rn; - let Inst{25} = offset{13}; + let Inst{25} = 0; let Inst{23} = offset{12}; let Inst{19-16} = Rn; let Inst{11-0} = offset{11-0}; } + + // FIXME: Merge with the above class when addrmode2 gets used for STR, STRB // but for now use this class for STRT and STRBT. class AI2stridxT op, bit op20, dag oops, dag iops, Format f, let Inst{11-8} = addr{7-4}; // imm7_4/zero let Inst{7-4} = op; let Inst{3-0} = addr{3-0}; // imm3_0/Rm + + let DecoderMethod = "DecodeAddrMode3Instruction"; } -class AI3ldstidx op, bit op20, bit isLd, bit isPre, dag oops, dag iops, +class AI3ldstidx op, bit op20, bit isPre, dag oops, dag iops, IndexMode im, Format f, InstrItinClass itin, string opc, string asm, string cstr, list pattern> : I op, bit op20, bit isLd, bit isPre, dag oops, dag iops, // FIXME: Merge with the above class when addrmode2 gets used for LDR, LDRB // but for now use this class for LDRSBT, LDRHT, LDSHT. -class AI3ldstidxT op, bit op20, bit isLd, bit isPre, dag oops, dag iops, +class AI3ldstidxT op, bit isLoad, dag oops, dag iops, IndexMode im, Format f, InstrItinClass itin, string opc, string asm, string cstr, list pattern> - : I { + : I { // {13} 1 == imm8, 0 == Rm // {12-9} Rn // {8} isAdd // {7-4} imm7_4/zero // {3-0} imm3_0/Rm - bits<14> addr; - bits<4> Rt; - let Inst{27-25} = 0b000; - let Inst{24} = isPre; // P bit - let Inst{23} = addr{8}; // U bit - let Inst{22} = addr{13}; // 1 == imm8, 0 == Rm - let Inst{20} = op20; // L bit - let Inst{19-16} = addr{12-9}; // Rn - let Inst{15-12} = Rt; // Rt - let Inst{11-8} = addr{7-4}; // imm7_4/zero - let Inst{7-4} = op; - let Inst{3-0} = addr{3-0}; // imm3_0/Rm - let AsmMatchConverter = "CvtLdWriteBackRegAddrMode3"; -} - -class AI3stridx op, bit isByte, bit isPre, dag oops, dag iops, - IndexMode im, Format f, InstrItinClass itin, string opc, - string asm, string cstr, list pattern> - : AI2ldstidx<0, isByte, isPre, oops, iops, im, f, itin, opc, asm, cstr, - pattern> { - // AM3 store w/ two operands: (GPR, am3offset) - bits<14> offset; + bits<4> addr; bits<4> Rt; - bits<4> Rn; let Inst{27-25} = 0b000; - let Inst{23} = offset{8}; - let Inst{22} = offset{9}; - let Inst{19-16} = Rn; + let Inst{24} = 0; // P bit + let Inst{21} = 1; + let Inst{20} = isLoad; // L bit + let Inst{19-16} = addr; // Rn let Inst{15-12} = Rt; // Rt - let Inst{11-8} = offset{7-4}; // imm7_4/zero let Inst{7-4} = op; - let Inst{3-0} = offset{3-0}; // imm3_0/Rm } // stores @@ -648,75 +665,7 @@ class AI3str op, dag oops, dag iops, Format f, InstrItinClass itin, let Inst{11-8} = addr{7-4}; // imm7_4/zero let Inst{7-4} = op; let Inst{3-0} = addr{3-0}; // imm3_0/Rm -} - -// Pre-indexed stores -class AI3sthpr pattern> - : I { - let Inst{4} = 1; - let Inst{5} = 1; // H bit - let Inst{6} = 0; // S bit - let Inst{7} = 1; - let Inst{20} = 0; // L bit - let Inst{21} = 1; // W bit - let Inst{24} = 1; // P bit - let Inst{27-25} = 0b000; -} -class AI3stdpr pattern> - : I { - let Inst{4} = 1; - let Inst{5} = 1; // H bit - let Inst{6} = 1; // S bit - let Inst{7} = 1; - let Inst{20} = 0; // L bit - let Inst{21} = 1; // W bit - let Inst{24} = 1; // P bit - let Inst{27-25} = 0b000; -} - -// Post-indexed stores -class AI3sthpo pattern> - : I { - // {13} 1 == imm8, 0 == Rm - // {12-9} Rn - // {8} isAdd - // {7-4} imm7_4/zero - // {3-0} imm3_0/Rm - bits<14> addr; - bits<4> Rt; - let Inst{3-0} = addr{3-0}; // imm3_0/Rm - let Inst{4} = 1; - let Inst{5} = 1; // H bit - let Inst{6} = 0; // S bit - let Inst{7} = 1; - let Inst{11-8} = addr{7-4}; // imm7_4/zero - let Inst{15-12} = Rt; // Rt - let Inst{19-16} = addr{12-9}; // Rn - let Inst{20} = 0; // L bit - let Inst{21} = 0; // W bit - let Inst{22} = addr{13}; // 1 == imm8, 0 == Rm - let Inst{23} = addr{8}; // U bit - let Inst{24} = 0; // P bit - let Inst{27-25} = 0b000; -} -class AI3stdpo pattern> - : I { - let Inst{4} = 1; - let Inst{5} = 1; // H bit - let Inst{6} = 1; // S bit - let Inst{7} = 1; - let Inst{20} = 0; // L bit - let Inst{21} = 0; // W bit - let Inst{24} = 0; // P bit - let Inst{27-25} = 0b000; + let DecoderMethod = "DecodeAddrMode3Instruction"; } // addrmode4 instructions @@ -843,6 +792,23 @@ class AMiscA1I opcod, bits<4> opc7_4, dag oops, dag iops, } // PKH instructions +def PKHLSLAsmOperand : AsmOperandClass { + let Name = "PKHLSLImm"; + let ParserMethod = "parsePKHLSLImm"; +} +def pkh_lsl_amt: Operand, ImmLeaf= 0 && Imm < 32; }]>{ + let PrintMethod = "printPKHLSLShiftImm"; + let ParserMatchClass = PKHLSLAsmOperand; +} +def PKHASRAsmOperand : AsmOperandClass { + let Name = "PKHASRImm"; + let ParserMethod = "parsePKHASRImm"; +} +def pkh_asr_amt: Operand, ImmLeaf 0 && Imm <= 32; }]>{ + let PrintMethod = "printPKHASRShiftImm"; + let ParserMatchClass = PKHASRAsmOperand; +} + class APKHI opcod, bit tb, dag oops, dag iops, InstrItinClass itin, string opc, string asm, list pattern> : I opcod, bit tb, dag oops, dag iops, InstrItinClass itin, bits<4> Rd; bits<4> Rn; bits<4> Rm; - bits<8> sh; + bits<5> sh; let Inst{27-20} = opcod; let Inst{19-16} = Rn; let Inst{15-12} = Rd; - let Inst{11-7} = sh{7-3}; + let Inst{11-7} = sh; let Inst{6} = tb; let Inst{5-4} = 0b01; let Inst{3-0} = Rm; @@ -949,7 +915,9 @@ class Thumb1sI Predicates = [IsThumb, IsThumb1Only]; + let DecoderNamespace = "ThumbSBit"; } class T1sI Predicates = [IsThumb2]; + let DecoderNamespace = "Thumb2"; } // Same as Thumb2I except it can optionally modify CPSR. Note it's modeled as an @@ -1091,6 +1060,7 @@ class Thumb2sI Predicates = [IsThumb2]; + let DecoderNamespace = "Thumb2"; } // Special cases @@ -1103,6 +1073,7 @@ class Thumb2XI Predicates = [IsThumb2]; + let DecoderNamespace = "Thumb2"; } class ThumbXI Predicates = [IsThumb, IsThumb1Only]; + let DecoderNamespace = "Thumb"; } class T2I pattern> : Thumb2I; class T2Ii8s4 pattern> - : Thumb2I pattern> + : Thumb2I { bits<4> Rt; bits<4> Rt2; @@ -1149,6 +1121,26 @@ class T2Ii8s4 pattern> + : Thumb2I { + bits<4> Rt; + bits<4> Rt2; + bits<4> addr; + bits<9> imm; + let Inst{31-25} = 0b1110100; + let Inst{24} = P; + let Inst{23} = imm{8}; + let Inst{22} = 1; + let Inst{21} = W; + let Inst{20} = isLoad; + let Inst{19-16} = addr; + let Inst{15-12} = Rt{3-0}; + let Inst{11-8} = Rt2{3-0}; + let Inst{7-0} = imm{7-0}; +} class T2sI pattern> @@ -1172,8 +1164,8 @@ class T2XIt pattern> : Thumb2XI; -// T2Iidxldst - Thumb2 indexed load / store instructions. -class T2Iidxldst opcod, bit load, bit pre, +// T2Ipreldst - Thumb2 pre-indexed load / store instructions. +class T2Ipreldst opcod, bit load, bit pre, dag oops, dag iops, AddrMode am, IndexMode im, InstrItinClass itin, string opc, string asm, string cstr, list pattern> @@ -1183,25 +1175,60 @@ class T2Iidxldst opcod, bit load, bit pre, let AsmString = !strconcat(opc, "${p}", asm); let Pattern = pattern; list Predicates = [IsThumb2]; + let DecoderNamespace = "Thumb2"; + + bits<4> Rt; + bits<13> addr; let Inst{31-27} = 0b11111; let Inst{26-25} = 0b00; let Inst{24} = signed; let Inst{23} = 0; let Inst{22-21} = opcod; let Inst{20} = load; + let Inst{19-16} = addr{12-9}; + let Inst{15-12} = Rt{3-0}; let Inst{11} = 1; // (P, W) = (1, 1) Pre-indexed or (0, 1) Post-indexed let Inst{10} = pre; // The P bit. + let Inst{9} = addr{8}; // Sign bit let Inst{8} = 1; // The W bit. + let Inst{7-0} = addr{7-0}; - bits<9> addr; - let Inst{7-0} = addr{7-0}; - let Inst{9} = addr{8}; // Sign bit + let DecoderMethod = "DecodeT2LdStPre"; +} + +// T2Ipostldst - Thumb2 post-indexed load / store instructions. +class T2Ipostldst opcod, bit load, bit pre, + dag oops, dag iops, + AddrMode am, IndexMode im, InstrItinClass itin, + string opc, string asm, string cstr, list pattern> + : InstARM { + let OutOperandList = oops; + let InOperandList = !con(iops, (ins pred:$p)); + let AsmString = !strconcat(opc, "${p}", asm); + let Pattern = pattern; + list Predicates = [IsThumb2]; + let DecoderNamespace = "Thumb2"; bits<4> Rt; bits<4> Rn; + bits<9> offset; + let Inst{31-27} = 0b11111; + let Inst{26-25} = 0b00; + let Inst{24} = signed; + let Inst{23} = 0; + let Inst{22-21} = opcod; + let Inst{20} = load; + let Inst{19-16} = Rn; let Inst{15-12} = Rt{3-0}; - let Inst{19-16} = Rn{3-0}; + let Inst{11} = 1; + // (P, W) = (1, 1) Pre-indexed or (0, 1) Post-indexed + let Inst{10} = pre; // The P bit. + let Inst{9} = offset{8}; // Sign bit + let Inst{8} = 1; // The W bit. + let Inst{7-0} = offset{7-0}; + + let DecoderMethod = "DecodeT2LdStPre"; } // Tv5Pat - Same as Pat<>, but requires V5T Thumb mode. @@ -1242,6 +1269,7 @@ class VFPI Predicates = [HasVFP2]; } @@ -1257,6 +1285,7 @@ class VFPXI Predicates = [HasVFP2]; } @@ -1574,6 +1603,7 @@ class NeonI Predicates = [HasNEON]; + let DecoderNamespace = "NEON"; } // Same as NeonI except it does not have a "data type" specifier. @@ -1586,6 +1616,7 @@ class NeonXI Predicates = [HasNEON]; + let DecoderNamespace = "NEON"; } class NLdSt op21_20, bits<4> op11_8, bits<4> op7_4, @@ -1600,6 +1631,7 @@ class NLdSt op21_20, bits<4> op11_8, bits<4> op7_4, let Inst{7-4} = op7_4; let PostEncoderMethod = "NEONThumb2LoadStorePostEncoder"; + let DecoderNamespace = "NEONLoadStore"; bits<5> Vd; bits<6> Rn; @@ -1643,6 +1675,7 @@ class NDataI { let Inst{31-25} = 0b1111001; let PostEncoderMethod = "NEONThumb2DataIPostEncoder"; + let DecoderNamespace = "NEONData"; } class NDataXI { let Inst{31-25} = 0b1111001; let PostEncoderMethod = "NEONThumb2DataIPostEncoder"; + let DecoderNamespace = "NEONData"; } // NEON "one register and a modified immediate" format. @@ -1677,6 +1711,7 @@ class N1ModImm op21_19, bits<4> op11_8, bit op7, bit op6, let Inst{24} = SIMM{7}; let Inst{18-16} = SIMM{6-4}; let Inst{3-0} = SIMM{3-0}; + let DecoderMethod = "DecodeNEONModImmInstruction"; } // NEON 2 vector register format. @@ -1874,6 +1909,7 @@ class NVLaneOp opcod1, bits<4> opcod2, bits<2> opcod3, list Predicates = [HasNEON]; let PostEncoderMethod = "NEONThumb2DupPostEncoder"; + let DecoderNamespace = "NEONDup"; bits<5> V; bits<4> R; @@ -1915,7 +1951,6 @@ class NVDupLane op19_16, bit op6, dag oops, dag iops, bits<5> Vd; bits<5> Vm; - bits<4> lane; let Inst{22} = Vd{4}; let Inst{15-12} = Vd{3-0}; diff --git a/contrib/llvm/lib/Target/ARM/ARMInstrInfo.cpp b/contrib/llvm/lib/Target/ARM/ARMInstrInfo.cpp index adcbf1806..48da03f63 100644 --- a/contrib/llvm/lib/Target/ARM/ARMInstrInfo.cpp +++ b/contrib/llvm/lib/Target/ARM/ARMInstrInfo.cpp @@ -13,8 +13,8 @@ #include "ARMInstrInfo.h" #include "ARM.h" -#include "ARMAddressingModes.h" #include "ARMMachineFunctionInfo.h" +#include "MCTargetDesc/ARMAddressingModes.h" #include "llvm/ADT/STLExtras.h" #include "llvm/CodeGen/LiveVariables.h" #include "llvm/CodeGen/MachineFrameInfo.h" @@ -30,14 +30,18 @@ ARMInstrInfo::ARMInstrInfo(const ARMSubtarget &STI) unsigned ARMInstrInfo::getUnindexedOpcode(unsigned Opc) const { switch (Opc) { default: break; - case ARM::LDR_PRE: - case ARM::LDR_POST: + case ARM::LDR_PRE_IMM: + case ARM::LDR_PRE_REG: + case ARM::LDR_POST_IMM: + case ARM::LDR_POST_REG: return ARM::LDRi12; case ARM::LDRH_PRE: case ARM::LDRH_POST: return ARM::LDRH; - case ARM::LDRB_PRE: - case ARM::LDRB_POST: + case ARM::LDRB_PRE_IMM: + case ARM::LDRB_PRE_REG: + case ARM::LDRB_POST_IMM: + case ARM::LDRB_POST_REG: return ARM::LDRBi12; case ARM::LDRSH_PRE: case ARM::LDRSH_POST: @@ -45,14 +49,18 @@ unsigned ARMInstrInfo::getUnindexedOpcode(unsigned Opc) const { case ARM::LDRSB_PRE: case ARM::LDRSB_POST: return ARM::LDRSB; - case ARM::STR_PRE: - case ARM::STR_POST: + case ARM::STR_PRE_IMM: + case ARM::STR_PRE_REG: + case ARM::STR_POST_IMM: + case ARM::STR_POST_REG: return ARM::STRi12; case ARM::STRH_PRE: case ARM::STRH_POST: return ARM::STRH; - case ARM::STRB_PRE: - case ARM::STRB_POST: + case ARM::STRB_PRE_IMM: + case ARM::STRB_PRE_REG: + case ARM::STRB_POST_IMM: + case ARM::STRB_POST_REG: return ARM::STRBi12; } diff --git a/contrib/llvm/lib/Target/ARM/ARMInstrInfo.td b/contrib/llvm/lib/Target/ARM/ARMInstrInfo.td index a42dd1a54..2cf0f09ff 100644 --- a/contrib/llvm/lib/Target/ARM/ARMInstrInfo.td +++ b/contrib/llvm/lib/Target/ARM/ARMInstrInfo.td @@ -70,6 +70,18 @@ def SDT_ARMTCRET : SDTypeProfile<0, 1, [SDTCisPtrTy<0>]>; def SDT_ARMBFI : SDTypeProfile<1, 3, [SDTCisVT<0, i32>, SDTCisVT<1, i32>, SDTCisVT<2, i32>, SDTCisVT<3, i32>]>; +def SDTBinaryArithWithFlags : SDTypeProfile<2, 2, + [SDTCisSameAs<0, 2>, + SDTCisSameAs<0, 3>, + SDTCisInt<0>, SDTCisVT<1, i32>]>; + +// SDTBinaryArithWithFlagsInOut - RES1, CPSR = op LHS, RHS, CPSR +def SDTBinaryArithWithFlagsInOut : SDTypeProfile<2, 3, + [SDTCisSameAs<0, 2>, + SDTCisSameAs<0, 3>, + SDTCisInt<0>, + SDTCisVT<1, i32>, + SDTCisVT<4, i32>]>; // Node definitions. def ARMWrapper : SDNode<"ARMISD::Wrapper", SDTIntUnaryOp>; def ARMWrapperDYN : SDNode<"ARMISD::WrapperDYN", SDTIntUnaryOp>; @@ -120,6 +132,12 @@ def ARMsrl_flag : SDNode<"ARMISD::SRL_FLAG", SDTIntUnaryOp, [SDNPOutGlue]>; def ARMsra_flag : SDNode<"ARMISD::SRA_FLAG", SDTIntUnaryOp, [SDNPOutGlue]>; def ARMrrx : SDNode<"ARMISD::RRX" , SDTIntUnaryOp, [SDNPInGlue ]>; +def ARMaddc : SDNode<"ARMISD::ADDC", SDTBinaryArithWithFlags, + [SDNPCommutative]>; +def ARMsubc : SDNode<"ARMISD::SUBC", SDTBinaryArithWithFlags>; +def ARMadde : SDNode<"ARMISD::ADDE", SDTBinaryArithWithFlagsInOut>; +def ARMsube : SDNode<"ARMISD::SUBE", SDTBinaryArithWithFlagsInOut>; + def ARMthread_pointer: SDNode<"ARMISD::THREAD_POINTER", SDT_ARMThreadPointer>; def ARMeh_sjlj_setjmp: SDNode<"ARMISD::EH_SJLJ_SETJMP", SDT_ARMEH_SJLJ_Setjmp, [SDNPHasChain]>; @@ -187,10 +205,16 @@ def IsThumb : Predicate<"Subtarget->isThumb()">, def IsThumb1Only : Predicate<"Subtarget->isThumb1Only()">; def IsThumb2 : Predicate<"Subtarget->isThumb2()">, AssemblerPredicate<"ModeThumb,FeatureThumb2">; +def IsMClass : Predicate<"Subtarget->isMClass()">, + AssemblerPredicate<"FeatureMClass">; +def IsARClass : Predicate<"!Subtarget->isMClass()">, + AssemblerPredicate<"!FeatureMClass">; def IsARM : Predicate<"!Subtarget->isThumb()">, AssemblerPredicate<"!ModeThumb">; def IsDarwin : Predicate<"Subtarget->isTargetDarwin()">; def IsNotDarwin : Predicate<"!Subtarget->isTargetDarwin()">; +def IsNaCl : Predicate<"Subtarget->isTargetNaCl()">, + AssemblerPredicate<"ModeNaCl">; // FIXME: Eventually this will be just "hasV6T2Ops". def UseMovt : Predicate<"Subtarget->useMovt()">; @@ -263,24 +287,11 @@ def imm0_65535 : Operand, ImmLeaf : + PatFrag<(ops node:$LHS, node:$RHS, node:$FLAG), res>; class BinOpFrag : PatFrag<(ops node:$LHS, node:$RHS), res>; class UnOpFrag : PatFrag<(ops node:$Src), res>; -/// adde and sube predicates - True based on whether the carry flag output -/// will be needed or not. -def adde_dead_carry : - PatFrag<(ops node:$LHS, node:$RHS), (adde node:$LHS, node:$RHS), - [{return !N->hasAnyUseOfValue(1);}]>; -def sube_dead_carry : - PatFrag<(ops node:$LHS, node:$RHS), (sube node:$LHS, node:$RHS), - [{return !N->hasAnyUseOfValue(1);}]>; -def adde_live_carry : - PatFrag<(ops node:$LHS, node:$RHS), (adde node:$LHS, node:$RHS), - [{return N->hasAnyUseOfValue(1);}]>; -def sube_live_carry : - PatFrag<(ops node:$LHS, node:$RHS), (sube node:$LHS, node:$RHS), - [{return N->hasAnyUseOfValue(1);}]>; - // An 'and' node with a single use. def and_su : PatFrag<(ops node:$lhs, node:$rhs), (and node:$lhs, node:$rhs), [{ return N->hasOneUse(); @@ -315,6 +326,7 @@ def fsub_mlx : PatFrag<(ops node:$lhs, node:$rhs),(fsub node:$lhs, node:$rhs),[{ def brtarget : Operand { let EncoderMethod = "getBranchTargetOpValue"; let OperandType = "OPERAND_PCREL"; + let DecoderMethod = "DecodeT2BROperand"; } // FIXME: get rid of this one? @@ -345,39 +357,35 @@ def bl_target : Operand { let OperandType = "OPERAND_PCREL"; } - -// A list of registers separated by comma. Used by load/store multiple. -def RegListAsmOperand : AsmOperandClass { - let Name = "RegList"; - let SuperClasses = []; -} - -def DPRRegListAsmOperand : AsmOperandClass { - let Name = "DPRRegList"; - let SuperClasses = []; -} - -def SPRRegListAsmOperand : AsmOperandClass { - let Name = "SPRRegList"; - let SuperClasses = []; +def blx_target : Operand { + // Encoded the same as branch targets. + let EncoderMethod = "getARMBLXTargetOpValue"; + let OperandType = "OPERAND_PCREL"; } +// A list of registers separated by comma. Used by load/store multiple. +def RegListAsmOperand : AsmOperandClass { let Name = "RegList"; } def reglist : Operand { let EncoderMethod = "getRegisterListOpValue"; let ParserMatchClass = RegListAsmOperand; let PrintMethod = "printRegisterList"; + let DecoderMethod = "DecodeRegListOperand"; } +def DPRRegListAsmOperand : AsmOperandClass { let Name = "DPRRegList"; } def dpr_reglist : Operand { let EncoderMethod = "getRegisterListOpValue"; let ParserMatchClass = DPRRegListAsmOperand; let PrintMethod = "printRegisterList"; + let DecoderMethod = "DecodeDPRRegListOperand"; } +def SPRRegListAsmOperand : AsmOperandClass { let Name = "SPRRegList"; } def spr_reglist : Operand { let EncoderMethod = "getRegisterListOpValue"; let ParserMatchClass = SPRRegListAsmOperand; let PrintMethod = "printRegisterList"; + let DecoderMethod = "DecodeSPRRegListOperand"; } // An operand for the CONSTPOOL_ENTRY pseudo-instruction. @@ -397,56 +405,99 @@ def adrlabel : Operand { def neon_vcvt_imm32 : Operand { let EncoderMethod = "getNEONVcvtImm32OpValue"; + let DecoderMethod = "DecodeVCVTImmOperand"; } // rot_imm: An integer that encodes a rotate amount. Must be 8, 16, or 24. -def rot_imm : Operand, ImmLeaf { - let EncoderMethod = "getRotImmOpValue"; +def rot_imm_XFORM: SDNodeXFormgetZExtValue()){ + default: assert(0); + case 0: return CurDAG->getTargetConstant(0, MVT::i32); + case 8: return CurDAG->getTargetConstant(1, MVT::i32); + case 16: return CurDAG->getTargetConstant(2, MVT::i32); + case 24: return CurDAG->getTargetConstant(3, MVT::i32); + } +}]>; +def RotImmAsmOperand : AsmOperandClass { + let Name = "RotImm"; + let ParserMethod = "parseRotImm"; } - -def ShifterAsmOperand : AsmOperandClass { - let Name = "Shifter"; - let SuperClasses = []; +def rot_imm : Operand, PatLeaf<(i32 imm), [{ + int32_t v = N->getZExtValue(); + return v == 8 || v == 16 || v == 24; }], + rot_imm_XFORM> { + let PrintMethod = "printRotImmOperand"; + let ParserMatchClass = RotImmAsmOperand; } // shift_imm: An integer that encodes a shift amount and the type of shift -// (currently either asr or lsl) using the same encoding used for the -// immediates in so_reg operands. +// (asr or lsl). The 6-bit immediate encodes as: +// {5} 0 ==> lsl +// 1 asr +// {4-0} imm5 shift amount. +// asr #32 encoded as imm5 == 0. +def ShifterImmAsmOperand : AsmOperandClass { + let Name = "ShifterImm"; + let ParserMethod = "parseShifterImm"; +} def shift_imm : Operand { let PrintMethod = "printShiftImmOperand"; - let ParserMatchClass = ShifterAsmOperand; + let ParserMatchClass = ShifterImmAsmOperand; } -def ShiftedRegAsmOperand : AsmOperandClass { - let Name = "ShiftedReg"; +// shifter_operand operands: so_reg_reg, so_reg_imm, and so_imm. +def ShiftedRegAsmOperand : AsmOperandClass { let Name = "RegShiftedReg"; } +def so_reg_reg : Operand, // reg reg imm + ComplexPattern { + let EncoderMethod = "getSORegRegOpValue"; + let PrintMethod = "printSORegRegOperand"; + let DecoderMethod = "DecodeSORegRegOperand"; + let ParserMatchClass = ShiftedRegAsmOperand; + let MIOperandInfo = (ops GPRnopc, GPRnopc, i32imm); } -// shifter_operand operands: so_reg and so_imm. -def so_reg : Operand, // reg reg imm - ComplexPattern { - let EncoderMethod = "getSORegOpValue"; - let PrintMethod = "printSORegOperand"; - let ParserMatchClass = ShiftedRegAsmOperand; - let MIOperandInfo = (ops GPR, GPR, shift_imm); +def ShiftedImmAsmOperand : AsmOperandClass { let Name = "RegShiftedImm"; } +def so_reg_imm : Operand, // reg imm + ComplexPattern { + let EncoderMethod = "getSORegImmOpValue"; + let PrintMethod = "printSORegImmOperand"; + let DecoderMethod = "DecodeSORegImmOperand"; + let ParserMatchClass = ShiftedImmAsmOperand; + let MIOperandInfo = (ops GPR, i32imm); +} + +// FIXME: Does this need to be distinct from so_reg? +def shift_so_reg_reg : Operand, // reg reg imm + ComplexPattern { + let EncoderMethod = "getSORegRegOpValue"; + let PrintMethod = "printSORegRegOperand"; + let DecoderMethod = "DecodeSORegRegOperand"; + let MIOperandInfo = (ops GPR, GPR, i32imm); } + // FIXME: Does this need to be distinct from so_reg? -def shift_so_reg : Operand, // reg reg imm - ComplexPattern, // reg reg imm + ComplexPattern { - let EncoderMethod = "getSORegOpValue"; - let PrintMethod = "printSORegOperand"; - let MIOperandInfo = (ops GPR, GPR, shift_imm); + let EncoderMethod = "getSORegImmOpValue"; + let PrintMethod = "printSORegImmOperand"; + let DecoderMethod = "DecodeSORegImmOperand"; + let MIOperandInfo = (ops GPR, i32imm); } + // so_imm - Match a 32-bit shifter_operand immediate operand, which is an // 8-bit immediate rotated by an arbitrary number of bits. +def SOImmAsmOperand: AsmOperandClass { let Name = "ARMSOImm"; } def so_imm : Operand, ImmLeaf { let EncoderMethod = "getSOImmOpValue"; + let ParserMatchClass = SOImmAsmOperand; + let DecoderMethod = "DecodeSOImmOperand"; } // Break so_imm's up into two pieces. This handles immediates with up to 16 @@ -464,7 +515,7 @@ def arm_i32imm : PatLeaf<(imm), [{ return ARM_AM::isSOImmTwoPartVal((unsigned)N->getZExtValue()); }]>; -/// imm0_7 predicate - Immediate in the range [0,31]. +/// imm0_7 predicate - Immediate in the range [0,7]. def Imm0_7AsmOperand: AsmOperandClass { let Name = "Imm0_7"; } def imm0_7 : Operand, ImmLeaf= 0 && Imm < 8; @@ -472,7 +523,7 @@ def imm0_7 : Operand, ImmLeaf, ImmLeaf= 0 && Imm < 16; @@ -481,68 +532,83 @@ def imm0_15 : Operand, ImmLeaf, ImmLeaf= 0 && Imm < 32; -}]>; - -/// imm0_31_m1 - Matches and prints like imm0_31, but encodes as 'value - 1'. -def imm0_31_m1 : Operand, ImmLeaf= 0 && Imm < 32; }]> { - let EncoderMethod = "getImmMinusOneOpValue"; + let ParserMatchClass = Imm0_31AsmOperand; } -// i32imm_hilo16 - For movt/movw - sets the MC Encoder method. -// The imm is split into imm{15-12}, imm{11-0} +/// imm0_255 predicate - Immediate in the range [0,255]. +def Imm0_255AsmOperand : AsmOperandClass { let Name = "Imm0_255"; } +def imm0_255 : Operand, ImmLeaf= 0 && Imm < 256; }]> { + let ParserMatchClass = Imm0_255AsmOperand; +} + +// imm0_65535_expr - For movt/movw - 16-bit immediate that can also reference +// a relocatable expression. // -def i32imm_hilo16 : Operand { +// FIXME: This really needs a Thumb version separate from the ARM version. +// While the range is the same, and can thus use the same match class, +// the encoding is different so it should have a different encoder method. +def Imm0_65535ExprAsmOperand: AsmOperandClass { let Name = "Imm0_65535Expr"; } +def imm0_65535_expr : Operand { let EncoderMethod = "getHiLo16ImmOpValue"; + let ParserMatchClass = Imm0_65535ExprAsmOperand; +} + +/// imm24b - True if the 32-bit immediate is encodable in 24 bits. +def Imm24bitAsmOperand: AsmOperandClass { let Name = "Imm24bit"; } +def imm24b : Operand, ImmLeaf= 0 && Imm <= 0xffffff; +}]> { + let ParserMatchClass = Imm24bitAsmOperand; } + /// bf_inv_mask_imm predicate - An AND mask to clear an arbitrary width bitfield /// e.g., 0xf000ffff +def BitfieldAsmOperand : AsmOperandClass { + let Name = "Bitfield"; + let ParserMethod = "parseBitfield"; +} def bf_inv_mask_imm : Operand, PatLeaf<(imm), [{ return ARM::isBitFieldInvertedMask(N->getZExtValue()); }] > { let EncoderMethod = "getBitfieldInvertedMaskOpValue"; let PrintMethod = "printBitfieldInvMaskImmOperand"; + let DecoderMethod = "DecodeBitfieldMaskOperand"; + let ParserMatchClass = BitfieldAsmOperand; } -/// lsb_pos_imm - position of the lsb bit, used by BFI4p and t2BFI4p -def lsb_pos_imm : Operand, ImmLeaf(Imm); +def imm1_32_XFORM: SDNodeXFormgetTargetConstant((int)N->getZExtValue() - 1, MVT::i32); }]>; - -/// width_imm - number of bits to be copied, used by BFI4p and t2BFI4p -def width_imm : Operand, ImmLeaf 0 && Imm <= 32; -}] > { - let EncoderMethod = "getMsbOpValue"; -} - -def ssat_imm : Operand, ImmLeaf 0 && Imm <= 32; -}]> { - let EncoderMethod = "getSsatBitPosValue"; +def Imm1_32AsmOperand: AsmOperandClass { let Name = "Imm1_32"; } +def imm1_32 : Operand, PatLeaf<(imm), [{ + uint64_t Imm = N->getZExtValue(); + return Imm > 0 && Imm <= 32; + }], + imm1_32_XFORM> { + let PrintMethod = "printImmPlusOneOperand"; + let ParserMatchClass = Imm1_32AsmOperand; +} + +def imm1_16_XFORM: SDNodeXFormgetTargetConstant((int)N->getZExtValue() - 1, MVT::i32); +}]>; +def Imm1_16AsmOperand: AsmOperandClass { let Name = "Imm1_16"; } +def imm1_16 : Operand, PatLeaf<(imm), [{ return Imm > 0 && Imm <= 16; }], + imm1_16_XFORM> { + let PrintMethod = "printImmPlusOneOperand"; + let ParserMatchClass = Imm1_16AsmOperand; } // Define ARM specific addressing modes. - -def MemMode2AsmOperand : AsmOperandClass { - let Name = "MemMode2"; - let SuperClasses = []; - let ParserMethod = "tryParseMemMode2Operand"; -} - -def MemMode3AsmOperand : AsmOperandClass { - let Name = "MemMode3"; - let SuperClasses = []; - let ParserMethod = "tryParseMemMode3Operand"; -} - // addrmode_imm12 := reg +/- imm12 // +def MemImm12OffsetAsmOperand : AsmOperandClass { let Name = "MemImm12Offset"; } def addrmode_imm12 : Operand, ComplexPattern { // 12-bit immediate operand. Note that instructions using this encode @@ -551,53 +617,129 @@ def addrmode_imm12 : Operand, let EncoderMethod = "getAddrModeImm12OpValue"; let PrintMethod = "printAddrModeImm12Operand"; + let DecoderMethod = "DecodeAddrModeImm12Operand"; + let ParserMatchClass = MemImm12OffsetAsmOperand; let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm); } // ldst_so_reg := reg +/- reg shop imm // +def MemRegOffsetAsmOperand : AsmOperandClass { let Name = "MemRegOffset"; } def ldst_so_reg : Operand, ComplexPattern { let EncoderMethod = "getLdStSORegOpValue"; // FIXME: Simplify the printer let PrintMethod = "printAddrMode2Operand"; - let MIOperandInfo = (ops GPR:$base, GPR:$offsreg, i32imm:$offsimm); + let DecoderMethod = "DecodeSORegMemOperand"; + let ParserMatchClass = MemRegOffsetAsmOperand; + let MIOperandInfo = (ops GPR:$base, GPRnopc:$offsreg, i32imm:$shift); } +// postidx_imm8 := +/- [0,255] +// +// 9 bit value: +// {8} 1 is imm8 is non-negative. 0 otherwise. +// {7-0} [0,255] imm8 value. +def PostIdxImm8AsmOperand : AsmOperandClass { let Name = "PostIdxImm8"; } +def postidx_imm8 : Operand { + let PrintMethod = "printPostIdxImm8Operand"; + let ParserMatchClass = PostIdxImm8AsmOperand; + let MIOperandInfo = (ops i32imm); +} + +// postidx_imm8s4 := +/- [0,1020] +// +// 9 bit value: +// {8} 1 is imm8 is non-negative. 0 otherwise. +// {7-0} [0,255] imm8 value, scaled by 4. +def PostIdxImm8s4AsmOperand : AsmOperandClass { let Name = "PostIdxImm8s4"; } +def postidx_imm8s4 : Operand { + let PrintMethod = "printPostIdxImm8s4Operand"; + let ParserMatchClass = PostIdxImm8s4AsmOperand; + let MIOperandInfo = (ops i32imm); +} + + +// postidx_reg := +/- reg +// +def PostIdxRegAsmOperand : AsmOperandClass { + let Name = "PostIdxReg"; + let ParserMethod = "parsePostIdxReg"; +} +def postidx_reg : Operand { + let EncoderMethod = "getPostIdxRegOpValue"; + let DecoderMethod = "DecodePostIdxReg"; + let PrintMethod = "printPostIdxRegOperand"; + let ParserMatchClass = PostIdxRegAsmOperand; + let MIOperandInfo = (ops GPR, i32imm); +} + + // addrmode2 := reg +/- imm12 // := reg +/- reg shop imm // +// FIXME: addrmode2 should be refactored the rest of the way to always +// use explicit imm vs. reg versions above (addrmode_imm12 and ldst_so_reg). +def AddrMode2AsmOperand : AsmOperandClass { let Name = "AddrMode2"; } def addrmode2 : Operand, ComplexPattern { let EncoderMethod = "getAddrMode2OpValue"; let PrintMethod = "printAddrMode2Operand"; - let ParserMatchClass = MemMode2AsmOperand; + let ParserMatchClass = AddrMode2AsmOperand; let MIOperandInfo = (ops GPR:$base, GPR:$offsreg, i32imm:$offsimm); } -def am2offset : Operand, - ComplexPattern, + ComplexPattern { + let EncoderMethod = "getAddrMode2OffsetOpValue"; + let PrintMethod = "printAddrMode2OffsetOperand"; + // When using this for assembly, it's always as a post-index offset. + let ParserMatchClass = PostIdxRegShiftedAsmOperand; + let MIOperandInfo = (ops GPR, i32imm); +} + +// FIXME: am2offset_imm should only need the immediate, not the GPR. Having +// the GPR is purely vestigal at this point. +def AM2OffsetImmAsmOperand : AsmOperandClass { let Name = "AM2OffsetImm"; } +def am2offset_imm : Operand, + ComplexPattern { let EncoderMethod = "getAddrMode2OffsetOpValue"; let PrintMethod = "printAddrMode2OffsetOperand"; + let ParserMatchClass = AM2OffsetImmAsmOperand; let MIOperandInfo = (ops GPR, i32imm); } + // addrmode3 := reg +/- reg // addrmode3 := reg +/- imm8 // +// FIXME: split into imm vs. reg versions. +def AddrMode3AsmOperand : AsmOperandClass { let Name = "AddrMode3"; } def addrmode3 : Operand, ComplexPattern { let EncoderMethod = "getAddrMode3OpValue"; let PrintMethod = "printAddrMode3Operand"; - let ParserMatchClass = MemMode3AsmOperand; + let ParserMatchClass = AddrMode3AsmOperand; let MIOperandInfo = (ops GPR:$base, GPR:$offsreg, i32imm:$offsimm); } +// FIXME: split into imm vs. reg versions. +// FIXME: parser method to handle +/- register. +def AM3OffsetAsmOperand : AsmOperandClass { + let Name = "AM3Offset"; + let ParserMethod = "parseAM3Offset"; +} def am3offset : Operand, ComplexPattern { let EncoderMethod = "getAddrMode3OffsetOpValue"; let PrintMethod = "printAddrMode3OffsetOperand"; + let ParserMatchClass = AM3OffsetAsmOperand; let MIOperandInfo = (ops GPR, i32imm); } @@ -608,28 +750,28 @@ def ldstm_mode : OptionalDefOperand { let PrintMethod = "printLdStmModeOperand"; } -def MemMode5AsmOperand : AsmOperandClass { - let Name = "MemMode5"; - let SuperClasses = []; -} - // addrmode5 := reg +/- imm8*4 // +def AddrMode5AsmOperand : AsmOperandClass { let Name = "AddrMode5"; } def addrmode5 : Operand, ComplexPattern { let PrintMethod = "printAddrMode5Operand"; - let MIOperandInfo = (ops GPR:$base, i32imm); - let ParserMatchClass = MemMode5AsmOperand; let EncoderMethod = "getAddrMode5OpValue"; + let DecoderMethod = "DecodeAddrMode5Operand"; + let ParserMatchClass = AddrMode5AsmOperand; + let MIOperandInfo = (ops GPR:$base, i32imm); } // addrmode6 := reg with optional alignment // +def AddrMode6AsmOperand : AsmOperandClass { let Name = "AlignedMemory"; } def addrmode6 : Operand, ComplexPattern{ let PrintMethod = "printAddrMode6Operand"; - let MIOperandInfo = (ops GPR:$addr, i32imm); + let MIOperandInfo = (ops GPR:$addr, i32imm:$align); let EncoderMethod = "getAddrMode6AddressOpValue"; + let DecoderMethod = "DecodeAddrMode6Operand"; + let ParserMatchClass = AddrMode6AsmOperand; } def am6offset : Operand, @@ -638,6 +780,7 @@ def am6offset : Operand, let PrintMethod = "printAddrMode6OffsetOperand"; let MIOperandInfo = (ops GPR); let EncoderMethod = "getAddrMode6OffsetOpValue"; + let DecoderMethod = "DecodeGPRRegisterClass"; } // Special version of addrmode6 to handle alignment encoding for VST1/VLD1 @@ -666,19 +809,15 @@ def addrmodepc : Operand, let MIOperandInfo = (ops GPR, i32imm); } -def MemMode7AsmOperand : AsmOperandClass { - let Name = "MemMode7"; - let SuperClasses = []; -} - -// addrmode7 := reg -// Used by load/store exclusive instructions. Useful to enable right assembly -// parsing and printing. Not used for any codegen matching. +// addr_offset_none := reg // -def addrmode7 : Operand { +def MemNoOffsetAsmOperand : AsmOperandClass { let Name = "MemNoOffset"; } +def addr_offset_none : Operand, + ComplexPattern { let PrintMethod = "printAddrMode7Operand"; - let MIOperandInfo = (ops GPR); - let ParserMatchClass = MemMode7AsmOperand; + let DecoderMethod = "DecodeAddrMode7Operand"; + let ParserMatchClass = MemNoOffsetAsmOperand; + let MIOperandInfo = (ops GPR:$base); } def nohash_imm : Operand { @@ -687,25 +826,30 @@ def nohash_imm : Operand { def CoprocNumAsmOperand : AsmOperandClass { let Name = "CoprocNum"; - let SuperClasses = []; - let ParserMethod = "tryParseCoprocNumOperand"; -} - -def CoprocRegAsmOperand : AsmOperandClass { - let Name = "CoprocReg"; - let SuperClasses = []; - let ParserMethod = "tryParseCoprocRegOperand"; + let ParserMethod = "parseCoprocNumOperand"; } - def p_imm : Operand { let PrintMethod = "printPImmediate"; let ParserMatchClass = CoprocNumAsmOperand; + let DecoderMethod = "DecodeCoprocessor"; } +def CoprocRegAsmOperand : AsmOperandClass { + let Name = "CoprocReg"; + let ParserMethod = "parseCoprocRegOperand"; +} def c_imm : Operand { let PrintMethod = "printCImmediate"; let ParserMatchClass = CoprocRegAsmOperand; } +def CoprocOptionAsmOperand : AsmOperandClass { + let Name = "CoprocOption"; + let ParserMethod = "parseCoprocOptionOperand"; +} +def coproc_option_imm : Operand { + let PrintMethod = "printCoprocOptionImm"; + let ParserMatchClass = CoprocOptionAsmOperand; +} //===----------------------------------------------------------------------===// @@ -748,16 +892,37 @@ multiclass AsI1_bin_irs opcod, string opc, let Inst{11-4} = 0b00000000; let Inst{3-0} = Rm; } - def rs : AsI1 { + bits<4> Rd; + bits<4> Rn; + bits<12> shift; + let Inst{25} = 0; + let Inst{19-16} = Rn; + let Inst{15-12} = Rd; + let Inst{11-5} = shift{11-5}; + let Inst{4} = 0; + let Inst{3-0} = shift{3-0}; + } + + def rsr : AsI1 { + [(set GPR:$Rd, (opnode GPR:$Rn, so_reg_reg:$shift))]> { bits<4> Rd; bits<4> Rn; bits<12> shift; let Inst{25} = 0; let Inst{19-16} = Rn; let Inst{15-12} = Rd; - let Inst{11-0} = shift; + let Inst{11-8} = shift{11-8}; + let Inst{7} = 0; + let Inst{6-5} = shift{6-5}; + let Inst{4} = 1; + let Inst{3-0} = shift{3-0}; } // Assembly aliases for optional destination operand when it's the same @@ -773,59 +938,175 @@ multiclass AsI1_bin_irs opcod, string opc, cc_out:$s)>, Requires<[IsARM]>; def : InstAlias(!strconcat(baseOpc, "rs")) GPR:$Rdn, GPR:$Rdn, - so_reg:$shift, pred:$p, + (!cast(!strconcat(baseOpc, "rsi")) GPR:$Rdn, GPR:$Rdn, + so_reg_imm:$shift, pred:$p, cc_out:$s)>, Requires<[IsARM]>; + def : InstAlias(!strconcat(baseOpc, "rsr")) GPR:$Rdn, GPR:$Rdn, + so_reg_reg:$shift, pred:$p, + cc_out:$s)>, + Requires<[IsARM]>; + } -/// AI1_bin_s_irs - Similar to AsI1_bin_irs except it sets the 's' bit so the -/// instruction modifies the CPSR register. -let isCodeGenOnly = 1, Defs = [CPSR] in { -multiclass AI1_bin_s_irs opcod, string opc, +/// AsI1_rbin_irs - Same as AsI1_bin_irs except the order of operands are +/// reversed. The 'rr' form is only defined for the disassembler; for codegen +/// it is equivalent to the AsI1_bin_irs counterpart. +multiclass AsI1_rbin_irs opcod, string opc, InstrItinClass iii, InstrItinClass iir, InstrItinClass iis, - PatFrag opnode, bit Commutable = 0> { - def ri : AI1 { + // The register-immediate version is re-materializable. This is useful + // in particular for taking the address of a local. + let isReMaterializable = 1 in { + def ri : AsI1 { + [(set GPR:$Rd, (opnode so_imm:$imm, GPR:$Rn))]> { bits<4> Rd; bits<4> Rn; bits<12> imm; let Inst{25} = 1; - let Inst{20} = 1; let Inst{19-16} = Rn; let Inst{15-12} = Rd; let Inst{11-0} = imm; } - def rr : AI1 { + [/* pattern left blank */]> { bits<4> Rd; bits<4> Rn; bits<4> Rm; - let isCommutable = Commutable; + let Inst{11-4} = 0b00000000; + let Inst{25} = 0; + let Inst{3-0} = Rm; + let Inst{15-12} = Rd; + let Inst{19-16} = Rn; + } + + def rsi : AsI1 { + bits<4> Rd; + bits<4> Rn; + bits<12> shift; let Inst{25} = 0; - let Inst{20} = 1; let Inst{19-16} = Rn; let Inst{15-12} = Rd; - let Inst{11-4} = 0b00000000; - let Inst{3-0} = Rm; + let Inst{11-5} = shift{11-5}; + let Inst{4} = 0; + let Inst{3-0} = shift{3-0}; } - def rs : AI1 { + [(set GPR:$Rd, (opnode so_reg_reg:$shift, GPR:$Rn))]> { + bits<4> Rd; + bits<4> Rn; + bits<12> shift; + let Inst{25} = 0; + let Inst{19-16} = Rn; + let Inst{15-12} = Rd; + let Inst{11-8} = shift{11-8}; + let Inst{7} = 0; + let Inst{6-5} = shift{6-5}; + let Inst{4} = 1; + let Inst{3-0} = shift{3-0}; + } + + // Assembly aliases for optional destination operand when it's the same + // as the source operand. + def : InstAlias(!strconcat(baseOpc, "ri")) GPR:$Rdn, GPR:$Rdn, + so_imm:$imm, pred:$p, + cc_out:$s)>, + Requires<[IsARM]>; + def : InstAlias(!strconcat(baseOpc, "rr")) GPR:$Rdn, GPR:$Rdn, + GPR:$Rm, pred:$p, + cc_out:$s)>, + Requires<[IsARM]>; + def : InstAlias(!strconcat(baseOpc, "rsi")) GPR:$Rdn, GPR:$Rdn, + so_reg_imm:$shift, pred:$p, + cc_out:$s)>, + Requires<[IsARM]>; + def : InstAlias(!strconcat(baseOpc, "rsr")) GPR:$Rdn, GPR:$Rdn, + so_reg_reg:$shift, pred:$p, + cc_out:$s)>, + Requires<[IsARM]>; + +} + +/// AsI1_rbin_s_is - Same as AsI1_rbin_s_is except it sets 's' bit by default. +/// +/// These opcodes will be converted to the real non-S opcodes by +/// AdjustInstrPostInstrSelection after giving then an optional CPSR operand. +let hasPostISelHook = 1, isCodeGenOnly = 1, isPseudo = 1, Defs = [CPSR] in { +multiclass AsI1_rbin_s_is opcod, string opc, + InstrItinClass iii, InstrItinClass iir, InstrItinClass iis, + PatFrag opnode, bit Commutable = 0> { + def ri : AsI1; + + def rr : AsI1; + + def rsi : AsI1; + + def rsr : AsI1 { bits<4> Rd; bits<4> Rn; bits<12> shift; let Inst{25} = 0; - let Inst{20} = 1; let Inst{19-16} = Rn; let Inst{15-12} = Rd; - let Inst{11-0} = shift; + let Inst{11-8} = shift{11-8}; + let Inst{7} = 0; + let Inst{6-5} = shift{6-5}; + let Inst{4} = 1; + let Inst{3-0} = shift{3-0}; } } } +/// AsI1_bin_s_irs - Same as AsI1_bin_irs except it sets the 's' bit by default. +/// +/// These opcodes will be converted to the real non-S opcodes by +/// AdjustInstrPostInstrSelection after giving then an optional CPSR operand. +let hasPostISelHook = 1, isCodeGenOnly = 1, isPseudo = 1, Defs = [CPSR] in { +multiclass AsI1_bin_s_irs opcod, string opc, + InstrItinClass iii, InstrItinClass iir, InstrItinClass iis, + PatFrag opnode, bit Commutable = 0> { + def ri : AsI1; + def rr : AsI1; + def rsi : AsI1; + + def rsr : AsI1; +} +} + /// AI1_cmp_irs - Defines a set of (op r, {so_imm|r|so_reg}) cmp / test /// patterns. Similar to AsI1_bin_irs except the instruction does not produce /// a explicit result, only implicitly set CPSR. @@ -857,128 +1138,190 @@ multiclass AI1_cmp_irs opcod, string opc, let Inst{11-4} = 0b00000000; let Inst{3-0} = Rm; } - def rs : AI1 { + [(opnode GPR:$Rn, so_reg_imm:$shift)]> { bits<4> Rn; bits<12> shift; let Inst{25} = 0; let Inst{20} = 1; let Inst{19-16} = Rn; let Inst{15-12} = 0b0000; - let Inst{11-0} = shift; + let Inst{11-5} = shift{11-5}; + let Inst{4} = 0; + let Inst{3-0} = shift{3-0}; } + def rsr : AI1 { + bits<4> Rn; + bits<12> shift; + let Inst{25} = 0; + let Inst{20} = 1; + let Inst{19-16} = Rn; + let Inst{15-12} = 0b0000; + let Inst{11-8} = shift{11-8}; + let Inst{7} = 0; + let Inst{6-5} = shift{6-5}; + let Inst{4} = 1; + let Inst{3-0} = shift{3-0}; + } + } } /// AI_ext_rrot - A unary operation with two forms: one whose operand is a /// register and one whose operand is a register rotated by 8/16/24. /// FIXME: Remove the 'r' variant. Its rot_imm is zero. -multiclass AI_ext_rrot opcod, string opc, PatFrag opnode> { - def r : AExtI, - Requires<[IsARM, HasV6]> { - bits<4> Rd; - bits<4> Rm; - let Inst{19-16} = 0b1111; - let Inst{15-12} = Rd; - let Inst{11-10} = 0b00; - let Inst{3-0} = Rm; - } - def r_rot : AExtI, - Requires<[IsARM, HasV6]> { - bits<4> Rd; - bits<4> Rm; - bits<2> rot; - let Inst{19-16} = 0b1111; - let Inst{15-12} = Rd; - let Inst{11-10} = rot; - let Inst{3-0} = Rm; - } +class AI_ext_rrot opcod, string opc, PatFrag opnode> + : AExtI, + Requires<[IsARM, HasV6]> { + bits<4> Rd; + bits<4> Rm; + bits<2> rot; + let Inst{19-16} = 0b1111; + let Inst{15-12} = Rd; + let Inst{11-10} = rot; + let Inst{3-0} = Rm; } -multiclass AI_ext_rrot_np opcod, string opc> { - def r : AExtI, - Requires<[IsARM, HasV6]> { - let Inst{19-16} = 0b1111; - let Inst{11-10} = 0b00; - } - def r_rot : AExtI, - Requires<[IsARM, HasV6]> { - bits<2> rot; - let Inst{19-16} = 0b1111; - let Inst{11-10} = rot; - } +class AI_ext_rrot_np opcod, string opc> + : AExtI, + Requires<[IsARM, HasV6]> { + bits<2> rot; + let Inst{19-16} = 0b1111; + let Inst{11-10} = rot; } /// AI_exta_rrot - A binary operation with two forms: one whose operand is a /// register and one whose operand is a register rotated by 8/16/24. -multiclass AI_exta_rrot opcod, string opc, PatFrag opnode> { - def rr : AExtI, - Requires<[IsARM, HasV6]> { +class AI_exta_rrot opcod, string opc, PatFrag opnode> + : AExtI, + Requires<[IsARM, HasV6]> { + bits<4> Rd; + bits<4> Rm; + bits<4> Rn; + bits<2> rot; + let Inst{19-16} = Rn; + let Inst{15-12} = Rd; + let Inst{11-10} = rot; + let Inst{9-4} = 0b000111; + let Inst{3-0} = Rm; +} + +class AI_exta_rrot_np opcod, string opc> + : AExtI, + Requires<[IsARM, HasV6]> { + bits<4> Rn; + bits<2> rot; + let Inst{19-16} = Rn; + let Inst{11-10} = rot; +} + +/// AI1_adde_sube_irs - Define instructions and patterns for adde and sube. +multiclass AI1_adde_sube_irs opcod, string opc, PatFrag opnode, + string baseOpc, bit Commutable = 0> { + let hasPostISelHook = 1, Defs = [CPSR], Uses = [CPSR] in { + def ri : AsI1, + Requires<[IsARM]> { bits<4> Rd; - bits<4> Rm; bits<4> Rn; - let Inst{19-16} = Rn; + bits<12> imm; + let Inst{25} = 1; let Inst{15-12} = Rd; - let Inst{11-10} = 0b00; - let Inst{9-4} = 0b000111; - let Inst{3-0} = Rm; - } - def rr_rot : AExtI, - Requires<[IsARM, HasV6]> { + let Inst{19-16} = Rn; + let Inst{11-0} = imm; + } + def rr : AsI1, + Requires<[IsARM]> { bits<4> Rd; + bits<4> Rn; bits<4> Rm; + let Inst{11-4} = 0b00000000; + let Inst{25} = 0; + let isCommutable = Commutable; + let Inst{3-0} = Rm; + let Inst{15-12} = Rd; + let Inst{19-16} = Rn; + } + def rsi : AsI1, + Requires<[IsARM]> { + bits<4> Rd; bits<4> Rn; - bits<2> rot; + bits<12> shift; + let Inst{25} = 0; let Inst{19-16} = Rn; let Inst{15-12} = Rd; - let Inst{11-10} = rot; - let Inst{9-4} = 0b000111; - let Inst{3-0} = Rm; - } -} - -// For disassembly only. -multiclass AI_exta_rrot_np opcod, string opc> { - def rr : AExtI, - Requires<[IsARM, HasV6]> { - let Inst{11-10} = 0b00; + let Inst{11-5} = shift{11-5}; + let Inst{4} = 0; + let Inst{3-0} = shift{3-0}; } - def rr_rot : AExtI, - Requires<[IsARM, HasV6]> { + def rsr : AsI1, + Requires<[IsARM]> { + bits<4> Rd; bits<4> Rn; - bits<2> rot; + bits<12> shift; + let Inst{25} = 0; let Inst{19-16} = Rn; - let Inst{11-10} = rot; + let Inst{15-12} = Rd; + let Inst{11-8} = shift{11-8}; + let Inst{7} = 0; + let Inst{6-5} = shift{6-5}; + let Inst{4} = 1; + let Inst{3-0} = shift{3-0}; + } } + + // Assembly aliases for optional destination operand when it's the same + // as the source operand. + def : InstAlias(!strconcat(baseOpc, "ri")) GPR:$Rdn, GPR:$Rdn, + so_imm:$imm, pred:$p, + cc_out:$s)>, + Requires<[IsARM]>; + def : InstAlias(!strconcat(baseOpc, "rr")) GPR:$Rdn, GPR:$Rdn, + GPR:$Rm, pred:$p, + cc_out:$s)>, + Requires<[IsARM]>; + def : InstAlias(!strconcat(baseOpc, "rsi")) GPR:$Rdn, GPR:$Rdn, + so_reg_imm:$shift, pred:$p, + cc_out:$s)>, + Requires<[IsARM]>; + def : InstAlias(!strconcat(baseOpc, "rsr")) GPR:$Rdn, GPR:$Rdn, + so_reg_reg:$shift, pred:$p, + cc_out:$s)>, + Requires<[IsARM]>; } -/// AI1_adde_sube_irs - Define instructions and patterns for adde and sube. -multiclass AI1_adde_sube_irs opcod, string opc, PatFrag opnode, - string baseOpc, bit Commutable = 0> { - let Uses = [CPSR] in { +/// AI1_rsc_irs - Define instructions and patterns for rsc +multiclass AI1_rsc_irs opcod, string opc, PatFrag opnode, + string baseOpc> { + let hasPostISelHook = 1, Defs = [CPSR], Uses = [CPSR] in { def ri : AsI1, + [(set GPR:$Rd, CPSR, (opnode so_imm:$imm, GPR:$Rn, CPSR))]>, Requires<[IsARM]> { bits<4> Rd; bits<4> Rn; @@ -990,31 +1333,48 @@ multiclass AI1_adde_sube_irs opcod, string opc, PatFrag opnode, } def rr : AsI1, - Requires<[IsARM]> { + [/* pattern left blank */]> { bits<4> Rd; bits<4> Rn; bits<4> Rm; let Inst{11-4} = 0b00000000; let Inst{25} = 0; - let isCommutable = Commutable; let Inst{3-0} = Rm; let Inst{15-12} = Rd; let Inst{19-16} = Rn; } - def rs : AsI1, + def rsi : AsI1, Requires<[IsARM]> { bits<4> Rd; bits<4> Rn; bits<12> shift; let Inst{25} = 0; - let Inst{11-0} = shift; + let Inst{19-16} = Rn; let Inst{15-12} = Rd; + let Inst{11-5} = shift{11-5}; + let Inst{4} = 0; + let Inst{3-0} = shift{3-0}; + } + def rsr : AsI1, + Requires<[IsARM]> { + bits<4> Rd; + bits<4> Rn; + bits<12> shift; + let Inst{25} = 0; let Inst{19-16} = Rn; + let Inst{15-12} = Rd; + let Inst{11-8} = shift{11-8}; + let Inst{7} = 0; + let Inst{6-5} = shift{6-5}; + let Inst{4} = 1; + let Inst{3-0} = shift{3-0}; } } + // Assembly aliases for optional destination operand when it's the same // as the source operand. def : InstAlias opcod, string opc, PatFrag opnode, cc_out:$s)>, Requires<[IsARM]>; def : InstAlias(!strconcat(baseOpc, "rs")) GPR:$Rdn, GPR:$Rdn, - so_reg:$shift, pred:$p, + (!cast(!strconcat(baseOpc, "rsi")) GPR:$Rdn, GPR:$Rdn, + so_reg_imm:$shift, pred:$p, + cc_out:$s)>, + Requires<[IsARM]>; + def : InstAlias(!strconcat(baseOpc, "rsr")) GPR:$Rdn, GPR:$Rdn, + so_reg_reg:$shift, pred:$p, cc_out:$s)>, Requires<[IsARM]>; -} - -// Carry setting variants -// NOTE: CPSR def omitted because it will be handled by the custom inserter. -let usesCustomInserter = 1 in { -multiclass AI1_adde_sube_s_irs { - def ri : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, so_imm:$imm), - 4, IIC_iALUi, - [(set GPR:$Rd, (opnode GPR:$Rn, so_imm:$imm))]>; - def rr : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm), - 4, IIC_iALUr, - [(set GPR:$Rd, (opnode GPR:$Rn, GPR:$Rm))]> { - let isCommutable = Commutable; - } - def rs : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, so_reg:$shift), - 4, IIC_iALUsr, - [(set GPR:$Rd, (opnode GPR:$Rn, so_reg:$shift))]>; -} } let canFoldAsLoad = 1, isReMaterializable = 1 in { @@ -1082,6 +1429,37 @@ multiclass AI_ldr1 { + // Note: We use the complex addrmode_imm12 rather than just an input + // GPR and a constrained immediate so that we can use this to match + // frame index references and avoid matching constant pool references. + def i12: AI2ldst<0b010, 1, isByte, (outs GPRnopc:$Rt), (ins addrmode_imm12:$addr), + AddrMode_i12, LdFrm, iii, opc, "\t$Rt, $addr", + [(set GPRnopc:$Rt, (opnode addrmode_imm12:$addr))]> { + bits<4> Rt; + bits<17> addr; + let Inst{23} = addr{12}; // U (add = ('U' == 1)) + let Inst{19-16} = addr{16-13}; // Rn + let Inst{15-12} = Rt; + let Inst{11-0} = addr{11-0}; // imm12 + } + def rs : AI2ldst<0b011, 1, isByte, (outs GPRnopc:$Rt), (ins ldst_so_reg:$shift), + AddrModeNone, LdFrm, iir, opc, "\t$Rt, $shift", + [(set GPRnopc:$Rt, (opnode ldst_so_reg:$shift))]> { + bits<4> Rt; + bits<17> shift; + let shift{4} = 0; // Inst{4} = 0 + let Inst{23} = shift{12}; // U (add = ('U' == 1)) + let Inst{19-16} = shift{16-13}; // Rn + let Inst{15-12} = Rt; + let Inst{11-0} = shift{11-0}; + } +} +} + + multiclass AI_str1 { // Note: We use the complex addrmode_imm12 rather than just an input @@ -1110,6 +1488,37 @@ multiclass AI_str1 { + // Note: We use the complex addrmode_imm12 rather than just an input + // GPR and a constrained immediate so that we can use this to match + // frame index references and avoid matching constant pool references. + def i12 : AI2ldst<0b010, 0, isByte, (outs), + (ins GPRnopc:$Rt, addrmode_imm12:$addr), + AddrMode_i12, StFrm, iii, opc, "\t$Rt, $addr", + [(opnode GPRnopc:$Rt, addrmode_imm12:$addr)]> { + bits<4> Rt; + bits<17> addr; + let Inst{23} = addr{12}; // U (add = ('U' == 1)) + let Inst{19-16} = addr{16-13}; // Rn + let Inst{15-12} = Rt; + let Inst{11-0} = addr{11-0}; // imm12 + } + def rs : AI2ldst<0b011, 0, isByte, (outs), (ins GPRnopc:$Rt, ldst_so_reg:$shift), + AddrModeNone, StFrm, iir, opc, "\t$Rt, $shift", + [(opnode GPRnopc:$Rt, ldst_so_reg:$shift)]> { + bits<4> Rt; + bits<17> shift; + let shift{4} = 0; // Inst{4} = 0 + let Inst{23} = shift{12}; // U (add = ('U' == 1)) + let Inst{19-16} = shift{16-13}; // Rn + let Inst{15-12} = Rt; + let Inst{11-0} = shift{11-0}; + } +} + + //===----------------------------------------------------------------------===// // Instructions //===----------------------------------------------------------------------===// @@ -1140,42 +1549,66 @@ PseudoInst<(outs), (ins i32imm:$amt, pred:$p), NoItinerary, [(ARMcallseq_start timm:$amt)]>; } -def NOP : AI<(outs), (ins), MiscFrm, NoItinerary, "nop", "", - [/* For disassembly only; pattern left blank */]>, +// Atomic pseudo-insts which will be lowered to ldrexd/strexd loops. +// (These psuedos use a hand-written selection code). +let usesCustomInserter = 1, Defs = [CPSR], mayLoad = 1, mayStore = 1 in { +def ATOMOR6432 : PseudoInst<(outs GPR:$dst1, GPR:$dst2), + (ins GPR:$addr, GPR:$src1, GPR:$src2), + NoItinerary, []>; +def ATOMXOR6432 : PseudoInst<(outs GPR:$dst1, GPR:$dst2), + (ins GPR:$addr, GPR:$src1, GPR:$src2), + NoItinerary, []>; +def ATOMADD6432 : PseudoInst<(outs GPR:$dst1, GPR:$dst2), + (ins GPR:$addr, GPR:$src1, GPR:$src2), + NoItinerary, []>; +def ATOMSUB6432 : PseudoInst<(outs GPR:$dst1, GPR:$dst2), + (ins GPR:$addr, GPR:$src1, GPR:$src2), + NoItinerary, []>; +def ATOMNAND6432 : PseudoInst<(outs GPR:$dst1, GPR:$dst2), + (ins GPR:$addr, GPR:$src1, GPR:$src2), + NoItinerary, []>; +def ATOMAND6432 : PseudoInst<(outs GPR:$dst1, GPR:$dst2), + (ins GPR:$addr, GPR:$src1, GPR:$src2), + NoItinerary, []>; +def ATOMSWAP6432 : PseudoInst<(outs GPR:$dst1, GPR:$dst2), + (ins GPR:$addr, GPR:$src1, GPR:$src2), + NoItinerary, []>; +def ATOMCMPXCHG6432 : PseudoInst<(outs GPR:$dst1, GPR:$dst2), + (ins GPR:$addr, GPR:$cmp1, GPR:$cmp2, + GPR:$set1, GPR:$set2), + NoItinerary, []>; +} + +def NOP : AI<(outs), (ins), MiscFrm, NoItinerary, "nop", "", []>, Requires<[IsARM, HasV6T2]> { let Inst{27-16} = 0b001100100000; let Inst{15-8} = 0b11110000; let Inst{7-0} = 0b00000000; } -def YIELD : AI<(outs), (ins), MiscFrm, NoItinerary, "yield", "", - [/* For disassembly only; pattern left blank */]>, +def YIELD : AI<(outs), (ins), MiscFrm, NoItinerary, "yield", "", []>, Requires<[IsARM, HasV6T2]> { let Inst{27-16} = 0b001100100000; let Inst{15-8} = 0b11110000; let Inst{7-0} = 0b00000001; } -def WFE : AI<(outs), (ins), MiscFrm, NoItinerary, "wfe", "", - [/* For disassembly only; pattern left blank */]>, +def WFE : AI<(outs), (ins), MiscFrm, NoItinerary, "wfe", "", []>, Requires<[IsARM, HasV6T2]> { let Inst{27-16} = 0b001100100000; let Inst{15-8} = 0b11110000; let Inst{7-0} = 0b00000010; } -def WFI : AI<(outs), (ins), MiscFrm, NoItinerary, "wfi", "", - [/* For disassembly only; pattern left blank */]>, +def WFI : AI<(outs), (ins), MiscFrm, NoItinerary, "wfi", "", []>, Requires<[IsARM, HasV6T2]> { let Inst{27-16} = 0b001100100000; let Inst{15-8} = 0b11110000; let Inst{7-0} = 0b00000011; } -def SEL : AI<(outs GPR:$dst), (ins GPR:$a, GPR:$b), DPFrm, NoItinerary, "sel", - "\t$dst, $a, $b", - [/* For disassembly only; pattern left blank */]>, - Requires<[IsARM, HasV6]> { +def SEL : AI<(outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm), DPFrm, NoItinerary, "sel", + "\t$Rd, $Rn, $Rm", []>, Requires<[IsARM, HasV6]> { bits<4> Rd; bits<4> Rn; bits<4> Rm; @@ -1188,8 +1621,7 @@ def SEL : AI<(outs GPR:$dst), (ins GPR:$a, GPR:$b), DPFrm, NoItinerary, "sel", } def SEV : AI<(outs), (ins), MiscFrm, NoItinerary, "sev", "", - [/* For disassembly only; pattern left blank */]>, - Requires<[IsARM, HasV6T2]> { + []>, Requires<[IsARM, HasV6T2]> { let Inst{27-16} = 0b001100100000; let Inst{15-8} = 0b11110000; let Inst{7-0} = 0b00000100; @@ -1206,14 +1638,11 @@ def BKPT : AI<(outs), (ins imm0_65535:$val), MiscFrm, NoItinerary, let Inst{7-4} = 0b0111; } -// Change Processor State is a system instruction -- for disassembly and -// parsing only. -// FIXME: Since the asm parser has currently no clean way to handle optional -// operands, create 3 versions of the same instruction. Once there's a clean -// framework to represent optional operands, change this behavior. +// Change Processor State +// FIXME: We should use InstAlias to handle the optional operands. class CPS : AXI<(outs), iops, MiscFrm, NoItinerary, !strconcat("cps", asm_ops), - [/* For disassembly only; pattern left blank */]>, Requires<[IsARM]> { + []>, Requires<[IsARM]> { bits<2> imod; bits<3> iflags; bits<5> mode; @@ -1229,17 +1658,18 @@ class CPS let Inst{4-0} = mode; } +let DecoderMethod = "DecodeCPSInstruction" in { let M = 1 in - def CPS3p : CPS<(ins imod_op:$imod, iflags_op:$iflags, i32imm:$mode), + def CPS3p : CPS<(ins imod_op:$imod, iflags_op:$iflags, imm0_31:$mode), "$imod\t$iflags, $mode">; let mode = 0, M = 0 in def CPS2p : CPS<(ins imod_op:$imod, iflags_op:$iflags), "$imod\t$iflags">; let imod = 0, iflags = 0, M = 1 in - def CPS1p : CPS<(ins i32imm:$mode), "\t$mode">; + def CPS1p : CPS<(ins imm0_31:$mode), "\t$mode">; +} // Preload signals the memory system of possible future data/instruction access. -// These are for disassembly only. multiclass APreLoad read, bits<1> data, string opc> { def i12 : AXI<(outs), (ins addrmode_imm12:$addr), MiscFrm, IIC_Preload, @@ -1271,6 +1701,7 @@ multiclass APreLoad read, bits<1> data, string opc> { let Inst{19-16} = shift{16-13}; // Rn let Inst{15-12} = 0b1111; let Inst{11-0} = shift{11-0}; + let Inst{4} = 0; } } @@ -1278,10 +1709,8 @@ defm PLD : APreLoad<1, 1, "pld">, Requires<[IsARM]>; defm PLDW : APreLoad<0, 1, "pldw">, Requires<[IsARM,HasV7,HasMP]>; defm PLI : APreLoad<1, 0, "pli">, Requires<[IsARM,HasV7]>; -def SETEND : AXI<(outs),(ins setend_op:$end), MiscFrm, NoItinerary, - "setend\t$end", - [/* For disassembly only; pattern left blank */]>, - Requires<[IsARM]> { +def SETEND : AXI<(outs), (ins setend_op:$end), MiscFrm, NoItinerary, + "setend\t$end", []>, Requires<[IsARM]> { bits<1> end; let Inst{31-10} = 0b1111000100000001000000; let Inst{9} = end; @@ -1351,14 +1780,17 @@ let neverHasSideEffects = 1, isReMaterializable = 1 in // the instruction. The {24-21} opcode bits are set by the fixup, as we don't // know until then which form of the instruction will be used. def ADR : AI1<{0,?,?,0}, (outs GPR:$Rd), (ins adrlabel:$label), - MiscFrm, IIC_iALUi, "adr", "\t$Rd, #$label", []> { + MiscFrm, IIC_iALUi, "adr", "\t$Rd, $label", []> { bits<4> Rd; - bits<12> label; + bits<14> label; let Inst{27-25} = 0b001; + let Inst{24} = 0; + let Inst{23-22} = label{13-12}; + let Inst{21} = 0; let Inst{20} = 0; let Inst{19-16} = 0b1111; let Inst{15-12} = Rd; - let Inst{11-0} = label; + let Inst{11-0} = label{11-0}; } def LEApcrel : ARMPseudoInst<(outs GPR:$Rd), (ins i32imm:$label, pred:$p), 4, IIC_iALUi, []>; @@ -1424,6 +1856,7 @@ let isCall = 1, let Inst{31-28} = 0b1110; bits<24> func; let Inst{23-0} = func; + let DecoderMethod = "DecodeBranchImmInstruction"; } def BL_pred : ABI<0b1011, (outs), (ins bl_target:$func, variable_ops), @@ -1432,6 +1865,7 @@ let isCall = 1, Requires<[IsARM, IsNotDarwin]> { bits<24> func; let Inst{23-0} = func; + let DecoderMethod = "DecodeBranchImmInstruction"; } // ARMv5T and above @@ -1516,6 +1950,7 @@ let isBranch = 1, isTerminator = 1 in { [/*(ARMbrcond bb:$target, imm:$cc, CCR:$ccr)*/]> { bits<24> target; let Inst{23-0} = target; + let DecoderMethod = "DecodeBranchImmInstruction"; } let isBarrier = 1 in { @@ -1549,9 +1984,9 @@ let isBranch = 1, isTerminator = 1 in { } -// BLX (immediate) -- for disassembly only -def BLXi : AXI<(outs), (ins br_target:$target), BrMiscFrm, NoItinerary, - "blx\t$target", [/* pattern left blank */]>, +// BLX (immediate) +def BLXi : AXI<(outs), (ins blx_target:$target), BrMiscFrm, NoItinerary, + "blx\t$target", []>, Requires<[IsARM, HasV5T]> { let Inst{31-25} = 0b1111101; bits<25> target; @@ -1614,64 +2049,100 @@ let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in { } } - - - - -// Secure Monitor Call is a system instruction -- for disassembly only -def SMC : ABI<0b0001, (outs), (ins i32imm:$opt), NoItinerary, "smc", "\t$opt", - [/* For disassembly only; pattern left blank */]> { +// Secure Monitor Call is a system instruction. +def SMC : ABI<0b0001, (outs), (ins imm0_15:$opt), NoItinerary, "smc", "\t$opt", + []> { bits<4> opt; let Inst{23-4} = 0b01100000000000000111; let Inst{3-0} = opt; } -// Supervisor Call (Software Interrupt) -- for disassembly only +// Supervisor Call (Software Interrupt) let isCall = 1, Uses = [SP] in { -def SVC : ABI<0b1111, (outs), (ins i32imm:$svc), IIC_Br, "svc", "\t$svc", - [/* For disassembly only; pattern left blank */]> { +def SVC : ABI<0b1111, (outs), (ins imm24b:$svc), IIC_Br, "svc", "\t$svc", []> { bits<24> svc; let Inst{23-0} = svc; } } -// Store Return State is a system instruction -- for disassembly only -let isCodeGenOnly = 1 in { // FIXME: This should not use submode! -def SRSW : ABXI<{1,0,0,?}, (outs), (ins ldstm_mode:$amode, i32imm:$mode), - NoItinerary, "srs${amode}\tsp!, $mode", - [/* For disassembly only; pattern left blank */]> { +// Store Return State +class SRSI + : XI<(outs), (ins imm0_31:$mode), AddrModeNone, 4, IndexModeNone, BrFrm, + NoItinerary, asm, "", []> { + bits<5> mode; let Inst{31-28} = 0b1111; - let Inst{22-20} = 0b110; // W = 1 - let Inst{19-8} = 0xd05; - let Inst{7-5} = 0b000; + let Inst{27-25} = 0b100; + let Inst{22} = 1; + let Inst{21} = wb; + let Inst{20} = 0; + let Inst{19-16} = 0b1101; // SP + let Inst{15-5} = 0b00000101000; + let Inst{4-0} = mode; } -def SRS : ABXI<{1,0,0,?}, (outs), (ins ldstm_mode:$amode, i32imm:$mode), - NoItinerary, "srs${amode}\tsp, $mode", - [/* For disassembly only; pattern left blank */]> { - let Inst{31-28} = 0b1111; - let Inst{22-20} = 0b100; // W = 0 - let Inst{19-8} = 0xd05; - let Inst{7-5} = 0b000; +def SRSDA : SRSI<0, "srsda\tsp, $mode"> { + let Inst{24-23} = 0; +} +def SRSDA_UPD : SRSI<1, "srsda\tsp!, $mode"> { + let Inst{24-23} = 0; +} +def SRSDB : SRSI<0, "srsdb\tsp, $mode"> { + let Inst{24-23} = 0b10; +} +def SRSDB_UPD : SRSI<1, "srsdb\tsp!, $mode"> { + let Inst{24-23} = 0b10; +} +def SRSIA : SRSI<0, "srsia\tsp, $mode"> { + let Inst{24-23} = 0b01; +} +def SRSIA_UPD : SRSI<1, "srsia\tsp!, $mode"> { + let Inst{24-23} = 0b01; +} +def SRSIB : SRSI<0, "srsib\tsp, $mode"> { + let Inst{24-23} = 0b11; +} +def SRSIB_UPD : SRSI<1, "srsib\tsp!, $mode"> { + let Inst{24-23} = 0b11; } -// Return From Exception is a system instruction -- for disassembly only -def RFEW : ABXI<{1,0,0,?}, (outs), (ins ldstm_mode:$amode, GPR:$base), - NoItinerary, "rfe${amode}\t$base!", - [/* For disassembly only; pattern left blank */]> { +// Return From Exception +class RFEI + : XI<(outs), (ins GPR:$Rn), AddrModeNone, 4, IndexModeNone, BrFrm, + NoItinerary, asm, "", []> { + bits<4> Rn; let Inst{31-28} = 0b1111; - let Inst{22-20} = 0b011; // W = 1 - let Inst{15-0} = 0x0a00; + let Inst{27-25} = 0b100; + let Inst{22} = 0; + let Inst{21} = wb; + let Inst{20} = 1; + let Inst{19-16} = Rn; + let Inst{15-0} = 0xa00; } -def RFE : ABXI<{1,0,0,?}, (outs), (ins ldstm_mode:$amode, GPR:$base), - NoItinerary, "rfe${amode}\t$base", - [/* For disassembly only; pattern left blank */]> { - let Inst{31-28} = 0b1111; - let Inst{22-20} = 0b001; // W = 0 - let Inst{15-0} = 0x0a00; +def RFEDA : RFEI<0, "rfeda\t$Rn"> { + let Inst{24-23} = 0; +} +def RFEDA_UPD : RFEI<1, "rfeda\t$Rn!"> { + let Inst{24-23} = 0; +} +def RFEDB : RFEI<0, "rfedb\t$Rn"> { + let Inst{24-23} = 0b10; +} +def RFEDB_UPD : RFEI<1, "rfedb\t$Rn!"> { + let Inst{24-23} = 0b10; +} +def RFEIA : RFEI<0, "rfeia\t$Rn"> { + let Inst{24-23} = 0b01; +} +def RFEIA_UPD : RFEI<1, "rfeia\t$Rn!"> { + let Inst{24-23} = 0b01; +} +def RFEIB : RFEI<0, "rfeib\t$Rn"> { + let Inst{24-23} = 0b11; +} +def RFEIB_UPD : RFEI<1, "rfeib\t$Rn!"> { + let Inst{24-23} = 0b11; } -} // isCodeGenOnly = 1 //===----------------------------------------------------------------------===// // Load / store Instructions. @@ -1682,16 +2153,16 @@ def RFE : ABXI<{1,0,0,?}, (outs), (ins ldstm_mode:$amode, GPR:$base), defm LDR : AI_ldr1<0, "ldr", IIC_iLoad_r, IIC_iLoad_si, UnOpFrag<(load node:$Src)>>; -defm LDRB : AI_ldr1<1, "ldrb", IIC_iLoad_bh_r, IIC_iLoad_bh_si, +defm LDRB : AI_ldr1nopc<1, "ldrb", IIC_iLoad_bh_r, IIC_iLoad_bh_si, UnOpFrag<(zextloadi8 node:$Src)>>; defm STR : AI_str1<0, "str", IIC_iStore_r, IIC_iStore_si, BinOpFrag<(store node:$LHS, node:$RHS)>>; -defm STRB : AI_str1<1, "strb", IIC_iStore_bh_r, IIC_iStore_bh_si, +defm STRB : AI_str1nopc<1, "strb", IIC_iStore_bh_r, IIC_iStore_bh_si, BinOpFrag<(truncstorei8 node:$LHS, node:$RHS)>>; // Special LDR for loads from non-pc-relative constpools. let canFoldAsLoad = 1, mayLoad = 1, neverHasSideEffects = 1, - isReMaterializable = 1 in + isReMaterializable = 1, isCodeGenOnly = 1 in def LDRcp : AI2ldst<0b010, 1, 0, (outs GPR:$Rt), (ins addrmode_imm12:$addr), AddrMode_i12, LdFrm, IIC_iLoad_r, "ldr", "\t$Rt, $addr", []> { @@ -1725,36 +2196,67 @@ def LDRD : AI3ld<0b1101, 0, (outs GPR:$Rd, GPR:$dst2), []>, Requires<[IsARM, HasV5TE]>; } -// Indexed loads -multiclass AI2_ldridx { - def _PRE : AI2ldstidx<1, isByte, 1, (outs GPR:$Rt, GPR:$Rn_wb), - (ins addrmode2:$addr), IndexModePre, LdFrm, itin, +// Indexed loads +multiclass AI2_ldridx { + def _PRE_IMM : AI2ldstidx<1, isByte, 1, (outs GPR:$Rt, GPR:$Rn_wb), + (ins addrmode_imm12:$addr), IndexModePre, LdFrm, itin, + opc, "\t$Rt, $addr!", "$addr.base = $Rn_wb", []> { + bits<17> addr; + let Inst{25} = 0; + let Inst{23} = addr{12}; + let Inst{19-16} = addr{16-13}; + let Inst{11-0} = addr{11-0}; + let DecoderMethod = "DecodeLDRPreImm"; + let AsmMatchConverter = "cvtLdWriteBackRegAddrModeImm12"; + } + + def _PRE_REG : AI2ldstidx<1, isByte, 1, (outs GPR:$Rt, GPR:$Rn_wb), + (ins ldst_so_reg:$addr), IndexModePre, LdFrm, itin, opc, "\t$Rt, $addr!", "$addr.base = $Rn_wb", []> { - // {17-14} Rn - // {13} 1 == Rm, 0 == imm12 - // {12} isAdd - // {11-0} imm12/Rm - bits<18> addr; - let Inst{25} = addr{13}; + bits<17> addr; + let Inst{25} = 1; let Inst{23} = addr{12}; - let Inst{19-16} = addr{17-14}; + let Inst{19-16} = addr{16-13}; let Inst{11-0} = addr{11-0}; - let AsmMatchConverter = "CvtLdWriteBackRegAddrMode2"; + let Inst{4} = 0; + let DecoderMethod = "DecodeLDRPreReg"; + let AsmMatchConverter = "cvtLdWriteBackRegAddrMode2"; } - def _POST : AI2ldstidx<1, isByte, 0, (outs GPR:$Rt, GPR:$Rn_wb), - (ins GPR:$Rn, am2offset:$offset), + + def _POST_REG : AI2ldstidx<1, isByte, 0, (outs GPR:$Rt, GPR:$Rn_wb), + (ins addr_offset_none:$addr, am2offset_reg:$offset), + IndexModePost, LdFrm, itin, + opc, "\t$Rt, $addr, $offset", + "$addr.base = $Rn_wb", []> { + // {12} isAdd + // {11-0} imm12/Rm + bits<14> offset; + bits<4> addr; + let Inst{25} = 1; + let Inst{23} = offset{12}; + let Inst{19-16} = addr; + let Inst{11-0} = offset{11-0}; + + let DecoderMethod = "DecodeAddrMode2IdxInstruction"; + } + + def _POST_IMM : AI2ldstidx<1, isByte, 0, (outs GPR:$Rt, GPR:$Rn_wb), + (ins addr_offset_none:$addr, am2offset_imm:$offset), IndexModePost, LdFrm, itin, - opc, "\t$Rt, [$Rn], $offset", "$Rn = $Rn_wb", []> { - // {13} 1 == Rm, 0 == imm12 + opc, "\t$Rt, $addr, $offset", + "$addr.base = $Rn_wb", []> { // {12} isAdd // {11-0} imm12/Rm bits<14> offset; - bits<4> Rn; - let Inst{25} = offset{13}; + bits<4> addr; + let Inst{25} = 0; let Inst{23} = offset{12}; - let Inst{19-16} = Rn; + let Inst{19-16} = addr; let Inst{11-0} = offset{11-0}; + + let DecoderMethod = "DecodeAddrMode2IdxInstruction"; } + } let mayLoad = 1, neverHasSideEffects = 1 in { @@ -1762,8 +2264,8 @@ defm LDR : AI2_ldridx<0, "ldr", IIC_iLoad_ru>; defm LDRB : AI2_ldridx<1, "ldrb", IIC_iLoad_bh_ru>; } -multiclass AI3_ldridx op, bit op20, string opc, InstrItinClass itin> { - def _PRE : AI3ldstidx op, string opc, InstrItinClass itin> { + def _PRE : AI3ldstidx { @@ -1773,27 +2275,31 @@ multiclass AI3_ldridx op, bit op20, string opc, InstrItinClass itin> { let Inst{19-16} = addr{12-9}; // Rn let Inst{11-8} = addr{7-4}; // imm7_4/zero let Inst{3-0} = addr{3-0}; // imm3_0/Rm + let AsmMatchConverter = "cvtLdWriteBackRegAddrMode3"; + let DecoderMethod = "DecodeAddrMode3Instruction"; } - def _POST : AI3ldstidx { + def _POST : AI3ldstidx { bits<10> offset; - bits<4> Rn; + bits<4> addr; let Inst{23} = offset{8}; // U bit let Inst{22} = offset{9}; // 1 == imm8, 0 == Rm - let Inst{19-16} = Rn; + let Inst{19-16} = addr; let Inst{11-8} = offset{7-4}; // imm7_4/zero let Inst{3-0} = offset{3-0}; // imm3_0/Rm + let DecoderMethod = "DecodeAddrMode3Instruction"; } } let mayLoad = 1, neverHasSideEffects = 1 in { -defm LDRH : AI3_ldridx<0b1011, 1, "ldrh", IIC_iLoad_bh_ru>; -defm LDRSH : AI3_ldridx<0b1111, 1, "ldrsh", IIC_iLoad_bh_ru>; -defm LDRSB : AI3_ldridx<0b1101, 1, "ldrsb", IIC_iLoad_bh_ru>; +defm LDRH : AI3_ldridx<0b1011, "ldrh", IIC_iLoad_bh_ru>; +defm LDRSH : AI3_ldridx<0b1111, "ldrsh", IIC_iLoad_bh_ru>; +defm LDRSB : AI3_ldridx<0b1101, "ldrsb", IIC_iLoad_bh_ru>; let hasExtraDefRegAllocReq = 1 in { -def LDRD_PRE : AI3ldstidx<0b1101, 0, 1, 1, (outs GPR:$Rt, GPR:$Rt2, GPR:$Rn_wb), +def LDRD_PRE : AI3ldstidx<0b1101, 0, 1, (outs GPR:$Rt, GPR:$Rt2, GPR:$Rn_wb), (ins addrmode3:$addr), IndexModePre, LdMiscFrm, IIC_iLoad_d_ru, "ldrd", "\t$Rt, $Rt2, $addr!", @@ -1804,70 +2310,128 @@ def LDRD_PRE : AI3ldstidx<0b1101, 0, 1, 1, (outs GPR:$Rt, GPR:$Rt2, GPR:$Rn_wb), let Inst{19-16} = addr{12-9}; // Rn let Inst{11-8} = addr{7-4}; // imm7_4/zero let Inst{3-0} = addr{3-0}; // imm3_0/Rm + let DecoderMethod = "DecodeAddrMode3Instruction"; + let AsmMatchConverter = "cvtLdrdPre"; } -def LDRD_POST: AI3ldstidx<0b1101, 0, 1, 0, (outs GPR:$Rt, GPR:$Rt2, GPR:$Rn_wb), - (ins GPR:$Rn, am3offset:$offset), IndexModePost, - LdMiscFrm, IIC_iLoad_d_ru, - "ldrd", "\t$Rt, $Rt2, [$Rn], $offset", - "$Rn = $Rn_wb", []> { +def LDRD_POST: AI3ldstidx<0b1101, 0, 0, (outs GPR:$Rt, GPR:$Rt2, GPR:$Rn_wb), + (ins addr_offset_none:$addr, am3offset:$offset), + IndexModePost, LdMiscFrm, IIC_iLoad_d_ru, + "ldrd", "\t$Rt, $Rt2, $addr, $offset", + "$addr.base = $Rn_wb", []> { bits<10> offset; - bits<4> Rn; + bits<4> addr; let Inst{23} = offset{8}; // U bit let Inst{22} = offset{9}; // 1 == imm8, 0 == Rm - let Inst{19-16} = Rn; + let Inst{19-16} = addr; let Inst{11-8} = offset{7-4}; // imm7_4/zero let Inst{3-0} = offset{3-0}; // imm3_0/Rm + let DecoderMethod = "DecodeAddrMode3Instruction"; } } // hasExtraDefRegAllocReq = 1 } // mayLoad = 1, neverHasSideEffects = 1 -// LDRT, LDRBT, LDRSBT, LDRHT, LDRSHT are for disassembly only. +// LDRT, LDRBT, LDRSBT, LDRHT, LDRSHT. let mayLoad = 1, neverHasSideEffects = 1 in { -def LDRT : AI2ldstidx<1, 0, 0, (outs GPR:$Rt, GPR:$base_wb), - (ins addrmode2:$addr), IndexModePost, LdFrm, IIC_iLoad_ru, - "ldrt", "\t$Rt, $addr", "$addr.base = $base_wb", []> { - // {17-14} Rn - // {13} 1 == Rm, 0 == imm12 +def LDRT_POST_REG : AI2ldstidx<1, 0, 0, (outs GPR:$Rt, GPR:$Rn_wb), + (ins addr_offset_none:$addr, am2offset_reg:$offset), + IndexModePost, LdFrm, IIC_iLoad_ru, + "ldrt", "\t$Rt, $addr, $offset", + "$addr.base = $Rn_wb", []> { // {12} isAdd // {11-0} imm12/Rm - bits<18> addr; - let Inst{25} = addr{13}; - let Inst{23} = addr{12}; + bits<14> offset; + bits<4> addr; + let Inst{25} = 1; + let Inst{23} = offset{12}; let Inst{21} = 1; // overwrite - let Inst{19-16} = addr{17-14}; - let Inst{11-0} = addr{11-0}; - let AsmMatchConverter = "CvtLdWriteBackRegAddrMode2"; -} -def LDRBT : AI2ldstidx<1, 1, 0, (outs GPR:$Rt, GPR:$base_wb), - (ins addrmode2:$addr), IndexModePost, LdFrm, IIC_iLoad_bh_ru, - "ldrbt", "\t$Rt, $addr", "$addr.base = $base_wb", []> { - // {17-14} Rn - // {13} 1 == Rm, 0 == imm12 + let Inst{19-16} = addr; + let Inst{11-5} = offset{11-5}; + let Inst{4} = 0; + let Inst{3-0} = offset{3-0}; + let DecoderMethod = "DecodeAddrMode2IdxInstruction"; +} + +def LDRT_POST_IMM : AI2ldstidx<1, 0, 0, (outs GPR:$Rt, GPR:$Rn_wb), + (ins addr_offset_none:$addr, am2offset_imm:$offset), + IndexModePost, LdFrm, IIC_iLoad_ru, + "ldrt", "\t$Rt, $addr, $offset", + "$addr.base = $Rn_wb", []> { // {12} isAdd // {11-0} imm12/Rm - bits<18> addr; - let Inst{25} = addr{13}; - let Inst{23} = addr{12}; - let Inst{21} = 1; // overwrite - let Inst{19-16} = addr{17-14}; - let Inst{11-0} = addr{11-0}; - let AsmMatchConverter = "CvtLdWriteBackRegAddrMode2"; -} -def LDRSBT : AI3ldstidxT<0b1101, 1, 1, 0, (outs GPR:$Rt, GPR:$base_wb), - (ins addrmode3:$addr), IndexModePost, LdMiscFrm, IIC_iLoad_bh_ru, - "ldrsbt", "\t$Rt, $addr", "$addr.base = $base_wb", []> { + bits<14> offset; + bits<4> addr; + let Inst{25} = 0; + let Inst{23} = offset{12}; let Inst{21} = 1; // overwrite + let Inst{19-16} = addr; + let Inst{11-0} = offset{11-0}; + let DecoderMethod = "DecodeAddrMode2IdxInstruction"; } -def LDRHT : AI3ldstidxT<0b1011, 1, 1, 0, (outs GPR:$Rt, GPR:$base_wb), - (ins addrmode3:$addr), IndexModePost, LdMiscFrm, IIC_iLoad_bh_ru, - "ldrht", "\t$Rt, $addr", "$addr.base = $base_wb", []> { + +def LDRBT_POST_REG : AI2ldstidx<1, 1, 0, (outs GPR:$Rt, GPR:$Rn_wb), + (ins addr_offset_none:$addr, am2offset_reg:$offset), + IndexModePost, LdFrm, IIC_iLoad_bh_ru, + "ldrbt", "\t$Rt, $addr, $offset", + "$addr.base = $Rn_wb", []> { + // {12} isAdd + // {11-0} imm12/Rm + bits<14> offset; + bits<4> addr; + let Inst{25} = 1; + let Inst{23} = offset{12}; let Inst{21} = 1; // overwrite -} -def LDRSHT : AI3ldstidxT<0b1111, 1, 1, 0, (outs GPR:$Rt, GPR:$base_wb), - (ins addrmode3:$addr), IndexModePost, LdMiscFrm, IIC_iLoad_bh_ru, - "ldrsht", "\t$Rt, $addr", "$addr.base = $base_wb", []> { + let Inst{19-16} = addr; + let Inst{11-5} = offset{11-5}; + let Inst{4} = 0; + let Inst{3-0} = offset{3-0}; + let DecoderMethod = "DecodeAddrMode2IdxInstruction"; +} + +def LDRBT_POST_IMM : AI2ldstidx<1, 1, 0, (outs GPR:$Rt, GPR:$Rn_wb), + (ins addr_offset_none:$addr, am2offset_imm:$offset), + IndexModePost, LdFrm, IIC_iLoad_bh_ru, + "ldrbt", "\t$Rt, $addr, $offset", + "$addr.base = $Rn_wb", []> { + // {12} isAdd + // {11-0} imm12/Rm + bits<14> offset; + bits<4> addr; + let Inst{25} = 0; + let Inst{23} = offset{12}; let Inst{21} = 1; // overwrite + let Inst{19-16} = addr; + let Inst{11-0} = offset{11-0}; + let DecoderMethod = "DecodeAddrMode2IdxInstruction"; +} + +multiclass AI3ldrT op, string opc> { + def i : AI3ldstidxT { + bits<9> offset; + let Inst{23} = offset{8}; + let Inst{22} = 1; + let Inst{11-8} = offset{7-4}; + let Inst{3-0} = offset{3-0}; + let AsmMatchConverter = "cvtLdExtTWriteBackImm"; + } + def r : AI3ldstidxT { + bits<5> Rm; + let Inst{23} = Rm{4}; + let Inst{22} = 0; + let Inst{11-8} = 0; + let Inst{3-0} = Rm{3-0}; + let AsmMatchConverter = "cvtLdExtTWriteBackReg"; + } } + +defm LDRSBT : AI3ldrT<0b1101, "ldrsbt">; +defm LDRHT : AI3ldrT<0b1011, "ldrht">; +defm LDRSHT : AI3ldrT<0b1111, "ldrsht">; } // Store @@ -1881,98 +2445,302 @@ def STRH : AI3str<0b1011, (outs), (ins GPR:$Rt, addrmode3:$addr), StMiscFrm, let mayStore = 1, neverHasSideEffects = 1, hasExtraSrcRegAllocReq = 1 in def STRD : AI3str<0b1111, (outs), (ins GPR:$Rt, GPR:$src2, addrmode3:$addr), StMiscFrm, IIC_iStore_d_r, - "strd", "\t$Rt, $src2, $addr", []>, Requires<[IsARM, HasV5TE]>; + "strd", "\t$Rt, $src2, $addr", []>, + Requires<[IsARM, HasV5TE]> { + let Inst{21} = 0; +} // Indexed stores -def STR_PRE : AI2stridx<0, 1, (outs GPR:$Rn_wb), - (ins GPR:$Rt, GPR:$Rn, am2offset:$offset), - IndexModePre, StFrm, IIC_iStore_ru, - "str", "\t$Rt, [$Rn, $offset]!", - "$Rn = $Rn_wb,@earlyclobber $Rn_wb", - [(set GPR:$Rn_wb, - (pre_store GPR:$Rt, GPR:$Rn, am2offset:$offset))]>; - -def STR_POST : AI2stridx<0, 0, (outs GPR:$Rn_wb), - (ins GPR:$Rt, GPR:$Rn, am2offset:$offset), - IndexModePost, StFrm, IIC_iStore_ru, - "str", "\t$Rt, [$Rn], $offset", - "$Rn = $Rn_wb,@earlyclobber $Rn_wb", - [(set GPR:$Rn_wb, - (post_store GPR:$Rt, GPR:$Rn, am2offset:$offset))]>; - -def STRB_PRE : AI2stridx<1, 1, (outs GPR:$Rn_wb), - (ins GPR:$Rt, GPR:$Rn, am2offset:$offset), - IndexModePre, StFrm, IIC_iStore_bh_ru, - "strb", "\t$Rt, [$Rn, $offset]!", - "$Rn = $Rn_wb,@earlyclobber $Rn_wb", - [(set GPR:$Rn_wb, (pre_truncsti8 GPR:$Rt, - GPR:$Rn, am2offset:$offset))]>; -def STRB_POST: AI2stridx<1, 0, (outs GPR:$Rn_wb), - (ins GPR:$Rt, GPR:$Rn, am2offset:$offset), - IndexModePost, StFrm, IIC_iStore_bh_ru, - "strb", "\t$Rt, [$Rn], $offset", - "$Rn = $Rn_wb,@earlyclobber $Rn_wb", - [(set GPR:$Rn_wb, (post_truncsti8 GPR:$Rt, - GPR:$Rn, am2offset:$offset))]>; - -def STRH_PRE : AI3stridx<0b1011, 0, 1, (outs GPR:$Rn_wb), - (ins GPR:$Rt, GPR:$Rn, am3offset:$offset), - IndexModePre, StMiscFrm, IIC_iStore_ru, - "strh", "\t$Rt, [$Rn, $offset]!", - "$Rn = $Rn_wb,@earlyclobber $Rn_wb", - [(set GPR:$Rn_wb, - (pre_truncsti16 GPR:$Rt, GPR:$Rn, am3offset:$offset))]>; - -def STRH_POST: AI3stridx<0b1011, 0, 0, (outs GPR:$Rn_wb), - (ins GPR:$Rt, GPR:$Rn, am3offset:$offset), - IndexModePost, StMiscFrm, IIC_iStore_bh_ru, - "strh", "\t$Rt, [$Rn], $offset", - "$Rn = $Rn_wb,@earlyclobber $Rn_wb", - [(set GPR:$Rn_wb, (post_truncsti16 GPR:$Rt, - GPR:$Rn, am3offset:$offset))]>; - -// For disassembly only +multiclass AI2_stridx { + def _PRE_IMM : AI2ldstidx<0, isByte, 1, (outs GPR:$Rn_wb), + (ins GPR:$Rt, addrmode_imm12:$addr), IndexModePre, + StFrm, itin, + opc, "\t$Rt, $addr!", "$addr.base = $Rn_wb", []> { + bits<17> addr; + let Inst{25} = 0; + let Inst{23} = addr{12}; // U (add = ('U' == 1)) + let Inst{19-16} = addr{16-13}; // Rn + let Inst{11-0} = addr{11-0}; // imm12 + let AsmMatchConverter = "cvtStWriteBackRegAddrModeImm12"; + let DecoderMethod = "DecodeSTRPreImm"; + } + + def _PRE_REG : AI2ldstidx<0, isByte, 1, (outs GPR:$Rn_wb), + (ins GPR:$Rt, ldst_so_reg:$addr), + IndexModePre, StFrm, itin, + opc, "\t$Rt, $addr!", "$addr.base = $Rn_wb", []> { + bits<17> addr; + let Inst{25} = 1; + let Inst{23} = addr{12}; // U (add = ('U' == 1)) + let Inst{19-16} = addr{16-13}; // Rn + let Inst{11-0} = addr{11-0}; + let Inst{4} = 0; // Inst{4} = 0 + let AsmMatchConverter = "cvtStWriteBackRegAddrMode2"; + let DecoderMethod = "DecodeSTRPreReg"; + } + def _POST_REG : AI2ldstidx<0, isByte, 0, (outs GPR:$Rn_wb), + (ins GPR:$Rt, addr_offset_none:$addr, am2offset_reg:$offset), + IndexModePost, StFrm, itin, + opc, "\t$Rt, $addr, $offset", + "$addr.base = $Rn_wb", []> { + // {12} isAdd + // {11-0} imm12/Rm + bits<14> offset; + bits<4> addr; + let Inst{25} = 1; + let Inst{23} = offset{12}; + let Inst{19-16} = addr; + let Inst{11-0} = offset{11-0}; + + let DecoderMethod = "DecodeAddrMode2IdxInstruction"; + } + + def _POST_IMM : AI2ldstidx<0, isByte, 0, (outs GPR:$Rn_wb), + (ins GPR:$Rt, addr_offset_none:$addr, am2offset_imm:$offset), + IndexModePost, StFrm, itin, + opc, "\t$Rt, $addr, $offset", + "$addr.base = $Rn_wb", []> { + // {12} isAdd + // {11-0} imm12/Rm + bits<14> offset; + bits<4> addr; + let Inst{25} = 0; + let Inst{23} = offset{12}; + let Inst{19-16} = addr; + let Inst{11-0} = offset{11-0}; + + let DecoderMethod = "DecodeAddrMode2IdxInstruction"; + } +} + +let mayStore = 1, neverHasSideEffects = 1 in { +defm STR : AI2_stridx<0, "str", IIC_iStore_ru>; +defm STRB : AI2_stridx<1, "strb", IIC_iStore_bh_ru>; +} + +def : ARMPat<(post_store GPR:$Rt, addr_offset_none:$addr, + am2offset_reg:$offset), + (STR_POST_REG GPR:$Rt, addr_offset_none:$addr, + am2offset_reg:$offset)>; +def : ARMPat<(post_store GPR:$Rt, addr_offset_none:$addr, + am2offset_imm:$offset), + (STR_POST_IMM GPR:$Rt, addr_offset_none:$addr, + am2offset_imm:$offset)>; +def : ARMPat<(post_truncsti8 GPR:$Rt, addr_offset_none:$addr, + am2offset_reg:$offset), + (STRB_POST_REG GPR:$Rt, addr_offset_none:$addr, + am2offset_reg:$offset)>; +def : ARMPat<(post_truncsti8 GPR:$Rt, addr_offset_none:$addr, + am2offset_imm:$offset), + (STRB_POST_IMM GPR:$Rt, addr_offset_none:$addr, + am2offset_imm:$offset)>; + +// Pseudo-instructions for pattern matching the pre-indexed stores. We can't +// put the patterns on the instruction definitions directly as ISel wants +// the address base and offset to be separate operands, not a single +// complex operand like we represent the instructions themselves. The +// pseudos map between the two. +let usesCustomInserter = 1, + Constraints = "$Rn = $Rn_wb,@earlyclobber $Rn_wb" in { +def STRi_preidx: ARMPseudoInst<(outs GPR:$Rn_wb), + (ins GPR:$Rt, GPR:$Rn, am2offset_imm:$offset, pred:$p), + 4, IIC_iStore_ru, + [(set GPR:$Rn_wb, + (pre_store GPR:$Rt, GPR:$Rn, am2offset_imm:$offset))]>; +def STRr_preidx: ARMPseudoInst<(outs GPR:$Rn_wb), + (ins GPR:$Rt, GPR:$Rn, am2offset_reg:$offset, pred:$p), + 4, IIC_iStore_ru, + [(set GPR:$Rn_wb, + (pre_store GPR:$Rt, GPR:$Rn, am2offset_reg:$offset))]>; +def STRBi_preidx: ARMPseudoInst<(outs GPR:$Rn_wb), + (ins GPR:$Rt, GPR:$Rn, am2offset_imm:$offset, pred:$p), + 4, IIC_iStore_ru, + [(set GPR:$Rn_wb, + (pre_truncsti8 GPR:$Rt, GPR:$Rn, am2offset_imm:$offset))]>; +def STRBr_preidx: ARMPseudoInst<(outs GPR:$Rn_wb), + (ins GPR:$Rt, GPR:$Rn, am2offset_reg:$offset, pred:$p), + 4, IIC_iStore_ru, + [(set GPR:$Rn_wb, + (pre_truncsti8 GPR:$Rt, GPR:$Rn, am2offset_reg:$offset))]>; +def STRH_preidx: ARMPseudoInst<(outs GPR:$Rn_wb), + (ins GPR:$Rt, GPR:$Rn, am3offset:$offset, pred:$p), + 4, IIC_iStore_ru, + [(set GPR:$Rn_wb, + (pre_truncsti16 GPR:$Rt, GPR:$Rn, am3offset:$offset))]>; +} + + + +def STRH_PRE : AI3ldstidx<0b1011, 0, 1, (outs GPR:$Rn_wb), + (ins GPR:$Rt, addrmode3:$addr), IndexModePre, + StMiscFrm, IIC_iStore_bh_ru, + "strh", "\t$Rt, $addr!", "$addr.base = $Rn_wb", []> { + bits<14> addr; + let Inst{23} = addr{8}; // U bit + let Inst{22} = addr{13}; // 1 == imm8, 0 == Rm + let Inst{19-16} = addr{12-9}; // Rn + let Inst{11-8} = addr{7-4}; // imm7_4/zero + let Inst{3-0} = addr{3-0}; // imm3_0/Rm + let AsmMatchConverter = "cvtStWriteBackRegAddrMode3"; + let DecoderMethod = "DecodeAddrMode3Instruction"; +} + +def STRH_POST : AI3ldstidx<0b1011, 0, 0, (outs GPR:$Rn_wb), + (ins GPR:$Rt, addr_offset_none:$addr, am3offset:$offset), + IndexModePost, StMiscFrm, IIC_iStore_bh_ru, + "strh", "\t$Rt, $addr, $offset", "$addr.base = $Rn_wb", + [(set GPR:$Rn_wb, (post_truncsti16 GPR:$Rt, + addr_offset_none:$addr, + am3offset:$offset))]> { + bits<10> offset; + bits<4> addr; + let Inst{23} = offset{8}; // U bit + let Inst{22} = offset{9}; // 1 == imm8, 0 == Rm + let Inst{19-16} = addr; + let Inst{11-8} = offset{7-4}; // imm7_4/zero + let Inst{3-0} = offset{3-0}; // imm3_0/Rm + let DecoderMethod = "DecodeAddrMode3Instruction"; +} + let mayStore = 1, neverHasSideEffects = 1, hasExtraSrcRegAllocReq = 1 in { -def STRD_PRE : AI3stdpr<(outs GPR:$base_wb), - (ins GPR:$src1, GPR:$src2, GPR:$base, am3offset:$offset), - StMiscFrm, IIC_iStore_d_ru, - "strd", "\t$src1, $src2, [$base, $offset]!", - "$base = $base_wb", []>; - -// For disassembly only -def STRD_POST: AI3stdpo<(outs GPR:$base_wb), - (ins GPR:$src1, GPR:$src2, GPR:$base, am3offset:$offset), - StMiscFrm, IIC_iStore_d_ru, - "strd", "\t$src1, $src2, [$base], $offset", - "$base = $base_wb", []>; +def STRD_PRE : AI3ldstidx<0b1111, 0, 1, (outs GPR:$Rn_wb), + (ins GPR:$Rt, GPR:$Rt2, addrmode3:$addr), + IndexModePre, StMiscFrm, IIC_iStore_d_ru, + "strd", "\t$Rt, $Rt2, $addr!", + "$addr.base = $Rn_wb", []> { + bits<14> addr; + let Inst{23} = addr{8}; // U bit + let Inst{22} = addr{13}; // 1 == imm8, 0 == Rm + let Inst{19-16} = addr{12-9}; // Rn + let Inst{11-8} = addr{7-4}; // imm7_4/zero + let Inst{3-0} = addr{3-0}; // imm3_0/Rm + let DecoderMethod = "DecodeAddrMode3Instruction"; + let AsmMatchConverter = "cvtStrdPre"; +} + +def STRD_POST: AI3ldstidx<0b1111, 0, 0, (outs GPR:$Rn_wb), + (ins GPR:$Rt, GPR:$Rt2, addr_offset_none:$addr, + am3offset:$offset), + IndexModePost, StMiscFrm, IIC_iStore_d_ru, + "strd", "\t$Rt, $Rt2, $addr, $offset", + "$addr.base = $Rn_wb", []> { + bits<10> offset; + bits<4> addr; + let Inst{23} = offset{8}; // U bit + let Inst{22} = offset{9}; // 1 == imm8, 0 == Rm + let Inst{19-16} = addr; + let Inst{11-8} = offset{7-4}; // imm7_4/zero + let Inst{3-0} = offset{3-0}; // imm3_0/Rm + let DecoderMethod = "DecodeAddrMode3Instruction"; +} } // mayStore = 1, neverHasSideEffects = 1, hasExtraSrcRegAllocReq = 1 -// STRT, STRBT, and STRHT are for disassembly only. +// STRT, STRBT, and STRHT -def STRT : AI2stridxT<0, 0, (outs GPR:$Rn_wb), (ins GPR:$Rt, addrmode2:$addr), - IndexModePost, StFrm, IIC_iStore_ru, - "strt", "\t$Rt, $addr", "$addr.base = $Rn_wb", - [/* For disassembly only; pattern left blank */]> { +def STRBT_POST_REG : AI2ldstidx<0, 1, 0, (outs GPR:$Rn_wb), + (ins GPR:$Rt, addr_offset_none:$addr, am2offset_reg:$offset), + IndexModePost, StFrm, IIC_iStore_bh_ru, + "strbt", "\t$Rt, $addr, $offset", + "$addr.base = $Rn_wb", []> { + // {12} isAdd + // {11-0} imm12/Rm + bits<14> offset; + bits<4> addr; + let Inst{25} = 1; + let Inst{23} = offset{12}; + let Inst{21} = 1; // overwrite + let Inst{19-16} = addr; + let Inst{11-5} = offset{11-5}; + let Inst{4} = 0; + let Inst{3-0} = offset{3-0}; + let DecoderMethod = "DecodeAddrMode2IdxInstruction"; +} + +def STRBT_POST_IMM : AI2ldstidx<0, 1, 0, (outs GPR:$Rn_wb), + (ins GPR:$Rt, addr_offset_none:$addr, am2offset_imm:$offset), + IndexModePost, StFrm, IIC_iStore_bh_ru, + "strbt", "\t$Rt, $addr, $offset", + "$addr.base = $Rn_wb", []> { + // {12} isAdd + // {11-0} imm12/Rm + bits<14> offset; + bits<4> addr; + let Inst{25} = 0; + let Inst{23} = offset{12}; let Inst{21} = 1; // overwrite - let AsmMatchConverter = "CvtStWriteBackRegAddrMode2"; + let Inst{19-16} = addr; + let Inst{11-0} = offset{11-0}; + let DecoderMethod = "DecodeAddrMode2IdxInstruction"; } -def STRBT : AI2stridxT<1, 0, (outs GPR:$Rn_wb), (ins GPR:$Rt, addrmode2:$addr), - IndexModePost, StFrm, IIC_iStore_bh_ru, - "strbt", "\t$Rt, $addr", "$addr.base = $Rn_wb", - [/* For disassembly only; pattern left blank */]> { +let mayStore = 1, neverHasSideEffects = 1 in { +def STRT_POST_REG : AI2ldstidx<0, 0, 0, (outs GPR:$Rn_wb), + (ins GPR:$Rt, addr_offset_none:$addr, am2offset_reg:$offset), + IndexModePost, StFrm, IIC_iStore_ru, + "strt", "\t$Rt, $addr, $offset", + "$addr.base = $Rn_wb", []> { + // {12} isAdd + // {11-0} imm12/Rm + bits<14> offset; + bits<4> addr; + let Inst{25} = 1; + let Inst{23} = offset{12}; + let Inst{21} = 1; // overwrite + let Inst{19-16} = addr; + let Inst{11-5} = offset{11-5}; + let Inst{4} = 0; + let Inst{3-0} = offset{3-0}; + let DecoderMethod = "DecodeAddrMode2IdxInstruction"; +} + +def STRT_POST_IMM : AI2ldstidx<0, 0, 0, (outs GPR:$Rn_wb), + (ins GPR:$Rt, addr_offset_none:$addr, am2offset_imm:$offset), + IndexModePost, StFrm, IIC_iStore_ru, + "strt", "\t$Rt, $addr, $offset", + "$addr.base = $Rn_wb", []> { + // {12} isAdd + // {11-0} imm12/Rm + bits<14> offset; + bits<4> addr; + let Inst{25} = 0; + let Inst{23} = offset{12}; let Inst{21} = 1; // overwrite - let AsmMatchConverter = "CvtStWriteBackRegAddrMode2"; + let Inst{19-16} = addr; + let Inst{11-0} = offset{11-0}; + let DecoderMethod = "DecodeAddrMode2IdxInstruction"; +} } -def STRHT: AI3sthpo<(outs GPR:$base_wb), (ins GPR:$Rt, addrmode3:$addr), - StMiscFrm, IIC_iStore_bh_ru, - "strht", "\t$Rt, $addr", "$addr.base = $base_wb", - [/* For disassembly only; pattern left blank */]> { - let Inst{21} = 1; // overwrite - let AsmMatchConverter = "CvtStWriteBackRegAddrMode3"; + +multiclass AI3strT op, string opc> { + def i : AI3ldstidxT { + bits<9> offset; + let Inst{23} = offset{8}; + let Inst{22} = 1; + let Inst{11-8} = offset{7-4}; + let Inst{3-0} = offset{3-0}; + let AsmMatchConverter = "cvtStExtTWriteBackImm"; + } + def r : AI3ldstidxT { + bits<5> Rm; + let Inst{23} = Rm{4}; + let Inst{22} = 0; + let Inst{11-8} = 0; + let Inst{3-0} = Rm{3-0}; + let AsmMatchConverter = "cvtStExtTWriteBackReg"; + } } + +defm STRHT : AI3strT<0b1011, "strht">; + + //===----------------------------------------------------------------------===// // Load / store multiple Instructions. // @@ -1996,6 +2764,8 @@ multiclass arm_ldst_mult; + // A version for the smaller set of tail call registers. let neverHasSideEffects = 1 in def MOVr_TC : AsI1<0b1101, (outs tcGPR:$Rd), (ins tcGPR:$Rm), DPFrm, @@ -2097,15 +2876,33 @@ def MOVr_TC : AsI1<0b1101, (outs tcGPR:$Rd), (ins tcGPR:$Rm), DPFrm, let Inst{15-12} = Rd; } -def MOVs : AsI1<0b1101, (outs GPR:$Rd), (ins shift_so_reg:$src), - DPSoRegFrm, IIC_iMOVsr, - "mov", "\t$Rd, $src", [(set GPR:$Rd, shift_so_reg:$src)]>, +def MOVsr : AsI1<0b1101, (outs GPRnopc:$Rd), (ins shift_so_reg_reg:$src), + DPSoRegRegFrm, IIC_iMOVsr, + "mov", "\t$Rd, $src", + [(set GPRnopc:$Rd, shift_so_reg_reg:$src)]>, UnaryDP { + bits<4> Rd; + bits<12> src; + let Inst{15-12} = Rd; + let Inst{19-16} = 0b0000; + let Inst{11-8} = src{11-8}; + let Inst{7} = 0; + let Inst{6-5} = src{6-5}; + let Inst{4} = 1; + let Inst{3-0} = src{3-0}; + let Inst{25} = 0; +} + +def MOVsi : AsI1<0b1101, (outs GPR:$Rd), (ins shift_so_reg_imm:$src), + DPSoRegImmFrm, IIC_iMOVsr, + "mov", "\t$Rd, $src", [(set GPR:$Rd, shift_so_reg_imm:$src)]>, UnaryDP { bits<4> Rd; bits<12> src; let Inst{15-12} = Rd; let Inst{19-16} = 0b0000; - let Inst{11-0} = src; + let Inst{11-5} = src{11-5}; + let Inst{4} = 0; + let Inst{3-0} = src{3-0}; let Inst{25} = 0; } @@ -2121,7 +2918,7 @@ def MOVi : AsI1<0b1101, (outs GPR:$Rd), (ins so_imm:$imm), DPFrm, IIC_iMOVi, } let isReMaterializable = 1, isAsCheapAsAMove = 1, isMoveImm = 1 in -def MOVi16 : AI1<0b1000, (outs GPR:$Rd), (ins i32imm_hilo16:$imm), +def MOVi16 : AI1<0b1000, (outs GPR:$Rd), (ins imm0_65535_expr:$imm), DPFrm, IIC_iMOVi, "movw", "\t$Rd, $imm", [(set GPR:$Rd, imm0_65535:$imm)]>, @@ -2133,16 +2930,22 @@ def MOVi16 : AI1<0b1000, (outs GPR:$Rd), (ins i32imm_hilo16:$imm), let Inst{19-16} = imm{15-12}; let Inst{20} = 0; let Inst{25} = 1; + let DecoderMethod = "DecodeArmMOVTWInstruction"; } +def : InstAlias<"mov${p} $Rd, $imm", + (MOVi16 GPR:$Rd, imm0_65535_expr:$imm, pred:$p)>, + Requires<[IsARM]>; + def MOVi16_ga_pcrel : PseudoInst<(outs GPR:$Rd), (ins i32imm:$addr, pclabel:$id), IIC_iMOVi, []>; let Constraints = "$src = $Rd" in { -def MOVTi16 : AI1<0b1010, (outs GPR:$Rd), (ins GPR:$src, i32imm_hilo16:$imm), +def MOVTi16 : AI1<0b1010, (outs GPRnopc:$Rd), + (ins GPR:$src, imm0_65535_expr:$imm), DPFrm, IIC_iMOVi, "movt", "\t$Rd, $imm", - [(set GPR:$Rd, + [(set GPRnopc:$Rd, (or (and GPR:$src, 0xffff), lo16AllZero:$imm))]>, UnaryDP, Requires<[IsARM, HasV6T2]> { @@ -2153,6 +2956,7 @@ def MOVTi16 : AI1<0b1010, (outs GPR:$Rd), (ins GPR:$src, i32imm_hilo16:$imm), let Inst{19-16} = imm{15-12}; let Inst{20} = 0; let Inst{25} = 1; + let DecoderMethod = "DecodeArmMOVTWInstruction"; } def MOVTi16_ga_pcrel : PseudoInst<(outs GPR:$Rd), @@ -2186,30 +2990,28 @@ def MOVsra_flag : PseudoInst<(outs GPR:$dst), (ins GPR:$src), IIC_iMOVsi, // Sign extenders -defm SXTB : AI_ext_rrot<0b01101010, +def SXTB : AI_ext_rrot<0b01101010, "sxtb", UnOpFrag<(sext_inreg node:$Src, i8)>>; -defm SXTH : AI_ext_rrot<0b01101011, +def SXTH : AI_ext_rrot<0b01101011, "sxth", UnOpFrag<(sext_inreg node:$Src, i16)>>; -defm SXTAB : AI_exta_rrot<0b01101010, +def SXTAB : AI_exta_rrot<0b01101010, "sxtab", BinOpFrag<(add node:$LHS, (sext_inreg node:$RHS, i8))>>; -defm SXTAH : AI_exta_rrot<0b01101011, +def SXTAH : AI_exta_rrot<0b01101011, "sxtah", BinOpFrag<(add node:$LHS, (sext_inreg node:$RHS,i16))>>; -// For disassembly only -defm SXTB16 : AI_ext_rrot_np<0b01101000, "sxtb16">; +def SXTB16 : AI_ext_rrot_np<0b01101000, "sxtb16">; -// For disassembly only -defm SXTAB16 : AI_exta_rrot_np<0b01101000, "sxtab16">; +def SXTAB16 : AI_exta_rrot_np<0b01101000, "sxtab16">; // Zero extenders let AddedComplexity = 16 in { -defm UXTB : AI_ext_rrot<0b01101110, +def UXTB : AI_ext_rrot<0b01101110, "uxtb" , UnOpFrag<(and node:$Src, 0x000000FF)>>; -defm UXTH : AI_ext_rrot<0b01101111, +def UXTH : AI_ext_rrot<0b01101111, "uxth" , UnOpFrag<(and node:$Src, 0x0000FFFF)>>; -defm UXTB16 : AI_ext_rrot<0b01101100, +def UXTB16 : AI_ext_rrot<0b01101100, "uxtb16", UnOpFrag<(and node:$Src, 0x00FF00FF)>>; // FIXME: This pattern incorrectly assumes the shl operator is a rotate. @@ -2217,23 +3019,22 @@ defm UXTB16 : AI_ext_rrot<0b01101100, // instead so we can include a check for masking back in the upper // eight bits of the source into the lower eight bits of the result. //def : ARMV6Pat<(and (shl GPR:$Src, (i32 8)), 0xFF00FF), -// (UXTB16r_rot GPR:$Src, 24)>; +// (UXTB16r_rot GPR:$Src, 3)>; def : ARMV6Pat<(and (srl GPR:$Src, (i32 8)), 0xFF00FF), - (UXTB16r_rot GPR:$Src, 8)>; + (UXTB16 GPR:$Src, 1)>; -defm UXTAB : AI_exta_rrot<0b01101110, "uxtab", +def UXTAB : AI_exta_rrot<0b01101110, "uxtab", BinOpFrag<(add node:$LHS, (and node:$RHS, 0x00FF))>>; -defm UXTAH : AI_exta_rrot<0b01101111, "uxtah", +def UXTAH : AI_exta_rrot<0b01101111, "uxtah", BinOpFrag<(add node:$LHS, (and node:$RHS, 0xFFFF))>>; } // This isn't safe in general, the add is two 16-bit units, not a 32-bit add. -// For disassembly only -defm UXTAB16 : AI_exta_rrot_np<0b01101100, "uxtab16">; +def UXTAB16 : AI_exta_rrot_np<0b01101100, "uxtab16">; -def SBFX : I<(outs GPR:$Rd), - (ins GPR:$Rn, imm0_31:$lsb, imm0_31_m1:$width), +def SBFX : I<(outs GPRnopc:$Rd), + (ins GPRnopc:$Rn, imm0_31:$lsb, imm1_32:$width), AddrMode1, 4, IndexModeNone, DPFrm, IIC_iUNAsi, "sbfx", "\t$Rd, $Rn, $lsb, $width", "", []>, Requires<[IsARM, HasV6T2]> { @@ -2250,7 +3051,7 @@ def SBFX : I<(outs GPR:$Rd), } def UBFX : I<(outs GPR:$Rd), - (ins GPR:$Rn, imm0_31:$lsb, imm0_31_m1:$width), + (ins GPR:$Rn, imm0_31:$lsb, imm1_32:$width), AddrMode1, 4, IndexModeNone, DPFrm, IIC_iUNAsi, "ubfx", "\t$Rd, $Rn, $lsb, $width", "", []>, Requires<[IsARM, HasV6T2]> { @@ -2278,148 +3079,58 @@ defm SUB : AsI1_bin_irs<0b0010, "sub", BinOpFrag<(sub node:$LHS, node:$RHS)>, "SUB">; // ADD and SUB with 's' bit set. -defm ADDS : AI1_bin_s_irs<0b0100, "adds", +// +// Currently, t2ADDS/t2SUBS are pseudo opcodes that exist only in the +// selection DAG. They are "lowered" to real t2ADD/t2SUB opcodes by +// AdjustInstrPostInstrSelection where we determine whether or not to +// set the "s" bit based on CPSR liveness. +// +// FIXME: Eliminate t2ADDS/t2SUBS pseudo opcodes after adding tablegen +// support for an optional CPSR definition that corresponds to the DAG +// node's second value. We can then eliminate the implicit def of CPSR. +defm ADDS : AsI1_bin_s_irs<0b0100, "add", IIC_iALUi, IIC_iALUr, IIC_iALUsr, - BinOpFrag<(addc node:$LHS, node:$RHS)>, 1>; -defm SUBS : AI1_bin_s_irs<0b0010, "subs", + BinOpFrag<(ARMaddc node:$LHS, node:$RHS)>, 1>; +defm SUBS : AsI1_bin_s_irs<0b0010, "sub", IIC_iALUi, IIC_iALUr, IIC_iALUsr, - BinOpFrag<(subc node:$LHS, node:$RHS)>>; + BinOpFrag<(ARMsubc node:$LHS, node:$RHS)>>; defm ADC : AI1_adde_sube_irs<0b0101, "adc", - BinOpFrag<(adde_dead_carry node:$LHS, node:$RHS)>, + BinOpWithFlagFrag<(ARMadde node:$LHS, node:$RHS, node:$FLAG)>, "ADC", 1>; defm SBC : AI1_adde_sube_irs<0b0110, "sbc", - BinOpFrag<(sube_dead_carry node:$LHS, node:$RHS)>, + BinOpWithFlagFrag<(ARMsube node:$LHS, node:$RHS, node:$FLAG)>, "SBC">; -// ADC and SUBC with 's' bit set. -let usesCustomInserter = 1 in { -defm ADCS : AI1_adde_sube_s_irs< - BinOpFrag<(adde_live_carry node:$LHS, node:$RHS)>, 1>; -defm SBCS : AI1_adde_sube_s_irs< - BinOpFrag<(sube_live_carry node:$LHS, node:$RHS) >>; -} - -def RSBri : AsI1<0b0011, (outs GPR:$Rd), (ins GPR:$Rn, so_imm:$imm), DPFrm, - IIC_iALUi, "rsb", "\t$Rd, $Rn, $imm", - [(set GPR:$Rd, (sub so_imm:$imm, GPR:$Rn))]> { - bits<4> Rd; - bits<4> Rn; - bits<12> imm; - let Inst{25} = 1; - let Inst{15-12} = Rd; - let Inst{19-16} = Rn; - let Inst{11-0} = imm; -} - -// The reg/reg form is only defined for the disassembler; for codegen it is -// equivalent to SUBrr. -def RSBrr : AsI1<0b0011, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm), DPFrm, - IIC_iALUr, "rsb", "\t$Rd, $Rn, $Rm", - [/* For disassembly only; pattern left blank */]> { - bits<4> Rd; - bits<4> Rn; - bits<4> Rm; - let Inst{11-4} = 0b00000000; - let Inst{25} = 0; - let Inst{3-0} = Rm; - let Inst{15-12} = Rd; - let Inst{19-16} = Rn; -} - -def RSBrs : AsI1<0b0011, (outs GPR:$Rd), (ins GPR:$Rn, so_reg:$shift), - DPSoRegFrm, IIC_iALUsr, "rsb", "\t$Rd, $Rn, $shift", - [(set GPR:$Rd, (sub so_reg:$shift, GPR:$Rn))]> { - bits<4> Rd; - bits<4> Rn; - bits<12> shift; - let Inst{25} = 0; - let Inst{11-0} = shift; - let Inst{15-12} = Rd; - let Inst{19-16} = Rn; -} +defm RSB : AsI1_rbin_irs <0b0011, "rsb", + IIC_iALUi, IIC_iALUr, IIC_iALUsr, + BinOpFrag<(sub node:$LHS, node:$RHS)>, "RSB">; -// RSB with 's' bit set. -// NOTE: CPSR def omitted because it will be handled by the custom inserter. -let usesCustomInserter = 1 in { -def RSBSri : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, so_imm:$imm), - 4, IIC_iALUi, - [(set GPR:$Rd, (subc so_imm:$imm, GPR:$Rn))]>; -def RSBSrr : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm), - 4, IIC_iALUr, - [/* For disassembly only; pattern left blank */]>; -def RSBSrs : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, so_reg:$shift), - 4, IIC_iALUsr, - [(set GPR:$Rd, (subc so_reg:$shift, GPR:$Rn))]>; -} - -let Uses = [CPSR] in { -def RSCri : AsI1<0b0111, (outs GPR:$Rd), (ins GPR:$Rn, so_imm:$imm), - DPFrm, IIC_iALUi, "rsc", "\t$Rd, $Rn, $imm", - [(set GPR:$Rd, (sube_dead_carry so_imm:$imm, GPR:$Rn))]>, - Requires<[IsARM]> { - bits<4> Rd; - bits<4> Rn; - bits<12> imm; - let Inst{25} = 1; - let Inst{15-12} = Rd; - let Inst{19-16} = Rn; - let Inst{11-0} = imm; -} -// The reg/reg form is only defined for the disassembler; for codegen it is -// equivalent to SUBrr. -def RSCrr : AsI1<0b0111, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm), - DPFrm, IIC_iALUr, "rsc", "\t$Rd, $Rn, $Rm", - [/* For disassembly only; pattern left blank */]> { - bits<4> Rd; - bits<4> Rn; - bits<4> Rm; - let Inst{11-4} = 0b00000000; - let Inst{25} = 0; - let Inst{3-0} = Rm; - let Inst{15-12} = Rd; - let Inst{19-16} = Rn; -} -def RSCrs : AsI1<0b0111, (outs GPR:$Rd), (ins GPR:$Rn, so_reg:$shift), - DPSoRegFrm, IIC_iALUsr, "rsc", "\t$Rd, $Rn, $shift", - [(set GPR:$Rd, (sube_dead_carry so_reg:$shift, GPR:$Rn))]>, - Requires<[IsARM]> { - bits<4> Rd; - bits<4> Rn; - bits<12> shift; - let Inst{25} = 0; - let Inst{11-0} = shift; - let Inst{15-12} = Rd; - let Inst{19-16} = Rn; -} -} +// FIXME: Eliminate them if we can write def : Pat patterns which defines +// CPSR and the implicit def of CPSR is not needed. +defm RSBS : AsI1_rbin_s_is<0b0011, "rsb", + IIC_iALUi, IIC_iALUr, IIC_iALUsr, + BinOpFrag<(ARMsubc node:$LHS, node:$RHS)>>; -// NOTE: CPSR def omitted because it will be handled by the custom inserter. -let usesCustomInserter = 1, Uses = [CPSR] in { -def RSCSri : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, so_imm:$imm), - 4, IIC_iALUi, - [(set GPR:$Rd, (sube_dead_carry so_imm:$imm, GPR:$Rn))]>; -def RSCSrs : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, so_reg:$shift), - 4, IIC_iALUsr, - [(set GPR:$Rd, (sube_dead_carry so_reg:$shift, GPR:$Rn))]>; -} +defm RSC : AI1_rsc_irs<0b0111, "rsc", + BinOpWithFlagFrag<(ARMsube node:$LHS, node:$RHS, node:$FLAG)>, + "RSC">; // (sub X, imm) gets canonicalized to (add X, -imm). Match this form. // The assume-no-carry-in form uses the negation of the input since add/sub // assume opposite meanings of the carry flag (i.e., carry == !borrow). // See the definition of AddWithCarry() in the ARM ARM A2.2.1 for the gory // details. -def : ARMPat<(add GPR:$src, so_imm_neg:$imm), - (SUBri GPR:$src, so_imm_neg:$imm)>; -def : ARMPat<(addc GPR:$src, so_imm_neg:$imm), - (SUBSri GPR:$src, so_imm_neg:$imm)>; +def : ARMPat<(add GPR:$src, so_imm_neg:$imm), + (SUBri GPR:$src, so_imm_neg:$imm)>; +def : ARMPat<(ARMaddc GPR:$src, so_imm_neg:$imm), + (SUBSri GPR:$src, so_imm_neg:$imm)>; + // The with-carry-in form matches bitwise not instead of the negation. // Effectively, the inverse interpretation of the carry flag already accounts // for part of the negation. -def : ARMPat<(adde_dead_carry GPR:$src, so_imm_not:$imm), - (SBCri GPR:$src, so_imm_not:$imm)>; -def : ARMPat<(adde_live_carry GPR:$src, so_imm_not:$imm), - (SBCSri GPR:$src, so_imm_not:$imm)>; +def : ARMPat<(ARMadde GPR:$src, so_imm_not:$imm, CPSR), + (SBCri GPR:$src, so_imm_not:$imm)>; // Note: These are implemented in C++ code, because they have to generate // ADD/SUBrs instructions, which use a complex pattern that a xform function @@ -2427,12 +3138,13 @@ def : ARMPat<(adde_live_carry GPR:$src, so_imm_not:$imm), // (mul X, 2^n+1) -> (add (X << n), X) // (mul X, 2^n-1) -> (rsb X, (X << n)) -// ARM Arithmetic Instruction -- for disassembly only +// ARM Arithmetic Instruction // GPR:$dst = GPR:$a op GPR:$b class AAI op27_20, bits<8> op11_4, string opc, - list pattern = [/* For disassembly only; pattern left blank */], - dag iops = (ins GPR:$Rn, GPR:$Rm), string asm = "\t$Rd, $Rn, $Rm"> - : AI<(outs GPR:$Rd), iops, DPFrm, IIC_iALUr, opc, asm, pattern> { + list pattern = [], + dag iops = (ins GPRnopc:$Rn, GPRnopc:$Rm), + string asm = "\t$Rd, $Rn, $Rm"> + : AI<(outs GPRnopc:$Rd), iops, DPFrm, IIC_iALUr, opc, asm, pattern> { bits<4> Rn; bits<4> Rd; bits<4> Rm; @@ -2443,17 +3155,19 @@ class AAI op27_20, bits<8> op11_4, string opc, let Inst{3-0} = Rm; } -// Saturating add/subtract -- for disassembly only +// Saturating add/subtract def QADD : AAI<0b00010000, 0b00000101, "qadd", - [(set GPR:$Rd, (int_arm_qadd GPR:$Rm, GPR:$Rn))], - (ins GPR:$Rm, GPR:$Rn), "\t$Rd, $Rm, $Rn">; + [(set GPRnopc:$Rd, (int_arm_qadd GPRnopc:$Rm, GPRnopc:$Rn))], + (ins GPRnopc:$Rm, GPRnopc:$Rn), "\t$Rd, $Rm, $Rn">; def QSUB : AAI<0b00010010, 0b00000101, "qsub", - [(set GPR:$Rd, (int_arm_qsub GPR:$Rm, GPR:$Rn))], - (ins GPR:$Rm, GPR:$Rn), "\t$Rd, $Rm, $Rn">; -def QDADD : AAI<0b00010100, 0b00000101, "qdadd", [], (ins GPR:$Rm, GPR:$Rn), + [(set GPRnopc:$Rd, (int_arm_qsub GPRnopc:$Rm, GPRnopc:$Rn))], + (ins GPRnopc:$Rm, GPRnopc:$Rn), "\t$Rd, $Rm, $Rn">; +def QDADD : AAI<0b00010100, 0b00000101, "qdadd", [], + (ins GPRnopc:$Rm, GPRnopc:$Rn), "\t$Rd, $Rm, $Rn">; -def QDSUB : AAI<0b00010110, 0b00000101, "qdsub", [], (ins GPR:$Rm, GPR:$Rn), +def QDSUB : AAI<0b00010110, 0b00000101, "qdsub", [], + (ins GPRnopc:$Rm, GPRnopc:$Rn), "\t$Rd, $Rm, $Rn">; def QADD16 : AAI<0b01100010, 0b11110001, "qadd16">; @@ -2469,7 +3183,7 @@ def UQSAX : AAI<0b01100110, 0b11110101, "uqsax">; def UQSUB16 : AAI<0b01100110, 0b11110111, "uqsub16">; def UQSUB8 : AAI<0b01100110, 0b11111111, "uqsub8">; -// Signed/Unsigned add/subtract -- for disassembly only +// Signed/Unsigned add/subtract def SASX : AAI<0b01100001, 0b11110011, "sasx">; def SADD16 : AAI<0b01100001, 0b11110001, "sadd16">; @@ -2484,7 +3198,7 @@ def USAX : AAI<0b01100101, 0b11110101, "usax">; def USUB16 : AAI<0b01100101, 0b11110111, "usub16">; def USUB8 : AAI<0b01100101, 0b11111111, "usub8">; -// Signed/Unsigned halving add/subtract -- for disassembly only +// Signed/Unsigned halving add/subtract def SHASX : AAI<0b01100011, 0b11110011, "shasx">; def SHADD16 : AAI<0b01100011, 0b11110001, "shadd16">; @@ -2499,7 +3213,7 @@ def UHSAX : AAI<0b01100111, 0b11110101, "uhsax">; def UHSUB16 : AAI<0b01100111, 0b11110111, "uhsub16">; def UHSUB8 : AAI<0b01100111, 0b11111111, "uhsub8">; -// Unsigned Sum of Absolute Differences [and Accumulate] -- for disassembly only +// Unsigned Sum of Absolute Differences [and Accumulate]. def USAD8 : AI<(outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm), MulFrm /* for convenience */, NoItinerary, "usad8", @@ -2531,11 +3245,11 @@ def USADA8 : AI<(outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm, GPR:$Ra), let Inst{3-0} = Rn; } -// Signed/Unsigned saturate -- for disassembly only +// Signed/Unsigned saturate -def SSAT : AI<(outs GPR:$Rd), (ins ssat_imm:$sat_imm, GPR:$a, shift_imm:$sh), - SatFrm, NoItinerary, "ssat", "\t$Rd, $sat_imm, $a$sh", - [/* For disassembly only; pattern left blank */]> { +def SSAT : AI<(outs GPRnopc:$Rd), + (ins imm1_32:$sat_imm, GPRnopc:$Rn, shift_imm:$sh), + SatFrm, NoItinerary, "ssat", "\t$Rd, $sat_imm, $Rn$sh", []> { bits<4> Rd; bits<5> sat_imm; bits<4> Rn; @@ -2544,14 +3258,14 @@ def SSAT : AI<(outs GPR:$Rd), (ins ssat_imm:$sat_imm, GPR:$a, shift_imm:$sh), let Inst{5-4} = 0b01; let Inst{20-16} = sat_imm; let Inst{15-12} = Rd; - let Inst{11-7} = sh{7-3}; - let Inst{6} = sh{0}; + let Inst{11-7} = sh{4-0}; + let Inst{6} = sh{5}; let Inst{3-0} = Rn; } -def SSAT16 : AI<(outs GPR:$Rd), (ins ssat_imm:$sat_imm, GPR:$Rn), SatFrm, - NoItinerary, "ssat16", "\t$Rd, $sat_imm, $Rn", - [/* For disassembly only; pattern left blank */]> { +def SSAT16 : AI<(outs GPRnopc:$Rd), + (ins imm1_16:$sat_imm, GPRnopc:$Rn), SatFrm, + NoItinerary, "ssat16", "\t$Rd, $sat_imm, $Rn", []> { bits<4> Rd; bits<4> sat_imm; bits<4> Rn; @@ -2562,9 +3276,9 @@ def SSAT16 : AI<(outs GPR:$Rd), (ins ssat_imm:$sat_imm, GPR:$Rn), SatFrm, let Inst{3-0} = Rn; } -def USAT : AI<(outs GPR:$Rd), (ins i32imm:$sat_imm, GPR:$a, shift_imm:$sh), - SatFrm, NoItinerary, "usat", "\t$Rd, $sat_imm, $a$sh", - [/* For disassembly only; pattern left blank */]> { +def USAT : AI<(outs GPRnopc:$Rd), + (ins imm0_31:$sat_imm, GPRnopc:$Rn, shift_imm:$sh), + SatFrm, NoItinerary, "usat", "\t$Rd, $sat_imm, $Rn$sh", []> { bits<4> Rd; bits<5> sat_imm; bits<4> Rn; @@ -2572,15 +3286,15 @@ def USAT : AI<(outs GPR:$Rd), (ins i32imm:$sat_imm, GPR:$a, shift_imm:$sh), let Inst{27-21} = 0b0110111; let Inst{5-4} = 0b01; let Inst{15-12} = Rd; - let Inst{11-7} = sh{7-3}; - let Inst{6} = sh{0}; + let Inst{11-7} = sh{4-0}; + let Inst{6} = sh{5}; let Inst{20-16} = sat_imm; let Inst{3-0} = Rn; } -def USAT16 : AI<(outs GPR:$Rd), (ins i32imm:$sat_imm, GPR:$a), SatFrm, - NoItinerary, "usat16", "\t$Rd, $sat_imm, $a", - [/* For disassembly only; pattern left blank */]> { +def USAT16 : AI<(outs GPRnopc:$Rd), + (ins imm0_15:$sat_imm, GPRnopc:$Rn), SatFrm, + NoItinerary, "usat16", "\t$Rd, $sat_imm, $Rn", []> { bits<4> Rd; bits<4> sat_imm; bits<4> Rn; @@ -2591,8 +3305,10 @@ def USAT16 : AI<(outs GPR:$Rd), (ins i32imm:$sat_imm, GPR:$a), SatFrm, let Inst{3-0} = Rn; } -def : ARMV6Pat<(int_arm_ssat GPR:$a, imm:$pos), (SSAT imm:$pos, GPR:$a, 0)>; -def : ARMV6Pat<(int_arm_usat GPR:$a, imm:$pos), (USAT imm:$pos, GPR:$a, 0)>; +def : ARMV6Pat<(int_arm_ssat GPRnopc:$a, imm:$pos), + (SSAT imm:$pos, GPRnopc:$a, 0)>; +def : ARMV6Pat<(int_arm_usat GPRnopc:$a, imm:$pos), + (USAT imm:$pos, GPRnopc:$a, 0)>; //===----------------------------------------------------------------------===// // Bitwise Instructions. @@ -2611,6 +3327,10 @@ defm BIC : AsI1_bin_irs<0b1110, "bic", IIC_iBITi, IIC_iBITr, IIC_iBITsr, BinOpFrag<(and node:$LHS, (not node:$RHS))>, "BIC">; +// FIXME: bf_inv_mask_imm should be two operands, the lsb and the msb, just +// like in the actual instruction encoding. The complexity of mapping the mask +// to the lsb/msb pair should be handled by ISel, not encapsulated in the +// instruction description. def BFC : I<(outs GPR:$Rd), (ins GPR:$src, bf_inv_mask_imm:$imm), AddrMode1, 4, IndexModeNone, DPFrm, IIC_iUNAsi, "bfc", "\t$Rd, $imm", "$src = $Rd", @@ -2622,16 +3342,16 @@ def BFC : I<(outs GPR:$Rd), (ins GPR:$src, bf_inv_mask_imm:$imm), let Inst{6-0} = 0b0011111; let Inst{15-12} = Rd; let Inst{11-7} = imm{4-0}; // lsb - let Inst{20-16} = imm{9-5}; // width + let Inst{20-16} = imm{9-5}; // msb } // A8.6.18 BFI - Bitfield insert (Encoding A1) -def BFI : I<(outs GPR:$Rd), (ins GPR:$src, GPR:$Rn, bf_inv_mask_imm:$imm), - AddrMode1, 4, IndexModeNone, DPFrm, IIC_iUNAsi, - "bfi", "\t$Rd, $Rn, $imm", "$src = $Rd", - [(set GPR:$Rd, (ARMbfi GPR:$src, GPR:$Rn, - bf_inv_mask_imm:$imm))]>, - Requires<[IsARM, HasV6T2]> { +def BFI:I<(outs GPRnopc:$Rd), (ins GPRnopc:$src, GPR:$Rn, bf_inv_mask_imm:$imm), + AddrMode1, 4, IndexModeNone, DPFrm, IIC_iUNAsi, + "bfi", "\t$Rd, $Rn, $imm", "$src = $Rd", + [(set GPRnopc:$Rd, (ARMbfi GPRnopc:$src, GPR:$Rn, + bf_inv_mask_imm:$imm))]>, + Requires<[IsARM, HasV6T2]> { bits<4> Rd; bits<4> Rn; bits<10> imm; @@ -2643,25 +3363,6 @@ def BFI : I<(outs GPR:$Rd), (ins GPR:$src, GPR:$Rn, bf_inv_mask_imm:$imm), let Inst{3-0} = Rn; } -// GNU as only supports this form of bfi (w/ 4 arguments) -let isAsmParserOnly = 1 in -def BFI4p : I<(outs GPR:$Rd), (ins GPR:$src, GPR:$Rn, - lsb_pos_imm:$lsb, width_imm:$width), - AddrMode1, 4, IndexModeNone, DPFrm, IIC_iUNAsi, - "bfi", "\t$Rd, $Rn, $lsb, $width", "$src = $Rd", - []>, Requires<[IsARM, HasV6T2]> { - bits<4> Rd; - bits<4> Rn; - bits<5> lsb; - bits<5> width; - let Inst{27-21} = 0b0111110; - let Inst{6-4} = 0b001; // Rn: Inst{3-0} != 15 - let Inst{15-12} = Rd; - let Inst{11-7} = lsb; - let Inst{20-16} = width; // Custom encoder => lsb+width-1 - let Inst{3-0} = Rn; -} - def MVNr : AsI1<0b1111, (outs GPR:$Rd), (ins GPR:$Rm), DPFrm, IIC_iMVNr, "mvn", "\t$Rd, $Rm", [(set GPR:$Rd, (not GPR:$Rm))]>, UnaryDP { @@ -2673,15 +3374,31 @@ def MVNr : AsI1<0b1111, (outs GPR:$Rd), (ins GPR:$Rm), DPFrm, IIC_iMVNr, let Inst{15-12} = Rd; let Inst{3-0} = Rm; } -def MVNs : AsI1<0b1111, (outs GPR:$Rd), (ins so_reg:$shift), DPSoRegFrm, - IIC_iMVNsr, "mvn", "\t$Rd, $shift", - [(set GPR:$Rd, (not so_reg:$shift))]>, UnaryDP { +def MVNsi : AsI1<0b1111, (outs GPR:$Rd), (ins so_reg_imm:$shift), + DPSoRegImmFrm, IIC_iMVNsr, "mvn", "\t$Rd, $shift", + [(set GPR:$Rd, (not so_reg_imm:$shift))]>, UnaryDP { + bits<4> Rd; + bits<12> shift; + let Inst{25} = 0; + let Inst{19-16} = 0b0000; + let Inst{15-12} = Rd; + let Inst{11-5} = shift{11-5}; + let Inst{4} = 0; + let Inst{3-0} = shift{3-0}; +} +def MVNsr : AsI1<0b1111, (outs GPR:$Rd), (ins so_reg_reg:$shift), + DPSoRegRegFrm, IIC_iMVNsr, "mvn", "\t$Rd, $shift", + [(set GPR:$Rd, (not so_reg_reg:$shift))]>, UnaryDP { bits<4> Rd; bits<12> shift; let Inst{25} = 0; let Inst{19-16} = 0b0000; let Inst{15-12} = Rd; - let Inst{11-0} = shift; + let Inst{11-8} = shift{11-8}; + let Inst{7} = 0; + let Inst{6-5} = shift{6-5}; + let Inst{4} = 1; + let Inst{3-0} = shift{3-0}; } let isReMaterializable = 1, isAsCheapAsAMove = 1, isMoveImm = 1 in def MVNi : AsI1<0b1111, (outs GPR:$Rd), (ins so_imm:$imm), DPFrm, @@ -2820,8 +3537,8 @@ def UMAAL : AMul1I <0b0000010, (outs GPR:$RdLo, GPR:$RdHi), bits<4> RdHi; bits<4> Rm; bits<4> Rn; - let Inst{19-16} = RdLo; - let Inst{15-12} = RdHi; + let Inst{19-16} = RdHi; + let Inst{15-12} = RdLo; let Inst{11-8} = Rm; let Inst{3-0} = Rn; } @@ -2855,8 +3572,7 @@ def SMMUL : AMul2I <0b0111010, 0b0001, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm), } def SMMULR : AMul2I <0b0111010, 0b0011, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm), - IIC_iMUL32, "smmulr", "\t$Rd, $Rn, $Rm", - [/* For disassembly only; pattern left blank */]>, + IIC_iMUL32, "smmulr", "\t$Rd, $Rn, $Rm", []>, Requires<[IsARM, HasV6]> { let Inst{15-12} = 0b1111; } @@ -2869,8 +3585,7 @@ def SMMLA : AMul2Ia <0b0111010, 0b0001, (outs GPR:$Rd), def SMMLAR : AMul2Ia <0b0111010, 0b0011, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm, GPR:$Ra), - IIC_iMAC32, "smmlar", "\t$Rd, $Rn, $Rm, $Ra", - [/* For disassembly only; pattern left blank */]>, + IIC_iMAC32, "smmlar", "\t$Rd, $Rn, $Rm, $Ra", []>, Requires<[IsARM, HasV6]>; def SMMLS : AMul2Ia <0b0111010, 0b1101, (outs GPR:$Rd), @@ -2881,8 +3596,7 @@ def SMMLS : AMul2Ia <0b0111010, 0b1101, (outs GPR:$Rd), def SMMLSR : AMul2Ia <0b0111010, 0b1111, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm, GPR:$Ra), - IIC_iMAC32, "smmlsr", "\t$Rd, $Rn, $Rm, $Ra", - [/* For disassembly only; pattern left blank */]>, + IIC_iMAC32, "smmlsr", "\t$Rd, $Rn, $Rm, $Ra", []>, Requires<[IsARM, HasV6]>; multiclass AI_smul { @@ -2925,92 +3639,95 @@ multiclass AI_smul { multiclass AI_smla { - def BB : AMulxyIa<0b0001000, 0b00, (outs GPR:$Rd), - (ins GPR:$Rn, GPR:$Rm, GPR:$Ra), + let DecoderMethod = "DecodeSMLAInstruction" in { + def BB : AMulxyIa<0b0001000, 0b00, (outs GPRnopc:$Rd), + (ins GPRnopc:$Rn, GPRnopc:$Rm, GPR:$Ra), IIC_iMAC16, !strconcat(opc, "bb"), "\t$Rd, $Rn, $Rm, $Ra", - [(set GPR:$Rd, (add GPR:$Ra, - (opnode (sext_inreg GPR:$Rn, i16), - (sext_inreg GPR:$Rm, i16))))]>, + [(set GPRnopc:$Rd, (add GPR:$Ra, + (opnode (sext_inreg GPRnopc:$Rn, i16), + (sext_inreg GPRnopc:$Rm, i16))))]>, Requires<[IsARM, HasV5TE]>; - def BT : AMulxyIa<0b0001000, 0b10, (outs GPR:$Rd), - (ins GPR:$Rn, GPR:$Rm, GPR:$Ra), + def BT : AMulxyIa<0b0001000, 0b10, (outs GPRnopc:$Rd), + (ins GPRnopc:$Rn, GPRnopc:$Rm, GPR:$Ra), IIC_iMAC16, !strconcat(opc, "bt"), "\t$Rd, $Rn, $Rm, $Ra", - [(set GPR:$Rd, (add GPR:$Ra, (opnode (sext_inreg GPR:$Rn, i16), - (sra GPR:$Rm, (i32 16)))))]>, + [(set GPRnopc:$Rd, + (add GPR:$Ra, (opnode (sext_inreg GPRnopc:$Rn, i16), + (sra GPRnopc:$Rm, (i32 16)))))]>, Requires<[IsARM, HasV5TE]>; - def TB : AMulxyIa<0b0001000, 0b01, (outs GPR:$Rd), - (ins GPR:$Rn, GPR:$Rm, GPR:$Ra), + def TB : AMulxyIa<0b0001000, 0b01, (outs GPRnopc:$Rd), + (ins GPRnopc:$Rn, GPRnopc:$Rm, GPR:$Ra), IIC_iMAC16, !strconcat(opc, "tb"), "\t$Rd, $Rn, $Rm, $Ra", - [(set GPR:$Rd, (add GPR:$Ra, (opnode (sra GPR:$Rn, (i32 16)), - (sext_inreg GPR:$Rm, i16))))]>, + [(set GPRnopc:$Rd, + (add GPR:$Ra, (opnode (sra GPRnopc:$Rn, (i32 16)), + (sext_inreg GPRnopc:$Rm, i16))))]>, Requires<[IsARM, HasV5TE]>; - def TT : AMulxyIa<0b0001000, 0b11, (outs GPR:$Rd), - (ins GPR:$Rn, GPR:$Rm, GPR:$Ra), + def TT : AMulxyIa<0b0001000, 0b11, (outs GPRnopc:$Rd), + (ins GPRnopc:$Rn, GPRnopc:$Rm, GPR:$Ra), IIC_iMAC16, !strconcat(opc, "tt"), "\t$Rd, $Rn, $Rm, $Ra", - [(set GPR:$Rd, (add GPR:$Ra, (opnode (sra GPR:$Rn, (i32 16)), - (sra GPR:$Rm, (i32 16)))))]>, + [(set GPRnopc:$Rd, + (add GPR:$Ra, (opnode (sra GPRnopc:$Rn, (i32 16)), + (sra GPRnopc:$Rm, (i32 16)))))]>, Requires<[IsARM, HasV5TE]>; - def WB : AMulxyIa<0b0001001, 0b00, (outs GPR:$Rd), - (ins GPR:$Rn, GPR:$Rm, GPR:$Ra), + def WB : AMulxyIa<0b0001001, 0b00, (outs GPRnopc:$Rd), + (ins GPRnopc:$Rn, GPRnopc:$Rm, GPR:$Ra), IIC_iMAC16, !strconcat(opc, "wb"), "\t$Rd, $Rn, $Rm, $Ra", - [(set GPR:$Rd, (add GPR:$Ra, (sra (opnode GPR:$Rn, - (sext_inreg GPR:$Rm, i16)), (i32 16))))]>, + [(set GPRnopc:$Rd, + (add GPR:$Ra, (sra (opnode GPRnopc:$Rn, + (sext_inreg GPRnopc:$Rm, i16)), (i32 16))))]>, Requires<[IsARM, HasV5TE]>; - def WT : AMulxyIa<0b0001001, 0b10, (outs GPR:$Rd), - (ins GPR:$Rn, GPR:$Rm, GPR:$Ra), + def WT : AMulxyIa<0b0001001, 0b10, (outs GPRnopc:$Rd), + (ins GPRnopc:$Rn, GPRnopc:$Rm, GPR:$Ra), IIC_iMAC16, !strconcat(opc, "wt"), "\t$Rd, $Rn, $Rm, $Ra", - [(set GPR:$Rd, (add GPR:$Ra, (sra (opnode GPR:$Rn, - (sra GPR:$Rm, (i32 16))), (i32 16))))]>, + [(set GPRnopc:$Rd, + (add GPR:$Ra, (sra (opnode GPRnopc:$Rn, + (sra GPRnopc:$Rm, (i32 16))), (i32 16))))]>, Requires<[IsARM, HasV5TE]>; + } } defm SMUL : AI_smul<"smul", BinOpFrag<(mul node:$LHS, node:$RHS)>>; defm SMLA : AI_smla<"smla", BinOpFrag<(mul node:$LHS, node:$RHS)>>; -// Halfword multiply accumulate long: SMLAL -- for disassembly only -def SMLALBB : AMulxyI64<0b0001010, 0b00, (outs GPR:$RdLo, GPR:$RdHi), - (ins GPR:$Rn, GPR:$Rm), - IIC_iMAC64, "smlalbb", "\t$RdLo, $RdHi, $Rn, $Rm", - [/* For disassembly only; pattern left blank */]>, +// Halfword multiply accumulate long: SMLAL. +def SMLALBB : AMulxyI64<0b0001010, 0b00, (outs GPRnopc:$RdLo, GPRnopc:$RdHi), + (ins GPRnopc:$Rn, GPRnopc:$Rm), + IIC_iMAC64, "smlalbb", "\t$RdLo, $RdHi, $Rn, $Rm", []>, Requires<[IsARM, HasV5TE]>; -def SMLALBT : AMulxyI64<0b0001010, 0b10, (outs GPR:$RdLo, GPR:$RdHi), - (ins GPR:$Rn, GPR:$Rm), - IIC_iMAC64, "smlalbt", "\t$RdLo, $RdHi, $Rn, $Rm", - [/* For disassembly only; pattern left blank */]>, +def SMLALBT : AMulxyI64<0b0001010, 0b10, (outs GPRnopc:$RdLo, GPRnopc:$RdHi), + (ins GPRnopc:$Rn, GPRnopc:$Rm), + IIC_iMAC64, "smlalbt", "\t$RdLo, $RdHi, $Rn, $Rm", []>, Requires<[IsARM, HasV5TE]>; -def SMLALTB : AMulxyI64<0b0001010, 0b01, (outs GPR:$RdLo, GPR:$RdHi), - (ins GPR:$Rn, GPR:$Rm), - IIC_iMAC64, "smlaltb", "\t$RdLo, $RdHi, $Rn, $Rm", - [/* For disassembly only; pattern left blank */]>, +def SMLALTB : AMulxyI64<0b0001010, 0b01, (outs GPRnopc:$RdLo, GPRnopc:$RdHi), + (ins GPRnopc:$Rn, GPRnopc:$Rm), + IIC_iMAC64, "smlaltb", "\t$RdLo, $RdHi, $Rn, $Rm", []>, Requires<[IsARM, HasV5TE]>; -def SMLALTT : AMulxyI64<0b0001010, 0b11, (outs GPR:$RdLo, GPR:$RdHi), - (ins GPR:$Rn, GPR:$Rm), - IIC_iMAC64, "smlaltt", "\t$RdLo, $RdHi, $Rn, $Rm", - [/* For disassembly only; pattern left blank */]>, +def SMLALTT : AMulxyI64<0b0001010, 0b11, (outs GPRnopc:$RdLo, GPRnopc:$RdHi), + (ins GPRnopc:$Rn, GPRnopc:$Rm), + IIC_iMAC64, "smlaltt", "\t$RdLo, $RdHi, $Rn, $Rm", []>, Requires<[IsARM, HasV5TE]>; -// Helper class for AI_smld -- for disassembly only +// Helper class for AI_smld. class AMulDualIbase : AI, Requires<[IsARM, HasV6]> { bits<4> Rn; bits<4> Rm; - let Inst{4} = 1; - let Inst{5} = swap; - let Inst{6} = sub; - let Inst{7} = 0; - let Inst{21-20} = 0b00; - let Inst{22} = long; let Inst{27-23} = 0b01110; + let Inst{22} = long; + let Inst{21-20} = 0b00; let Inst{11-8} = Rm; + let Inst{7} = 0; + let Inst{6} = sub; + let Inst{5} = swap; + let Inst{4} = 1; let Inst{3-0} = Rn; } class AMulDualI : AMulDualIbase { bits<4> Ra; + bits<4> Rd; + let Inst{19-16} = Rd; let Inst{15-12} = Ra; } class AMulDualI64 { - def D : AMulDualIa<0, sub, 0, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm, GPR:$Ra), + def D : AMulDualIa<0, sub, 0, (outs GPRnopc:$Rd), + (ins GPRnopc:$Rn, GPRnopc:$Rm, GPR:$Ra), NoItinerary, !strconcat(opc, "d"), "\t$Rd, $Rn, $Rm, $Ra">; - def DX: AMulDualIa<0, sub, 1, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm, GPR:$Ra), + def DX: AMulDualIa<0, sub, 1, (outs GPRnopc:$Rd), + (ins GPRnopc:$Rn, GPRnopc:$Rm, GPR:$Ra), NoItinerary, !strconcat(opc, "dx"), "\t$Rd, $Rn, $Rm, $Ra">; - def LD: AMulDualI64<1, sub, 0, (outs GPR:$RdLo,GPR:$RdHi), - (ins GPR:$Rn, GPR:$Rm), NoItinerary, + def LD: AMulDualI64<1, sub, 0, (outs GPRnopc:$RdLo, GPRnopc:$RdHi), + (ins GPRnopc:$Rn, GPRnopc:$Rm), NoItinerary, !strconcat(opc, "ld"), "\t$RdLo, $RdHi, $Rn, $Rm">; - def LDX : AMulDualI64<1, sub, 1, (outs GPR:$RdLo,GPR:$RdHi), - (ins GPR:$Rn, GPR:$Rm), NoItinerary, + def LDX : AMulDualI64<1, sub, 1, (outs GPRnopc:$RdLo, GPRnopc:$RdHi), + (ins GPRnopc:$Rn, GPRnopc:$Rm), NoItinerary, !strconcat(opc, "ldx"),"\t$RdLo, $RdHi, $Rn, $Rm">; } @@ -3058,10 +3779,10 @@ defm SMLS : AI_smld<1, "smls">; multiclass AI_sdml { - def D : AMulDualI<0, sub, 0, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm), - NoItinerary, !strconcat(opc, "d"), "\t$Rd, $Rn, $Rm">; - def DX : AMulDualI<0, sub, 1, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm), - NoItinerary, !strconcat(opc, "dx"), "\t$Rd, $Rn, $Rm">; + def D:AMulDualI<0, sub, 0, (outs GPRnopc:$Rd), (ins GPRnopc:$Rn, GPRnopc:$Rm), + NoItinerary, !strconcat(opc, "d"), "\t$Rd, $Rn, $Rm">; + def DX:AMulDualI<0, sub, 1, (outs GPRnopc:$Rd),(ins GPRnopc:$Rn, GPRnopc:$Rm), + NoItinerary, !strconcat(opc, "dx"), "\t$Rd, $Rn, $Rm">; } defm SMUA : AI_sdml<0, "smua">; @@ -3100,55 +3821,38 @@ def : ARMV6Pat<(or (sra (shl GPR:$Rm, (i32 24)), (i32 16)), (and (srl GPR:$Rm, (i32 8)), 0xFF)), (REVSH GPR:$Rm)>; -def lsl_shift_imm : SDNodeXFormgetZExtValue()); - return CurDAG->getTargetConstant(Sh, MVT::i32); -}]>; - -def lsl_amt : ImmLeaf 0 && Imm < 32; -}], lsl_shift_imm>; - -def PKHBT : APKHI<0b01101000, 0, (outs GPR:$Rd), - (ins GPR:$Rn, GPR:$Rm, shift_imm:$sh), +def PKHBT : APKHI<0b01101000, 0, (outs GPRnopc:$Rd), + (ins GPRnopc:$Rn, GPRnopc:$Rm, pkh_lsl_amt:$sh), IIC_iALUsi, "pkhbt", "\t$Rd, $Rn, $Rm$sh", - [(set GPR:$Rd, (or (and GPR:$Rn, 0xFFFF), - (and (shl GPR:$Rm, lsl_amt:$sh), - 0xFFFF0000)))]>, + [(set GPRnopc:$Rd, (or (and GPRnopc:$Rn, 0xFFFF), + (and (shl GPRnopc:$Rm, pkh_lsl_amt:$sh), + 0xFFFF0000)))]>, Requires<[IsARM, HasV6]>; // Alternate cases for PKHBT where identities eliminate some nodes. -def : ARMV6Pat<(or (and GPR:$Rn, 0xFFFF), (and GPR:$Rm, 0xFFFF0000)), - (PKHBT GPR:$Rn, GPR:$Rm, 0)>; -def : ARMV6Pat<(or (and GPR:$Rn, 0xFFFF), (shl GPR:$Rm, imm16_31:$sh)), - (PKHBT GPR:$Rn, GPR:$Rm, (lsl_shift_imm imm16_31:$sh))>; - -def asr_shift_imm : SDNodeXFormgetZExtValue()); - return CurDAG->getTargetConstant(Sh, MVT::i32); -}]>; - -def asr_amt : ImmLeaf 0 && Imm <= 32; -}], asr_shift_imm>; +def : ARMV6Pat<(or (and GPRnopc:$Rn, 0xFFFF), (and GPRnopc:$Rm, 0xFFFF0000)), + (PKHBT GPRnopc:$Rn, GPRnopc:$Rm, 0)>; +def : ARMV6Pat<(or (and GPRnopc:$Rn, 0xFFFF), (shl GPRnopc:$Rm, imm16_31:$sh)), + (PKHBT GPRnopc:$Rn, GPRnopc:$Rm, imm16_31:$sh)>; // Note: Shifts of 1-15 bits will be transformed to srl instead of sra and // will match the pattern below. -def PKHTB : APKHI<0b01101000, 1, (outs GPR:$Rd), - (ins GPR:$Rn, GPR:$Rm, shift_imm:$sh), +def PKHTB : APKHI<0b01101000, 1, (outs GPRnopc:$Rd), + (ins GPRnopc:$Rn, GPRnopc:$Rm, pkh_asr_amt:$sh), IIC_iBITsi, "pkhtb", "\t$Rd, $Rn, $Rm$sh", - [(set GPR:$Rd, (or (and GPR:$Rn, 0xFFFF0000), - (and (sra GPR:$Rm, asr_amt:$sh), - 0xFFFF)))]>, + [(set GPRnopc:$Rd, (or (and GPRnopc:$Rn, 0xFFFF0000), + (and (sra GPRnopc:$Rm, pkh_asr_amt:$sh), + 0xFFFF)))]>, Requires<[IsARM, HasV6]>; // Alternate cases for PKHTB where identities eliminate some nodes. Note that // a shift amount of 0 is *not legal* here, it is PKHBT instead. -def : ARMV6Pat<(or (and GPR:$src1, 0xFFFF0000), (srl GPR:$src2, imm16_31:$sh)), - (PKHTB GPR:$src1, GPR:$src2, (asr_shift_imm imm16_31:$sh))>; -def : ARMV6Pat<(or (and GPR:$src1, 0xFFFF0000), - (and (srl GPR:$src2, imm1_15:$sh), 0xFFFF)), - (PKHTB GPR:$src1, GPR:$src2, (asr_shift_imm imm1_15:$sh))>; +def : ARMV6Pat<(or (and GPRnopc:$src1, 0xFFFF0000), + (srl GPRnopc:$src2, imm16_31:$sh)), + (PKHTB GPRnopc:$src1, GPRnopc:$src2, imm16_31:$sh)>; +def : ARMV6Pat<(or (and GPRnopc:$src1, 0xFFFF0000), + (and (srl GPRnopc:$src2, imm1_15:$sh), 0xFFFF)), + (PKHTB GPRnopc:$src1, GPRnopc:$src2, imm1_15:$sh)>; //===----------------------------------------------------------------------===// // Comparison Instructions... @@ -3163,8 +3867,10 @@ def : ARMPat<(ARMcmpZ GPR:$src, so_imm:$imm), (CMPri GPR:$src, so_imm:$imm)>; def : ARMPat<(ARMcmpZ GPR:$src, GPR:$rhs), (CMPrr GPR:$src, GPR:$rhs)>; -def : ARMPat<(ARMcmpZ GPR:$src, so_reg:$rhs), - (CMPrs GPR:$src, so_reg:$rhs)>; +def : ARMPat<(ARMcmpZ GPR:$src, so_reg_imm:$rhs), + (CMPrsi GPR:$src, so_reg_imm:$rhs)>; +def : ARMPat<(ARMcmpZ GPR:$src, so_reg_reg:$rhs), + (CMPrsr GPR:$src, so_reg_reg:$rhs)>; // FIXME: We have to be careful when using the CMN instruction and comparison // with 0. One would expect these two pieces of code should give identical @@ -3250,15 +3956,23 @@ def MOVCCr : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$false, GPR:$Rm, pred:$p), 4, IIC_iCMOVr, [/*(set GPR:$Rd, (ARMcmov GPR:$false, GPR:$Rm, imm:$cc, CCR:$ccr))*/]>, RegConstraint<"$false = $Rd">; -def MOVCCs : ARMPseudoInst<(outs GPR:$Rd), - (ins GPR:$false, so_reg:$shift, pred:$p), +def MOVCCsi : ARMPseudoInst<(outs GPR:$Rd), + (ins GPR:$false, so_reg_imm:$shift, pred:$p), + 4, IIC_iCMOVsr, + [/*(set GPR:$Rd, (ARMcmov GPR:$false, so_reg_imm:$shift, + imm:$cc, CCR:$ccr))*/]>, + RegConstraint<"$false = $Rd">; +def MOVCCsr : ARMPseudoInst<(outs GPR:$Rd), + (ins GPR:$false, so_reg_reg:$shift, pred:$p), 4, IIC_iCMOVsr, - [/*(set GPR:$Rd, (ARMcmov GPR:$false, so_reg:$shift, imm:$cc, CCR:$ccr))*/]>, + [/*(set GPR:$Rd, (ARMcmov GPR:$false, so_reg_reg:$shift, + imm:$cc, CCR:$ccr))*/]>, RegConstraint<"$false = $Rd">; + let isMoveImm = 1 in def MOVCCi16 : ARMPseudoInst<(outs GPR:$Rd), - (ins GPR:$false, i32imm_hilo16:$imm, pred:$p), + (ins GPR:$false, imm0_65535_expr:$imm, pred:$p), 4, IIC_iMOVi, []>, RegConstraint<"$false = $Rd">, Requires<[IsARM, HasV6T2]>; @@ -3288,9 +4002,14 @@ def MVNCCi : ARMPseudoInst<(outs GPR:$Rd), // Atomic operations intrinsics // +def MemBarrierOptOperand : AsmOperandClass { + let Name = "MemBarrierOpt"; + let ParserMethod = "parseMemBarrierOptOperand"; +} def memb_opt : Operand { let PrintMethod = "printMemBOption"; let ParserMatchClass = MemBarrierOptOperand; + let DecoderMethod = "DecodeMemBarrierOption"; } // memory barriers protect the atomic sequences @@ -3321,8 +4040,16 @@ def ISB : AInoP<(outs), (ins memb_opt:$opt), MiscFrm, NoItinerary, let Inst{3-0} = opt; } +// Pseudo isntruction that combines movs + predicated rsbmi +// to implement integer ABS +let usesCustomInserter = 1, Defs = [CPSR] in { +def ABS : ARMPseudoInst< + (outs GPR:$dst), (ins GPR:$src), + 8, NoItinerary, []>; +} + let usesCustomInserter = 1 in { - let Uses = [CPSR] in { + let Defs = [CPSR] in { def ATOMIC_LOAD_ADD_I8 : PseudoInst< (outs GPR:$dst), (ins GPR:$ptr, GPR:$incr), NoItinerary, [(set GPR:$dst, (atomic_load_add_8 GPR:$ptr, GPR:$incr))]>; @@ -3437,44 +4164,47 @@ let usesCustomInserter = 1 in { } let mayLoad = 1 in { -def LDREXB : AIldrex<0b10, (outs GPR:$Rt), (ins addrmode7:$addr), NoItinerary, +def LDREXB : AIldrex<0b10, (outs GPR:$Rt), (ins addr_offset_none:$addr), + NoItinerary, "ldrexb", "\t$Rt, $addr", []>; -def LDREXH : AIldrex<0b11, (outs GPR:$Rt), (ins addrmode7:$addr), NoItinerary, - "ldrexh", "\t$Rt, $addr", []>; -def LDREX : AIldrex<0b00, (outs GPR:$Rt), (ins addrmode7:$addr), NoItinerary, - "ldrex", "\t$Rt, $addr", []>; +def LDREXH : AIldrex<0b11, (outs GPR:$Rt), (ins addr_offset_none:$addr), + NoItinerary, "ldrexh", "\t$Rt, $addr", []>; +def LDREX : AIldrex<0b00, (outs GPR:$Rt), (ins addr_offset_none:$addr), + NoItinerary, "ldrex", "\t$Rt, $addr", []>; let hasExtraDefRegAllocReq = 1 in - def LDREXD : AIldrex<0b01, (outs GPR:$Rt, GPR:$Rt2), (ins addrmode7:$addr), - NoItinerary, "ldrexd", "\t$Rt, $Rt2, $addr", []>; +def LDREXD: AIldrex<0b01, (outs GPR:$Rt, GPR:$Rt2),(ins addr_offset_none:$addr), + NoItinerary, "ldrexd", "\t$Rt, $Rt2, $addr", []> { + let DecoderMethod = "DecodeDoubleRegLoad"; +} } let mayStore = 1, Constraints = "@earlyclobber $Rd" in { -def STREXB : AIstrex<0b10, (outs GPR:$Rd), (ins GPR:$Rt, addrmode7:$addr), +def STREXB: AIstrex<0b10, (outs GPR:$Rd), (ins GPR:$Rt, addr_offset_none:$addr), NoItinerary, "strexb", "\t$Rd, $Rt, $addr", []>; -def STREXH : AIstrex<0b11, (outs GPR:$Rd), (ins GPR:$Rt, addrmode7:$addr), +def STREXH: AIstrex<0b11, (outs GPR:$Rd), (ins GPR:$Rt, addr_offset_none:$addr), NoItinerary, "strexh", "\t$Rd, $Rt, $addr", []>; -def STREX : AIstrex<0b00, (outs GPR:$Rd), (ins GPR:$Rt, addrmode7:$addr), +def STREX : AIstrex<0b00, (outs GPR:$Rd), (ins GPR:$Rt, addr_offset_none:$addr), NoItinerary, "strex", "\t$Rd, $Rt, $addr", []>; } let hasExtraSrcRegAllocReq = 1, Constraints = "@earlyclobber $Rd" in def STREXD : AIstrex<0b01, (outs GPR:$Rd), - (ins GPR:$Rt, GPR:$Rt2, addrmode7:$addr), - NoItinerary, "strexd", "\t$Rd, $Rt, $Rt2, $addr", []>; + (ins GPR:$Rt, GPR:$Rt2, addr_offset_none:$addr), + NoItinerary, "strexd", "\t$Rd, $Rt, $Rt2, $addr", []> { + let DecoderMethod = "DecodeDoubleRegStore"; +} -// Clear-Exclusive is for disassembly only. -def CLREX : AXI<(outs), (ins), MiscFrm, NoItinerary, "clrex", - [/* For disassembly only; pattern left blank */]>, +def CLREX : AXI<(outs), (ins), MiscFrm, NoItinerary, "clrex", []>, Requires<[IsARM, HasV7]> { let Inst{31-0} = 0b11110101011111111111000000011111; } -// SWP/SWPB are deprecated in V6/V7 and for disassembly only. -let mayLoad = 1 in { -def SWP : AIswp<0, (outs GPR:$Rt), (ins GPR:$Rt2, GPR:$Rn), "swp", - [/* For disassembly only; pattern left blank */]>; -def SWPB : AIswp<1, (outs GPR:$Rt), (ins GPR:$Rt2, GPR:$Rn), "swpb", - [/* For disassembly only; pattern left blank */]>; +// SWP/SWPB are deprecated in V6/V7. +let mayLoad = 1, mayStore = 1 in { +def SWP : AIswp<0, (outs GPR:$Rt), (ins GPR:$Rt2, addr_offset_none:$addr), + "swp", []>; +def SWPB: AIswp<1, (outs GPR:$Rt), (ins GPR:$Rt2, addr_offset_none:$addr), + "swpb", []>; } //===----------------------------------------------------------------------===// @@ -3526,108 +4256,171 @@ def CDP2 : ABXI<0b1110, (outs), (ins p_imm:$cop, imm0_15:$opc1, class ACI + : I { + let Inst{27-25} = 0b110; +} +class ACInoP : InoP { + opc, asm, "", []> { + let Inst{31-28} = 0b1111; let Inst{27-25} = 0b110; } - -multiclass LdStCop op31_28, bit load, dag ops, string opc, string cond>{ - - def _OFFSET : ACI<(outs), - !con((ins nohash_imm:$cop, nohash_imm:$CRd, addrmode2:$addr), ops), - !strconcat(opc, cond), "\tp$cop, cr$CRd, $addr"> { - let Inst{31-28} = op31_28; +multiclass LdStCop { + def _OFFSET : ACI<(outs), (ins p_imm:$cop, c_imm:$CRd, addrmode5:$addr), + asm, "\t$cop, $CRd, $addr"> { + bits<13> addr; + bits<4> cop; + bits<4> CRd; let Inst{24} = 1; // P = 1 + let Inst{23} = addr{8}; + let Inst{22} = Dbit; let Inst{21} = 0; // W = 0 - let Inst{22} = 0; // D = 0 let Inst{20} = load; + let Inst{19-16} = addr{12-9}; + let Inst{15-12} = CRd; + let Inst{11-8} = cop; + let Inst{7-0} = addr{7-0}; + let DecoderMethod = "DecodeCopMemInstruction"; } - - def _PRE : ACI<(outs), - !con((ins nohash_imm:$cop, nohash_imm:$CRd, addrmode2:$addr), ops), - !strconcat(opc, cond), "\tp$cop, cr$CRd, $addr!", IndexModePre> { - let Inst{31-28} = op31_28; + def _PRE : ACI<(outs), (ins p_imm:$cop, c_imm:$CRd, addrmode5:$addr), + asm, "\t$cop, $CRd, $addr!", IndexModePre> { + bits<13> addr; + bits<4> cop; + bits<4> CRd; let Inst{24} = 1; // P = 1 + let Inst{23} = addr{8}; + let Inst{22} = Dbit; let Inst{21} = 1; // W = 1 - let Inst{22} = 0; // D = 0 let Inst{20} = load; + let Inst{19-16} = addr{12-9}; + let Inst{15-12} = CRd; + let Inst{11-8} = cop; + let Inst{7-0} = addr{7-0}; + let DecoderMethod = "DecodeCopMemInstruction"; } - - def _POST : ACI<(outs), - !con((ins nohash_imm:$cop, nohash_imm:$CRd, addrmode2:$addr), ops), - !strconcat(opc, cond), "\tp$cop, cr$CRd, $addr", IndexModePost> { - let Inst{31-28} = op31_28; + def _POST: ACI<(outs), (ins p_imm:$cop, c_imm:$CRd, addr_offset_none:$addr, + postidx_imm8s4:$offset), + asm, "\t$cop, $CRd, $addr, $offset", IndexModePost> { + bits<9> offset; + bits<4> addr; + bits<4> cop; + bits<4> CRd; let Inst{24} = 0; // P = 0 + let Inst{23} = offset{8}; + let Inst{22} = Dbit; let Inst{21} = 1; // W = 1 - let Inst{22} = 0; // D = 0 let Inst{20} = load; + let Inst{19-16} = addr; + let Inst{15-12} = CRd; + let Inst{11-8} = cop; + let Inst{7-0} = offset{7-0}; + let DecoderMethod = "DecodeCopMemInstruction"; } - def _OPTION : ACI<(outs), - !con((ins nohash_imm:$cop,nohash_imm:$CRd,GPR:$base, nohash_imm:$option), - ops), - !strconcat(opc, cond), "\tp$cop, cr$CRd, [$base], \\{$option\\}"> { - let Inst{31-28} = op31_28; + (ins p_imm:$cop, c_imm:$CRd, addr_offset_none:$addr, + coproc_option_imm:$option), + asm, "\t$cop, $CRd, $addr, $option"> { + bits<8> option; + bits<4> addr; + bits<4> cop; + bits<4> CRd; let Inst{24} = 0; // P = 0 let Inst{23} = 1; // U = 1 + let Inst{22} = Dbit; let Inst{21} = 0; // W = 0 - let Inst{22} = 0; // D = 0 let Inst{20} = load; + let Inst{19-16} = addr; + let Inst{15-12} = CRd; + let Inst{11-8} = cop; + let Inst{7-0} = option; + let DecoderMethod = "DecodeCopMemInstruction"; } - - def L_OFFSET : ACI<(outs), - !con((ins nohash_imm:$cop, nohash_imm:$CRd, addrmode2:$addr), ops), - !strconcat(!strconcat(opc, "l"), cond), "\tp$cop, cr$CRd, $addr"> { - let Inst{31-28} = op31_28; +} +multiclass LdSt2Cop { + def _OFFSET : ACInoP<(outs), (ins p_imm:$cop, c_imm:$CRd, addrmode5:$addr), + asm, "\t$cop, $CRd, $addr"> { + bits<13> addr; + bits<4> cop; + bits<4> CRd; let Inst{24} = 1; // P = 1 + let Inst{23} = addr{8}; + let Inst{22} = Dbit; let Inst{21} = 0; // W = 0 - let Inst{22} = 1; // D = 1 let Inst{20} = load; + let Inst{19-16} = addr{12-9}; + let Inst{15-12} = CRd; + let Inst{11-8} = cop; + let Inst{7-0} = addr{7-0}; + let DecoderMethod = "DecodeCopMemInstruction"; } - - def L_PRE : ACI<(outs), - !con((ins nohash_imm:$cop, nohash_imm:$CRd, addrmode2:$addr), ops), - !strconcat(!strconcat(opc, "l"), cond), "\tp$cop, cr$CRd, $addr!", - IndexModePre> { - let Inst{31-28} = op31_28; + def _PRE : ACInoP<(outs), (ins p_imm:$cop, c_imm:$CRd, addrmode5:$addr), + asm, "\t$cop, $CRd, $addr!", IndexModePre> { + bits<13> addr; + bits<4> cop; + bits<4> CRd; let Inst{24} = 1; // P = 1 + let Inst{23} = addr{8}; + let Inst{22} = Dbit; let Inst{21} = 1; // W = 1 - let Inst{22} = 1; // D = 1 let Inst{20} = load; + let Inst{19-16} = addr{12-9}; + let Inst{15-12} = CRd; + let Inst{11-8} = cop; + let Inst{7-0} = addr{7-0}; + let DecoderMethod = "DecodeCopMemInstruction"; } - - def L_POST : ACI<(outs), - !con((ins nohash_imm:$cop, nohash_imm:$CRd, addrmode2:$addr), ops), - !strconcat(!strconcat(opc, "l"), cond), "\tp$cop, cr$CRd, $addr", - IndexModePost> { - let Inst{31-28} = op31_28; + def _POST: ACInoP<(outs), (ins p_imm:$cop, c_imm:$CRd, addr_offset_none:$addr, + postidx_imm8s4:$offset), + asm, "\t$cop, $CRd, $addr, $offset", IndexModePost> { + bits<9> offset; + bits<4> addr; + bits<4> cop; + bits<4> CRd; let Inst{24} = 0; // P = 0 + let Inst{23} = offset{8}; + let Inst{22} = Dbit; let Inst{21} = 1; // W = 1 - let Inst{22} = 1; // D = 1 let Inst{20} = load; + let Inst{19-16} = addr; + let Inst{15-12} = CRd; + let Inst{11-8} = cop; + let Inst{7-0} = offset{7-0}; + let DecoderMethod = "DecodeCopMemInstruction"; } - - def L_OPTION : ACI<(outs), - !con((ins nohash_imm:$cop, nohash_imm:$CRd,GPR:$base,nohash_imm:$option), - ops), - !strconcat(!strconcat(opc, "l"), cond), - "\tp$cop, cr$CRd, [$base], \\{$option\\}"> { - let Inst{31-28} = op31_28; + def _OPTION : ACInoP<(outs), + (ins p_imm:$cop, c_imm:$CRd, addr_offset_none:$addr, + coproc_option_imm:$option), + asm, "\t$cop, $CRd, $addr, $option"> { + bits<8> option; + bits<4> addr; + bits<4> cop; + bits<4> CRd; let Inst{24} = 0; // P = 0 let Inst{23} = 1; // U = 1 + let Inst{22} = Dbit; let Inst{21} = 0; // W = 0 - let Inst{22} = 1; // D = 1 let Inst{20} = load; + let Inst{19-16} = addr; + let Inst{15-12} = CRd; + let Inst{11-8} = cop; + let Inst{7-0} = option; + let DecoderMethod = "DecodeCopMemInstruction"; } } -defm LDC : LdStCop<{?,?,?,?}, 1, (ins pred:$p), "ldc", "${p}">; -defm LDC2 : LdStCop<0b1111, 1, (ins), "ldc2", "">; -defm STC : LdStCop<{?,?,?,?}, 0, (ins pred:$p), "stc", "${p}">; -defm STC2 : LdStCop<0b1111, 0, (ins), "stc2", "">; +defm LDC : LdStCop <1, 0, "ldc">; +defm LDCL : LdStCop <1, 1, "ldcl">; +defm STC : LdStCop <0, 0, "stc">; +defm STCL : LdStCop <0, 1, "stcl">; +defm LDC2 : LdSt2Cop<1, 0, "ldc2">; +defm LDC2L : LdSt2Cop<1, 1, "ldc2l">; +defm STC2 : LdSt2Cop<0, 0, "stc2">; +defm STC2L : LdSt2Cop<0, 1, "stc2l">; //===----------------------------------------------------------------------===// -// Move between coprocessor and ARM core register -- for disassembly only +// Move between coprocessor and ARM core register. // class MovRCopro; def MRC : MovRCopro<"mrc", 1 /* from coprocessor to ARM core register */, (outs GPR:$Rt), - (ins p_imm:$cop, i32imm:$opc1, c_imm:$CRn, c_imm:$CRm, - i32imm:$opc2), []>; + (ins p_imm:$cop, imm0_7:$opc1, c_imm:$CRn, c_imm:$CRm, + imm0_7:$opc2), []>; def : ARMPat<(int_arm_mrc imm:$cop, imm:$opc1, imm:$CRn, imm:$CRm, imm:$opc2), (MRC imm:$cop, imm:$opc1, imm:$CRn, imm:$CRm, imm:$opc2)>; @@ -3697,15 +4490,14 @@ def MCR2 : MovRCopro2<"mcr2", 0 /* from ARM core register to coprocessor */, imm:$CRm, imm:$opc2)]>; def MRC2 : MovRCopro2<"mrc2", 1 /* from coprocessor to ARM core register */, (outs GPR:$Rt), - (ins p_imm:$cop, i32imm:$opc1, c_imm:$CRn, c_imm:$CRm, - i32imm:$opc2), []>; + (ins p_imm:$cop, imm0_7:$opc1, c_imm:$CRn, c_imm:$CRm, + imm0_7:$opc2), []>; def : ARMV5TPat<(int_arm_mrc2 imm:$cop, imm:$opc1, imm:$CRn, imm:$CRm, imm:$opc2), (MRC2 imm:$cop, imm:$opc1, imm:$CRn, imm:$CRm, imm:$opc2)>; -class MovRRCopro pattern = [/* For disassembly only */]> +class MovRRCopro pattern = []> : ABI<0b1100, (outs), (ins p_imm:$cop, imm0_15:$opc1, GPR:$Rt, GPR:$Rt2, c_imm:$CRm), NoItinerary, opc, "\t$cop, $opc1, $Rt, $Rt2, $CRm", pattern> { @@ -3730,8 +4522,7 @@ def MCRR : MovRRCopro<"mcrr", 0 /* from ARM core register to coprocessor */, imm:$CRm)]>; def MRRC : MovRRCopro<"mrrc", 1 /* from coprocessor to ARM core register */>; -class MovRRCopro2 pattern = [/* For disassembly only */]> +class MovRRCopro2 pattern = []> : ABXI<0b1100, (outs), (ins p_imm:$cop, imm0_15:$opc1, GPR:$Rt, GPR:$Rt2, c_imm:$CRm), NoItinerary, !strconcat(opc, "\t$cop, $opc1, $Rt, $Rt2, $CRm"), pattern> { @@ -3758,20 +4549,22 @@ def MCRR2 : MovRRCopro2<"mcrr2", 0 /* from ARM core register to coprocessor */, def MRRC2 : MovRRCopro2<"mrrc2", 1 /* from coprocessor to ARM core register */>; //===----------------------------------------------------------------------===// -// Move between special register and ARM core register -- for disassembly only +// Move between special register and ARM core register // // Move to ARM core register from Special Register -def MRS : ABI<0b0001, (outs GPR:$Rd), (ins), NoItinerary, "mrs", "\t$Rd, cpsr", - [/* For disassembly only; pattern left blank */]> { +def MRS : ABI<0b0001, (outs GPR:$Rd), (ins), NoItinerary, + "mrs", "\t$Rd, apsr", []> { bits<4> Rd; let Inst{23-16} = 0b00001111; let Inst{15-12} = Rd; let Inst{7-4} = 0b0000; } -def MRSsys : ABI<0b0001, (outs GPR:$Rd), (ins), NoItinerary,"mrs","\t$Rd, spsr", - [/* For disassembly only; pattern left blank */]> { +def : InstAlias<"mrs${p} $Rd, cpsr", (MRS GPR:$Rd, pred:$p)>, Requires<[IsARM]>; + +def MRSsys : ABI<0b0001, (outs GPR:$Rd), (ins), NoItinerary, + "mrs", "\t$Rd, spsr", []> { bits<4> Rd; let Inst{23-16} = 0b01001111; let Inst{15-12} = Rd; @@ -3785,8 +4578,7 @@ def MRSsys : ABI<0b0001, (outs GPR:$Rd), (ins), NoItinerary,"mrs","\t$Rd, spsr", // operand contains the special register (R Bit) in bit 4 and bits 3-0 contains // the mask with the fields to be accessed in the special register. def MSR : ABI<0b0001, (outs), (ins msr_mask:$mask, GPR:$Rn), NoItinerary, - "msr", "\t$mask, $Rn", - [/* For disassembly only; pattern left blank */]> { + "msr", "\t$mask, $Rn", []> { bits<5> mask; bits<4> Rn; @@ -3800,8 +4592,7 @@ def MSR : ABI<0b0001, (outs), (ins msr_mask:$mask, GPR:$Rn), NoItinerary, } def MSRi : ABI<0b0011, (outs), (ins msr_mask:$mask, so_imm:$a), NoItinerary, - "msr", "\t$mask, $a", - [/* For disassembly only; pattern left blank */]> { + "msr", "\t$mask, $a", []> { bits<5> mask; bits<12> a; @@ -4030,6 +4821,47 @@ def : ARMV5TEPat<(add GPR:$acc, def : ARMPat<(ARMMemBarrierMCR GPR:$zero), (MCR 15, 0, GPR:$zero, 7, 10, 5)>, Requires<[IsARM, HasV6]>; +// SXT/UXT with no rotate +let AddedComplexity = 16 in { +def : ARMV6Pat<(and GPR:$Src, 0x000000FF), (UXTB GPR:$Src, 0)>; +def : ARMV6Pat<(and GPR:$Src, 0x0000FFFF), (UXTH GPR:$Src, 0)>; +def : ARMV6Pat<(and GPR:$Src, 0x00FF00FF), (UXTB16 GPR:$Src, 0)>; +def : ARMV6Pat<(add GPR:$Rn, (and GPR:$Rm, 0x00FF)), + (UXTAB GPR:$Rn, GPR:$Rm, 0)>; +def : ARMV6Pat<(add GPR:$Rn, (and GPR:$Rm, 0xFFFF)), + (UXTAH GPR:$Rn, GPR:$Rm, 0)>; +} + +def : ARMV6Pat<(sext_inreg GPR:$Src, i8), (SXTB GPR:$Src, 0)>; +def : ARMV6Pat<(sext_inreg GPR:$Src, i16), (SXTH GPR:$Src, 0)>; + +def : ARMV6Pat<(add GPR:$Rn, (sext_inreg GPRnopc:$Rm, i8)), + (SXTAB GPR:$Rn, GPRnopc:$Rm, 0)>; +def : ARMV6Pat<(add GPR:$Rn, (sext_inreg GPRnopc:$Rm, i16)), + (SXTAH GPR:$Rn, GPRnopc:$Rm, 0)>; + +// Atomic load/store patterns +def : ARMPat<(atomic_load_8 ldst_so_reg:$src), + (LDRBrs ldst_so_reg:$src)>; +def : ARMPat<(atomic_load_8 addrmode_imm12:$src), + (LDRBi12 addrmode_imm12:$src)>; +def : ARMPat<(atomic_load_16 addrmode3:$src), + (LDRH addrmode3:$src)>; +def : ARMPat<(atomic_load_32 ldst_so_reg:$src), + (LDRrs ldst_so_reg:$src)>; +def : ARMPat<(atomic_load_32 addrmode_imm12:$src), + (LDRi12 addrmode_imm12:$src)>; +def : ARMPat<(atomic_store_8 ldst_so_reg:$ptr, GPR:$val), + (STRBrs GPR:$val, ldst_so_reg:$ptr)>; +def : ARMPat<(atomic_store_8 addrmode_imm12:$ptr, GPR:$val), + (STRBi12 GPR:$val, addrmode_imm12:$ptr)>; +def : ARMPat<(atomic_store_16 addrmode3:$ptr, GPR:$val), + (STRH GPR:$val, addrmode3:$ptr)>; +def : ARMPat<(atomic_store_32 ldst_so_reg:$ptr, GPR:$val), + (STRrs GPR:$val, ldst_so_reg:$ptr)>; +def : ARMPat<(atomic_store_32 addrmode_imm12:$ptr, GPR:$val), + (STRi12 GPR:$val, addrmode_imm12:$ptr)>; + //===----------------------------------------------------------------------===// // Thumb Support @@ -4070,7 +4902,103 @@ def : MnemonicAlias<"swi", "svc">; // Load / Store Multiple def : MnemonicAlias<"ldmfd", "ldm">; def : MnemonicAlias<"ldmia", "ldm">; +def : MnemonicAlias<"ldmea", "ldmdb">; def : MnemonicAlias<"stmfd", "stmdb">; def : MnemonicAlias<"stmia", "stm">; def : MnemonicAlias<"stmea", "stm">; +// PKHBT/PKHTB with default shift amount. PKHTB is equivalent to PKHBT when the +// shift amount is zero (i.e., unspecified). +def : InstAlias<"pkhbt${p} $Rd, $Rn, $Rm", + (PKHBT GPRnopc:$Rd, GPRnopc:$Rn, GPRnopc:$Rm, 0, pred:$p)>, + Requires<[IsARM, HasV6]>; +def : InstAlias<"pkhtb${p} $Rd, $Rn, $Rm", + (PKHBT GPRnopc:$Rd, GPRnopc:$Rn, GPRnopc:$Rm, 0, pred:$p)>, + Requires<[IsARM, HasV6]>; + +// PUSH/POP aliases for STM/LDM +def : ARMInstAlias<"push${p} $regs", (STMDB_UPD SP, pred:$p, reglist:$regs)>; +def : ARMInstAlias<"pop${p} $regs", (LDMIA_UPD SP, pred:$p, reglist:$regs)>; + +// SSAT/USAT optional shift operand. +def : ARMInstAlias<"ssat${p} $Rd, $sat_imm, $Rn", + (SSAT GPRnopc:$Rd, imm1_32:$sat_imm, GPRnopc:$Rn, 0, pred:$p)>; +def : ARMInstAlias<"usat${p} $Rd, $sat_imm, $Rn", + (USAT GPRnopc:$Rd, imm0_31:$sat_imm, GPRnopc:$Rn, 0, pred:$p)>; + + +// Extend instruction optional rotate operand. +def : ARMInstAlias<"sxtab${p} $Rd, $Rn, $Rm", + (SXTAB GPRnopc:$Rd, GPR:$Rn, GPRnopc:$Rm, 0, pred:$p)>; +def : ARMInstAlias<"sxtah${p} $Rd, $Rn, $Rm", + (SXTAH GPRnopc:$Rd, GPR:$Rn, GPRnopc:$Rm, 0, pred:$p)>; +def : ARMInstAlias<"sxtab16${p} $Rd, $Rn, $Rm", + (SXTAB16 GPRnopc:$Rd, GPR:$Rn, GPRnopc:$Rm, 0, pred:$p)>; +def : ARMInstAlias<"sxtb${p} $Rd, $Rm", + (SXTB GPRnopc:$Rd, GPRnopc:$Rm, 0, pred:$p)>; +def : ARMInstAlias<"sxtb16${p} $Rd, $Rm", + (SXTB16 GPRnopc:$Rd, GPRnopc:$Rm, 0, pred:$p)>; +def : ARMInstAlias<"sxth${p} $Rd, $Rm", + (SXTH GPRnopc:$Rd, GPRnopc:$Rm, 0, pred:$p)>; + +def : ARMInstAlias<"uxtab${p} $Rd, $Rn, $Rm", + (UXTAB GPRnopc:$Rd, GPR:$Rn, GPRnopc:$Rm, 0, pred:$p)>; +def : ARMInstAlias<"uxtah${p} $Rd, $Rn, $Rm", + (UXTAH GPRnopc:$Rd, GPR:$Rn, GPRnopc:$Rm, 0, pred:$p)>; +def : ARMInstAlias<"uxtab16${p} $Rd, $Rn, $Rm", + (UXTAB16 GPRnopc:$Rd, GPR:$Rn, GPRnopc:$Rm, 0, pred:$p)>; +def : ARMInstAlias<"uxtb${p} $Rd, $Rm", + (UXTB GPRnopc:$Rd, GPRnopc:$Rm, 0, pred:$p)>; +def : ARMInstAlias<"uxtb16${p} $Rd, $Rm", + (UXTB16 GPRnopc:$Rd, GPRnopc:$Rm, 0, pred:$p)>; +def : ARMInstAlias<"uxth${p} $Rd, $Rm", + (UXTH GPRnopc:$Rd, GPRnopc:$Rm, 0, pred:$p)>; + + +// RFE aliases +def : MnemonicAlias<"rfefa", "rfeda">; +def : MnemonicAlias<"rfeea", "rfedb">; +def : MnemonicAlias<"rfefd", "rfeia">; +def : MnemonicAlias<"rfeed", "rfeib">; +def : MnemonicAlias<"rfe", "rfeia">; + +// SRS aliases +def : MnemonicAlias<"srsfa", "srsda">; +def : MnemonicAlias<"srsea", "srsdb">; +def : MnemonicAlias<"srsfd", "srsia">; +def : MnemonicAlias<"srsed", "srsib">; +def : MnemonicAlias<"srs", "srsia">; + +// QSAX == QSUBADDX +def : MnemonicAlias<"qsubaddx", "qsax">; +// SASX == SADDSUBX +def : MnemonicAlias<"saddsubx", "sasx">; +// SHASX == SHADDSUBX +def : MnemonicAlias<"shaddsubx", "shasx">; +// SHSAX == SHSUBADDX +def : MnemonicAlias<"shsubaddx", "shsax">; +// SSAX == SSUBADDX +def : MnemonicAlias<"ssubaddx", "ssax">; +// UASX == UADDSUBX +def : MnemonicAlias<"uaddsubx", "uasx">; +// UHASX == UHADDSUBX +def : MnemonicAlias<"uhaddsubx", "uhasx">; +// UHSAX == UHSUBADDX +def : MnemonicAlias<"uhsubaddx", "uhsax">; +// UQASX == UQADDSUBX +def : MnemonicAlias<"uqaddsubx", "uqasx">; +// UQSAX == UQSUBADDX +def : MnemonicAlias<"uqsubaddx", "uqsax">; +// USAX == USUBADDX +def : MnemonicAlias<"usubaddx", "usax">; + +// LDRSBT/LDRHT/LDRSHT post-index offset if optional. +// Note that the write-back output register is a dummy operand for MC (it's +// only meaningful for codegen), so we just pass zero here. +// FIXME: tblgen not cooperating with argument conversions. +//def : InstAlias<"ldrsbt${p} $Rt, $addr", +// (LDRSBTi GPR:$Rt, GPR:$Rt, addr_offset_none:$addr, 0,pred:$p)>; +//def : InstAlias<"ldrht${p} $Rt, $addr", +// (LDRHTi GPR:$Rt, GPR:$Rt, addr_offset_none:$addr, 0, pred:$p)>; +//def : InstAlias<"ldrsht${p} $Rt, $addr", +// (LDRSHTi GPR:$Rt, GPR:$Rt, addr_offset_none:$addr, 0, pred:$p)>; diff --git a/contrib/llvm/lib/Target/ARM/ARMInstrNEON.td b/contrib/llvm/lib/Target/ARM/ARMInstrNEON.td index 0df62f456..7aad18695 100644 --- a/contrib/llvm/lib/Target/ARM/ARMInstrNEON.td +++ b/contrib/llvm/lib/Target/ARM/ARMInstrNEON.td @@ -11,6 +11,35 @@ // //===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// NEON-specific Operands. +//===----------------------------------------------------------------------===// +def VectorIndex8Operand : AsmOperandClass { let Name = "VectorIndex8"; } +def VectorIndex16Operand : AsmOperandClass { let Name = "VectorIndex16"; } +def VectorIndex32Operand : AsmOperandClass { let Name = "VectorIndex32"; } +def VectorIndex8 : Operand, ImmLeaf { + let ParserMatchClass = VectorIndex8Operand; + let PrintMethod = "printVectorIndex"; + let MIOperandInfo = (ops i32imm); +} +def VectorIndex16 : Operand, ImmLeaf { + let ParserMatchClass = VectorIndex16Operand; + let PrintMethod = "printVectorIndex"; + let MIOperandInfo = (ops i32imm); +} +def VectorIndex32 : Operand, ImmLeaf { + let ParserMatchClass = VectorIndex32Operand; + let PrintMethod = "printVectorIndex"; + let MIOperandInfo = (ops i32imm); +} + //===----------------------------------------------------------------------===// // NEON-specific DAG Nodes. //===----------------------------------------------------------------------===// @@ -175,7 +204,8 @@ class VLDQQWBPseudo (ins addrmode6:$addr, am6offset:$offset), itin, "$addr.addr = $wb">; class VLDQQQQPseudo - : PseudoNLdSt<(outs QQQQPR:$dst), (ins addrmode6:$addr, QQQQPR:$src),itin,"">; + : PseudoNLdSt<(outs QQQQPR:$dst), (ins addrmode6:$addr, QQQQPR:$src),itin, + "$src = $dst">; class VLDQQQQWBPseudo : PseudoNLdSt<(outs QQQQPR:$dst, GPR:$wb), (ins addrmode6:$addr, am6offset:$offset, QQQQPR:$src), itin, @@ -190,6 +220,7 @@ class VLD1D op7_4, string Dt> "vld1", Dt, "\\{$Vd\\}, $Rn", "", []> { let Rm = 0b1111; let Inst{4} = Rn{4}; + let DecoderMethod = "DecodeVLDInstruction"; } class VLD1Q op7_4, string Dt> : NLdSt<0,0b10,0b1010,op7_4, (outs DPR:$Vd, DPR:$dst2), @@ -197,6 +228,7 @@ class VLD1Q op7_4, string Dt> "vld1", Dt, "\\{$Vd, $dst2\\}, $Rn", "", []> { let Rm = 0b1111; let Inst{5-4} = Rn{5-4}; + let DecoderMethod = "DecodeVLDInstruction"; } def VLD1d8 : VLD1D<{0,0,0,?}, "8">; @@ -221,6 +253,7 @@ class VLD1DWB op7_4, string Dt> "vld1", Dt, "\\{$Vd\\}, $Rn$Rm", "$Rn.addr = $wb", []> { let Inst{4} = Rn{4}; + let DecoderMethod = "DecodeVLDInstruction"; } class VLD1QWB op7_4, string Dt> : NLdSt<0,0b10,0b1010,op7_4, (outs DPR:$Vd, DPR:$dst2, GPR:$wb), @@ -228,6 +261,7 @@ class VLD1QWB op7_4, string Dt> "vld1", Dt, "\\{$Vd, $dst2\\}, $Rn$Rm", "$Rn.addr = $wb", []> { let Inst{5-4} = Rn{5-4}; + let DecoderMethod = "DecodeVLDInstruction"; } def VLD1d8_UPD : VLD1DWB<{0,0,0,?}, "8">; @@ -252,12 +286,14 @@ class VLD1D3 op7_4, string Dt> "\\{$Vd, $dst2, $dst3\\}, $Rn", "", []> { let Rm = 0b1111; let Inst{4} = Rn{4}; + let DecoderMethod = "DecodeVLDInstruction"; } class VLD1D3WB op7_4, string Dt> : NLdSt<0,0b10,0b0110,op7_4, (outs DPR:$Vd, DPR:$dst2, DPR:$dst3, GPR:$wb), (ins addrmode6:$Rn, am6offset:$Rm), IIC_VLD1x3u, "vld1", Dt, "\\{$Vd, $dst2, $dst3\\}, $Rn$Rm", "$Rn.addr = $wb", []> { let Inst{4} = Rn{4}; + let DecoderMethod = "DecodeVLDInstruction"; } def VLD1d8T : VLD1D3<{0,0,0,?}, "8">; @@ -280,6 +316,7 @@ class VLD1D4 op7_4, string Dt> "\\{$Vd, $dst2, $dst3, $dst4\\}, $Rn", "", []> { let Rm = 0b1111; let Inst{5-4} = Rn{5-4}; + let DecoderMethod = "DecodeVLDInstruction"; } class VLD1D4WB op7_4, string Dt> : NLdSt<0,0b10,0b0010,op7_4, @@ -288,6 +325,7 @@ class VLD1D4WB op7_4, string Dt> "\\{$Vd, $dst2, $dst3, $dst4\\}, $Rn$Rm", "$Rn.addr = $wb", []> { let Inst{5-4} = Rn{5-4}; + let DecoderMethod = "DecodeVLDInstruction"; } def VLD1d8Q : VLD1D4<{0,0,?,?}, "8">; @@ -310,6 +348,7 @@ class VLD2D op11_8, bits<4> op7_4, string Dt> "vld2", Dt, "\\{$Vd, $dst2\\}, $Rn", "", []> { let Rm = 0b1111; let Inst{5-4} = Rn{5-4}; + let DecoderMethod = "DecodeVLDInstruction"; } class VLD2Q op7_4, string Dt> : NLdSt<0, 0b10, 0b0011, op7_4, @@ -318,6 +357,7 @@ class VLD2Q op7_4, string Dt> "vld2", Dt, "\\{$Vd, $dst2, $dst3, $dst4\\}, $Rn", "", []> { let Rm = 0b1111; let Inst{5-4} = Rn{5-4}; + let DecoderMethod = "DecodeVLDInstruction"; } def VLD2d8 : VLD2D<0b1000, {0,0,?,?}, "8">; @@ -343,6 +383,7 @@ class VLD2DWB op11_8, bits<4> op7_4, string Dt> "vld2", Dt, "\\{$Vd, $dst2\\}, $Rn$Rm", "$Rn.addr = $wb", []> { let Inst{5-4} = Rn{5-4}; + let DecoderMethod = "DecodeVLDInstruction"; } class VLD2QWB op7_4, string Dt> : NLdSt<0, 0b10, 0b0011, op7_4, @@ -351,6 +392,7 @@ class VLD2QWB op7_4, string Dt> "vld2", Dt, "\\{$Vd, $dst2, $dst3, $dst4\\}, $Rn$Rm", "$Rn.addr = $wb", []> { let Inst{5-4} = Rn{5-4}; + let DecoderMethod = "DecodeVLDInstruction"; } def VLD2d8_UPD : VLD2DWB<0b1000, {0,0,?,?}, "8">; @@ -384,6 +426,7 @@ class VLD3D op11_8, bits<4> op7_4, string Dt> "vld3", Dt, "\\{$Vd, $dst2, $dst3\\}, $Rn", "", []> { let Rm = 0b1111; let Inst{4} = Rn{4}; + let DecoderMethod = "DecodeVLDInstruction"; } def VLD3d8 : VLD3D<0b0100, {0,0,0,?}, "8">; @@ -402,6 +445,7 @@ class VLD3DWB op11_8, bits<4> op7_4, string Dt> "vld3", Dt, "\\{$Vd, $dst2, $dst3\\}, $Rn$Rm", "$Rn.addr = $wb", []> { let Inst{4} = Rn{4}; + let DecoderMethod = "DecodeVLDInstruction"; } def VLD3d8_UPD : VLD3DWB<0b0100, {0,0,0,?}, "8">; @@ -441,6 +485,7 @@ class VLD4D op11_8, bits<4> op7_4, string Dt> "vld4", Dt, "\\{$Vd, $dst2, $dst3, $dst4\\}, $Rn", "", []> { let Rm = 0b1111; let Inst{5-4} = Rn{5-4}; + let DecoderMethod = "DecodeVLDInstruction"; } def VLD4d8 : VLD4D<0b0000, {0,0,?,?}, "8">; @@ -459,6 +504,7 @@ class VLD4DWB op11_8, bits<4> op7_4, string Dt> "vld4", Dt, "\\{$Vd, $dst2, $dst3, $dst4\\}, $Rn$Rm", "$Rn.addr = $wb", []> { let Inst{5-4} = Rn{5-4}; + let DecoderMethod = "DecodeVLDInstruction"; } def VLD4d8_UPD : VLD4DWB<0b0000, {0,0,?,?}, "8">; @@ -530,6 +576,7 @@ class VLD1LN op11_8, bits<4> op7_4, string Dt, ValueType Ty, (i32 (LoadOp addrmode6:$Rn)), imm:$lane))]> { let Rm = 0b1111; + let DecoderMethod = "DecodeVLD1LN"; } class VLD1LN32 op11_8, bits<4> op7_4, string Dt, ValueType Ty, PatFrag LoadOp> @@ -541,6 +588,7 @@ class VLD1LN32 op11_8, bits<4> op7_4, string Dt, ValueType Ty, (i32 (LoadOp addrmode6oneL32:$Rn)), imm:$lane))]> { let Rm = 0b1111; + let DecoderMethod = "DecodeVLD1LN"; } class VLD1QLNPseudo : VLDQLNPseudo { let Pattern = [(set QPR:$dst, (vector_insert (Ty QPR:$src), @@ -580,7 +628,9 @@ class VLD1LNWB op11_8, bits<4> op7_4, string Dt> (ins addrmode6:$Rn, am6offset:$Rm, DPR:$src, nohash_imm:$lane), IIC_VLD1lnu, "vld1", Dt, "\\{$Vd[$lane]\\}, $Rn$Rm", - "$src = $Vd, $Rn.addr = $wb", []>; + "$src = $Vd, $Rn.addr = $wb", []> { + let DecoderMethod = "DecodeVLD1LN"; +} def VLD1LNd8_UPD : VLD1LNWB<0b0000, {?,?,?,0}, "8"> { let Inst{7-5} = lane{2-0}; @@ -607,6 +657,7 @@ class VLD2LN op11_8, bits<4> op7_4, string Dt> "$src1 = $Vd, $src2 = $dst2", []> { let Rm = 0b1111; let Inst{4} = Rn{4}; + let DecoderMethod = "DecodeVLD2LN"; } def VLD2LNd8 : VLD2LN<0b0001, {?,?,?,?}, "8"> { @@ -642,6 +693,7 @@ class VLD2LNWB op11_8, bits<4> op7_4, string Dt> "\\{$Vd[$lane], $dst2[$lane]\\}, $Rn$Rm", "$src1 = $Vd, $src2 = $dst2, $Rn.addr = $wb", []> { let Inst{4} = Rn{4}; + let DecoderMethod = "DecodeVLD2LN"; } def VLD2LNd8_UPD : VLD2LNWB<0b0001, {?,?,?,?}, "8"> { @@ -676,6 +728,7 @@ class VLD3LN op11_8, bits<4> op7_4, string Dt> "\\{$Vd[$lane], $dst2[$lane], $dst3[$lane]\\}, $Rn", "$src1 = $Vd, $src2 = $dst2, $src3 = $dst3", []> { let Rm = 0b1111; + let DecoderMethod = "DecodeVLD3LN"; } def VLD3LNd8 : VLD3LN<0b0010, {?,?,?,0}, "8"> { @@ -712,7 +765,9 @@ class VLD3LNWB op11_8, bits<4> op7_4, string Dt> IIC_VLD3lnu, "vld3", Dt, "\\{$Vd[$lane], $dst2[$lane], $dst3[$lane]\\}, $Rn$Rm", "$src1 = $Vd, $src2 = $dst2, $src3 = $dst3, $Rn.addr = $wb", - []>; + []> { + let DecoderMethod = "DecodeVLD3LN"; +} def VLD3LNd8_UPD : VLD3LNWB<0b0010, {?,?,?,0}, "8"> { let Inst{7-5} = lane{2-0}; @@ -748,6 +803,7 @@ class VLD4LN op11_8, bits<4> op7_4, string Dt> "$src1 = $Vd, $src2 = $dst2, $src3 = $dst3, $src4 = $dst4", []> { let Rm = 0b1111; let Inst{4} = Rn{4}; + let DecoderMethod = "DecodeVLD4LN"; } def VLD4LNd8 : VLD4LN<0b0011, {?,?,?,?}, "8"> { @@ -788,6 +844,7 @@ class VLD4LNWB op11_8, bits<4> op7_4, string Dt> "$src1 = $Vd, $src2 = $dst2, $src3 = $dst3, $src4 = $dst4, $Rn.addr = $wb", []> { let Inst{4} = Rn{4}; + let DecoderMethod = "DecodeVLD4LN" ; } def VLD4LNd8_UPD : VLD4LNWB<0b0011, {?,?,?,?}, "8"> { @@ -825,6 +882,7 @@ class VLD1DUP op7_4, string Dt, ValueType Ty, PatFrag LoadOp> [(set DPR:$Vd, (Ty (NEONvdup (i32 (LoadOp addrmode6dup:$Rn)))))]> { let Rm = 0b1111; let Inst{4} = Rn{4}; + let DecoderMethod = "DecodeVLD1DupInstruction"; } class VLD1QDUPPseudo : VLDQPseudo { let Pattern = [(set QPR:$dst, @@ -852,6 +910,7 @@ class VLD1QDUP op7_4, string Dt> "vld1", Dt, "\\{$Vd[], $dst2[]\\}, $Rn", "", []> { let Rm = 0b1111; let Inst{4} = Rn{4}; + let DecoderMethod = "DecodeVLD1DupInstruction"; } def VLD1DUPq8 : VLD1QDUP<{0,0,1,0}, "8">; @@ -864,12 +923,14 @@ class VLD1DUPWB op7_4, string Dt> (ins addrmode6dup:$Rn, am6offset:$Rm), IIC_VLD1dupu, "vld1", Dt, "\\{$Vd[]\\}, $Rn$Rm", "$Rn.addr = $wb", []> { let Inst{4} = Rn{4}; + let DecoderMethod = "DecodeVLD1DupInstruction"; } class VLD1QDUPWB op7_4, string Dt> : NLdSt<1, 0b10, 0b1100, op7_4, (outs DPR:$Vd, DPR:$dst2, GPR:$wb), (ins addrmode6dup:$Rn, am6offset:$Rm), IIC_VLD1dupu, "vld1", Dt, "\\{$Vd[], $dst2[]\\}, $Rn$Rm", "$Rn.addr = $wb", []> { let Inst{4} = Rn{4}; + let DecoderMethod = "DecodeVLD1DupInstruction"; } def VLD1DUPd8_UPD : VLD1DUPWB<{0,0,0,0}, "8">; @@ -891,6 +952,7 @@ class VLD2DUP op7_4, string Dt> "vld2", Dt, "\\{$Vd[], $dst2[]\\}, $Rn", "", []> { let Rm = 0b1111; let Inst{4} = Rn{4}; + let DecoderMethod = "DecodeVLD2DupInstruction"; } def VLD2DUPd8 : VLD2DUP<{0,0,0,?}, "8">; @@ -912,6 +974,7 @@ class VLD2DUPWB op7_4, string Dt> (ins addrmode6dup:$Rn, am6offset:$Rm), IIC_VLD2dupu, "vld2", Dt, "\\{$Vd[], $dst2[]\\}, $Rn$Rm", "$Rn.addr = $wb", []> { let Inst{4} = Rn{4}; + let DecoderMethod = "DecodeVLD2DupInstruction"; } def VLD2DUPd8_UPD : VLD2DUPWB<{0,0,0,0}, "8">; @@ -932,7 +995,8 @@ class VLD3DUP op7_4, string Dt> (ins addrmode6dup:$Rn), IIC_VLD3dup, "vld3", Dt, "\\{$Vd[], $dst2[], $dst3[]\\}, $Rn", "", []> { let Rm = 0b1111; - let Inst{4} = Rn{4}; + let Inst{4} = 0; + let DecoderMethod = "DecodeVLD3DupInstruction"; } def VLD3DUPd8 : VLD3DUP<{0,0,0,?}, "8">; @@ -954,7 +1018,8 @@ class VLD3DUPWB op7_4, string Dt> (ins addrmode6dup:$Rn, am6offset:$Rm), IIC_VLD3dupu, "vld3", Dt, "\\{$Vd[], $dst2[], $dst3[]\\}, $Rn$Rm", "$Rn.addr = $wb", []> { - let Inst{4} = Rn{4}; + let Inst{4} = 0; + let DecoderMethod = "DecodeVLD3DupInstruction"; } def VLD3DUPd8_UPD : VLD3DUPWB<{0,0,0,0}, "8">; @@ -977,6 +1042,7 @@ class VLD4DUP op7_4, string Dt> "vld4", Dt, "\\{$Vd[], $dst2[], $dst3[], $dst4[]\\}, $Rn", "", []> { let Rm = 0b1111; let Inst{4} = Rn{4}; + let DecoderMethod = "DecodeVLD4DupInstruction"; } def VLD4DUPd8 : VLD4DUP<{0,0,0,?}, "8">; @@ -1000,6 +1066,7 @@ class VLD4DUPWB op7_4, string Dt> "vld4", Dt, "\\{$Vd[], $dst2[], $dst3[], $dst4[]\\}, $Rn$Rm", "$Rn.addr = $wb", []> { let Inst{4} = Rn{4}; + let DecoderMethod = "DecodeVLD4DupInstruction"; } def VLD4DUPd8_UPD : VLD4DUPWB<{0,0,0,0}, "8">; @@ -1045,6 +1112,7 @@ class VST1D op7_4, string Dt> IIC_VST1, "vst1", Dt, "\\{$Vd\\}, $Rn", "", []> { let Rm = 0b1111; let Inst{4} = Rn{4}; + let DecoderMethod = "DecodeVSTInstruction"; } class VST1Q op7_4, string Dt> : NLdSt<0,0b00,0b1010,op7_4, (outs), @@ -1052,6 +1120,7 @@ class VST1Q op7_4, string Dt> "vst1", Dt, "\\{$Vd, $src2\\}, $Rn", "", []> { let Rm = 0b1111; let Inst{5-4} = Rn{5-4}; + let DecoderMethod = "DecodeVSTInstruction"; } def VST1d8 : VST1D<{0,0,0,?}, "8">; @@ -1075,6 +1144,7 @@ class VST1DWB op7_4, string Dt> (ins addrmode6:$Rn, am6offset:$Rm, DPR:$Vd), IIC_VST1u, "vst1", Dt, "\\{$Vd\\}, $Rn$Rm", "$Rn.addr = $wb", []> { let Inst{4} = Rn{4}; + let DecoderMethod = "DecodeVSTInstruction"; } class VST1QWB op7_4, string Dt> : NLdSt<0, 0b00, 0b1010, op7_4, (outs GPR:$wb), @@ -1082,6 +1152,7 @@ class VST1QWB op7_4, string Dt> IIC_VST1x2u, "vst1", Dt, "\\{$Vd, $src2\\}, $Rn$Rm", "$Rn.addr = $wb", []> { let Inst{5-4} = Rn{5-4}; + let DecoderMethod = "DecodeVSTInstruction"; } def VST1d8_UPD : VST1DWB<{0,0,0,?}, "8">; @@ -1106,6 +1177,7 @@ class VST1D3 op7_4, string Dt> IIC_VST1x3, "vst1", Dt, "\\{$Vd, $src2, $src3\\}, $Rn", "", []> { let Rm = 0b1111; let Inst{4} = Rn{4}; + let DecoderMethod = "DecodeVSTInstruction"; } class VST1D3WB op7_4, string Dt> : NLdSt<0, 0b00, 0b0110, op7_4, (outs GPR:$wb), @@ -1114,6 +1186,7 @@ class VST1D3WB op7_4, string Dt> IIC_VST1x3u, "vst1", Dt, "\\{$Vd, $src2, $src3\\}, $Rn$Rm", "$Rn.addr = $wb", []> { let Inst{4} = Rn{4}; + let DecoderMethod = "DecodeVSTInstruction"; } def VST1d8T : VST1D3<{0,0,0,?}, "8">; @@ -1137,6 +1210,7 @@ class VST1D4 op7_4, string Dt> []> { let Rm = 0b1111; let Inst{5-4} = Rn{5-4}; + let DecoderMethod = "DecodeVSTInstruction"; } class VST1D4WB op7_4, string Dt> : NLdSt<0, 0b00, 0b0010, op7_4, (outs GPR:$wb), @@ -1145,6 +1219,7 @@ class VST1D4WB op7_4, string Dt> "vst1", Dt, "\\{$Vd, $src2, $src3, $src4\\}, $Rn$Rm", "$Rn.addr = $wb", []> { let Inst{5-4} = Rn{5-4}; + let DecoderMethod = "DecodeVSTInstruction"; } def VST1d8Q : VST1D4<{0,0,?,?}, "8">; @@ -1167,6 +1242,7 @@ class VST2D op11_8, bits<4> op7_4, string Dt> IIC_VST2, "vst2", Dt, "\\{$Vd, $src2\\}, $Rn", "", []> { let Rm = 0b1111; let Inst{5-4} = Rn{5-4}; + let DecoderMethod = "DecodeVSTInstruction"; } class VST2Q op7_4, string Dt> : NLdSt<0, 0b00, 0b0011, op7_4, (outs), @@ -1175,6 +1251,7 @@ class VST2Q op7_4, string Dt> "", []> { let Rm = 0b1111; let Inst{5-4} = Rn{5-4}; + let DecoderMethod = "DecodeVSTInstruction"; } def VST2d8 : VST2D<0b1000, {0,0,?,?}, "8">; @@ -1200,6 +1277,7 @@ class VST2DWB op11_8, bits<4> op7_4, string Dt> IIC_VST2u, "vst2", Dt, "\\{$Vd, $src2\\}, $Rn$Rm", "$Rn.addr = $wb", []> { let Inst{5-4} = Rn{5-4}; + let DecoderMethod = "DecodeVSTInstruction"; } class VST2QWB op7_4, string Dt> : NLdSt<0, 0b00, 0b0011, op7_4, (outs GPR:$wb), @@ -1208,6 +1286,7 @@ class VST2QWB op7_4, string Dt> "vst2", Dt, "\\{$Vd, $src2, $src3, $src4\\}, $Rn$Rm", "$Rn.addr = $wb", []> { let Inst{5-4} = Rn{5-4}; + let DecoderMethod = "DecodeVSTInstruction"; } def VST2d8_UPD : VST2DWB<0b1000, {0,0,?,?}, "8">; @@ -1241,6 +1320,7 @@ class VST3D op11_8, bits<4> op7_4, string Dt> "vst3", Dt, "\\{$Vd, $src2, $src3\\}, $Rn", "", []> { let Rm = 0b1111; let Inst{4} = Rn{4}; + let DecoderMethod = "DecodeVSTInstruction"; } def VST3d8 : VST3D<0b0100, {0,0,0,?}, "8">; @@ -1259,6 +1339,7 @@ class VST3DWB op11_8, bits<4> op7_4, string Dt> "vst3", Dt, "\\{$Vd, $src2, $src3\\}, $Rn$Rm", "$Rn.addr = $wb", []> { let Inst{4} = Rn{4}; + let DecoderMethod = "DecodeVSTInstruction"; } def VST3d8_UPD : VST3DWB<0b0100, {0,0,0,?}, "8">; @@ -1298,6 +1379,7 @@ class VST4D op11_8, bits<4> op7_4, string Dt> "", []> { let Rm = 0b1111; let Inst{5-4} = Rn{5-4}; + let DecoderMethod = "DecodeVSTInstruction"; } def VST4d8 : VST4D<0b0000, {0,0,?,?}, "8">; @@ -1316,6 +1398,7 @@ class VST4DWB op11_8, bits<4> op7_4, string Dt> "vst4", Dt, "\\{$Vd, $src2, $src3, $src4\\}, $Rn$Rm", "$Rn.addr = $wb", []> { let Inst{5-4} = Rn{5-4}; + let DecoderMethod = "DecodeVSTInstruction"; } def VST4d8_UPD : VST4DWB<0b0000, {0,0,?,?}, "8">; @@ -1381,6 +1464,7 @@ class VST1LN op11_8, bits<4> op7_4, string Dt, ValueType Ty, IIC_VST1ln, "vst1", Dt, "\\{$Vd[$lane]\\}, $Rn", "", [(StoreOp (ExtractOp (Ty DPR:$Vd), imm:$lane), addrmode6:$Rn)]> { let Rm = 0b1111; + let DecoderMethod = "DecodeVST1LN"; } class VST1LN32 op11_8, bits<4> op7_4, string Dt, ValueType Ty, PatFrag StoreOp, SDNode ExtractOp> @@ -1389,6 +1473,7 @@ class VST1LN32 op11_8, bits<4> op7_4, string Dt, ValueType Ty, IIC_VST1ln, "vst1", Dt, "\\{$Vd[$lane]\\}, $Rn", "", [(StoreOp (ExtractOp (Ty DPR:$Vd), imm:$lane), addrmode6oneL32:$Rn)]>{ let Rm = 0b1111; + let DecoderMethod = "DecodeVST1LN"; } class VST1QLNPseudo : VSTQLNPseudo { @@ -1429,7 +1514,9 @@ class VST1LNWB op11_8, bits<4> op7_4, string Dt, ValueType Ty, "\\{$Vd[$lane]\\}, $Rn$Rm", "$Rn.addr = $wb", [(set GPR:$wb, (StoreOp (ExtractOp (Ty DPR:$Vd), imm:$lane), - addrmode6:$Rn, am6offset:$Rm))]>; + addrmode6:$Rn, am6offset:$Rm))]> { + let DecoderMethod = "DecodeVST1LN"; +} class VST1QLNWBPseudo : VSTQLNWBPseudo { let Pattern = [(set GPR:$wb, (StoreOp (ExtractOp (Ty QPR:$src), imm:$lane), @@ -1465,6 +1552,7 @@ class VST2LN op11_8, bits<4> op7_4, string Dt> "", []> { let Rm = 0b1111; let Inst{4} = Rn{4}; + let DecoderMethod = "DecodeVST2LN"; } def VST2LNd8 : VST2LN<0b0001, {?,?,?,?}, "8"> { @@ -1502,6 +1590,7 @@ class VST2LNWB op11_8, bits<4> op7_4, string Dt> "\\{$src1[$lane], $src2[$lane]\\}, $addr$offset", "$addr.addr = $wb", []> { let Inst{4} = Rn{4}; + let DecoderMethod = "DecodeVST2LN"; } def VST2LNd8_UPD : VST2LNWB<0b0001, {?,?,?,?}, "8"> { @@ -1535,6 +1624,7 @@ class VST3LN op11_8, bits<4> op7_4, string Dt> nohash_imm:$lane), IIC_VST3ln, "vst3", Dt, "\\{$Vd[$lane], $src2[$lane], $src3[$lane]\\}, $Rn", "", []> { let Rm = 0b1111; + let DecoderMethod = "DecodeVST3LN"; } def VST3LNd8 : VST3LN<0b0010, {?,?,?,0}, "8"> { @@ -1569,7 +1659,9 @@ class VST3LNWB op11_8, bits<4> op7_4, string Dt> DPR:$Vd, DPR:$src2, DPR:$src3, nohash_imm:$lane), IIC_VST3lnu, "vst3", Dt, "\\{$Vd[$lane], $src2[$lane], $src3[$lane]\\}, $Rn$Rm", - "$Rn.addr = $wb", []>; + "$Rn.addr = $wb", []> { + let DecoderMethod = "DecodeVST3LN"; +} def VST3LNd8_UPD : VST3LNWB<0b0010, {?,?,?,0}, "8"> { let Inst{7-5} = lane{2-0}; @@ -1604,6 +1696,7 @@ class VST4LN op11_8, bits<4> op7_4, string Dt> "", []> { let Rm = 0b1111; let Inst{4} = Rn{4}; + let DecoderMethod = "DecodeVST4LN"; } def VST4LNd8 : VST4LN<0b0011, {?,?,?,?}, "8"> { @@ -1642,6 +1735,7 @@ class VST4LNWB op11_8, bits<4> op7_4, string Dt> "\\{$Vd[$lane], $src2[$lane], $src3[$lane], $src4[$lane]\\}, $Rn$Rm", "$Rn.addr = $wb", []> { let Inst{4} = Rn{4}; + let DecoderMethod = "DecodeVST4LN"; } def VST4LNd8_UPD : VST4LNWB<0b0011, {?,?,?,?}, "8"> { @@ -4039,6 +4133,7 @@ class N2VLShMax op21_16, bits<4> op11_8, bit op7, : N2VLSh { let Inst{21-16} = op21_16; + let DecoderMethod = "DecodeVSHLMaxInstruction"; } def VSHLLi8 : N2VLShMax<1, 1, 0b110010, 0b0011, 0, 0, 0, "vshll", "i8", v8i16, v8i8, NEONvshlli>; @@ -4219,16 +4314,6 @@ def : InstAlias<"vmov${p} $Vd, $Vm", def : InstAlias<"vmov${p} $Vd, $Vm", (VORRq QPR:$Vd, QPR:$Vm, QPR:$Vm, pred:$p)>; -let neverHasSideEffects = 1 in { -// Pseudo vector move instructions for QQ and QQQQ registers. This should -// be expanded after register allocation is completed. -def VMOVQQ : PseudoInst<(outs QQPR:$dst), (ins QQPR:$src), - NoItinerary, []>; - -def VMOVQQQQ : PseudoInst<(outs QQQQPR:$dst), (ins QQQQPR:$src), - NoItinerary, []>; -} // neverHasSideEffects - // VMOV : Vector Move (Immediate) let isReMaterializable = 1 in { @@ -4462,36 +4547,42 @@ def : Pat<(v4f32 (NEONvdup (f32 (bitconvert GPR:$R)))), (VDUP32q GPR:$R)>; // VDUP : Vector Duplicate Lane (from scalar to all elements) class VDUPLND op19_16, string OpcodeStr, string Dt, - ValueType Ty> - : NVDupLane + : NVDupLane; class VDUPLNQ op19_16, string OpcodeStr, string Dt, - ValueType ResTy, ValueType OpTy> - : NVDupLane + : NVDupLane; + VectorIndex32:$lane)))]>; // Inst{19-16} is partially specified depending on the element size. -def VDUPLN8d : VDUPLND<{?,?,?,1}, "vdup", "8", v8i8> { +def VDUPLN8d : VDUPLND<{?,?,?,1}, "vdup", "8", v8i8, VectorIndex8> { + bits<3> lane; let Inst{19-17} = lane{2-0}; } -def VDUPLN16d : VDUPLND<{?,?,1,0}, "vdup", "16", v4i16> { +def VDUPLN16d : VDUPLND<{?,?,1,0}, "vdup", "16", v4i16, VectorIndex16> { + bits<2> lane; let Inst{19-18} = lane{1-0}; } -def VDUPLN32d : VDUPLND<{?,1,0,0}, "vdup", "32", v2i32> { +def VDUPLN32d : VDUPLND<{?,1,0,0}, "vdup", "32", v2i32, VectorIndex32> { + bits<1> lane; let Inst{19} = lane{0}; } -def VDUPLN8q : VDUPLNQ<{?,?,?,1}, "vdup", "8", v16i8, v8i8> { +def VDUPLN8q : VDUPLNQ<{?,?,?,1}, "vdup", "8", v16i8, v8i8, VectorIndex8> { + bits<3> lane; let Inst{19-17} = lane{2-0}; } -def VDUPLN16q : VDUPLNQ<{?,?,1,0}, "vdup", "16", v8i16, v4i16> { +def VDUPLN16q : VDUPLNQ<{?,?,1,0}, "vdup", "16", v8i16, v4i16, VectorIndex16> { + bits<2> lane; let Inst{19-18} = lane{1-0}; } -def VDUPLN32q : VDUPLNQ<{?,1,0,0}, "vdup", "32", v4i32, v2i32> { +def VDUPLN32q : VDUPLNQ<{?,1,0,0}, "vdup", "32", v4i32, v2i32, VectorIndex32> { + bits<1> lane; let Inst{19} = lane{0}; } @@ -4753,6 +4844,7 @@ def VZIPq32 : N2VQShuffle<0b10, 0b00011, IIC_VPERMQ3, "vzip", "32">; // Vector Table Lookup and Table Extension. // VTBL : Vector Table Lookup +let DecoderMethod = "DecodeTBLInstruction" in { def VTBL1 : N3V<1,1,0b11,0b1000,0,0, (outs DPR:$Vd), (ins DPR:$Vn, DPR:$Vm), NVTBLFrm, IIC_VTB1, @@ -4815,6 +4907,7 @@ def VTBX3Pseudo def VTBX4Pseudo : PseudoNeonI<(outs DPR:$dst), (ins DPR:$orig, QQPR:$tbl, DPR:$src), IIC_VTBX4, "$orig = $dst", []>; +} // DecoderMethod = "DecodeTBLInstruction" //===----------------------------------------------------------------------===// // NEON instructions for single-precision FP math diff --git a/contrib/llvm/lib/Target/ARM/ARMInstrThumb.td b/contrib/llvm/lib/Target/ARM/ARMInstrThumb.td index bfe83eceb..cedb54799 100644 --- a/contrib/llvm/lib/Target/ARM/ARMInstrThumb.td +++ b/contrib/llvm/lib/Target/ARM/ARMInstrThumb.td @@ -19,6 +19,19 @@ def ARMtcall : SDNode<"ARMISD::tCALL", SDT_ARMcall, [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue, SDNPVariadic]>; +def imm_sr_XFORM: SDNodeXFormgetZExtValue(); + return CurDAG->getTargetConstant((Imm == 32 ? 0 : Imm), MVT::i32); +}]>; +def ThumbSRImmAsmOperand: AsmOperandClass { let Name = "ImmThumbSR"; } +def imm_sr : Operand, PatLeaf<(imm), [{ + uint64_t Imm = N->getZExtValue(); + return Imm > 0 && Imm <= 32; +}], imm_sr_XFORM> { + let PrintMethod = "printThumbSRImm"; + let ParserMatchClass = ThumbSRImmAsmOperand; +} + def imm_neg_XFORM : SDNodeXFormgetTargetConstant(-(int)N->getZExtValue(), MVT::i32); }]>; @@ -30,10 +43,6 @@ def imm0_7_neg : PatLeaf<(i32 imm), [{ return (uint32_t)-N->getZExtValue() < 8; }], imm_neg_XFORM>; -def imm0_255_asmoperand : AsmOperandClass { let Name = "Imm0_255"; } -def imm0_255 : Operand, ImmLeaf= 0 && Imm < 256; }]> { - let ParserMatchClass = imm0_255_asmoperand; -} def imm0_255_comp : PatLeaf<(i32 imm), [{ return ~((uint32_t)N->getZExtValue()) < 256; }]>; @@ -69,8 +78,17 @@ def t_adrlabel : Operand { } // Scaled 4 immediate. -def t_imm_s4 : Operand { +def t_imm0_1020s4_asmoperand: AsmOperandClass { let Name = "Imm0_1020s4"; } +def t_imm0_1020s4 : Operand { + let PrintMethod = "printThumbS4ImmOperand"; + let ParserMatchClass = t_imm0_1020s4_asmoperand; + let OperandType = "OPERAND_IMMEDIATE"; +} + +def t_imm0_508s4_asmoperand: AsmOperandClass { let Name = "Imm0_508s4"; } +def t_imm0_508s4 : Operand { let PrintMethod = "printThumbS4ImmOperand"; + let ParserMatchClass = t_imm0_508s4_asmoperand; let OperandType = "OPERAND_IMMEDIATE"; } @@ -79,113 +97,129 @@ def t_imm_s4 : Operand { let OperandType = "OPERAND_PCREL" in { def t_brtarget : Operand { let EncoderMethod = "getThumbBRTargetOpValue"; + let DecoderMethod = "DecodeThumbBROperand"; } def t_bcctarget : Operand { let EncoderMethod = "getThumbBCCTargetOpValue"; + let DecoderMethod = "DecodeThumbBCCTargetOperand"; } def t_cbtarget : Operand { let EncoderMethod = "getThumbCBTargetOpValue"; + let DecoderMethod = "DecodeThumbCmpBROperand"; } def t_bltarget : Operand { let EncoderMethod = "getThumbBLTargetOpValue"; + let DecoderMethod = "DecodeThumbBLTargetOperand"; } def t_blxtarget : Operand { let EncoderMethod = "getThumbBLXTargetOpValue"; + let DecoderMethod = "DecodeThumbBLXOffset"; } } -def MemModeRegThumbAsmOperand : AsmOperandClass { - let Name = "MemModeRegThumb"; - let SuperClasses = []; -} - -def MemModeImmThumbAsmOperand : AsmOperandClass { - let Name = "MemModeImmThumb"; - let SuperClasses = []; -} - // t_addrmode_rr := reg + reg // +def t_addrmode_rr_asm_operand : AsmOperandClass { let Name = "MemThumbRR"; } def t_addrmode_rr : Operand, ComplexPattern { let EncoderMethod = "getThumbAddrModeRegRegOpValue"; let PrintMethod = "printThumbAddrModeRROperand"; + let DecoderMethod = "DecodeThumbAddrModeRR"; + let ParserMatchClass = t_addrmode_rr_asm_operand; let MIOperandInfo = (ops tGPR:$base, tGPR:$offsreg); } // t_addrmode_rrs := reg + reg // +// We use separate scaled versions because the Select* functions need +// to explicitly check for a matching constant and return false here so that +// the reg+imm forms will match instead. This is a horrible way to do that, +// as it forces tight coupling between the methods, but it's how selectiondag +// currently works. def t_addrmode_rrs1 : Operand, ComplexPattern { let EncoderMethod = "getThumbAddrModeRegRegOpValue"; let PrintMethod = "printThumbAddrModeRROperand"; + let DecoderMethod = "DecodeThumbAddrModeRR"; + let ParserMatchClass = t_addrmode_rr_asm_operand; let MIOperandInfo = (ops tGPR:$base, tGPR:$offsreg); - let ParserMatchClass = MemModeRegThumbAsmOperand; } def t_addrmode_rrs2 : Operand, ComplexPattern { let EncoderMethod = "getThumbAddrModeRegRegOpValue"; + let DecoderMethod = "DecodeThumbAddrModeRR"; let PrintMethod = "printThumbAddrModeRROperand"; + let ParserMatchClass = t_addrmode_rr_asm_operand; let MIOperandInfo = (ops tGPR:$base, tGPR:$offsreg); - let ParserMatchClass = MemModeRegThumbAsmOperand; } def t_addrmode_rrs4 : Operand, ComplexPattern { let EncoderMethod = "getThumbAddrModeRegRegOpValue"; + let DecoderMethod = "DecodeThumbAddrModeRR"; let PrintMethod = "printThumbAddrModeRROperand"; + let ParserMatchClass = t_addrmode_rr_asm_operand; let MIOperandInfo = (ops tGPR:$base, tGPR:$offsreg); - let ParserMatchClass = MemModeRegThumbAsmOperand; } // t_addrmode_is4 := reg + imm5 * 4 // +def t_addrmode_is4_asm_operand : AsmOperandClass { let Name = "MemThumbRIs4"; } def t_addrmode_is4 : Operand, ComplexPattern { let EncoderMethod = "getAddrModeISOpValue"; + let DecoderMethod = "DecodeThumbAddrModeIS"; let PrintMethod = "printThumbAddrModeImm5S4Operand"; + let ParserMatchClass = t_addrmode_is4_asm_operand; let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm); - let ParserMatchClass = MemModeImmThumbAsmOperand; } // t_addrmode_is2 := reg + imm5 * 2 // +def t_addrmode_is2_asm_operand : AsmOperandClass { let Name = "MemThumbRIs2"; } def t_addrmode_is2 : Operand, ComplexPattern { let EncoderMethod = "getAddrModeISOpValue"; + let DecoderMethod = "DecodeThumbAddrModeIS"; let PrintMethod = "printThumbAddrModeImm5S2Operand"; + let ParserMatchClass = t_addrmode_is2_asm_operand; let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm); - let ParserMatchClass = MemModeImmThumbAsmOperand; } // t_addrmode_is1 := reg + imm5 // +def t_addrmode_is1_asm_operand : AsmOperandClass { let Name = "MemThumbRIs1"; } def t_addrmode_is1 : Operand, ComplexPattern { let EncoderMethod = "getAddrModeISOpValue"; + let DecoderMethod = "DecodeThumbAddrModeIS"; let PrintMethod = "printThumbAddrModeImm5S1Operand"; + let ParserMatchClass = t_addrmode_is1_asm_operand; let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm); - let ParserMatchClass = MemModeImmThumbAsmOperand; } // t_addrmode_sp := sp + imm8 * 4 // +// FIXME: This really shouldn't have an explicit SP operand at all. It should +// be implicit, just like in the instruction encoding itself. +def t_addrmode_sp_asm_operand : AsmOperandClass { let Name = "MemThumbSPI"; } def t_addrmode_sp : Operand, ComplexPattern { let EncoderMethod = "getAddrModeThumbSPOpValue"; + let DecoderMethod = "DecodeThumbAddrModeSP"; let PrintMethod = "printThumbAddrModeSPOperand"; + let ParserMatchClass = t_addrmode_sp_asm_operand; let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm); - let ParserMatchClass = MemModeImmThumbAsmOperand; } // t_addrmode_pc :=